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/context.c | 5 + src/pulse/ext-device-manager.c | 358 +++++++++++++++++++++++++++++++++++++++++ src/pulse/ext-device-manager.h | 106 ++++++++++++ src/pulse/internal.h | 6 + 4 files changed, 475 insertions(+) create mode 100644 src/pulse/ext-device-manager.c create mode 100644 src/pulse/ext-device-manager.h (limited to 'src/pulse') diff --git a/src/pulse/context.c b/src/pulse/context.c index 23ae30ce..7468d0a9 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -128,6 +128,9 @@ static void reset_callbacks(pa_context *c) { c->event_callback = NULL; c->event_userdata = NULL; + c->ext_device_manager.callback = NULL; + c->ext_device_manager.userdata = NULL; + c->ext_stream_restore.callback = NULL; c->ext_stream_restore.userdata = NULL; } @@ -1434,6 +1437,8 @@ void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t if (!strcmp(name, "module-stream-restore")) pa_ext_stream_restore_command(c, tag, t); + else if (!strcmp(name, "module-device-manager")) + pa_ext_device_manager_command(c, tag, t); else pa_log(_("Received message for unknown extension '%s'"), name); 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); +} diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h new file mode 100644 index 00000000..eed0c50c --- /dev/null +++ b/src/pulse/ext-device-manager.h @@ -0,0 +1,106 @@ +#ifndef foopulseextdevicemanagerhfoo +#define foopulseextdevicemanagerhfoo + +/*** + 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. +***/ + +#include +#include + +/** \file + * + * Routines for controlling module-stream-restore + */ + +PA_C_DECL_BEGIN + +/** Stores information about one device in the device database that is + * maintained by module-device-manager. \since 0.9.17 */ +typedef struct pa_ext_device_manager_info { + const char *name; /**< Identifier string of the device. A string like "sink:" or similar followed by the name of the device. */ + const char *description; /**< The description of the device when it was last seen, if applicable and saved */ +} pa_ext_device_manager_info; + +/** Callback prototype for pa_ext_device_manager_test(). \since 0.9.17 */ +typedef void (*pa_ext_device_manager_test_cb_t)( + pa_context *c, + uint32_t version, + void *userdata); + +/** Test if this extension module is available in the server. \since 0.9.17 */ +pa_operation *pa_ext_device_manager_test( + pa_context *c, + pa_ext_device_manager_test_cb_t cb, + void *userdata); + +/** Callback prototype for pa_ext_device_manager_read(). \since 0.9.17 */ +typedef void (*pa_ext_device_manager_read_cb_t)( + pa_context *c, + const pa_ext_device_manager_info *info, + int eol, + void *userdata); + +/** Read all entries from the device database. \since 0.9.17 */ +pa_operation *pa_ext_device_manager_read( + pa_context *c, + pa_ext_device_manager_read_cb_t cb, + void *userdata); + +/** Store entries in the device database. \since 0.9.17 */ +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); + +/** Delete entries from the device database. \since 0.9.17 */ +pa_operation *pa_ext_device_manager_delete( + pa_context *c, + const char *const s[], + pa_context_success_cb_t cb, + void *userdata); + +/** Subscribe to changes in the device database. \since 0.9.17 */ +pa_operation *pa_ext_device_manager_subscribe( + pa_context *c, + int enable, + pa_context_success_cb_t cb, + void *userdata); + +/** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.17 */ +typedef void (*pa_ext_device_manager_subscribe_cb_t)( + pa_context *c, + void *userdata); + +/** Set the subscription callback that is called when + * pa_ext_device_manager_subscribe() was called. \since 0.9.17 */ +void pa_ext_device_manager_set_subscribe_cb( + pa_context *c, + pa_ext_device_manager_subscribe_cb_t cb, + void *userdata); + +PA_C_DECL_END + +#endif diff --git a/src/pulse/internal.h b/src/pulse/internal.h index e069c9e9..b371bfc2 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,10 @@ struct pa_context { uint32_t client_index; /* Extension specific data */ + struct { + pa_ext_device_manager_subscribe_cb_t callback; + void *userdata; + } ext_device_manager; struct { pa_ext_stream_restore_subscribe_cb_t callback; void *userdata; @@ -283,6 +288,7 @@ pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *ta #define PA_FAIL_RETURN_NULL(context, error) \ PA_FAIL_RETURN_ANY(context, error, NULL) +void pa_ext_device_manager_command(pa_context *c, uint32_t tag, pa_tagstruct *t); void pa_ext_stream_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t); pa_bool_t pa_mainloop_is_our_api(pa_mainloop_api*m); -- cgit From 464e1a89868b7c68927d7c95b4ff7d8fe3dbb0f0 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sun, 5 Jul 2009 19:40:06 +0100 Subject: device-manager: Fix copy+paste leftover --- src/pulse/ext-device-manager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pulse') diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h index eed0c50c..422691fe 100644 --- a/src/pulse/ext-device-manager.h +++ b/src/pulse/ext-device-manager.h @@ -28,7 +28,7 @@ /** \file * - * Routines for controlling module-stream-restore + * Routines for controlling module-device-manager */ PA_C_DECL_BEGIN -- cgit From 9357bdf4e7c069e29d2fa403a01a892d80d2d89f Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Sat, 19 Sep 2009 15:32:13 +0100 Subject: device-manager: Update docs version -> 0.9.19 (predicted) --- src/pulse/ext-device-manager.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/pulse') diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h index 422691fe..33bcbfa8 100644 --- a/src/pulse/ext-device-manager.h +++ b/src/pulse/ext-device-manager.h @@ -34,38 +34,38 @@ PA_C_DECL_BEGIN /** Stores information about one device in the device database that is - * maintained by module-device-manager. \since 0.9.17 */ + * maintained by module-device-manager. \since 0.9.19 */ typedef struct pa_ext_device_manager_info { const char *name; /**< Identifier string of the device. A string like "sink:" or similar followed by the name of the device. */ const char *description; /**< The description of the device when it was last seen, if applicable and saved */ } pa_ext_device_manager_info; -/** Callback prototype for pa_ext_device_manager_test(). \since 0.9.17 */ +/** Callback prototype for pa_ext_device_manager_test(). \since 0.9.19 */ typedef void (*pa_ext_device_manager_test_cb_t)( pa_context *c, uint32_t version, void *userdata); -/** Test if this extension module is available in the server. \since 0.9.17 */ +/** Test if this extension module is available in the server. \since 0.9.19 */ pa_operation *pa_ext_device_manager_test( pa_context *c, pa_ext_device_manager_test_cb_t cb, void *userdata); -/** Callback prototype for pa_ext_device_manager_read(). \since 0.9.17 */ +/** Callback prototype for pa_ext_device_manager_read(). \since 0.9.19 */ typedef void (*pa_ext_device_manager_read_cb_t)( pa_context *c, const pa_ext_device_manager_info *info, int eol, void *userdata); -/** Read all entries from the device database. \since 0.9.17 */ +/** Read all entries from the device database. \since 0.9.19 */ pa_operation *pa_ext_device_manager_read( pa_context *c, pa_ext_device_manager_read_cb_t cb, void *userdata); -/** Store entries in the device database. \since 0.9.17 */ +/** Store entries in the device database. \since 0.9.19 */ pa_operation *pa_ext_device_manager_write( pa_context *c, pa_update_mode_t mode, @@ -75,27 +75,27 @@ pa_operation *pa_ext_device_manager_write( pa_context_success_cb_t cb, void *userdata); -/** Delete entries from the device database. \since 0.9.17 */ +/** Delete entries from the device database. \since 0.9.19 */ pa_operation *pa_ext_device_manager_delete( pa_context *c, const char *const s[], pa_context_success_cb_t cb, void *userdata); -/** Subscribe to changes in the device database. \since 0.9.17 */ +/** Subscribe to changes in the device database. \since 0.9.19 */ pa_operation *pa_ext_device_manager_subscribe( pa_context *c, int enable, pa_context_success_cb_t cb, void *userdata); -/** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.17 */ +/** Callback prototype for pa_ext_device_manager_set_subscribe_cb(). \since 0.9.19 */ typedef void (*pa_ext_device_manager_subscribe_cb_t)( pa_context *c, void *userdata); /** Set the subscription callback that is called when - * pa_ext_device_manager_subscribe() was called. \since 0.9.17 */ + * pa_ext_device_manager_subscribe() was called. \since 0.9.19 */ void pa_ext_device_manager_set_subscribe_cb( pa_context *c, pa_ext_device_manager_subscribe_cb_t cb, -- 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 ++++++++++++++++++++++++++++++++ src/pulse/ext-device-manager.h | 7 +++++++ 2 files changed, 39 insertions(+) (limited to 'src/pulse') 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, diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h index 33bcbfa8..29d56ba4 100644 --- a/src/pulse/ext-device-manager.h +++ b/src/pulse/ext-device-manager.h @@ -82,6 +82,13 @@ pa_operation *pa_ext_device_manager_delete( pa_context_success_cb_t cb, void *userdata); +/** Subscribe to changes in the device database. \since 0.9.19 */ +pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( + pa_context *c, + int enable, + pa_context_success_cb_t cb, + void *userdata); + /** Subscribe to changes in the device database. \since 0.9.19 */ pa_operation *pa_ext_device_manager_subscribe( pa_context *c, -- 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 ++++++++++++++++++++++++++++++++++++++++++ src/pulse/ext-device-manager.h | 16 +++++++++ 2 files changed, 90 insertions(+) (limited to 'src/pulse') 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, diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h index 29d56ba4..d6de1320 100644 --- a/src/pulse/ext-device-manager.h +++ b/src/pulse/ext-device-manager.h @@ -89,6 +89,22 @@ pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( pa_context_success_cb_t cb, void *userdata); +/** Subscribe to changes in the device database. \since 0.9.19 */ +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); + +/** Subscribe to changes in the device database. \since 0.9.19 */ +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); + /** Subscribe to changes in the device database. \since 0.9.19 */ pa_operation *pa_ext_device_manager_subscribe( pa_context *c, -- 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 +++++++++------------------------------- src/pulse/ext-device-manager.h | 16 +++++++--------- 2 files changed, 16 insertions(+), 40 deletions(-) (limited to 'src/pulse') 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( diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h index d6de1320..686c8d22 100644 --- a/src/pulse/ext-device-manager.h +++ b/src/pulse/ext-device-manager.h @@ -65,13 +65,11 @@ pa_operation *pa_ext_device_manager_read( pa_ext_device_manager_read_cb_t cb, void *userdata); -/** Store entries in the device database. \since 0.9.19 */ -pa_operation *pa_ext_device_manager_write( +/** Sets the description for a device. \since 0.9.19 */ +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); @@ -82,14 +80,14 @@ pa_operation *pa_ext_device_manager_delete( pa_context_success_cb_t cb, void *userdata); -/** Subscribe to changes in the device database. \since 0.9.19 */ +/** Enable the role-based device-priority routing mode. \since 0.9.19 */ pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( pa_context *c, int enable, pa_context_success_cb_t cb, void *userdata); -/** Subscribe to changes in the device database. \since 0.9.19 */ +/** Prefer a given device in the priority list. \since 0.9.19 */ pa_operation *pa_ext_device_manager_prefer_device( pa_context *c, const char* role, @@ -97,7 +95,7 @@ pa_operation *pa_ext_device_manager_prefer_device( pa_context_success_cb_t cb, void *userdata); -/** Subscribe to changes in the device database. \since 0.9.19 */ +/** Defer a given device in the priority list. \since 0.9.19 */ pa_operation *pa_ext_device_manager_defer_device( pa_context *c, const char* role, -- 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 ++++++++++++++++++++++++++++++- src/pulse/ext-device-manager.h | 9 +++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'src/pulse') 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); } } diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h index 686c8d22..bd52331c 100644 --- a/src/pulse/ext-device-manager.h +++ b/src/pulse/ext-device-manager.h @@ -33,11 +33,20 @@ PA_C_DECL_BEGIN +typedef struct pa_ext_device_manager_role_priority_info { + const char *role; + uint32_t priority; +} pa_ext_device_manager_role_priority_info; + /** Stores information about one device in the device database that is * maintained by module-device-manager. \since 0.9.19 */ typedef struct pa_ext_device_manager_info { const char *name; /**< Identifier string of the device. A string like "sink:" or similar followed by the name of the device. */ const char *description; /**< The description of the device when it was last seen, if applicable and saved */ + const char *icon; /**< The icon given to the device */ + uint8_t available; /**< Is the device currently available? */ + uint32_t n_role_priorities; /**< How many role priorities do we have? */ + pa_ext_device_manager_role_priority_info *role_priorities; /**< An array of role priority structures or NULL */ } pa_ext_device_manager_info; /** Callback prototype for pa_ext_device_manager_test(). \since 0.9.19 */ -- 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 +++++++++--------------------------------- src/pulse/ext-device-manager.h | 12 ++-------- 2 files changed, 13 insertions(+), 52 deletions(-) (limited to 'src/pulse') 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); diff --git a/src/pulse/ext-device-manager.h b/src/pulse/ext-device-manager.h index bd52331c..13538f0c 100644 --- a/src/pulse/ext-device-manager.h +++ b/src/pulse/ext-device-manager.h @@ -97,18 +97,10 @@ pa_operation *pa_ext_device_manager_enable_role_device_priority_routing( void *userdata); /** Prefer a given device in the priority list. \since 0.9.19 */ -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, - pa_context_success_cb_t cb, - void *userdata); - -/** Defer a given device in the priority list. \since 0.9.19 */ -pa_operation *pa_ext_device_manager_defer_device( - pa_context *c, - const char* role, - const char* device, + const char** devices, pa_context_success_cb_t cb, void *userdata); -- cgit