Merge lp:~diwic/gnome-settings-daemon/what-did-you-plug-in into lp:~ubuntu-desktop/gnome-settings-daemon/ubuntu
- what-did-you-plug-in
- Merge into ubuntu
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 |
Related bugs: |
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.
Commit message
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.
David Henningsson (diwic) wrote : Posted in a previous version of this proposal | # |
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?
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.
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.
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-
- 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_
- 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(
better to cal "unity-
- > d->settings_btn = gtk_button_
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
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
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-
> patch there, it's full source)
Sure, is it https:/
> - 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?
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/
> Sure, is it https:/
It moved teams for acl reasons, it's now https:/
> 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
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 |
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.