static pa_hook_result_t source_output_put_cb(pa_core *core, pa_source_output *i, struct userdata *u) { pa_core_assert_ref(core); pa_source_output_assert_ref(i); pa_assert(u); return process(u, PA_OBJECT(i), FALSE); }
/* Called from main context */ void pa_source_output_kill(pa_source_output*o) { pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state)); o->kill(o); }
/* Called from input thread context */ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) { struct userdata *u; pa_memchunk copy; pa_source_output_assert_ref(o); pa_source_output_assert_io_context(o); pa_assert_se(u = o->userdata); if (u->skip > chunk->length) { u->skip -= chunk->length; return; } if (u->skip > 0) { copy = *chunk; copy.index += u->skip; copy.length -= u->skip; u->skip = 0; chunk = © } pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, chunk, NULL); u->send_counter += (int64_t) chunk->length; }
/* Called from main context */ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) { pa_source_output_assert_ref(o); pa_assert_ctl_context(); if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) { pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0); return usec; } /* If this source output is not realized yet or is being moved, we * have to touch the thread info data directly */ if (o->source) { if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY)) usec = pa_source_get_fixed_latency(o->source); if (usec != (pa_usec_t) -1) { pa_usec_t min_latency, max_latency; pa_source_get_latency_range(o->source, &min_latency, &max_latency); usec = PA_CLAMP(usec, min_latency, max_latency); } } o->thread_info.requested_source_latency = usec; return usec; }
/* Called from main thread */ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { pa_proplist *p; const char *n; struct userdata *u; if (!dest) return; pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert_se(u = o->userdata); p = pa_proplist_new(); pa_proplist_setf(p, PA_PROP_MEDIA_NAME, "Loopback of %s", pa_strnull(pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION))); if ((n = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_ICON_NAME))) pa_proplist_sets(p, PA_PROP_MEDIA_ICON_NAME, n); pa_sink_input_update_proplist(u->sink_input, PA_UPDATE_REPLACE, p); pa_proplist_free(p); if (pa_source_get_state(dest) == PA_SOURCE_SUSPENDED) pa_sink_input_cork(u->sink_input, true); else pa_sink_input_cork(u->sink_input, false); update_adjust_timer(u); }
/* Called from main thread */ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { struct userdata *u; char *input_description; const char *n; if (!dest) return; pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert_se(u = o->userdata); input_description = pa_sprintf_malloc("Loopback of %s", pa_strnull(pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION))); pa_sink_input_set_property(u->sink_input, PA_PROP_MEDIA_NAME, input_description); pa_xfree(input_description); if ((n = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_ICON_NAME))) pa_sink_input_set_property(u->sink_input, PA_PROP_DEVICE_ICON_NAME, n); if (pa_source_get_state(dest) == PA_SOURCE_SUSPENDED) pa_sink_input_cork(u->sink_input, true); else pa_sink_input_cork(u->sink_input, false); update_adjust_timer(u); }
/* Called from main context */ void pa_source_output_send_event(pa_source_output *o, const char *event, pa_proplist *data) { pa_proplist *pl = NULL; pa_source_output_send_event_hook_data hook_data; pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert(event); if (!o->send_event) return; if (!data) data = pl = pa_proplist_new(); hook_data.source_output = o; hook_data.data = data; hook_data.event = event; if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT], &hook_data) < 0) goto finish; o->send_event(o, event, data); finish: if (pl) pa_proplist_free(pl); }
/* Called from main context */ int pa_source_output_move_to(pa_source_output *o, pa_source *dest, pa_bool_t save) { int r; pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state)); pa_assert(o->source); pa_source_assert_ref(dest); if (dest == o->source) return 0; if (!pa_source_output_may_move_to(o, dest)) return -PA_ERR_NOTSUPPORTED; pa_source_output_ref(o); if ((r = pa_source_output_start_move(o)) < 0) { pa_source_output_unref(o); return r; } if ((r = pa_source_output_finish_move(o, dest, save)) < 0) { pa_source_output_fail_move(o); pa_source_output_unref(o); return r; } pa_source_output_unref(o); return 0; }
/* Called from main context */ int pa_source_output_start_move(pa_source_output *o) { pa_source *origin; int r; pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state)); pa_assert(o->source); if (!pa_source_output_may_move(o)) return -PA_ERR_NOTSUPPORTED; if ((r = pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START], o)) < 0) return r; origin = o->source; pa_idxset_remove_by_data(o->source->outputs, o, NULL); if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED) pa_assert_se(origin->n_corked-- >= 1); pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL) == 0); pa_source_update_status(o->source); o->source = NULL; pa_source_output_unref(o); return 0; }
/* Called from main context */ void pa_source_output_cork(pa_source_output *o, pa_bool_t b) { pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state)); source_output_set_state(o, b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING); }
/* Called from thread context */ void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes /* in source sample spec */) { pa_source_output_assert_ref(o); pa_source_output_assert_io_context(o); pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->thread_info.state)); pa_assert(pa_frame_aligned(nbytes, &o->source->sample_spec)); if (nbytes <= 0) return; if (o->process_rewind) { pa_assert(pa_memblockq_get_length(o->thread_info.delay_memblockq) == 0); if (o->thread_info.resampler) nbytes = pa_resampler_result(o->thread_info.resampler, nbytes); pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) nbytes); if (nbytes > 0) o->process_rewind(o, nbytes); if (o->thread_info.resampler) pa_resampler_reset(o->thread_info.resampler); } else pa_memblockq_rewind(o->thread_info.delay_memblockq, nbytes); }
/* Called from main thread */ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { struct userdata *u; pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert_se(u = o->userdata); if (dest) { pa_source_set_asyncmsgq(u->source, dest->asyncmsgq); pa_source_update_flags(u->source, PA_SOURCE_LATENCY|PA_SOURCE_DYNAMIC_LATENCY, dest->flags); } else pa_source_set_asyncmsgq(u->source, NULL); if (u->auto_desc && dest) { const char *k; pa_proplist *pl; pl = pa_proplist_new(); k = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION); pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : dest->name); pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, pl); pa_proplist_free(pl); } }
/* Called from I/O thread context */ static void cmtspeech_source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) { struct userdata *u; pa_source_output_assert_ref(o); pa_assert_se(u = o->userdata); pa_log_debug("State changed %d -> %d", o->thread_info.state, state); }
/* Called from main context */ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) { connection*c; pa_source_output_assert_ref(o); c = CONNECTION(o->userdata); pa_assert(c); return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec); }
/* Called from main thread */ static pa_bool_t source_output_may_move_to_cb(pa_source_output *o, pa_source *dest) { struct userdata *u; pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert_se(u = o->userdata); return dest != u->sink_input->sink->monitor_source; }
/* Called from thread context */ void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes /* in the source's sample spec */) { pa_source_output_assert_ref(o); pa_source_output_assert_io_context(o); pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->thread_info.state)); pa_assert(pa_frame_aligned(nbytes, &o->source->sample_spec)); if (o->update_max_rewind) o->update_max_rewind(o, o->thread_info.resampler ? pa_resampler_result(o->thread_info.resampler, nbytes) : nbytes); }
/* Called from output thread context */ static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) { struct userdata *u; pa_source_output_assert_ref(o); pa_source_output_assert_io_context(o); pa_assert_se(u = o->userdata); pa_source_process_rewind(u->source, nbytes); }
/* Called from output thread context */ static void source_output_state_change_cb(pa_source_output *o, pa_source_output_state_t state) { struct userdata *u; pa_source_output_assert_ref(o); pa_source_output_assert_io_context(o); pa_assert_se(u = o->userdata); pa_log_debug("Source output %d state %d.", o->index, state); }
/* Called from main thread */ static void source_output_kill_cb(pa_source_output *o) { struct userdata *u; pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert_se(u = o->userdata); teardown(u); pa_module_unload_request(u->module, TRUE); }
/* Called from thread context */ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) { connection *c; pa_source_output_assert_ref(o); c = CONNECTION(o->userdata); pa_assert(c); pa_assert(chunk); pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL); }
/* Called from output thread context */ static void source_output_detach_cb(pa_source_output *o) { struct userdata *u; pa_source_output_assert_ref(o); pa_source_output_assert_io_context(o); pa_assert_se(u = o->userdata); pa_source_detach_within_thread(u->source); pa_source_set_rtpoll(u->source, NULL); }
/* Called from I/O thread context */ static void cmtspeech_source_output_attach_cb(pa_source_output *o) { struct userdata *u; pa_source_output_assert_ref(o); pa_assert_se(u = o->userdata); pa_assert(u->source == o->source); pa_log_debug("CMT source output connected to %s", o->source->name); }
/* Called from I/O thread context */ static void cmtspeech_source_output_detach_cb(pa_source_output *o) { struct userdata *u; pa_source_output_assert_ref(o); pa_assert_se(u = o->userdata); u->source = NULL; pa_log_debug("CMT source output detach called"); }
/* Called from main context */ static void cmtspeech_source_output_moving_cb(pa_source_output *o, pa_source *dest) { struct userdata *u; pa_source_output_assert_ref(o); pa_assert_se(u = o->userdata); u->source = o->source; pa_log_debug("CMT Source output moving to %s", dest ? dest->name : "(null)"); }
/* Called from input thread context */ static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes) { struct userdata *u; pa_source_output_assert_ref(o); pa_source_output_assert_io_context(o); pa_assert_se(u = o->userdata); pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_REWIND, NULL, (int64_t) nbytes, NULL, NULL); u->send_counter -= (int64_t) nbytes; }
static pa_hook_result_t source_output_move_finish_cb(pa_core *core, pa_source_output *i, struct userdata *u) { pa_core_assert_ref(core); pa_source_output_assert_ref(i); pa_assert(u); /* module-filter-apply triggered this move, ignore */ if (pa_proplist_gets(i->proplist, PA_PROP_FILTER_APPLY_MOVING)) return PA_HOOK_OK; return process(u, PA_OBJECT(i), FALSE); }
/* Called from main thread */ static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspended) { struct userdata *u; pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert_se(u = o->userdata); pa_sink_input_cork(u->sink_input, suspended); update_adjust_timer(u); }
/* Called from main context */ static void source_output_kill_cb(pa_source_output* o) { struct userdata *u; pa_source_output_assert_ref(o); pa_assert_se(u = o->userdata); pa_module_unload_request(u->module, true); pa_source_output_unlink(u->source_output); pa_source_output_unref(u->source_output); u->source_output = NULL; }
/* Called from output thread context */ static void source_output_attach_cb(pa_source_output *o) { struct userdata *u; pa_source_output_assert_ref(o); pa_source_output_assert_io_context(o); pa_assert_se(u = o->userdata); u->rtpoll_item_write = pa_rtpoll_item_new_asyncmsgq_write( o->source->thread_info.rtpoll, PA_RTPOLL_LATE, u->asyncmsgq); }
/* Called from output thread context */ static void source_output_detach_cb(pa_source_output *o) { struct userdata *u; pa_source_output_assert_ref(o); pa_source_output_assert_io_context(o); pa_assert_se(u = o->userdata); if (u->rtpoll_item_write) { pa_rtpoll_item_free(u->rtpoll_item_write); u->rtpoll_item_write = NULL; } }