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