diff options
Diffstat (limited to 'src/modules/module-remap-sink.c')
-rw-r--r-- | src/modules/module-remap-sink.c | 132 |
1 files changed, 82 insertions, 50 deletions
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c index 39a9245d..1c97a824 100644 --- a/src/modules/module-remap-sink.c +++ b/src/modules/module-remap-sink.c @@ -59,8 +59,6 @@ struct userdata { pa_sink *sink, *master; pa_sink_input *sink_input; - - pa_memchunk memchunk; }; static const char* const valid_modargs[] = { @@ -86,7 +84,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse if (PA_MSGOBJECT(u->master)->process_msg(PA_MSGOBJECT(u->master), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) usec = 0; - *((pa_usec_t*) data) = usec + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec); + *((pa_usec_t*) data) = usec/* + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec)*/; return 0; } } @@ -108,12 +106,34 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) { } /* Called from I/O thread context */ +static void sink_request_rewind(pa_sink *s) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + pa_sink_input_request_rewrite(u->sink_input, s->thread_info.rewind_nbytes); +} + +/* Called from I/O thread context */ +static void sink_update_requested_latency(pa_sink *s) { + struct userdata *u; + + pa_sink_assert_ref(s); + pa_assert_se(u = s->userdata); + + /* Just hand this one over to the master sink */ + u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency(s); + pa_sink_invalidate_requested_latency(u->master); +} + +/* Called from I/O thread context */ static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { struct userdata *u = PA_SINK_INPUT(o)->userdata; switch (code) { case PA_SINK_INPUT_MESSAGE_GET_LATENCY: - *((pa_usec_t*) data) = pa_bytes_to_usec(u->memchunk.length, &u->sink_input->sample_spec); + *((pa_usec_t*) data) = 0; /*pa_bytes_to_usec(u->memchunk.length, &u->sink_input->sample_spec);*/ /* Fall through, the default handler will add in the extra * latency added by the resampler */ @@ -123,45 +143,41 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t return pa_sink_input_process_msg(o, code, data, offset, chunk); } +static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes); + /* Called from I/O thread context */ -static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { +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); - if (!u->memchunk.memblock) - pa_sink_render(u->sink, length, &u->memchunk); + pa_sink_render(u->sink, nbytes, chunk); - pa_assert(u->memchunk.memblock); - *chunk = u->memchunk; - pa_memblock_ref(chunk->memblock); return 0; } /* Called from I/O thread context */ -static void sink_input_drop_cb(pa_sink_input *i, size_t length) { +static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) { struct userdata *u; pa_sink_input_assert_ref(i); pa_assert_se(u = i->userdata); - pa_assert(length > 0); + pa_assert(nbytes > 0); - if (u->memchunk.memblock) { + u->sink->thread_info.rewind_nbytes = nbytes; + pa_sink_process_rewind(u->sink); +} - if (length < u->memchunk.length) { - u->memchunk.index += length; - u->memchunk.length -= length; - return; - } +/* Called from I/O thread context */ +static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes) { + struct userdata *u; - pa_memblock_unref(u->memchunk.memblock); - length -= u->memchunk.length; - pa_memchunk_reset(&u->memchunk); - } + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); - if (length > 0) - pa_sink_skip(u->sink, length); + pa_sink_set_max_rewind(u->sink, nbytes); } /* Called from I/O thread context */ @@ -211,9 +227,10 @@ int pa__init(pa_module*m) { pa_channel_map sink_map, stream_map; pa_modargs *ma; char *t; + const char *k; pa_sink *master; - pa_sink_input_new_data data; - char *default_sink_name = NULL; + pa_sink_input_new_data sink_input_data; + pa_sink_new_data sink_data; pa_assert(m); @@ -245,47 +262,68 @@ int pa__init(pa_module*m) { goto fail; } + if (pa_channel_map_equal(&stream_map, &master->channel_map)) + pa_log_warn("No remapping configured, proceeding nonetheless!"); + u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; m->userdata = u; u->master = master; - pa_memchunk_reset(&u->memchunk); - - default_sink_name = pa_sprintf_malloc("%s.remapped", master->name); + u->sink = NULL; + u->sink_input = NULL; /* Create sink */ - if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", default_sink_name), 0, &ss, &sink_map))) { + pa_sink_new_data_init(&sink_data); + sink_data.driver = __FILE__; + sink_data.module = m; + if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL)))) + sink_data.name = pa_sprintf_malloc("%s.remapped", master->name); + pa_sink_new_data_set_sample_spec(&sink_data, &ss); + pa_sink_new_data_set_channel_map(&sink_data, &sink_map); + k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION); + pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Remapped %s", k ? k : master->name)); + pa_xfree(t); + pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name); + + u->sink = pa_sink_new(m->core, &sink_data, 0); + pa_sink_new_data_done(&sink_data); + + if (!u->sink) { pa_log("Failed to create sink."); goto fail; } u->sink->parent.process_msg = sink_process_msg; u->sink->set_state = sink_set_state; + u->sink->update_requested_latency = sink_update_requested_latency; + u->sink->request_rewind = sink_request_rewind; u->sink->userdata = u; u->sink->flags = PA_SINK_LATENCY; - pa_sink_set_module(u->sink, m); - pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Remapped %s", master->description)); - pa_xfree(t); pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq); pa_sink_set_rtpoll(u->sink, master->rtpoll); /* Create sink input */ - pa_sink_input_new_data_init(&data); - data.sink = u->master; - data.driver = __FILE__; - data.name = "Remapped Stream"; - pa_sink_input_new_data_set_sample_spec(&data, &ss); - pa_sink_input_new_data_set_channel_map(&data, &stream_map); - data.module = m; - - if (!(u->sink_input = pa_sink_input_new(m->core, &data, PA_SINK_INPUT_DONT_MOVE))) + pa_sink_input_new_data_init(&sink_input_data); + sink_input_data.driver = __FILE__; + sink_input_data.module = m; + sink_input_data.sink = u->master; + pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Remapped Stream"); + pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "routing"); + pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); + pa_sink_input_new_data_set_channel_map(&sink_input_data, &stream_map); + + u->sink_input = pa_sink_input_new(m->core, &sink_input_data, PA_SINK_INPUT_DONT_MOVE); + pa_sink_input_new_data_done(&sink_input_data); + + if (!u->sink_input) goto fail; u->sink_input->parent.process_msg = sink_input_process_msg; - u->sink_input->peek = sink_input_peek_cb; - u->sink_input->drop = sink_input_drop_cb; + u->sink_input->pop = sink_input_pop_cb; + u->sink_input->rewind = sink_input_rewind_cb; + u->sink_input->set_max_rewind = sink_input_set_max_rewind_cb; u->sink_input->kill = sink_input_kill_cb; u->sink_input->attach = sink_input_attach_cb; u->sink_input->detach = sink_input_detach_cb; @@ -295,7 +333,6 @@ int pa__init(pa_module*m) { pa_sink_input_put(u->sink_input); pa_modargs_free(ma); - pa_xfree(default_sink_name); return 0; @@ -305,8 +342,6 @@ fail: pa__done(m); - pa_xfree(default_sink_name); - return -1; } @@ -328,8 +363,5 @@ void pa__done(pa_module*m) { pa_sink_unref(u->sink); } - if (u->memchunk.memblock) - pa_memblock_unref(u->memchunk.memblock); - pa_xfree(u); } |