mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
Merge branch 'jack_detection' into 'master'
Add message commands to enable/disable jack detection per port See merge request pulseaudio/pulseaudio!452
This commit is contained in:
commit
8dc3837d1e
10 changed files with 364 additions and 75 deletions
|
|
@ -47,3 +47,28 @@ Object path: /card/<card_name>
|
|||
Message: get-profile-sticky
|
||||
Parameters: None
|
||||
Return value: JSON "true" or "false"
|
||||
|
||||
Object path: /cards/<card_name>
|
||||
Message: set-jack-detection
|
||||
Parameters: {"port_name|all":true|false}
|
||||
Return value: None
|
||||
|
||||
Object path: /cards/<card_name>
|
||||
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/<card_name>
|
||||
Message: set-port-state
|
||||
Parameters: {"port_name|all":0|1|2}
|
||||
Return value: None
|
||||
0=unknown, 1=no, 2=yes
|
||||
|
||||
Object path: /cards/<card_name>
|
||||
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, ...}}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue