[PATCH v6 2/2] pipe-source: implement autosuspend option

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 b7eb4bf..76c0691 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,
@@ -185,6 +231,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;
 
@@ -194,6 +243,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;
@@ -290,6 +342,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) {
@@ -418,6 +482,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



[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux