/* Called from main context */ static void cmtspeech_sink_input_moving_cb(pa_sink_input *i, pa_sink *dest){ struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); u->sink = i->sink; pa_log_debug("CMT Sink input moving to %s", dest ? dest->name : "(null)"); }
/* Called from I/O thread context */ static void sink_input_detach_cb(pa_sink_input *i) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); pa_sink_detach_within_thread(u->sink); pa_sink_set_rtpoll(u->sink, NULL); }
/* Called from main context */ static pa_bool_t cmtspeech_sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); if (cmtspeech_check_sink_api(dest)) return FALSE; return TRUE; }
/* Called from main thread */ static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspended) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_ctl_context(); pa_assert_se(u = i->userdata); pa_source_output_cork(u->source_output, suspended); update_adjust_timer(u); }
/* Called from I/O thread context */ static void cmtspeech_sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); if (!PA_SINK_INPUT_IS_LINKED(i->thread_info.state)) return; pa_log_debug("Max request of %s updated to %zu bytes", i->sink->name, nbytes); }
/* Called from IO context */ static void sink_input_suspend_within_thread(pa_sink_input* i, pa_bool_t b) { struct session *s; pa_sink_input_assert_ref(i); pa_assert_se(s = i->userdata); if (b) { pa_smoother_pause(s->smoother, pa_rtclock_now()); pa_memblockq_flush_read(s->memblockq); } else s->first_packet = FALSE; }
/* Called from IO thread context */ static void aep_sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); pa_log_debug("State change cb %d", state); /* What ever the new state was, we should remain corked. */ i->thread_info.state = PA_SINK_INPUT_CORKED; }
/* Called from output thread context */ static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) { struct userdata *u; pa_sink_input_assert_ref(i); pa_sink_input_assert_io_context(i); pa_assert_se(u = i->userdata); pa_memblockq_set_prebuf(u->memblockq, nbytes*2); pa_log_info("Max request changed"); pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_MAX_REQUEST_CHANGED, NULL, 0, NULL, NULL); }
/* Called from I/O thread context */ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); /* FIXME: Too small max_rewind: * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */ pa_memblockq_set_maxrewind(u->memblockq, nbytes); pa_sink_set_max_rewind_within_thread(u->sink, nbytes); }
/* Called from I/O thread context */ static void cmtspeech_sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); if (!PA_SINK_INPUT_IS_LINKED(i->thread_info.state)) return; pa_log_debug("%s rewound %zu bytes", i->sink->name, nbytes); }
/* Called from I/O thread context */ static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); /* (6) IF YOU NEED A FIXED BLOCK SIZE ROUND nbytes UP TO MULTIPLES * OF IT HERE. THE PA_ROUND_UP MACRO IS USEFUL FOR THAT. */ pa_sink_set_max_request_within_thread(u->sink, nbytes); }
/* Called from I/O thread context */ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) { struct userdata *u; float *src, *dst; size_t fs; unsigned n, h, c; pa_memchunk tchunk; pa_sink_input_assert_ref(i); pa_assert(chunk); pa_assert_se(u = i->userdata); /* Hmm, process any rewind request that might be queued up */ pa_sink_process_rewind(u->sink, 0); while (pa_memblockq_peek(u->memblockq, &tchunk) < 0) { pa_memchunk nchunk; pa_sink_render(u->sink, nbytes, &nchunk); pa_memblockq_push(u->memblockq, &nchunk); pa_memblock_unref(nchunk.memblock); } tchunk.length = PA_MIN(nbytes, tchunk.length); pa_assert(tchunk.length > 0); fs = pa_frame_size(&i->sample_spec); n = (unsigned) (PA_MIN(tchunk.length, u->block_size) / fs); pa_assert(n > 0); chunk->index = 0; chunk->length = n*fs; chunk->memblock = pa_memblock_new(i->sink->core->mempool, chunk->length); pa_memblockq_drop(u->memblockq, chunk->length); src = (float*) ((uint8_t*) pa_memblock_acquire(tchunk.memblock) + tchunk.index); dst = (float*) pa_memblock_acquire(chunk->memblock); for (h = 0; h < (u->channels / u->max_ladspaport_count); h++) { for (c = 0; c < u->input_count; c++) pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input[c], sizeof(float), src+ h*u->max_ladspaport_count + c, u->channels*sizeof(float), n); u->descriptor->run(u->handle[h], n); for (c = 0; c < u->output_count; c++) pa_sample_clamp(PA_SAMPLE_FLOAT32NE, dst + h*u->max_ladspaport_count + c, u->channels*sizeof(float), u->output[c], sizeof(float), n); } pa_memblock_release(tchunk.memblock); pa_memblock_release(chunk->memblock); pa_memblock_unref(tchunk.memblock); return 0; }
/* Called from I/O thread context */ static void sink_input_detach_cb(pa_sink_input *i) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); if (PA_SINK_IS_LINKED(u->sink->thread_info.state)) pa_sink_detach_within_thread(u->sink); pa_sink_set_rtpoll(u->sink, NULL); }
static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input *i, struct userdata *u) { pa_core_assert_ref(core); pa_sink_input_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), TRUE); }
static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) { memblockq_stream *u; pa_sink_input_assert_ref(i); u = MEMBLOCKQ_STREAM(i->userdata); memblockq_stream_assert_ref(u); if (!u->memblockq) return; pa_memblockq_set_maxrewind(u->memblockq, nbytes); }
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); }
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) { file_stream *u; pa_sink_input_assert_ref(i); u = FILE_STREAM(i->userdata); file_stream_assert_ref(u); if (!u->memblockq) return; pa_memblockq_rewind(u->memblockq, nbytes); }
/* Called from I/O thread context */ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { struct session *s; pa_sink_input_assert_ref(i); pa_assert_se(s = i->userdata); if (pa_memblockq_peek(s->memblockq, chunk) < 0) return -1; pa_memblockq_drop(s->memblockq, chunk->length); return 0; }
/* Called from IO thread context */ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); /* If we are added for the first time, ask for a rewinding so that * we are heard right-away. */ if (PA_SINK_INPUT_IS_LINKED(state) && i->thread_info.state == PA_SINK_INPUT_INIT) pa_sink_input_request_rewind(i, 0, false, true, true); }
/* Called from main thread */ static bool sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_ctl_context(); pa_assert_se(u = i->userdata); if (!u->source_output || !u->source_output->source) return true; return dest != u->source_output->source->monitor_of; }
/* Called from output thread context */ static void sink_input_detach_cb(pa_sink_input *i) { struct userdata *u; pa_sink_input_assert_ref(i); pa_sink_input_assert_io_context(i); pa_assert_se(u = i->userdata); if (u->rtpoll_item_read) { pa_rtpoll_item_free(u->rtpoll_item_read); u->rtpoll_item_read = NULL; } }
/* Called from I/O thread context */ static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); /* (7) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE * BLOCK MINUS ONE SAMPLE HERE. pa_usec_to_bytes_round_up() IS * USEFUL FOR THAT. */ pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency); }
/* Called from I/O thread context */ static void cmtspeech_sink_input_detach_cb(pa_sink_input *i) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); u->sink = NULL; u->voice_sideinfoq = NULL; cmtspeech_sink_input_reset_dl_stream(u); pa_log_debug("Detach called for CMT sink input"); }
/* Called from thread context */ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) { connection *c; pa_sink_input_assert_ref(i); c = CONNECTION(i->userdata); connection_assert_ref(c); /* If we are in an underrun, then we don't rewind */ if (i->thread_info.underrun_for > 0) return; pa_memblockq_rewind(c->input_memblockq, nbytes); }
static pa_hook_result_t sink_input_move_start_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) { struct device_info *d; pa_assert(c); pa_sink_input_assert_ref(s); pa_assert(u); if (pa_sink_check_suspend(s->sink) <= 1) if ((d = pa_hashmap_get(u->device_infos, s->sink))) restart(d); return PA_HOOK_OK; }
/* Called from IO thread context */ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) { memblockq_stream *u; pa_sink_input_assert_ref(i); u = MEMBLOCKQ_STREAM(i->userdata); memblockq_stream_assert_ref(u); /* If we are added for the first time, ask for a rewinding so that * we are heard right-away. */ if (PA_SINK_INPUT_IS_LINKED(state) && i->thread_info.state == PA_SINK_INPUT_INIT) pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE); }
/* Called from I/O thread context */ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert(chunk); pa_assert_se(u = i->userdata); /* Hmm, process any rewind request that might be queued up */ pa_sink_process_rewind(u->sink, 0); pa_sink_render(u->sink, nbytes, chunk); return 0; }
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); nbytes %= u->memchunk.length; if (u->peek_index >= nbytes) u->peek_index -= nbytes; else u->peek_index = u->memchunk.length + u->peek_index - nbytes; }
/* Called from IO thread context */ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); /* If we are added for the first time, ask for a rewinding so that * we are heard right-away. */ if (PA_SINK_INPUT_IS_LINKED(state) && i->thread_info.state == PA_SINK_INPUT_INIT) { pa_log_debug("Requesting rewind due to state change."); pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE); } }
/* Called from I/O thread context */ static void sink_input_attach_cb(pa_sink_input *i) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll); pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency); pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency); pa_sink_set_max_request_within_thread(u->sink, pa_sink_input_get_max_request(i)); pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i)); pa_sink_attach_within_thread(u->sink); }