[PATCH 3/4] stream-restore: introduce TEST_VERSION & send/receive volume_is_absolute

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Marc-Andr? Lureau <marc-andre.lureau@xxxxxxxxx>

---
 PROTOCOL                            |    4 ++-
 src/modules/module-stream-restore.c |   67 ++++++++++++++++++++++++++---------
 src/pulse/ext-stream-restore.c      |   10 ++++--
 3 files changed, 60 insertions(+), 21 deletions(-)

diff --git a/PROTOCOL b/PROTOCOL
index b14b854..5538f63 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -189,7 +189,9 @@ First version supported.
 
 ### ext-stream-restore v2, implemented by >= 0.9.16
 
-First version supported.
+new message:
+
+  SUBCOMMAND_TEST_VERSION
 
 SUBCOMMAND_WRITE, SUBCOMMAND_READ
 
diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index 6a03ad0..60cd7e1 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -71,6 +71,11 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
+struct connection_info {
+    uint32_t ext_version;
+    pa_bool_t subscribed;
+};
+
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -88,7 +93,7 @@ struct userdata {
     pa_bool_t restore_muted:1;
 
     pa_native_protocol *protocol;
-    pa_idxset *subscribed;
+    pa_hashmap *connections;
 };
 
 #define ENTRY_VERSION 3
@@ -109,7 +114,8 @@ enum {
     SUBCOMMAND_WRITE,
     SUBCOMMAND_DELETE,
     SUBCOMMAND_SUBSCRIBE,
-    SUBCOMMAND_EVENT
+    SUBCOMMAND_EVENT,
+    SUBCOMMAND_TEST_VERSION
 };
 
 static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
@@ -212,12 +218,16 @@ fail:
 
 static void trigger_save(struct userdata *u) {
     struct timeval tv;
+    void *state = NULL;
+    struct connection_info *i;
     pa_native_connection *c;
-    uint32_t idx;
 
-    for (c = pa_idxset_first(u->subscribed, &idx); c; c = pa_idxset_next(u->subscribed, &idx)) {
+    while ((i = pa_hashmap_iterate(u->connections, &state, (const void **)&c))) {
         pa_tagstruct *t;
 
+        if (!i->subscribed)
+            continue;
+
         t = pa_tagstruct_new(NULL, 0);
         pa_tagstruct_putu32(t, PA_COMMAND_EXTENSION);
         pa_tagstruct_putu32(t, 0);
@@ -598,13 +608,19 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
     struct userdata *u;
     uint32_t command;
     pa_tagstruct *reply = NULL;
+    struct connection_info *i;
 
     pa_assert(p);
     pa_assert(m);
     pa_assert(c);
     pa_assert(t);
 
-    u = m->userdata;
+    pa_assert_se(u = m->userdata);
+
+    if (!(i = pa_hashmap_get(u->connections, c))) {
+        i = pa_xnew0(struct connection_info, 1);
+        pa_hashmap_put(u->connections, c, i);
+    }
 
     if (pa_tagstruct_getu32(t, &command) < 0)
         goto fail;
@@ -618,6 +634,20 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
             if (!pa_tagstruct_eof(t))
                 goto fail;
 
+            /* If the client use SUBCOMMAND_TEST, we assume he is
+               using v1, unless we already have a version */
+            if (i->ext_version == 0)
+                i->ext_version = 1;
+
+            pa_tagstruct_putu32(reply, EXT_VERSION);
+            break;
+        }
+
+        case SUBCOMMAND_TEST_VERSION: {
+            if (pa_tagstruct_getu32(t, &i->ext_version) < 0 ||
+                !pa_tagstruct_eof(t))
+                goto fail;
+
             pa_tagstruct_putu32(reply, EXT_VERSION);
             break;
         }
@@ -648,7 +678,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
                     pa_tagstruct_put_cvolume(reply, e->volume_valid ? &e->volume : pa_cvolume_init(&r));
                     pa_tagstruct_puts(reply, e->device_valid ? e->device : NULL);
                     pa_tagstruct_put_boolean(reply, e->muted_valid ? e->muted : FALSE);
-		    if (c->version >= 16) /* FIXME: should be client side extension version */
+		    if (i->ext_version >= 2)
                         pa_tagstruct_put_boolean(reply, e->volume_is_absolute_valid ? e->volume_is_absolute : FALSE);
 
                     pa_xfree(e);
@@ -695,14 +725,12 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
                     pa_tagstruct_get_boolean(t, &muted) < 0)
                     goto fail;
 
-                if (c->version >= 16) {
+                if (i->ext_version >= 2) {
                     if (pa_tagstruct_get_boolean(t, &volume_is_absolute) < 0)
                         goto fail;
 
                     entry.volume_is_absolute = volume_is_absolute;
                     entry.volume_is_absolute_valid = TRUE;
-
-                    goto fail;
                 }
 
                 if (!name || !*name)
@@ -768,10 +796,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
                 !pa_tagstruct_eof(t))
                 goto fail;
 
-            if (enabled)
-                pa_idxset_put(u->subscribed, c, NULL);
-            else
-                pa_idxset_remove_by_data(u->subscribed, c, NULL);
+            i->subscribed = enabled;
 
             break;
         }
@@ -792,11 +817,15 @@ fail:
 }
 
 static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_native_connection *c, struct userdata *u) {
+    struct connection_info *i;
+
     pa_assert(p);
     pa_assert(c);
     pa_assert(u);
 
-    pa_idxset_remove_by_data(u->subscribed, c, NULL);
+    i = pa_hashmap_remove(u->connections, c);
+    pa_xfree(i);
+
     return PA_HOOK_OK;
 }
 
@@ -835,7 +864,7 @@ int pa__init(pa_module*m) {
     u->restore_volume = restore_volume;
     u->restore_muted = restore_muted;
     u->gdbm_file = NULL;
-    u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+    u->connections = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 
     u->protocol = pa_native_protocol_get(m->core);
     pa_native_protocol_install_ext(u->protocol, m, extension_cb);
@@ -894,6 +923,10 @@ fail:
     return  -1;
 }
 
+static void free_connection_info(void *p, void *userdata) {
+    pa_xfree(p);
+}
+
 void pa__done(pa_module*m) {
     struct userdata* u;
 
@@ -926,8 +959,8 @@ void pa__done(pa_module*m) {
         pa_native_protocol_unref(u->protocol);
     }
 
-    if (u->subscribed)
-        pa_idxset_free(u->subscribed, NULL, NULL);
+    if (u->connections)
+        pa_hashmap_free(u->connections, free_connection_info, NULL);
 
     pa_xfree(u);
 }
diff --git a/src/pulse/ext-stream-restore.c b/src/pulse/ext-stream-restore.c
index dde7222..bcef315 100644
--- a/src/pulse/ext-stream-restore.c
+++ b/src/pulse/ext-stream-restore.c
@@ -35,13 +35,16 @@
 
 #include "ext-stream-restore.h"
 
+#define EXT_VERSION 2
+
 enum {
-    SUBCOMMAND_TEST,
+    SUBCOMMAND_TEST, /* deprecated since v2, use SUBCOMMAND_TEST_VERSION instead */
     SUBCOMMAND_READ,
     SUBCOMMAND_WRITE,
     SUBCOMMAND_DELETE,
     SUBCOMMAND_SUBSCRIBE,
-    SUBCOMMAND_EVENT
+    SUBCOMMAND_EVENT,
+    SUBCOMMAND_TEST_VERSION
 };
 
 static void ext_stream_restore_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
@@ -96,7 +99,8 @@ pa_operation *pa_ext_stream_restore_test(
     t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
     pa_tagstruct_putu32(t, PA_INVALID_INDEX);
     pa_tagstruct_puts(t, "module-stream-restore");
-    pa_tagstruct_putu32(t, SUBCOMMAND_TEST);
+    pa_tagstruct_putu32(t, SUBCOMMAND_TEST_VERSION);
+    pa_tagstruct_putu32(t, EXT_VERSION);
     pa_pstream_send_tagstruct(c->pstream, t);
     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_stream_restore_test_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
-- 
1.6.2.4




[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux