[pulseaudio-discuss] [PATCH 1/3] card: add infrastructure to enable/disable jack detection
Georg Chini
georg at chini.tk
Mon Apr 9 18:38:24 UTC 2018
This patch adds a card message handler which will be used to enable
or disable jack detection on a per port basis. Only the necessary
variables and functions are added without changing functionality.
---
src/pulsecore/card.c | 129 +++++++++++++++++++++++++++++++++++++++++++-
src/pulsecore/card.h | 4 ++
src/pulsecore/device-port.h | 2 +
3 files changed, 133 insertions(+), 2 deletions(-)
diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index bc5b75b0..e91c034f 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -27,11 +27,13 @@
#include <pulse/xmalloc.h>
#include <pulse/util.h>
+#include <pulse/message-params.h>
#include <pulsecore/log.h>
#include <pulsecore/macro.h>
#include <pulsecore/core-util.h>
#include <pulsecore/namereg.h>
+#include <pulsecore/message-handler.h>
#include <pulsecore/device-port.h>
#include "card.h"
@@ -86,6 +88,7 @@ pa_card_new_data* pa_card_new_data_init(pa_card_new_data *data) {
data->proplist = pa_proplist_new();
data->profiles = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) pa_card_profile_free);
data->ports = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) pa_device_port_unref);
+ data->jack_detection = true;
return data;
}
@@ -120,9 +123,115 @@ void pa_card_new_data_done(pa_card_new_data *data) {
pa_xfree(data->name);
}
+static int card_message_handler(const char *object_path, const char *message, char *message_parameters, char **response, void *userdata) {
+ pa_card *c;
+ char *port_name;
+ bool jack_detection;
+ void *state = NULL;
+ void *state2;
+ pa_device_port *port = NULL;
+
+ pa_assert(c = (pa_card *) userdata);
+ pa_assert(message);
+ pa_assert(response);
+
+ /* Get the first argument of the message */
+ if (pa_message_param_read_string(message_parameters, &port_name, false, &state) <= 0)
+ return -PA_ERR_INVALID;
+
+ /* If the port argument is not "all", retrieve the port */
+ if (!pa_streq(port_name, "all")) {
+ if (!(port = pa_hashmap_get(c->ports, port_name)))
+ return -PA_ERR_INVALID;
+ }
+
+ if (pa_streq(message, "set-jack-detection")) {
+
+ /* Get the requested detection state */
+ if (pa_message_param_read_bool(message_parameters, &jack_detection, &state) <= 0)
+ return -PA_ERR_INVALID;
+
+ if (!port) {
+ c->jack_detection = jack_detection;
+
+ PA_HASHMAP_FOREACH(port, c->ports, state2)
+ port->jack_detection = c->jack_detection;
+
+ } else
+ port->jack_detection = jack_detection;
+
+ return PA_OK;
+
+ } else if (pa_streq(message, "get-jack-detection")) {
+ pa_message_param *param;
+
+ param = pa_message_param_new();
+ if (!port) {
+ pa_message_param_begin_list(param);
+ pa_message_param_write_string(param, c->name, false);
+ pa_message_param_write_bool(param, c->jack_detection);
+ pa_message_param_end_list(param);
+
+ PA_HASHMAP_FOREACH(port, c->ports, state2) {
+ pa_message_param_begin_list(param);
+ pa_message_param_write_string(param, port->name, false);
+ pa_message_param_write_bool(param, port->jack_detection);
+ pa_message_param_end_list(param);
+ }
+
+ } else {
+
+ pa_message_param_begin_list(param);
+ pa_message_param_write_string(param, port->name, false);
+ pa_message_param_write_bool(param, port->jack_detection);
+ pa_message_param_end_list(param);
+ }
+
+ *response = pa_message_param_to_string(param);
+ return PA_OK;
+
+ } else if (pa_streq(message, "set-port-state")) {
+
+ /* Not implemented because jack_detection is still unused
+ * and manually setting a port state would require to disable
+ * jack detection */
+ return -PA_ERR_NOTIMPLEMENTED;
+
+ } else if (pa_streq(message, "get-port-state")) {
+ pa_message_param *param;
+ uint64_t current_state;
+
+ param = pa_message_param_new();
+ if (!port) {
+ PA_HASHMAP_FOREACH(port, c->ports, state2) {
+ pa_message_param_begin_list(param);
+ pa_message_param_write_string(param, port->name, false);
+ current_state = port->available;
+ pa_message_param_write_uint64(param, current_state);
+ pa_message_param_end_list(param);
+ }
+
+ } else {
+
+ pa_message_param_begin_list(param);
+ pa_message_param_write_string(param, port->name, false);
+ current_state = port->available;
+ pa_message_param_write_uint64(param, current_state);
+ pa_message_param_end_list(param);
+ }
+
+ *response = pa_message_param_to_string(param);
+ return PA_OK;
+
+ }
+
+ return -PA_ERR_NOTIMPLEMENTED;
+}
+
pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
pa_card *c;
- const char *name;
+ const char *name, *tmp;
+ char *object_path, *description;
void *state;
pa_card_profile *profile;
pa_device_port *port;
@@ -148,6 +257,7 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
c->proplist = pa_proplist_copy(data->proplist);
c->driver = pa_xstrdup(pa_path_get_filename(data->driver));
c->module = data->module;
+ c->jack_detection = data->jack_detection;
c->sinks = pa_idxset_new(NULL, NULL);
c->sources = pa_idxset_new(NULL, NULL);
@@ -162,8 +272,10 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
PA_HASHMAP_FOREACH(profile, c->profiles, state)
profile->card = c;
- PA_HASHMAP_FOREACH(port, c->ports, state)
+ PA_HASHMAP_FOREACH(port, c->ports, state) {
port->card = c;
+ port->jack_detection = c->jack_detection;
+ }
c->preferred_input_port = data->preferred_input_port;
c->preferred_output_port = data->preferred_output_port;
@@ -172,6 +284,14 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
pa_device_init_icon(c->proplist, true);
pa_device_init_intended_roles(c->proplist);
+ object_path = pa_sprintf_malloc("/cards/%s", c->name);
+ if (!(tmp = pa_proplist_gets(c->proplist, PA_PROP_DEVICE_DESCRIPTION)))
+ tmp = c->name;
+ description = pa_sprintf_malloc("Message handler for card \"%s\"", tmp);
+ pa_message_handler_register(c->core, object_path, description, card_message_handler, (void *) c);
+ pa_xfree(object_path);
+ pa_xfree(description);
+
return c;
}
@@ -222,6 +342,7 @@ void pa_card_put(pa_card *card) {
void pa_card_free(pa_card *c) {
pa_core *core;
+ char *object_path;
pa_assert(c);
pa_assert(c->core);
@@ -236,6 +357,10 @@ void pa_card_free(pa_card *c) {
pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
}
+ object_path = pa_sprintf_malloc("/cards/%s", c->name);
+ pa_message_handler_unregister(core, object_path);
+ pa_xfree(object_path);
+
pa_namereg_unregister(core, c->name);
pa_assert(pa_idxset_isempty(c->sinks));
diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
index 5699475d..00a682b4 100644
--- a/src/pulsecore/card.h
+++ b/src/pulsecore/card.h
@@ -88,6 +88,8 @@ struct pa_card {
bool linked;
+ bool jack_detection;
+
void *userdata;
int (*set_profile)(pa_card *c, pa_card_profile *profile);
@@ -105,6 +107,8 @@ typedef struct pa_card_new_data {
pa_device_port *preferred_input_port;
pa_device_port *preferred_output_port;
+ bool jack_detection;
+
bool namereg_fail:1;
} pa_card_new_data;
diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h
index fbdce1aa..4787ff79 100644
--- a/src/pulsecore/device-port.h
+++ b/src/pulsecore/device-port.h
@@ -44,6 +44,8 @@ struct pa_device_port {
char *description;
char *preferred_profile;
+ bool jack_detection;
+
unsigned priority;
pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
--
2.14.1
More information about the pulseaudio-discuss
mailing list