/* Called from main context */
static void teardown(struct userdata *u) {
    pa_assert(u);
    pa_assert_ctl_context();

    u->adjust_time = 0;
    enable_adjust_timer(u, false);

    /* Handling the asyncmsgq between the source output and the sink input
     * requires some care. When the source output is unlinked, nothing needs
     * to be done for the asyncmsgq, because the source output is the sending
     * end. But when the sink input is unlinked, we should ensure that the
     * asyncmsgq is emptied, because the messages in the queue hold references
     * to the sink input. Also, we need to ensure that new messages won't be
     * written to the queue after we have emptied it.
     *
     * Emptying the queue can be done in the state_changed() callback of the
     * sink input, when the new state is "unlinked".
     *
     * Preventing new messages from being written to the queue can be achieved
     * by unlinking the source output before unlinking the sink input. There
     * are no other writers for that queue, so this is sufficient. */

    if (u->source_output) {
        pa_source_output_unlink(u->source_output);
        pa_source_output_unref(u->source_output);
        u->source_output = NULL;
    }

    if (u->sink_input) {
        pa_sink_input_unlink(u->sink_input);
        pa_sink_input_unref(u->sink_input);
        u->sink_input = NULL;
    }
}
void pa__done(pa_module*m) {
    struct userdata *u;

    pa_assert(m);

    if (!(u = m->userdata))
        return;

    /* See comments in sink_input_kill_cb() above regarding
     * destruction order! */

    if (u->sink_input)
        pa_sink_input_unlink(u->sink_input);

    if (u->sink)
        pa_sink_unlink(u->sink);

    if (u->sink_input)
        pa_sink_input_unref(u->sink_input);

    if (u->sink)
        pa_sink_unref(u->sink);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    pa_xfree(u);
}
Example #3
0
static void sink_input_kill_cb(pa_sink_input *i) {
    struct userdata *u;

    pa_sink_input_assert_ref(i);
    pa_assert_se(u = i->userdata);

    pa_sink_input_unlink(u->sink_input);
    pa_sink_input_unref(u->sink_input);
    u->sink_input = NULL;

    pa_module_unload_request(u->module, true);
}
Example #4
0
static void memblockq_stream_unlink(memblockq_stream *u) {
    pa_assert(u);

    if (!u->sink_input)
        return;

    pa_sink_input_unlink(u->sink_input);
    pa_sink_input_unref(u->sink_input);
    u->sink_input = NULL;

    memblockq_stream_unref(u);
}
Example #5
0
/* Called from main context */
static void file_stream_unlink(file_stream *u) {
    pa_assert(u);

    if (!u->sink_input)
        return;

    pa_sink_input_unlink(u->sink_input);
    pa_sink_input_unref(u->sink_input);
    u->sink_input = NULL;

    /* Make sure we don't decrease the ref count twice. */
    file_stream_unref(u);
}
void cmtspeech_delete_sink_input(struct userdata *u) {
    pa_assert(u);
    ENTER();

    if (!u->sink_input) {
        pa_log_info("Delete called but no sink input exists");
        return;
    }

    pa_sink_input_unlink(u->sink_input);
    pa_sink_input_unref(u->sink_input);
    u->sink_input = NULL;

    pa_log_info("cmtspeech sink-input deleted");
}
/* Called from main context */
static void aep_sink_input_kill_cb(pa_sink_input *i) {
    struct userdata *u;

    pa_log_debug("Kill called");

    pa_sink_input_assert_ref(i);
    pa_assert_se(u = i->userdata);

    /* FIXME: this is sort-of understandable with the may_move hack... we avoid abort in free() here */
    u->aep_sink_input->thread_info.attached = FALSE;
    pa_sink_input_unlink(u->aep_sink_input);
    pa_sink_input_unref(u->aep_sink_input);
    u->aep_sink_input = NULL;

    pa_module_unload_request(u->module, TRUE);
}
Example #8
0
void pa__done(pa_module*m) {
    struct userdata *u;

    pa_assert(m);

    if (!(u = m->userdata))
        return;

    if (u->sink_input) {
        pa_sink_input_unlink(u->sink_input);
        pa_sink_input_unref(u->sink_input);
    }

    if (u->memchunk.memblock)
        pa_memblock_unref(u->memchunk.memblock);

    pa_xfree(u);
}
Example #9
0
void pa__done(pa_module*m) {
    struct userdata *u;
    unsigned c;

    pa_assert(m);

    if (!(u = m->userdata))
        return;

    /* See comments in sink_input_kill_cb() above regarding
     * destruction order! */

    if (u->sink_input)
        pa_sink_input_unlink(u->sink_input);

    if (u->sink)
        pa_sink_unlink(u->sink);

    if (u->sink_input)
        pa_sink_input_unref(u->sink_input);

    if (u->sink)
        pa_sink_unref(u->sink);

    for (c = 0; c < u->channels; c++)
        if (u->handle[c]) {
            if (u->descriptor->deactivate)
                u->descriptor->deactivate(u->handle[c]);
            u->descriptor->cleanup(u->handle[c]);
        }

    if (u->output != u->input)
        pa_xfree(u->output);

    if (u->memblockq)
        pa_memblockq_free(u->memblockq);

    pa_xfree(u->input);

    pa_xfree(u->control);

    pa_xfree(u);
}
Example #10
0
/* Called from main context */
static void sink_input_kill_cb(pa_sink_input *i) {
    struct userdata *u;

    pa_sink_input_assert_ref(i);
    pa_assert_se(u = i->userdata);

    /* The order here matters! We first kill the sink input, followed
     * by the sink. That means the sink callbacks must be protected
     * against an unconnected sink input! */
    pa_sink_input_unlink(u->sink_input);
    pa_sink_unlink(u->sink);

    pa_sink_input_unref(u->sink_input);
    u->sink_input = NULL;

    pa_sink_unref(u->sink);
    u->sink = NULL;

    pa_module_unload_request(u->module, TRUE);
}
Example #11
0
/* Called from main context */
static void teardown(struct userdata *u) {
    pa_assert(u);
    pa_assert_ctl_context();

    if (u->sink_input)
        pa_sink_input_unlink(u->sink_input);

    if (u->source_output)
        pa_source_output_unlink(u->source_output);

    if (u->sink_input) {
        pa_sink_input_unref(u->sink_input);
        u->sink_input = NULL;
    }

    if (u->source_output) {
        pa_source_output_unref(u->source_output);
        u->source_output = NULL;
    }
}
Example #12
0
/* Called from main context */
static void sink_input_kill_cb(pa_sink_input *i) {
    struct userdata *u;

    pa_sink_input_assert_ref(i);
    pa_assert_se(u = i->userdata);

    /* The order here matters! We first kill the sink so that streams
     * can properly be moved away while the sink input is still connected
     * to the master. */
    pa_sink_input_cork(u->sink_input, true);
    pa_sink_unlink(u->sink);
    pa_sink_input_unlink(u->sink_input);

    pa_sink_input_unref(u->sink_input);
    u->sink_input = NULL;

    pa_sink_unref(u->sink);
    u->sink = NULL;

    pa_module_unload_request(u->module, true);
}
static void connection_unlink(connection *c) {
    pa_assert(c);

    if (!c->protocol)
        return;

    if (c->options) {
        pa_simple_options_unref(c->options);
        c->options = NULL;
    }

    if (c->sink_input) {
        pa_sink_input_unlink(c->sink_input);
        pa_sink_input_unref(c->sink_input);
        c->sink_input = NULL;
    }

    if (c->source_output) {
        pa_source_output_unlink(c->source_output);
        pa_source_output_unref(c->source_output);
        c->source_output = NULL;
    }

    if (c->client) {
        pa_client_free(c->client);
        c->client = NULL;
    }

    if (c->io) {
        pa_iochannel_free(c->io);
        c->io = NULL;
    }

    pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
    c->protocol = NULL;
    connection_unref(c);
}
/*** Deallocate stuff ***/
void voice_clear_up(struct userdata *u) {
    pa_assert(u);

    if (u->mainloop_handler) {
        u->mainloop_handler->parent.free((pa_object *)u->mainloop_handler);
        u->mainloop_handler = NULL;
    }

    if (u->hw_sink_input) {
        pa_sink_input_unlink(u->hw_sink_input);
        pa_sink_input_unref(u->hw_sink_input);
        u->hw_sink_input = NULL;
    }

    if (u->raw_sink) {
        pa_sink_unlink(u->raw_sink);
        pa_sink_unref(u->raw_sink);
        u->raw_sink = NULL;
    }

    if (u->dl_memblockq) {
        pa_memblockq_free(u->dl_memblockq);
        u->dl_memblockq = NULL;
    }

    if (u->voip_sink) {
        pa_sink_unlink(u->voip_sink);
        pa_sink_unref(u->voip_sink);
        u->voip_sink = NULL;
    }

    if (u->hw_source_output) {
        pa_source_output_unlink(u->hw_source_output);
        pa_source_output_unref(u->hw_source_output);
        u->hw_source_output = NULL;
    }

    if (u->voip_source) {
        pa_source_unlink(u->voip_source);
        pa_source_unref(u->voip_source);
        u->voip_source = NULL;
    }

    if (u->raw_source) {
        pa_source_unlink(u->raw_source);
        pa_source_unref(u->raw_source);
        u->raw_source = NULL;
    }

    if (u->hw_source_memblockq) {
        pa_memblockq_free(u->hw_source_memblockq);
        u->hw_source_memblockq = NULL;
    }

    if (u->ul_memblockq) {
        pa_memblockq_free(u->ul_memblockq);
        u->ul_memblockq = NULL;
    }

    if (u->dl_sideinfo_queue) {
        pa_queue_free(u->dl_sideinfo_queue, NULL, u);
        u->dl_sideinfo_queue = NULL;
    }

    voice_aep_ear_ref_unload(u);

    if (u->aep_silence_memchunk.memblock) {
        pa_memblock_unref(u->aep_silence_memchunk.memblock);
        pa_memchunk_reset(&u->aep_silence_memchunk);
    }

    if (u->sink_temp_buff) {
        pa_xfree(u->sink_temp_buff);
        u->sink_temp_buff = NULL;
    }

    if (u->sink_subscription) {
        pa_subscription_free(u->sink_subscription);
        u->sink_subscription = NULL;
    }

    if (u->sink_proplist_changed_slot) {
        pa_hook_slot_free(u->sink_proplist_changed_slot);
        u->sink_proplist_changed_slot = NULL;
    }

    if (u->source_proplist_changed_slot) {
        pa_hook_slot_free(u->source_proplist_changed_slot);
        u->source_proplist_changed_slot = NULL;
    }

    voice_convert_free(u);
    voice_memchunk_pool_unload(u);
    voice_unload_event_forwarder(u);
}