diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c index 1813ad9f8..59a9ac9fe 100644 --- a/src/modules/alsa/alsa-mixer.c +++ b/src/modules/alsa/alsa-mixer.c @@ -1724,6 +1724,8 @@ static pa_alsa_jack* jack_get(pa_alsa_path *p, const char *section) { goto finish; j = pa_xnew0(pa_alsa_jack, 1); + j->state_unplugged = PA_PORT_AVAILABLE_NO; + j->state_plugged = PA_PORT_AVAILABLE_YES; j->path = p; j->name = pa_xstrdup(section); j->alsa_name = pa_sprintf_malloc("%s Jack", section); @@ -2187,6 +2189,45 @@ static int element_parse_override_map( return 0; } +static int jack_parse_state( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + const char *rvalue, + void *data, + void *userdata) { + + pa_alsa_path *p = userdata; + pa_alsa_jack *j; + pa_port_available_t pa; + + if (!(j = jack_get(p, section))) { + pa_log("[%s:%u] state makes no sense in '%s'", filename, line, section); + return -1; + } + + if (!strcmp(rvalue,"yes")) + pa = PA_PORT_AVAILABLE_YES; + else if (!strcmp(rvalue,"no")) + pa = PA_PORT_AVAILABLE_NO; + else if (!strcmp(rvalue,"unknown")) + pa = PA_PORT_AVAILABLE_UNKNOWN; + else { + pa_log("[%s:%u] state must be 'yes','no' or 'unknown' in '%s'", filename, line, section); + return -1; + } + + if (!strcmp(lvalue, "state.unplugged")) + j->state_unplugged = pa; + else { + j->state_plugged = pa; + pa_assert(!strcmp(lvalue, "state.plugged")); + } + + return 0; +} + static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx) { snd_mixer_selem_id_t *sid; snd_mixer_elem_t *me; @@ -2380,6 +2421,10 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa { "priority", option_parse_priority, NULL, NULL }, { "name", option_parse_name, NULL, NULL }, + /* [Jack ...] */ + { "state.plugged", jack_parse_state, NULL, NULL }, + { "state.unplugged", jack_parse_state, NULL, NULL }, + /* [Element ...] */ { "switch", element_parse_switch, NULL, NULL }, { "volume", element_parse_volume, NULL, NULL }, diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h index 1912ba180..59bd3fbe0 100644 --- a/src/modules/alsa/alsa-mixer.h +++ b/src/modules/alsa/alsa-mixer.h @@ -164,6 +164,7 @@ struct pa_alsa_jack { pa_bool_t has_control; /* is the jack itself present? */ pa_bool_t plugged_in; /* is this jack currently plugged in? */ snd_hctl_elem_t *hctl_elem; /* Jack detection handle */ + pa_port_available_t state_unplugged, state_plugged; pa_alsa_required_t required; pa_alsa_required_t required_any; diff --git a/src/modules/alsa/mixer/paths/analog-input-internal-mic.conf b/src/modules/alsa/mixer/paths/analog-input-internal-mic.conf index dd400754e..ba15f1c7a 100644 --- a/src/modules/alsa/mixer/paths/analog-input-internal-mic.conf +++ b/src/modules/alsa/mixer/paths/analog-input-internal-mic.conf @@ -23,6 +23,22 @@ priority = 89 name = analog-input-microphone-internal +[Jack Mic] +state.plugged = no +state.unplugged = unknown + +[Jack Dock Mic] +state.plugged = no +state.unplugged = unknown + +[Jack Front Mic] +state.plugged = no +state.unplugged = unknown + +[Jack Rear Mic] +state.plugged = no +state.unplugged = unknown + [Element Internal Mic Boost] required-any = any switch = select diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf b/src/modules/alsa/mixer/paths/analog-output-speaker.conf index 0ba3e911c..9c58ed9fc 100644 --- a/src/modules/alsa/mixer/paths/analog-output-speaker.conf +++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf @@ -22,6 +22,10 @@ priority = 100 name = analog-output-speaker +[Jack Headphone] +state.plugged = no +state.unplugged = unknown + [Element Hardware Master] switch = mute volume = merge diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index c5bffcd29..3493465ad 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -288,7 +288,7 @@ static void report_port_state(pa_device_port *p, struct userdata *u) if (p != jack->path->port) continue; - cpa = jack->plugged_in ? PA_PORT_AVAILABLE_YES : PA_PORT_AVAILABLE_NO; + cpa = jack->plugged_in ? jack->state_plugged : jack->state_unplugged; /* "Yes" and "no" trumphs "unknown" if we have more than one jack */ if (cpa == PA_PORT_AVAILABLE_UNKNOWN) diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c index 9149b6dd4..0a115d32e 100644 --- a/src/modules/module-switch-on-port-available.c +++ b/src/modules/module-switch-on-port-available.c @@ -120,6 +120,9 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port pa_source *source; pa_bool_t is_active_profile, is_active_port; + if (port->available == PA_PORT_AVAILABLE_UNKNOWN) + return PA_HOOK_OK; + pa_log_debug("finding port %s", port->name); PA_IDXSET_FOREACH(card, c->cards, state) diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c index 30fb02529..50c99b8f2 100644 --- a/src/pulsecore/device-port.c +++ b/src/pulsecore/device-port.c @@ -39,10 +39,11 @@ void pa_device_port_set_available(pa_device_port *p, pa_port_available_t status) if (p->available == status) return; - pa_assert(status != PA_PORT_AVAILABLE_UNKNOWN); +/* pa_assert(status != PA_PORT_AVAILABLE_UNKNOWN); */ p->available = status; - pa_log_debug("Setting port %s to status %s", p->name, status == PA_PORT_AVAILABLE_YES ? "yes" : "no"); + pa_log_debug("Setting port %s to status %s", p->name, status == PA_PORT_AVAILABLE_YES ? "yes" : + status == PA_PORT_AVAILABLE_NO ? "no" : "unknown"); /* Post subscriptions to the card which owns us */ pa_assert_se(core = p->core);