mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	card: Add messages to enable/disable jack detection
With this patch, messages can be sent to the cards to enable/disable jack detection for the whole card or single ports, manually set a port state and to retrieve the current state of jack detection and port availability.
This commit is contained in:
		
							parent
							
								
									58521c05e8
								
							
						
					
					
						commit
						f178a5b12e
					
				
					 7 changed files with 95 additions and 21 deletions
				
			
		| 
						 | 
					@ -47,3 +47,28 @@ Object path: /card/<card_name>
 | 
				
			||||||
Message: get-profile-sticky
 | 
					Message: get-profile-sticky
 | 
				
			||||||
Parameters: None
 | 
					Parameters: None
 | 
				
			||||||
Return value: JSON "true" or "false"
 | 
					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;
 | 
					    device->available = available;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PA_DYNARRAY_FOREACH(port, device->ucm_ports, idx)
 | 
					    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) {
 | 
					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,
 | 
					    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_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) {
 | 
					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++)
 | 
					    for (tp = tports; tp->port; tp++)
 | 
				
			||||||
        if (tp->avail != PA_AVAILABLE_NO)
 | 
					        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++)
 | 
					    for (tp = tports; tp->port; tp++)
 | 
				
			||||||
        if (tp->avail == PA_AVAILABLE_NO)
 | 
					        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++) {
 | 
					    for (tp = tports; tp->port; tp++) {
 | 
				
			||||||
        pa_alsa_port_data *data;
 | 
					        pa_alsa_port_data *data;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2340,9 +2340,9 @@ static void handle_transport_state_change(struct userdata *u, struct pa_bluetoot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Update port availability */
 | 
					    /* Update port availability */
 | 
				
			||||||
    pa_assert_se(port = pa_hashmap_get(u->card->ports, u->output_port_name));
 | 
					    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_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 or release transport as needed */
 | 
				
			||||||
    acquire = (t->state == PA_BLUETOOTH_TRANSPORT_STATE_PLAYING && u->profile == t->profile);
 | 
					    acquire = (t->state == PA_BLUETOOTH_TRANSPORT_STATE_PLAYING && u->profile == t->profile);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,10 +163,10 @@ static int card_message_handler(const char *object_path, const char *message, co
 | 
				
			||||||
    pa_card *c = userdata;
 | 
					    pa_card *c = userdata;
 | 
				
			||||||
    const char *port_name;
 | 
					    const char *port_name;
 | 
				
			||||||
    bool jack_detection;
 | 
					    bool jack_detection;
 | 
				
			||||||
 | 
					    int64_t port_state;
 | 
				
			||||||
    void *state = NULL;
 | 
					    void *state = NULL;
 | 
				
			||||||
    pa_device_port *port = NULL;
 | 
					    pa_device_port *port = NULL;
 | 
				
			||||||
    const pa_json_object *o;
 | 
					    const pa_json_object *o;
 | 
				
			||||||
    int64_t current_state;
 | 
					 | 
				
			||||||
    char *message_handler_path;
 | 
					    char *message_handler_path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(c);
 | 
					    pa_assert(c);
 | 
				
			||||||
| 
						 | 
					@ -240,7 +240,7 @@ static int card_message_handler(const char *object_path, const char *message, co
 | 
				
			||||||
                pa_log_info("Parameters type does not match message command");
 | 
					                pa_log_info("Parameters type does not match message command");
 | 
				
			||||||
                return -PA_ERR_INVALID;
 | 
					                return -PA_ERR_INVALID;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            current_state = pa_json_object_get_int(o);
 | 
					            port_state = pa_json_object_get_int(o);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
| 
						 | 
					@ -256,15 +256,35 @@ static int card_message_handler(const char *object_path, const char *message, co
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    state = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (pa_streq(message, "set-jack-detection")) {
 | 
					    if (pa_streq(message, "set-jack-detection")) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!port) {
 | 
					        if (!port) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            PA_HASHMAP_FOREACH(port, c->ports, state)
 | 
					            PA_HASHMAP_FOREACH(port, c->ports, state) {
 | 
				
			||||||
                port->jack_detection = jack_detection;
 | 
					                pa_available_t avail = PA_AVAILABLE_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* If jack detection was enabled, set the port state
 | 
				
			||||||
 | 
					                 * to the hardware state. */
 | 
				
			||||||
 | 
					                if (jack_detection)
 | 
				
			||||||
 | 
					                    avail = port->hw_available;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } else
 | 
					 | 
				
			||||||
                port->jack_detection = jack_detection;
 | 
					                port->jack_detection = jack_detection;
 | 
				
			||||||
 | 
					                pa_device_port_set_available(port, avail, true);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            pa_available_t avail = PA_AVAILABLE_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* If jack detection was enabled, set the port state
 | 
				
			||||||
 | 
					             * to the hardware state. */
 | 
				
			||||||
 | 
					            if (jack_detection)
 | 
				
			||||||
 | 
					                avail = port->hw_available;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            port->jack_detection = jack_detection;
 | 
				
			||||||
 | 
					            pa_device_port_set_available(port, avail, true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return PA_OK;
 | 
					        return PA_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -291,10 +311,25 @@ static int card_message_handler(const char *object_path, const char *message, co
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } else if (pa_streq(message, "set-port-state")) {
 | 
					    } else if (pa_streq(message, "set-port-state")) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Not implemented because jack_detection is still unused
 | 
					        /* Validate port state parameter */
 | 
				
			||||||
         * and manually setting a port state would require to disable
 | 
					        if ((pa_available_t) port_state > PA_AVAILABLE_YES)
 | 
				
			||||||
         * jack detection */
 | 
					            return -PA_ERR_INVALID;
 | 
				
			||||||
        return -PA_ERR_NOTIMPLEMENTED;
 | 
					
 | 
				
			||||||
 | 
					        if (!port) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            PA_HASHMAP_FOREACH(port, c->ports, state) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                port->jack_detection = false;
 | 
				
			||||||
 | 
					                pa_device_port_set_available(port, (pa_available_t) port_state, true);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            port->jack_detection = false;
 | 
				
			||||||
 | 
					            pa_device_port_set_available(port, (pa_available_t) port_state, true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return PA_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } else if (pa_streq(message, "get-port-state")) {
 | 
					    } else if (pa_streq(message, "get-port-state")) {
 | 
				
			||||||
        pa_json_encoder *encoder;
 | 
					        pa_json_encoder *encoder;
 | 
				
			||||||
| 
						 | 
					@ -306,14 +341,14 @@ static int card_message_handler(const char *object_path, const char *message, co
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            pa_json_encoder_begin_member_object(encoder, "Port states");
 | 
					            pa_json_encoder_begin_member_object(encoder, "Port states");
 | 
				
			||||||
            PA_HASHMAP_FOREACH(port, c->ports, state) {
 | 
					            PA_HASHMAP_FOREACH(port, c->ports, state) {
 | 
				
			||||||
                current_state = port->available;
 | 
					                port_state = port->available;
 | 
				
			||||||
                pa_json_encoder_add_member_int(encoder, port->name, current_state);
 | 
					                pa_json_encoder_add_member_int(encoder, port->name, port_state);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            pa_json_encoder_end_object(encoder);
 | 
					            pa_json_encoder_end_object(encoder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       } else {
 | 
					       } else {
 | 
				
			||||||
            current_state = port->available;
 | 
					            port_state = port->available;
 | 
				
			||||||
            pa_json_encoder_add_member_int(encoder, port->name, current_state);
 | 
					            pa_json_encoder_add_member_int(encoder, port->name, port_state);
 | 
				
			||||||
       }
 | 
					       }
 | 
				
			||||||
       pa_json_encoder_end_object(encoder);
 | 
					       pa_json_encoder_end_object(encoder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
					    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)
 | 
					    if (p->available == status)
 | 
				
			||||||
        return;
 | 
					        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); */
 | 
					/*    pa_assert(status != PA_AVAILABLE_UNKNOWN); */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    p->available = status;
 | 
					    p->available = status;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,7 @@ struct pa_device_port {
 | 
				
			||||||
    unsigned priority;
 | 
					    unsigned priority;
 | 
				
			||||||
    pa_available_t available;         /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
 | 
					    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 */
 | 
					    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_proplist *proplist;
 | 
				
			||||||
    pa_hashmap *profiles; /* Does not own the profiles */
 | 
					    pa_hashmap *profiles; /* Does not own the profiles */
 | 
				
			||||||
| 
						 | 
					@ -88,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);
 | 
					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 */
 | 
					/* 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_latency_offset(pa_device_port *p, int64_t offset);
 | 
				
			||||||
void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp);
 | 
					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