[pulseaudio-discuss] [PATCH] pipe-sink: auto-drain the pipe on sink resume

Samo Pogačnik samo_pogacnik at t-2.net
Sat Feb 24 16:41:35 UTC 2018


Added option auto_drain_pipe_on_resume to enable draining any remaining
data from the pipe upon every pipe-sink resume out of suspend.
---
 src/modules/module-pipe-sink.c | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 995785e..10ce882 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -62,6 +62,7 @@ PA_MODULE_USAGE(
         "channels=<number of channels> "
         "channel_map=<channel map> "
         "use_system_clock_for_timing=<yes or no> "
+        "auto_drain_pipe_on_resume=<yes or no> "
 );
 
 #define DEFAULT_FILE_NAME "fifo_output"
@@ -82,16 +83,19 @@ struct userdata {
     size_t buffer_size;
     size_t bytes_dropped;
     bool fifo_error;
+    uint8_t *drain_buffer;
 
     pa_memchunk memchunk;
 
     pa_rtpoll_item *rtpoll_item;
 
+    int read_type;
     int write_type;
     pa_usec_t block_usec;
     pa_usec_t timestamp;
 
     bool use_system_clock_for_timing;
+    bool auto_drain_pipe_on_resume;
 };
 
 static const char* const valid_modargs[] = {
@@ -103,17 +107,39 @@ static const char* const valid_modargs[] = {
     "channels",
     "channel_map",
     "use_system_clock_for_timing",
+    "auto_drain_pipe_on_resume",
     NULL
 };
 
+static ssize_t drain_pipe_sink(struct userdata *u) {
+    ssize_t l, drained = 0;
+
+    pa_assert(u);
+
+    do {
+        l = pa_read(u->fd, u->drain_buffer, u->buffer_size, &u->read_type);
+
+        if (l > 0)
+            drained += l;
+
+    } while ((l > 0) || (errno == EINTR));
+
+    return drained;
+}
+
 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
     struct userdata *u = PA_SINK(o)->userdata;
 
     switch (code) {
         case PA_SINK_MESSAGE_SET_STATE:
             if (u->sink->thread_info.state == PA_SINK_SUSPENDED || u->sink->thread_info.state == PA_SINK_INIT) {
-                if (PA_SINK_IS_OPENED(PA_PTR_TO_UINT(data)))
+                if (PA_SINK_IS_OPENED(PA_PTR_TO_UINT(data))) {
                     u->timestamp = pa_rtclock_now();
+                    if (u->auto_drain_pipe_on_resume) {
+                        ssize_t d = drain_pipe_sink(u);
+                        pa_log_debug("Pipe-sink resume from suspend: auto-drained %zd bytes from the pipe", d);
+                    }
+                }
             } else if (u->sink->thread_info.state == PA_SINK_RUNNING || u->sink->thread_info.state == PA_SINK_IDLE) {
                 if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) {
                     /* Clear potential FIFO error flag */
@@ -443,11 +469,17 @@ int pa__init(pa_module *m) {
         goto fail;
     }
 
+    if (pa_modargs_get_value_boolean(ma, "auto_drain_pipe_on_resume", &u->auto_drain_pipe_on_resume) < 0) {
+        pa_log("Failed to parse auto_drain_pipe_on_resume argument.");
+        goto fail;
+    }
+
     if (pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll) < 0) {
         pa_log("pa_thread_mq_init() failed.");
         goto fail;
     }
 
+    u->read_type = 0;
     u->write_type = 0;
 
     u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
@@ -525,6 +557,9 @@ int pa__init(pa_module *m) {
     }
     pa_sink_set_max_request(u->sink, u->buffer_size);
 
+    if (u->auto_drain_pipe_on_resume)
+        u->drain_buffer = (uint8_t *)pa_xmalloc(u->buffer_size);
+
     u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
     pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
     pollfd->fd = u->fd;
-- 
2.7.4

regards, Samo


More information about the pulseaudio-discuss mailing list