Merge lp:~diwic/gnome-settings-daemon/what-did-you-plug-in into lp:~ubuntu-desktop/gnome-settings-daemon/ubuntu

Proposed by David Henningsson
Status: Superseded
Proposed branch: lp:~diwic/gnome-settings-daemon/what-did-you-plug-in
Merge into: lp:~ubuntu-desktop/gnome-settings-daemon/ubuntu
Diff against target: 713 lines (+655/-1) (has conflicts)
5 files modified
debian/changelog (+9/-0)
debian/control (+2/-1)
debian/control.in (+1/-0)
debian/patches/series (+4/-0)
debian/patches/what-did-you-plug-in.patch (+639/-0)
Text conflict in debian/changelog
Text conflict in debian/patches/series
To merge this branch: bzr merge lp:~diwic/gnome-settings-daemon/what-did-you-plug-in
Reviewer Review Type Date Requested Status
Sebastien Bacher Needs Fixing
Review via email: mp+205234@code.launchpad.net

This proposal supersedes a proposal from 2014-02-04.

This proposal has been superseded by a proposal from 2014-02-15.

Description of the change

Hi,

Here comes the implementation of the "what did you plug in"-dialog for 14.04. While I'd like some more real-world testing before the actual merge happens (I can see to that), in parallel it would be good with some code focused review so I don't spend time polishing things if there's something with the design that you think is bad.

To post a comment you must log in.
Revision history for this message
David Henningsson (diwic) wrote : Posted in a previous version of this proposal

Hrm, looking at the diff below I probably did something wrong, like submitting against the wrong branch or something. Anyway, it's the file debian/patches/what-did-you-plug-in.patch in the lp:~diwic/gnome-settings-daemon/what-did-you-plug-in branch that should be looked at.

Revision history for this message
Sebastien Bacher (seb128) wrote : Posted in a previous version of this proposal

@David: can you resubmit it (top right corner of the launchpad page) and change the target vcs to lp:~ubuntu-desktop/gnome-settings-daemon/ubuntu?

Revision history for this message
David Henningsson (diwic) wrote :

Sure, done now. I notice that a new version of g-s-d was released in parallel, but hopefully that won't stop you from looking at the code - I can rebase it on top of the latest g-s-d when we feel ready quality wise.

Revision history for this message
David Henningsson (diwic) wrote :

Btw, I chose to implement it in the media-keys plugin instead of making a new plugin, mostly for efficiency reasons: no need to have two different connections to PulseAudio constantly up, and I save some code because I don't have to reimplement stuff like reconnecting on PA restart and such.

Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks for the work David, some questions/comments:

- is there any easy way to test that? I've tried plugging headphones/a microphone on my laptop but that doesn't trigger the dialog, not sure if you can easily emulate the unknown case? Having a way to display the UI at least would be nice

- we started the transition to unity-settings-daemon, can you retarget your changes against that branch (not distro patch there, it's full source)

- could you explain a bit what the code does? I tried to look at bit at the logic but I don't really know pulseaudio and things like "snd_ctl_elem_id_set_name(id, "Headset Mic Phantom Jack")" look a bit weird to me...

- pa-backend.h has commented functions, do you plan to add those back/use them? if not could you delete the lines rather than commenting them?

- > if (system("gnome-control-center sound") == -1)

better to cal "unity-control-center sound" since we are transitionning to that

- > d->settings_btn = gtk_button_new_with_label(_("Sound Settings..."));

can you replace the "..." by a their utf8 variant "…"?

- the design has a checkbox to store the choice, do you plan to add that?

- you need to list the new sources in po/POTFILES.in so the translatable strings are included in the translation template

review: Needs Fixing
Revision history for this message
Sebastien Bacher (seb128) wrote :

I've tweaked the source to run the UI, some extra comments:

- the "What kind of device did you plug in?" label is centered in the design and left aligned on your version

- the spacing between the Cancel/Sound Settings buttons is non standard

review: Needs Fixing
Revision history for this message
David Henningsson (diwic) wrote :

Hi Seb, thanks for your review! Just a few question before I start fixing the things you said:

> - is there any easy way to test that? I've tried plugging headphones/a microphone on my laptop but that doesn't
> trigger the dialog, not sure if you can easily emulate the unknown case? Having a way to display the UI at least
> would be nice

Do you think adding a local "#define DIALOGTEST" (that would pop up the dialog on any plug in or so) would do? Or do you want something that can be runtime enabled through some switch?

> - we started the transition to unity-settings-daemon, can you retarget your changes against that branch (not distro
> patch there, it's full source)

Sure, is it https://code.launchpad.net/~ubuntu-desktop/unity-greeter/unity-settings-daemon ?

> - the design has a checkbox to store the choice, do you plan to add that?

Because it requires significant additional coding (mostly in sound settings, where you need to be able to revert back to "please ask me"), I was thinking of deferring it to the next cycle, where things have to be rewritten for Qt anyway. Also, this checkbox was not present in the wireframe we got from the design team at one point, so I figured it would be a nice-to-have rather than an absolute requirement. Is that okay with you?

Revision history for this message
Sebastien Bacher (seb128) wrote :

> Do you think adding a local "#define DIALOGTEST" (that would pop up the dialog on any plug in or so) would do? Or do you want something that can be runtime enabled through some switch?

That would be useful, but feel free to skip over that. I basically hacked dialog-window.c to add a main() with gtk_init/gtk_run/call to dialog_create, which was enough to do a local testing

> Sure, is it https://code.launchpad.net/~ubuntu-desktop/unity-greeter/unity-settings-daemon ?

It moved teams for acl reasons, it's now https://code.launchpad.net/~unity-settings-daemon-team/unity-settings-daemon/trunk (or just use lp:unity-settings-daemon)

> Because it requires significant additional coding (mostly in sound settings, where you need to be able to revert back to "please ask me"), I was thinking of deferring it to the next cycle, where things have to be rewritten for Qt anyway. Also, this checkbox was not present in the wireframe we got from the design team at one point, so I figured it would be a nice-to-have rather than an absolute requirement. Is that okay with you?

That seems reasonable to me as well, yes.

Unmerged revisions

454. By David Henningsson

i18n + cleanup

453. By David Henningsson

Fix icons

452. By David Henningsson

and now for some actions...

451. By David Henningsson

Some more work, still unfinished

450. By David Henningsson

WIP, this is just to get the thing to compile

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2014-02-03 16:17:50 +0000
3+++ debian/changelog 2014-02-06 18:04:12 +0000
4@@ -1,3 +1,4 @@
5+<<<<<<< TREE
6 gnome-settings-daemon (3.8.6.1-0ubuntu3) trusty; urgency=medium
7
8 * debian/patches/git_hidpi_scalling.patch:
9@@ -7,6 +8,14 @@
10
11 -- Sebastien Bacher <seb128@ubuntu.com> Mon, 03 Feb 2014 16:17:44 +0000
12
13+=======
14+gnome-settings-daemon (3.8.6.1-0ubuntu3) UNRELEASED; urgency=medium
15+
16+ * What-did-you-plug-in dialog
17+
18+ -- David Henningsson <david.henningsson@canonical.com> Wed, 08 Jan 2014 14:10:30 +0100
19+
20+>>>>>>> MERGE-SOURCE
21 gnome-settings-daemon (3.8.6.1-0ubuntu2) trusty; urgency=low
22
23 * debian/patches/git_xsettings_segfaults.patch:
24
25=== modified file 'debian/control'
26--- debian/control 2013-09-09 14:21:05 +0000
27+++ debian/control 2014-02-06 18:04:12 +0000
28@@ -7,7 +7,7 @@
29 Priority: optional
30 Maintainer: Ubuntu Desktop Team <ubuntu-desktop@lists.ubuntu.com>
31 XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
32-Uploaders: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>, Jeremy Bicha <jbicha@ubuntu.com>
33+Uploaders: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
34 Build-Depends: cdbs,
35 debhelper (>= 9),
36 gnome-pkg-tools,
37@@ -28,6 +28,7 @@
38 gsettings-desktop-schemas-dev (>= 3.7.2.1),
39 libgnome-desktop-3-dev (>= 3.7.90),
40 libpulse-dev (>= 1:2.0),
41+ libasound2-dev,
42 librsvg2-dev (>= 2.36.2),
43 libcanberra-gtk3-dev,
44 libcups2-dev,
45
46=== modified file 'debian/control.in'
47--- debian/control.in 2013-09-09 14:21:05 +0000
48+++ debian/control.in 2014-02-06 18:04:12 +0000
49@@ -24,6 +24,7 @@
50 gsettings-desktop-schemas-dev (>= 3.7.2.1),
51 libgnome-desktop-3-dev (>= 3.7.90),
52 libpulse-dev (>= 1:2.0),
53+ libasound2-dev,
54 librsvg2-dev (>= 2.36.2),
55 libcanberra-gtk3-dev,
56 libcups2-dev,
57
58=== modified file 'debian/patches/series'
59--- debian/patches/series 2014-02-03 16:17:38 +0000
60+++ debian/patches/series 2014-02-06 18:04:12 +0000
61@@ -28,4 +28,8 @@
62 unity-modifier-media-keys.patch
63 ubuntu-lid-open-reset-ideletime.patch
64 git_xsettings_segfaults.patch
65+<<<<<<< TREE
66 git_hidpi_scalling.patch
67+=======
68+what-did-you-plug-in.patch
69+>>>>>>> MERGE-SOURCE
70
71=== added file 'debian/patches/what-did-you-plug-in.patch'
72--- debian/patches/what-did-you-plug-in.patch 1970-01-01 00:00:00 +0000
73+++ debian/patches/what-did-you-plug-in.patch 2014-02-06 18:04:12 +0000
74@@ -0,0 +1,639 @@
75+Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/gvc/gvc-mixer-control.c
76+===================================================================
77+--- gnome-settings-daemon-3.8.6.1.orig/plugins/media-keys/gvc/gvc-mixer-control.c 2014-02-04 13:32:40.805078130 +0100
78++++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/gvc/gvc-mixer-control.c 2014-02-04 13:32:40.797078130 +0100
79+@@ -114,6 +114,7 @@
80+ INPUT_ADDED,
81+ OUTPUT_REMOVED,
82+ INPUT_REMOVED,
83++ CARD_INFO,
84+ LAST_SIGNAL
85+ };
86+
87+@@ -2150,6 +2151,10 @@
88+ }
89+ }
90+ g_signal_emit (G_OBJECT (control),
91++ signals[CARD_INFO],
92++ 0,
93++ info);
94++ g_signal_emit (G_OBJECT (control),
95+ signals[CARD_ADDED],
96+ 0,
97+ info->index);
98+@@ -3206,6 +3211,14 @@
99+ NULL, NULL,
100+ g_cclosure_marshal_VOID__UINT,
101+ G_TYPE_NONE, 1, G_TYPE_UINT);
102++ signals [CARD_INFO] =
103++ g_signal_new ("card-info",
104++ G_TYPE_FROM_CLASS (klass),
105++ G_SIGNAL_RUN_LAST,
106++ 0,
107++ NULL, NULL,
108++ g_cclosure_marshal_VOID__POINTER,
109++ G_TYPE_NONE, 1, G_TYPE_POINTER);
110+ signals [CARD_ADDED] =
111+ g_signal_new ("card-added",
112+ G_TYPE_FROM_CLASS (klass),
113+Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/pa-backend.c
114+===================================================================
115+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
116++++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/pa-backend.c 2014-02-04 13:39:26.137070964 +0100
117+@@ -0,0 +1,235 @@
118++#include <stdlib.h>
119++#include <stdio.h>
120++#include <string.h>
121++#include <alsa/asoundlib.h>
122++#include <pulse/pulseaudio.h>
123++#include <pulse/glib-mainloop.h>
124++
125++#include "pa-backend.h"
126++
127++struct pa_backend {
128++ const pa_context *context;
129++ pa_backend_cb dialog_cb;
130++ void *cb_userdata;
131++ int headset_card;
132++ bool headset_plugged_in;
133++ bool has_headsetmic;
134++ bool has_headphonemic;
135++
136++ const char *sink_port_name_to_set;
137++ const char *source_port_name_to_set;
138++};
139++
140++void pa_backend_set_context(pa_backend *p, const pa_context *c)
141++{
142++ p->context = c;
143++}
144++
145++pa_backend *pa_backend_new(pa_backend_cb cb, void *cb_userdata)
146++{
147++ pa_backend *p = calloc(1, sizeof(*p));
148++
149++ if (!p)
150++ return NULL;
151++
152++ p->headset_card = -1;
153++ p->dialog_cb = cb;
154++ p->cb_userdata = cb_userdata;
155++ return p;
156++}
157++
158++typedef struct headset_ports {
159++ const pa_card_port_info *headphones, *headsetmic, *headphonemic;
160++} headset_ports;
161++
162++static headset_ports get_headset_ports(const pa_card_info *c)
163++{
164++ headset_ports h = {NULL, NULL, NULL};
165++ int i;
166++ for (i = 0; i < c->n_ports; i++) {
167++ pa_card_port_info *p = c->ports[i];
168++ if (!strcmp(p->name, "analog-output-headphones"))
169++ h.headphones = p;
170++ else if (!strcmp(p->name, "analog-input-microphone-headset"))
171++ h.headsetmic = p;
172++ else if (!strcmp(p->name, "analog-input-microphone"))
173++ h.headphonemic = p;
174++ }
175++ return h;
176++}
177++
178++static bool verify_alsa_card(int cardindex, bool *headsetmic, bool *headphonemic)
179++{
180++ char ctlstr[20];
181++ snd_hctl_t *hctl;
182++ snd_ctl_elem_id_t *id;
183++ int err;
184++
185++ *headsetmic = false;
186++ *headphonemic = false;
187++
188++ snprintf(ctlstr, sizeof(ctlstr), "hw:%i", cardindex);
189++ if ((err = snd_hctl_open(&hctl, ctlstr, 0)) < 0) {
190++ g_warning("snd_hctl_open failed: %s", snd_strerror(err));
191++ return false;
192++ }
193++
194++ if ((err = snd_hctl_load(hctl)) < 0) {
195++ g_warning("snd_hctl_load failed: %s", snd_strerror(err));
196++ snd_hctl_close(hctl);
197++ return false;
198++ }
199++
200++ snd_ctl_elem_id_alloca(&id);
201++
202++ snd_ctl_elem_id_clear(id);
203++ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
204++ snd_ctl_elem_id_set_name(id, "Headphone Mic Jack");
205++ if (snd_hctl_find_elem(hctl, id))
206++ *headphonemic = true;
207++
208++ snd_ctl_elem_id_clear(id);
209++ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
210++ snd_ctl_elem_id_set_name(id, "Headset Mic Phantom Jack");
211++ if (snd_hctl_find_elem(hctl, id))
212++ *headsetmic = true;
213++
214++ if (*headphonemic) {
215++ snd_ctl_elem_id_clear(id);
216++ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
217++ snd_ctl_elem_id_set_name(id, "Headset Mic Jack");
218++ if (snd_hctl_find_elem(hctl, id))
219++ *headsetmic = true;
220++ }
221++
222++ snd_hctl_close(hctl);
223++ return *headsetmic || *headphonemic;
224++}
225++
226++void pa_backend_card_changed(pa_backend *p, const pa_card_info *i)
227++{
228++ headset_ports h;
229++ bool start_dialog = false, stop_dialog = false;
230++
231++ h = get_headset_ports(i);
232++
233++ if (!h.headphones || (!h.headsetmic && !h.headphonemic))
234++ return; /* Not a headset jack */
235++
236++ if (p->headset_card != (int) i->index) {
237++ int cardindex = 0;
238++ bool hsmic, hpmic;
239++ const char *s = pa_proplist_gets(i->proplist, "alsa.card");
240++ if (!s)
241++ return;
242++ cardindex = strtol(s, NULL, 10);
243++ if (cardindex == 0 && strcmp(s, "0"))
244++ return;
245++
246++ if (!verify_alsa_card(cardindex, &hsmic, &hpmic))
247++ return;
248++
249++ p->headset_card = (int) i->index;
250++ p->has_headsetmic = hsmic && h.headsetmic;
251++ p->has_headphonemic = hpmic && h.headphonemic;
252++ }
253++ else {
254++ start_dialog = p->dialog_cb && (h.headphones->available != PA_PORT_AVAILABLE_NO) &&
255++ !p->headset_plugged_in;
256++ stop_dialog = p->dialog_cb && (h.headphones->available == PA_PORT_AVAILABLE_NO) &&
257++ p->headset_plugged_in;
258++ }
259++
260++
261++ p->headset_plugged_in = h.headphones->available != PA_PORT_AVAILABLE_NO;
262++
263++ if (start_dialog)
264++ p->dialog_cb(p->has_headsetmic, p->has_headphonemic, p->cb_userdata);
265++ else if (stop_dialog)
266++ p->dialog_cb(false, false, p->cb_userdata);
267++}
268++
269++static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
270++{
271++ pa_backend *p = userdata;
272++ pa_operation *o;
273++ int j;
274++ const char *s = p->sink_port_name_to_set;
275++
276++ if (eol)
277++ return;
278++
279++ if (i->card != p->headset_card)
280++ return;
281++
282++ if (i->active_port && !strcmp(i->active_port->name, s))
283++ return;
284++
285++ for (j = 0; j < i->n_ports; j++)
286++ if (!strcmp(i->ports[j]->name, s))
287++ break;
288++
289++ if (j >= i->n_ports)
290++ return;
291++
292++ o = pa_context_set_sink_port_by_index(c, i->index, s, NULL, NULL);
293++ if (o)
294++ pa_operation_unref(o);
295++}
296++
297++static void source_info_cb(pa_context *c, const pa_source_info *i, int eol, void *userdata)
298++{
299++ pa_backend *p = userdata;
300++ pa_operation *o;
301++ int j;
302++ const char *s = p->source_port_name_to_set;
303++
304++ if (eol)
305++ return;
306++
307++ if (i->card != p->headset_card)
308++ return;
309++
310++ if (i->active_port && !strcmp(i->active_port->name, s))
311++ return;
312++
313++ for (j = 0; j < i->n_ports; j++)
314++ if (!strcmp(i->ports[j]->name, s))
315++ break;
316++
317++ if (j >= i->n_ports)
318++ return;
319++
320++ o = pa_context_set_source_port_by_index(c, i->index, s, NULL, NULL);
321++ if (o)
322++ pa_operation_unref(o);
323++}
324++
325++
326++void pa_backend_set_port(pa_backend *p, const char *portname, bool is_output)
327++{
328++ pa_operation *o;
329++
330++ if (is_output) {
331++ p->sink_port_name_to_set = portname;
332++ o = pa_context_get_sink_info_list(p->context, sink_info_cb, p);
333++ }
334++ else {
335++ p->source_port_name_to_set = portname;
336++ o = pa_context_get_source_info_list(p->context, source_info_cb, p);
337++ }
338++
339++ if (o) {
340++ pa_operation_unref(o);
341++ }
342++}
343++
344++
345++void pa_backend_free(pa_backend *p)
346++{
347++ if (!p)
348++ return;
349++
350++ free(p);
351++}
352++
353+Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/pa-backend.h
354+===================================================================
355+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
356++++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/pa-backend.h 2014-02-04 13:32:40.801078130 +0100
357+@@ -0,0 +1,26 @@
358++#ifndef __PA_BACKEND_H__
359++#define __PA_BACKEND_H__
360++
361++#include <stdbool.h>
362++#include <pulse/pulseaudio.h>
363++
364++typedef struct pa_backend pa_backend;
365++
366++typedef void (*pa_backend_cb)(bool headsetmic, bool headphonemic, void *userdata);
367++
368++pa_backend *pa_backend_new(pa_backend_cb cb, void *cb_userdata);
369++
370++//bool pa_backend_has_headset_jack(pa_backend *p);
371++
372++void pa_backend_free(pa_backend *p);
373++
374++void pa_backend_card_changed(pa_backend *p, const pa_card_info *i);
375++
376++void pa_backend_set_context(pa_backend *p, const pa_context *c);
377++
378++//void pa_backend_start_listening(pa_backend *p, pa_backend_cb cb);
379++
380++void pa_backend_set_port(pa_backend *p, const char *portname, bool is_output);
381++
382++
383++#endif
384+Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/Makefile.am
385+===================================================================
386+--- gnome-settings-daemon-3.8.6.1.orig/plugins/media-keys/Makefile.am 2014-02-04 13:32:40.805078130 +0100
387++++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/Makefile.am 2014-02-04 13:32:40.801078130 +0100
388+@@ -29,6 +29,8 @@
389+ $(srcdir)/org.gnome.ShellKeyGrabber.xml
390+
391+ libmedia_keys_la_SOURCES = \
392++ what-did-you-plug-in/pa-backend.c \
393++ what-did-you-plug-in/dialog-window.c \
394+ gsd-media-keys-plugin.c \
395+ gsd-media-keys-manager.h \
396+ gsd-media-keys-manager.c \
397+@@ -44,6 +46,7 @@
398+ -I$(top_srcdir)/gnome-settings-daemon \
399+ -I$(top_srcdir)/plugins/common \
400+ -I$(top_srcdir)/plugins/media-keys/gvc \
401++ -I$(top_srcdir)/plugins/media-keys/what-did-you-plug-in \
402+ -DBINDIR=\"$(bindir)\" \
403+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
404+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
405+@@ -87,6 +90,7 @@
406+ -I$(top_srcdir)/gnome-settings-daemon \
407+ -I$(top_srcdir)/plugins/common \
408+ -I$(top_srcdir)/plugins/media-keys/gvc \
409++ -I$(top_srcdir)/plugins/media-keys/what-did-you-plug-in \
410+ -DBINDIR=\"$(bindir)\" \
411+ -DPIXMAPDIR=\""$(pkgdatadir)"\" \
412+ -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \
413+Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/gsd-media-keys-manager.c
414+===================================================================
415+--- gnome-settings-daemon-3.8.6.1.orig/plugins/media-keys/gsd-media-keys-manager.c 2014-02-04 13:32:40.805078130 +0100
416++++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/gsd-media-keys-manager.c 2014-02-04 13:41:02.985069252 +0100
417+@@ -60,7 +60,10 @@
418+ #include <canberra.h>
419+ #include <pulse/pulseaudio.h>
420+ #include "gvc-mixer-control.h"
421++#include "gvc-mixer-control-private.h"
422+ #include "gvc-mixer-sink.h"
423++#include "pa-backend.h"
424++#include "dialog-window.h"
425+
426+ #include <libnotify/notify.h>
427+
428+@@ -213,6 +216,8 @@
429+ /* Legacy keygrabber stuff */
430+ guint have_legacy_keygrabber;
431+
432++ /* What did you plug in dialog */
433++ pa_backend *wdypi_pa_backend;
434+ };
435+
436+ static void gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass);
437+@@ -2683,6 +2688,64 @@
438+ }
439+
440+ static void
441++on_control_card_info_updated (GvcMixerControl *control,
442++ gpointer card_info,
443++ GsdMediaKeysManager *manager)
444++{
445++ pa_backend_card_changed (manager->priv->wdypi_pa_backend, card_info);
446++}
447++
448++
449++static void
450++launch_sound_settings()
451++{
452++ if (fork() != 0)
453++ return;
454++
455++ /* Child process */
456++ if (system("gnome-control-center sound") == -1)
457++ fprintf(stderr, "Failed to launch sound settings.\n");
458++ exit(0);
459++}
460++
461++static void
462++on_wdypi_action (int action, void *userdata)
463++{
464++ GsdMediaKeysManager *manager = userdata;
465++ pa_backend *pb = manager->priv->wdypi_pa_backend;
466++
467++ pa_backend_set_context(pb, gvc_mixer_control_get_pa_context(manager->priv->volume));
468++
469++ switch (action) {
470++ case WDYPI_DIALOG_SOUND_SETTINGS:
471++ launch_sound_settings();
472++ break;
473++ case WDYPI_DIALOG_HEADPHONES:
474++ pa_backend_set_port(pb, "analog-output-headphones", true);
475++ pa_backend_set_port(pb, "analog-input-microphone-internal", false);
476++ break;
477++ case WDYPI_DIALOG_HEADSET:
478++ pa_backend_set_port(pb, "analog-output-headphones", true);
479++ pa_backend_set_port(pb, "analog-input-microphone-headset", false);
480++ break;
481++ case WDYPI_DIALOG_MICROPHONE:
482++ pa_backend_set_port(pb, "analog-output-speaker", true);
483++ pa_backend_set_port(pb, "analog-input-microphone", false);
484++ break;
485++ default:
486++ break;
487++ }
488++}
489++
490++static void
491++on_wdypi_popup (bool hsmic, bool hpmic, void *userdata)
492++{
493++ if (!hpmic && !hsmic)
494++ wdypi_dialog_kill();
495++ else wdypi_dialog_run(hsmic, hpmic, on_wdypi_action, userdata);
496++}
497++
498++static void
499+ initialize_volume_handler (GsdMediaKeysManager *manager)
500+ {
501+ /* initialise Volume handler
502+@@ -2695,6 +2758,8 @@
503+
504+ manager->priv->volume = gvc_mixer_control_new ("GNOME Volume Control Media Keys");
505+
506++ manager->priv->wdypi_pa_backend = pa_backend_new(on_wdypi_popup, manager);
507++
508+ g_signal_connect (manager->priv->volume,
509+ "state-changed",
510+ G_CALLBACK (on_control_state_changed),
511+@@ -2711,6 +2776,10 @@
512+ "stream-removed",
513+ G_CALLBACK (on_control_stream_removed),
514+ manager);
515++ g_signal_connect (manager->priv->volume,
516++ "card-info",
517++ G_CALLBACK (on_control_card_info_updated),
518++ manager);
519+
520+ gvc_mixer_control_open (manager->priv->volume);
521+
522+@@ -3035,6 +3104,12 @@
523+ gdk_error_trap_pop_ignored ();
524+ }
525+
526++ if (manager->priv->wdypi_pa_backend) {
527++ pa_backend_free (manager->priv->wdypi_pa_backend);
528++ manager->priv->wdypi_pa_backend = NULL;
529++ }
530++ wdypi_dialog_kill();
531++
532+ if (priv->grab_cancellable != NULL) {
533+ g_cancellable_cancel (priv->grab_cancellable);
534+ g_clear_object (&priv->grab_cancellable);
535+Index: gnome-settings-daemon-3.8.6.1/configure.ac
536+===================================================================
537+--- gnome-settings-daemon-3.8.6.1.orig/configure.ac 2014-02-04 13:32:40.805078130 +0100
538++++ gnome-settings-daemon-3.8.6.1/configure.ac 2014-02-04 13:32:40.801078130 +0100
539+@@ -213,7 +213,7 @@
540+ dnl - media-keys plugin stuff
541+ dnl ---------------------------------------------------------------------------
542+
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])
544++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])
545+ PKG_CHECK_MODULES(GVC, [gobject-2.0 libpulse >= $PA_REQUIRED_VERSION libpulse-mainloop-glib >= $PA_REQUIRED_VERSION])
546+ AM_CONDITIONAL(HAVE_INTROSPECTION, false)
547+
548+Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/dialog-window.c
549+===================================================================
550+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
551++++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/dialog-window.c 2014-02-04 13:41:13.721069062 +0100
552+@@ -0,0 +1,138 @@
553++#include <glib/gi18n.h>
554++#include <gtk/gtk.h>
555++#include <gdk-pixbuf/gdk-pixbuf.h>
556++
557++#include "dialog-window.h"
558++
559++typedef struct dialog_window {
560++ GtkWidget *dialog;
561++ GtkWidget *ca_box;
562++ GtkWidget *v_box;
563++ GtkWidget *icon_box;
564++ GtkWidget *btn_box;
565++ GtkWidget *label;
566++ GtkWidget *cancel_btn;
567++ GtkWidget *settings_btn;
568++ GtkWidget *hp_btn;
569++ GtkWidget *hs_btn;
570++ GtkWidget *mic_btn;
571++
572++ int button_response;
573++ wdypi_dialog_cb cb;
574++ void *cb_userdata;
575++} dialog_window;
576++
577++/* It's okay to have a global here - we should never show more than one dialog */
578++dialog_window dlg;
579++
580++void wdypi_dialog_kill()
581++{
582++ dialog_window *d = &dlg;
583++ if (d->dialog) {
584++ gtk_widget_destroy(d->dialog);
585++ d->dialog = NULL;
586++ }
587++}
588++
589++static void on_cancel_clicked (GtkWidget *widget, gpointer data)
590++{
591++ dialog_window *d = data;
592++ gtk_dialog_response(GTK_DIALOG(d->dialog), GTK_RESPONSE_CANCEL);
593++}
594++
595++static void on_settings_clicked (GtkWidget *widget, gpointer data)
596++{
597++ dialog_window *d = data;
598++ d->button_response = WDYPI_DIALOG_SOUND_SETTINGS;
599++ gtk_dialog_response(GTK_DIALOG(d->dialog), GTK_RESPONSE_OK);
600++}
601++
602++static void on_iconbtn_clicked (GtkWidget *widget, gpointer data)
603++{
604++ dialog_window *d = &dlg;
605++ d->button_response = (ssize_t) data;
606++ gtk_dialog_response(GTK_DIALOG(d->dialog), GTK_RESPONSE_OK);
607++}
608++
609++static void on_response (GtkWidget *widget, gint response_id, gpointer data)
610++{
611++ dialog_window *d = data;
612++ if (!d->cb)
613++ return;
614++
615++ if (response_id == GTK_RESPONSE_OK)
616++ d->cb(d->button_response, d->cb_userdata);
617++ else
618++ d->cb(WDYPI_DIALOG_CANCELLED, d->cb_userdata);
619++
620++ wdypi_dialog_kill();
621++}
622++
623++static GtkWidget * create_icon_button(int response, const char *name, const char *icon)
624++{
625++ GtkWidget *btn = gtk_button_new();
626++ GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 12);
627++ GtkWidget *lbl = gtk_label_new(name);
628++ GtkWidget *img = gtk_image_new_from_icon_name(icon, GTK_ICON_SIZE_DIALOG);
629++
630++ gtk_box_pack_end(GTK_BOX(box), lbl, FALSE, FALSE, 0);
631++ gtk_box_pack_end(GTK_BOX(box), img, FALSE, FALSE, 0);
632++ gtk_container_set_border_width(GTK_CONTAINER(box), 12);
633++ gtk_container_add(GTK_CONTAINER(btn), box);
634++ g_signal_connect(btn, "clicked", G_CALLBACK(on_iconbtn_clicked), (void*) (ssize_t) response);
635++ return btn;
636++}
637++
638++static void dialog_create(dialog_window *d, bool show_headset, bool show_mic)
639++{
640++ d->dialog = gtk_dialog_new();
641++ gtk_window_set_title(GTK_WINDOW(d->dialog), _("Unknown Audio Device"));
642++ gtk_container_set_border_width(GTK_CONTAINER(d->dialog), 12);
643++ gtk_window_set_icon_name(GTK_WINDOW(d->dialog), "audio-headphones");
644++
645++ d->ca_box = gtk_dialog_get_content_area(GTK_DIALOG(d->dialog));
646++ d->v_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 25);
647++ d->icon_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 25);
648++ gtk_box_set_homogeneous(GTK_BOX(d->icon_box), TRUE);
649++ d->btn_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 25);
650++
651++ d->label = gtk_label_new(_("What kind of device did you plug in?"));
652++ gtk_misc_set_alignment(GTK_MISC(d->label), 0, 0.5);
653++ gtk_container_add(GTK_CONTAINER(d->v_box), d->label);
654++
655++ d->hp_btn = create_icon_button(WDYPI_DIALOG_HEADPHONES, _("Headphones"), "audio-headphones");
656++ gtk_box_pack_start(GTK_BOX(d->icon_box), d->hp_btn, FALSE, TRUE, 0);
657++ if (show_headset) {
658++ d->hs_btn = create_icon_button(WDYPI_DIALOG_HEADSET, _("Headset"), "audio-headset");
659++ gtk_box_pack_start(GTK_BOX(d->icon_box), d->hs_btn, FALSE, TRUE, 0);
660++ }
661++ if (show_mic) {
662++ d->mic_btn = create_icon_button(WDYPI_DIALOG_MICROPHONE, _("Microphone"), "audio-input-microphone");
663++ gtk_box_pack_start(GTK_BOX(d->icon_box), d->mic_btn, FALSE, TRUE, 0);
664++ }
665++ gtk_container_add(GTK_CONTAINER(d->v_box), d->icon_box);
666++
667++ d->settings_btn = gtk_button_new_with_label(_("Sound Settings..."));
668++ g_signal_connect(d->settings_btn, "clicked", G_CALLBACK(on_settings_clicked), d);
669++ gtk_box_pack_end(GTK_BOX(d->btn_box), d->settings_btn, FALSE, FALSE, 0);
670++
671++ d->cancel_btn = gtk_button_new_with_label(_("Cancel"));
672++ g_signal_connect(d->cancel_btn, "clicked", G_CALLBACK(on_cancel_clicked), d);
673++ gtk_box_pack_end(GTK_BOX(d->btn_box), d->cancel_btn, FALSE, FALSE, 0);
674++ gtk_container_add(GTK_CONTAINER(d->v_box), d->btn_box);
675++
676++ gtk_container_add(GTK_CONTAINER(d->ca_box), d->v_box);
677++ g_signal_connect(d->dialog, "response", G_CALLBACK(on_response), d);
678++
679++ gtk_widget_show_all(d->dialog);
680++}
681++
682++void wdypi_dialog_run(bool show_headset, bool show_mic, wdypi_dialog_cb cb, void *cb_userdata)
683++{
684++ dialog_window *d = &dlg;
685++
686++ wdypi_dialog_kill();
687++ d->cb = cb;
688++ d->cb_userdata = cb_userdata;
689++ dialog_create(d, show_headset, show_mic);
690++}
691+Index: gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/dialog-window.h
692+===================================================================
693+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
694++++ gnome-settings-daemon-3.8.6.1/plugins/media-keys/what-did-you-plug-in/dialog-window.h 2014-02-04 13:32:40.801078130 +0100
695+@@ -0,0 +1,18 @@
696++#ifndef __DIALOG_WINDOW_H__
697++#define __DIALOG_WINDOW_H__
698++
699++#include <stdbool.h>
700++
701++#define WDYPI_DIALOG_CANCELLED 0
702++#define WDYPI_DIALOG_HEADPHONES 1
703++#define WDYPI_DIALOG_HEADSET 2
704++#define WDYPI_DIALOG_MICROPHONE 3
705++#define WDYPI_DIALOG_SOUND_SETTINGS 4
706++
707++typedef void (*wdypi_dialog_cb)(int response, void *userdata);
708++
709++void wdypi_dialog_run(bool show_headset, bool show_mic, wdypi_dialog_cb cb, void *cb_userdata);
710++
711++void wdypi_dialog_kill();
712++
713++#endif

Subscribers

People subscribed via source and target branches