diff --git a/doc/messaging_api.txt b/doc/messaging_api.txt index ad0774fde..6a1d077c6 100644 --- a/doc/messaging_api.txt +++ b/doc/messaging_api.txt @@ -47,3 +47,28 @@ Object path: /card/ Message: get-profile-sticky Parameters: None Return value: JSON "true" or "false" + +Object path: /cards/ +Message: set-jack-detection +Parameters: {"port_name|all":true|false} +Return value: None + +Object path: /cards/ +Message: get-jack-detection +Parameters: "port_name|all" +Return value: {"port_name":true|false} +If "all" is specified, the returned object looks different: +{"Card name":"card_name", "Detection states":{"port_name":true|false, ...}} + +Object path: /cards/ +Message: set-port-state +Parameters: {"port_name|all":0|1|2} +Return value: None +0=unknown, 1=no, 2=yes + +Object path: /cards/ +Message: get-port-state +Parameters: "port_name|all" +Return value: {"port_name":0|1|2} +If "all" is specified, the returned object looks different: +{"Card name":"card_name", "Port states":{"port_name":0|1|2, ...}} diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c index 018c01739..af37b44af 100644 --- a/src/modules/alsa/alsa-ucm.c +++ b/src/modules/alsa/alsa-ucm.c @@ -2480,7 +2480,7 @@ static void device_set_available(pa_alsa_ucm_device *device, pa_available_t avai device->available = available; PA_DYNARRAY_FOREACH(port, device->ucm_ports, idx) - pa_device_port_set_available(port->core_port, port->device->available); + pa_device_port_set_available(port->core_port, port->device->available, false); } void pa_alsa_ucm_device_update_available(pa_alsa_ucm_device *device) { @@ -2519,7 +2519,7 @@ static void ucm_port_data_init(pa_alsa_ucm_port_data *port, pa_alsa_ucm_config * port->paths = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, pa_xfree, (pa_free_cb_t) pa_alsa_path_free); - pa_device_port_set_available(port->core_port, port->device->available); + pa_device_port_set_available(port->core_port, port->device->available, false); } static void ucm_port_data_free(pa_device_port *port) { diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index 05c87c6bb..80a072e2d 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -435,10 +435,10 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { for (tp = tports; tp->port; tp++) if (tp->avail != PA_AVAILABLE_NO) - pa_device_port_set_available(tp->port, tp->avail); + pa_device_port_set_available(tp->port, tp->avail, false); for (tp = tports; tp->port; tp++) if (tp->avail == PA_AVAILABLE_NO) - pa_device_port_set_available(tp->port, tp->avail); + pa_device_port_set_available(tp->port, tp->avail, false); for (tp = tports; tp->port; tp++) { pa_alsa_port_data *data; diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c index dc6809ce5..2d76b6905 100644 --- a/src/modules/bluetooth/module-bluez5-device.c +++ b/src/modules/bluetooth/module-bluez5-device.c @@ -2340,9 +2340,9 @@ static void handle_transport_state_change(struct userdata *u, struct pa_bluetoot /* Update port availability */ pa_assert_se(port = pa_hashmap_get(u->card->ports, u->output_port_name)); - pa_device_port_set_available(port, get_port_availability(u, PA_DIRECTION_OUTPUT)); + pa_device_port_set_available(port, get_port_availability(u, PA_DIRECTION_OUTPUT), false); pa_assert_se(port = pa_hashmap_get(u->card->ports, u->input_port_name)); - pa_device_port_set_available(port, get_port_availability(u, PA_DIRECTION_INPUT)); + pa_device_port_set_available(port, get_port_availability(u, PA_DIRECTION_INPUT), false); /* Acquire or release transport as needed */ acquire = (t->state == PA_BLUETOOTH_TRANSPORT_STATE_PLAYING && u->profile == t->profile); diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c index c93d584ef..c5fc1a931 100644 --- a/src/modules/module-card-restore.c +++ b/src/modules/module-card-restore.c @@ -67,12 +67,14 @@ struct userdata { bool restore_bluetooth_profile; }; -#define ENTRY_VERSION 5 +#define ENTRY_VERSION 6 struct port_info { char *name; int64_t offset; char *profile; + bool jack_detection; + pa_available_t available; }; struct entry { @@ -126,6 +128,8 @@ static struct port_info *port_info_new(pa_device_port *port) { p_info = pa_xnew0(struct port_info, 1); p_info->name = pa_xstrdup(port->name); p_info->offset = port->latency_offset; + p_info->jack_detection = port->jack_detection; + p_info->available = port->available; if (port->preferred_profile) p_info->profile = pa_xstrdup(port->preferred_profile); } else @@ -184,7 +188,11 @@ static bool entrys_equal(struct entry *a, struct entry *b) { PA_HASHMAP_FOREACH(Ap_info, a->ports, state) { if ((Bp_info = pa_hashmap_get(b->ports, Ap_info->name))) { - if (Ap_info->offset != Bp_info->offset) + if (Ap_info->offset != Bp_info->offset || + Ap_info->jack_detection != Bp_info->jack_detection) + return false; + /* Availability only matters if jack detection is off */ + if (!Ap_info->jack_detection && Ap_info->available != Bp_info->available) return false; } else return false; @@ -222,6 +230,8 @@ static bool entry_write(struct userdata *u, const char *name, const struct entry pa_tagstruct_puts(t, p_info->name); pa_tagstruct_puts64(t, p_info->offset); pa_tagstruct_puts(t, p_info->profile); + pa_tagstruct_put_boolean(t, p_info->jack_detection); + pa_tagstruct_putu32(t, (uint32_t)p_info->available); } pa_tagstruct_puts(t, e->preferred_input_port); @@ -319,6 +329,8 @@ static struct entry* entry_read(struct userdata *u, const char *name) { int64_t port_offset = 0; struct port_info *p_info; unsigned i; + uint32_t available = PA_AVAILABLE_UNKNOWN; + bool jack_detection = true; if (pa_tagstruct_getu32(t, &port_count) < 0) goto fail; @@ -331,12 +343,19 @@ static struct entry* entry_read(struct userdata *u, const char *name) { goto fail; if (version >= 3 && pa_tagstruct_gets(t, &profile_name) < 0) goto fail; + if (version >= 6) { + if (pa_tagstruct_get_boolean(t, &jack_detection) < 0 || + pa_tagstruct_getu32(t, &available) < 0) + goto fail; + } p_info = port_info_new(NULL); p_info->name = pa_xstrdup(port_name); p_info->offset = port_offset; if (profile_name) p_info->profile = pa_xstrdup(profile_name); + p_info->jack_detection = jack_detection; + p_info->available = (pa_available_t)available; pa_assert_se(pa_hashmap_put(e->ports, p_info->name, p_info) >= 0); } @@ -399,9 +418,9 @@ static void show_full_info(pa_card *card) { pa_assert(card); if (card->save_profile) - pa_log_info("Storing profile and port latency offsets for card %s.", card->name); + pa_log_info("Storing profile, port latency offsets, jack detection and port availability for card %s.", card->name); else - pa_log_info("Storing port latency offsets for card %s.", card->name); + pa_log_info("Storing port latency offsets, jack detection and port availability for card %s.", card->name); } static pa_hook_result_t card_put_hook_callback(pa_core *c, pa_card *card, struct userdata *u) { @@ -534,6 +553,76 @@ static pa_hook_result_t port_offset_change_callback(pa_core *c, pa_device_port * return PA_HOOK_OK; } +static pa_hook_result_t port_available_change_callback(pa_core *c, pa_device_port *port, struct userdata *u) { + struct entry *entry; + pa_card *card; + + pa_assert(port); + + /* If jack detection is enabled, the availability change needs not be saved */ + if (port->jack_detection) + return PA_HOOK_OK; + + card = port->card; + + if ((entry = entry_read(u, card->name))) { + struct port_info *p_info; + + if ((p_info = pa_hashmap_get(entry->ports, port->name))) + p_info->available = port->available; + else { + p_info = port_info_new(port); + pa_assert_se(pa_hashmap_put(entry->ports, p_info->name, p_info) >= 0); + } + + pa_log_info("Storing availability for port %s on card %s.", port->name, card->name); + + } else { + entry = entry_from_card(card); + show_full_info(card); + } + + if (entry_write(u, card->name, entry)) + trigger_save(u); + + entry_free(entry); + return PA_HOOK_OK; +} + +static pa_hook_result_t port_jack_detection_change_callback(pa_core *c, pa_device_port *port, struct userdata *u) { + struct entry *entry; + pa_card *card; + + pa_assert(port); + + card = port->card; + + if ((entry = entry_read(u, card->name))) { + struct port_info *p_info; + + if ((p_info = pa_hashmap_get(entry->ports, port->name))) { + p_info->jack_detection = port->jack_detection; + if (!p_info->jack_detection) + p_info->available = port->available; + } else { + p_info = port_info_new(port); + pa_assert_se(pa_hashmap_put(entry->ports, p_info->name, p_info) >= 0); + } + + pa_log_info("Storing jack detection for port %s on card %s.", port->name, card->name); + + } else { + entry = entry_from_card(card); + show_full_info(card); + } + + if (entry_write(u, card->name, entry)) + trigger_save(u); + + entry_free(entry); + return PA_HOOK_OK; +} + static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new_data, struct userdata *u) { struct entry *e; void *state; @@ -548,13 +637,19 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new /* Always restore the latency offsets because their * initial value is always 0 */ - pa_log_info("Restoring port latency offsets for card %s.", new_data->name); + pa_log_info("Restoring port latency offsets and jack detection for card %s.", new_data->name); PA_HASHMAP_FOREACH(p_info, e->ports, state) if ((p = pa_hashmap_get(new_data->ports, p_info->name))) { p->latency_offset = p_info->offset; if (!p->preferred_profile && p_info->profile) pa_device_port_set_preferred_profile(p, p_info->profile); + + /* Restore availability and jack detection only if jack detction was off */ + if (!p_info->jack_detection) { + p->jack_detection = p_info->jack_detection; + p->available = p_info->available; + } } if (e->preferred_input_port) { @@ -674,6 +769,8 @@ int pa__init(pa_module*m) { pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_changed_callback, u); pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_added_callback, u); pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) port_offset_change_callback, u); + pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) port_available_change_callback, u); + pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_PORT_JACK_DETECTION_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) port_jack_detection_change_callback, u); if (!(state_path = pa_state_path(NULL, true))) goto fail; diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index 4f5997d2c..351922874 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -38,8 +38,6 @@ #include "card.h" -static int card_message_handler(const char *object_path, const char *message, const pa_json_object *parameters, char **response, void *userdata); - static char* make_message_handler_path(const char *name) { return pa_sprintf_malloc("/card/%s", name); } @@ -142,6 +140,215 @@ void pa_card_new_data_done(pa_card_new_data *data) { pa_xfree(data->name); } +static int card_set_profile_is_sticky(pa_card *c, bool profile_is_sticky) { + pa_assert(c); + + if (c->profile_is_sticky == profile_is_sticky) + return 0; + + pa_log_debug("%s: profile_is_sticky: %s -> %s", + c->name, pa_yes_no(c->profile_is_sticky), pa_yes_no(profile_is_sticky)); + + c->profile_is_sticky = profile_is_sticky; + + if (c->linked) { + pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], c); + pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index); + } + + return 0; +} + +static void set_jack_detection(pa_device_port *port, bool jack_detection, pa_available_t avail) { + + /* If jack detection was enabled, set the port state + * to the hardware state. */ + if (jack_detection) + avail = port->hw_available; + + if (port->jack_detection != jack_detection) { + port->jack_detection = jack_detection; + pa_hook_fire(&port->core->hooks[PA_CORE_HOOK_PORT_JACK_DETECTION_CHANGED], port); + } + + pa_device_port_set_available(port, avail, true); +} + +static int card_message_handler(const char *object_path, const char *message, const pa_json_object *parameters, char **response, void *userdata) { + pa_card *c = userdata; + const char *port_name; + bool jack_detection; + int64_t port_state; + void *state = NULL; + pa_device_port *port = NULL; + const pa_json_object *o; + char *message_handler_path; + + pa_assert(c); + pa_assert(message); + pa_assert(response); + + message_handler_path = make_message_handler_path(c->name); + + if (!object_path || !pa_streq(object_path, message_handler_path)) { + pa_xfree(message_handler_path); + return -PA_ERR_NOENTITY; + } + + pa_xfree(message_handler_path); + + /* Sticky profile operations */ + + if (pa_streq(message, "get-profile-sticky")) { + pa_json_encoder *encoder; + encoder = pa_json_encoder_new(); + + pa_json_encoder_add_element_bool(encoder, c->profile_is_sticky); + + *response = pa_json_encoder_to_string_free(encoder); + + return PA_OK; + } else if (pa_streq(message, "set-profile-sticky")) { + + if (!parameters || pa_json_object_get_type(parameters) != PA_JSON_TYPE_BOOL) { + pa_log_info("Card operation set-profile-sticky requires argument: \"true\" or \"false\""); + return -PA_ERR_INVALID; + } + + card_set_profile_is_sticky(c, pa_json_object_get_bool(parameters)); + + return PA_OK; + } + + /* Jack detection operations */ + + if (!parameters) { + pa_log_info("Card jack detection operations require at least one parameter"); + return -PA_ERR_INVALID; + } + + /* Get the arguments of the message */ + if (pa_json_object_get_type(parameters) == PA_JSON_TYPE_STRING) + port_name = pa_json_object_get_string(parameters); + + else if (pa_json_object_get_type(parameters) == PA_JSON_TYPE_OBJECT) { + const pa_hashmap *h; + + h = pa_json_object_get_object_member_hashmap(parameters); + if (pa_hashmap_size(h) > 1) { + pa_log_info("Too many parameters"); + return -PA_ERR_INVALID; + } + o = pa_hashmap_iterate(h, &state, (const void **) &port_name); + if (!o || (pa_json_object_get_type(o) != PA_JSON_TYPE_BOOL && pa_json_object_get_type(o) != PA_JSON_TYPE_INT)) { + pa_log_info("Parameters must contain a valid JSON object"); + return -PA_ERR_INVALID; + } + if (pa_json_object_get_type(o) == PA_JSON_TYPE_BOOL) { + if (!pa_streq(message, "set-jack-detection")) { + pa_log_info("Parameters type does not match message command"); + return -PA_ERR_INVALID; + } + jack_detection = pa_json_object_get_bool(o); + } else { + if (!pa_streq(message, "set-port-state")) { + pa_log_info("Parameters type does not match message command"); + return -PA_ERR_INVALID; + } + port_state = pa_json_object_get_int(o); + } + + } else { + pa_log_info("Parameters must be a valid JSON object"); + 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))) { + pa_log_info("Parameters do not contain a valid port name"); + return -PA_ERR_INVALID; + } + } + + state = NULL; + + if (pa_streq(message, "set-jack-detection")) { + + if (!port) { + PA_HASHMAP_FOREACH(port, c->ports, state) + set_jack_detection(port, jack_detection, PA_AVAILABLE_UNKNOWN); + + } else + set_jack_detection(port, jack_detection, PA_AVAILABLE_UNKNOWN); + + return PA_OK; + + } else if (pa_streq(message, "get-jack-detection")) { + pa_json_encoder *encoder; + + encoder = pa_json_encoder_new(); + pa_json_encoder_begin_element_object(encoder); + if (!port) { + pa_json_encoder_add_member_string(encoder, "Card name", c->name); + + pa_json_encoder_begin_member_object(encoder, "Detection states"); + PA_HASHMAP_FOREACH(port, c->ports, state) + pa_json_encoder_add_member_bool(encoder, port->name, port->jack_detection); + pa_json_encoder_end_object(encoder); + + } else + pa_json_encoder_add_member_bool(encoder, port->name, port->jack_detection); + + pa_json_encoder_end_object(encoder); + + *response = pa_json_encoder_to_string_free(encoder); + return PA_OK; + + } else if (pa_streq(message, "set-port-state")) { + + /* Validate port state parameter */ + if ((pa_available_t) port_state > PA_AVAILABLE_YES) + return -PA_ERR_INVALID; + + if (!port) { + PA_HASHMAP_FOREACH(port, c->ports, state) + set_jack_detection(port, false, (pa_available_t) port_state); + + } else + set_jack_detection(port, false, (pa_available_t) port_state); + + return PA_OK; + + } else if (pa_streq(message, "get-port-state")) { + pa_json_encoder *encoder; + + encoder = pa_json_encoder_new(); + pa_json_encoder_begin_element_object(encoder); + if (!port) { + pa_json_encoder_add_member_string(encoder, "Card name", c->name); + + pa_json_encoder_begin_member_object(encoder, "Port states"); + PA_HASHMAP_FOREACH(port, c->ports, state) { + port_state = port->available; + pa_json_encoder_add_member_int(encoder, port->name, port_state); + } + pa_json_encoder_end_object(encoder); + + } else { + port_state = port->available; + pa_json_encoder_add_member_int(encoder, port->name, port_state); + } + pa_json_encoder_end_object(encoder); + + *response = pa_json_encoder_to_string_free(encoder); + 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, *tmp; @@ -328,25 +535,6 @@ static void update_port_preferred_profile(pa_card *c) { pa_device_port_set_preferred_profile(source->active_port, profile_name_for_dir(c->active_profile, PA_DIRECTION_INPUT)); } -static int card_set_profile_is_sticky(pa_card *c, bool profile_is_sticky) { - pa_assert(c); - - if (c->profile_is_sticky == profile_is_sticky) - return 0; - - pa_log_debug("%s: profile_is_sticky: %s -> %s", - c->name, pa_yes_no(c->profile_is_sticky), pa_yes_no(profile_is_sticky)); - - c->profile_is_sticky = profile_is_sticky; - - if (c->linked) { - pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], c); - pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, c->index); - } - - return 0; -} - int pa_card_set_profile(pa_card *c, pa_card_profile *profile, bool save) { int r; @@ -465,44 +653,3 @@ int pa_card_suspend(pa_card *c, bool suspend, pa_suspend_cause_t cause) { return ret; } - -static int card_message_handler(const char *object_path, const char *message, const pa_json_object *parameters, char **response, void *userdata) { - pa_card *c = userdata; - char *message_handler_path; - - pa_assert(c); - pa_assert(message); - pa_assert(response); - - message_handler_path = make_message_handler_path(c->name); - - if (!object_path || !pa_streq(object_path, message_handler_path)) { - pa_xfree(message_handler_path); - return -PA_ERR_NOENTITY; - } - - pa_xfree(message_handler_path); - - if (pa_streq(message, "get-profile-sticky")) { - pa_json_encoder *encoder; - encoder = pa_json_encoder_new(); - - pa_json_encoder_add_element_bool(encoder, c->profile_is_sticky); - - *response = pa_json_encoder_to_string_free(encoder); - - return PA_OK; - } else if (pa_streq(message, "set-profile-sticky")) { - - if (!parameters || pa_json_object_get_type(parameters) != PA_JSON_TYPE_BOOL) { - pa_log_info("Card operation set-profile-sticky requires argument: \"true\" or \"false\""); - return -PA_ERR_INVALID; - } - - card_set_profile_is_sticky(c, pa_json_object_get_bool(parameters)); - - return PA_OK; - } - - return -PA_ERR_NOTIMPLEMENTED; -} diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h index 20f66aa4e..df539e494 100644 --- a/src/pulsecore/card.h +++ b/src/pulsecore/card.h @@ -106,6 +106,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/core.h b/src/pulsecore/core.h index 7ac06f5d7..f53d5aba5 100644 --- a/src/pulsecore/core.h +++ b/src/pulsecore/core.h @@ -136,6 +136,7 @@ typedef enum pa_core_hook { PA_CORE_HOOK_CARD_SUSPEND_CHANGED, PA_CORE_HOOK_PORT_AVAILABLE_CHANGED, PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED, + PA_CORE_HOOK_PORT_JACK_DETECTION_CHANGED, PA_CORE_HOOK_DEFAULT_SINK_CHANGED, PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED, PA_CORE_HOOK_MODULE_NEW, diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c index 4f9235e51..beb5ab693 100644 --- a/src/pulsecore/device-port.c +++ b/src/pulsecore/device-port.c @@ -90,12 +90,25 @@ void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp) } } -void pa_device_port_set_available(pa_device_port *p, pa_available_t status) { +void pa_device_port_set_available(pa_device_port *p, pa_available_t status, bool force) { pa_assert(p); + /* If force is not set, status reflects the state of the port from a + * hardware perspective. We need to keep track of the real port state + * so that we can go back to it once jack detection is enabled for the + * port. If force is set, we are updating the port state manually, so + * the hardware state is unaffected. */ + if (!force) + p->hw_available = status; + if (p->available == status) return; + /* Do not set the port state if jack detection is disabled for the port + * unless we are setting the state manually. */ + if (!force && !p->jack_detection) + return; + /* pa_assert(status != PA_AVAILABLE_UNKNOWN); */ p->available = status; @@ -200,6 +213,7 @@ pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, si p->type = data->type; p->latency_offset = 0; + p->jack_detection = true; p->proplist = pa_proplist_new(); return p; diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h index 7178ff2ae..2953e9558 100644 --- a/src/pulsecore/device-port.h +++ b/src/pulsecore/device-port.h @@ -45,9 +45,12 @@ struct pa_device_port { char *preferred_profile; pa_device_port_type_t type; + bool jack_detection; + unsigned priority; pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */ char *availability_group; /* a string indentifier which determine the group of devices handling the available state simulteneously */ + pa_available_t hw_available; pa_proplist *proplist; pa_hashmap *profiles; /* Does not own the profiles */ @@ -86,7 +89,7 @@ void pa_device_port_new_data_done(pa_device_port_new_data *data); pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, size_t extra); /* The port's available status has changed */ -void pa_device_port_set_available(pa_device_port *p, pa_available_t available); +void pa_device_port_set_available(pa_device_port *p, pa_available_t available, bool force); void pa_device_port_set_latency_offset(pa_device_port *p, int64_t offset); void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp);