02.10.2014 19:58, David Henningsson wrote: > @@ -216,6 +216,10 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk > pa_memchunk nchunk; > > pa_sink_render(u->sink, nbytes, &nchunk); > + if (nchunk.memblock == u->sink->silence.memblock) { > + pa_memblock_unref(nchunk.memblock); > + return -1; > + } > pa_memblockq_push(u->memblockq, &nchunk); > pa_memblock_unref(nchunk.memblock); > } This chunk looks correct if we ignore the tail of the filter response. It should be split out as a separate patch and applied. > @@ -265,6 +269,23 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk > return 0; > } > > +/* Called from thread context */ > + > +static bool sink_input_process_underrun_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_INPUT_IS_LINKED(u->sink_input->thread_info.state)) > + return false; > + > + pa_log_debug("sink_input_process_underrun_cb for virtual sink"); > + return pa_sink_process_input_underruns(u->sink, 0); > +} > + > + > /* Called from I/O thread context */ > static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) { > struct userdata *u; > @@ -586,6 +607,7 @@ int pa__init(pa_module*m) { > goto fail; > > u->sink_input->pop = sink_input_pop_cb; > + u->sink_input->process_underrun = sink_input_process_underrun_cb; > u->sink_input->process_rewind = sink_input_process_rewind_cb; > u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb; > u->sink_input->update_max_request = sink_input_update_max_request_cb; > And for this I have doubts whether this is a right approach at all. By analogy with the ALSA sink, I'd expect that pa_sink_process_input_underruns() will be called from sink_input_pop_cb() - but I am also not sure if this is a viable approach. But at least it won't have the "correct for only one sink input" limitation. -- Alexander E. Patrakov