Merge lp:~xavi-garcia-mena/indicator-sound/last-running-player-accounts-service into lp:indicator-sound/15.10
- last-running-player-accounts-service
- Merge into trunk.15.10
Status: | Merged |
---|---|
Approved by: | Charles Kerr |
Approved revision: | 537 |
Merged at revision: | 530 |
Proposed branch: | lp:~xavi-garcia-mena/indicator-sound/last-running-player-accounts-service |
Merge into: | lp:indicator-sound/15.10 |
Diff against target: |
2481 lines (+1148/-895) 16 files modified
data/com.canonical.indicator.sound.gschema.xml (+2/-13) src/CMakeLists.txt (+22/-11) src/accounts-service-access.vala (+235/-0) src/main.c (+63/-61) src/service.vala (+15/-8) src/sound-menu.vala (+35/-13) src/volume-control-pulse.vala (+12/-141) tests/integration/indicator-sound-test-base.cpp (+29/-5) tests/integration/indicator-sound-test-base.h (+4/-0) tests/integration/test-indicator.cpp (+69/-12) tests/notifications-test.cc (+568/-558) tests/service-mocks/accounts-mock/AccountsServiceSoundMock.cpp (+15/-0) tests/service-mocks/accounts-mock/AccountsServiceSoundMock.h (+4/-0) tests/service-mocks/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml (+1/-0) tests/sound-menu.cc (+16/-16) tests/volume-control-test.cc (+58/-57) |
To merge this branch: | bzr merge lp:~xavi-garcia-mena/indicator-sound/last-running-player-accounts-service |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Charles Kerr (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+286897@code.launchpad.net |
Commit message
This branch sets the last running player using accounts service instead of gsettings.
It also includes a new class AccountsService
Description of the change
This branch sets the last running player using accounts service instead of gsettings.
It also includes a new class AccountsService
PS Jenkins bot (ps-jenkins) wrote : | # |
- 533. By Xavi Garcia
-
Fixed integration test
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:533
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 534. By Xavi Garcia
-
Removed log statement
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:534
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 535. By Xavi Garcia
-
Accounts service notification fix
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:535
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Charles Kerr (charlesk) wrote : | # |
A lot of this looks great. I like the improved tests and the refactoring of AccountsServices into its own class.
Several questions inline though, with a couple of serious issues eg the way GCancellable is used and my questions about the use of last_player_added in SoundMenu.
- 536. By Xavi Garcia
-
Changed following Charles's suggestions
Xavi Garcia (xavi-garcia-mena) wrote : | # |
Thanks for the review, Charles!
I assumed the existing code had passed already a code review in deep and did not refactored it. Big mistake.
I've fixed almost everything you commented. I think there's only one point remaining... please take a look at the inline comments.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:536
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Charles Kerr (charlesk) wrote : | # |
Ah, I didn't realize that GCancellable issue was a carryover from old code. I'm glad it's fixed.
One last suggestion, I do think AccountsService
Nice fix wrt the cascading signal emission.
- 537. By Xavi Garcia
-
Added Cancellable to AccountsService
Access
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:537
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Charles Kerr (charlesk) wrote : | # |
Good stuff.
I won't block this patch further because this is a preexisting condition, but if you want to finish making AccountsService
accounts-
accounts-
accounts-
accounts-
accounts-
In (I think) all of these cases the cancellable is passed in as the invisible last argument, where vala has a C++-like default argument which is null.
Preview Diff
1 | === modified file 'data/com.canonical.indicator.sound.gschema.xml' |
2 | --- data/com.canonical.indicator.sound.gschema.xml 2016-02-10 13:08:49 +0000 |
3 | +++ data/com.canonical.indicator.sound.gschema.xml 2016-03-03 08:59:58 +0000 |
4 | @@ -59,10 +59,10 @@ |
5 | <description> |
6 | How long to remember a user's approval of the confirmation dialog discussed in the |
7 | description of 'warning-volume-enabled'. |
8 | - |
9 | + |
10 | The default value (72,000 seconds) corresponds to the 20 hours suggested by |
11 | EU standard EN 60950-1/Al2: “The acknowledgement does not need to be repeated |
12 | - more than once every 20 h of cumulative listening time.” |
13 | + more than once every 20 h of cumulative listening time.” |
14 | </description> |
15 | </key> |
16 | <key name="warning-volume-decibels" type="d"> |
17 | @@ -102,16 +102,5 @@ |
18 | </description> |
19 | </key> |
20 | |
21 | - <key name="last-running-player" type="s"> |
22 | - <default>""</default> |
23 | - <summary>Stores which was the last running music player.</summary> |
24 | - <description> |
25 | - To make the last running player persistent and be able to set its playback controls |
26 | - we store which was the last player running id. |
27 | - |
28 | - The default value ("") corresponds to no player. |
29 | - </description> |
30 | - </key> |
31 | - |
32 | </schema> |
33 | </schemalist> |
34 | |
35 | === modified file 'src/CMakeLists.txt' |
36 | --- src/CMakeLists.txt 2016-02-12 19:36:10 +0000 |
37 | +++ src/CMakeLists.txt 2016-03-03 08:59:58 +0000 |
38 | @@ -69,29 +69,37 @@ |
39 | media-player-list |
40 | mpris2-interfaces |
41 | accounts-service-user |
42 | + accounts-service-access |
43 | ) |
44 | vala_add(indicator-sound-service |
45 | options.vala |
46 | DEPENDS |
47 | volume-control |
48 | volume-control-pulse |
49 | + accounts-service-access |
50 | ) |
51 | vala_add(indicator-sound-service |
52 | options-gsettings.vala |
53 | DEPENDS |
54 | options |
55 | - volume-control-pulse |
56 | + volume-control-pulse |
57 | volume-control |
58 | + accounts-service-access |
59 | ) |
60 | vala_add(indicator-sound-service |
61 | volume-control.vala |
62 | DEPENDS |
63 | options |
64 | - volume-control-pulse |
65 | + volume-control-pulse |
66 | + accounts-service-access |
67 | +) |
68 | +vala_add(indicator-sound-service |
69 | + accounts-service-access.vala |
70 | ) |
71 | vala_add(indicator-sound-service |
72 | volume-control-pulse.vala |
73 | DEPENDS |
74 | + accounts-service-access |
75 | options |
76 | volume-control |
77 | ) |
78 | @@ -99,20 +107,22 @@ |
79 | volume-warning.vala |
80 | DEPENDS |
81 | options |
82 | - volume-control-pulse |
83 | + volume-control-pulse |
84 | volume-control |
85 | warn-notification |
86 | - notification |
87 | + notification |
88 | + accounts-service-access |
89 | ) |
90 | vala_add(indicator-sound-service |
91 | volume-warning-pulse.vala |
92 | DEPENDS |
93 | volume-warning |
94 | - options |
95 | - volume-control-pulse |
96 | - volume-control |
97 | - warn-notification |
98 | - notification |
99 | + options |
100 | + volume-control-pulse |
101 | + volume-control |
102 | + warn-notification |
103 | + notification |
104 | + accounts-service-access |
105 | ) |
106 | vala_add(indicator-sound-service |
107 | media-player.vala |
108 | @@ -161,8 +171,9 @@ |
109 | DEPENDS |
110 | media-player |
111 | volume-control |
112 | - options |
113 | - volume-control-pulse |
114 | + options |
115 | + volume-control-pulse |
116 | + accounts-service-access |
117 | ) |
118 | vala_add(indicator-sound-service |
119 | accounts-service-user.vala |
120 | |
121 | === added file 'src/accounts-service-access.vala' |
122 | --- src/accounts-service-access.vala 1970-01-01 00:00:00 +0000 |
123 | +++ src/accounts-service-access.vala 2016-03-03 08:59:58 +0000 |
124 | @@ -0,0 +1,235 @@ |
125 | +/* |
126 | + * -*- Mode:Vala; indent-tabs-mode:t; tab-width:4; encoding:utf8 -*- |
127 | + * Copyright 2016 Canonical Ltd. |
128 | + * |
129 | + * This program is free software; you can redistribute it and/or modify |
130 | + * it under the terms of the GNU General Public License as published by |
131 | + * the Free Software Foundation; version 3. |
132 | + * |
133 | + * This program is distributed in the hope that it will be useful, |
134 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
135 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
136 | + * GNU General Public License for more details. |
137 | + * |
138 | + * You should have received a copy of the GNU General Public License |
139 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
140 | + * |
141 | + * Authors: |
142 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
143 | + */ |
144 | + |
145 | +using PulseAudio; |
146 | +using Notify; |
147 | +using Gee; |
148 | + |
149 | +[DBus (name="com.canonical.UnityGreeter.List")] |
150 | +interface GreeterListInterfaceAccess : Object |
151 | +{ |
152 | + public abstract async string get_active_entry () throws IOError; |
153 | + public signal void entry_selected (string entry_name); |
154 | +} |
155 | + |
156 | +public class AccountsServiceAccess : Object |
157 | +{ |
158 | + private DBusProxy _user_proxy; |
159 | + private GreeterListInterfaceAccess _greeter_proxy; |
160 | + private double _volume = 0.0; |
161 | + private string _last_running_player = ""; |
162 | + private bool _mute = false; |
163 | + private Cancellable _dbus_call_cancellable; |
164 | + |
165 | + public AccountsServiceAccess () |
166 | + { |
167 | + _dbus_call_cancellable = new Cancellable (); |
168 | + setup_accountsservice.begin (); |
169 | + } |
170 | + |
171 | + ~AccountsServiceAccess () |
172 | + { |
173 | + _dbus_call_cancellable.cancel (); |
174 | + } |
175 | + |
176 | + public string last_running_player |
177 | + { |
178 | + get |
179 | + { |
180 | + return _last_running_player; |
181 | + } |
182 | + set |
183 | + { |
184 | + sync_last_running_player_to_accountsservice.begin (value); |
185 | + } |
186 | + } |
187 | + |
188 | + public bool mute |
189 | + { |
190 | + get |
191 | + { |
192 | + return _mute; |
193 | + } |
194 | + set |
195 | + { |
196 | + sync_mute_to_accountsservice.begin (value); |
197 | + } |
198 | + } |
199 | + |
200 | + public double volume |
201 | + { |
202 | + get |
203 | + { |
204 | + return _volume; |
205 | + } |
206 | + set |
207 | + { |
208 | + sync_volume_to_accountsservice.begin (value); |
209 | + } |
210 | + } |
211 | + |
212 | + /* AccountsService operations */ |
213 | + private void accountsservice_props_changed_cb (DBusProxy proxy, Variant changed_properties, string[]? invalidated_properties) |
214 | + { |
215 | + Variant volume_variant = changed_properties.lookup_value ("Volume", VariantType.DOUBLE); |
216 | + if (volume_variant != null) { |
217 | + var volume = volume_variant.get_double (); |
218 | + if (volume >= 0 && _volume != volume) { |
219 | + _volume = volume; |
220 | + this.notify_property("volume"); |
221 | + } |
222 | + } |
223 | + |
224 | + Variant mute_variant = changed_properties.lookup_value ("Muted", VariantType.BOOLEAN); |
225 | + if (mute_variant != null) { |
226 | + _mute = mute_variant.get_boolean (); |
227 | + this.notify_property("mute"); |
228 | + } |
229 | + |
230 | + Variant last_running_player_variant = changed_properties.lookup_value ("LastRunningPlayer", VariantType.STRING); |
231 | + if (last_running_player_variant != null) { |
232 | + _last_running_player = last_running_player_variant.get_string (); |
233 | + this.notify_property("last-running-player"); |
234 | + } |
235 | + } |
236 | + |
237 | + private async void setup_user_proxy (string? username_in = null) |
238 | + { |
239 | + var username = username_in; |
240 | + _user_proxy = null; |
241 | + |
242 | + // Look up currently selected greeter user, if asked |
243 | + if (username == null) { |
244 | + try { |
245 | + username = yield _greeter_proxy.get_active_entry (); |
246 | + if (username == "" || username == null) |
247 | + return; |
248 | + } catch (GLib.Error e) { |
249 | + warning ("unable to find Accounts path for user %s: %s", username == null ? "null" : username, e.message); |
250 | + return; |
251 | + } |
252 | + } |
253 | + |
254 | + // Get master AccountsService object |
255 | + DBusProxy accounts_proxy; |
256 | + try { |
257 | + accounts_proxy = yield DBusProxy.create_for_bus (BusType.SYSTEM, DBusProxyFlags.DO_NOT_LOAD_PROPERTIES | DBusProxyFlags.DO_NOT_CONNECT_SIGNALS, null, "org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts"); |
258 | + } catch (GLib.Error e) { |
259 | + warning ("unable to get greeter proxy: %s", e.message); |
260 | + return; |
261 | + } |
262 | + |
263 | + // Find user's AccountsService object |
264 | + try { |
265 | + var user_path_variant = yield accounts_proxy.call ("FindUserByName", new Variant ("(s)", username), DBusCallFlags.NONE, -1); |
266 | + string user_path; |
267 | + if (user_path_variant.check_format_string ("(o)", true)) { |
268 | + user_path_variant.get ("(o)", out user_path); |
269 | + _user_proxy = yield DBusProxy.create_for_bus (BusType.SYSTEM, DBusProxyFlags.GET_INVALIDATED_PROPERTIES, null, "org.freedesktop.Accounts", user_path, "com.ubuntu.AccountsService.Sound"); |
270 | + } else { |
271 | + warning ("Unable to find user name after calling FindUserByName. Expected type: %s and obtained %s", "(o)", user_path_variant.get_type_string () ); |
272 | + return; |
273 | + } |
274 | + } catch (GLib.Error e) { |
275 | + warning ("unable to find Accounts path for user %s: %s", username, e.message); |
276 | + return; |
277 | + } |
278 | + |
279 | + // Get current values and listen for changes |
280 | + _user_proxy.g_properties_changed.connect (accountsservice_props_changed_cb); |
281 | + try { |
282 | + var props_variant = yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "GetAll", new Variant ("(s)", _user_proxy.get_interface_name ()), null, DBusCallFlags.NONE, -1); |
283 | + if (props_variant.check_format_string ("(@a{sv})", true)) { |
284 | + Variant props; |
285 | + props_variant.get ("(@a{sv})", out props); |
286 | + accountsservice_props_changed_cb(_user_proxy, props, null); |
287 | + } else { |
288 | + warning ("Unable to get accounts service properties after calling GetAll. Expected type: %s and obtained %s", "(@a{sv})", props_variant.get_type_string () ); |
289 | + return; |
290 | + } |
291 | + } catch (GLib.Error e) { |
292 | + debug("Unable to get properties for user %s at first try: %s", username, e.message); |
293 | + } |
294 | + } |
295 | + |
296 | + private void greeter_user_changed (string username) |
297 | + { |
298 | + setup_user_proxy.begin (username); |
299 | + } |
300 | + |
301 | + private async void setup_accountsservice () |
302 | + { |
303 | + if (Environment.get_variable ("XDG_SESSION_CLASS") == "greeter") { |
304 | + try { |
305 | + _greeter_proxy = yield Bus.get_proxy (BusType.SESSION, "com.canonical.UnityGreeter", "/list"); |
306 | + } catch (GLib.Error e) { |
307 | + warning ("unable to get greeter proxy: %s", e.message); |
308 | + return; |
309 | + } |
310 | + _greeter_proxy.entry_selected.connect (greeter_user_changed); |
311 | + yield setup_user_proxy (); |
312 | + } else { |
313 | + // We are in a user session. We just need our own proxy |
314 | + unowned string username = Environment.get_variable ("USER"); |
315 | + if (username != null && username != "") { |
316 | + yield setup_user_proxy (username); |
317 | + } |
318 | + } |
319 | + } |
320 | + |
321 | + private async void sync_last_running_player_to_accountsservice (string last_running_player) |
322 | + { |
323 | + if (_user_proxy == null) |
324 | + return; |
325 | + |
326 | + try { |
327 | + yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "Set", new Variant ("(ssv)", _user_proxy.get_interface_name (), "LastRunningPlayer", new Variant ("s", last_running_player)), null, DBusCallFlags.NONE, -1, _dbus_call_cancellable); |
328 | + } catch (GLib.Error e) { |
329 | + warning ("unable to sync last running player %s to AccountsService: %s",last_running_player, e.message); |
330 | + } |
331 | + _last_running_player = last_running_player; |
332 | + } |
333 | + |
334 | + private async void sync_volume_to_accountsservice (double volume) |
335 | + { |
336 | + if (_user_proxy == null) |
337 | + return; |
338 | + |
339 | + try { |
340 | + yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "Set", new Variant ("(ssv)", _user_proxy.get_interface_name (), "Volume", new Variant ("d", volume)), null, DBusCallFlags.NONE, -1, _dbus_call_cancellable); |
341 | + } catch (GLib.Error e) { |
342 | + warning ("unable to sync volume %f to AccountsService: %s", volume, e.message); |
343 | + } |
344 | + } |
345 | + |
346 | + private async void sync_mute_to_accountsservice (bool mute) |
347 | + { |
348 | + if (_user_proxy == null) |
349 | + return; |
350 | + |
351 | + try { |
352 | + yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "Set", new Variant ("(ssv)", _user_proxy.get_interface_name (), "Muted", new Variant ("b", mute)), null, DBusCallFlags.NONE, -1, _dbus_call_cancellable); |
353 | + } catch (GLib.Error e) { |
354 | + warning ("unable to sync mute %s to AccountsService: %s", mute ? "true" : "false", e.message); |
355 | + } |
356 | + } |
357 | +} |
358 | + |
359 | + |
360 | |
361 | === modified file 'src/main.c' |
362 | --- src/main.c 2015-12-29 17:03:41 +0000 |
363 | +++ src/main.c 2016-03-03 08:59:58 +0000 |
364 | @@ -27,9 +27,9 @@ |
365 | static gboolean |
366 | sigterm_handler (gpointer data) |
367 | { |
368 | - g_debug("Got SIGTERM"); |
369 | - g_main_loop_quit((GMainLoop *)data); |
370 | - return G_SOURCE_REMOVE; |
371 | + g_debug("Got SIGTERM"); |
372 | + g_main_loop_quit((GMainLoop *)data); |
373 | + return G_SOURCE_REMOVE; |
374 | } |
375 | |
376 | static void |
377 | @@ -37,8 +37,8 @@ |
378 | const gchar * name, |
379 | gpointer user_data) |
380 | { |
381 | - g_warning("Name lost or unable to acquire bus: %s", name); |
382 | - g_main_loop_quit((GMainLoop *)user_data); |
383 | + g_warning("Name lost or unable to acquire bus: %s", name); |
384 | + g_main_loop_quit((GMainLoop *)user_data); |
385 | } |
386 | |
387 | static void |
388 | @@ -46,66 +46,68 @@ |
389 | const gchar *name, |
390 | gpointer user_data) |
391 | { |
392 | - MediaPlayerList * playerlist = NULL; |
393 | - IndicatorSoundOptions * options = NULL; |
394 | - VolumeControlPulse * volume = NULL; |
395 | - AccountsServiceUser * accounts = NULL; |
396 | - VolumeWarning * warning = NULL; |
397 | - |
398 | - |
399 | - if (g_strcmp0("lightdm", g_get_user_name()) == 0) { |
400 | - playerlist = MEDIA_PLAYER_LIST(media_player_list_greeter_new()); |
401 | - } else { |
402 | - playerlist = MEDIA_PLAYER_LIST(media_player_list_mpris_new()); |
403 | - accounts = accounts_service_user_new(); |
404 | - } |
405 | - |
406 | - pgloop = pa_glib_mainloop_new(NULL); |
407 | - options = indicator_sound_options_gsettings_new(); |
408 | - volume = volume_control_pulse_new(options, pgloop); |
409 | - warning = volume_warning_pulse_new(options, pgloop); |
410 | - |
411 | - service = indicator_sound_service_new (playerlist, volume, accounts, options, warning); |
412 | - |
413 | - g_clear_object(&playerlist); |
414 | - g_clear_object(&options); |
415 | - g_clear_object(&volume); |
416 | - g_clear_object(&accounts); |
417 | - g_clear_object(&warning); |
418 | + MediaPlayerList * playerlist = NULL; |
419 | + IndicatorSoundOptions * options = NULL; |
420 | + VolumeControlPulse * volume = NULL; |
421 | + AccountsServiceUser * accounts = NULL; |
422 | + VolumeWarning * warning = NULL; |
423 | + AccountsServiceAccess * accounts_service_access = NULL; |
424 | + |
425 | + |
426 | + if (g_strcmp0("lightdm", g_get_user_name()) == 0) { |
427 | + playerlist = MEDIA_PLAYER_LIST(media_player_list_greeter_new()); |
428 | + } else { |
429 | + playerlist = MEDIA_PLAYER_LIST(media_player_list_mpris_new()); |
430 | + accounts = accounts_service_user_new(); |
431 | + } |
432 | + |
433 | + pgloop = pa_glib_mainloop_new(NULL); |
434 | + options = indicator_sound_options_gsettings_new(); |
435 | + accounts_service_access = accounts_service_access_new(); |
436 | + volume = volume_control_pulse_new(options, pgloop, accounts_service_access); |
437 | + warning = volume_warning_pulse_new(options, pgloop); |
438 | + |
439 | + service = indicator_sound_service_new (playerlist, volume, accounts, options, warning, accounts_service_access); |
440 | + |
441 | + g_clear_object(&playerlist); |
442 | + g_clear_object(&options); |
443 | + g_clear_object(&volume); |
444 | + g_clear_object(&accounts); |
445 | + g_clear_object(&warning); |
446 | } |
447 | |
448 | int |
449 | main (int argc, char ** argv) |
450 | { |
451 | - GMainLoop * loop = NULL; |
452 | - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); |
453 | - setlocale (LC_ALL, ""); |
454 | - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); |
455 | - |
456 | - /* Build Mainloop */ |
457 | - loop = g_main_loop_new(NULL, FALSE); |
458 | - |
459 | - g_unix_signal_add(SIGTERM, sigterm_handler, loop); |
460 | - |
461 | - /* Initialize libnotify */ |
462 | - notify_init ("indicator-sound"); |
463 | - |
464 | - g_bus_own_name(G_BUS_TYPE_SESSION, |
465 | - "com.canonical.indicator.sound", |
466 | - G_BUS_NAME_OWNER_FLAGS_NONE, |
467 | - on_bus_acquired, |
468 | - NULL, /* name acquired */ |
469 | - on_name_lost, |
470 | - loop, |
471 | - NULL); |
472 | - |
473 | - g_main_loop_run(loop); |
474 | - |
475 | - g_clear_object(&service); |
476 | - g_clear_pointer(&pgloop, pa_glib_mainloop_free); |
477 | - |
478 | - notify_uninit(); |
479 | - |
480 | - return 0; |
481 | + GMainLoop * loop = NULL; |
482 | + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); |
483 | + setlocale (LC_ALL, ""); |
484 | + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); |
485 | + |
486 | + /* Build Mainloop */ |
487 | + loop = g_main_loop_new(NULL, FALSE); |
488 | + |
489 | + g_unix_signal_add(SIGTERM, sigterm_handler, loop); |
490 | + |
491 | + /* Initialize libnotify */ |
492 | + notify_init ("indicator-sound"); |
493 | + |
494 | + g_bus_own_name(G_BUS_TYPE_SESSION, |
495 | + "com.canonical.indicator.sound", |
496 | + G_BUS_NAME_OWNER_FLAGS_NONE, |
497 | + on_bus_acquired, |
498 | + NULL, /* name acquired */ |
499 | + on_name_lost, |
500 | + loop, |
501 | + NULL); |
502 | + |
503 | + g_main_loop_run(loop); |
504 | + |
505 | + g_clear_object(&service); |
506 | + g_clear_pointer(&pgloop, pa_glib_mainloop_free); |
507 | + |
508 | + notify_uninit(); |
509 | + |
510 | + return 0; |
511 | } |
512 | |
513 | |
514 | === modified file 'src/service.vala' |
515 | --- src/service.vala 2016-02-10 13:08:49 +0000 |
516 | +++ src/service.vala 2016-03-03 08:59:58 +0000 |
517 | @@ -20,7 +20,9 @@ |
518 | public class IndicatorSound.Service: Object { |
519 | DBusConnection bus; |
520 | |
521 | - public Service (MediaPlayerList playerlist, VolumeControl volume, AccountsServiceUser? accounts, Options options, VolumeWarning volume_warning) { |
522 | + public Service (MediaPlayerList playerlist, VolumeControl volume, AccountsServiceUser? accounts, Options options, VolumeWarning volume_warning, AccountsServiceAccess? accounts_service_access) { |
523 | + |
524 | + _accounts_service_access = accounts_service_access; |
525 | |
526 | try { |
527 | bus = Bus.get_sync(GLib.BusType.SESSION); |
528 | @@ -60,7 +62,6 @@ |
529 | headphones = false; |
530 | break; |
531 | } |
532 | - message("setting _volume_warning.headphones_active to %d", (int)headphones); |
533 | _volume_warning.headphones_active = headphones; |
534 | |
535 | update_root_icon(); |
536 | @@ -91,12 +92,11 @@ |
537 | this.actions.add_action (this.create_high_volume_action ()); |
538 | this.actions.add_action (this.create_volume_sync_action ()); |
539 | |
540 | - string last_player = this.settings.get_string ("last-running-player"); |
541 | this.menus = new HashTable<string, SoundMenu> (str_hash, str_equal); |
542 | - this.menus.insert ("desktop_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS, last_player)); |
543 | - this.menus.insert ("phone_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_SILENT_MODE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS, last_player)); |
544 | - this.menus.insert ("desktop", new SoundMenu ("indicator.desktop-settings", SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS_PLAY_CONTROLS | SoundMenu.DisplayFlags.ADD_PLAY_CONTROL_INACTIVE_PLAYER, last_player)); |
545 | - this.menus.insert ("phone", new SoundMenu ("indicator.phone-settings", SoundMenu.DisplayFlags.SHOW_SILENT_MODE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS, last_player)); |
546 | + this.menus.insert ("desktop_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS)); |
547 | + this.menus.insert ("phone_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_SILENT_MODE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS)); |
548 | + this.menus.insert ("desktop", new SoundMenu ("indicator.desktop-settings", SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS_PLAY_CONTROLS | SoundMenu.DisplayFlags.ADD_PLAY_CONTROL_INACTIVE_PLAYER)); |
549 | + this.menus.insert ("phone", new SoundMenu ("indicator.phone-settings", SoundMenu.DisplayFlags.SHOW_SILENT_MODE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS)); |
550 | |
551 | this.menus.@foreach ( (profile, menu) => { |
552 | this.volume_control.bind_property ("active-mic", menu, "show-mic-volume", BindingFlags.SYNC_CREATE); |
553 | @@ -112,7 +112,13 @@ |
554 | |
555 | this.menus.@foreach ( (profile, menu) => { |
556 | menu.last_player_updated.connect ((player_id) => { |
557 | - this.settings.set_value ("last-running-player", player_id); |
558 | + this._accounts_service_access.last_running_player = player_id; |
559 | + }); |
560 | + }); |
561 | + |
562 | + this._accounts_service_access.notify["last-running-player"].connect(() => { |
563 | + this.menus.@foreach ( (profile, menu) => { |
564 | + menu.set_default_player (this._accounts_service_access.last_running_player); |
565 | }); |
566 | }); |
567 | |
568 | @@ -199,6 +205,7 @@ |
569 | private Options _options; |
570 | private VolumeWarning _volume_warning; |
571 | private IndicatorSound.InfoNotification _info_notification = new IndicatorSound.InfoNotification(); |
572 | + private AccountsServiceAccess _accounts_service_access; |
573 | |
574 | const double volume_step_percentage = 0.06; |
575 | |
576 | |
577 | === modified file 'src/sound-menu.vala' |
578 | --- src/sound-menu.vala 2016-02-10 13:08:49 +0000 |
579 | +++ src/sound-menu.vala 2016-03-03 08:59:58 +0000 |
580 | @@ -38,7 +38,7 @@ |
581 | |
582 | const string PLAYBACK_ITEM_TYPE = "com.canonical.unity.playback-item"; |
583 | |
584 | - public SoundMenu (string? settings_action, DisplayFlags flags, string default_player_id) { |
585 | + public SoundMenu (string? settings_action, DisplayFlags flags) { |
586 | /* A sound menu always has at least two sections: the volume section (this.volume_section) |
587 | * at the start of the menu, and the settings section at the end. Between those two, |
588 | * it has a dynamic amount of player sections, one for each registered player. |
589 | @@ -83,9 +83,6 @@ |
590 | this.notify_handlers = new HashTable<MediaPlayer, ulong> (direct_hash, direct_equal); |
591 | |
592 | this.greeter_players = (flags & DisplayFlags.GREETER_PLAYERS) != 0; |
593 | - |
594 | - this.default_player = default_player_id; |
595 | - |
596 | } |
597 | |
598 | ~SoundMenu () { |
599 | @@ -95,6 +92,16 @@ |
600 | } |
601 | } |
602 | |
603 | + public void set_default_player (string default_player_id) { |
604 | + this.default_player = default_player_id; |
605 | + foreach (var player_stored in notify_handlers.get_keys ()) { |
606 | + int index = this.find_player_section(player_stored); |
607 | + if (index != -1 && player_stored.id == this.default_player) { |
608 | + add_player_playback_controls (player_stored, index, true); |
609 | + } |
610 | + } |
611 | + } |
612 | + |
613 | DBusConnection? bus = null; |
614 | uint export_id = 0; |
615 | |
616 | @@ -171,7 +178,17 @@ |
617 | } |
618 | } |
619 | } |
620 | - |
621 | + |
622 | + private void check_last_running_player () { |
623 | + foreach (var player in notify_handlers.get_keys ()) { |
624 | + if (player.is_running && number_of_running_players == 1) { |
625 | + // this is the first or the last player running... |
626 | + // store its id |
627 | + this.last_player_updated (player.id); |
628 | + } |
629 | + } |
630 | + } |
631 | + |
632 | public void add_player (MediaPlayer player) { |
633 | if (this.notify_handlers.contains (player)) |
634 | return; |
635 | @@ -198,11 +215,15 @@ |
636 | // we need to update the rest of players, because we might have |
637 | // a non running player still showing the playback controls |
638 | update_all_players_play_section(); |
639 | + |
640 | + check_last_running_player (); |
641 | }); |
642 | this.notify_handlers.insert (player, handler_id); |
643 | |
644 | player.playlists_changed.connect (this.update_playlists); |
645 | player.playbackstatus_changed.connect (this.update_playbackstatus); |
646 | + |
647 | + check_last_running_player (); |
648 | } |
649 | |
650 | public void remove_player (MediaPlayer player) { |
651 | @@ -217,6 +238,8 @@ |
652 | |
653 | /* this'll drop our ref to it */ |
654 | this.notify_handlers.remove (player); |
655 | + |
656 | + check_last_running_player (); |
657 | } |
658 | |
659 | public void update_volume_slider (VolumeControl.ActiveOutput active_output) { |
660 | @@ -368,16 +391,11 @@ |
661 | this.menu.remove (index); |
662 | } |
663 | |
664 | - void update_player_section (MediaPlayer player, int index) { |
665 | + void add_player_playback_controls (MediaPlayer player, int index, bool adding_default_player) { |
666 | var player_section = this.menu.get_item_link(index, Menu.LINK_SECTION) as Menu; |
667 | |
668 | int play_control_index = find_player_playback_controls_section (player_section); |
669 | - if (player.is_running && number_of_running_players == 1) { |
670 | - // this is the first or the last player running... |
671 | - // store its id |
672 | - this.last_player_updated (player.id); |
673 | - } |
674 | - if (player.is_running || !this.hide_inactive_player_controls) { |
675 | + if (player.is_running || !this.hide_inactive_player_controls || (number_of_running_players == 0 && adding_default_player) ) { |
676 | MenuItem playback_item = create_playback_menu_item (player); |
677 | if (play_control_index != -1) { |
678 | player_section.remove (PlayerSectionPosition.PLAYER_CONTROLS); |
679 | @@ -389,7 +407,11 @@ |
680 | player_section.remove (PlayerSectionPosition.PLAYLIST); |
681 | player_section.remove (PlayerSectionPosition.PLAYER_CONTROLS); |
682 | } |
683 | - } |
684 | + } |
685 | + } |
686 | + |
687 | + void update_player_section (MediaPlayer player, int index) { |
688 | + add_player_playback_controls (player, index, false); |
689 | } |
690 | |
691 | void update_playlists (MediaPlayer player) { |
692 | |
693 | === modified file 'src/volume-control-pulse.vala' |
694 | --- src/volume-control-pulse.vala 2016-01-07 05:28:51 +0000 |
695 | +++ src/volume-control-pulse.vala 2016-03-03 08:59:58 +0000 |
696 | @@ -22,13 +22,6 @@ |
697 | using Notify; |
698 | using Gee; |
699 | |
700 | -[DBus (name="com.canonical.UnityGreeter.List")] |
701 | -interface GreeterListInterface : Object |
702 | -{ |
703 | - public abstract async string get_active_entry () throws IOError; |
704 | - public signal void entry_selected (string entry_name); |
705 | -} |
706 | - |
707 | public class VolumeControlPulse : VolumeControl |
708 | { |
709 | private unowned PulseAudio.GLibMainLoop loop = null; |
710 | @@ -55,20 +48,17 @@ |
711 | private string? _objp_role_phone = null; |
712 | private uint _pa_volume_sig_count = 0; |
713 | |
714 | - private DBusProxy _user_proxy; |
715 | - private GreeterListInterface _greeter_proxy; |
716 | - private Cancellable _mute_cancellable; |
717 | - private Cancellable _volume_cancellable; |
718 | private uint _local_volume_timer = 0; |
719 | private uint _accountservice_volume_timer = 0; |
720 | private bool _send_next_local_volume = false; |
721 | private double _account_service_volume = 0.0; |
722 | private VolumeControl.ActiveOutput _active_output = VolumeControl.ActiveOutput.SPEAKERS; |
723 | + private AccountsServiceAccess _accounts_service_access; |
724 | |
725 | /** true when a microphone is active **/ |
726 | public override bool active_mic { get; private set; default = false; } |
727 | |
728 | - public VolumeControlPulse (IndicatorSound.Options options, PulseAudio.GLibMainLoop loop) |
729 | + public VolumeControlPulse (IndicatorSound.Options options, PulseAudio.GLibMainLoop loop, AccountsServiceAccess? accounts_service_access) |
730 | { |
731 | base(options); |
732 | |
733 | @@ -77,11 +67,14 @@ |
734 | |
735 | this.loop = loop; |
736 | |
737 | - _mute_cancellable = new Cancellable (); |
738 | - _volume_cancellable = new Cancellable (); |
739 | - |
740 | - setup_accountsservice.begin (); |
741 | - |
742 | + _accounts_service_access = accounts_service_access; |
743 | + this._accounts_service_access.notify["volume"].connect(() => { |
744 | + if (this._accounts_service_access.volume >= 0 && _account_service_volume != this._accounts_service_access.volume) { |
745 | + _account_service_volume = this._accounts_service_access.volume; |
746 | + // we need to wait for this to settle. |
747 | + start_account_service_volume_timer(); |
748 | + } |
749 | + }); |
750 | this.reconnect_to_pulse (); |
751 | } |
752 | |
753 | @@ -537,7 +530,7 @@ |
754 | public override void set_mute (bool mute) |
755 | { |
756 | if (set_mute_internal (mute)) |
757 | - sync_mute_to_accountsservice.begin (mute); |
758 | + _accounts_service_access.mute = mute; |
759 | } |
760 | |
761 | public void toggle_mute () |
762 | @@ -773,128 +766,6 @@ |
763 | } |
764 | |
765 | /* AccountsService operations */ |
766 | - private void accountsservice_props_changed_cb (DBusProxy proxy, Variant changed_properties, string[]? invalidated_properties) |
767 | - { |
768 | - Variant volume_variant = changed_properties.lookup_value ("Volume", VariantType.DOUBLE); |
769 | - if (volume_variant != null) { |
770 | - var volume = volume_variant.get_double (); |
771 | - if (volume >= 0) { |
772 | - _account_service_volume = volume; |
773 | - // we need to wait for this to settle. |
774 | - start_account_service_volume_timer(); |
775 | - } |
776 | - } |
777 | - |
778 | - Variant mute_variant = changed_properties.lookup_value ("Muted", VariantType.BOOLEAN); |
779 | - if (mute_variant != null) { |
780 | - var mute = mute_variant.get_boolean (); |
781 | - set_mute_internal (mute); |
782 | - } |
783 | - } |
784 | - |
785 | - private async void setup_user_proxy (string? username_in = null) |
786 | - { |
787 | - var username = username_in; |
788 | - _user_proxy = null; |
789 | - |
790 | - // Look up currently selected greeter user, if asked |
791 | - if (username == null) { |
792 | - try { |
793 | - username = yield _greeter_proxy.get_active_entry (); |
794 | - if (username == "" || username == null) |
795 | - return; |
796 | - } catch (GLib.Error e) { |
797 | - warning ("unable to find Accounts path for user %s: %s", username, e.message); |
798 | - return; |
799 | - } |
800 | - } |
801 | - |
802 | - // Get master AccountsService object |
803 | - DBusProxy accounts_proxy; |
804 | - try { |
805 | - accounts_proxy = yield DBusProxy.create_for_bus (BusType.SYSTEM, DBusProxyFlags.DO_NOT_LOAD_PROPERTIES | DBusProxyFlags.DO_NOT_CONNECT_SIGNALS, null, "org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts"); |
806 | - } catch (GLib.Error e) { |
807 | - warning ("unable to get greeter proxy: %s", e.message); |
808 | - return; |
809 | - } |
810 | - |
811 | - // Find user's AccountsService object |
812 | - try { |
813 | - var user_path_variant = yield accounts_proxy.call ("FindUserByName", new Variant ("(s)", username), DBusCallFlags.NONE, -1); |
814 | - string user_path; |
815 | - user_path_variant.get ("(o)", out user_path); |
816 | - _user_proxy = yield DBusProxy.create_for_bus (BusType.SYSTEM, DBusProxyFlags.GET_INVALIDATED_PROPERTIES, null, "org.freedesktop.Accounts", user_path, "com.ubuntu.AccountsService.Sound"); |
817 | - } catch (GLib.Error e) { |
818 | - warning ("unable to find Accounts path for user %s: %s", username, e.message); |
819 | - return; |
820 | - } |
821 | - |
822 | - // Get current values and listen for changes |
823 | - _user_proxy.g_properties_changed.connect (accountsservice_props_changed_cb); |
824 | - try { |
825 | - var props_variant = yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "GetAll", new Variant ("(s)", _user_proxy.get_interface_name ()), null, DBusCallFlags.NONE, -1); |
826 | - Variant props; |
827 | - props_variant.get ("(@a{sv})", out props); |
828 | - accountsservice_props_changed_cb(_user_proxy, props, null); |
829 | - } catch (GLib.Error e) { |
830 | - debug("Unable to get properties for user %s at first try: %s", username, e.message); |
831 | - } |
832 | - } |
833 | - |
834 | - private void greeter_user_changed (string username) |
835 | - { |
836 | - setup_user_proxy.begin (username); |
837 | - } |
838 | - |
839 | - private async void setup_accountsservice () |
840 | - { |
841 | - if (Environment.get_variable ("XDG_SESSION_CLASS") == "greeter") { |
842 | - try { |
843 | - _greeter_proxy = yield Bus.get_proxy (BusType.SESSION, "com.canonical.UnityGreeter", "/list"); |
844 | - } catch (GLib.Error e) { |
845 | - warning ("unable to get greeter proxy: %s", e.message); |
846 | - return; |
847 | - } |
848 | - _greeter_proxy.entry_selected.connect (greeter_user_changed); |
849 | - yield setup_user_proxy (); |
850 | - } else { |
851 | - // We are in a user session. We just need our own proxy |
852 | - unowned string username = Environment.get_variable ("USER"); |
853 | - if (username != "" && username != null) { |
854 | - yield setup_user_proxy (username); |
855 | - } |
856 | - } |
857 | - } |
858 | - |
859 | - private async void sync_mute_to_accountsservice (bool mute) |
860 | - { |
861 | - if (_user_proxy == null) |
862 | - return; |
863 | - |
864 | - _mute_cancellable.cancel (); |
865 | - _mute_cancellable.reset (); |
866 | - |
867 | - try { |
868 | - yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "Set", new Variant ("(ssv)", _user_proxy.get_interface_name (), "Muted", new Variant ("b", mute)), null, DBusCallFlags.NONE, -1, _mute_cancellable); |
869 | - } catch (GLib.Error e) { |
870 | - warning ("unable to sync mute to AccountsService: %s", e.message); |
871 | - } |
872 | - } |
873 | - |
874 | - private async void sync_volume_to_accountsservice (VolumeControl.Volume volume) |
875 | - { |
876 | - if (_user_proxy == null) |
877 | - return; |
878 | - |
879 | - _volume_cancellable.cancel (); |
880 | - _volume_cancellable.reset (); |
881 | - |
882 | - try { |
883 | - yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "Set", new Variant ("(ssv)", _user_proxy.get_interface_name (), "Volume", new Variant ("d", volume.volume)), null, DBusCallFlags.NONE, -1, _volume_cancellable); |
884 | - } catch (GLib.Error e) { |
885 | - warning ("unable to sync volume to AccountsService: %s", e.message); |
886 | - } |
887 | - } |
888 | |
889 | private void start_local_volume_timer() |
890 | { |
891 | @@ -904,7 +775,7 @@ |
892 | stop_account_service_volume_timer(); |
893 | |
894 | if (_local_volume_timer == 0) { |
895 | - sync_volume_to_accountsservice.begin (_volume); |
896 | + _accounts_service_access.volume = _volume.volume; |
897 | _local_volume_timer = Timeout.add_seconds (1, local_volume_changed_timeout); |
898 | } else { |
899 | _send_next_local_volume = true; |
900 | |
901 | === modified file 'tests/integration/indicator-sound-test-base.cpp' |
902 | --- tests/integration/indicator-sound-test-base.cpp 2016-01-29 11:16:34 +0000 |
903 | +++ tests/integration/indicator-sound-test-base.cpp 2016-03-03 08:59:58 +0000 |
904 | @@ -448,13 +448,37 @@ |
905 | return true; |
906 | } |
907 | |
908 | +QVariant IndicatorSoundTestBase::waitPropertyChanged(QSignalSpy *signalSpy, QString property) |
909 | +{ |
910 | + QVariant ret_val; |
911 | + if (signalSpy) |
912 | + { |
913 | + signalSpy->wait(); |
914 | + if (signalSpy->count()) |
915 | + { |
916 | + QList<QVariant> arguments = signalSpy->takeLast(); |
917 | + if (arguments.size() == 3 && static_cast<QMetaType::Type>(arguments.at(1).type()) == QMetaType::QVariantMap) |
918 | + { |
919 | + QMap<QString, QVariant> map = arguments.at(1).toMap(); |
920 | + QMap<QString, QVariant>::iterator iter = map.find(property); |
921 | + if (iter != map.end()) |
922 | + { |
923 | + return iter.value(); |
924 | + } |
925 | + } |
926 | + } |
927 | + } |
928 | + return ret_val; |
929 | +} |
930 | bool IndicatorSoundTestBase::waitVolumeChangedInIndicator() |
931 | { |
932 | - if (signal_spy_volume_changed_) |
933 | - { |
934 | - return signal_spy_volume_changed_->wait(); |
935 | - } |
936 | - return false; |
937 | + QVariant val = waitPropertyChanged(signal_spy_volume_changed_.get(), "Volume"); |
938 | + return !val.isNull(); |
939 | +} |
940 | + |
941 | +QVariant IndicatorSoundTestBase::waitLastRunningPlayerChanged() |
942 | +{ |
943 | + return waitPropertyChanged(signal_spy_volume_changed_.get(), "LastRunningPlayer"); |
944 | } |
945 | |
946 | void IndicatorSoundTestBase::initializeAccountsInterface() |
947 | |
948 | === modified file 'tests/integration/indicator-sound-test-base.h' |
949 | --- tests/integration/indicator-sound-test-base.h 2016-01-29 11:16:34 +0000 |
950 | +++ tests/integration/indicator-sound-test-base.h 2016-03-03 08:59:58 +0000 |
951 | @@ -144,6 +144,10 @@ |
952 | |
953 | float getVolumeValue(bool *isValid = nullptr); |
954 | |
955 | + static QVariant waitPropertyChanged(QSignalSpy * signalSpy, QString property); |
956 | + |
957 | + QVariant waitLastRunningPlayerChanged(); |
958 | + |
959 | QtDBusTest::DBusTestRunner dbusTestRunner; |
960 | |
961 | QtDBusMock::DBusMock dbusMock; |
962 | |
963 | === modified file 'tests/integration/test-indicator.cpp' |
964 | --- tests/integration/test-indicator.cpp 2016-02-10 13:08:49 +0000 |
965 | +++ tests/integration/test-indicator.cpp 2016-03-03 08:59:58 +0000 |
966 | @@ -394,9 +394,7 @@ |
967 | .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
968 | ) |
969 | .item(mh::MenuItemMatcher() |
970 | - .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop") |
971 | .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop") |
972 | - .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop") |
973 | .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
974 | ) |
975 | ) |
976 | @@ -925,16 +923,75 @@ |
977 | .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
978 | ) |
979 | .item(mh::MenuItemMatcher() |
980 | - .string_attribute("x-canonical-previous-action","indicator.previous.testplayer3.desktop") |
981 | - .string_attribute("x-canonical-play-action","indicator.play.testplayer3.desktop") |
982 | - .string_attribute("x-canonical-next-action","indicator.next.testplayer3.desktop") |
983 | - .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
984 | - ) |
985 | - ) |
986 | - .item(mh::MenuItemMatcher() |
987 | - .label("Sound Settings…") |
988 | - ) |
989 | - ).match()); |
990 | + .string_attribute("x-canonical-play-action","indicator.play.testplayer3.desktop") |
991 | + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
992 | + ) |
993 | + ) |
994 | + .item(mh::MenuItemMatcher() |
995 | + .label("Sound Settings…") |
996 | + ) |
997 | + ).match()); |
998 | + |
999 | + // check that the last running player is the one we expect |
1000 | + QVariant lastPlayerRunning = waitLastRunningPlayerChanged(); |
1001 | + EXPECT_TRUE(lastPlayerRunning.type() == QVariant::String); |
1002 | + EXPECT_EQ(lastPlayerRunning.toString(), "testplayer3.desktop"); |
1003 | + |
1004 | + // restart the indicator to simulate a new user session |
1005 | + ASSERT_NO_THROW(startIndicator()); |
1006 | + |
1007 | + // check that player 3 is the only one with playback controls |
1008 | + // as it was the last one being stopped |
1009 | + EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters()) |
1010 | + .item(mh::MenuItemMatcher() |
1011 | + .action("indicator.root") |
1012 | + .string_attribute("x-canonical-type", "com.canonical.indicator.root") |
1013 | + .string_attribute("x-canonical-secondary-action", "indicator.mute") |
1014 | + .mode(mh::MenuItemMatcher::Mode::all) |
1015 | + .submenu() |
1016 | + .item(mh::MenuItemMatcher() |
1017 | + .section() |
1018 | + .item(mh::MenuItemMatcher().checkbox() |
1019 | + .label("Mute") |
1020 | + ) |
1021 | + .item(volumeSlider(INITIAL_VOLUME, "Volume")) |
1022 | + ) |
1023 | + .item(mh::MenuItemMatcher() |
1024 | + .section() |
1025 | + .item(mh::MenuItemMatcher() |
1026 | + .action("indicator.testplayer3.desktop") |
1027 | + .label("TestPlayer3") |
1028 | + .themed_icon("icon", {"testplayer"}) |
1029 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
1030 | + ) |
1031 | + .item(mh::MenuItemMatcher() |
1032 | + .string_attribute("x-canonical-play-action","indicator.play.testplayer3.desktop") |
1033 | + .string_attribute("x-canonical-type","com.canonical.unity.playback-item") |
1034 | + ) |
1035 | + ) |
1036 | + .item(mh::MenuItemMatcher() |
1037 | + .section() |
1038 | + .item(mh::MenuItemMatcher() |
1039 | + .action("indicator.testplayer1.desktop") |
1040 | + .label("TestPlayer1") |
1041 | + .themed_icon("icon", {"testplayer"}) |
1042 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
1043 | + ) |
1044 | + ) |
1045 | + .item(mh::MenuItemMatcher() |
1046 | + .section() |
1047 | + .item(mh::MenuItemMatcher() |
1048 | + .action("indicator.testplayer2.desktop") |
1049 | + .label("TestPlayer2") |
1050 | + .themed_icon("icon", {"testplayer"}) |
1051 | + .string_attribute("x-canonical-type", "com.canonical.unity.media-player") |
1052 | + ) |
1053 | + ) |
1054 | + .item(mh::MenuItemMatcher() |
1055 | + .label("Sound Settings…") |
1056 | + ) |
1057 | + ).match()); |
1058 | + |
1059 | } |
1060 | |
1061 | TEST_F(TestIndicator, DesktopMprisPlayerButtonsState) |
1062 | |
1063 | === modified file 'tests/notifications-test.cc' |
1064 | --- tests/notifications-test.cc 2016-01-05 19:15:46 +0000 |
1065 | +++ tests/notifications-test.cc 2016-03-03 08:59:58 +0000 |
1066 | @@ -36,592 +36,602 @@ |
1067 | |
1068 | class NotificationsTest : public ::testing::Test |
1069 | { |
1070 | - protected: |
1071 | - DbusTestService * service = NULL; |
1072 | - |
1073 | - GDBusConnection * session = NULL; |
1074 | - std::shared_ptr<NotificationsMock> notifications; |
1075 | - |
1076 | - virtual void SetUp() { |
1077 | - g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); |
1078 | - g_setenv("GSETTINGS_BACKEND", "memory", TRUE); |
1079 | - |
1080 | - service = dbus_test_service_new(NULL); |
1081 | - dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_SESSION); |
1082 | - |
1083 | - /* Useful for debugging test failures, not needed all the time (until it fails) */ |
1084 | - #if 0 |
1085 | - auto bustle = std::shared_ptr<DbusTestTask>([]() { |
1086 | - DbusTestTask * bustle = DBUS_TEST_TASK(dbus_test_bustle_new("notifications-test.bustle")); |
1087 | - dbus_test_task_set_name(bustle, "Bustle"); |
1088 | - dbus_test_task_set_bus(bustle, DBUS_TEST_SERVICE_BUS_SESSION); |
1089 | - return bustle; |
1090 | - }(), [](DbusTestTask * bustle) { |
1091 | - g_clear_object(&bustle); |
1092 | - }); |
1093 | - dbus_test_service_add_task(service, bustle.get()); |
1094 | - #endif |
1095 | - |
1096 | - notifications = std::make_shared<NotificationsMock>(); |
1097 | - |
1098 | - dbus_test_service_add_task(service, (DbusTestTask*)*notifications); |
1099 | - dbus_test_service_start_tasks(service); |
1100 | - |
1101 | - session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1102 | - ASSERT_NE(nullptr, session); |
1103 | - g_dbus_connection_set_exit_on_close(session, FALSE); |
1104 | - g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session); |
1105 | - |
1106 | - /* This is done in main.c */ |
1107 | - notify_init("indicator-sound"); |
1108 | - } |
1109 | - |
1110 | - virtual void TearDown() { |
1111 | - if (notify_is_initted()) |
1112 | - notify_uninit(); |
1113 | - |
1114 | - notifications.reset(); |
1115 | - g_clear_object(&service); |
1116 | - |
1117 | - g_object_unref(session); |
1118 | - |
1119 | - unsigned int cleartry = 0; |
1120 | - while (session != NULL && cleartry < 100) { |
1121 | - loop(100); |
1122 | - cleartry++; |
1123 | - } |
1124 | - |
1125 | - ASSERT_EQ(nullptr, session); |
1126 | - } |
1127 | - |
1128 | - static gboolean timeout_cb (gpointer user_data) { |
1129 | - GMainLoop * loop = static_cast<GMainLoop *>(user_data); |
1130 | - g_main_loop_quit(loop); |
1131 | - return G_SOURCE_REMOVE; |
1132 | - } |
1133 | - |
1134 | - void loop (unsigned int ms) { |
1135 | - GMainLoop * loop = g_main_loop_new(NULL, FALSE); |
1136 | - g_timeout_add(ms, timeout_cb, loop); |
1137 | - g_main_loop_run(loop); |
1138 | - g_main_loop_unref(loop); |
1139 | - } |
1140 | - |
1141 | - void loop_until(const std::function<bool()>& test, unsigned int max_ms=50, unsigned int test_interval_ms=10) { |
1142 | - |
1143 | - // g_timeout's callback only allows a single pointer, |
1144 | - // so use a temporary stack struct to wedge everything into one pointer |
1145 | - struct CallbackData { |
1146 | - const std::function<bool()>& test; |
1147 | - const gint64 deadline; |
1148 | - GMainLoop* loop = g_main_loop_new(nullptr, false); |
1149 | - CallbackData (const std::function<bool()>& f, unsigned int max_ms): |
1150 | - test{f}, |
1151 | - deadline{g_get_monotonic_time() + (max_ms*1000)} {} |
1152 | - ~CallbackData() {g_main_loop_unref(loop);} |
1153 | - } data(test, max_ms); |
1154 | - |
1155 | - // tell the timer to stop looping on success or deadline |
1156 | - auto timerfunc = [](gpointer gdata) -> gboolean { |
1157 | - auto& data = *static_cast<CallbackData*>(gdata); |
1158 | - if (!data.test() && (g_get_monotonic_time() < data.deadline)) |
1159 | - return G_SOURCE_CONTINUE; |
1160 | - g_main_loop_quit(data.loop); |
1161 | - return G_SOURCE_REMOVE; |
1162 | - }; |
1163 | - |
1164 | - // start looping |
1165 | - g_timeout_add (std::min(max_ms, test_interval_ms), timerfunc, &data); |
1166 | - g_main_loop_run(data.loop); |
1167 | - } |
1168 | - |
1169 | - void loop_until_notifications(unsigned int max_seconds=1) { |
1170 | - auto test = [this]{ return !notifications->getNotifications().empty(); }; |
1171 | - loop_until(test, max_seconds); |
1172 | - } |
1173 | - |
1174 | - static int unref_idle (gpointer user_data) { |
1175 | - g_variant_unref(static_cast<GVariant *>(user_data)); |
1176 | - return G_SOURCE_REMOVE; |
1177 | - } |
1178 | - |
1179 | - std::shared_ptr<MediaPlayerList> playerListMock () { |
1180 | - auto playerList = std::shared_ptr<MediaPlayerList>( |
1181 | - MEDIA_PLAYER_LIST(media_player_list_mock_new()), |
1182 | - [](MediaPlayerList * list) { |
1183 | - g_clear_object(&list); |
1184 | - }); |
1185 | - return playerList; |
1186 | - } |
1187 | - |
1188 | - std::shared_ptr<IndicatorSoundOptions> optionsMock () { |
1189 | - auto options = std::shared_ptr<IndicatorSoundOptions>( |
1190 | - INDICATOR_SOUND_OPTIONS(options_mock_new()), |
1191 | - [](IndicatorSoundOptions * options){ |
1192 | - g_clear_object(&options); |
1193 | - }); |
1194 | - return options; |
1195 | - } |
1196 | - |
1197 | - std::shared_ptr<VolumeControl> volumeControlMock (const std::shared_ptr<IndicatorSoundOptions>& optionsMock) { |
1198 | - auto volumeControl = std::shared_ptr<VolumeControl>( |
1199 | - VOLUME_CONTROL(volume_control_mock_new(optionsMock.get())), |
1200 | - [](VolumeControl * control){ |
1201 | - g_clear_object(&control); |
1202 | - }); |
1203 | - return volumeControl; |
1204 | - } |
1205 | - |
1206 | - std::shared_ptr<VolumeWarning> volumeWarningMock (const std::shared_ptr<IndicatorSoundOptions>& optionsMock) { |
1207 | - auto volumeWarning = std::shared_ptr<VolumeWarning>( |
1208 | - VOLUME_WARNING(volume_warning_mock_new(optionsMock.get())), |
1209 | - [](VolumeWarning * warning){ |
1210 | - g_clear_object(&warning); |
1211 | - }); |
1212 | - return volumeWarning; |
1213 | - } |
1214 | - |
1215 | - std::shared_ptr<IndicatorSoundService> standardService ( |
1216 | - const std::shared_ptr<VolumeControl>& volumeControl, |
1217 | - const std::shared_ptr<MediaPlayerList>& playerList, |
1218 | - const std::shared_ptr<IndicatorSoundOptions>& options, |
1219 | - const std::shared_ptr<VolumeWarning>& warning) { |
1220 | - auto soundService = std::shared_ptr<IndicatorSoundService>( |
1221 | - indicator_sound_service_new(playerList.get(), volumeControl.get(), nullptr, options.get(), warning.get()), |
1222 | - [](IndicatorSoundService * service){ |
1223 | - g_clear_object(&service); |
1224 | - }); |
1225 | - |
1226 | - return soundService; |
1227 | - } |
1228 | - |
1229 | - void setMockVolume (std::shared_ptr<VolumeControl> volumeControl, double volume, VolumeControlVolumeReasons reason = VOLUME_CONTROL_VOLUME_REASONS_USER_KEYPRESS) { |
1230 | - VolumeControlVolume * vol = volume_control_volume_new(); |
1231 | - vol->volume = volume; |
1232 | - vol->reason = reason; |
1233 | - |
1234 | - volume_control_set_volume(volumeControl.get(), vol); |
1235 | - g_object_unref(vol); |
1236 | - } |
1237 | - |
1238 | - void setIndicatorShown (bool shown) { |
1239 | - auto bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr); |
1240 | - |
1241 | - g_dbus_connection_call(bus, |
1242 | - g_dbus_connection_get_unique_name(bus), |
1243 | - "/com/canonical/indicator/sound", |
1244 | - "org.gtk.Actions", |
1245 | - "SetState", |
1246 | - g_variant_new("(sva{sv})", "indicator-shown", g_variant_new_boolean(shown), nullptr), |
1247 | - nullptr, |
1248 | - G_DBUS_CALL_FLAGS_NONE, |
1249 | - -1, |
1250 | - nullptr, |
1251 | - nullptr, |
1252 | - nullptr); |
1253 | - |
1254 | - g_clear_object(&bus); |
1255 | - } |
1256 | + protected: |
1257 | + DbusTestService * service = NULL; |
1258 | + |
1259 | + GDBusConnection * session = NULL; |
1260 | + std::shared_ptr<NotificationsMock> notifications; |
1261 | + |
1262 | + virtual void SetUp() { |
1263 | + g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); |
1264 | + g_setenv("GSETTINGS_BACKEND", "memory", TRUE); |
1265 | + |
1266 | + service = dbus_test_service_new(NULL); |
1267 | + dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_SESSION); |
1268 | + |
1269 | + /* Useful for debugging test failures, not needed all the time (until it fails) */ |
1270 | + #if 0 |
1271 | + auto bustle = std::shared_ptr<DbusTestTask>([]() { |
1272 | + DbusTestTask * bustle = DBUS_TEST_TASK(dbus_test_bustle_new("notifications-test.bustle")); |
1273 | + dbus_test_task_set_name(bustle, "Bustle"); |
1274 | + dbus_test_task_set_bus(bustle, DBUS_TEST_SERVICE_BUS_SESSION); |
1275 | + return bustle; |
1276 | + }(), [](DbusTestTask * bustle) { |
1277 | + g_clear_object(&bustle); |
1278 | + }); |
1279 | + dbus_test_service_add_task(service, bustle.get()); |
1280 | + #endif |
1281 | + |
1282 | + notifications = std::make_shared<NotificationsMock>(); |
1283 | + |
1284 | + dbus_test_service_add_task(service, (DbusTestTask*)*notifications); |
1285 | + dbus_test_service_start_tasks(service); |
1286 | + |
1287 | + session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1288 | + ASSERT_NE(nullptr, session); |
1289 | + g_dbus_connection_set_exit_on_close(session, FALSE); |
1290 | + g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session); |
1291 | + |
1292 | + /* This is done in main.c */ |
1293 | + notify_init("indicator-sound"); |
1294 | + } |
1295 | + |
1296 | + virtual void TearDown() { |
1297 | + if (notify_is_initted()) |
1298 | + notify_uninit(); |
1299 | + |
1300 | + notifications.reset(); |
1301 | + g_clear_object(&service); |
1302 | + |
1303 | + g_object_unref(session); |
1304 | + |
1305 | + unsigned int cleartry = 0; |
1306 | + while (session != NULL && cleartry < 100) { |
1307 | + loop(100); |
1308 | + cleartry++; |
1309 | + } |
1310 | + |
1311 | + ASSERT_EQ(nullptr, session); |
1312 | + } |
1313 | + |
1314 | + static gboolean timeout_cb (gpointer user_data) { |
1315 | + GMainLoop * loop = static_cast<GMainLoop *>(user_data); |
1316 | + g_main_loop_quit(loop); |
1317 | + return G_SOURCE_REMOVE; |
1318 | + } |
1319 | + |
1320 | + void loop (unsigned int ms) { |
1321 | + GMainLoop * loop = g_main_loop_new(NULL, FALSE); |
1322 | + g_timeout_add(ms, timeout_cb, loop); |
1323 | + g_main_loop_run(loop); |
1324 | + g_main_loop_unref(loop); |
1325 | + } |
1326 | + |
1327 | + void loop_until(const std::function<bool()>& test, unsigned int max_ms=50, unsigned int test_interval_ms=10) { |
1328 | + |
1329 | + // g_timeout's callback only allows a single pointer, |
1330 | + // so use a temporary stack struct to wedge everything into one pointer |
1331 | + struct CallbackData { |
1332 | + const std::function<bool()>& test; |
1333 | + const gint64 deadline; |
1334 | + GMainLoop* loop = g_main_loop_new(nullptr, false); |
1335 | + CallbackData (const std::function<bool()>& f, unsigned int max_ms): |
1336 | + test{f}, |
1337 | + deadline{g_get_monotonic_time() + (max_ms*1000)} {} |
1338 | + ~CallbackData() {g_main_loop_unref(loop);} |
1339 | + } data(test, max_ms); |
1340 | + |
1341 | + // tell the timer to stop looping on success or deadline |
1342 | + auto timerfunc = [](gpointer gdata) -> gboolean { |
1343 | + auto& data = *static_cast<CallbackData*>(gdata); |
1344 | + if (!data.test() && (g_get_monotonic_time() < data.deadline)) |
1345 | + return G_SOURCE_CONTINUE; |
1346 | + g_main_loop_quit(data.loop); |
1347 | + return G_SOURCE_REMOVE; |
1348 | + }; |
1349 | + |
1350 | + // start looping |
1351 | + g_timeout_add (std::min(max_ms, test_interval_ms), timerfunc, &data); |
1352 | + g_main_loop_run(data.loop); |
1353 | + } |
1354 | + |
1355 | + void loop_until_notifications(unsigned int max_seconds=1) { |
1356 | + auto test = [this]{ return !notifications->getNotifications().empty(); }; |
1357 | + loop_until(test, max_seconds); |
1358 | + } |
1359 | + |
1360 | + static int unref_idle (gpointer user_data) { |
1361 | + g_variant_unref(static_cast<GVariant *>(user_data)); |
1362 | + return G_SOURCE_REMOVE; |
1363 | + } |
1364 | + |
1365 | + std::shared_ptr<MediaPlayerList> playerListMock () { |
1366 | + auto playerList = std::shared_ptr<MediaPlayerList>( |
1367 | + MEDIA_PLAYER_LIST(media_player_list_mock_new()), |
1368 | + [](MediaPlayerList * list) { |
1369 | + g_clear_object(&list); |
1370 | + }); |
1371 | + return playerList; |
1372 | + } |
1373 | + |
1374 | + std::shared_ptr<IndicatorSoundOptions> optionsMock () { |
1375 | + auto options = std::shared_ptr<IndicatorSoundOptions>( |
1376 | + INDICATOR_SOUND_OPTIONS(options_mock_new()), |
1377 | + [](IndicatorSoundOptions * options){ |
1378 | + g_clear_object(&options); |
1379 | + }); |
1380 | + return options; |
1381 | + } |
1382 | + |
1383 | + std::shared_ptr<VolumeControl> volumeControlMock (const std::shared_ptr<IndicatorSoundOptions>& optionsMock) { |
1384 | + auto volumeControl = std::shared_ptr<VolumeControl>( |
1385 | + VOLUME_CONTROL(volume_control_mock_new(optionsMock.get())), |
1386 | + [](VolumeControl * control){ |
1387 | + g_clear_object(&control); |
1388 | + }); |
1389 | + return volumeControl; |
1390 | + } |
1391 | + |
1392 | + std::shared_ptr<VolumeWarning> volumeWarningMock (const std::shared_ptr<IndicatorSoundOptions>& optionsMock) { |
1393 | + auto volumeWarning = std::shared_ptr<VolumeWarning>( |
1394 | + VOLUME_WARNING(volume_warning_mock_new(optionsMock.get())), |
1395 | + [](VolumeWarning * warning){ |
1396 | + g_clear_object(&warning); |
1397 | + }); |
1398 | + return volumeWarning; |
1399 | + } |
1400 | + |
1401 | + std::shared_ptr<IndicatorSoundService> standardService ( |
1402 | + const std::shared_ptr<VolumeControl>& volumeControl, |
1403 | + const std::shared_ptr<MediaPlayerList>& playerList, |
1404 | + const std::shared_ptr<IndicatorSoundOptions>& options, |
1405 | + const std::shared_ptr<VolumeWarning>& warning, |
1406 | + const std::shared_ptr<AccountsServiceAccess>& accounts_service_access) { |
1407 | + auto soundService = std::shared_ptr<IndicatorSoundService>( |
1408 | + indicator_sound_service_new(playerList.get(), volumeControl.get(), nullptr, options.get(), warning.get(), accounts_service_access.get()), |
1409 | + [](IndicatorSoundService * service){ |
1410 | + g_clear_object(&service); |
1411 | + }); |
1412 | + |
1413 | + return soundService; |
1414 | + } |
1415 | + |
1416 | + void setMockVolume (std::shared_ptr<VolumeControl> volumeControl, double volume, VolumeControlVolumeReasons reason = VOLUME_CONTROL_VOLUME_REASONS_USER_KEYPRESS) { |
1417 | + VolumeControlVolume * vol = volume_control_volume_new(); |
1418 | + vol->volume = volume; |
1419 | + vol->reason = reason; |
1420 | + |
1421 | + volume_control_set_volume(volumeControl.get(), vol); |
1422 | + g_object_unref(vol); |
1423 | + } |
1424 | + |
1425 | + void setIndicatorShown (bool shown) { |
1426 | + auto bus = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr); |
1427 | + |
1428 | + g_dbus_connection_call(bus, |
1429 | + g_dbus_connection_get_unique_name(bus), |
1430 | + "/com/canonical/indicator/sound", |
1431 | + "org.gtk.Actions", |
1432 | + "SetState", |
1433 | + g_variant_new("(sva{sv})", "indicator-shown", g_variant_new_boolean(shown), nullptr), |
1434 | + nullptr, |
1435 | + G_DBUS_CALL_FLAGS_NONE, |
1436 | + -1, |
1437 | + nullptr, |
1438 | + nullptr, |
1439 | + nullptr); |
1440 | + |
1441 | + g_clear_object(&bus); |
1442 | + } |
1443 | |
1444 | }; |
1445 | |
1446 | TEST_F(NotificationsTest, BasicObject) { |
1447 | - auto options = optionsMock(); |
1448 | - auto volumeControl = volumeControlMock(options); |
1449 | - auto volumeWarning = volumeWarningMock(options); |
1450 | - auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning); |
1451 | - |
1452 | - /* Give some time settle */ |
1453 | - loop(50); |
1454 | - |
1455 | - /* Auto free */ |
1456 | + auto options = optionsMock(); |
1457 | + auto volumeControl = volumeControlMock(options); |
1458 | + auto volumeWarning = volumeWarningMock(options); |
1459 | + auto accountsService = std::make_shared<AccountsServiceAccess>(); |
1460 | + auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService); |
1461 | + |
1462 | + /* Give some time settle */ |
1463 | + loop(50); |
1464 | + |
1465 | + /* Auto free */ |
1466 | } |
1467 | |
1468 | TEST_F(NotificationsTest, VolumeChanges) { |
1469 | - auto options = optionsMock(); |
1470 | - auto volumeControl = volumeControlMock(options); |
1471 | - auto volumeWarning = volumeWarningMock(options); |
1472 | - auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning); |
1473 | - |
1474 | - /* Set a volume */ |
1475 | - notifications->clearNotifications(); |
1476 | - setMockVolume(volumeControl, 0.50); |
1477 | - loop(50); |
1478 | - auto notev = notifications->getNotifications(); |
1479 | - ASSERT_EQ(1, notev.size()); |
1480 | - EXPECT_EQ("indicator-sound", notev[0].app_name); |
1481 | - EXPECT_EQ("Volume", notev[0].summary); |
1482 | - EXPECT_EQ(0, notev[0].actions.size()); |
1483 | - EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]); |
1484 | - EXPECT_GVARIANT_EQ("@i 50", notev[0].hints["value"]); |
1485 | - |
1486 | - /* Set a different volume */ |
1487 | - notifications->clearNotifications(); |
1488 | - setMockVolume(volumeControl, 0.60); |
1489 | - loop(50); |
1490 | - notev = notifications->getNotifications(); |
1491 | - ASSERT_EQ(1, notev.size()); |
1492 | - EXPECT_GVARIANT_EQ("@i 60", notev[0].hints["value"]); |
1493 | - |
1494 | - /* Have pulse set a volume */ |
1495 | - notifications->clearNotifications(); |
1496 | - setMockVolume(volumeControl, 0.70, VOLUME_CONTROL_VOLUME_REASONS_PULSE_CHANGE); |
1497 | - loop(50); |
1498 | - notev = notifications->getNotifications(); |
1499 | - ASSERT_EQ(0, notev.size()); |
1500 | - |
1501 | - /* Have AS set the volume */ |
1502 | - notifications->clearNotifications(); |
1503 | - setMockVolume(volumeControl, 0.80, VOLUME_CONTROL_VOLUME_REASONS_ACCOUNTS_SERVICE_SET); |
1504 | - loop(50); |
1505 | - notev = notifications->getNotifications(); |
1506 | - ASSERT_EQ(0, notev.size()); |
1507 | + auto options = optionsMock(); |
1508 | + auto volumeControl = volumeControlMock(options); |
1509 | + auto volumeWarning = volumeWarningMock(options); |
1510 | + auto accountsService = std::make_shared<AccountsServiceAccess>(); |
1511 | + auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService); |
1512 | + |
1513 | + /* Set a volume */ |
1514 | + notifications->clearNotifications(); |
1515 | + setMockVolume(volumeControl, 0.50); |
1516 | + loop(50); |
1517 | + auto notev = notifications->getNotifications(); |
1518 | + ASSERT_EQ(1, notev.size()); |
1519 | + EXPECT_EQ("indicator-sound", notev[0].app_name); |
1520 | + EXPECT_EQ("Volume", notev[0].summary); |
1521 | + EXPECT_EQ(0, notev[0].actions.size()); |
1522 | + EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]); |
1523 | + EXPECT_GVARIANT_EQ("@i 50", notev[0].hints["value"]); |
1524 | + |
1525 | + /* Set a different volume */ |
1526 | + notifications->clearNotifications(); |
1527 | + setMockVolume(volumeControl, 0.60); |
1528 | + loop(50); |
1529 | + notev = notifications->getNotifications(); |
1530 | + ASSERT_EQ(1, notev.size()); |
1531 | + EXPECT_GVARIANT_EQ("@i 60", notev[0].hints["value"]); |
1532 | + |
1533 | + /* Have pulse set a volume */ |
1534 | + notifications->clearNotifications(); |
1535 | + setMockVolume(volumeControl, 0.70, VOLUME_CONTROL_VOLUME_REASONS_PULSE_CHANGE); |
1536 | + loop(50); |
1537 | + notev = notifications->getNotifications(); |
1538 | + ASSERT_EQ(0, notev.size()); |
1539 | + |
1540 | + /* Have AS set the volume */ |
1541 | + notifications->clearNotifications(); |
1542 | + setMockVolume(volumeControl, 0.80, VOLUME_CONTROL_VOLUME_REASONS_ACCOUNTS_SERVICE_SET); |
1543 | + loop(50); |
1544 | + notev = notifications->getNotifications(); |
1545 | + ASSERT_EQ(0, notev.size()); |
1546 | } |
1547 | |
1548 | TEST_F(NotificationsTest, StreamChanges) { |
1549 | - auto options = optionsMock(); |
1550 | - auto volumeControl = volumeControlMock(options); |
1551 | - auto volumeWarning = volumeWarningMock(options); |
1552 | - auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning); |
1553 | - |
1554 | - /* Set a volume */ |
1555 | - notifications->clearNotifications(); |
1556 | - setMockVolume(volumeControl, 0.5); |
1557 | - loop(50); |
1558 | - auto notev = notifications->getNotifications(); |
1559 | - ASSERT_EQ(1, notev.size()); |
1560 | - |
1561 | - /* Change Streams, no volume change */ |
1562 | - notifications->clearNotifications(); |
1563 | - volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALARM); |
1564 | - setMockVolume(volumeControl, 0.5, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE); |
1565 | - loop(50); |
1566 | - notev = notifications->getNotifications(); |
1567 | - EXPECT_EQ(0, notev.size()); |
1568 | - |
1569 | - /* Change Streams, volume change */ |
1570 | - notifications->clearNotifications(); |
1571 | - volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALERT); |
1572 | - setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE); |
1573 | - loop(50); |
1574 | - notev = notifications->getNotifications(); |
1575 | - EXPECT_EQ(0, notev.size()); |
1576 | - |
1577 | - /* Change Streams, no volume change, volume up */ |
1578 | - notifications->clearNotifications(); |
1579 | - volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_MULTIMEDIA); |
1580 | - setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE); |
1581 | - loop(50); |
1582 | - setMockVolume(volumeControl, 0.65); |
1583 | - notev = notifications->getNotifications(); |
1584 | - EXPECT_EQ(1, notev.size()); |
1585 | - EXPECT_GVARIANT_EQ("@i 65", notev[0].hints["value"]); |
1586 | + auto options = optionsMock(); |
1587 | + auto volumeControl = volumeControlMock(options); |
1588 | + auto volumeWarning = volumeWarningMock(options); |
1589 | + auto accountsService = std::make_shared<AccountsServiceAccess>(); |
1590 | + auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService); |
1591 | + |
1592 | + /* Set a volume */ |
1593 | + notifications->clearNotifications(); |
1594 | + setMockVolume(volumeControl, 0.5); |
1595 | + loop(50); |
1596 | + auto notev = notifications->getNotifications(); |
1597 | + ASSERT_EQ(1, notev.size()); |
1598 | + |
1599 | + /* Change Streams, no volume change */ |
1600 | + notifications->clearNotifications(); |
1601 | + volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALARM); |
1602 | + setMockVolume(volumeControl, 0.5, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE); |
1603 | + loop(50); |
1604 | + notev = notifications->getNotifications(); |
1605 | + EXPECT_EQ(0, notev.size()); |
1606 | + |
1607 | + /* Change Streams, volume change */ |
1608 | + notifications->clearNotifications(); |
1609 | + volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALERT); |
1610 | + setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE); |
1611 | + loop(50); |
1612 | + notev = notifications->getNotifications(); |
1613 | + EXPECT_EQ(0, notev.size()); |
1614 | + |
1615 | + /* Change Streams, no volume change, volume up */ |
1616 | + notifications->clearNotifications(); |
1617 | + volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_MULTIMEDIA); |
1618 | + setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE); |
1619 | + loop(50); |
1620 | + setMockVolume(volumeControl, 0.65); |
1621 | + notev = notifications->getNotifications(); |
1622 | + EXPECT_EQ(1, notev.size()); |
1623 | + EXPECT_GVARIANT_EQ("@i 65", notev[0].hints["value"]); |
1624 | } |
1625 | |
1626 | TEST_F(NotificationsTest, IconTesting) { |
1627 | - auto options = optionsMock(); |
1628 | - auto volumeControl = volumeControlMock(options); |
1629 | - auto volumeWarning = volumeWarningMock(options); |
1630 | - auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning); |
1631 | - |
1632 | - /* Set an initial volume */ |
1633 | - notifications->clearNotifications(); |
1634 | - setMockVolume(volumeControl, 0.5); |
1635 | - loop(50); |
1636 | - auto notev = notifications->getNotifications(); |
1637 | - ASSERT_EQ(1, notev.size()); |
1638 | - |
1639 | - /* Generate a set of notifications */ |
1640 | - notifications->clearNotifications(); |
1641 | - for (float i = 0.0; i < 1.01; i += 0.1) { |
1642 | - setMockVolume(volumeControl, i); |
1643 | - } |
1644 | - |
1645 | - loop(50); |
1646 | - notev = notifications->getNotifications(); |
1647 | - ASSERT_EQ(11, notev.size()); |
1648 | - |
1649 | - EXPECT_EQ("audio-volume-muted", notev[0].app_icon); |
1650 | - EXPECT_EQ("audio-volume-low", notev[1].app_icon); |
1651 | - EXPECT_EQ("audio-volume-low", notev[2].app_icon); |
1652 | - EXPECT_EQ("audio-volume-medium", notev[3].app_icon); |
1653 | - EXPECT_EQ("audio-volume-medium", notev[4].app_icon); |
1654 | - EXPECT_EQ("audio-volume-medium", notev[5].app_icon); |
1655 | - EXPECT_EQ("audio-volume-medium", notev[6].app_icon); |
1656 | - EXPECT_EQ("audio-volume-high", notev[7].app_icon); |
1657 | - EXPECT_EQ("audio-volume-high", notev[8].app_icon); |
1658 | - EXPECT_EQ("audio-volume-high", notev[9].app_icon); |
1659 | - EXPECT_EQ("audio-volume-high", notev[10].app_icon); |
1660 | + auto options = optionsMock(); |
1661 | + auto volumeControl = volumeControlMock(options); |
1662 | + auto volumeWarning = volumeWarningMock(options); |
1663 | + auto accountsService = std::make_shared<AccountsServiceAccess>(); |
1664 | + auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService); |
1665 | + |
1666 | + /* Set an initial volume */ |
1667 | + notifications->clearNotifications(); |
1668 | + setMockVolume(volumeControl, 0.5); |
1669 | + loop(50); |
1670 | + auto notev = notifications->getNotifications(); |
1671 | + ASSERT_EQ(1, notev.size()); |
1672 | + |
1673 | + /* Generate a set of notifications */ |
1674 | + notifications->clearNotifications(); |
1675 | + for (float i = 0.0; i < 1.01; i += 0.1) { |
1676 | + setMockVolume(volumeControl, i); |
1677 | + } |
1678 | + |
1679 | + loop(50); |
1680 | + notev = notifications->getNotifications(); |
1681 | + ASSERT_EQ(11, notev.size()); |
1682 | + |
1683 | + EXPECT_EQ("audio-volume-muted", notev[0].app_icon); |
1684 | + EXPECT_EQ("audio-volume-low", notev[1].app_icon); |
1685 | + EXPECT_EQ("audio-volume-low", notev[2].app_icon); |
1686 | + EXPECT_EQ("audio-volume-medium", notev[3].app_icon); |
1687 | + EXPECT_EQ("audio-volume-medium", notev[4].app_icon); |
1688 | + EXPECT_EQ("audio-volume-medium", notev[5].app_icon); |
1689 | + EXPECT_EQ("audio-volume-medium", notev[6].app_icon); |
1690 | + EXPECT_EQ("audio-volume-high", notev[7].app_icon); |
1691 | + EXPECT_EQ("audio-volume-high", notev[8].app_icon); |
1692 | + EXPECT_EQ("audio-volume-high", notev[9].app_icon); |
1693 | + EXPECT_EQ("audio-volume-high", notev[10].app_icon); |
1694 | } |
1695 | |
1696 | TEST_F(NotificationsTest, ServerRestart) { |
1697 | - auto options = optionsMock(); |
1698 | - auto volumeControl = volumeControlMock(options); |
1699 | - auto volumeWarning = volumeWarningMock(options); |
1700 | - auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning); |
1701 | - |
1702 | - /* Set a volume */ |
1703 | - notifications->clearNotifications(); |
1704 | - setMockVolume(volumeControl, 0.50); |
1705 | - loop(50); |
1706 | - auto notev = notifications->getNotifications(); |
1707 | - ASSERT_EQ(1, notev.size()); |
1708 | - |
1709 | - /* Restart server without sync notifications */ |
1710 | - notifications->clearNotifications(); |
1711 | - dbus_test_service_remove_task(service, (DbusTestTask*)*notifications); |
1712 | - notifications.reset(); |
1713 | - |
1714 | - loop(50); |
1715 | - |
1716 | - notifications = std::make_shared<NotificationsMock>(std::vector<std::string>({"body", "body-markup", "icon-static"})); |
1717 | - dbus_test_service_add_task(service, (DbusTestTask*)*notifications); |
1718 | - dbus_test_task_run((DbusTestTask*)*notifications); |
1719 | - |
1720 | - /* Change the volume */ |
1721 | - notifications->clearNotifications(); |
1722 | - setMockVolume(volumeControl, 0.60); |
1723 | - loop(50); |
1724 | - notev = notifications->getNotifications(); |
1725 | - ASSERT_EQ(0, notev.size()); |
1726 | - |
1727 | - /* Put a good server back */ |
1728 | - dbus_test_service_remove_task(service, (DbusTestTask*)*notifications); |
1729 | - notifications.reset(); |
1730 | - |
1731 | - loop(50); |
1732 | - |
1733 | - notifications = std::make_shared<NotificationsMock>(); |
1734 | - dbus_test_service_add_task(service, (DbusTestTask*)*notifications); |
1735 | - dbus_test_task_run((DbusTestTask*)*notifications); |
1736 | - |
1737 | - /* Change the volume again */ |
1738 | - notifications->clearNotifications(); |
1739 | - setMockVolume(volumeControl, 0.70); |
1740 | - loop(50); |
1741 | - notev = notifications->getNotifications(); |
1742 | - ASSERT_EQ(1, notev.size()); |
1743 | + auto options = optionsMock(); |
1744 | + auto volumeControl = volumeControlMock(options); |
1745 | + auto volumeWarning = volumeWarningMock(options); |
1746 | + auto accountsService = std::make_shared<AccountsServiceAccess>(); |
1747 | + auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService); |
1748 | + |
1749 | + /* Set a volume */ |
1750 | + notifications->clearNotifications(); |
1751 | + setMockVolume(volumeControl, 0.50); |
1752 | + loop(50); |
1753 | + auto notev = notifications->getNotifications(); |
1754 | + ASSERT_EQ(1, notev.size()); |
1755 | + |
1756 | + /* Restart server without sync notifications */ |
1757 | + notifications->clearNotifications(); |
1758 | + dbus_test_service_remove_task(service, (DbusTestTask*)*notifications); |
1759 | + notifications.reset(); |
1760 | + |
1761 | + loop(50); |
1762 | + |
1763 | + notifications = std::make_shared<NotificationsMock>(std::vector<std::string>({"body", "body-markup", "icon-static"})); |
1764 | + dbus_test_service_add_task(service, (DbusTestTask*)*notifications); |
1765 | + dbus_test_task_run((DbusTestTask*)*notifications); |
1766 | + |
1767 | + /* Change the volume */ |
1768 | + notifications->clearNotifications(); |
1769 | + setMockVolume(volumeControl, 0.60); |
1770 | + loop(50); |
1771 | + notev = notifications->getNotifications(); |
1772 | + ASSERT_EQ(0, notev.size()); |
1773 | + |
1774 | + /* Put a good server back */ |
1775 | + dbus_test_service_remove_task(service, (DbusTestTask*)*notifications); |
1776 | + notifications.reset(); |
1777 | + |
1778 | + loop(50); |
1779 | + |
1780 | + notifications = std::make_shared<NotificationsMock>(); |
1781 | + dbus_test_service_add_task(service, (DbusTestTask*)*notifications); |
1782 | + dbus_test_task_run((DbusTestTask*)*notifications); |
1783 | + |
1784 | + /* Change the volume again */ |
1785 | + notifications->clearNotifications(); |
1786 | + setMockVolume(volumeControl, 0.70); |
1787 | + loop(50); |
1788 | + notev = notifications->getNotifications(); |
1789 | + ASSERT_EQ(1, notev.size()); |
1790 | } |
1791 | |
1792 | TEST_F(NotificationsTest, HighVolume) { |
1793 | - auto options = optionsMock(); |
1794 | - auto volumeControl = volumeControlMock(options); |
1795 | - auto volumeWarning = volumeWarningMock(options); |
1796 | - auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning); |
1797 | - |
1798 | - /* Set a volume */ |
1799 | - notifications->clearNotifications(); |
1800 | - setMockVolume(volumeControl, 0.50); |
1801 | - loop(50); |
1802 | - auto notev = notifications->getNotifications(); |
1803 | - ASSERT_EQ(1, notev.size()); |
1804 | - EXPECT_EQ("Volume", notev[0].summary); |
1805 | - EXPECT_EQ("Speakers", notev[0].body); |
1806 | - EXPECT_GVARIANT_EQ("@s 'false'", notev[0].hints["x-canonical-value-bar-tint"]); |
1807 | - |
1808 | - /* Set high volume with volume change */ |
1809 | - notifications->clearNotifications(); |
1810 | - volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), true); |
1811 | - setMockVolume(volumeControl, 0.90); |
1812 | - loop(50); |
1813 | - notev = notifications->getNotifications(); |
1814 | - ASSERT_LT(0, notev.size()); /* This passes with one or two since it would just be an update to the first if a second was sent */ |
1815 | - EXPECT_EQ("Volume", notev[0].summary); |
1816 | - EXPECT_EQ("Speakers", notev[0].body); |
1817 | - EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]); |
1818 | - |
1819 | - /* Move it back */ |
1820 | - volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), false); |
1821 | - setMockVolume(volumeControl, 0.50); |
1822 | - loop(50); |
1823 | - |
1824 | - /* Set high volume without level change */ |
1825 | - /* NOTE: This can happen if headphones are plugged in */ |
1826 | - notifications->clearNotifications(); |
1827 | - volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), true); |
1828 | - loop(50); |
1829 | - notev = notifications->getNotifications(); |
1830 | - ASSERT_EQ(1, notev.size()); |
1831 | - EXPECT_EQ("Volume", notev[0].summary); |
1832 | - EXPECT_EQ("Speakers", notev[0].body); |
1833 | - EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]); |
1834 | + auto options = optionsMock(); |
1835 | + auto volumeControl = volumeControlMock(options); |
1836 | + auto volumeWarning = volumeWarningMock(options); |
1837 | + auto accountsService = std::make_shared<AccountsServiceAccess>(); |
1838 | + auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService); |
1839 | + |
1840 | + /* Set a volume */ |
1841 | + notifications->clearNotifications(); |
1842 | + setMockVolume(volumeControl, 0.50); |
1843 | + loop(50); |
1844 | + auto notev = notifications->getNotifications(); |
1845 | + ASSERT_EQ(1, notev.size()); |
1846 | + EXPECT_EQ("Volume", notev[0].summary); |
1847 | + EXPECT_EQ("Speakers", notev[0].body); |
1848 | + EXPECT_GVARIANT_EQ("@s 'false'", notev[0].hints["x-canonical-value-bar-tint"]); |
1849 | + |
1850 | + /* Set high volume with volume change */ |
1851 | + notifications->clearNotifications(); |
1852 | + volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), true); |
1853 | + setMockVolume(volumeControl, 0.90); |
1854 | + loop(50); |
1855 | + notev = notifications->getNotifications(); |
1856 | + ASSERT_LT(0, notev.size()); /* This passes with one or two since it would just be an update to the first if a second was sent */ |
1857 | + EXPECT_EQ("Volume", notev[0].summary); |
1858 | + EXPECT_EQ("Speakers", notev[0].body); |
1859 | + EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]); |
1860 | + |
1861 | + /* Move it back */ |
1862 | + volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), false); |
1863 | + setMockVolume(volumeControl, 0.50); |
1864 | + loop(50); |
1865 | + |
1866 | + /* Set high volume without level change */ |
1867 | + /* NOTE: This can happen if headphones are plugged in */ |
1868 | + notifications->clearNotifications(); |
1869 | + volume_warning_mock_set_high_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), true); |
1870 | + loop(50); |
1871 | + notev = notifications->getNotifications(); |
1872 | + ASSERT_EQ(1, notev.size()); |
1873 | + EXPECT_EQ("Volume", notev[0].summary); |
1874 | + EXPECT_EQ("Speakers", notev[0].body); |
1875 | + EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]); |
1876 | } |
1877 | |
1878 | TEST_F(NotificationsTest, MenuHide) { |
1879 | - auto options = optionsMock(); |
1880 | - auto volumeControl = volumeControlMock(options); |
1881 | - auto volumeWarning = volumeWarningMock(options); |
1882 | - auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning); |
1883 | - |
1884 | - /* Set a volume */ |
1885 | - notifications->clearNotifications(); |
1886 | - setMockVolume(volumeControl, 0.50); |
1887 | - loop(50); |
1888 | - auto notev = notifications->getNotifications(); |
1889 | - EXPECT_EQ(1, notev.size()); |
1890 | - |
1891 | - /* Set the indicator to shown, and set a new volume */ |
1892 | - notifications->clearNotifications(); |
1893 | - setIndicatorShown(true); |
1894 | - loop(50); |
1895 | - setMockVolume(volumeControl, 0.60); |
1896 | - loop(50); |
1897 | - notev = notifications->getNotifications(); |
1898 | - EXPECT_EQ(0, notev.size()); |
1899 | - |
1900 | - /* Set the indicator to hidden, and set a new volume */ |
1901 | - notifications->clearNotifications(); |
1902 | - setIndicatorShown(false); |
1903 | - loop(50); |
1904 | - setMockVolume(volumeControl, 0.70); |
1905 | - loop(50); |
1906 | - notev = notifications->getNotifications(); |
1907 | - EXPECT_EQ(1, notev.size()); |
1908 | + auto options = optionsMock(); |
1909 | + auto volumeControl = volumeControlMock(options); |
1910 | + auto volumeWarning = volumeWarningMock(options); |
1911 | + auto accountsService = std::make_shared<AccountsServiceAccess>(); |
1912 | + auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService); |
1913 | + |
1914 | + /* Set a volume */ |
1915 | + notifications->clearNotifications(); |
1916 | + setMockVolume(volumeControl, 0.50); |
1917 | + loop(50); |
1918 | + auto notev = notifications->getNotifications(); |
1919 | + EXPECT_EQ(1, notev.size()); |
1920 | + |
1921 | + /* Set the indicator to shown, and set a new volume */ |
1922 | + notifications->clearNotifications(); |
1923 | + setIndicatorShown(true); |
1924 | + loop(50); |
1925 | + setMockVolume(volumeControl, 0.60); |
1926 | + loop(50); |
1927 | + notev = notifications->getNotifications(); |
1928 | + EXPECT_EQ(0, notev.size()); |
1929 | + |
1930 | + /* Set the indicator to hidden, and set a new volume */ |
1931 | + notifications->clearNotifications(); |
1932 | + setIndicatorShown(false); |
1933 | + loop(50); |
1934 | + setMockVolume(volumeControl, 0.70); |
1935 | + loop(50); |
1936 | + notev = notifications->getNotifications(); |
1937 | + EXPECT_EQ(1, notev.size()); |
1938 | } |
1939 | |
1940 | TEST_F(NotificationsTest, ExtendendVolumeNotification) { |
1941 | - auto options = optionsMock(); |
1942 | - auto volumeControl = volumeControlMock(options); |
1943 | - auto volumeWarning = volumeWarningMock(options); |
1944 | - auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning); |
1945 | - |
1946 | - /* Set a volume */ |
1947 | - notifications->clearNotifications(); |
1948 | - setMockVolume(volumeControl, 0.50); |
1949 | - loop(50); |
1950 | - auto notev = notifications->getNotifications(); |
1951 | - ASSERT_EQ(1, notev.size()); |
1952 | - EXPECT_EQ("indicator-sound", notev[0].app_name); |
1953 | - EXPECT_EQ("Volume", notev[0].summary); |
1954 | - EXPECT_EQ(0, notev[0].actions.size()); |
1955 | - EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]); |
1956 | - EXPECT_GVARIANT_EQ("@i 50", notev[0].hints["value"]); |
1957 | - |
1958 | - /* Allow an amplified volume */ |
1959 | - notifications->clearNotifications(); |
1960 | - volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALARM); |
1961 | - options_mock_mock_set_max_volume(OPTIONS_MOCK(options.get()), 1.5); |
1962 | - loop(50); |
1963 | - notev = notifications->getNotifications(); |
1964 | - ASSERT_EQ(1, notev.size()); |
1965 | - EXPECT_GVARIANT_EQ("@i 33", notev[0].hints["value"]); |
1966 | - |
1967 | - /* Set to 'over max' */ |
1968 | - notifications->clearNotifications(); |
1969 | - setMockVolume(volumeControl, 1.525); |
1970 | - loop(50); |
1971 | - notev = notifications->getNotifications(); |
1972 | - ASSERT_EQ(1, notev.size()); |
1973 | - EXPECT_GVARIANT_EQ("@i 100", notev[0].hints["value"]); |
1974 | - |
1975 | - /* Put back */ |
1976 | - notifications->clearNotifications(); |
1977 | - options_mock_mock_set_max_volume(OPTIONS_MOCK(options.get()), 1.0); |
1978 | - loop(50); |
1979 | - notev = notifications->getNotifications(); |
1980 | - ASSERT_EQ(1, notev.size()); |
1981 | - EXPECT_GVARIANT_EQ("@i 100", notev[0].hints["value"]); |
1982 | + auto options = optionsMock(); |
1983 | + auto volumeControl = volumeControlMock(options); |
1984 | + auto volumeWarning = volumeWarningMock(options); |
1985 | + auto accountsService = std::make_shared<AccountsServiceAccess>(); |
1986 | + auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService); |
1987 | + |
1988 | + /* Set a volume */ |
1989 | + notifications->clearNotifications(); |
1990 | + setMockVolume(volumeControl, 0.50); |
1991 | + loop(50); |
1992 | + auto notev = notifications->getNotifications(); |
1993 | + ASSERT_EQ(1, notev.size()); |
1994 | + EXPECT_EQ("indicator-sound", notev[0].app_name); |
1995 | + EXPECT_EQ("Volume", notev[0].summary); |
1996 | + EXPECT_EQ(0, notev[0].actions.size()); |
1997 | + EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]); |
1998 | + EXPECT_GVARIANT_EQ("@i 50", notev[0].hints["value"]); |
1999 | + |
2000 | + /* Allow an amplified volume */ |
2001 | + notifications->clearNotifications(); |
2002 | + volume_control_mock_mock_set_active_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), VOLUME_CONTROL_STREAM_ALARM); |
2003 | + options_mock_mock_set_max_volume(OPTIONS_MOCK(options.get()), 1.5); |
2004 | + loop(50); |
2005 | + notev = notifications->getNotifications(); |
2006 | + ASSERT_EQ(1, notev.size()); |
2007 | + EXPECT_GVARIANT_EQ("@i 33", notev[0].hints["value"]); |
2008 | + |
2009 | + /* Set to 'over max' */ |
2010 | + notifications->clearNotifications(); |
2011 | + setMockVolume(volumeControl, 1.525); |
2012 | + loop(50); |
2013 | + notev = notifications->getNotifications(); |
2014 | + ASSERT_EQ(1, notev.size()); |
2015 | + EXPECT_GVARIANT_EQ("@i 100", notev[0].hints["value"]); |
2016 | + |
2017 | + /* Put back */ |
2018 | + notifications->clearNotifications(); |
2019 | + options_mock_mock_set_max_volume(OPTIONS_MOCK(options.get()), 1.0); |
2020 | + loop(50); |
2021 | + notev = notifications->getNotifications(); |
2022 | + ASSERT_EQ(1, notev.size()); |
2023 | + EXPECT_GVARIANT_EQ("@i 100", notev[0].hints["value"]); |
2024 | } |
2025 | |
2026 | TEST_F(NotificationsTest, TriggerWarning) { |
2027 | |
2028 | - // Tests all the conditions needed to trigger a volume warning. |
2029 | - // There are many possible combinations, so this test is slow. :P |
2030 | - |
2031 | - const struct { |
2032 | - bool expected; |
2033 | - VolumeControlActiveOutput output; |
2034 | - } test_outputs[] = { |
2035 | - { false, VOLUME_CONTROL_ACTIVE_OUTPUT_SPEAKERS }, |
2036 | - { true, VOLUME_CONTROL_ACTIVE_OUTPUT_HEADPHONES }, |
2037 | - { true, VOLUME_CONTROL_ACTIVE_OUTPUT_BLUETOOTH_HEADPHONES }, |
2038 | - { false, VOLUME_CONTROL_ACTIVE_OUTPUT_BLUETOOTH_SPEAKER }, |
2039 | - { false, VOLUME_CONTROL_ACTIVE_OUTPUT_USB_SPEAKER }, |
2040 | - { true, VOLUME_CONTROL_ACTIVE_OUTPUT_USB_HEADPHONES }, |
2041 | - { false, VOLUME_CONTROL_ACTIVE_OUTPUT_HDMI_SPEAKER }, |
2042 | - { true, VOLUME_CONTROL_ACTIVE_OUTPUT_HDMI_HEADPHONES }, |
2043 | - { false, VOLUME_CONTROL_ACTIVE_OUTPUT_CALL_MODE } |
2044 | - }; |
2045 | - |
2046 | - const struct { |
2047 | - bool expected; |
2048 | - pa_volume_t volume; |
2049 | - pa_volume_t loud_volume; |
2050 | - } test_volumes[] = { |
2051 | - { false, 50, 100 }, |
2052 | - { false, 99, 100 }, |
2053 | - { true, 100, 100 }, |
2054 | - { true, 101, 100 } |
2055 | - }; |
2056 | - |
2057 | - const struct { |
2058 | - bool expected; |
2059 | - bool approved; |
2060 | - } test_approved[] = { |
2061 | - { true, false }, |
2062 | - { false, true } |
2063 | - }; |
2064 | - |
2065 | - const struct { |
2066 | - bool expected; |
2067 | - bool warnings_enabled; |
2068 | - } test_warnings_enabled[] = { |
2069 | - { true, true }, |
2070 | - { false, false } |
2071 | - }; |
2072 | - |
2073 | - const struct { |
2074 | - bool expected; |
2075 | - bool multimedia_active; |
2076 | - } test_multimedia_active[] = { |
2077 | - { true, true }, |
2078 | - { false, false } |
2079 | - }; |
2080 | - |
2081 | - for (const auto& outputs : test_outputs) { |
2082 | - for (const auto& volumes : test_volumes) { |
2083 | - for (const auto& approved : test_approved) { |
2084 | - for (const auto& warnings_enabled : test_warnings_enabled) { |
2085 | - for (const auto& multimedia_active : test_multimedia_active) { |
2086 | - |
2087 | - notifications->clearNotifications(); |
2088 | - |
2089 | - // instantiate the test subjects |
2090 | - auto options = optionsMock(); |
2091 | - auto volumeControl = volumeControlMock(options); |
2092 | - auto volumeWarning = volumeWarningMock(options); |
2093 | - auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning); |
2094 | - |
2095 | - // run the test |
2096 | - options_mock_mock_set_loud_volume(OPTIONS_MOCK(options.get()), volumes.loud_volume); |
2097 | - options_mock_mock_set_loud_warning_enabled(OPTIONS_MOCK(options.get()), warnings_enabled.warnings_enabled); |
2098 | - volume_warning_mock_set_approved(VOLUME_WARNING_MOCK(volumeWarning.get()), approved.approved); |
2099 | - volume_warning_mock_set_multimedia_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), volumes.volume); |
2100 | - volume_warning_mock_set_multimedia_active(VOLUME_WARNING_MOCK(volumeWarning.get()), multimedia_active.multimedia_active); |
2101 | - volume_control_mock_mock_set_active_output(VOLUME_CONTROL_MOCK(volumeControl.get()), outputs.output); |
2102 | - |
2103 | - loop_until_notifications(); |
2104 | - |
2105 | - // check the result |
2106 | - auto notev = notifications->getNotifications(); |
2107 | - const bool warning_expected = outputs.expected && volumes.expected && approved.expected && warnings_enabled.expected && multimedia_active.expected; |
2108 | - if (warning_expected) { |
2109 | - EXPECT_TRUE(volume_warning_get_active(volumeWarning.get())); |
2110 | - ASSERT_EQ(1, notev.size()); |
2111 | - EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-snap-decisions"]); |
2112 | - EXPECT_GVARIANT_EQ(nullptr, notev[0].hints["x-canonical-private-synchronous"]); |
2113 | - } |
2114 | - else { |
2115 | - EXPECT_FALSE(volume_warning_get_active(volumeWarning.get())); |
2116 | - ASSERT_EQ(1, notev.size()); |
2117 | - EXPECT_GVARIANT_EQ(nullptr, notev[0].hints["x-canonical-snap-decisions"]); |
2118 | - EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]); |
2119 | - } |
2120 | - |
2121 | - } // multimedia_active |
2122 | - } // warnings_enabled |
2123 | - } // approved |
2124 | - } // volumes |
2125 | - } // outputs |
2126 | + // Tests all the conditions needed to trigger a volume warning. |
2127 | + // There are many possible combinations, so this test is slow. :P |
2128 | + |
2129 | + const struct { |
2130 | + bool expected; |
2131 | + VolumeControlActiveOutput output; |
2132 | + } test_outputs[] = { |
2133 | + { false, VOLUME_CONTROL_ACTIVE_OUTPUT_SPEAKERS }, |
2134 | + { true, VOLUME_CONTROL_ACTIVE_OUTPUT_HEADPHONES }, |
2135 | + { true, VOLUME_CONTROL_ACTIVE_OUTPUT_BLUETOOTH_HEADPHONES }, |
2136 | + { false, VOLUME_CONTROL_ACTIVE_OUTPUT_BLUETOOTH_SPEAKER }, |
2137 | + { false, VOLUME_CONTROL_ACTIVE_OUTPUT_USB_SPEAKER }, |
2138 | + { true, VOLUME_CONTROL_ACTIVE_OUTPUT_USB_HEADPHONES }, |
2139 | + { false, VOLUME_CONTROL_ACTIVE_OUTPUT_HDMI_SPEAKER }, |
2140 | + { true, VOLUME_CONTROL_ACTIVE_OUTPUT_HDMI_HEADPHONES }, |
2141 | + { false, VOLUME_CONTROL_ACTIVE_OUTPUT_CALL_MODE } |
2142 | + }; |
2143 | + |
2144 | + const struct { |
2145 | + bool expected; |
2146 | + pa_volume_t volume; |
2147 | + pa_volume_t loud_volume; |
2148 | + } test_volumes[] = { |
2149 | + { false, 50, 100 }, |
2150 | + { false, 99, 100 }, |
2151 | + { true, 100, 100 }, |
2152 | + { true, 101, 100 } |
2153 | + }; |
2154 | + |
2155 | + const struct { |
2156 | + bool expected; |
2157 | + bool approved; |
2158 | + } test_approved[] = { |
2159 | + { true, false }, |
2160 | + { false, true } |
2161 | + }; |
2162 | + |
2163 | + const struct { |
2164 | + bool expected; |
2165 | + bool warnings_enabled; |
2166 | + } test_warnings_enabled[] = { |
2167 | + { true, true }, |
2168 | + { false, false } |
2169 | + }; |
2170 | + |
2171 | + const struct { |
2172 | + bool expected; |
2173 | + bool multimedia_active; |
2174 | + } test_multimedia_active[] = { |
2175 | + { true, true }, |
2176 | + { false, false } |
2177 | + }; |
2178 | + |
2179 | + for (const auto& outputs : test_outputs) { |
2180 | + for (const auto& volumes : test_volumes) { |
2181 | + for (const auto& approved : test_approved) { |
2182 | + for (const auto& warnings_enabled : test_warnings_enabled) { |
2183 | + for (const auto& multimedia_active : test_multimedia_active) { |
2184 | + |
2185 | + notifications->clearNotifications(); |
2186 | + |
2187 | + // instantiate the test subjects |
2188 | + auto options = optionsMock(); |
2189 | + auto volumeControl = volumeControlMock(options); |
2190 | + auto volumeWarning = volumeWarningMock(options); |
2191 | + auto accountsService = std::make_shared<AccountsServiceAccess>(); |
2192 | + auto soundService = standardService(volumeControl, playerListMock(), options, volumeWarning, accountsService); |
2193 | + |
2194 | + // run the test |
2195 | + options_mock_mock_set_loud_volume(OPTIONS_MOCK(options.get()), volumes.loud_volume); |
2196 | + options_mock_mock_set_loud_warning_enabled(OPTIONS_MOCK(options.get()), warnings_enabled.warnings_enabled); |
2197 | + volume_warning_mock_set_approved(VOLUME_WARNING_MOCK(volumeWarning.get()), approved.approved); |
2198 | + volume_warning_mock_set_multimedia_volume(VOLUME_WARNING_MOCK(volumeWarning.get()), volumes.volume); |
2199 | + volume_warning_mock_set_multimedia_active(VOLUME_WARNING_MOCK(volumeWarning.get()), multimedia_active.multimedia_active); |
2200 | + volume_control_mock_mock_set_active_output(VOLUME_CONTROL_MOCK(volumeControl.get()), outputs.output); |
2201 | + |
2202 | + loop_until_notifications(); |
2203 | + |
2204 | + // check the result |
2205 | + auto notev = notifications->getNotifications(); |
2206 | + const bool warning_expected = outputs.expected && volumes.expected && approved.expected && warnings_enabled.expected && multimedia_active.expected; |
2207 | + if (warning_expected) { |
2208 | + EXPECT_TRUE(volume_warning_get_active(volumeWarning.get())); |
2209 | + ASSERT_EQ(1, notev.size()); |
2210 | + EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-snap-decisions"]); |
2211 | + EXPECT_GVARIANT_EQ(nullptr, notev[0].hints["x-canonical-private-synchronous"]); |
2212 | + } |
2213 | + else { |
2214 | + EXPECT_FALSE(volume_warning_get_active(volumeWarning.get())); |
2215 | + ASSERT_EQ(1, notev.size()); |
2216 | + EXPECT_GVARIANT_EQ(nullptr, notev[0].hints["x-canonical-snap-decisions"]); |
2217 | + EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-private-synchronous"]); |
2218 | + } |
2219 | + |
2220 | + } // multimedia_active |
2221 | + } // warnings_enabled |
2222 | + } // approved |
2223 | + } // volumes |
2224 | + } // outputs |
2225 | } |
2226 | |
2227 | |
2228 | === modified file 'tests/service-mocks/accounts-mock/AccountsServiceSoundMock.cpp' |
2229 | --- tests/service-mocks/accounts-mock/AccountsServiceSoundMock.cpp 2015-12-23 13:35:46 +0000 |
2230 | +++ tests/service-mocks/accounts-mock/AccountsServiceSoundMock.cpp 2016-03-03 08:59:58 +0000 |
2231 | @@ -46,3 +46,18 @@ |
2232 | "Volume", |
2233 | property("Volume")); |
2234 | } |
2235 | + |
2236 | +QString AccountsServiceSoundMock::lastRunningPlayer() const |
2237 | +{ |
2238 | + return lastRunningPlayer_; |
2239 | +} |
2240 | + |
2241 | +void AccountsServiceSoundMock::setLastRunningPlayer(QString const & lastRunningPlayer) |
2242 | +{ |
2243 | + lastRunningPlayer_ = lastRunningPlayer; |
2244 | + notifier_.notifyPropertyChanged(QDBusConnection::systemBus(), |
2245 | + ACCOUNTS_SOUND_INTERFACE, |
2246 | + USER_PATH, |
2247 | + "LastRunningPlayer", |
2248 | + property("LastRunningPlayer")); |
2249 | +} |
2250 | |
2251 | === modified file 'tests/service-mocks/accounts-mock/AccountsServiceSoundMock.h' |
2252 | --- tests/service-mocks/accounts-mock/AccountsServiceSoundMock.h 2015-12-23 13:35:46 +0000 |
2253 | +++ tests/service-mocks/accounts-mock/AccountsServiceSoundMock.h 2016-03-03 08:59:58 +0000 |
2254 | @@ -37,10 +37,13 @@ |
2255 | { |
2256 | Q_OBJECT |
2257 | Q_PROPERTY(double Volume READ volume WRITE setVolume) |
2258 | + Q_PROPERTY(QString LastRunningPlayer READ lastRunningPlayer WRITE setLastRunningPlayer) |
2259 | |
2260 | public Q_SLOTS: |
2261 | double volume() const; |
2262 | void setVolume(double volume); |
2263 | + QString lastRunningPlayer() const; |
2264 | + void setLastRunningPlayer(QString const & lastRunningPlayer); |
2265 | |
2266 | public: |
2267 | AccountsServiceSoundMock(QObject* parent = 0); |
2268 | @@ -48,6 +51,7 @@ |
2269 | |
2270 | private: |
2271 | double volume_; |
2272 | + QString lastRunningPlayer_; |
2273 | DBusPropertiesNotifier notifier_; |
2274 | }; |
2275 | |
2276 | |
2277 | === modified file 'tests/service-mocks/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml' |
2278 | --- tests/service-mocks/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml 2015-12-23 13:35:46 +0000 |
2279 | +++ tests/service-mocks/accounts-mock/com.ubuntu.AccountsService.Sound.Mock.xml 2016-03-03 08:59:58 +0000 |
2280 | @@ -2,5 +2,6 @@ |
2281 | <node> |
2282 | <interface name="com.ubuntu.AccountsService.Sound"> |
2283 | <property name="Volume" type="d" access="readwrite"/> |
2284 | + <property name="LastRunningPlayer" type="s" access="readwrite"/> |
2285 | </interface> |
2286 | </node> |
2287 | \ No newline at end of file |
2288 | |
2289 | === modified file 'tests/sound-menu.cc' |
2290 | --- tests/sound-menu.cc 2016-02-10 13:08:49 +0000 |
2291 | +++ tests/sound-menu.cc 2016-03-03 08:59:58 +0000 |
2292 | @@ -62,7 +62,7 @@ |
2293 | |
2294 | void check_player_control_buttons(bool canPlay, bool canNext, bool canPrev) |
2295 | { |
2296 | - SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE, ""); |
2297 | + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); |
2298 | |
2299 | MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); |
2300 | |
2301 | @@ -96,22 +96,22 @@ |
2302 | |
2303 | /* Player control */ |
2304 | verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item")); |
2305 | - //verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("")); |
2306 | - if (!canPlay) { |
2307 | + //verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("")); |
2308 | + if (!canPlay) { |
2309 | verify_item_attribute_is_not_set(section, 1, "x-canonical-play-action", G_VARIANT_TYPE_STRING); |
2310 | - } else { |
2311 | - verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id")); |
2312 | - } |
2313 | - if (!canNext) { |
2314 | + } else { |
2315 | + verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id")); |
2316 | + } |
2317 | + if (!canNext) { |
2318 | verify_item_attribute_is_not_set(section, 1, "x-canonical-next-action", G_VARIANT_TYPE_STRING); |
2319 | - } else { |
2320 | - verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); |
2321 | - } |
2322 | - if (!canPrev) { |
2323 | + } else { |
2324 | + verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id")); |
2325 | + } |
2326 | + if (!canPrev) { |
2327 | verify_item_attribute_is_not_set(section, 1, "x-canonical-previous-action", G_VARIANT_TYPE_STRING); |
2328 | - } else { |
2329 | - verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id")); |
2330 | - } |
2331 | + } else { |
2332 | + verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id")); |
2333 | + } |
2334 | |
2335 | g_clear_object(§ion); |
2336 | |
2337 | @@ -125,7 +125,7 @@ |
2338 | }; |
2339 | |
2340 | TEST_F(SoundMenuTest, BasicObject) { |
2341 | - SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE, ""); |
2342 | + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); |
2343 | |
2344 | ASSERT_NE(nullptr, menu); |
2345 | |
2346 | @@ -134,7 +134,7 @@ |
2347 | } |
2348 | |
2349 | TEST_F(SoundMenuTest, AddRemovePlayer) { |
2350 | - SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE, ""); |
2351 | + SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE); |
2352 | |
2353 | MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url"); |
2354 | |
2355 | |
2356 | === modified file 'tests/volume-control-test.cc' |
2357 | --- tests/volume-control-test.cc 2015-12-29 17:03:41 +0000 |
2358 | +++ tests/volume-control-test.cc 2016-03-03 08:59:58 +0000 |
2359 | @@ -29,64 +29,65 @@ |
2360 | class VolumeControlTest : public ::testing::Test |
2361 | { |
2362 | |
2363 | - protected: |
2364 | - DbusTestService * service = NULL; |
2365 | - GDBusConnection * session = NULL; |
2366 | - |
2367 | - virtual void SetUp() override { |
2368 | - |
2369 | - g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); |
2370 | - g_setenv("GSETTINGS_BACKEND", "memory", TRUE); |
2371 | - |
2372 | - service = dbus_test_service_new(NULL); |
2373 | - dbus_test_service_start_tasks(service); |
2374 | - |
2375 | - session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2376 | - ASSERT_NE(nullptr, session); |
2377 | - g_dbus_connection_set_exit_on_close(session, FALSE); |
2378 | - g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session); |
2379 | - } |
2380 | - |
2381 | - virtual void TearDown() { |
2382 | - g_clear_object(&service); |
2383 | - |
2384 | - g_object_unref(session); |
2385 | - |
2386 | - unsigned int cleartry = 0; |
2387 | - while (session != NULL && cleartry < 100) { |
2388 | - loop(100); |
2389 | - cleartry++; |
2390 | - } |
2391 | - |
2392 | - ASSERT_EQ(nullptr, session); |
2393 | - } |
2394 | - |
2395 | - static gboolean timeout_cb (gpointer user_data) { |
2396 | - GMainLoop * loop = static_cast<GMainLoop *>(user_data); |
2397 | - g_main_loop_quit(loop); |
2398 | - return G_SOURCE_REMOVE; |
2399 | - } |
2400 | - |
2401 | - void loop (unsigned int ms) { |
2402 | - GMainLoop * loop = g_main_loop_new(NULL, FALSE); |
2403 | - g_timeout_add(ms, timeout_cb, loop); |
2404 | - g_main_loop_run(loop); |
2405 | - g_main_loop_unref(loop); |
2406 | - } |
2407 | + protected: |
2408 | + DbusTestService * service = NULL; |
2409 | + GDBusConnection * session = NULL; |
2410 | + |
2411 | + virtual void SetUp() override { |
2412 | + |
2413 | + g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); |
2414 | + g_setenv("GSETTINGS_BACKEND", "memory", TRUE); |
2415 | + |
2416 | + service = dbus_test_service_new(NULL); |
2417 | + dbus_test_service_start_tasks(service); |
2418 | + |
2419 | + session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2420 | + ASSERT_NE(nullptr, session); |
2421 | + g_dbus_connection_set_exit_on_close(session, FALSE); |
2422 | + g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session); |
2423 | + } |
2424 | + |
2425 | + virtual void TearDown() { |
2426 | + g_clear_object(&service); |
2427 | + |
2428 | + g_object_unref(session); |
2429 | + |
2430 | + unsigned int cleartry = 0; |
2431 | + while (session != NULL && cleartry < 100) { |
2432 | + loop(100); |
2433 | + cleartry++; |
2434 | + } |
2435 | + |
2436 | + ASSERT_EQ(nullptr, session); |
2437 | + } |
2438 | + |
2439 | + static gboolean timeout_cb (gpointer user_data) { |
2440 | + GMainLoop * loop = static_cast<GMainLoop *>(user_data); |
2441 | + g_main_loop_quit(loop); |
2442 | + return G_SOURCE_REMOVE; |
2443 | + } |
2444 | + |
2445 | + void loop (unsigned int ms) { |
2446 | + GMainLoop * loop = g_main_loop_new(NULL, FALSE); |
2447 | + g_timeout_add(ms, timeout_cb, loop); |
2448 | + g_main_loop_run(loop); |
2449 | + g_main_loop_unref(loop); |
2450 | + } |
2451 | }; |
2452 | |
2453 | TEST_F(VolumeControlTest, BasicObject) { |
2454 | - auto options = options_mock_new(); |
2455 | - auto pgloop = pa_glib_mainloop_new(NULL); |
2456 | - auto control = volume_control_pulse_new(INDICATOR_SOUND_OPTIONS(options), pgloop); |
2457 | - |
2458 | - /* Setup the PA backend */ |
2459 | - loop(100); |
2460 | - |
2461 | - /* Ready */ |
2462 | - EXPECT_TRUE(volume_control_get_ready(VOLUME_CONTROL(control))); |
2463 | - |
2464 | - g_clear_object(&control); |
2465 | - g_clear_object(&options); |
2466 | - g_clear_pointer(&pgloop, pa_glib_mainloop_free); |
2467 | + auto options = options_mock_new(); |
2468 | + auto pgloop = pa_glib_mainloop_new(NULL); |
2469 | + auto accounts_service_access = accounts_service_access_new(); |
2470 | + auto control = volume_control_pulse_new(INDICATOR_SOUND_OPTIONS(options), pgloop, accounts_service_access); |
2471 | + |
2472 | + /* Setup the PA backend */ |
2473 | + loop(100); |
2474 | + |
2475 | + /* Ready */ |
2476 | + EXPECT_TRUE(volume_control_get_ready(VOLUME_CONTROL(control))); |
2477 | + |
2478 | + g_clear_object(&control); |
2479 | + g_clear_object(&options); |
2480 | + g_clear_pointer(&pgloop, pa_glib_mainloop_free); |
2481 | } |
PASSED: Continuous integration, rev:532 jenkins. qa.ubuntu. com/job/ indicator- sound-ci/ 312/ jenkins. qa.ubuntu. com/job/ indicator- sound-wily- amd64-ci/ 87 jenkins. qa.ubuntu. com/job/ indicator- sound-wily- armhf-ci/ 88 jenkins. qa.ubuntu. com/job/ indicator- sound-wily- armhf-ci/ 88/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/indicator- sound-ci/ 312/rebuild
http://