1
Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/gvc/gvc-mixer-control.c
2
===================================================================
3
--- gnome-settings-daemon-3.8.6.1.orig/plugins/media-keys/gvc/gvc-mixer-control.c 2014-01-08 14:01:19.776910908 +0100
4
+++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/gvc/gvc-mixer-control.c 2014-01-08 14:01:19.772910908 +0100
13
@@ -2150,6 +2151,10 @@
16
g_signal_emit (G_OBJECT (control),
20
+ g_signal_emit (G_OBJECT (control),
24
@@ -3206,6 +3211,14 @@
26
g_cclosure_marshal_VOID__UINT,
27
G_TYPE_NONE, 1, G_TYPE_UINT);
28
+ signals [CARD_INFO] =
29
+ g_signal_new ("card-info",
30
+ G_TYPE_FROM_CLASS (klass),
34
+ g_cclosure_marshal_VOID__POINTER,
35
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
36
signals [CARD_ADDED] =
37
g_signal_new ("card-added",
38
G_TYPE_FROM_CLASS (klass),
39
Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/pa-backend.c
40
===================================================================
41
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
42
+++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/pa-backend.c 2014-01-08 14:01:19.772910908 +0100
47
+#include <alsa/asoundlib.h>
48
+#include <pulse/pulseaudio.h>
49
+#include <pulse/glib-mainloop.h>
50
+//#include <gtk/gtk.h>
52
+#include "pa-backend.h"
55
+// pa_glib_mainloop *mainloop;
56
+// pa_mainloop_api *ml_api;
57
+// pa_defer_event *defer_event;
58
+ pa_context *context;
59
+ pa_backend_cb dialog_cb;
61
+ bool headset_plugged_in;
62
+ bool has_headsetmic;
63
+ bool has_headphonemic;
65
+ const char *sink_port_name_to_set;
66
+ const char *source_port_name_to_set;
69
+void pa_backend_set_context(pa_backend *p, const pa_context *c)
76
+static void context_state_callback(pa_context *c, void *userdata) {
77
+ switch (pa_context_get_state(c)) {
78
+ case PA_CONTEXT_READY:
79
+ fprintf(stderr, "Connection established!\n");
83
+ case PA_CONTEXT_TERMINATED:
84
+ case PA_CONTEXT_FAILED:
85
+ fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c)));
94
+static void call_dialog(pa_mainloop_api *a, pa_defer_event *e, void *userdata)
96
+ pa_backend *p = userdata;
98
+ fprintf(stderr, "Deferred event\n");
99
+ a->defer_enable(e, 0);
102
+ if (p->headset_plugged_in)
103
+ p->dialog_cb(p->has_headsetmic, p->has_headphonemic);
105
+ p->dialog_cb(false, false);
108
+pa_backend *pa_backend_new()
110
+ pa_backend *p = calloc(1, sizeof(*p));
115
+ p->headset_card = -1;
117
+ if (!(p->mainloop = pa_glib_mainloop_new(NULL))) {
118
+ pa_backend_free(p);
122
+ p->ml_api = pa_glib_mainloop_get_api(p->mainloop);
123
+ if (!(p->context = pa_context_new(p->ml_api, "what-did-you-plug-in"))) {
124
+ pa_backend_free(p);
128
+ if (pa_context_connect(p->context, NULL, 0, NULL) < 0) {
129
+ fprintf(stderr, "pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(p->context)));
130
+ pa_backend_free(p);
134
+ fprintf(stderr, "Connecting to PulseAudio...\n");
135
+ pa_context_set_state_callback(p->context, context_state_callback, p);
137
+ pa_context_set_state_callback(p->context, NULL, NULL);
139
+ if (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
140
+ pa_backend_free(p);
144
+ p->defer_event = p->ml_api->defer_new(p->ml_api, call_dialog, p);
145
+ if (!p->defer_event) {
146
+ pa_backend_free(p);
149
+ p->ml_api->defer_enable(p->defer_event, 0);
154
+typedef struct headset_ports {
155
+ const pa_card_port_info *headphones, *headsetmic, *headphonemic;
158
+static headset_ports get_headset_ports(const pa_card_info *c)
160
+ headset_ports h = {NULL, NULL, NULL};
162
+ for (i = 0; i < c->n_ports; i++) {
163
+ pa_card_port_info *p = c->ports[i];
164
+ if (!strcmp(p->name, "analog-output-headphones"))
166
+ else if (!strcmp(p->name, "analog-input-microphone-headset"))
168
+ else if (!strcmp(p->name, "analog-input-microphone"))
169
+ h.headphonemic = p;
174
+static bool verify_alsa_card(int cardindex, bool *headsetmic, bool *headphonemic)
178
+ snd_ctl_elem_id_t *id;
181
+ *headsetmic = false;
182
+ *headphonemic = false;
184
+ snprintf(ctlstr, sizeof(ctlstr), "hw:%i", cardindex);
185
+ if ((err = snd_hctl_open(&hctl, ctlstr, 0)) < 0) {
186
+ fprintf(stderr, "snd_hctl_open failed: %s", snd_strerror(err));
190
+ if ((err = snd_hctl_load(hctl)) < 0) {
191
+ fprintf(stderr, "snd_hctl_load failed: %s", snd_strerror(err));
192
+ snd_hctl_close(hctl);
196
+ snd_ctl_elem_id_alloca(&id);
198
+ snd_ctl_elem_id_clear(id);
199
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
200
+ snd_ctl_elem_id_set_name(id, "Headphone Mic Jack");
201
+ if (snd_hctl_find_elem(hctl, id))
202
+ *headphonemic = true;
204
+ snd_ctl_elem_id_clear(id);
205
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
206
+ snd_ctl_elem_id_set_name(id, "Headset Mic Phantom Jack");
207
+ if (snd_hctl_find_elem(hctl, id))
208
+ *headsetmic = true;
210
+ if (*headphonemic) {
211
+ snd_ctl_elem_id_clear(id);
212
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
213
+ snd_ctl_elem_id_set_name(id, "Headset Mic Jack");
214
+ if (snd_hctl_find_elem(hctl, id))
215
+ *headsetmic = true;
218
+ snd_hctl_close(hctl);
219
+ return *headsetmic || *headphonemic;
222
+void pa_backend_card_changed(pa_backend *p, const pa_card_info *i)
225
+ bool start_dialog = false, stop_dialog = false;
227
+ h = get_headset_ports(i);
229
+ if (!h.headphones || (!h.headsetmic && !h.headphonemic))
230
+ return; /* Not a headset jack */
232
+ if (p->headset_card != (int) i->index) {
235
+ const char *s = pa_proplist_gets(i->proplist, "alsa.card");
238
+ cardindex = strtol(s, NULL, 10);
239
+ if (cardindex == 0 && strcmp(s, "0"))
242
+ fprintf(stderr, "%s: has headphones %d headsetmic %d headphonemic %d\n", i->name, h.headphones ? 1 : 0, h.headsetmic ? 1 : 0, h.headphonemic ? 1 : 0);
243
+ if (!verify_alsa_card(cardindex, &hsmic, &hpmic))
245
+ fprintf(stderr, "Alsa: headset mic %d, headphone mic %d\n", hsmic, hpmic);
247
+ p->headset_card = (int) i->index;
248
+ p->has_headsetmic = hsmic && h.headsetmic;
249
+ p->has_headphonemic = hpmic && h.headphonemic;
252
+ start_dialog = p->dialog_cb && (h.headphones->available != PA_PORT_AVAILABLE_NO) &&
253
+ !p->headset_plugged_in;
254
+ stop_dialog = p->dialog_cb && (h.headphones->available == PA_PORT_AVAILABLE_NO) &&
255
+ p->headset_plugged_in;
258
+ fprintf(stderr, "was plugged in %d, is plugged in %d\n", (int) p->headset_plugged_in, (int) (h.headphones->available != PA_PORT_AVAILABLE_NO));
260
+ p->headset_plugged_in = h.headphones->available != PA_PORT_AVAILABLE_NO;
263
+ p->dialog_cb(p->has_headsetmic, p->has_headphonemic);
264
+ else if (stop_dialog)
265
+ p->dialog_cb(false, false);
268
+bool pa_backend_has_headset_jack(pa_backend *p)
272
+ p->headset_card = -1;
273
+ o = pa_context_get_card_info_list(p->context, card_info_cb, p);
276
+ while (pa_operation_get_state(o) == PA_OPERATION_RUNNING)
278
+ pa_operation_unref(o);
281
+ return p->headset_card != -1;
284
+static void event_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata)
287
+ pa_backend *p = userdata;
288
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
290
+ if (idx != p->headset_card)
293
+ o = pa_context_get_card_info_by_index(c, idx, card_info_cb, p);
295
+ pa_operation_unref(o);
298
+void pa_backend_start_listening(pa_backend *p, pa_backend_cb cb)
302
+ pa_context_set_subscribe_callback(p->context, event_cb, p);
303
+ o = pa_context_subscribe(p->context, PA_SUBSCRIPTION_MASK_CARD, NULL, p);
305
+ pa_operation_unref(o);
309
+static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
311
+ pa_backend *p = userdata;
314
+ const char *s = p->sink_port_name_to_set;
320
+ if (i->card != p->headset_card)
323
+ if (i->active_port && !strcmp(i->active_port->name, s))
326
+ for (j = 0; j < i->n_ports; j++)
327
+ if (!strcmp(i->ports[j]->name, s))
330
+ if (j >= i->n_ports)
333
+ o = pa_context_set_sink_port_by_index(c, i->index, s, NULL, NULL);
335
+ pa_operation_unref(o);
338
+static void source_info_cb(pa_context *c, const pa_source_info *i, int eol, void *userdata)
340
+ pa_backend *p = userdata;
343
+ const char *s = p->source_port_name_to_set;
349
+ if (i->card != p->headset_card)
352
+ if (i->active_port && !strcmp(i->active_port->name, s))
355
+ for (j = 0; j < i->n_ports; j++)
356
+ if (!strcmp(i->ports[j]->name, s))
359
+ if (j >= i->n_ports)
362
+ o = pa_context_set_source_port_by_index(c, i->index, s, NULL, NULL);
364
+ pa_operation_unref(o);
368
+void pa_backend_set_port(pa_backend *p, const char *portname, bool is_output)
373
+ p->sink_port_name_to_set = portname;
374
+ o = pa_context_get_sink_info_list(p->context, sink_info_cb, p);
377
+ p->source_port_name_to_set = portname;
378
+ o = pa_context_get_source_info_list(p->context, source_info_cb, p);
382
+ pa_operation_unref(o);
387
+void pa_backend_free(pa_backend *p)
392
+ if (p->defer_event) {
393
+ p->ml_api->defer_free(p->defer_event);
397
+ pa_context_disconnect(p->context);
398
+ pa_context_unref(p->context);
402
+ pa_glib_mainloop_free(p->mainloop);
407
Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/pa-backend.h
408
===================================================================
409
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
410
+++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/pa-backend.h 2014-01-08 14:01:19.772910908 +0100
412
+#ifndef __PA_BACKEND_H__
413
+#define __PA_BACKEND_H__
415
+#include <stdbool.h>
416
+#include <pulse/pulseaudio.h>
418
+typedef struct pa_backend pa_backend;
420
+typedef void (*pa_backend_cb)(bool headsetmic, bool headphonemic);
422
+pa_backend *pa_backend_new();
424
+//bool pa_backend_has_headset_jack(pa_backend *p);
426
+void pa_backend_free(pa_backend *p);
428
+void pa_backend_card_changed(pa_backend *p, const pa_card_info *i);
430
+void pa_backend_set_context(pa_backend *p, const pa_context *c);
432
+//void pa_backend_start_listening(pa_backend *p, pa_backend_cb cb);
434
+void pa_backend_set_port(pa_backend *p, const char *portname, bool is_output);
438
Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/Makefile.am
439
===================================================================
440
--- gnome-settings-daemon-3.8.6.1.orig/plugins/media-keys/Makefile.am 2014-01-08 14:01:19.776910908 +0100
441
+++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/Makefile.am 2014-01-08 14:02:00.232910193 +0100
443
$(srcdir)/org.gnome.ShellKeyGrabber.xml
445
libmedia_keys_la_SOURCES = \
446
+ what-did-you-plug-in/pa-backend.c \
447
gsd-media-keys-plugin.c \
448
gsd-media-keys-manager.h \
449
gsd-media-keys-manager.c \
451
-I$(top_srcdir)/gnome-settings-daemon \
452
-I$(top_srcdir)/plugins/common \
453
-I$(top_srcdir)/plugins/media-keys/gvc \
454
+ -I$(top_srcdir)/plugins/media-keys/what-did-you-plug-in \
455
-DBINDIR=\"$(bindir)\" \
456
-DPIXMAPDIR=\""$(pkgdatadir)"\" \
457
-DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
459
-I$(top_srcdir)/gnome-settings-daemon \
460
-I$(top_srcdir)/plugins/common \
461
-I$(top_srcdir)/plugins/media-keys/gvc \
462
+ -I$(top_srcdir)/plugins/media-keys/what-did-you-plug-in \
463
-DBINDIR=\"$(bindir)\" \
464
-DPIXMAPDIR=\""$(pkgdatadir)"\" \
465
-DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
466
Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/gsd-media-keys-manager.c
467
===================================================================
468
--- gnome-settings-daemon-3.8.6.1.orig/plugins/media-keys/gsd-media-keys-manager.c 2014-01-08 14:01:19.776910908 +0100
469
+++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/gsd-media-keys-manager.c 2014-01-08 14:01:19.772910908 +0100
471
#include <pulse/pulseaudio.h>
472
#include "gvc-mixer-control.h"
473
#include "gvc-mixer-sink.h"
474
+#include "pa-backend.h"
476
#include <libnotify/notify.h>
479
/* Legacy keygrabber stuff */
480
guint have_legacy_keygrabber;
482
+ /* What did you plug in dialog */
483
+ pa_backend *wdypi_pa_backend;
486
static void gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass);
487
@@ -2683,6 +2686,14 @@
491
+on_control_card_info_updated (GvcMixerControl *control,
492
+ gpointer card_info,
493
+ GsdMediaKeysManager *manager)
495
+ pa_backend_card_changed (manager->priv->wdypi_pa_backend, card_info);
499
initialize_volume_handler (GsdMediaKeysManager *manager)
501
/* initialise Volume handler
502
@@ -2695,6 +2706,8 @@
504
manager->priv->volume = gvc_mixer_control_new ("GNOME Volume Control Media Keys");
506
+ manager->priv->wdypi_pa_backend = pa_backend_new();
508
g_signal_connect (manager->priv->volume,
510
G_CALLBACK (on_control_state_changed),
511
@@ -2711,6 +2724,10 @@
513
G_CALLBACK (on_control_stream_removed),
515
+ g_signal_connect (manager->priv->volume,
517
+ G_CALLBACK (on_control_card_info_updated),
520
gvc_mixer_control_open (manager->priv->volume);
522
@@ -3035,6 +3052,11 @@
523
gdk_error_trap_pop_ignored ();
526
+ if (manager->priv->wdypi_pa_backend) {
527
+ pa_backend_free (manager->priv->wdypi_pa_backend);
528
+ manager->priv->wdypi_pa_backend = NULL;
531
if (priv->grab_cancellable != NULL) {
532
g_cancellable_cancel (priv->grab_cancellable);
533
g_clear_object (&priv->grab_cancellable);
534
Index: gnome-settings-daemon-3.8.6.1/configure.ac
535
===================================================================
536
--- gnome-settings-daemon-3.8.6.1.orig/configure.ac 2014-01-08 14:01:19.776910908 +0100
537
+++ gnome-settings-daemon-3.8.6.1/configure.ac 2014-01-08 14:01:19.772910908 +0100
539
dnl - media-keys plugin stuff
540
dnl ---------------------------------------------------------------------------
542
-PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra-gtk3 libnotify])
543
+PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra-gtk3 libnotify alsa])
544
PKG_CHECK_MODULES(GVC, [gobject-2.0 libpulse >= $PA_REQUIRED_VERSION libpulse-mainloop-glib >= $PA_REQUIRED_VERSION])
545
AM_CONDITIONAL(HAVE_INTROSPECTION, false)