]> code.delx.au - pulseaudio/blobdiff - src/modules/module-esound-sink.c
Remove pa_bool_t and replace it with bool.
[pulseaudio] / src / modules / module-esound-sink.c
index 14f1810a4a63f401f021a1df667471777fdb700c..8b74ea433cfebedadbad7d3161166f37eda62034 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
 #endif
 
 #include <stdlib.h>
 #endif
 
 #include <stdlib.h>
-#include <sys/stat.h>
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
-#include <fcntl.h>
 #include <unistd.h>
 #include <unistd.h>
-#include <limits.h>
-#include <poll.h>
-#include <sys/socket.h>
+
+#ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #include <netinet/in.h>
+#endif
+
+#ifdef HAVE_NETINET_TCP_H
 #include <netinet/tcp.h>
 #include <netinet/tcp.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #include <sys/ioctl.h>
+#endif
 
 #ifdef HAVE_LINUX_SOCKIOS_H
 #include <linux/sockios.h>
 #endif
 
 
 #ifdef HAVE_LINUX_SOCKIOS_H
 #include <linux/sockios.h>
 #endif
 
-#include <pulse/xmalloc.h>
+#include <pulse/rtclock.h>
 #include <pulse/timeval.h>
 #include <pulse/timeval.h>
+#include <pulse/xmalloc.h>
 
 
+#include <pulsecore/socket.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/iochannel.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/iochannel.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/time-smoother.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/time-smoother.h>
-#include <pulsecore/rtclock.h>
 #include <pulsecore/socket-util.h>
 #include <pulsecore/socket-util.h>
+#include <pulsecore/rtpoll.h>
+#include <pulsecore/poll.h>
 
 #include "module-esound-sink-symdef.h"
 
 PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("ESOUND Sink");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 
 #include "module-esound-sink-symdef.h"
 
 PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("ESOUND Sink");
 PA_MODULE_VERSION(PACKAGE_VERSION);
-PA_MODULE_LOAD_ONCE(FALSE);
+PA_MODULE_LOAD_ONCE(false);
 PA_MODULE_USAGE(
         "sink_name=<name for the sink> "
 PA_MODULE_USAGE(
         "sink_name=<name for the sink> "
+        "sink_properties=<properties for the sink> "
         "server=<address> cookie=<filename>  "
         "format=<sample format> "
         "server=<address> cookie=<filename>  "
         "format=<sample format> "
-        "channels=<number of channels> "
-        "rate=<sample rate>");
+        "rate=<sample rate> "
+        "channels=<number of channels>");
 
 #define DEFAULT_SINK_NAME "esound_out"
 
 
 #define DEFAULT_SINK_NAME "esound_out"
 
@@ -118,12 +126,13 @@ struct userdata {
 };
 
 static const char* const valid_modargs[] = {
 };
 
 static const char* const valid_modargs[] = {
+    "sink_name",
+    "sink_properties",
     "server",
     "cookie",
     "server",
     "cookie",
-    "rate",
     "format",
     "format",
+    "rate",
     "channels",
     "channels",
-    "sink_name",
     NULL
 };
 
     NULL
 };
 
@@ -143,19 +152,20 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                 case PA_SINK_SUSPENDED:
                     pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
 
                 case PA_SINK_SUSPENDED:
                     pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
 
-                    pa_smoother_pause(u->smoother, pa_rtclock_usec());
+                    pa_smoother_pause(u->smoother, pa_rtclock_now());
                     break;
 
                 case PA_SINK_IDLE:
                 case PA_SINK_RUNNING:
 
                     if (u->sink->thread_info.state == PA_SINK_SUSPENDED)
                     break;
 
                 case PA_SINK_IDLE:
                 case PA_SINK_RUNNING:
 
                     if (u->sink->thread_info.state == PA_SINK_SUSPENDED)
-                        pa_smoother_resume(u->smoother, pa_rtclock_usec());
+                        pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
 
                     break;
 
                 case PA_SINK_UNLINKED:
                 case PA_SINK_INIT:
 
                     break;
 
                 case PA_SINK_UNLINKED:
                 case PA_SINK_INIT:
+                case PA_SINK_INVALID_STATE:
                     ;
             }
 
                     ;
             }
 
@@ -164,11 +174,11 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case PA_SINK_MESSAGE_GET_LATENCY: {
             pa_usec_t w, r;
 
         case PA_SINK_MESSAGE_GET_LATENCY: {
             pa_usec_t w, r;
 
-            r = pa_smoother_get(u->smoother, pa_rtclock_usec());
+            r = pa_smoother_get(u->smoother, pa_rtclock_now());
             w = pa_bytes_to_usec((uint64_t) u->offset + u->memchunk.length, &u->sink->sample_spec);
 
             *((pa_usec_t*) data) = w > r ? w - r : 0;
             w = pa_bytes_to_usec((uint64_t) u->offset + u->memchunk.length, &u->sink->sample_spec);
 
             *((pa_usec_t*) data) = w > r ? w - r : 0;
-            break;
+            return 0;
         }
 
         case SINK_MESSAGE_PASS_SOCKET: {
         }
 
         case SINK_MESSAGE_PASS_SOCKET: {
@@ -197,16 +207,14 @@ 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);
 
 
-    pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
+    pa_smoother_set_time_offset(u->smoother, pa_rtclock_now());
 
     for (;;) {
         int ret;
 
 
     for (;;) {
         int ret;
 
-        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
-            if (u->sink->thread_info.rewind_requested)
-                pa_sink_process_rewind(u->sink, 0);
+        if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
+            pa_sink_process_rewind(u->sink, 0);
 
         if (u->rtpoll_item) {
             struct pollfd *pollfd;
 
         if (u->rtpoll_item) {
             struct pollfd *pollfd;
@@ -292,14 +300,14 @@ static void thread_func(void *userdata) {
                 else
                     usec = 0;
 
                 else
                     usec = 0;
 
-                pa_smoother_put(u->smoother, pa_rtclock_usec(), usec);
+                pa_smoother_put(u->smoother, pa_rtclock_now(), usec);
             }
 
             /* Hmm, nothing to do. Let's sleep */
             pollfd->events = (short) (PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0);
         }
 
             }
 
             /* Hmm, nothing to do. Let's sleep */
             pollfd->events = (short) (PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0);
         }
 
-        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
+        if ((ret = pa_rtpoll_run(u->rtpoll, true)) < 0)
             goto fail;
 
         if (ret == 0)
             goto fail;
 
         if (ret == 0)
@@ -337,7 +345,7 @@ static int do_write(struct userdata *u) {
     if (u->write_data) {
         pa_assert(u->write_index < u->write_length);
 
     if (u->write_data) {
         pa_assert(u->write_index < u->write_length);
 
-        if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) <= 0) {
+        if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) < 0) {
             pa_log("write() failed: %s", pa_cstrerror(errno));
             return -1;
         }
             pa_log("write() failed: %s", pa_cstrerror(errno));
             return -1;
         }
@@ -353,18 +361,28 @@ static int do_write(struct userdata *u) {
     }
 
     if (!u->write_data && u->state == STATE_PREPARE) {
     }
 
     if (!u->write_data && u->state == STATE_PREPARE) {
+        int so_sndbuf = 0;
+        socklen_t sl = sizeof(int);
+
         /* OK, we're done with sending all control data we need to, so
          * let's hand the socket over to the IO thread now */
 
         pa_assert(u->fd < 0);
         u->fd = pa_iochannel_get_send_fd(u->io);
 
         /* OK, we're done with sending all control data we need to, so
          * let's hand the socket over to the IO thread now */
 
         pa_assert(u->fd < 0);
         u->fd = pa_iochannel_get_send_fd(u->io);
 
-        pa_iochannel_set_noclose(u->io, TRUE);
+        pa_iochannel_set_noclose(u->io, true);
         pa_iochannel_free(u->io);
         u->io = NULL;
 
         pa_make_tcp_socket_low_delay(u->fd);
 
         pa_iochannel_free(u->io);
         u->io = NULL;
 
         pa_make_tcp_socket_low_delay(u->fd);
 
+        if (getsockopt(u->fd, SOL_SOCKET, SO_SNDBUF, (void *) &so_sndbuf, &sl) < 0)
+            pa_log_warn("getsockopt(SO_SNDBUF) failed: %s", pa_cstrerror(errno));
+        else {
+            pa_log_debug("SO_SNDBUF is %zu.", (size_t) so_sndbuf);
+            pa_sink_set_max_request(u->sink, PA_MAX((size_t) so_sndbuf, u->block_size));
+        }
+
         pa_log_debug("Connection authenticated, handing fd to IO thread...");
 
         pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL);
         pa_log_debug("Connection authenticated, handing fd to IO thread...");
 
         pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL);
@@ -479,7 +497,7 @@ static void io_callback(pa_iochannel *io, void*userdata) {
             u->io = NULL;
         }
 
             u->io = NULL;
         }
 
-        pa_module_unload_request(u->module, TRUE);
+        pa_module_unload_request(u->module, true);
     }
 }
 
     }
 }
 
@@ -491,7 +509,7 @@ static void on_connection(pa_socket_client *c, pa_iochannel*io, void *userdata)
 
     if (!io) {
         pa_log("Connection failed: %s", pa_cstrerror(errno));
 
     if (!io) {
         pa_log("Connection failed: %s", pa_cstrerror(errno));
-        pa_module_unload_request(u->module, TRUE);
+        pa_module_unload_request(u->module, true);
         return;
     }
 
         return;
     }
 
@@ -534,7 +552,14 @@ int pa__init(pa_module*m) {
     u->module = m;
     m->userdata = u;
     u->fd = -1;
     u->module = m;
     m->userdata = u;
     u->fd = -1;
-    u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
+    u->smoother = pa_smoother_new(
+            PA_USEC_PER_SEC,
+            PA_USEC_PER_SEC*2,
+            true,
+            true,
+            10,
+            0,
+            false);
     pa_memchunk_reset(&u->memchunk);
     u->offset = 0;
 
     pa_memchunk_reset(&u->memchunk);
     u->offset = 0;
 
@@ -565,7 +590,14 @@ int pa__init(pa_module*m) {
     pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
     pa_sink_new_data_set_sample_spec(&data, &ss);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, espeaker);
     pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
     pa_sink_new_data_set_sample_spec(&data, &ss);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, espeaker);
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Esound sink '%s'", espeaker);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "esd");
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "EsounD Output on %s", espeaker);
+
+    if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
+        pa_log("Invalid properties");
+        pa_sink_new_data_done(&data);
+        goto fail;
+    }
 
     u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY|PA_SINK_NETWORK);
     pa_sink_new_data_done(&data);
 
     u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY|PA_SINK_NETWORK);
     pa_sink_new_data_done(&data);
@@ -581,7 +613,7 @@ int pa__init(pa_module*m) {
     pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
     pa_sink_set_rtpoll(u->sink, u->rtpoll);
 
     pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
     pa_sink_set_rtpoll(u->sink, u->rtpoll);
 
-    if (!(u->client = pa_socket_client_new_string(u->core->mainloop, espeaker, ESD_DEFAULT_PORT))) {
+    if (!(u->client = pa_socket_client_new_string(u->core->mainloop, true, espeaker, ESD_DEFAULT_PORT))) {
         pa_log("Failed to connect to server.");
         goto fail;
     }
         pa_log("Failed to connect to server.");
         goto fail;
     }
@@ -590,7 +622,7 @@ int pa__init(pa_module*m) {
 
     /* Prepare the initial request */
     u->write_data = pa_xmalloc(u->write_length = ESD_KEY_LEN + sizeof(int32_t));
 
     /* Prepare the initial request */
     u->write_data = pa_xmalloc(u->write_length = ESD_KEY_LEN + sizeof(int32_t));
-    if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", ".esd_auth"), u->write_data, ESD_KEY_LEN) < 0) {
+    if (pa_authkey_load_auto(pa_modargs_get_value(ma, "cookie", ".esd_auth"), true, u->write_data, ESD_KEY_LEN) < 0) {
         pa_log("Failed to load cookie");
         goto fail;
     }
         pa_log("Failed to load cookie");
         goto fail;
     }
@@ -601,7 +633,7 @@ int pa__init(pa_module*m) {
     /* Reserve space for the response */
     u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t));
 
     /* Reserve space for the response */
     u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t));
 
-    if (!(u->thread = pa_thread_new(thread_func, u))) {
+    if (!(u->thread = pa_thread_new("esound-sink", thread_func, u))) {
         pa_log("Failed to create thread.");
         goto fail;
     }
         pa_log("Failed to create thread.");
         goto fail;
     }
@@ -621,6 +653,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_sink_linked_by(u->sink);
+}
+
 void pa__done(pa_module*m) {
     struct userdata *u;
     pa_assert(m);
 void pa__done(pa_module*m) {
     struct userdata *u;
     pa_assert(m);