Some people want module-rtp-send to send silence when the sink that is monitored goes idle, and some people want module-rtp-send to pause the RTP stream to avoid unnecessary bandwidth consumption. --- src/modules/rtp/module-rtp-send.c | 63 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 454e781..a2bc395 100644 --- a/src/modules/rtp/module-rtp-send.c +++ b/src/modules/rtp/module-rtp-send.c @@ -68,7 +68,8 @@ PA_MODULE_USAGE( "port=<port number> " "mtu=<maximum transfer unit> " "loop=<loopback to local host?> " - "ttl=<ttl value>" + "ttl=<ttl value> " + "allow_suspending_on_idle=<always|never|only_with_monitor_sources>" ); #define DEFAULT_PORT 46000 @@ -92,9 +93,16 @@ static const char* const valid_modargs[] = { "mtu" , "loop", "ttl", + "allow_suspending_on_idle", NULL }; +enum allow_suspending_on_idle { + ALLOW_SUSPENDING_ON_IDLE_ALWAYS, + ALLOW_SUSPENDING_ON_IDLE_NEVER, + ALLOW_SUSPENDING_ON_IDLE_ONLY_WITH_MONITOR_SOURCES +}; + struct userdata { pa_module *module; @@ -106,6 +114,8 @@ struct userdata { size_t mtu; pa_time_event *sap_event; + + enum allow_suspending_on_idle allow_suspending_on_idle; }; /* Called from I/O thread context */ @@ -139,6 +149,39 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) pa_rtp_send(&u->rtp_context, u->mtu, u->memblockq); } +static pa_source_output_flags_t get_dont_inhibit_auto_suspend_flag(pa_source *source, + enum allow_suspending_on_idle allow_suspending_on_idle) { + pa_assert(source); + + switch (allow_suspending_on_idle) { + case ALLOW_SUSPENDING_ON_IDLE_ALWAYS: + return PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; + + case ALLOW_SUSPENDING_ON_IDLE_NEVER: + return 0; + + case ALLOW_SUSPENDING_ON_IDLE_ONLY_WITH_MONITOR_SOURCES: + return source->monitor_of ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0; + } + + pa_assert_not_reached(); +} + +/* Called from the main thread. */ +static void source_output_moving_cb(pa_source_output *o, pa_source *dest) { + struct userdata *u; + + pa_assert(o); + + u = o->userdata; + + if (!dest) + return; + + o->flags &= ~PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; + o->flags |= get_dont_inhibit_auto_suspend_flag(dest, u->allow_suspending_on_idle); +} + /* Called from main context */ static void source_output_kill_cb(pa_source_output* o) { struct userdata *u; @@ -188,6 +231,8 @@ int pa__init(pa_module*m) { socklen_t k; char hn[128], *n; bool loop = false; + enum allow_suspending_on_idle allow_suspending_on_idle = ALLOW_SUSPENDING_ON_IDLE_ONLY_WITH_MONITOR_SOURCES; + const char *allow_suspending_on_idle_str; pa_source_output_new_data data; pa_assert(m); @@ -207,6 +252,19 @@ int pa__init(pa_module*m) { goto fail; } + if ((allow_suspending_on_idle_str = pa_modargs_get_value(ma, "allow_suspending_on_idle", NULL))) { + if (pa_streq(allow_suspending_on_idle_str, "always")) + allow_suspending_on_idle = ALLOW_SUSPENDING_ON_IDLE_ALWAYS; + else if (pa_streq(allow_suspending_on_idle_str, "never")) + allow_suspending_on_idle = ALLOW_SUSPENDING_ON_IDLE_NEVER; + else if (pa_streq(allow_suspending_on_idle_str, "only_with_monitor_sources")) + allow_suspending_on_idle = ALLOW_SUSPENDING_ON_IDLE_ONLY_WITH_MONITOR_SOURCES; + else { + pa_log("Failed to parse \"allow_suspending_on_idle\" parameter."); + goto fail; + } + } + ss = s->sample_spec; pa_rtp_sample_spec_fixup(&ss); cm = s->channel_map; @@ -377,6 +435,7 @@ int pa__init(pa_module*m) { pa_source_output_new_data_set_source(&data, s, false); pa_source_output_new_data_set_sample_spec(&data, &ss); pa_source_output_new_data_set_channel_map(&data, &cm); + data.flags |= get_dont_inhibit_auto_suspend_flag(s, allow_suspending_on_idle); pa_source_output_new(&o, m->core, &data); pa_source_output_new_data_done(&data); @@ -388,6 +447,7 @@ int pa__init(pa_module*m) { o->parent.process_msg = source_output_process_msg; o->push = source_output_push_cb; + o->moving = source_output_moving_cb; o->kill = source_output_kill_cb; pa_log_info("Configured source latency of %llu ms.", @@ -440,6 +500,7 @@ int pa__init(pa_module*m) { pa_sap_send(&u->sap_context, 0); u->sap_event = pa_core_rttime_new(m->core, pa_rtclock_now() + SAP_INTERVAL, sap_event_cb, u); + u->allow_suspending_on_idle = allow_suspending_on_idle; pa_source_output_put(u->source_output); -- 1.8.3.1