]> code.delx.au - pulseaudio/blobdiff - src/modules/module-pipe-source.c
alsa-mixer: Make sure capture source and input source use right path
[pulseaudio] / src / modules / module-pipe-source.c
index b0de34cab94cbeaabdd21fa1f9551e5b987b8baa..c50536efae80478299bdc89633345494b8361979 100644 (file)
@@ -5,7 +5,7 @@
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
 #include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
-#include <sys/poll.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
 
 #include <pulse/xmalloc.h>
 
 
 #include <pulse/xmalloc.h>
 
@@ -44,6 +48,7 @@
 #include <pulsecore/thread.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtpoll.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtpoll.h>
+#include <pulsecore/poll.h>
 
 #include "module-pipe-source-symdef.h"
 
 
 #include "module-pipe-source-symdef.h"
 
@@ -53,10 +58,11 @@ PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
         "source_name=<name for the source> "
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
         "source_name=<name for the source> "
+        "source_properties=<properties for the source> "
         "file=<path of the FIFO> "
         "format=<sample format> "
         "file=<path of the FIFO> "
         "format=<sample format> "
-        "channels=<number of channels> "
         "rate=<sample rate> "
         "rate=<sample rate> "
+        "channels=<number of channels> "
         "channel_map=<channel map>");
 
 #define DEFAULT_FILE_NAME "/tmp/music.input"
         "channel_map=<channel map>");
 
 #define DEFAULT_FILE_NAME "/tmp/music.input"
@@ -80,15 +86,45 @@ struct userdata {
 };
 
 static const char* const valid_modargs[] = {
 };
 
 static const char* const valid_modargs[] = {
+    "source_name",
+    "source_properties",
     "file",
     "file",
+    "format",
     "rate",
     "channels",
     "rate",
     "channels",
-    "format",
-    "source_name",
     "channel_map",
     NULL
 };
 
     "channel_map",
     NULL
 };
 
+static int source_process_msg(
+        pa_msgobject *o,
+        int code,
+        void *data,
+        int64_t offset,
+        pa_memchunk *chunk) {
+
+    struct userdata *u = PA_SOURCE(o)->userdata;
+
+    switch (code) {
+
+        case PA_SOURCE_MESSAGE_GET_LATENCY: {
+            size_t n = 0;
+
+#ifdef FIONREAD
+            int l;
+
+            if (ioctl(u->fd, FIONREAD, &l) >= 0 && l > 0)
+                n = (size_t) l;
+#endif
+
+            *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->source->sample_spec);
+            return 0;
+        }
+    }
+
+    return pa_source_process_msg(o, code, data, offset, chunk);
+}
+
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
     int read_type = 0;
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
     int read_type = 0;
@@ -98,7 +134,6 @@ static void thread_func(void *userdata) {
     pa_log_debug("Thread starting up");
 
     pa_thread_mq_install(&u->thread_mq);
     pa_log_debug("Thread starting up");
 
     pa_thread_mq_install(&u->thread_mq);
-    pa_rtpoll_install(u->rtpoll);
 
     for (;;) {
         int ret;
 
     for (;;) {
         int ret;
@@ -112,7 +147,7 @@ static void thread_func(void *userdata) {
             void *p;
 
             if (!u->memchunk.memblock) {
             void *p;
 
             if (!u->memchunk.memblock) {
-                u->memchunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF);
+                u->memchunk.memblock = pa_memblock_new(u->core->mempool, pa_pipe_buf(u->fd));
                 u->memchunk.index = u->memchunk.length = 0;
             }
 
                 u->memchunk.index = u->memchunk.length = 0;
             }
 
@@ -129,15 +164,15 @@ static void thread_func(void *userdata) {
                 if (errno == EINTR)
                     continue;
                 else if (errno != EAGAIN) {
                 if (errno == EINTR)
                     continue;
                 else if (errno != EAGAIN) {
-                    pa_log("Faile to read data from FIFO: %s", pa_cstrerror(errno));
+                    pa_log("Failed to read data from FIFO: %s", pa_cstrerror(errno));
                     goto fail;
                 }
 
             } else {
 
                     goto fail;
                 }
 
             } else {
 
-                u->memchunk.length = l;
+                u->memchunk.length = (size_t) l;
                 pa_source_post(u->source, &u->memchunk);
                 pa_source_post(u->source, &u->memchunk);
-                u->memchunk.index += l;
+                u->memchunk.index += (size_t) l;
 
                 if (u->memchunk.index >= pa_memblock_get_length(u->memchunk.memblock)) {
                     pa_memblock_unref(u->memchunk.memblock);
 
                 if (u->memchunk.index >= pa_memblock_get_length(u->memchunk.memblock)) {
                     pa_memblock_unref(u->memchunk.memblock);
@@ -149,7 +184,7 @@ static void thread_func(void *userdata) {
         }
 
         /* Hmm, nothing to do. Let's sleep */
         }
 
         /* Hmm, nothing to do. Let's sleep */
-        pollfd->events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0;
+        pollfd->events = (short) (u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0);
 
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
@@ -192,15 +227,15 @@ int pa__init(pa_module*m) {
     }
 
     ss = m->core->default_sample_spec;
     }
 
     ss = m->core->default_sample_spec;
+    map = m->core->default_channel_map;
     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
         pa_log("invalid sample format specification or channel map");
         goto fail;
     }
 
     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
         pa_log("invalid sample format specification or channel map");
         goto fail;
     }
 
-    u = pa_xnew0(struct userdata, 1);
+    m->userdata = u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
     u->core = m->core;
     u->module = m;
-    m->userdata = u;
     pa_memchunk_reset(&u->memchunk);
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
     pa_memchunk_reset(&u->memchunk);
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
@@ -208,12 +243,11 @@ int pa__init(pa_module*m) {
     u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
     mkfifo(u->filename, 0666);
     u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
     mkfifo(u->filename, 0666);
-    if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) {
+    if ((u->fd = pa_open_cloexec(u->filename, O_RDWR, 0)) < 0) {
         pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno));
         goto fail;
     }
 
         pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_make_fd_cloexec(u->fd);
     pa_make_fd_nonblock(u->fd);
 
     if (fstat(u->fd, &st) < 0) {
     pa_make_fd_nonblock(u->fd);
 
     if (fstat(u->fd, &st) < 0) {
@@ -235,7 +269,13 @@ int pa__init(pa_module*m) {
     pa_source_new_data_set_sample_spec(&data, &ss);
     pa_source_new_data_set_channel_map(&data, &map);
 
     pa_source_new_data_set_sample_spec(&data, &ss);
     pa_source_new_data_set_channel_map(&data, &map);
 
-    u->source = pa_source_new(m->core, &data, 0);
+    if (pa_modargs_get_proplist(ma, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
+        pa_log("Invalid properties");
+        pa_source_new_data_done(&data);
+        goto fail;
+    }
+
+    u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY);
     pa_source_new_data_done(&data);
 
     if (!u->source) {
     pa_source_new_data_done(&data);
 
     if (!u->source) {
@@ -243,17 +283,19 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
         goto fail;
     }
 
+    u->source->parent.process_msg = source_process_msg;
     u->source->userdata = u;
 
     pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
     pa_source_set_rtpoll(u->source, u->rtpoll);
     u->source->userdata = u;
 
     pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
     pa_source_set_rtpoll(u->source, u->rtpoll);
+    pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(PIPE_BUF, &u->source->sample_spec));
 
     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;
     pollfd->events = pollfd->revents = 0;
 
 
     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;
     pollfd->events = pollfd->revents = 0;
 
-    if (!(u->thread = pa_thread_new(thread_func, u))) {
+    if (!(u->thread = pa_thread_new("pipe-source", thread_func, u))) {
         pa_log("Failed to create thread.");
         goto fail;
     }
         pa_log("Failed to create thread.");
         goto fail;
     }
@@ -273,6 +315,15 @@ fail:
     return -1;
 }
 
     return -1;
 }
 
+int pa__get_n_used(pa_module *m) {
+    struct userdata *u;
+
+    pa_assert(m);
+    pa_assert_se(u = m->userdata);
+
+    return pa_source_linked_by(u->source);
+}
+
 void pa__done(pa_module*m) {
     struct userdata *u;
 
 void pa__done(pa_module*m) {
     struct userdata *u;