summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Guthrie <cguthrie@mandriva.org>2009-09-19 17:48:10 +0100
committerColin Guthrie <cguthrie@mandriva.org>2009-11-11 17:44:23 +0000
commit4981268738cca80a2104575d5844167346a0dcfb (patch)
tree3148457ae3fcd1376f18f6618d056802cafa10da
parenta9bd1ab69c6c23610b509ec5bb70d279f722f48a (diff)
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.
-rw-r--r--src/modules/module-device-manager.c148
-rw-r--r--src/pulse/ext-device-manager.c74
-rw-r--r--src/pulse/ext-device-manager.h16
3 files changed, 238 insertions, 0 deletions
diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c
index b3c407ca..740b98fa 100644
--- a/src/modules/module-device-manager.c
+++ b/src/modules/module-device-manager.c
@@ -87,9 +87,23 @@ struct userdata {
#define ENTRY_VERSION 1
+#define NUM_ROLES 9
+enum {
+ ROLE_NONE,
+ ROLE_VIDEO,
+ ROLE_MUSIC,
+ ROLE_GAME,
+ ROLE_EVENT,
+ ROLE_PHONE,
+ ROLE_ANIMATION,
+ ROLE_PRODUCTION,
+ ROLE_A11Y,
+};
+
struct entry {
uint8_t version;
char description[PA_NAME_MAX];
+ uint32_t priority[NUM_ROLES];
} PA_GCC_PACKED;
enum {
@@ -98,6 +112,8 @@ enum {
SUBCOMMAND_WRITE,
SUBCOMMAND_DELETE,
SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING,
+ SUBCOMMAND_PREFER_DEVICE,
+ SUBCOMMAND_DEFER_DEVICE,
SUBCOMMAND_SUBSCRIBE,
SUBCOMMAND_EVENT
};
@@ -346,6 +362,31 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
}
}
+
+static uint32_t get_role_index(const char* role) {
+ pa_assert(role);
+
+ if (strcmp(role, "") == 0)
+ return ROLE_NONE;
+ if (strcmp(role, "video") == 0)
+ return ROLE_VIDEO;
+ if (strcmp(role, "music") == 0)
+ return ROLE_MUSIC;
+ if (strcmp(role, "game") == 0)
+ return ROLE_GAME;
+ if (strcmp(role, "event") == 0)
+ return ROLE_EVENT;
+ if (strcmp(role, "phone") == 0)
+ return ROLE_PHONE;
+ if (strcmp(role, "animation") == 0)
+ return ROLE_ANIMATION;
+ if (strcmp(role, "production") == 0)
+ return ROLE_PRODUCTION;
+ if (strcmp(role, "a11y") == 0)
+ return ROLE_A11Y;
+ return PA_INVALID_INDEX;
+}
+
#define EXT_VERSION 1
static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connection *c, uint32_t tag, pa_tagstruct *t) {
@@ -526,6 +567,113 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
break;
}
+ case SUBCOMMAND_PREFER_DEVICE:
+ case SUBCOMMAND_DEFER_DEVICE: {
+
+ const char *role, *device;
+ struct entry *e;
+ uint32_t role_index;
+
+ if (pa_tagstruct_gets(t, &role) < 0 ||
+ pa_tagstruct_gets(t, &device) < 0)
+ goto fail;
+
+ if (!role || !device || !*device)
+ goto fail;
+
+ role_index = get_role_index(role);
+ if (PA_INVALID_INDEX == role_index)
+ goto fail;
+
+ if ((e = read_entry(u, device)) && ENTRY_VERSION == e->version) {
+ pa_datum key;
+ pa_datum data;
+ pa_bool_t done;
+ char* prefix;
+ uint32_t priority;
+ pa_bool_t haschanged = FALSE;
+
+ if (strncmp(device, "sink:", 5) == 0)
+ prefix = pa_xstrdup("sink:");
+ else
+ prefix = pa_xstrdup("source:");
+
+ priority = e->priority[role_index];
+
+ /* Now we need to load up all the other entries of this type and shuffle the priroities around */
+
+ done = !pa_database_first(u->database, &key, NULL);
+
+ while (!done && !haschanged) {
+ pa_datum next_key;
+
+ done = !pa_database_next(u->database, &key, &next_key, NULL);
+
+ /* Only read devices with the right prefix */
+ if (key.size > strlen(prefix) && strncmp(key.data, prefix, strlen(prefix)) == 0) {
+ char *name;
+ struct entry *e2;
+
+ name = pa_xstrndup(key.data, key.size);
+ pa_datum_free(&key);
+
+ if ((e2 = read_entry(u, name))) {
+ if (SUBCOMMAND_PREFER_DEVICE == command) {
+ /* PREFER */
+ if (e2->priority[role_index] == (priority - 1)) {
+ e2->priority[role_index]++;
+ haschanged = TRUE;
+ }
+ } else {
+ /* DEFER */
+ if (e2->priority[role_index] == (priority + 1)) {
+ e2->priority[role_index]--;
+ haschanged = TRUE;
+ }
+ }
+
+ if (haschanged) {
+ data.data = e2;
+ data.size = sizeof(*e2);
+
+ if (pa_database_set(u->database, &key, &data, FALSE))
+ pa_log_warn("Could not save device");
+ }
+ pa_xfree(e2);
+ }
+
+ pa_xfree(name);
+ }
+
+ key = next_key;
+ }
+
+ /* Now write out our actual entry */
+ if (haschanged) {
+ if (SUBCOMMAND_PREFER_DEVICE == command)
+ e->priority[role_index]--;
+ else
+ e->priority[role_index]++;
+
+ key.data = (char *) device;
+ key.size = strlen(device);
+
+ data.data = e;
+ data.size = sizeof(*e);
+
+ if (pa_database_set(u->database, &key, &data, FALSE))
+ pa_log_warn("Could not save device");
+
+ trigger_save(u);
+ }
+
+ pa_xfree(e);
+
+ pa_xfree(prefix);
+ }
+ break;
+ }
+
case SUBCOMMAND_SUBSCRIBE: {
pa_bool_t enabled;
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
@@ -90,6 +90,22 @@ pa_operation *pa_ext_device_manager_enable_role_device_priority_routing(
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,
int enable,