Merge lp:~ted/indicator-sound/volume-reason into lp:indicator-sound/15.04
- volume-reason
- Merge into trunk.15.04
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Ted Gould | ||||||||
Approved revision: | 487 | ||||||||
Merged at revision: | 479 | ||||||||
Proposed branch: | lp:~ted/indicator-sound/volume-reason | ||||||||
Merge into: | lp:indicator-sound/15.04 | ||||||||
Prerequisite: | lp:~ted/indicator-sound/notification-mock | ||||||||
Diff against target: |
654 lines (+133/-116) 6 files modified
src/CMakeLists.txt (+2/-0) src/service.vala (+28/-31) src/volume-control-pulse.vala (+58/-64) src/volume-control.vala (+15/-1) tests/notifications-test.cc (+28/-19) tests/volume-control-mock.vala (+2/-1) |
||||||||
To merge this branch: | bzr merge lp:~ted/indicator-sound/volume-reason | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jussi Pakkanen (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+250042@code.launchpad.net |
Commit message
Track the reason a volume was set to filter volume changes more accurately
Description of the change
This branch adds a reason to the volume so that we can track why it was set where it is. Most importantly this means that we can actually determine when we should show notifications or not, but it also does things like ensure that we don't have any PulseAudio setting loops that get built up.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:480
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:480
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:481
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:482
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:482
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:485
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:482
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Ted Gould (ted) wrote : | # |
Okay, works well now.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:486
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Jussi Pakkanen (jpakkane) wrote : | # |
Looks fine to me.
Preview Diff
1 | === modified file 'src/CMakeLists.txt' |
2 | --- src/CMakeLists.txt 2015-02-19 16:23:35 +0000 |
3 | +++ src/CMakeLists.txt 2015-02-19 16:23:36 +0000 |
4 | @@ -160,6 +160,7 @@ |
5 | |
6 | add_definitions( |
7 | -w |
8 | + -DG_LOG_DOMAIN="indicator-sound" |
9 | ) |
10 | |
11 | add_library( |
12 | @@ -170,6 +171,7 @@ |
13 | target_link_libraries( |
14 | indicator-sound-service-lib |
15 | ${SOUNDSERVICE_LIBRARIES} |
16 | + -lm |
17 | ) |
18 | |
19 | ########################### |
20 | |
21 | === modified file 'src/service.vala' |
22 | --- src/service.vala 2015-02-19 16:23:35 +0000 |
23 | +++ src/service.vala 2015-02-19 16:23:36 +0000 |
24 | @@ -173,7 +173,7 @@ |
25 | } |
26 | |
27 | /* Normalize volume, because the volume action's state is [0.0, 1.0], see create_volume_action() */ |
28 | - this.actions.change_action_state ("volume", this.volume_control.volume / this.max_volume); |
29 | + this.actions.change_action_state ("volume", this.volume_control.volume.volume / this.max_volume); |
30 | } |
31 | } |
32 | |
33 | @@ -210,8 +210,11 @@ |
34 | void activate_scroll_action (SimpleAction action, Variant? param) { |
35 | int delta = param.get_int32(); /* positive for up, negative for down */ |
36 | |
37 | - double v = this.volume_control.volume + volume_step_percentage * delta; |
38 | - this.volume_control.volume = v.clamp (0.0, this.max_volume); |
39 | + var scrollvol = new VolumeControl.Volume(); |
40 | + double v = this.volume_control.volume.volume + volume_step_percentage * delta; |
41 | + scrollvol.volume = v.clamp (0.0, this.max_volume); |
42 | + scrollvol.reason = VolumeControl.VolumeReasons.USER_KEYPRESS; |
43 | + this.volume_control.volume = scrollvol; |
44 | } |
45 | |
46 | void activate_desktop_settings (SimpleAction action, Variant? param) { |
47 | @@ -246,7 +249,7 @@ |
48 | } |
49 | |
50 | void update_root_icon () { |
51 | - double volume = this.volume_control.volume; |
52 | + double volume = this.volume_control.volume.volume; |
53 | string icon; |
54 | if (this.volume_control.mute) |
55 | icon = this.mute_blocks_sound ? "audio-volume-muted-blocking-panel" : "audio-volume-muted-panel"; |
56 | @@ -283,8 +286,6 @@ |
57 | |
58 | private bool check_sync_notification = false; |
59 | private bool support_sync_notification = false; |
60 | - private string last_output_notification = "multimedia"; |
61 | - private double last_volume_notification = 0; |
62 | |
63 | void update_sync_notification () { |
64 | if (!check_sync_notification) { |
65 | @@ -310,11 +311,11 @@ |
66 | |
67 | /* Choose an icon */ |
68 | string icon = "audio-volume-muted"; |
69 | - if (volume_control.volume <= 0.0) |
70 | + if (volume_control.volume.volume <= 0.0) |
71 | icon = "audio-volume-muted"; |
72 | - else if (volume_control.volume <= 0.3) |
73 | + else if (volume_control.volume.volume <= 0.3) |
74 | icon = "audio-volume-low"; |
75 | - else if (volume_control.volume <= 0.7) |
76 | + else if (volume_control.volume.volume <= 0.7) |
77 | icon = "audio-volume-medium"; |
78 | else |
79 | icon = "audio-volume-high"; |
80 | @@ -327,7 +328,7 @@ |
81 | /* Put it all into the notification */ |
82 | sync_notification.clear_hints (); |
83 | sync_notification.update (_("Volume"), volume_label, icon); |
84 | - sync_notification.set_hint ("value", (int32)(volume_control.volume * 100.0)); |
85 | + sync_notification.set_hint ("value", (int32)Math.round(volume_control.volume.volume * 100.0)); |
86 | sync_notification.set_hint ("x-canonical-value-bar-tint", tint); |
87 | sync_notification.set_hint ("x-canonical-private-synchronous", "true"); |
88 | sync_notification.set_hint ("x-canonical-non-shaped-icon", "true"); |
89 | @@ -425,44 +426,40 @@ |
90 | * volume_control.set_volume(). |
91 | */ |
92 | |
93 | - double volume = this.volume_control.volume / this.max_volume; |
94 | + double volume = this.volume_control.volume.volume / this.max_volume; |
95 | |
96 | volume_action = new SimpleAction.stateful ("volume", VariantType.INT32, new Variant.double (volume)); |
97 | |
98 | volume_action.change_state.connect ( (action, val) => { |
99 | double v = val.get_double () * this.max_volume; |
100 | - volume_control.volume = v.clamp (0.0, this.max_volume); |
101 | + |
102 | + var vol = new VolumeControl.Volume(); |
103 | + vol.volume = v.clamp (0.0, this.max_volume); |
104 | + vol.reason = VolumeControl.VolumeReasons.USER_KEYPRESS; |
105 | + volume_control.volume = vol; |
106 | }); |
107 | |
108 | /* activating this action changes the volume by the amount given in the parameter */ |
109 | volume_action.activate.connect ( (action, param) => { |
110 | int delta = param.get_int32 (); |
111 | - double v = volume_control.volume + volume_step_percentage * delta; |
112 | - volume_control.volume = v.clamp (0.0, this.max_volume); |
113 | + double v = volume_control.volume.volume + volume_step_percentage * delta; |
114 | + |
115 | + var vol = new VolumeControl.Volume(); |
116 | + vol.volume = v.clamp (0.0, this.max_volume); |
117 | + vol.reason = VolumeControl.VolumeReasons.USER_KEYPRESS; |
118 | + volume_control.volume = vol; |
119 | }); |
120 | |
121 | this.volume_control.notify["volume"].connect (() => { |
122 | /* Normalize volume, because the volume action's state is [0.0, 1.0], see create_volume_action() */ |
123 | - volume_action.set_state (new Variant.double (this.volume_control.volume / this.max_volume)); |
124 | + volume_action.set_state (new Variant.double (this.volume_control.volume.volume / this.max_volume)); |
125 | |
126 | this.update_root_icon (); |
127 | |
128 | - /* Update our volume and output */ |
129 | - var oldoutput = this.last_output_notification; |
130 | - this.last_output_notification = this.volume_control.stream; |
131 | - |
132 | - var oldvolume = this.last_volume_notification; |
133 | - this.last_volume_notification = volume_control.volume; |
134 | - |
135 | - /* Suppress notifications of volume changes if it is because the |
136 | - output stream changed. */ |
137 | - if (oldoutput != this.last_output_notification) |
138 | - return; |
139 | - /* Supress updates that don't change the value */ |
140 | - if (GLib.Math.fabs(oldvolume - this.last_volume_notification) < 0.01) |
141 | - return; |
142 | - |
143 | - this.update_sync_notification (); |
144 | + var reason = volume_control.volume.reason; |
145 | + if (reason == VolumeControl.VolumeReasons.USER_KEYPRESS || |
146 | + reason == VolumeControl.VolumeReasons.DEVICE_OUTPUT_CHANGE) |
147 | + this.update_sync_notification (); |
148 | }); |
149 | |
150 | this.volume_control.bind_property ("ready", volume_action, "enabled", BindingFlags.SYNC_CREATE); |
151 | |
152 | === modified file 'src/volume-control-pulse.vala' |
153 | --- src/volume-control-pulse.vala 2015-02-19 16:23:35 +0000 |
154 | +++ src/volume-control-pulse.vala 2015-02-19 16:23:36 +0000 |
155 | @@ -42,7 +42,7 @@ |
156 | private PulseAudio.Context context; |
157 | private bool _mute = true; |
158 | private bool _is_playing = false; |
159 | - private double _volume = 0.0; |
160 | + private VolumeControl.Volume _volume = new VolumeControl.Volume(); |
161 | private double _mic_volume = 0.0; |
162 | |
163 | /* Used by the pulseaudio stream restore extension */ |
164 | @@ -52,7 +52,7 @@ |
165 | private Gee.ArrayList<uint32> _sink_input_list = new Gee.ArrayList<uint32> (); |
166 | private HashMap<uint32, string> _sink_input_hash = new HashMap<uint32, string> (); |
167 | private bool _pulse_use_stream_restore = false; |
168 | - private uint32 _active_sink_input = -1; |
169 | + private int32 _active_sink_input = -1; |
170 | private string[] _valid_roles = {"multimedia", "alert", "alarm", "phone"}; |
171 | public override string stream { |
172 | get { |
173 | @@ -87,12 +87,15 @@ |
174 | /** true when high volume warnings should be shown */ |
175 | public override bool high_volume { |
176 | get { |
177 | - return this._volume > 0.75 && _active_port_headphone; |
178 | + return this._volume.volume > 0.75 && _active_port_headphone; |
179 | } |
180 | } |
181 | |
182 | public VolumeControlPulse () |
183 | { |
184 | + _volume.volume = 0.0; |
185 | + _volume.reason = VolumeControl.VolumeReasons.PULSE_CHANGE; |
186 | + |
187 | if (loop == null) |
188 | loop = new PulseAudio.GLibMainLoop (); |
189 | |
190 | @@ -164,8 +167,6 @@ |
191 | |
192 | private void sink_info_cb_for_props (Context c, SinkInfo? i, int eol) |
193 | { |
194 | - bool old_high_volume = this.high_volume; |
195 | - |
196 | if (i == null) |
197 | return; |
198 | |
199 | @@ -197,16 +198,13 @@ |
200 | } |
201 | |
202 | if (_pulse_use_stream_restore == false && |
203 | - _volume != volume_to_double (i.volume.max ())) |
204 | + _volume.volume != volume_to_double (i.volume.max ())) |
205 | { |
206 | - _volume = volume_to_double (i.volume.max ()); |
207 | - this.notify_property("volume"); |
208 | - start_local_volume_timer(); |
209 | + var vol = new VolumeControl.Volume(); |
210 | + vol.volume = volume_to_double (i.volume.max ()); |
211 | + vol.reason = VolumeControl.VolumeReasons.PULSE_CHANGE; |
212 | + this.volume = vol; |
213 | } |
214 | - |
215 | - if (this.high_volume != old_high_volume) { |
216 | - this.notify_property("high-volume"); |
217 | - } |
218 | } |
219 | |
220 | private void source_info_cb (Context c, SourceInfo? i, int eol) |
221 | @@ -264,17 +262,18 @@ |
222 | Variant body = message.get_body (); |
223 | Variant varray = body.get_child_value (0); |
224 | |
225 | - uint32 type = 0, volume = 0; |
226 | + uint32 type = 0, lvolume = 0; |
227 | VariantIter iter = varray.iterator (); |
228 | - iter.next ("(uu)", &type, &volume); |
229 | + iter.next ("(uu)", &type, &lvolume); |
230 | /* Here we need to compare integer values to avoid rounding issues, so just |
231 | * using the volume values used by pulseaudio */ |
232 | - PulseAudio.Volume cvolume = double_to_volume (_volume); |
233 | - if (volume != cvolume) { |
234 | + PulseAudio.Volume cvolume = double_to_volume (_volume.volume); |
235 | + if (lvolume != cvolume) { |
236 | /* Someone else changed the volume for this role, reflect on the indicator */ |
237 | - _volume = volume_to_double (volume); |
238 | - this.notify_property("volume"); |
239 | - start_local_volume_timer(); |
240 | + var vol = new VolumeControl.Volume(); |
241 | + vol.volume = volume_to_double (lvolume); |
242 | + vol.reason = VolumeControl.VolumeReasons.PULSE_CHANGE; |
243 | + this.volume = vol; |
244 | } |
245 | } |
246 | } |
247 | @@ -283,7 +282,7 @@ |
248 | return message; |
249 | } |
250 | |
251 | - private async void update_active_sink_input (uint32 index) |
252 | + private async void update_active_sink_input (int32 index) |
253 | { |
254 | if ((index == -1) || (index != _active_sink_input && index in _sink_input_list)) { |
255 | string sink_input_objp = _objp_role_alert; |
256 | @@ -315,9 +314,10 @@ |
257 | VariantIter iter = tmp.iterator (); |
258 | iter.next ("(uu)", &type, &volume); |
259 | |
260 | - _volume = volume_to_double (volume); |
261 | - this.notify_property("volume"); |
262 | - start_local_volume_timer(); |
263 | + var vol = new VolumeControl.Volume(); |
264 | + vol.volume = volume_to_double (volume); |
265 | + vol.reason = VolumeControl.VolumeReasons.VOLUME_STREAM_CHANGE; |
266 | + this.volume = vol; |
267 | } catch (GLib.Error e) { |
268 | warning ("unable to get volume for active role %s (%s)", sink_input_objp, e.message); |
269 | } |
270 | @@ -350,7 +350,7 @@ |
271 | /* Only switch the active sink input in case a phone one is not active */ |
272 | if (_active_sink_input == -1 || |
273 | _sink_input_hash.get (_active_sink_input) != _objp_role_phone) |
274 | - update_active_sink_input.begin (sink_input.index); |
275 | + update_active_sink_input.begin ((int32)sink_input.index); |
276 | } |
277 | } |
278 | } |
279 | @@ -362,7 +362,7 @@ |
280 | _sink_input_hash.unset (index); |
281 | if (index == _active_sink_input) { |
282 | if (_sink_input_list.size != 0) |
283 | - update_active_sink_input.begin (_sink_input_list.get (0)); |
284 | + update_active_sink_input.begin ((int32)_sink_input_list.get (0)); |
285 | else |
286 | update_active_sink_input.begin (-1); |
287 | } |
288 | @@ -542,7 +542,7 @@ |
289 | return; |
290 | |
291 | unowned CVolume cvol = i.volume; |
292 | - cvol.scale (double_to_volume (_volume)); |
293 | + cvol.scale (double_to_volume (_volume.volume)); |
294 | c.set_sink_volume_by_index (i.index, cvol, set_volume_success_cb); |
295 | } |
296 | |
297 | @@ -565,8 +565,9 @@ |
298 | active_role_objp = _sink_input_hash.get (_active_sink_input); |
299 | |
300 | try { |
301 | + double vol = _volume.volume; |
302 | var builder = new VariantBuilder (new VariantType ("a(uu)")); |
303 | - builder.add ("(uu)", 0, double_to_volume (_volume)); |
304 | + builder.add ("(uu)", 0, double_to_volume (vol)); |
305 | Variant volume = builder.end (); |
306 | |
307 | /* Increase the signal counter so we can handle the callback */ |
308 | @@ -579,7 +580,7 @@ |
309 | new Variant ("(ssv)", "org.PulseAudio.Ext.StreamRestore1.RestoreEntry", "Volume", volume), |
310 | null, DBusCallFlags.NONE, -1); |
311 | |
312 | - this.notify_property("volume"); |
313 | + debug ("Set volume to %f on path %s", vol, active_role_objp); |
314 | } catch (GLib.Error e) { |
315 | lock (_pa_volume_sig_count) { |
316 | _pa_volume_sig_count--; |
317 | @@ -588,31 +589,6 @@ |
318 | } |
319 | } |
320 | |
321 | - bool set_volume_internal (double volume) |
322 | - { |
323 | - if (context.get_state () != Context.State.READY) |
324 | - return false; |
325 | - |
326 | - if (_volume != volume) { |
327 | - var old_high_volume = this.high_volume; |
328 | - |
329 | - _volume = volume; |
330 | - if (_pulse_use_stream_restore) |
331 | - set_volume_active_role.begin (); |
332 | - else |
333 | - context.get_server_info (server_info_cb_for_set_volume); |
334 | - |
335 | - this.notify_property("volume"); |
336 | - |
337 | - if (this.high_volume != old_high_volume) |
338 | - this.notify_property("high-volume"); |
339 | - |
340 | - return true; |
341 | - } else { |
342 | - return false; |
343 | - } |
344 | - } |
345 | - |
346 | void set_mic_volume_success_cb (Context c, int success) |
347 | { |
348 | if ((bool)success) |
349 | @@ -627,14 +603,28 @@ |
350 | } |
351 | } |
352 | |
353 | - public override double volume { |
354 | + public override VolumeControl.Volume volume { |
355 | get { |
356 | return _volume; |
357 | } |
358 | set { |
359 | - if (set_volume_internal (value)) { |
360 | - start_local_volume_timer(); |
361 | - } |
362 | + debug("Setting volume to %f for profile %d because %d", value.volume, _active_sink_input, value.reason); |
363 | + |
364 | + var old_high_volume = this.high_volume; |
365 | + _volume = value; |
366 | + |
367 | + /* Make sure we're connected to Pulse and pulse didn't give us the change */ |
368 | + if (context.get_state () == Context.State.READY && |
369 | + _volume.reason != VolumeControl.VolumeReasons.PULSE_CHANGE) |
370 | + if (_pulse_use_stream_restore) |
371 | + set_volume_active_role.begin (); |
372 | + else |
373 | + context.get_server_info (server_info_cb_for_set_volume); |
374 | + |
375 | + if (this.high_volume != old_high_volume) |
376 | + this.notify_property("high-volume"); |
377 | + |
378 | + start_local_volume_timer(); |
379 | } |
380 | } |
381 | |
382 | @@ -687,7 +677,7 @@ |
383 | } |
384 | } |
385 | |
386 | - stdout.printf ("PulseAudio dbus unix socket: %s\n", address); |
387 | + debug ("PulseAudio dbus unix socket: %s", address); |
388 | try { |
389 | _pconn = new DBusConnection.for_address_sync (address, DBusConnectionFlags.AUTHENTICATION_CLIENT); |
390 | } catch (GLib.Error e) { |
391 | @@ -707,7 +697,7 @@ |
392 | |
393 | /* Only use stream restore if every used role is available */ |
394 | if (_objp_role_multimedia != null && _objp_role_alert != null && _objp_role_alarm != null && _objp_role_phone != null) { |
395 | - stdout.printf ("Using PulseAudio DBUS Stream Restore module\n"); |
396 | + debug ("Using PulseAudio DBUS Stream Restore module"); |
397 | /* Restore volume and update default entry */ |
398 | update_active_sink_input.begin (-1); |
399 | _pulse_use_stream_restore = true; |
400 | @@ -723,7 +713,7 @@ |
401 | /* Workaround for older versions of vala that don't provide get_objv */ |
402 | VariantIter iter = props_variant.iterator (); |
403 | iter.next ("o", &objp); |
404 | - stdout.printf ("Found obj path %s for restore data named %s\n", objp, name); |
405 | + debug ("Found obj path %s for restore data named %s\n", objp, name); |
406 | } catch (GLib.Error e) { |
407 | warning ("unable to find stream restore data for: %s", name); |
408 | } |
409 | @@ -839,7 +829,7 @@ |
410 | } |
411 | } |
412 | |
413 | - private async void sync_volume_to_accountsservice (double volume) |
414 | + private async void sync_volume_to_accountsservice (VolumeControl.Volume volume) |
415 | { |
416 | if (_user_proxy == null) |
417 | return; |
418 | @@ -848,7 +838,7 @@ |
419 | _volume_cancellable.reset (); |
420 | |
421 | try { |
422 | - 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, _volume_cancellable); |
423 | + 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); |
424 | } catch (GLib.Error e) { |
425 | warning ("unable to sync volume to AccountsService: %s", e.message); |
426 | } |
427 | @@ -891,7 +881,11 @@ |
428 | { |
429 | if (_accountservice_volume_timer == 0) { |
430 | // If we haven't been messing with local volume recently, apply immediately. |
431 | - if (_local_volume_timer == 0 && !set_volume_internal (_account_service_volume)) { |
432 | + if (_local_volume_timer == 0) { |
433 | + var vol = new VolumeControl.Volume(); |
434 | + vol.volume = _account_service_volume; |
435 | + vol.reason = VolumeControl.VolumeReasons.ACCOUNTS_SERVICE_SET; |
436 | + this.volume = vol; |
437 | return; |
438 | } |
439 | // Else check again in another second if needed. |
440 | |
441 | === modified file 'src/volume-control.vala' |
442 | --- src/volume-control.vala 2015-02-19 16:23:35 +0000 |
443 | +++ src/volume-control.vala 2015-02-19 16:23:36 +0000 |
444 | @@ -20,13 +20,27 @@ |
445 | |
446 | public abstract class VolumeControl : Object |
447 | { |
448 | + public enum VolumeReasons { |
449 | + PULSE_CHANGE, |
450 | + ACCOUNTS_SERVICE_SET, |
451 | + DEVICE_OUTPUT_CHANGE, |
452 | + USER_KEYPRESS, |
453 | + VOLUME_STREAM_CHANGE |
454 | + } |
455 | + |
456 | + public class Volume : Object { |
457 | + public double volume; |
458 | + public VolumeReasons reason; |
459 | + } |
460 | + |
461 | public virtual string stream { get { return ""; } } |
462 | public virtual bool ready { get { return false; } set { } } |
463 | public virtual bool active_mic { get { return false; } set { } } |
464 | public virtual bool high_volume { get { return false; } } |
465 | public virtual bool mute { get { return false; } } |
466 | public virtual bool is_playing { get { return false; } } |
467 | - public virtual double volume { get { return 0.0; } set { } } |
468 | + private Volume _volume; |
469 | + public virtual Volume volume { get { return _volume; } set { } } |
470 | public virtual double mic_volume { get { return 0.0; } set { } } |
471 | |
472 | public abstract void set_mute (bool mute); |
473 | |
474 | === modified file 'tests/notifications-test.cc' |
475 | --- tests/notifications-test.cc 2015-02-19 16:23:35 +0000 |
476 | +++ tests/notifications-test.cc 2015-02-19 16:23:36 +0000 |
477 | @@ -137,6 +137,15 @@ |
478 | |
479 | return soundService; |
480 | } |
481 | + |
482 | + void setMockVolume (std::shared_ptr<VolumeControl> volumeControl, double volume, VolumeControlVolumeReasons reason = VOLUME_CONTROL_VOLUME_REASONS_USER_KEYPRESS) { |
483 | + VolumeControlVolume * vol = volume_control_volume_new(); |
484 | + vol->volume = volume; |
485 | + vol->reason = reason; |
486 | + |
487 | + volume_control_set_volume(volumeControl.get(), vol); |
488 | + g_object_unref(vol); |
489 | + } |
490 | }; |
491 | |
492 | TEST_F(NotificationsTest, BasicObject) { |
493 | @@ -154,7 +163,7 @@ |
494 | |
495 | /* Set a volume */ |
496 | notifications->clearNotifications(); |
497 | - volume_control_set_volume(volumeControl.get(), 0.50); |
498 | + setMockVolume(volumeControl, 0.50); |
499 | loop(50); |
500 | auto notev = notifications->getNotifications(); |
501 | ASSERT_EQ(1, notev.size()); |
502 | @@ -166,22 +175,22 @@ |
503 | |
504 | /* Set a different volume */ |
505 | notifications->clearNotifications(); |
506 | - volume_control_set_volume(volumeControl.get(), 0.60); |
507 | + setMockVolume(volumeControl, 0.60); |
508 | loop(50); |
509 | notev = notifications->getNotifications(); |
510 | ASSERT_EQ(1, notev.size()); |
511 | EXPECT_GVARIANT_EQ("@i 60", notev[0].hints["value"]); |
512 | |
513 | - /* Set the same volume */ |
514 | + /* Have pulse set a volume */ |
515 | notifications->clearNotifications(); |
516 | - volume_control_set_volume(volumeControl.get(), 0.60); |
517 | + setMockVolume(volumeControl, 0.70, VOLUME_CONTROL_VOLUME_REASONS_PULSE_CHANGE); |
518 | loop(50); |
519 | notev = notifications->getNotifications(); |
520 | ASSERT_EQ(0, notev.size()); |
521 | |
522 | - /* Change just a little */ |
523 | + /* Have AS set the volume */ |
524 | notifications->clearNotifications(); |
525 | - volume_control_set_volume(volumeControl.get(), 0.60001); |
526 | + setMockVolume(volumeControl, 0.80, VOLUME_CONTROL_VOLUME_REASONS_ACCOUNTS_SERVICE_SET); |
527 | loop(50); |
528 | notev = notifications->getNotifications(); |
529 | ASSERT_EQ(0, notev.size()); |
530 | @@ -193,7 +202,7 @@ |
531 | |
532 | /* Set a volume */ |
533 | notifications->clearNotifications(); |
534 | - volume_control_set_volume(volumeControl.get(), 0.5); |
535 | + setMockVolume(volumeControl, 0.5); |
536 | loop(50); |
537 | auto notev = notifications->getNotifications(); |
538 | ASSERT_EQ(1, notev.size()); |
539 | @@ -201,7 +210,7 @@ |
540 | /* Change Streams, no volume change */ |
541 | notifications->clearNotifications(); |
542 | volume_control_mock_set_mock_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), "alarm"); |
543 | - volume_control_set_volume(volumeControl.get(), 0.5); |
544 | + setMockVolume(volumeControl, 0.5, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE); |
545 | loop(50); |
546 | notev = notifications->getNotifications(); |
547 | EXPECT_EQ(0, notev.size()); |
548 | @@ -209,7 +218,7 @@ |
549 | /* Change Streams, volume change */ |
550 | notifications->clearNotifications(); |
551 | volume_control_mock_set_mock_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), "alert"); |
552 | - volume_control_set_volume(volumeControl.get(), 0.60); |
553 | + setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE); |
554 | loop(50); |
555 | notev = notifications->getNotifications(); |
556 | EXPECT_EQ(0, notev.size()); |
557 | @@ -217,9 +226,9 @@ |
558 | /* Change Streams, no volume change, volume up */ |
559 | notifications->clearNotifications(); |
560 | volume_control_mock_set_mock_stream(VOLUME_CONTROL_MOCK(volumeControl.get()), "multimedia"); |
561 | - volume_control_set_volume(volumeControl.get(), 0.60); |
562 | + setMockVolume(volumeControl, 0.6, VOLUME_CONTROL_VOLUME_REASONS_VOLUME_STREAM_CHANGE); |
563 | loop(50); |
564 | - volume_control_set_volume(volumeControl.get(), 0.65); |
565 | + setMockVolume(volumeControl, 0.65); |
566 | notev = notifications->getNotifications(); |
567 | EXPECT_EQ(1, notev.size()); |
568 | EXPECT_GVARIANT_EQ("@i 65", notev[0].hints["value"]); |
569 | @@ -231,7 +240,7 @@ |
570 | |
571 | /* Set an initial volume */ |
572 | notifications->clearNotifications(); |
573 | - volume_control_set_volume(volumeControl.get(), 0.5); |
574 | + setMockVolume(volumeControl, 0.5); |
575 | loop(50); |
576 | auto notev = notifications->getNotifications(); |
577 | ASSERT_EQ(1, notev.size()); |
578 | @@ -239,7 +248,7 @@ |
579 | /* Generate a set of notifications */ |
580 | notifications->clearNotifications(); |
581 | for (float i = 0.0; i < 1.01; i += 0.1) { |
582 | - volume_control_set_volume(volumeControl.get(), i); |
583 | + setMockVolume(volumeControl, i); |
584 | } |
585 | |
586 | loop(50); |
587 | @@ -265,7 +274,7 @@ |
588 | |
589 | /* Set a volume */ |
590 | notifications->clearNotifications(); |
591 | - volume_control_set_volume(volumeControl.get(), 0.50); |
592 | + setMockVolume(volumeControl, 0.50); |
593 | loop(50); |
594 | auto notev = notifications->getNotifications(); |
595 | ASSERT_EQ(1, notev.size()); |
596 | @@ -283,7 +292,7 @@ |
597 | |
598 | /* Change the volume */ |
599 | notifications->clearNotifications(); |
600 | - volume_control_set_volume(volumeControl.get(), 0.60); |
601 | + setMockVolume(volumeControl, 0.60); |
602 | loop(50); |
603 | notev = notifications->getNotifications(); |
604 | ASSERT_EQ(0, notev.size()); |
605 | @@ -300,7 +309,7 @@ |
606 | |
607 | /* Change the volume again */ |
608 | notifications->clearNotifications(); |
609 | - volume_control_set_volume(volumeControl.get(), 0.70); |
610 | + setMockVolume(volumeControl, 0.70); |
611 | loop(50); |
612 | notev = notifications->getNotifications(); |
613 | ASSERT_EQ(1, notev.size()); |
614 | @@ -312,7 +321,7 @@ |
615 | |
616 | /* Set a volume */ |
617 | notifications->clearNotifications(); |
618 | - volume_control_set_volume(volumeControl.get(), 0.50); |
619 | + setMockVolume(volumeControl, 0.50); |
620 | loop(50); |
621 | auto notev = notifications->getNotifications(); |
622 | ASSERT_EQ(1, notev.size()); |
623 | @@ -323,7 +332,7 @@ |
624 | /* Set high volume with volume change */ |
625 | notifications->clearNotifications(); |
626 | volume_control_mock_set_mock_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), TRUE); |
627 | - volume_control_set_volume(volumeControl.get(), 0.90); |
628 | + setMockVolume(volumeControl, 0.90); |
629 | loop(50); |
630 | notev = notifications->getNotifications(); |
631 | 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 */ |
632 | @@ -333,7 +342,7 @@ |
633 | |
634 | /* Move it back */ |
635 | volume_control_mock_set_mock_high_volume(VOLUME_CONTROL_MOCK(volumeControl.get()), FALSE); |
636 | - volume_control_set_volume(volumeControl.get(), 0.50); |
637 | + setMockVolume(volumeControl, 0.50); |
638 | loop(50); |
639 | |
640 | /* Set high volume without level change */ |
641 | |
642 | === modified file 'tests/volume-control-mock.vala' |
643 | --- tests/volume-control-mock.vala 2015-02-19 16:23:35 +0000 |
644 | +++ tests/volume-control-mock.vala 2015-02-19 16:23:36 +0000 |
645 | @@ -30,7 +30,8 @@ |
646 | public override bool mute { get { return mock_mute; } } |
647 | public bool mock_is_playing { get; set; } |
648 | public override bool is_playing { get { return mock_is_playing; } } |
649 | - public override double volume { get; set; } |
650 | + private VolumeControl.Volume _vol = new VolumeControl.Volume(); |
651 | + public override VolumeControl.Volume volume { get { return _vol; } set { _vol = value; }} |
652 | public override double mic_volume { get; set; } |
653 | |
654 | public override void set_mute (bool mute) { |
FAILED: Continuous integration, rev:480 jenkins. qa.ubuntu. com/job/ indicator- sound-ci/ 203/ jenkins. qa.ubuntu. com/job/ indicator- sound-vivid- amd64-ci/ 30/console jenkins. qa.ubuntu. com/job/ indicator- sound-vivid- armhf-ci/ 30/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/indicator- sound-ci/ 203/rebuild
http://