From 37e82cec0ad13923a5db259a88bd00a2840112c6 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sat, 27 Jun 2009 22:08:07 +0100 Subject: device-manager: Add an untested protocol extension. This is effectively copied from the stream restore extension. --- src/pulse/ext-device-manager.c | 358 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 src/pulse/ext-device-manager.c (limited to 'src/pulse/ext-device-manager.c') diff --git a/src/pulse/ext-device-manager.c b/src/pulse/ext-device-manager.c new file mode 100644 index 00000000..1c6eee5e --- /dev/null +++ b/src/pulse/ext-device-manager.c @@ -0,0 +1,358 @@ +/*** + This file is part of PulseAudio. + + Copyright 2008 Lennart Poettering + Copyright 2009 Colin Guthrie + + 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.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include +#include + +#include "internal.h" +#include "operation.h" +#include "fork-detect.h" + +#include "ext-device-manager.h" + +enum { + SUBCOMMAND_TEST, + SUBCOMMAND_READ, + SUBCOMMAND_WRITE, + SUBCOMMAND_DELETE, + SUBCOMMAND_SUBSCRIBE, + SUBCOMMAND_EVENT +}; + +static void ext_device_manager_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + uint32_t version = PA_INVALID_INDEX; + + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + + if (!o->context) + goto finish; + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t, FALSE) < 0) + goto finish; + + } else if (pa_tagstruct_getu32(t, &version) < 0 || + !pa_tagstruct_eof(t)) { + + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + + if (o->callback) { + pa_ext_device_manager_test_cb_t cb = (pa_ext_device_manager_test_cb_t) o->callback; + cb(o->context, version, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +pa_operation *pa_ext_device_manager_test( + pa_context *c, + pa_ext_device_manager_test_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o; + pa_tagstruct *t; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_TEST); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_manager_test_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +static void ext_device_manager_read_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + int eol = 1; + + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + + if (!o->context) + goto finish; + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t, FALSE) < 0) + goto finish; + + eol = -1; + } else { + + while (!pa_tagstruct_eof(t)) { + pa_ext_device_manager_info i; + + memset(&i, 0, sizeof(i)); + + if (pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.description) < 0) { + + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + + if (o->callback) { + pa_ext_device_manager_read_cb_t cb = (pa_ext_device_manager_read_cb_t) o->callback; + cb(o->context, &i, 0, o->userdata); + } + } + } + + if (o->callback) { + pa_ext_device_manager_read_cb_t cb = (pa_ext_device_manager_read_cb_t) o->callback; + cb(o->context, NULL, eol, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +pa_operation *pa_ext_device_manager_read( + pa_context *c, + pa_ext_device_manager_read_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o; + pa_tagstruct *t; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_READ); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_device_manager_read_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation *pa_ext_device_manager_write( + pa_context *c, + pa_update_mode_t mode, + const pa_ext_device_manager_info data[], + unsigned n, + int apply_immediately, + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o = NULL; + pa_tagstruct *t = NULL; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE || mode == PA_UPDATE_SET); + pa_assert(data); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_WRITE); + + pa_tagstruct_putu32(t, mode); + pa_tagstruct_put_boolean(t, apply_immediately); + + for (; n > 0; n--, data++) { + if (!data->name || !*data->name) + goto fail; + + pa_tagstruct_puts(t, data->name); + pa_tagstruct_puts(t, data->description); + } + + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; + +fail: + if (o) { + pa_operation_cancel(o); + pa_operation_unref(o); + } + + if (t) + pa_tagstruct_free(t); + + pa_context_set_error(c, PA_ERR_INVALID); + return NULL; +} + +pa_operation *pa_ext_device_manager_delete( + pa_context *c, + const char *const s[], + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o = NULL; + pa_tagstruct *t = NULL; + const char *const *k; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(s); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_DELETE); + + for (k = s; *k; k++) { + if (!*k || !**k) + goto fail; + + pa_tagstruct_puts(t, *k); + } + + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; + +fail: + if (o) { + pa_operation_cancel(o); + pa_operation_unref(o); + } + + if (t) + pa_tagstruct_free(t); + + pa_context_set_error(c, PA_ERR_INVALID); + return NULL; +} + +pa_operation *pa_ext_device_manager_subscribe( + pa_context *c, + int enable, + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o; + pa_tagstruct *t; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE); + pa_tagstruct_put_boolean(t, enable); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +void pa_ext_device_manager_set_subscribe_cb( + pa_context *c, + pa_ext_device_manager_subscribe_cb_t cb, + void *userdata) { + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + if (pa_detect_fork()) + return; + + c->ext_device_manager.callback = cb; + c->ext_device_manager.userdata = userdata; +} + +void pa_ext_device_manager_command(pa_context *c, uint32_t tag, pa_tagstruct *t) { + uint32_t subcommand; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(t); + + if (pa_tagstruct_getu32(t, &subcommand) < 0 || + !pa_tagstruct_eof(t)) { + + pa_context_fail(c, PA_ERR_PROTOCOL); + return; + } + + if (subcommand != SUBCOMMAND_EVENT) { + pa_context_fail(c, PA_ERR_PROTOCOL); + return; + } + + if (c->ext_device_manager.callback) + c->ext_device_manager.callback(c, c->ext_device_manager.userdata); +} -- cgit From 103897a1e33fe83f6ba0b7d521ccc2e36da43881 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sat, 19 Sep 2009 16:13:25 +0100 Subject: device-manager: Provide a way for clients to enable/disable role-based device-priority routing. The routing logic itself does not yet exist, but the command currently will unload/load module-stream-restore as approriate. (module-stream-restore would conflict with the role-based priority-routing). --- src/pulse/ext-device-manager.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src/pulse/ext-device-manager.c') diff --git a/src/pulse/ext-device-manager.c b/src/pulse/ext-device-manager.c index 1c6eee5e..0603a89a 100644 --- a/src/pulse/ext-device-manager.c +++ b/src/pulse/ext-device-manager.c @@ -41,6 +41,7 @@ enum { SUBCOMMAND_READ, SUBCOMMAND_WRITE, SUBCOMMAND_DELETE, + SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING, SUBCOMMAND_SUBSCRIBE, SUBCOMMAND_EVENT }; @@ -289,6 +290,37 @@ fail: return NULL; } +pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( + pa_context *c, + int enable, + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o = NULL; + pa_tagstruct *t = NULL; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING); + pa_tagstruct_put_boolean(t, !!enable); + + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + pa_operation *pa_ext_device_manager_subscribe( pa_context *c, int enable, -- cgit From aebe4787f293cc6810c54db751bee7df3a5d1ea2 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sat, 19 Sep 2009 17:48:10 +0100 Subject: device-manager: Provide a method for prefering/defering a device. This allows clients to edit the priroity order. What is not yet in place is the initialisation of that priority list when new devices are detected or the cleaning (remove holes) when devices are removed. In order to keep the storage transparent I will likely remove the write functionality and replace it with a simple rename method. I also still need to expose the priority itself when reading the data. --- src/pulse/ext-device-manager.c | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'src/pulse/ext-device-manager.c') diff --git a/src/pulse/ext-device-manager.c b/src/pulse/ext-device-manager.c index 0603a89a..a634e212 100644 --- a/src/pulse/ext-device-manager.c +++ b/src/pulse/ext-device-manager.c @@ -42,6 +42,8 @@ enum { SUBCOMMAND_WRITE, SUBCOMMAND_DELETE, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING, + SUBCOMMAND_PREFER_DEVICE, + SUBCOMMAND_DEFER_DEVICE, SUBCOMMAND_SUBSCRIBE, SUBCOMMAND_EVENT }; @@ -321,6 +323,78 @@ pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( return o; } +pa_operation *pa_ext_device_manager_prefer_device( + pa_context *c, + const char* role, + const char* device, + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o = NULL; + pa_tagstruct *t = NULL; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + pa_assert(role); + pa_assert(device); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_PREFER_DEVICE); + pa_tagstruct_puts(t, role); + pa_tagstruct_puts(t, device); + + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation *pa_ext_device_manager_defer_device( + pa_context *c, + const char* role, + const char* device, + pa_context_success_cb_t cb, + void *userdata) { + + uint32_t tag; + pa_operation *o = NULL; + pa_tagstruct *t = NULL; + + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); + + pa_assert(role); + pa_assert(device); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); + pa_tagstruct_putu32(t, PA_INVALID_INDEX); + pa_tagstruct_puts(t, "module-device-manager"); + pa_tagstruct_putu32(t, SUBCOMMAND_DEFER_DEVICE); + pa_tagstruct_puts(t, role); + pa_tagstruct_puts(t, device); + + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + pa_operation *pa_ext_device_manager_subscribe( pa_context *c, int enable, -- cgit From f8ec8f382ff1e9a05296b5a656195d44e8d05b44 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sun, 20 Sep 2009 12:44:02 +0100 Subject: device-manager: Change the write function to a rename function. The structure itself will contain various bits of info so exposing this fully to the client is a bad idea. By keeping to a rename operation we keep what we do store abstracted from the clients. Also fix some doxy comments. --- src/pulse/ext-device-manager.c | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) (limited to 'src/pulse/ext-device-manager.c') diff --git a/src/pulse/ext-device-manager.c b/src/pulse/ext-device-manager.c index a634e212..bc6301ca 100644 --- a/src/pulse/ext-device-manager.c +++ b/src/pulse/ext-device-manager.c @@ -39,7 +39,7 @@ enum { SUBCOMMAND_TEST, SUBCOMMAND_READ, - SUBCOMMAND_WRITE, + SUBCOMMAND_RENAME, SUBCOMMAND_DELETE, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING, SUBCOMMAND_PREFER_DEVICE, @@ -183,12 +183,10 @@ pa_operation *pa_ext_device_manager_read( return o; } -pa_operation *pa_ext_device_manager_write( +pa_operation *pa_ext_device_manager_set_device_description( pa_context *c, - pa_update_mode_t mode, - const pa_ext_device_manager_info data[], - unsigned n, - int apply_immediately, + const char* device, + const char* description, pa_context_success_cb_t cb, void *userdata) { @@ -198,8 +196,8 @@ pa_operation *pa_ext_device_manager_write( pa_assert(c); pa_assert(PA_REFCNT_VALUE(c) >= 1); - pa_assert(mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE || mode == PA_UPDATE_SET); - pa_assert(data); + pa_assert(device); + pa_assert(description); PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -210,35 +208,15 @@ pa_operation *pa_ext_device_manager_write( t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, "module-device-manager"); - pa_tagstruct_putu32(t, SUBCOMMAND_WRITE); - - pa_tagstruct_putu32(t, mode); - pa_tagstruct_put_boolean(t, apply_immediately); - - for (; n > 0; n--, data++) { - if (!data->name || !*data->name) - goto fail; + pa_tagstruct_putu32(t, SUBCOMMAND_RENAME); - pa_tagstruct_puts(t, data->name); - pa_tagstruct_puts(t, data->description); - } + pa_tagstruct_puts(t, device); + pa_tagstruct_puts(t, description); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); return o; - -fail: - if (o) { - pa_operation_cancel(o); - pa_operation_unref(o); - } - - if (t) - pa_tagstruct_free(t); - - pa_context_set_error(c, PA_ERR_INVALID); - return NULL; } pa_operation *pa_ext_device_manager_delete( -- cgit From 8b2cc4def30327a72d95365c671d2adcae1a77a8 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sat, 26 Sep 2009 14:36:36 +0100 Subject: device-manager: Expose the priority lists in the protocol extension. Also leave space for 'icon' and 'available' details too, althought currently this info is dummy. --- src/pulse/ext-device-manager.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'src/pulse/ext-device-manager.c') diff --git a/src/pulse/ext-device-manager.c b/src/pulse/ext-device-manager.c index bc6301ca..01e4594b 100644 --- a/src/pulse/ext-device-manager.c +++ b/src/pulse/ext-device-manager.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -128,20 +129,48 @@ static void ext_device_manager_read_cb(pa_pdispatch *pd, uint32_t command, uint3 while (!pa_tagstruct_eof(t)) { pa_ext_device_manager_info i; + pa_bool_t available; memset(&i, 0, sizeof(i)); + available = FALSE; if (pa_tagstruct_gets(t, &i.name) < 0 || - pa_tagstruct_gets(t, &i.description) < 0) { + pa_tagstruct_gets(t, &i.description) < 0 || + pa_tagstruct_gets(t, &i.icon) < 0 || + pa_tagstruct_get_boolean(t, &available) < 0 || + pa_tagstruct_getu32(t, &i.n_role_priorities) < 0) { pa_context_fail(o->context, PA_ERR_PROTOCOL); goto finish; } + i.available = (uint8_t)available; + + if (i.n_role_priorities > 0) { + uint32_t j; + i.role_priorities = pa_xnew0(pa_ext_device_manager_role_priority_info, i.n_role_priorities+1); + + for (j = 0; j < i.n_role_priorities; j++) { + + if (pa_tagstruct_gets(t, &i.role_priorities[j].role) < 0 || + pa_tagstruct_getu32(t, &i.role_priorities[j].priority) < 0) { + + pa_context_fail(o->context, PA_ERR_PROTOCOL); + pa_xfree(i.role_priorities); + goto finish; + } + } + + /* Terminate with an extra NULL entry, just to make sure */ + i.role_priorities[j].role = NULL; + i.role_priorities[j].priority = 0; + } if (o->callback) { pa_ext_device_manager_read_cb_t cb = (pa_ext_device_manager_read_cb_t) o->callback; cb(o->context, &i, 0, o->userdata); } + + pa_xfree(i.role_priorities); } } -- cgit From f9b2d6500b75445b66c83ad1d6700e042f2f8d2a Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Thu, 1 Oct 2009 01:27:02 +0100 Subject: device-manager: Change the prefer/defer options to a single 'reorder' command. We put in the devices from the wire into a hashmap and then add all like type device in the database and then order them based on priority (with the ones specified on the wire always being in that order at the top of the list. --- src/pulse/ext-device-manager.c | 53 +++++++++--------------------------------- 1 file changed, 11 insertions(+), 42 deletions(-) (limited to 'src/pulse/ext-device-manager.c') diff --git a/src/pulse/ext-device-manager.c b/src/pulse/ext-device-manager.c index 01e4594b..138ed838 100644 --- a/src/pulse/ext-device-manager.c +++ b/src/pulse/ext-device-manager.c @@ -43,8 +43,7 @@ enum { SUBCOMMAND_RENAME, SUBCOMMAND_DELETE, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING, - SUBCOMMAND_PREFER_DEVICE, - SUBCOMMAND_DEFER_DEVICE, + SUBCOMMAND_REORDER, SUBCOMMAND_SUBSCRIBE, SUBCOMMAND_EVENT }; @@ -330,14 +329,14 @@ pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( return o; } -pa_operation *pa_ext_device_manager_prefer_device( +pa_operation *pa_ext_device_manager_reorder_devices_for_role( pa_context *c, const char* role, - const char* device, + const char** devices, pa_context_success_cb_t cb, void *userdata) { - uint32_t tag; + uint32_t tag, i; pa_operation *o = NULL; pa_tagstruct *t = NULL; @@ -349,52 +348,22 @@ pa_operation *pa_ext_device_manager_prefer_device( PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); pa_assert(role); - pa_assert(device); + pa_assert(devices); o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); pa_tagstruct_putu32(t, PA_INVALID_INDEX); pa_tagstruct_puts(t, "module-device-manager"); - pa_tagstruct_putu32(t, SUBCOMMAND_PREFER_DEVICE); + pa_tagstruct_putu32(t, SUBCOMMAND_REORDER); pa_tagstruct_puts(t, role); - pa_tagstruct_puts(t, device); - - pa_pstream_send_tagstruct(c->pstream, t); - pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); - - return o; -} - -pa_operation *pa_ext_device_manager_defer_device( - pa_context *c, - const char* role, - const char* device, - pa_context_success_cb_t cb, - void *userdata) { - - uint32_t tag; - pa_operation *o = NULL; - pa_tagstruct *t = NULL; - - pa_assert(c); - pa_assert(PA_REFCNT_VALUE(c) >= 1); - - PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED); - PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); - PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED); - pa_assert(role); - pa_assert(device); + i = 0; while (devices[i]) i++; + pa_tagstruct_putu32(t, i); - o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); - - t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag); - pa_tagstruct_putu32(t, PA_INVALID_INDEX); - pa_tagstruct_puts(t, "module-device-manager"); - pa_tagstruct_putu32(t, SUBCOMMAND_DEFER_DEVICE); - pa_tagstruct_puts(t, role); - pa_tagstruct_puts(t, device); + i = 0; + while (devices[i]) + pa_tagstruct_puts(t, devices[i++]); pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); -- cgit