summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gvc-mixer-control.c129
1 files changed, 110 insertions, 19 deletions
diff --git a/gvc-mixer-control.c b/gvc-mixer-control.c
index a43ae1d..2dc2cb7 100644
--- a/gvc-mixer-control.c
+++ b/gvc-mixer-control.c
@@ -62,6 +62,7 @@ struct GvcMixerControlPrivate
pa_glib_mainloop *pa_mainloop;
pa_mainloop_api *pa_api;
pa_context *pa_context;
+ guint server_protocol_version;
int n_outstanding;
guint reconnect_id;
char *name;
@@ -104,6 +105,11 @@ struct GvcMixerControlPrivate
gboolean has_headsetmic;
gboolean has_headphonemic;
gboolean headset_plugged_in;
+ char *headphones_name;
+ char *headsetmic_name;
+ char *headphonemic_name;
+ char *internalspk_name;
+ char *internalmic_name;
#endif /* HAVE_ALSA */
GvcMixerControlState state;
@@ -2173,6 +2179,19 @@ source_info_cb (pa_context *c,
s = data->port_name_to_set;
+ for (j = 0; j < i->n_ports; j++) {
+ if (g_str_equal (i->ports[j]->name, s)) {
+ o = pa_context_set_default_source (c,
+ i->name,
+ NULL,
+ NULL);
+ if (o == NULL) {
+ g_warning ("pa_context_set_default_source() failed");
+ return;
+ }
+ }
+ }
+
if (i->active_port && strcmp (i->active_port->name, s) == 0)
return;
@@ -2196,6 +2215,9 @@ gvc_mixer_control_set_port_status_for_headset (GvcMixerControl *control,
pa_operation *o;
PortStatusData *data;
+ if (port_name == NULL)
+ return;
+
data = g_new0 (PortStatusData, 1);
data->port_name_to_set = g_strdup (port_name);
data->headset_card = id;
@@ -2209,6 +2231,18 @@ gvc_mixer_control_set_port_status_for_headset (GvcMixerControl *control,
}
#endif /* HAVE_ALSA */
+static void
+free_priv_port_names (GvcMixerControl *control)
+{
+#ifdef HAVE_ALSA
+ g_clear_pointer (&control->priv->headphones_name, g_free);
+ g_clear_pointer (&control->priv->headsetmic_name, g_free);
+ g_clear_pointer (&control->priv->headphonemic_name, g_free);
+ g_clear_pointer (&control->priv->internalspk_name, g_free);
+ g_clear_pointer (&control->priv->internalmic_name, g_free);
+#endif
+}
+
void
gvc_mixer_control_set_headset_port (GvcMixerControl *control,
guint id,
@@ -2219,16 +2253,16 @@ gvc_mixer_control_set_headset_port (GvcMixerControl *control,
#ifdef HAVE_ALSA
switch (choice) {
case GVC_HEADSET_PORT_CHOICE_HEADPHONES:
- gvc_mixer_control_set_port_status_for_headset (control, id, "analog-output-headphones", TRUE);
- gvc_mixer_control_set_port_status_for_headset (control, id, "analog-input-internal-mic", FALSE);
+ gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->headphones_name, TRUE);
+ gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->internalmic_name, FALSE);
break;
case GVC_HEADSET_PORT_CHOICE_HEADSET:
- gvc_mixer_control_set_port_status_for_headset (control, id, "analog-output-headphones", TRUE);
- gvc_mixer_control_set_port_status_for_headset (control, id, "analog-input-headset-mic", FALSE);
+ gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->headphones_name, TRUE);
+ gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->headsetmic_name, FALSE);
break;
case GVC_HEADSET_PORT_CHOICE_MIC:
- gvc_mixer_control_set_port_status_for_headset (control, id, "analog-output-speaker", TRUE);
- gvc_mixer_control_set_port_status_for_headset (control, id, "analog-input-headphone-mic", FALSE);
+ gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->internalspk_name, TRUE);
+ gvc_mixer_control_set_port_status_for_headset (control, id, control->priv->headphonemic_name, FALSE);
break;
case GVC_HEADSET_PORT_CHOICE_NONE:
default:
@@ -2244,16 +2278,24 @@ typedef struct {
const pa_card_port_info *headphones;
const pa_card_port_info *headsetmic;
const pa_card_port_info *headphonemic;
+ const pa_card_port_info *internalmic;
+ const pa_card_port_info *internalspk;
} headset_ports;
/*
TODO: Check if we still need this with the changed PA port names
- In PulseAudio ports will show up with the following names:
+ In PulseAudio without ucm, ports will show up with the following names:
Headphones - analog-output-headphones
Headset mic - analog-input-headset-mic (was: analog-input-microphone-headset)
Jack in mic-in mode - analog-input-headphone-mic (was: analog-input-microphone)
+ In PulseAudio with ucm, the ports name depends on the ucm, with the current
+ ucm2, the ports will show up with the following names:
+ Headphones - [Out] Headphone
+ Headset mic - [In] Headset
+ Jack in mic-in mode - [In] Mic2
+
However, since regular mics also show up as analog-input-microphone,
we need to check for certain controls on alsa mixer level too, to know
if we deal with a separate mic jack, or a multi-function jack with a
@@ -2268,10 +2310,18 @@ typedef struct {
Headset Mic Jack - indicates headset jack where hardware can distinguish
between headphones and headsets. There is no use popping up a dialog in
this case, unless we already need to do this for the mic-in mode.
+
+ From the PA_PROCOTOL_VERSION=34, The device_port structure adds 2 members
+ available_group and type, with the help of these 2 members, we could
+ consolidate the port checking and port setting for non-ucm and with-ucm
+ cases.
*/
+#define GET_PORT_NAME(x) (x ? g_strdup (x->name) : NULL)
+
static headset_ports *
-get_headset_ports (const pa_card_info *c)
+get_headset_ports (GvcMixerControl *control,
+ const pa_card_info *c)
{
headset_ports *h;
guint i;
@@ -2280,13 +2330,42 @@ get_headset_ports (const pa_card_info *c)
for (i = 0; i < c->n_ports; i++) {
pa_card_port_info *p = c->ports[i];
-
- if (strcmp (p->name, "analog-output-headphones") == 0)
- h->headphones = p;
- else if (strcmp (p->name, "analog-input-headset-mic") == 0)
- h->headsetmic = p;
- else if (strcmp(p->name, "analog-input-headphone-mic") == 0)
- h->headphonemic = p;
+ if (control->priv->server_protocol_version < 34) {
+ if (g_str_equal (p->name, "analog-output-headphones"))
+ h->headphones = p;
+ else if (g_str_equal (p->name, "analog-input-headset-mic"))
+ h->headsetmic = p;
+ else if (g_str_equal (p->name, "analog-input-headphone-mic"))
+ h->headphonemic = p;
+ else if (g_str_equal (p->name, "analog-input-internal-mic"))
+ h->internalmic = p;
+ else if (g_str_equal (p->name, "analog-output-speaker"))
+ h->internalspk = p;
+ } else {
+#if (PA_PROTOCOL_VERSION >= 34)
+ if (p->available_group && strcmp (p->available_group, "Headphone Mic") == 0) {
+ if (p->type == PA_DEVICE_PORT_TYPE_HEADPHONES)
+ h->headphones = p;
+ else if (p->type == PA_DEVICE_PORT_TYPE_HEADSET)
+ h->headsetmic = p;
+ else if (p->type == PA_DEVICE_PORT_TYPE_MIC)
+ h->headphonemic = p;
+ } else if (p->type == PA_DEVICE_PORT_TYPE_SPEAKER) {
+ if (strcmp (p->name, "analog-output-speaker") == 0 ||
+ strcmp (p->name, "[Out] Speaker") == 0 )
+ h->internalspk = p;
+ } else if (p->type == PA_DEVICE_PORT_TYPE_MIC) {
+ if (strcmp (p->name, "analog-input-internal-mic") == 0 ||
+ strcmp (p->name, "[In] Mic1") == 0 )
+ h->internalmic = p;
+ }
+#else
+ g_warning_once ("libgnome-volume-control running against PulseAudio %u, "
+ "but compiled against older %d, report a bug to your distribution",
+ control->priv->server_protocol_version,
+ PA_PROTOCOL_VERSION);
+#endif
+ }
}
return h;
}
@@ -2353,7 +2432,7 @@ check_audio_device_selection_needed (GvcMixerControl *control,
start_dialog = FALSE;
stop_dialog = FALSE;
- h = get_headset_ports (info);
+ h = get_headset_ports (control, info);
if (!h->headphones ||
(!h->headsetmic && !h->headphonemic)) {
@@ -2363,7 +2442,8 @@ check_audio_device_selection_needed (GvcMixerControl *control,
if (control->priv->headset_card != (int) info->index) {
int cardindex;
- gboolean hsmic, hpmic;
+ gboolean hsmic = TRUE;
+ gboolean hpmic = TRUE;
const char *s;
s = pa_proplist_gets (info->proplist, "alsa.card");
@@ -2374,8 +2454,10 @@ check_audio_device_selection_needed (GvcMixerControl *control,
if (cardindex == 0 && strcmp(s, "0") != 0)
goto out;
- if (!verify_alsa_card(cardindex, &hsmic, &hpmic))
- goto out;
+ if (control->priv->server_protocol_version < 34) {
+ if (!verify_alsa_card(cardindex, &hsmic, &hpmic))
+ goto out;
+ }
control->priv->headset_card = info->index;
control->priv->has_headsetmic = hsmic && h->headsetmic;
@@ -2386,6 +2468,12 @@ check_audio_device_selection_needed (GvcMixerControl *control,
}
control->priv->headset_plugged_in = h->headphones->available != PA_PORT_AVAILABLE_NO;
+ free_priv_port_names (control);
+ control->priv->headphones_name = GET_PORT_NAME(h->headphones);
+ control->priv->headsetmic_name = GET_PORT_NAME(h->headsetmic);
+ control->priv->headphonemic_name = GET_PORT_NAME(h->headphonemic);
+ control->priv->internalspk_name = GET_PORT_NAME(h->internalspk);
+ control->priv->internalmic_name = GET_PORT_NAME(h->internalmic);
if (!start_dialog &&
!stop_dialog)
@@ -3268,6 +3356,7 @@ gvc_mixer_control_ready (GvcMixerControl *control)
req_update_sink_input_info (control, -1);
req_update_source_output_info (control, -1);
+ control->priv->server_protocol_version = pa_context_get_server_protocol_version (control->priv->pa_context);
control->priv->n_outstanding = 6;
@@ -3350,6 +3439,7 @@ idle_reconnect (gpointer data)
if (control->priv->pa_context) {
pa_context_unref (control->priv->pa_context);
control->priv->pa_context = NULL;
+ control->priv->server_protocol_version = 0;
gvc_mixer_new_pa_context (control);
}
@@ -3503,6 +3593,7 @@ gvc_mixer_control_dispose (GObject *object)
control->priv->ui_inputs = NULL;
}
+ free_priv_port_names (control);
G_OBJECT_CLASS (gvc_mixer_control_parent_class)->dispose (object);
}