]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/protocol-esound.c
core: memory leak, fix ref counting when moving streams
[pulseaudio] / src / pulsecore / protocol-esound.c
index ddecb8fef5fd72fb3793e4c76b5ec5e98917276f..a024471c690245d296701609b867a60a17b0957d 100644 (file)
@@ -6,7 +6,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
-  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
@@ -170,6 +170,7 @@ static int esd_proto_sample_cache(connection *c, esd_proto_t request, const void
 static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, const void *data, size_t length);
 static int esd_proto_sample_get_id(connection *c, esd_proto_t request, const void *data, size_t length);
 static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const void *data, size_t length);
+static int esd_proto_standby_mode(connection *c, esd_proto_t request, const void *data, size_t length);
 
 /* the big map of protocol handler info */
 static struct proto_handler proto_map[ESD_PROTO_MAX] = {
@@ -188,8 +189,8 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = {
     { sizeof(int),                    NULL, "sample stop" },
     { (size_t) -1,                    NULL, "TODO: sample kill" },
 
-    { ESD_KEY_LEN + sizeof(int),      esd_proto_standby_or_resume, "standby" },  /* NOOP! */
-    { ESD_KEY_LEN + sizeof(int),      esd_proto_standby_or_resume, "resume" },   /* NOOP! */         /* 13 */
+    { ESD_KEY_LEN + sizeof(int),      esd_proto_standby_or_resume, "standby" },
+    { ESD_KEY_LEN + sizeof(int),      esd_proto_standby_or_resume, "resume" },                       /* 13 */
 
     { ESD_NAME_MAX,                   esd_proto_sample_get_id, "sample getid" },                     /* 14 */
     { ESD_NAME_MAX + 2 * sizeof(int), NULL, "stream filter" },
@@ -202,7 +203,7 @@ static struct proto_handler proto_map[ESD_PROTO_MAX] = {
     { 3 * sizeof(int),                esd_proto_stream_pan, "stream pan"},
     { 3 * sizeof(int),                esd_proto_sample_pan, "sample pan" },
 
-    { sizeof(int),                    NULL, "standby mode" },
+    { sizeof(int),                    esd_proto_standby_mode, "standby mode" },
     { 0,                              esd_proto_get_latency, "get latency" }
 };
 
@@ -561,19 +562,20 @@ static int esd_proto_get_latency(connection *c, esd_proto_t request, const void
     pa_sink *sink;
     int32_t latency;
 
-    connection_ref(c);
+    connection_assert_ref(c);
     pa_assert(!data);
     pa_assert(length == 0);
 
     if (!(sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK)))
         latency = 0;
     else {
-        double usec = (double) pa_sink_get_latency(sink);
+        double usec = (double) pa_sink_get_requested_latency(sink);
         latency = (int) ((usec*44100)/1000000);
     }
 
     latency = PA_MAYBE_INT32_SWAP(c->swap_byte_order, latency);
     connection_write(c, &latency, sizeof(int32_t));
+
     return 0;
 }
 
@@ -582,7 +584,7 @@ static int esd_proto_server_info(connection *c, esd_proto_t request, const void
     int32_t response;
     pa_sink *sink;
 
-    connection_ref(c);
+    connection_assert_ref(c);
     pa_assert(data);
     pa_assert(length == sizeof(int32_t));
 
@@ -610,7 +612,7 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da
     unsigned nsamples;
     char terminator[sizeof(int32_t)*6+ESD_NAME_MAX];
 
-    connection_ref(c);
+    connection_assert_ref(c);
     pa_assert(data);
     pa_assert(length == sizeof(int32_t));
 
@@ -639,7 +641,7 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da
             pa_cvolume volume = *pa_sink_input_get_volume(conn->sink_input);
             rate = (int32_t) conn->sink_input->sample_spec.rate;
             lvolume = (int32_t) ((volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
-            rvolume = (int32_t) ((volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
+            rvolume = (int32_t) ((volume.values[volume.channels == 2 ? 1 : 0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
             format = format_native2esd(&conn->sink_input->sample_spec);
         }
 
@@ -774,7 +776,8 @@ static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void *
         pa_cvolume volume;
         volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
         volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
-        volume.channels = 2;
+        volume.channels = conn->sink_input->sample_spec.channels;
+
         pa_sink_input_set_volume(conn->sink_input, &volume, TRUE);
         ok = 1;
     } else
@@ -935,19 +938,47 @@ static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, con
 }
 
 static int esd_proto_standby_or_resume(connection *c, esd_proto_t request, const void *data, size_t length) {
-    int32_t ok;
+    int32_t ok = 1;
 
     connection_assert_ref(c);
 
     connection_write_prepare(c, sizeof(int32_t) * 2);
-
-    ok = 1;
     connection_write(c, &ok, sizeof(int32_t));
+
+    if (request == ESD_PROTO_STANDBY)
+        ok = pa_sink_suspend_all(c->protocol->core, TRUE) >= 0;
+    else {
+        pa_assert(request == ESD_PROTO_RESUME);
+        ok = pa_sink_suspend_all(c->protocol->core, FALSE) >= 0;
+    }
+
     connection_write(c, &ok, sizeof(int32_t));
 
     return 0;
 }
 
+static int esd_proto_standby_mode(connection *c, esd_proto_t request, const void *data, size_t length) {
+    int32_t mode;
+    pa_sink *sink, *source;
+
+    connection_assert_ref(c);
+
+    mode = ESM_RUNNING;
+
+    if ((sink = pa_namereg_get(c->protocol->core, c->options->default_sink, PA_NAMEREG_SINK)))
+        if (pa_sink_get_state(sink) == PA_SINK_SUSPENDED)
+            mode = ESM_ON_STANDBY;
+
+    if ((source = pa_namereg_get(c->protocol->core, c->options->default_source, PA_NAMEREG_SOURCE)))
+        if (pa_source_get_state(source) == PA_SOURCE_SUSPENDED)
+            mode = ESM_ON_STANDBY;
+
+    mode = PA_MAYBE_INT32_SWAP(c->swap_byte_order, mode);
+
+    connection_write(c, &mode, sizeof(mode));
+    return 0;
+}
+
 /*** client callbacks ***/
 
 static void client_kill_cb(pa_client *c) {
@@ -1075,8 +1106,7 @@ static int do_read(connection *c) {
             pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, c->client->proplist, &idx);
 
             pa_memblock_unref(c->scache.memchunk.memblock);
-            c->scache.memchunk.memblock = NULL;
-            c->scache.memchunk.index = c->scache.memchunk.length = 0;
+            pa_memchunk_reset(&c->scache.memchunk);
 
             pa_xfree(c->scache.name);
             c->scache.name = NULL;
@@ -1260,6 +1290,9 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int6
     connection *c = CONNECTION(o);
     connection_assert_ref(c);
 
+    if (!c->protocol)
+        return -1;
+
     switch (code) {
         case CONNECTION_MESSAGE_REQUEST_DATA:
             do_work(c);