Merge lp:~xavi-garcia-mena/indicator-sound/sync-vivid-wily into lp:indicator-sound/15.04

Proposed by Xavi Garcia
Status: Merged
Approved by: Xavi Garcia
Approved revision: 501
Merged at revision: 497
Proposed branch: lp:~xavi-garcia-mena/indicator-sound/sync-vivid-wily
Merge into: lp:indicator-sound/15.04
Diff against target: 1204 lines (+616/-182)
10 files modified
data/com.canonical.indicator.sound.gschema.xml (+63/-0)
debian/changelog (+42/-0)
src/service.vala (+180/-132)
src/volume-control-pulse.vala (+162/-15)
src/volume-control.vala (+13/-1)
tests/CMakeLists.txt (+1/-1)
tests/media-player-user.cc (+138/-22)
tests/notifications-test.cc (+8/-8)
tests/volume-control-mock.vala (+4/-2)
tests/volume-control-test.cc (+5/-1)
To merge this branch: bzr merge lp:~xavi-garcia-mena/indicator-sound/sync-vivid-wily
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
Xavi Garcia Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+273230@code.launchpad.net

Commit message

Sync vivid and wily branches

Description of the change

Sync vivid and wily branches

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Xavi Garcia (xavi-garcia-mena) wrote :

Approving as it is just a merge of commits from wily.
Source code should be in sync now with wily.

review: Approve
502. By Xavi Garcia

fixed version number in changelog

Revision history for this message
Charles Kerr (charlesk) wrote :

:)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'data/com.canonical.indicator.sound.gschema.xml'
--- data/com.canonical.indicator.sound.gschema.xml 2014-12-03 15:12:01 +0000
+++ data/com.canonical.indicator.sound.gschema.xml 2015-10-13 13:18:26 +0000
@@ -39,5 +39,68 @@
39 Whether or not to show the sound indicator in the menu bar.39 Whether or not to show the sound indicator in the menu bar.
40 </description>40 </description>
41 </key>41 </key>
42
43 <!-- VOLUME -->
44
45 <key name="warning-volume-enabled" type="b">
46 <default>true</default>
47 <summary>Whether or not to show high volume warnings.</summary>
48 <description>
49 If enabled on a device, a confirmation dialog will be presented to the user if
50 (a) something is plugged into the headphone jack (ie, no warnings for speaker volumes) AND
51 (b) media is playing (ie, no warnings for ringtone volumes) AND
52 (c) the user attempts to set the volume higher than warning-volume-decibels AND
53 (d) the user has not indicated approval in the last warning-volume-approval-ttl seconds.
54 </description>
55 </key>
56 <key name="warning-volume-confirmation-ttl" type="i">
57 <default>72000</default>
58 <summary>How many seconds a user's warning-volume approval should be remembered.</summary>
59 <description>
60 How long to remember a user's approval of the confirmation dialog discussed in the
61 description of 'warning-volume-enabled'.
62
63 The default value (72,000 seconds) corresponds to the 20 hours suggested by
64 EU standard EN 60950-1/Al2: “The acknowledgement does not need to be repeated
65 more than once every 20 h of cumulative listening time.”
66 </description>
67 </key>
68 <key name="warning-volume-decibels" type="d">
69 <default>-8.0</default>
70 <summary>Volume level that triggers a high volume warning.</summary>
71 <description>
72 Volume level that triggers a high volume warning.
73 See warning-volume-enabled for details.
74 </description>
75 </key>
76
77 <key name="normal-volume-decibels" type="d">
78 <default>0</default>
79 <summary>Normal output volume.</summary>
80 <description>
81 The maximum volume when com.ubuntu.sound's 'allow-amplified-volume' setting is disabled.
82
83 To conform with EU standard EN 60950-1/Al2, this value should never be
84 set to a dB that causes headphone sound output to exceed 100 dBA, nor
85 electric output to exceed 150 mV.
86
87 The default value (0) corresponds to PulseAudio's PA_VOLUME_NORM.
88 </description>
89 </key>
90
91 <key name="amplified-volume-decibels" type="d">
92 <default>11</default>
93 <summary>Output volume to use when com.ubuntu.sound's 'allow-amplified-volume' setting is enabled.</summary>
94 <description>
95 The maximum volume when com.ubuntu.sound's 'allow-amplified-volume' setting is enabled.
96
97 To conform with EU standard EN 60950-1/Al2, this value should never be
98 set to a dB that causes headphone sound output to exceed 100 dBA, nor
99 electric output to exceed 150 mV.
100
101 The default value (11) corresponds to PulseAudio's PA_VOLUME_UI_MAX.
102 </description>
103 </key>
104
42 </schema>105 </schema>
43</schemalist>106</schemalist>
44107
=== modified file 'debian/changelog'
--- debian/changelog 2015-05-08 12:20:07 +0000
+++ debian/changelog 2015-10-13 13:18:26 +0000
@@ -1,3 +1,45 @@
1indicator-sound (12.10.2+15.04.20150812.3-0ubuntu1) vivid; urgency=medium
2
3 [ CI Train Bot ]
4 * New rebuild forced.
5
6 [ Charles Kerr ]
7 * When showing a "Loud volumes can damage your hearing" confirmation
8 warning, clamp the volume until the user hits "OK". (LP: #1481913)
9
10 -- CI Train Bot <ci-train-bot@canonical.com> Wed, 12 Aug 2015 20:55:05 +0000
11
12indicator-sound (12.10.2+15.04.20150807.6-0ubuntu1) vivid; urgency=medium
13
14 [ CI Train Bot ]
15 * New rebuild forced.
16
17 [ Charles Kerr ]
18 * Revised UI volume warnings to comply with EU requirements. (LP:
19 #1481913)
20
21 -- CI Train Bot <ci-train-bot@canonical.com> Fri, 07 Aug 2015 22:35:58 +0000
22
23indicator-sound (12.10.2+15.04.20150605-0ubuntu1) vivid; urgency=medium
24
25 *
26
27 -- CI Train Bot <ci-train-bot@canonical.com> Fri, 05 Jun 2015 19:50:06 +0000
28
29indicator-sound (12.10.2+15.04.20150507+eventually4-0ubuntu1) vivid; urgency=medium
30
31 * Using eventually to avoid arbitrary timeouts in tests
32
33 -- Ted Gould <ted@ubuntu.com> Wed, 27 May 2015 11:11:19 -0500
34
35indicator-sound (12.10.2+15.04.20150507-0ubuntu1) vivid; urgency=medium
36
37 [ Charles Kerr ]
38 * Use the BusWatcher to look for org.freedesktop.Notifications
39 ownership changes on the bus. (LP: #1432446)
40
41 -- CI Train Bot <ci-train-bot@canonical.com> Thu, 07 May 2015 15:27:00 +0000
42
1indicator-sound (12.10.2+15.04.20150508-0ubuntu1) vivid; urgency=medium43indicator-sound (12.10.2+15.04.20150508-0ubuntu1) vivid; urgency=medium
244
3 [ CI Train Bot ]45 [ CI Train Bot ]
446
=== modified file 'src/service.vala'
--- src/service.vala 2015-04-20 21:02:32 +0000
+++ src/service.vala 2015-10-13 13:18:26 +0000
@@ -20,6 +20,13 @@
20public class IndicatorSound.Service: Object {20public class IndicatorSound.Service: Object {
21 DBusConnection bus;21 DBusConnection bus;
2222
23 /**
24 * A copy of volume_control.volume made before just warn_notification
25 * is shown. Since the volume is clamped during the warning, we cache
26 * the previous volume to use iff the user hits "OK".
27 */
28 VolumeControl.Volume _pre_warn_volume = null;
29
23 public Service (MediaPlayerList playerlist, VolumeControl volume, AccountsServiceUser? accounts) {30 public Service (MediaPlayerList playerlist, VolumeControl volume, AccountsServiceUser? accounts) {
24 try {31 try {
25 bus = Bus.get_sync(GLib.BusType.SESSION);32 bus = Bus.get_sync(GLib.BusType.SESSION);
@@ -27,14 +34,19 @@
27 error("Unable to get DBus session bus: %s", e.message);34 error("Unable to get DBus session bus: %s", e.message);
28 }35 }
2936
30 sync_notification = new Notify.Notification(_("Volume"), "", "audio-volume-muted");37 info_notification = new Notify.Notification(_("Volume"), "", "audio-volume-muted");
38
39 warn_notification = new Notify.Notification(_("Volume"), _("High volume can damage your hearing."), "audio-volume-high");
40 warn_notification.set_hint ("x-canonical-non-shaped-icon", "true");
41 warn_notification.set_hint ("x-canonical-snap-decisions", "true");
42 warn_notification.set_hint ("x-canonical-private-affirmative-tint", "true");
43 warn_notification.closed.connect((n) => { n.clear_actions(); });
31 BusWatcher.watch_namespace (GLib.BusType.SESSION,44 BusWatcher.watch_namespace (GLib.BusType.SESSION,
32 "org.freedesktop.Notifications",45 "org.freedesktop.Notifications",
33 () => { debug("Notifications name appeared"); check_sync_notification = false; },46 () => { debug("Notifications name appeared"); notify_server_caps_checked = false; },
34 () => { debug("Notifications name vanshed"); check_sync_notification = false; });47 () => { debug("Notifications name vanshed"); notify_server_caps_checked = false; });
3548
36 this.settings = new Settings ("com.canonical.indicator.sound");49 this.settings = new Settings ("com.canonical.indicator.sound");
37 this.sharedsettings = new Settings ("com.ubuntu.sound");
3850
39 this.settings.bind ("visible", this, "visible", SettingsBindFlags.GET);51 this.settings.bind ("visible", this, "visible", SettingsBindFlags.GET);
40 this.notify["visible"].connect ( () => this.update_root_icon () );52 this.notify["visible"].connect ( () => this.update_root_icon () );
@@ -83,19 +95,13 @@
83 this.sync_preferred_players ();95 this.sync_preferred_players ();
84 });96 });
8597
86 sharedsettings.bind ("allow-amplified-volume", this, "allow-amplified-volume", SettingsBindFlags.GET);
87
88 /* Hide the notification when the menu is shown */98 /* Hide the notification when the menu is shown */
89 var shown_action = actions.lookup_action ("indicator-shown") as SimpleAction;99 var shown_action = actions.lookup_action ("indicator-shown") as SimpleAction;
90 shown_action.change_state.connect ((state) => {100 shown_action.change_state.connect ((state) => {
91 block_notifications = state.get_boolean();101 block_info_notifications = state.get_boolean();
92 if (block_notifications) {102 if (block_info_notifications) {
93 debug("Indicator is shown");103 debug("Indicator is shown");
94 try {104 close_notification(info_notification);
95 sync_notification.close();
96 } catch (Error e) {
97 warning("Unable to close synchronous volume notification: %s", e.message);
98 }
99 } else {105 } else {
100 debug("Indicator is hidden");106 debug("Indicator is hidden");
101 }107 }
@@ -111,11 +117,33 @@
111 this.menus.@foreach ( (profile, menu) => menu.export (bus, @"/com/canonical/indicator/sound/$profile"));117 this.menus.@foreach ( (profile, menu) => menu.export (bus, @"/com/canonical/indicator/sound/$profile"));
112 }118 }
113119
120 private void close_notification(Notify.Notification? n) {
121 return_if_fail (n != null);
122 if (n.id != 0) {
123 try {
124 n.close();
125 } catch (GLib.Error e) {
126 warning("Unable to close notification: %s", e.message);
127 }
128 }
129 }
130
131 private void show_notification(Notify.Notification? n) {
132 return_if_fail (n != null);
133 try {
134 n.show ();
135 } catch (GLib.Error e) {
136 warning ("Unable to show notification: %s", e.message);
137 }
138 }
139
114 ~Service() {140 ~Service() {
115 debug("Destroying Service Object");141 debug("Destroying Service Object");
116142
117 clear_acts_player();143 clear_acts_player();
118144
145 stop_clamp_to_high_timeout();
146
119 if (this.player_action_update_id > 0) {147 if (this.player_action_update_id > 0) {
120 Source.remove (this.player_action_update_id);148 Source.remove (this.player_action_update_id);
121 this.player_action_update_id = 0;149 this.player_action_update_id = 0;
@@ -145,28 +173,6 @@
145173
146 public bool visible { get; set; }174 public bool visible { get; set; }
147175
148 public bool allow_amplified_volume {
149 get {
150 return this.max_volume > 1.0;
151 }
152
153 set {
154 if (this.allow_amplified_volume == value)
155 return;
156
157 if (value) {
158 /* from pulse/volume.h: #define PA_VOLUME_UI_MAX (pa_sw_volume_from_dB(+11.0)) */
159 this.max_volume = (double)PulseAudio.Volume.sw_from_dB(11.0) / PulseAudio.Volume.NORM;
160 }
161 else {
162 this.max_volume = 1.0;
163 }
164
165 /* Normalize volume, because the volume action's state is [0.0, 1.0], see create_volume_action() */
166 this.actions.change_action_state ("volume", this.volume_control.volume.volume / this.max_volume);
167 }
168 }
169
170 const ActionEntry[] action_entries = {176 const ActionEntry[] action_entries = {
171 { "root", null, null, "@a{sv} {}", null },177 { "root", null, null, "@a{sv} {}", null },
172 { "scroll", activate_scroll_action, "i", null, null },178 { "scroll", activate_scroll_action, "i", null, null },
@@ -178,7 +184,6 @@
178 SimpleActionGroup actions;184 SimpleActionGroup actions;
179 HashTable<string, SoundMenu> menus;185 HashTable<string, SoundMenu> menus;
180 Settings settings;186 Settings settings;
181 Settings sharedsettings;
182 VolumeControl volume_control;187 VolumeControl volume_control;
183 MediaPlayerList players;188 MediaPlayerList players;
184 uint player_action_update_id;189 uint player_action_update_id;
@@ -187,28 +192,27 @@
187 bool syncing_preferred_players = false;192 bool syncing_preferred_players = false;
188 AccountsServiceUser? accounts_service = null;193 AccountsServiceUser? accounts_service = null;
189 bool export_to_accounts_service = false;194 bool export_to_accounts_service = false;
190 private Notify.Notification sync_notification;195 private Notify.Notification info_notification;
191196 private Notify.Notification warn_notification;
192 /* Maximum volume as a scaling factor between the volume action's state and the value in
193 * this.volume_control. See create_volume_action().
194 */
195 double max_volume = 1.0;
196197
197 const double volume_step_percentage = 0.06;198 const double volume_step_percentage = 0.06;
198199
199 void activate_scroll_action (SimpleAction action, Variant? param) {200 private void activate_scroll_action (SimpleAction action, Variant? param) {
200 int delta = param.get_int32(); /* positive for up, negative for down */201 int delta = param.get_int32(); /* positive for up, negative for down */
201202 double v = volume_control.volume.volume + volume_step_percentage * delta;
202 var scrollvol = new VolumeControl.Volume();203 volume_control.set_volume_clamp (v, VolumeControl.VolumeReasons.USER_KEYPRESS);
203 double v = this.volume_control.volume.volume + volume_step_percentage * delta;
204 scrollvol.volume = v.clamp (0.0, this.max_volume);
205 scrollvol.reason = VolumeControl.VolumeReasons.USER_KEYPRESS;
206 this.volume_control.volume = scrollvol;
207 }204 }
208205
209 void activate_desktop_settings (SimpleAction action, Variant? param) {206 void activate_desktop_settings (SimpleAction action, Variant? param) {
210 var env = Environment.get_variable ("DESKTOP_SESSION");207 var env = Environment.get_variable ("DESKTOP_SESSION");
211 string cmd;208 string cmd;
209
210 if (Environment.get_variable ("MIR_SOCKET") != null)
211 {
212 UrlDispatch.send ("settings:///system/sound");
213 return;
214 }
215
212 if (env == "xubuntu" || env == "ubuntustudio")216 if (env == "xubuntu" || env == "ubuntustudio")
213 cmd = "pavucontrol";217 cmd = "pavucontrol";
214 else if (env == "mate")218 else if (env == "mate")
@@ -242,12 +246,10 @@
242 void update_root_icon () {246 void update_root_icon () {
243 double volume = this.volume_control.volume.volume;247 double volume = this.volume_control.volume.volume;
244 string icon;248 string icon;
245 if (this.volume_control.mute)249 if (this.volume_control.mute || volume <= 0.0)
246 icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";250 icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel";
247 else if (this.accounts_service != null && this.accounts_service.silentMode)251 else if (this.accounts_service != null && this.accounts_service.silentMode)
248 icon = "audio-volume-muted-panel";252 icon = "audio-volume-muted-panel";
249 else if (volume <= 0.0)
250 icon = "audio-volume-low-zero-panel";
251 else if (volume <= 0.3)253 else if (volume <= 0.3)
252 icon = "audio-volume-low-panel";254 icon = "audio-volume-low-panel";
253 else if (volume <= 0.7)255 else if (volume <= 0.7)
@@ -275,60 +277,83 @@
275 root_action.set_state (builder.end());277 root_action.set_state (builder.end());
276 }278 }
277279
278 private bool check_sync_notification = false;280 private bool notify_server_caps_checked = false;
279 private bool support_sync_notification = false;281 private bool notify_server_supports_actions = false;
280 private bool block_notifications = false;282 private bool notify_server_supports_sync = false;
281283 private bool block_info_notifications = false;
282 void update_sync_notification () {284
283 if (!check_sync_notification) {285 private void update_notification () {
284 support_sync_notification = false;286
287 if (!notify_server_caps_checked) {
285 List<string> caps = Notify.get_server_caps ();288 List<string> caps = Notify.get_server_caps ();
286 if (caps.find_custom ("x-canonical-private-synchronous", strcmp) != null) {289 notify_server_supports_actions = caps.find_custom ("actions", strcmp) != null;
287 support_sync_notification = true;290 notify_server_supports_sync = caps.find_custom ("x-canonical-private-synchronous", strcmp) != null;
288 }291 notify_server_caps_checked = true;
289 check_sync_notification = true;
290 }292 }
291293
292 if (!support_sync_notification)294 var loud = volume_control.high_volume;
293 return;295 var warn = loud
294296 && this.notify_server_supports_actions
295 if (block_notifications)297 && !this.volume_control.high_volume_approved;
296 return;298
297299 if (warn) {
298 /* Determine Label */300 close_notification(info_notification);
299 string volume_label = "";301 if (_pre_warn_volume == null) {
300 if (volume_control.high_volume)302 _pre_warn_volume = new VolumeControl.Volume();
301 volume_label = _("High volume");303 _pre_warn_volume.volume = volume_control.volume.volume;
302304 _pre_warn_volume.reason = volume_control.volume.reason;
303 /* Choose an icon */305 }
304 string icon = "audio-volume-muted";306 warn_notification.clear_actions();
305 if (volume_control.volume.volume <= 0.0)307 warn_notification.add_action ("ok", _("OK"), (n, a) => {
306 icon = "audio-volume-muted";308 stop_clamp_to_high_timeout();
307 else if (volume_control.volume.volume <= 0.3)309 volume_control.approve_high_volume ();
308 icon = "audio-volume-low";310 if (_pre_warn_volume != null) {
309 else if (volume_control.volume.volume <= 0.7)311 var tmp = _pre_warn_volume;
310 icon = "audio-volume-medium";312 _pre_warn_volume = null;
311 else313 volume_control.volume = tmp;
312 icon = "audio-volume-high";314 }
313315 });
314 /* Check tint */316 warn_notification.add_action ("cancel", _("Cancel"), (n, a) => {
315 string tint = "false";317 _pre_warn_volume = null;
316 if (volume_control.high_volume)318 });
317 tint = "true";319 show_notification(warn_notification);
318320 } else {
319 /* Put it all into the notification */321 close_notification(warn_notification);
320 sync_notification.clear_hints ();322
321 sync_notification.update (_("Volume"), volume_label, icon);323 if (notify_server_supports_sync && !block_info_notifications) {
322 sync_notification.set_hint ("value", (int32)Math.round(volume_control.volume.volume / this.max_volume * 100.0));324
323 sync_notification.set_hint ("x-canonical-value-bar-tint", tint);325 /* Determine Label */
324 sync_notification.set_hint ("x-canonical-private-synchronous", "true");326 unowned string volume_label = loud
325 sync_notification.set_hint ("x-canonical-non-shaped-icon", "true");327 ? _("High volume can damage your hearing.")
326328 : "";
327 /* Show it */329
328 try {330 /* Choose an icon */
329 sync_notification.show (); 331 unowned string icon;
330 } catch (GLib.Error e) {332 if (loud) {
331 warning("Unable to send volume change notification: %s", e.message);333 icon = "audio-volume-high";
334 } else {
335 var volume = volume_control.volume.volume;
336
337 if (volume <= 0.0)
338 icon = "audio-volume-muted";
339 else if (volume <= 0.3)
340 icon = "audio-volume-low";
341 else if (volume <= 0.7)
342 icon = "audio-volume-medium";
343 else
344 icon = "audio-volume-high";
345 }
346
347 /* Reset the notification */
348 var n = this.info_notification;
349 n.update (_("Volume"), volume_label, icon);
350 n.clear_hints();
351 n.set_hint ("x-canonical-non-shaped-icon", "true");
352 n.set_hint ("x-canonical-private-synchronous", "true");
353 n.set_hint ("x-canonical-value-bar-tint", loud ? "true" : "false");
354 n.set_hint ("value", (int32)Math.round(get_volume_percent() * 100.0));
355 show_notification(n);
356 }
332 }357 }
333 }358 }
334359
@@ -408,49 +433,49 @@
408 return mute_action;433 return mute_action;
409 }434 }
410435
411 SimpleAction volume_action;436 /* return the current volume in the range of [0.0, 1.0] */
412 Action create_volume_action () {437 private double get_volume_percent() {
413 /* The action's state is between be in [0.0, 1.0] instead of [0.0,438 return volume_control.volume.volume / this.volume_control.max_volume;
414 * max_volume], so that we don't need to update the slider menu item439 }
415 * every time allow-amplified-volume is changed. Convert between the440
416 * two here, so that we always pass the full range into441 /* volume control's range can vary depending on its max_volume property,
417 * volume_control.set_volume().442 * but the action always needs to be in [0.0, 1.0]... */
418 */443 private Variant create_volume_action_state() {
419444 return new Variant.double (get_volume_percent());
420 double volume = this.volume_control.volume.volume / this.max_volume;445 }
421446
422 volume_action = new SimpleAction.stateful ("volume", VariantType.INT32, new Variant.double (volume));447 private void update_volume_action_state() {
448 volume_action.set_state(create_volume_action_state());
449 }
450
451 private SimpleAction volume_action;
452 private Action create_volume_action () {
453 volume_action = new SimpleAction.stateful ("volume", VariantType.INT32, create_volume_action_state());
423454
424 volume_action.change_state.connect ( (action, val) => {455 volume_action.change_state.connect ( (action, val) => {
425 double v = val.get_double () * this.max_volume;456 double v = val.get_double () * this.volume_control.max_volume;
426457 volume_control.set_volume_clamp (v, VolumeControl.VolumeReasons.USER_KEYPRESS);
427 var vol = new VolumeControl.Volume();
428 vol.volume = v.clamp (0.0, this.max_volume);
429 vol.reason = VolumeControl.VolumeReasons.USER_KEYPRESS;
430 volume_control.volume = vol;
431 });458 });
432459
433 /* activating this action changes the volume by the amount given in the parameter */460 /* activating this action changes the volume by the amount given in the parameter */
434 volume_action.activate.connect ( (action, param) => {461 volume_action.activate.connect ((a,p) => activate_scroll_action(a,p));
435 int delta = param.get_int32 ();
436 double v = volume_control.volume.volume + volume_step_percentage * delta;
437462
438 var vol = new VolumeControl.Volume();463 this.volume_control.notify["max-volume"].connect(() => {
439 vol.volume = v.clamp (0.0, this.max_volume);464 update_volume_action_state();
440 vol.reason = VolumeControl.VolumeReasons.USER_KEYPRESS;
441 volume_control.volume = vol;
442 });465 });
443466
444 this.volume_control.notify["volume"].connect (() => {467 this.volume_control.notify["volume"].connect (() => {
445 /* Normalize volume, because the volume action's state is [0.0, 1.0], see create_volume_action() */468 update_volume_action_state();
446 volume_action.set_state (new Variant.double (this.volume_control.volume.volume / this.max_volume));
447469
448 this.update_root_icon ();470 this.update_root_icon ();
449471
450 var reason = volume_control.volume.reason;472 var reason = volume_control.volume.reason;
451 if (reason == VolumeControl.VolumeReasons.USER_KEYPRESS ||473 if (reason == VolumeControl.VolumeReasons.USER_KEYPRESS ||
452 reason == VolumeControl.VolumeReasons.DEVICE_OUTPUT_CHANGE)474 reason == VolumeControl.VolumeReasons.DEVICE_OUTPUT_CHANGE)
453 this.update_sync_notification ();475 this.update_notification ();
476
477 if ((warn_notification.id != 0) && (_pre_warn_volume != null))
478 clamp_to_high_soon();
454 });479 });
455480
456 this.volume_control.bind_property ("ready", volume_action, "enabled", BindingFlags.SYNC_CREATE);481 this.volume_control.bind_property ("ready", volume_action, "enabled", BindingFlags.SYNC_CREATE);
@@ -481,7 +506,7 @@
481506
482 this.volume_control.notify["high-volume"].connect( () => {507 this.volume_control.notify["high-volume"].connect( () => {
483 high_volume_action.set_state(new Variant.boolean (this.volume_control.high_volume));508 high_volume_action.set_state(new Variant.boolean (this.volume_control.high_volume));
484 update_sync_notification();509 update_notification();
485 });510 });
486511
487 return high_volume_action;512 return high_volume_action;
@@ -604,4 +629,27 @@
604629
605 this.update_preferred_players ();630 this.update_preferred_players ();
606 }631 }
632
633 /** VOLUME CLAMPING **/
634
635 private uint _clamp_to_high_timeout = 0;
636
637 private void stop_clamp_to_high_timeout() {
638 if (_clamp_to_high_timeout != 0) {
639 Source.remove(_clamp_to_high_timeout);
640 _clamp_to_high_timeout = 0;
641 }
642 }
643
644 private void clamp_to_high_soon() {
645 const uint interval_msec = 200;
646 if (_clamp_to_high_timeout == 0)
647 _clamp_to_high_timeout = Timeout.add(interval_msec, clamp_to_high_idle);
648 }
649
650 private bool clamp_to_high_idle() {
651 _clamp_to_high_timeout = 0;
652 volume_control.clamp_to_high_volume();
653 return false; // Source.REMOVE;
654 }
607}655}
608656
=== modified file 'src/volume-control-pulse.vala'
--- src/volume-control-pulse.vala 2015-04-17 17:10:28 +0000
+++ src/volume-control-pulse.vala 2015-10-13 13:18:26 +0000
@@ -28,8 +28,8 @@
28[DBus (name="com.canonical.UnityGreeter.List")]28[DBus (name="com.canonical.UnityGreeter.List")]
29interface GreeterListInterface : Object29interface GreeterListInterface : Object
30{30{
31 public abstract async string get_active_entry () throws IOError;31 public abstract async string get_active_entry () throws IOError;
32 public signal void entry_selected (string entry_name);32 public signal void entry_selected (string entry_name);
33}33}
3434
35public class VolumeControlPulse : VolumeControl35public class VolumeControlPulse : VolumeControl
@@ -44,6 +44,8 @@
44 private bool _is_playing = false;44 private bool _is_playing = false;
45 private VolumeControl.Volume _volume = new VolumeControl.Volume();45 private VolumeControl.Volume _volume = new VolumeControl.Volume();
46 private double _mic_volume = 0.0;46 private double _mic_volume = 0.0;
47 private Settings _settings = new Settings ("com.canonical.indicator.sound");
48 private Settings _shared_settings = new Settings ("com.ubuntu.sound");
4749
48 /* Used by the pulseaudio stream restore extension */50 /* Used by the pulseaudio stream restore extension */
49 private DBusConnection _pconn;51 private DBusConnection _pconn;
@@ -92,13 +94,6 @@
92 /** true when a microphone is active **/94 /** true when a microphone is active **/
93 public override bool active_mic { get; private set; default = false; }95 public override bool active_mic { get; private set; default = false; }
9496
95 /** true when high volume warnings should be shown */
96 public override bool high_volume {
97 get {
98 return this._volume.volume > 0.75 && _active_port_headphone && stream == "multimedia";
99 }
100 }
101
102 public VolumeControlPulse ()97 public VolumeControlPulse ()
103 {98 {
104 _volume.volume = 0.0;99 _volume.volume = 0.0;
@@ -110,19 +105,34 @@
110 _mute_cancellable = new Cancellable ();105 _mute_cancellable = new Cancellable ();
111 _volume_cancellable = new Cancellable ();106 _volume_cancellable = new Cancellable ();
112107
108 init_all_properties();
109
113 setup_accountsservice.begin ();110 setup_accountsservice.begin ();
114111
115 this.reconnect_to_pulse ();112 this.reconnect_to_pulse ();
116 }113 }
117114
115 private void init_all_properties()
116 {
117 init_max_volume();
118 init_high_volume();
119 init_high_volume_approved();
120 }
121
118 ~VolumeControlPulse ()122 ~VolumeControlPulse ()
119 {123 {
124 stop_all_timers();
125 }
126
127 private void stop_all_timers()
128 {
120 if (_reconnect_timer != 0) {129 if (_reconnect_timer != 0) {
121 Source.remove (_reconnect_timer);130 Source.remove (_reconnect_timer);
122 _reconnect_timer = 0;131 _reconnect_timer = 0;
123 }132 }
124 stop_local_volume_timer();133 stop_local_volume_timer();
125 stop_account_service_volume_timer();134 stop_account_service_volume_timer();
135 stop_high_volume_approved_timer();
126 }136 }
127137
128 /* PulseAudio logic*/138 /* PulseAudio logic*/
@@ -212,7 +222,7 @@
212 vol.volume = volume_to_double (i.volume.max ());222 vol.volume = volume_to_double (i.volume.max ());
213 vol.reason = VolumeControl.VolumeReasons.PULSE_CHANGE;223 vol.reason = VolumeControl.VolumeReasons.PULSE_CHANGE;
214 this.volume = vol;224 this.volume = vol;
215 } 225 }
216 }226 }
217227
218 private void source_info_cb (Context c, SourceInfo? i, int eol)228 private void source_info_cb (Context c, SourceInfo? i, int eol)
@@ -619,7 +629,6 @@
619 var volume_changed = (value.volume != _volume.volume);629 var volume_changed = (value.volume != _volume.volume);
620 debug("Setting volume to %f for profile %d because %d", value.volume, _active_sink_input, value.reason);630 debug("Setting volume to %f for profile %d because %d", value.volume, _active_sink_input, value.reason);
621631
622 var old_high_volume = this.high_volume;
623 _volume = value;632 _volume = value;
624633
625 /* Make sure we're connected to Pulse and pulse didn't give us the change */634 /* Make sure we're connected to Pulse and pulse didn't give us the change */
@@ -631,15 +640,153 @@
631 else640 else
632 context.get_server_info (server_info_cb_for_set_volume);641 context.get_server_info (server_info_cb_for_set_volume);
633642
634 if (this.high_volume != old_high_volume)
635 this.notify_property("high-volume");
636643
637 if (volume.reason != VolumeControl.VolumeReasons.ACCOUNTS_SERVICE_SET644 if (volume.reason != VolumeControl.VolumeReasons.ACCOUNTS_SERVICE_SET
638 && volume_changed) {645 && volume_changed) {
639 start_local_volume_timer();646 start_local_volume_timer();
640 }647 }
641 }648
642 }649 update_high_volume();
650 }
651 }
652
653 /** MAX VOLUME PROPERTY **/
654
655 private void init_max_volume() {
656 _settings.changed["normal-volume-decibels"].connect(() => update_max_volume());
657 _settings.changed["amplified-volume-decibels"].connect(() => update_max_volume());
658 _shared_settings.changed["allow-amplified-volume"].connect(() => update_max_volume());
659 update_max_volume();
660 }
661 private void update_max_volume () {
662 var new_max_volume = calculate_max_volume();
663 if (max_volume != new_max_volume) {
664 debug("changing max_volume from %f to %f", this.max_volume, new_max_volume);
665 max_volume = calculate_max_volume();
666 }
667 }
668 private double calculate_max_volume () {
669 unowned string decibel_key = _shared_settings.get_boolean("allow-amplified-volume")
670 ? "amplified-volume-decibels"
671 : "normal-volume-decibels";
672 var volume_dB = _settings.get_double(decibel_key);
673 var volume_sw = PulseAudio.Volume.sw_from_dB (volume_dB);
674 return volume_to_double (volume_sw);
675 }
676
677 /** HIGH VOLUME PROPERTY **/
678
679 private bool _warning_volume_enabled;
680 private double _warning_volume_norms; /* 1.0 == PA_VOLUME_NORM */
681 private bool _high_volume = false;
682 public override bool high_volume {
683 get { return this._high_volume; }
684 private set { this._high_volume = value; }
685 }
686 private void init_high_volume() {
687 _settings.changed["warning-volume-enabled"].connect(() => update_high_volume_cache());
688 _settings.changed["warning-volume-decibels"].connect(() => update_high_volume_cache());
689 update_high_volume_cache();
690 }
691 private void update_high_volume_cache() {
692 var volume_dB = _settings.get_double ("warning-volume-decibels");
693 var volume_sw = PulseAudio.Volume.sw_from_dB (volume_dB);
694 var volume_norms = volume_to_double (volume_sw);
695 _warning_volume_norms = volume_norms;
696 _warning_volume_enabled = _settings.get_boolean("warning-volume-enabled");
697 debug("updating high volume cache... enabled %d dB %f sw %lu norm %f", (int)_warning_volume_enabled, volume_dB, volume_sw, volume_norms);
698 update_high_volume();
699 }
700 private void update_high_volume() {
701 var new_high_volume = calculate_high_volume();
702 if (high_volume != new_high_volume) {
703 debug("changing high_volume from %d to %d", (int)high_volume, (int)new_high_volume);
704 high_volume = new_high_volume;
705 }
706 }
707 private bool calculate_high_volume() {
708 return calculate_high_volume_from_volume(_volume.volume);
709 }
710 private bool calculate_high_volume_from_volume(double volume) {
711 return _active_port_headphone
712 && _warning_volume_enabled
713 && volume >= _warning_volume_norms
714 && (stream == "multimedia");
715 }
716
717 public override void clamp_to_high_volume() {
718 if (_high_volume && (_volume.volume > _warning_volume_norms)) {
719 var vol = new VolumeControl.Volume();
720 vol.volume = _volume.volume.clamp(0, _warning_volume_norms);
721 vol.reason = _volume.reason;
722 debug("Clamping from %f down to %f", _volume.volume, vol.volume);
723 volume = vol;
724 }
725 }
726
727 /** HIGH VOLUME APPROVED PROPERTY **/
728
729 private bool _high_volume_approved = false;
730 private uint _high_volume_approved_timer = 0;
731 private int64 _high_volume_approved_at = 0;
732 private int64 _high_volume_approved_ttl_usec = 0;
733 public override bool high_volume_approved {
734 get { return this._high_volume_approved; }
735 private set { this._high_volume_approved = value; }
736 }
737 private void init_high_volume_approved() {
738 _settings.changed["warning-volume-confirmation-ttl"].connect(() => update_high_volume_approved_cache());
739 update_high_volume_approved_cache();
740 }
741 private void update_high_volume_approved_cache() {
742 _high_volume_approved_ttl_usec = _settings.get_int("warning-volume-confirmation-ttl");
743 _high_volume_approved_ttl_usec *= 1000000;
744
745 update_high_volume_approved();
746 update_high_volume_approved_timer();
747 }
748 private void update_high_volume_approved_timer() {
749 stop_high_volume_approved_timer();
750 if (_high_volume_approved_at != 0) {
751 int64 expires_at = _high_volume_approved_at + _high_volume_approved_ttl_usec;
752 int64 now = GLib.get_monotonic_time();
753 if (expires_at > now) {
754 var seconds_left = 1 + ((expires_at - now) / 1000000);
755 _high_volume_approved_timer = Timeout.add_seconds((uint)seconds_left, on_high_volume_approved_timer);
756 }
757 }
758 }
759 private void stop_high_volume_approved_timer() {
760 if (_high_volume_approved_timer != 0) {
761 Source.remove (_high_volume_approved_timer);
762 _high_volume_approved_timer = 0;
763 }
764 }
765 private bool on_high_volume_approved_timer() {
766 _high_volume_approved_timer = 0;
767 update_high_volume_approved();
768 return false; /* Source.REMOVE */
769 }
770 private void update_high_volume_approved() {
771 var new_high_volume_approved = calculate_high_volume_approved();
772 if (high_volume_approved != new_high_volume_approved) {
773 debug("changing high_volume_approved from %d to %d", (int)high_volume_approved, (int)new_high_volume_approved);
774 high_volume_approved = new_high_volume_approved;
775 }
776 }
777 private bool calculate_high_volume_approved() {
778 int64 now = GLib.get_monotonic_time();
779 return (_high_volume_approved_at != 0)
780 && (_high_volume_approved_at + _high_volume_approved_ttl_usec >= now);
781 }
782 public override void approve_high_volume() {
783 _high_volume_approved_at = GLib.get_monotonic_time();
784 update_high_volume_approved();
785 update_high_volume_approved_timer();
786 }
787
788
789 /** MIC VOLUME PROPERTY */
643790
644 public override double mic_volume {791 public override double mic_volume {
645 get {792 get {
646793
=== modified file 'src/volume-control.vala'
--- src/volume-control.vala 2015-02-17 16:54:33 +0000
+++ src/volume-control.vala 2015-10-13 13:18:26 +0000
@@ -36,12 +36,24 @@
36 public virtual string stream { get { return ""; } }36 public virtual string stream { get { return ""; } }
37 public virtual bool ready { get { return false; } set { } }37 public virtual bool ready { get { return false; } set { } }
38 public virtual bool active_mic { get { return false; } set { } }38 public virtual bool active_mic { get { return false; } set { } }
39 public virtual bool high_volume { get { return false; } }39 public virtual bool high_volume { get { return false; } protected set { } }
40 public virtual bool mute { get { return false; } }40 public virtual bool mute { get { return false; } }
41 public virtual bool is_playing { get { return false; } }41 public virtual bool is_playing { get { return false; } }
42 private Volume _volume;42 private Volume _volume;
43 public virtual Volume volume { get { return _volume; } set { } }43 public virtual Volume volume { get { return _volume; } set { } }
44 public virtual double mic_volume { get { return 0.0; } set { } }44 public virtual double mic_volume { get { return 0.0; } set { } }
45 public virtual double max_volume { get { return 1.0; } protected set { } }
46
47 public virtual bool high_volume_approved { get { return false; } protected set { } }
48 public virtual void approve_high_volume() { }
49 public virtual void clamp_to_high_volume() { }
4550
46 public abstract void set_mute (bool mute);51 public abstract void set_mute (bool mute);
52
53 public void set_volume_clamp (double unclamped, VolumeControl.VolumeReasons reason) {
54 var v = new VolumeControl.Volume();
55 v.volume = unclamped.clamp (0.0, this.max_volume);
56 v.reason = reason;
57 this.volume = v;
58 }
47}59}
4860
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2015-02-09 22:10:22 +0000
+++ tests/CMakeLists.txt 2015-10-13 13:18:26 +0000
@@ -163,7 +163,7 @@
163###########################163###########################
164164
165include_directories(${CMAKE_SOURCE_DIR}/src)165include_directories(${CMAKE_SOURCE_DIR}/src)
166add_executable (volume-control-test volume-control-test.cc)166add_executable (volume-control-test volume-control-test.cc gschemas.compiled)
167target_link_libraries (167target_link_libraries (
168 volume-control-test168 volume-control-test
169 indicator-sound-service-lib169 indicator-sound-service-lib
170170
=== modified file 'tests/media-player-user.cc'
--- tests/media-player-user.cc 2015-01-30 16:05:10 +0000
+++ tests/media-player-user.cc 2015-10-13 13:18:26 +0000
@@ -17,6 +17,9 @@
17 * Ted Gould <ted@canonical.com>17 * Ted Gould <ted@canonical.com>
18 */18 */
1919
20#include <chrono>
21#include <future>
22
20#include <gtest/gtest.h>23#include <gtest/gtest.h>
21#include <gio/gio.h>24#include <gio/gio.h>
22#include <libdbustest/dbus-test.h>25#include <libdbustest/dbus-test.h>
@@ -31,24 +34,55 @@
31{34{
3235
33 protected:36 protected:
34 DbusTestService * service = NULL;37 DbusTestService * testsystem = NULL;
35 AccountsServiceMock service_mock;38 AccountsServiceMock service_mock;
3639
40 DbusTestService * testsession = NULL;
41
42 DbusTestProcess * systemmonitor = nullptr;
43 DbusTestProcess * sessionmonitor = nullptr;
44
37 GDBusConnection * system = NULL;45 GDBusConnection * system = NULL;
46 GDBusConnection * session = NULL;
38 GDBusProxy * proxy = NULL;47 GDBusProxy * proxy = NULL;
3948
49 std::chrono::milliseconds _eventuallyTime = std::chrono::seconds{5};
50
40 virtual void SetUp() {51 virtual void SetUp() {
41 service = dbus_test_service_new(NULL);52 /* System Bus */
42 dbus_test_service_set_bus(service, DBUS_TEST_SERVICE_BUS_SYSTEM);53 testsystem = dbus_test_service_new(NULL);
4354 dbus_test_service_set_bus(testsystem, DBUS_TEST_SERVICE_BUS_SYSTEM);
44 dbus_test_service_add_task(service, (DbusTestTask*)service_mock);55
45 dbus_test_service_start_tasks(service);56 systemmonitor = dbus_test_process_new("dbus-monitor");
57 dbus_test_process_append_param(systemmonitor, "--system");
58 dbus_test_task_set_name(DBUS_TEST_TASK(systemmonitor), "System");
59 dbus_test_service_add_task(testsystem, DBUS_TEST_TASK(systemmonitor));
60
61 dbus_test_service_add_task(testsystem, (DbusTestTask*)service_mock);
62 dbus_test_service_start_tasks(testsystem);
4663
47 system = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);64 system = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
48 ASSERT_NE(nullptr, system);65 ASSERT_NE(nullptr, system);
49 g_dbus_connection_set_exit_on_close(system, FALSE);66 g_dbus_connection_set_exit_on_close(system, FALSE);
50 g_object_add_weak_pointer(G_OBJECT(system), (gpointer *)&system);67 g_object_add_weak_pointer(G_OBJECT(system), (gpointer *)&system);
5168
69 /* Session Bus */
70 testsession = dbus_test_service_new(NULL);
71 dbus_test_service_set_bus(testsession, DBUS_TEST_SERVICE_BUS_SESSION);
72
73 sessionmonitor = dbus_test_process_new("dbus-monitor");
74 dbus_test_process_append_param(sessionmonitor, "--session");
75 dbus_test_task_set_name(DBUS_TEST_TASK(sessionmonitor), "Session");
76 dbus_test_service_add_task(testsession, DBUS_TEST_TASK(sessionmonitor));
77
78 dbus_test_service_start_tasks(testsession);
79
80 session = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
81 ASSERT_NE(nullptr, session);
82 g_dbus_connection_set_exit_on_close(session, FALSE);
83 g_object_add_weak_pointer(G_OBJECT(session), (gpointer *)&session);
84
85 /* Setup proxy */
52 proxy = g_dbus_proxy_new_sync(system,86 proxy = g_dbus_proxy_new_sync(system,
53 G_DBUS_PROXY_FLAGS_NONE,87 G_DBUS_PROXY_FLAGS_NONE,
54 NULL,88 NULL,
@@ -60,10 +94,15 @@
60 }94 }
6195
62 virtual void TearDown() {96 virtual void TearDown() {
97 g_clear_object(&sessionmonitor);
98 g_clear_object(&systemmonitor);
99
63 g_clear_object(&proxy);100 g_clear_object(&proxy);
64 g_clear_object(&service);101 g_clear_object(&testsystem);
102 g_clear_object(&testsession);
65103
66 g_object_unref(system);104 g_object_unref(system);
105 g_object_unref(session);
67106
68 #if 0107 #if 0
69 /* Accounts Service keeps a bunch of references around so we108 /* Accounts Service keeps a bunch of references around so we
@@ -95,8 +134,78 @@
95 void set_property (const gchar * name, GVariant * value) {134 void set_property (const gchar * name, GVariant * value) {
96 dbus_test_dbus_mock_object_update_property((DbusTestDbusMock *)service_mock, service_mock.get_sound(), name, value, NULL);135 dbus_test_dbus_mock_object_update_property((DbusTestDbusMock *)service_mock, service_mock.get_sound(), name, value, NULL);
97 }136 }
137
138 testing::AssertionResult expectEventually (std::function<testing::AssertionResult(void)> &testfunc) {
139 auto loop = std::shared_ptr<GMainLoop>(g_main_loop_new(nullptr, FALSE), [](GMainLoop * loop) { if (loop != nullptr) g_main_loop_unref(loop); });
140
141 std::promise<testing::AssertionResult> retpromise;
142 auto retfuture = retpromise.get_future();
143 auto start = std::chrono::steady_clock::now();
144
145 /* The core of the idle function as an object so we can use the C++-isms
146 of attaching the variables and make this code reasonably readable */
147 std::function<void(void)> idlefunc = [&loop, &retpromise, &testfunc, &start, this]() -> void {
148 auto result = testfunc();
149
150 if (result == false && _eventuallyTime > (std::chrono::steady_clock::now() - start)) {
151 return;
152 }
153
154 retpromise.set_value(result);
155 g_main_loop_quit(loop.get());
156 };
157
158 auto idlesrc = g_idle_add([](gpointer data) -> gboolean {
159 auto func = reinterpret_cast<std::function<void(void)> *>(data);
160 (*func)();
161 return G_SOURCE_CONTINUE;
162 }, &idlefunc);
163
164 g_main_loop_run(loop.get());
165 g_source_remove(idlesrc);
166
167 return retfuture.get();
168 }
169
170 /* Eventually Helpers */
171 #define _EVENTUALLY_HELPER(oper) \
172 template <typename... Args> testing::AssertionResult expectEventually##oper (Args&& ... args) { \
173 std::function<testing::AssertionResult(void)> func = [&]() { \
174 return testing::internal::CmpHelper##oper(std::forward<Args>(args)...); \
175 }; \
176 return expectEventually(func); \
177 }
178
179 _EVENTUALLY_HELPER(EQ);
180 _EVENTUALLY_HELPER(NE);
181 _EVENTUALLY_HELPER(LT);
182 _EVENTUALLY_HELPER(GT);
183 _EVENTUALLY_HELPER(STREQ);
184 _EVENTUALLY_HELPER(STRNE);
185
186 #undef _EVENTUALLY_HELPER
98};187};
99188
189/* Helpers */
190#define EXPECT_EVENTUALLY_EQ(expected, actual) \
191 EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyEQ, expected, actual)
192
193#define EXPECT_EVENTUALLY_NE(expected, actual) \
194 EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyNE, expected, actual)
195
196#define EXPECT_EVENTUALLY_LT(expected, actual) \
197 EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyLT, expected, actual)
198
199#define EXPECT_EVENTUALLY_GT(expected, actual) \
200 EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallyGT, expected, actual)
201
202#define EXPECT_EVENTUALLY_STREQ(expected, actual) \
203 EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallySTREQ, expected, actual)
204
205#define EXPECT_EVENTUALLY_STRNE(expected, actual) \
206 EXPECT_PRED_FORMAT2(MediaPlayerUserTest::expectEventuallySTRNE, expected, actual)
207
208
100TEST_F(MediaPlayerUserTest, BasicObject) {209TEST_F(MediaPlayerUserTest, BasicObject) {
101 MediaPlayerUser * player = media_player_user_new("user");210 MediaPlayerUser * player = media_player_user_new("user");
102 ASSERT_NE(nullptr, player);211 ASSERT_NE(nullptr, player);
@@ -125,7 +234,12 @@
125 g_clear_object(&player);234 g_clear_object(&player);
126}235}
127236
128TEST_F(MediaPlayerUserTest, DataSet) {237void
238running_update (GObject * obj, GParamSpec * pspec, bool * running) {
239 *running = media_player_get_is_running(MEDIA_PLAYER(obj)) == TRUE;
240};
241
242TEST_F(MediaPlayerUserTest, DISABLED_DataSet) {
129 /* Put data into Acts */243 /* Put data into Acts */
130 set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time()));244 set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time()));
131 set_property("PlayerName", g_variant_new_string("The Player Formerly Known as Prince"));245 set_property("PlayerName", g_variant_new_string("The Player Formerly Known as Prince"));
@@ -141,11 +255,11 @@
141 MediaPlayerUser * player = media_player_user_new("user");255 MediaPlayerUser * player = media_player_user_new("user");
142 ASSERT_NE(nullptr, player);256 ASSERT_NE(nullptr, player);
143257
144 /* Get the proxy -- and it's precious precious data -- oh, my, precious! */
145 loop(100);
146
147 /* Ensure even with the proxy we don't have anything */258 /* Ensure even with the proxy we don't have anything */
148 EXPECT_TRUE(media_player_get_is_running(MEDIA_PLAYER(player)));259 bool running = false;
260 g_signal_connect(G_OBJECT(player), "notify::is-running", G_CALLBACK(running_update), &running);
261 running_update(G_OBJECT(player), nullptr, &running);
262 EXPECT_EVENTUALLY_EQ(true, running);
149 EXPECT_TRUE(media_player_get_can_raise(MEDIA_PLAYER(player)));263 EXPECT_TRUE(media_player_get_can_raise(MEDIA_PLAYER(player)));
150 EXPECT_STREQ("user", media_player_get_id(MEDIA_PLAYER(player)));264 EXPECT_STREQ("user", media_player_get_id(MEDIA_PLAYER(player)));
151 EXPECT_STREQ("The Player Formerly Known as Prince", media_player_get_name(MEDIA_PLAYER(player)));265 EXPECT_STREQ("The Player Formerly Known as Prince", media_player_get_name(MEDIA_PLAYER(player)));
@@ -168,7 +282,7 @@
168 g_clear_object(&player);282 g_clear_object(&player);
169}283}
170284
171TEST_F(MediaPlayerUserTest, TimeoutTest) {285TEST_F(MediaPlayerUserTest, DISABLED_TimeoutTest) {
172 /* Put data into Acts -- but 15 minutes ago */286 /* Put data into Acts -- but 15 minutes ago */
173 set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time() - 15 * 60 * 1000 * 1000));287 set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time() - 15 * 60 * 1000 * 1000));
174 set_property("PlayerName", g_variant_new_string("The Player Formerly Known as Prince"));288 set_property("PlayerName", g_variant_new_string("The Player Formerly Known as Prince"));
@@ -180,24 +294,26 @@
180 set_property("Album", g_variant_new_string("Vinyl is dead"));294 set_property("Album", g_variant_new_string("Vinyl is dead"));
181 set_property("ArtUrl", g_variant_new_string("http://art.url"));295 set_property("ArtUrl", g_variant_new_string("http://art.url"));
182296
183 /* Ensure the properties get set before we pull them */
184 loop(100);
185
186 /* Build our media player */297 /* Build our media player */
187 MediaPlayerUser * player = media_player_user_new("user");298 MediaPlayerUser * player = media_player_user_new("user");
188 ASSERT_NE(nullptr, player);299 ASSERT_NE(nullptr, player);
189300
190 /* Get the proxy -- and the old data, so old, like forever */301 bool running = false;
191 loop(100);302 g_signal_connect(G_OBJECT(player), "notify::is-running", G_CALLBACK(running_update), &running);
303 running_update(G_OBJECT(player), nullptr, &running);
192304
193 /* Ensure that we show up as not running */305 /* Ensure that we show up as not running */
194 EXPECT_FALSE(media_player_get_is_running(MEDIA_PLAYER(player)));306 EXPECT_EVENTUALLY_EQ(false, running);
195307
196 /* Update to make running */308 /* Update to make running */
197 set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time()));309 set_property("Timestamp", g_variant_new_uint64(g_get_monotonic_time()));
198 loop(100);310
199311 EXPECT_EVENTUALLY_EQ(true, running);
200 EXPECT_TRUE(media_player_get_is_running(MEDIA_PLAYER(player)));312
313 /* Clear to not run */
314 set_property("Timestamp", g_variant_new_uint64(1));
315
316 EXPECT_EVENTUALLY_EQ(false, running);
201317
202 g_clear_object(&in_icon);318 g_clear_object(&in_icon);
203 g_clear_object(&player);319 g_clear_object(&player);
204320
=== modified file 'tests/notifications-test.cc'
--- tests/notifications-test.cc 2015-02-24 19:05:10 +0000
+++ tests/notifications-test.cc 2015-10-13 13:18:26 +0000
@@ -350,29 +350,29 @@
350350
351 /* Set high volume with volume change */351 /* Set high volume with volume change */
352 notifications->clearNotifications();352 notifications->clearNotifications();
353 volume_control_mock_set_mock_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), TRUE);353 volume_control_mock_set_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), true);
354 setMockVolume(volumeControl, 0.90);354 setMockVolume(volumeControl, 0.90);
355 loop(50);355 loop(50);
356 notev = notifications->getNotifications();356 notev = notifications->getNotifications();
357 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 */357 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 */
358 EXPECT_EQ("Volume", notev[0].summary);358 EXPECT_EQ("Volume", notev[0].summary);
359 EXPECT_EQ("High volume", notev[0].body);359 EXPECT_EQ("High volume can damage your hearing.", notev[0].body);
360 EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);360 EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);
361361
362 /* Move it back */362 /* Move it back */
363 volume_control_mock_set_mock_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), FALSE);363 volume_control_mock_set_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), false);
364 setMockVolume(volumeControl, 0.50);364 setMockVolume(volumeControl, 0.50);
365 loop(50);365 loop(50);
366366
367 /* Set high volume without level change */367 /* Set high volume without level change */
368 /* NOTE: This can happen if headphones are plugged in */368 /* NOTE: This can happen if headphones are plugged in */
369 notifications->clearNotifications();369 notifications->clearNotifications();
370 volume_control_mock_set_mock_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), TRUE);370 volume_control_mock_set_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), TRUE);
371 loop(50);371 loop(50);
372 notev = notifications->getNotifications();372 notev = notifications->getNotifications();
373 ASSERT_EQ(1, notev.size());373 ASSERT_EQ(1, notev.size());
374 EXPECT_EQ("Volume", notev[0].summary);374 EXPECT_EQ("Volume", notev[0].summary);
375 EXPECT_EQ("High volume", notev[0].body);375 EXPECT_EQ("High volume can damage your hearing.", notev[0].body);
376 EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);376 EXPECT_GVARIANT_EQ("@s 'true'", notev[0].hints["x-canonical-value-bar-tint"]);
377}377}
378378
@@ -406,7 +406,7 @@
406 EXPECT_EQ(1, notev.size());406 EXPECT_EQ(1, notev.size());
407}407}
408408
409TEST_F(NotificationsTest, ExtendendVolumeNotification) {409TEST_F(NotificationsTest, DISABLED_ExtendendVolumeNotification) {
410 auto volumeControl = volumeControlMock();410 auto volumeControl = volumeControlMock();
411 auto soundService = standardService(volumeControl, playerListMock());411 auto soundService = standardService(volumeControl, playerListMock());
412412
@@ -424,7 +424,7 @@
424424
425 /* Allow an amplified volume */425 /* Allow an amplified volume */
426 notifications->clearNotifications();426 notifications->clearNotifications();
427 indicator_sound_service_set_allow_amplified_volume(soundService.get(), TRUE);427 //indicator_sound_service_set_allow_amplified_volume(soundService.get(), TRUE);
428 loop(50);428 loop(50);
429 notev = notifications->getNotifications();429 notev = notifications->getNotifications();
430 ASSERT_EQ(1, notev.size());430 ASSERT_EQ(1, notev.size());
@@ -440,7 +440,7 @@
440440
441 /* Put back */441 /* Put back */
442 notifications->clearNotifications();442 notifications->clearNotifications();
443 indicator_sound_service_set_allow_amplified_volume(soundService.get(), FALSE);443 //indicator_sound_service_set_allow_amplified_volume(soundService.get(), FALSE);
444 loop(50);444 loop(50);
445 notev = notifications->getNotifications();445 notev = notifications->getNotifications();
446 ASSERT_EQ(1, notev.size());446 ASSERT_EQ(1, notev.size());
447447
=== modified file 'tests/volume-control-mock.vala'
--- tests/volume-control-mock.vala 2015-02-17 16:54:53 +0000
+++ tests/volume-control-mock.vala 2015-10-13 13:18:26 +0000
@@ -20,12 +20,14 @@
2020
21public class VolumeControlMock : VolumeControl21public class VolumeControlMock : VolumeControl
22{22{
23 private bool _high_volume = false;
24 public override bool high_volume { get { return _high_volume; } protected set { _high_volume = value; } }
25 public void set_high_volume(bool b) { high_volume = b; }
26
23 public string mock_stream { get; set; default = "multimedia"; }27 public string mock_stream { get; set; default = "multimedia"; }
24 public override string stream { get { return mock_stream; } }28 public override string stream { get { return mock_stream; } }
25 public override bool ready { get; set; }29 public override bool ready { get; set; }
26 public override bool active_mic { get; set; }30 public override bool active_mic { get; set; }
27 public bool mock_high_volume { get; set; }
28 public override bool high_volume { get { return mock_high_volume; } }
29 public bool mock_mute { get; set; }31 public bool mock_mute { get; set; }
30 public override bool mute { get { return mock_mute; } }32 public override bool mute { get { return mock_mute; } }
31 public bool mock_is_playing { get; set; }33 public bool mock_is_playing { get; set; }
3234
=== modified file 'tests/volume-control-test.cc'
--- tests/volume-control-test.cc 2015-02-09 20:14:15 +0000
+++ tests/volume-control-test.cc 2015-10-13 13:18:26 +0000
@@ -32,7 +32,11 @@
32 DbusTestService * service = NULL;32 DbusTestService * service = NULL;
33 GDBusConnection * session = NULL;33 GDBusConnection * session = NULL;
3434
35 virtual void SetUp() {35 virtual void SetUp() override {
36
37 g_setenv("GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE);
38 g_setenv("GSETTINGS_BACKEND", "memory", TRUE);
39
36 service = dbus_test_service_new(NULL);40 service = dbus_test_service_new(NULL);
37 dbus_test_service_start_tasks(service);41 dbus_test_service_start_tasks(service);
3842

Subscribers

People subscribed via source and target branches