This patch adds the autosuspend=<bool> option to suspend pipe-source instead of generating silence when no writers are connected to pipe. --- src/modules/module-pipe-source.c | 69 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c index 152d84e..a416657 100644 --- a/src/modules/module-pipe-source.c +++ b/src/modules/module-pipe-source.c @@ -58,11 +58,24 @@ PA_MODULE_USAGE( "format=<sample format> " "rate=<sample rate> " "channels=<number of channels> " - "channel_map=<channel map>"); + "channel_map=<channel map> " + "autosuspend=<boolean>"); #define DEFAULT_FILE_NAME "/tmp/music.input" #define DEFAULT_SOURCE_NAME "fifo_input" +struct pipe_source_msg { + pa_msgobject parent; +}; + +typedef struct pipe_source_msg pipe_source_msg; +PA_DEFINE_PRIVATE_CLASS(pipe_source_msg, pa_msgobject); + +enum { + PIPE_SOURCE_SUSPEND, + PIPE_SOURCE_RESUME +}; + struct userdata { pa_core *core; pa_module *module; @@ -72,8 +85,10 @@ struct userdata { pa_thread_mq thread_mq; pa_rtpoll *rtpoll; + pipe_source_msg *msg; pa_usec_t timestamp; pa_usec_t latency; + bool autosuspend; char *filename; int corkfd; @@ -92,9 +107,40 @@ static const char* const valid_modargs[] = { "rate", "channels", "channel_map", + "autosuspend", NULL }; +/* Called from main context */ +static int pipe_source_process_msg( + pa_msgobject *o, + int code, + void *data, + int64_t offset, + pa_memchunk *chunk) { + + struct userdata *u = (struct userdata *) data; + + pa_assert(u); + + switch (code) { + case PIPE_SOURCE_SUSPEND: + pa_log_debug("Suspending source %s because no writers left", u->source->name); + pa_source_suspend(u->source, true, PA_SUSPEND_APPLICATION); + break; + + case PIPE_SOURCE_RESUME: + pa_log_debug("Resuming source %s", u->source->name); + pa_source_suspend(u->source, false, PA_SUSPEND_APPLICATION); + break; + + default: + pa_assert_not_reached(); + } + + return 0; +} + /* Called from thread context */ static int source_process_msg( pa_msgobject *o, @@ -174,6 +220,9 @@ static void thread_func(void *userdata) { } if (u->corkfd >= 0) { + if (u->autosuspend) + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->msg), PIPE_SOURCE_RESUME, u, 0, NULL, NULL); + pa_assert_se(pa_close(u->corkfd) == 0); u->corkfd = -1; @@ -183,6 +232,9 @@ static void thread_func(void *userdata) { if (u->corkfd < 0) { pa_log_debug("There are no writers left"); + if (u->autosuspend) + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->msg), PIPE_SOURCE_SUSPEND, u, 0, NULL, NULL); + if ((u->corkfd = pa_open_cloexec(u->filename, O_WRONLY, 0)) < 0) { pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno)); goto fail; @@ -278,6 +330,18 @@ int pa__init(pa_module *m) { goto fail; } + if (!(u->msg = pa_msgobject_new(pipe_source_msg))) + goto fail; + + u->msg->parent.process_msg = pipe_source_process_msg; + + u->autosuspend = false; + + if (pa_modargs_get_value_boolean(ma, "autosuspend", &u->autosuspend) < 0) { + pa_log("Failed to parse autosuspend= argument."); + goto fail; + } + u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME)); if (mkfifo(u->filename, 0666) < 0) { @@ -406,6 +470,9 @@ void pa__done(pa_module *m) { pa_xfree(u->filename); } + if (u->msg) + pa_xfree(u->msg); + if (u->corkfd >= 0) pa_assert_se(pa_close(u->corkfd) == 0); -- 1.8.3.1