]> code.delx.au - pulseaudio/blobdiff - src/modules/module-tunnel.c
introduce default channel map in addition to the default sample spec
[pulseaudio] / src / modules / module-tunnel.c
index ed7f4024f452596a37fc42e12e8fb61cf844f4cc..63ae740aba6ebb92c83c0488a95dd72a030ee1b3 100644 (file)
 #include <pulsecore/pdispatch.h>
 #include <pulsecore/pstream.h>
 #include <pulsecore/pstream-util.h>
-#include <pulsecore/authkey.h>
 #include <pulsecore/socket-client.h>
 #include <pulsecore/socket-util.h>
-#include <pulsecore/authkey-prop.h>
 #include <pulsecore/time-smoother.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtclock.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/proplist-util.h>
+#include <pulsecore/auth-cookie.h>
 
 #ifdef TUNNEL_SINK
 #include "module-tunnel-sink-symdef.h"
@@ -160,7 +159,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = command_suspended,
     [PA_COMMAND_RECORD_STREAM_SUSPENDED] = command_suspended,
     [PA_COMMAND_PLAYBACK_STREAM_MOVED] = command_moved,
-    [PA_COMMAND_RECORD_STREAM_MOVED] = command_moved,
+    [PA_COMMAND_RECORD_STREAM_MOVED] = command_moved
 };
 
 struct userdata {
@@ -179,13 +178,13 @@ struct userdata {
 #ifdef TUNNEL_SINK
     char *sink_name;
     pa_sink *sink;
-    int32_t requested_bytes;
+    size_t requested_bytes;
 #else
     char *source_name;
     pa_source *source;
 #endif
 
-    uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
+    pa_auth_cookie *auth_cookie;
 
     uint32_t version;
     uint32_t ctag;
@@ -204,8 +203,6 @@ struct userdata {
 
     pa_time_event *time_event;
 
-    pa_bool_t auth_cookie_in_property;
-
     pa_smoother *smoother;
 
     char *device_description;
@@ -234,7 +231,7 @@ static void command_stream_killed(pa_pdispatch *pd,  uint32_t command,  uint32_t
     pa_assert(u->pdispatch == pd);
 
     pa_log_warn("Stream killed");
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
 }
 
 /* Called from main context */
@@ -265,7 +262,7 @@ static void command_suspended(pa_pdispatch *pd,  uint32_t command,  uint32_t tag
         pa_tagstruct_get_boolean(t, &suspended) < 0 ||
         !pa_tagstruct_eof(t)) {
         pa_log("Invalid packet");
-        pa_module_unload_request(u->module);
+        pa_module_unload_request(u->module, TRUE);
         return;
     }
 
@@ -392,7 +389,7 @@ static void send_data(struct userdata *u) {
 
         u->requested_bytes -= memchunk.length;
 
-        u->counter += memchunk.length;
+        u->counter += (int64_t) memchunk.length;
     }
 }
 
@@ -420,7 +417,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case PA_SINK_MESSAGE_GET_LATENCY: {
             pa_usec_t yl, yr, *usec = data;
 
-            yl = pa_bytes_to_usec(u->counter, &u->sink->sample_spec);
+            yl = pa_bytes_to_usec((uint64_t) u->counter, &u->sink->sample_spec);
             yr = pa_smoother_get(u->smoother, pa_rtclock_usec());
 
             *usec = yl > yr ? yl - yr : 0;
@@ -447,10 +444,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case SINK_MESSAGE_UPDATE_LATENCY: {
             pa_usec_t y;
 
-            y = pa_bytes_to_usec(u->counter, &u->sink->sample_spec);
+            y = pa_bytes_to_usec((uint64_t) u->counter, &u->sink->sample_spec);
 
             if (y > (pa_usec_t) offset || offset < 0)
-                y -= offset;
+                y -= (pa_usec_t) offset;
             else
                 y = 0;
 
@@ -468,7 +465,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
             pa_pstream_send_memblock(u->pstream, u->channel, 0, PA_SEEK_RELATIVE, chunk);
 
-            u->counter_delta += chunk->length;
+            u->counter_delta += (int64_t) chunk->length;
 
             return 0;
     }
@@ -497,6 +494,7 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
 
         case PA_SINK_UNLINKED:
         case PA_SINK_INIT:
+        case PA_SINK_INVALID_STATE:
             ;
     }
 
@@ -511,10 +509,10 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
     switch (code) {
 
-        case PA_SINK_MESSAGE_SET_STATE: {
+        case PA_SOURCE_MESSAGE_SET_STATE: {
             int r;
 
-            if ((r = pa_sink_process_msg(o, code, data, offset, chunk)) >= 0)
+            if ((r = pa_source_process_msg(o, code, data, offset, chunk)) >= 0)
                 stream_cork_within_thread(u, u->source->state == PA_SOURCE_SUSPENDED);
 
             return r;
@@ -523,7 +521,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
         case PA_SOURCE_MESSAGE_GET_LATENCY: {
             pa_usec_t yr, yl, *usec = data;
 
-            yl = pa_bytes_to_usec(u->counter, &PA_SINK(o)->sample_spec);
+            yl = pa_bytes_to_usec((uint64_t) u->counter, &PA_SOURCE(o)->sample_spec);
             yr = pa_smoother_get(u->smoother, pa_rtclock_usec());
 
             *usec = yr > yl ? yr - yl : 0;
@@ -535,7 +533,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
             if (PA_SOURCE_IS_OPENED(u->source->thread_info.state))
                 pa_source_post(u->source, chunk);
 
-            u->counter += chunk->length;
+            u->counter += (int64_t) chunk->length;
 
             return 0;
 
@@ -547,10 +545,10 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
         case SOURCE_MESSAGE_UPDATE_LATENCY: {
             pa_usec_t y;
 
-            y = pa_bytes_to_usec(u->counter, &u->source->sample_spec);
+            y = pa_bytes_to_usec((uint64_t) u->counter, &u->source->sample_spec);
 
             if (offset >= 0 || y > (pa_usec_t) -offset)
-                y += offset;
+                y += (pa_usec_t) offset;
             else
                 y = 0;
 
@@ -584,6 +582,7 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
 
         case PA_SOURCE_UNLINKED:
         case PA_SOURCE_INIT:
+        case PA_SINK_INVALID_STATE:
             ;
     }
 
@@ -605,6 +604,12 @@ static void thread_func(void *userdata) {
     for (;;) {
         int ret;
 
+#ifdef TUNNEL_SINK
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+            if (u->sink->thread_info.rewind_requested)
+                pa_sink_process_rewind(u->sink, 0);
+#endif
+
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
@@ -649,7 +654,7 @@ static void command_request(pa_pdispatch *pd, uint32_t command,  uint32_t tag, p
     return;
 
 fail:
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
 }
 
 #endif
@@ -657,7 +662,7 @@ fail:
 /* Called from main context */
 static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     struct userdata *u = userdata;
-    pa_usec_t sink_usec, source_usec, transport_usec;
+    pa_usec_t sink_usec, source_usec, transport_usec = 0;
     pa_bool_t playing;
     int64_t write_index, read_index;
     struct timeval local, remote, now;
@@ -733,9 +738,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
 
     /* Add the length of our server-side buffer */
     if (write_index >= read_index)
-        delay += (int64_t) pa_bytes_to_usec(write_index-read_index, ss);
+        delay += (int64_t) pa_bytes_to_usec((uint64_t) (write_index-read_index), ss);
     else
-        delay -= (int64_t) pa_bytes_to_usec(read_index-write_index, ss);
+        delay -= (int64_t) pa_bytes_to_usec((uint64_t) (read_index-write_index), ss);
 
     /* Our measurements are already out of date, hence correct by the     *
      * transport latency */
@@ -747,9 +752,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
 
     /* Now correct by what we have have read/written since we requested the update */
 #ifdef TUNNEL_SINK
-    delay += (int64_t) pa_bytes_to_usec(u->counter_delta, ss);
+    delay += (int64_t) pa_bytes_to_usec((uint64_t) u->counter_delta, ss);
 #else
-    delay -= (int64_t) pa_bytes_to_usec(u->counter_delta, ss);
+    delay -= (int64_t) pa_bytes_to_usec((uint64_t) u->counter_delta, ss);
 #endif
 
 #ifdef TUNNEL_SINK
@@ -762,7 +767,7 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
 
 fail:
 
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
 }
 
 /* Called from main context */
@@ -899,7 +904,7 @@ static void server_info_cb(pa_pdispatch *pd, uint32_t command,  uint32_t tag, pa
     return;
 
 fail:
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
 }
 
 #ifdef TUNNEL_SINK
@@ -976,7 +981,7 @@ static void sink_info_cb(pa_pdispatch *pd, uint32_t command,  uint32_t tag, pa_t
     return;
 
 fail:
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
     pa_proplist_free(pl);
 }
 
@@ -1051,10 +1056,10 @@ static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command,  uint32_t tag
     pa_assert(u->sink);
 
     if ((u->version < 11 || !!mute == !!u->sink->muted) &&
-        pa_cvolume_equal(&volume, &u->sink->volume))
+        pa_cvolume_equal(&volume, &u->sink->virtual_volume))
         return;
 
-    memcpy(&u->sink->volume, &volume, sizeof(pa_cvolume));
+    memcpy(&u->sink->virtual_volume, &volume, sizeof(pa_cvolume));
 
     if (u->version >= 11)
         u->sink->muted = !!mute;
@@ -1063,7 +1068,7 @@ static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command,  uint32_t tag
     return;
 
 fail:
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
     pa_proplist_free(pl);
 }
 
@@ -1139,7 +1144,7 @@ static void source_info_cb(pa_pdispatch *pd, uint32_t command,  uint32_t tag, pa
     return;
 
 fail:
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
     pa_proplist_free(pl);
 }
 
@@ -1201,7 +1206,7 @@ static void command_subscribe_event(pa_pdispatch *pd,  uint32_t command,  uint32
     if (pa_tagstruct_getu32(t, &e) < 0 ||
         pa_tagstruct_getu32(t, &idx) < 0) {
         pa_log("Invalid protocol reply");
-        pa_module_unload_request(u->module);
+        pa_module_unload_request(u->module, TRUE);
         return;
     }
 
@@ -1341,7 +1346,7 @@ parse_error:
     pa_log("Invalid reply. (Create stream)");
 
 fail:
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
 
 }
 
@@ -1422,11 +1427,11 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
         u->maxlength = 4*1024*1024;
 
 #ifdef TUNNEL_SINK
-    u->tlength = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_TLENGTH_MSEC, &u->sink->sample_spec);
-    u->minreq = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_MINREQ_MSEC, &u->sink->sample_spec);
+    u->tlength = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_TLENGTH_MSEC, &u->sink->sample_spec);
+    u->minreq = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_MINREQ_MSEC, &u->sink->sample_spec);
     u->prebuf = u->tlength;
 #else
-    u->fragsize = pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_FRAGSIZE_MSEC, &u->source->sample_spec);
+    u->fragsize = (uint32_t) pa_usec_to_bytes(PA_USEC_PER_MSEC * DEFAULT_FRAGSIZE_MSEC, &u->source->sample_spec);
 #endif
 
 #ifdef TUNNEL_SINK
@@ -1491,6 +1496,13 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
 #endif
     }
 
+    if (u->version >= 14) {
+#ifdef TUNNEL_SINK
+        pa_tagstruct_put_boolean(reply, FALSE); /* volume_set */
+#endif
+        pa_tagstruct_put_boolean(reply, TRUE); /* early rquests */
+    }
+
     pa_pstream_send_tagstruct(u->pstream, reply);
     pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u, NULL);
 
@@ -1499,7 +1511,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
     return;
 
 fail:
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
 }
 
 /* Called from main context */
@@ -1510,7 +1522,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) {
     pa_assert(u);
 
     pa_log_warn("Stream died.");
-    pa_module_unload_request(u->module);
+    pa_module_unload_request(u->module, TRUE);
 }
 
 /* Called from main context */
@@ -1523,7 +1535,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_c
 
     if (pa_pdispatch_run(u->pdispatch, packet, creds, u) < 0) {
         pa_log("Invalid packet");
-        pa_module_unload_request(u->module);
+        pa_module_unload_request(u->module, TRUE);
         return;
     }
 }
@@ -1539,13 +1551,13 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
 
     if (channel != u->channel) {
         pa_log("Recieved memory block on bad channel.");
-        pa_module_unload_request(u->module);
+        pa_module_unload_request(u->module, TRUE);
         return;
     }
 
     pa_asyncmsgq_send(u->source->asyncmsgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_POST, PA_UINT_TO_PTR(seek), offset, chunk);
 
-    u->counter_delta += chunk->length;
+    u->counter_delta += (int64_t) chunk->length;
 }
 
 #endif
@@ -1565,7 +1577,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
 
     if (!io) {
         pa_log("Connection failed: %s", pa_cstrerror(errno));
-        pa_module_unload_request(u->module);
+        pa_module_unload_request(u->module, TRUE);
         return;
     }
 
@@ -1582,7 +1594,8 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
     pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
     pa_tagstruct_putu32(t, tag = u->ctag++);
     pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION);
-    pa_tagstruct_put_arbitrary(t, u->auth_cookie, sizeof(u->auth_cookie));
+
+    pa_tagstruct_put_arbitrary(t, pa_auth_cookie_read(u->auth_cookie, PA_NATIVE_COOKIE_LENGTH), PA_NATIVE_COOKIE_LENGTH);
 
 #ifdef HAVE_CREDS
 {
@@ -1608,7 +1621,7 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
 #ifdef TUNNEL_SINK
 
 /* Called from main context */
-static int sink_set_volume(pa_sink *sink) {
+static void sink_set_volume(pa_sink *sink) {
     struct userdata *u;
     pa_tagstruct *t;
     uint32_t tag;
@@ -1621,14 +1634,12 @@ static int sink_set_volume(pa_sink *sink) {
     pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME);
     pa_tagstruct_putu32(t, tag = u->ctag++);
     pa_tagstruct_putu32(t, u->device_index);
-    pa_tagstruct_put_cvolume(t, &sink->volume);
+    pa_tagstruct_put_cvolume(t, &sink->virtual_volume);
     pa_pstream_send_tagstruct(u->pstream, t);
-
-    return 0;
 }
 
 /* Called from main context */
-static int sink_set_mute(pa_sink *sink) {
+static void sink_set_mute(pa_sink *sink) {
     struct userdata *u;
     pa_tagstruct *t;
     uint32_t tag;
@@ -1638,7 +1649,7 @@ static int sink_set_mute(pa_sink *sink) {
     pa_assert(u);
 
     if (u->version < 11)
-        return -1;
+        return;
 
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_MUTE);
@@ -1646,39 +1657,10 @@ static int sink_set_mute(pa_sink *sink) {
     pa_tagstruct_putu32(t, u->device_index);
     pa_tagstruct_put_boolean(t, !!sink->muted);
     pa_pstream_send_tagstruct(u->pstream, t);
-
-    return 0;
 }
 
 #endif
 
-/* Called from main context */
-static int load_key(struct userdata *u, const char*fn) {
-    pa_assert(u);
-
-    u->auth_cookie_in_property = FALSE;
-
-    if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) {
-        pa_log_debug("Using already loaded auth cookie.");
-        pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
-        u->auth_cookie_in_property = 1;
-        return 0;
-    }
-
-    if (!fn)
-        fn = PA_NATIVE_COOKIE_FILE;
-
-    if (pa_authkey_load_auto(fn, u->auth_cookie, sizeof(u->auth_cookie)) < 0)
-        return -1;
-
-    pa_log_debug("Loading cookie from disk.");
-
-    if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0)
-        u->auth_cookie_in_property = TRUE;
-
-    return 0;
-}
-
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u = NULL;
@@ -1699,8 +1681,8 @@ int pa__init(pa_module*m) {
     }
 
     m->userdata = u = pa_xnew0(struct userdata, 1);
-    u->module = m;
     u->core = m->core;
+    u->module = m;
     u->client = NULL;
     u->pdispatch = NULL;
     u->pstream = NULL;
@@ -1716,7 +1698,6 @@ int pa__init(pa_module*m) {
     u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
     u->ctag = 1;
     u->device_index = u->channel = PA_INVALID_INDEX;
-    u->auth_cookie_in_property = FALSE;
     u->time_event = NULL;
     u->ignore_latency_before = 0;
     u->transport_usec = 0;
@@ -1727,7 +1708,7 @@ int pa__init(pa_module*m) {
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
-    if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
+    if (!(u->auth_cookie = pa_auth_cookie_get(u->core, pa_modargs_get_value(ma, "cookie", PA_NATIVE_COOKIE_FILE), PA_NATIVE_COOKIE_LENGTH)))
         goto fail;
 
     if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) {
@@ -1736,6 +1717,7 @@ int pa__init(pa_module*m) {
     }
 
     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");
         goto fail;
@@ -1779,7 +1761,7 @@ int pa__init(pa_module*m) {
     u->sink->set_volume = sink_set_volume;
     u->sink->set_mute = sink_set_mute;
 
-    u->sink->refresh_volume = u->sink->refresh_mute = FALSE;
+    u->sink->refresh_volume = u->sink->refresh_muted = FALSE;
 
     pa_sink_set_latency_range(u->sink, MIN_NETWORK_LATENCY_USEC, 0);
 
@@ -1812,8 +1794,8 @@ int pa__init(pa_module*m) {
     }
 
     u->source->parent.process_msg = source_process_msg;
-    u->source->userdata = u;
     u->source->set_state = source_set_state;
+    u->source->userdata = u;
 
     pa_source_set_latency_range(u->source, MIN_NETWORK_LATENCY_USEC, 0);
 
@@ -1905,8 +1887,8 @@ void pa__done(pa_module*m) {
     if (u->client)
         pa_socket_client_unref(u->client);
 
-    if (u->auth_cookie_in_property)
-        pa_authkey_prop_unref(m->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
+    if (u->auth_cookie)
+        pa_auth_cookie_unref(u->auth_cookie);
 
     if (u->smoother)
         pa_smoother_free(u->smoother);