Merge lp:~ted/indicator-sound/mega-merge into lp:indicator-sound/15.04

Proposed by Ted Gould
Status: Merged
Approved by: Charles Kerr
Approved revision: 469
Merged at revision: 461
Proposed branch: lp:~ted/indicator-sound/mega-merge
Merge into: lp:indicator-sound/15.04
Diff against target: 442 lines (+268/-9)
5 files modified
debian/changelog (+13/-0)
src/service.vala (+21/-2)
src/sound-menu.vala (+39/-1)
src/volume-control.vala (+96/-6)
tests/manual (+99/-0)
To merge this branch: bzr merge lp:~ted/indicator-sound/mega-merge
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Ted Gould Pending
Review via email: mp+240751@code.launchpad.net

This proposal supersedes a proposal from 2014-11-05.

Commit message

Manually merging branches to resolve conflicts

To post a comment you must log in.
lp:~ted/indicator-sound/mega-merge updated
468. By Ted Gould

Fixing bug number

469. By Ted Gould

Missed part of a merge

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) wrote :

These have already been approved separately; re-approving in the conflict-resolved megapatch

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2014-10-10 15:40:30 +0000
3+++ debian/changelog 2014-11-05 16:48:46 +0000
4@@ -1,3 +1,16 @@
5+indicator-sound (12.10.2+14.10.20141010-0ubuntu8) UNRELEASED; urgency=medium
6+
7+ * Remove various Vala warnings
8+ * Show notifications on volume change (LP: #1378564, #1378961)
9+ * Warn on high audio levels when using headphones (LP: #1232633, #1373404)
10+ * service.vala: don't call set_volume unnecessarily (LP: #1381871)
11+ * Integration test for audio roles
12+ * Integration test for silent mode
13+ * Ensure the greeter menu matches whether song metadata should be shown,
14+ and update the metadata based on the new setting. (LP: #1358340)
15+
16+ -- Ted Gould <ted@ubuntu.com> Wed, 05 Nov 2014 10:42:12 -0600
17+
18 indicator-sound (12.10.2+14.10.20141010-0ubuntu1) utopic; urgency=low
19
20 [ Ricardo Salveti de Araujo ]
21
22=== modified file 'src/service.vala'
23--- src/service.vala 2014-10-03 14:27:38 +0000
24+++ src/service.vala 2014-11-05 16:48:46 +0000
25@@ -49,6 +49,7 @@
26 this.actions.add_action (this.create_mute_action ());
27 this.actions.add_action (this.create_volume_action ());
28 this.actions.add_action (this.create_mic_volume_action ());
29+ this.actions.add_action (this.create_high_volume_actions ());
30
31 this.menus = new HashTable<string, SoundMenu> (str_hash, str_equal);
32 this.menus.insert ("desktop_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS));
33@@ -60,6 +61,10 @@
34 this.volume_control.bind_property ("active-mic", menu, "show-mic-volume", BindingFlags.SYNC_CREATE);
35 });
36
37+ this.menus.@foreach ( (profile, menu) => {
38+ this.volume_control.bind_property ("high-volume", menu, "show-high-volume-warning", BindingFlags.SYNC_CREATE);
39+ });
40+
41 this.sync_preferred_players ();
42 this.settings.changed["interested-media-players"].connect ( () => {
43 this.sync_preferred_players ();
44@@ -69,7 +74,7 @@
45 List<string> caps = Notify.get_server_caps ();
46 if (caps.find_custom ("x-canonical-private-synchronous", strcmp) != null) {
47 this.notification = new Notify.Notification ("indicator-sound", "", "");
48- this.notification.set_hint_string ("x-canonical-private-synchronous", "indicator-sound");
49+ this.notification.set_hint ("x-canonical-private-synchronous", "indicator-sound");
50 }
51 }
52
53@@ -126,6 +131,9 @@
54 }
55
56 set {
57+ if (this.allow_amplified_volume == value)
58+ return;
59+
60 if (value) {
61 /* from pulse/volume.h: #define PA_VOLUME_UI_MAX (pa_sw_volume_from_dB(+11.0)) */
62 this.max_volume = (double)PulseAudio.Volume.sw_from_dB(11.0) / PulseAudio.Volume.NORM;
63@@ -174,6 +182,8 @@
64 double v = this.volume_control.get_volume () + volume_step_percentage * delta;
65 this.volume_control.set_volume (v.clamp (0.0, this.max_volume));
66
67+ /* TODO: Don't want to mess up the desktop today, but we should remove this
68+ scrolling change and merge that into volume control's notification */
69 if (this.notification != null) {
70 string icon;
71 if (v <= 0.0)
72@@ -186,7 +196,7 @@
73 icon = "notification-audio-volume-high";
74
75 this.notification.update ("indicator-sound", "", icon);
76- this.notification.set_hint_int32 ("value", ((int32) (100 * v / this.max_volume)).clamp (-1, 101));
77+ this.notification.set_hint ("value", ((int32) (100 * v / this.max_volume)).clamp (-1, 101));
78 try {
79 this.notification.show ();
80 }
81@@ -388,6 +398,15 @@
82 return volume_action;
83 }
84
85+ Action create_high_volume_actions () {
86+ var high_volume_action = new SimpleAction.stateful("high-volume", null, new Variant.boolean (this.volume_control.high_volume));
87+
88+ this.volume_control.notify["high-volume"].connect( () =>
89+ high_volume_action.set_state(new Variant.boolean (this.volume_control.high_volume)));
90+
91+ return high_volume_action;
92+ }
93+
94 void bus_acquired (DBusConnection connection, string name) {
95 try {
96 connection.export_action_group ("/com/canonical/indicator/sound", this.actions);
97
98=== modified file 'src/sound-menu.vala'
99--- src/sound-menu.vala 2014-10-08 01:57:56 +0000
100+++ src/sound-menu.vala 2014-11-05 16:48:46 +0000
101@@ -93,12 +93,49 @@
102 this.mic_volume_shown = true;
103 }
104 else if (!value && this.mic_volume_shown) {
105- this.volume_section.remove (this.volume_section.get_n_items () -1);
106+ int location = -1;
107+ while ((location = find_action(this.volume_section, "indicator.mic-volume")) != -1) {
108+ this.volume_section.remove (location);
109+ }
110 this.mic_volume_shown = false;
111 }
112 }
113 }
114
115+ public bool show_high_volume_warning {
116+ get {
117+ return this.high_volume_warning_shown;
118+ }
119+ set {
120+ if (value && !this.high_volume_warning_shown) {
121+ /* NOTE: Action doesn't really exist, just used to find below when removing */
122+ var item = new MenuItem(_("High volume can damage your hearing."), "indicator.high-volume-warning-item");
123+ volume_section.append_item (item);
124+ this.high_volume_warning_shown = true;
125+ }
126+ else if (!value && this.high_volume_warning_shown) {
127+ int location = -1;
128+ while ((location = find_action(this.volume_section, "indicator.high-volume-warning-item")) != -1) {
129+ this.volume_section.remove (location);
130+ }
131+ this.high_volume_warning_shown = false;
132+ }
133+ }
134+ }
135+
136+ int find_action (Menu menu, string in_action) {
137+ int n = menu.get_n_items ();
138+ for (int i = 0; i < n; i++) {
139+ string action;
140+ menu.get_item_attribute (i, "action", "s", out action);
141+ if (in_action == action)
142+ return i;
143+ }
144+
145+ return -1;
146+ }
147+
148+
149 public void add_player (MediaPlayer player) {
150 if (this.notify_handlers.contains (player))
151 return;
152@@ -141,6 +178,7 @@
153 Menu volume_section;
154 bool mic_volume_shown;
155 bool settings_shown = false;
156+ bool high_volume_warning_shown = false;
157 bool hide_inactive;
158 bool hide_players = false;
159 HashTable<MediaPlayer, ulong> notify_handlers;
160
161=== modified file 'src/volume-control.vala'
162--- src/volume-control.vala 2014-10-10 15:40:19 +0000
163+++ src/volume-control.vala 2014-11-05 16:48:46 +0000
164@@ -19,6 +19,7 @@
165 */
166
167 using PulseAudio;
168+using Notify;
169 using Gee;
170
171 [CCode(cname="pa_cvolume_set", cheader_filename = "pulse/volume.h")]
172@@ -67,6 +68,8 @@
173 private uint _accountservice_volume_timer = 0;
174 private bool _send_next_local_volume = false;
175 private double _account_service_volume = 0.0;
176+ private Notify.Notification _notification;
177+ private bool _active_port_headphone = false;
178
179 public signal void volume_changed (double v);
180 public signal void mic_volume_changed (double v);
181@@ -77,6 +80,9 @@
182 /** true when a microphone is active **/
183 public bool active_mic { get; private set; default = false; }
184
185+ /** true when high volume warnings should be shown */
186+ public bool high_volume { get; set; }
187+
188 public VolumeControl ()
189 {
190 if (loop == null)
191@@ -84,6 +90,13 @@
192
193 _mute_cancellable = new Cancellable ();
194 _volume_cancellable = new Cancellable ();
195+
196+ Notify.init ("Volume");
197+ _notification = new Notify.Notification(_("Volume"), "", "audio-volume-muted");
198+ _notification.set_hint ("value", 0);
199+ _notification.set_hint ("x-canonical-private-synchronous", "true");
200+ _notification.set_hint ("x-canonical-non-shaped-icon", "true");
201+
202 setup_accountsservice.begin ();
203
204 this.reconnect_to_pulse ();
205@@ -149,6 +162,8 @@
206
207 private void sink_info_cb_for_props (Context c, SinkInfo? i, int eol)
208 {
209+ bool old_active_port_headphone = this._active_port_headphone;
210+
211 if (i == null)
212 return;
213
214@@ -165,12 +180,27 @@
215 this.notify_property ("is-playing");
216 }
217
218+ /* Check if the current active port is headset/headphone */
219+ /* There is not easy way to check if the port is a headset/headphone besides
220+ * checking for the port name. On touch (with the pulseaudio droid element)
221+ * the headset/headphone port is called 'output-headset' and 'output-headphone'.
222+ * On the desktop this is usually called 'analog-output-headphones' */
223+ if (i.active_port.name == "output-wired_headset" ||
224+ i.active_port.name == "output-wired_headphone" ||
225+ i.active_port.name == "analog-output-headphones") {
226+ _active_port_headphone = true;
227+ } else {
228+ _active_port_headphone = false;
229+ }
230+
231 if (_pulse_use_stream_restore == false &&
232 _volume != volume_to_double (i.volume.max ()))
233 {
234 _volume = volume_to_double (i.volume.max ());
235 volume_changed (_volume);
236 start_local_volume_timer();
237+ } else if (this._active_port_headphone != old_active_port_headphone) {
238+ volume_changed (_volume);
239 }
240 }
241
242@@ -572,8 +602,64 @@
243
244 public void set_volume (double volume)
245 {
246- if (set_volume_internal (volume))
247+ /* Using this to detect whether we're on the phone or not */
248+ if (_pulse_use_stream_restore) {
249+ /* Watch for extreme */
250+ if (volume > 0.75 && _active_port_headphone)
251+ high_volume = true;
252+ else
253+ high_volume = false;
254+
255+ /* Determine Label */
256+ string volume_label = "";
257+ if (high_volume)
258+ volume_label = _("High volume");
259+
260+ /* Choose an icon */
261+ string icon = "audio-volume-muted";
262+ if (volume <= 0.0)
263+ icon = "audio-volume-muted";
264+ else if (volume <= 0.3)
265+ icon = "audio-volume-low";
266+ else if (volume <= 0.7)
267+ icon = "audio-volume-medium";
268+ else
269+ icon = "audio-volume-high";
270+
271+ /* Choose a sound */
272+ string? sound = null;
273+ if (!((_active_sink_input >= 0) && (_active_sink_input < _valid_roles.length)
274+ && (_valid_roles[_active_sink_input] == "multimedia")))
275+ sound = "/usr/share/sounds/ubuntu/stereo/message.ogg";
276+
277+ /* Check tint */
278+ string tint = "false";
279+ if (high_volume)
280+ tint = "true";
281+
282+ /* Put it all into the notification */
283+ _notification.clear_hints ();
284+ _notification.update (_("Volume"), volume_label, icon);
285+ _notification.set_hint ("value", (int32)(volume * 100.0));
286+ /* TODO: Removing sound until we can get all the roles cleaned up for
287+ when to play it. We expect this to come back, but in another landing.
288+ _notification.set_hint ("sound-file", sound);
289+ */
290+ _notification.set_hint ("x-canonical-value-bar-tint", tint);
291+ _notification.set_hint ("x-canonical-private-synchronous", "true");
292+ _notification.set_hint ("x-canonical-non-shaped-icon", "true");
293+
294+ /* Show it */
295+ try {
296+ _notification.show ();
297+ } catch (GLib.Error e) {
298+ warning("Unable to send volume change notification: %s", e.message);
299+ }
300+ }
301+
302+ if (set_volume_internal (volume)) {
303 start_local_volume_timer();
304+ }
305 }
306
307 void set_mic_volume_success_cb (Context c, int success)
308@@ -689,7 +775,7 @@
309 }
310
311 /* AccountsService operations */
312- private void accountsservice_props_changed_cb (DBusProxy proxy, Variant changed_properties, string[] invalidated_properties)
313+ private void accountsservice_props_changed_cb (DBusProxy proxy, Variant changed_properties, string[]? invalidated_properties)
314 {
315 Variant volume_variant = changed_properties.lookup_value ("Volume", new VariantType ("d"));
316 if (volume_variant != null) {
317@@ -747,10 +833,14 @@
318
319 // Get current values and listen for changes
320 _user_proxy.g_properties_changed.connect (accountsservice_props_changed_cb);
321- 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);
322- Variant props;
323- props_variant.get ("(@a{sv})", out props);
324- accountsservice_props_changed_cb(_user_proxy, props, null);
325+ try {
326+ 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);
327+ Variant props;
328+ props_variant.get ("(@a{sv})", out props);
329+ accountsservice_props_changed_cb(_user_proxy, props, null);
330+ } catch (GLib.Error e) {
331+ debug("Unable to get properties for user %s at first try: %s", username, e.message);
332+ }
333 }
334
335 private void greeter_user_changed (string username)
336
337=== modified file 'tests/manual'
338--- tests/manual 2014-01-31 20:09:51 +0000
339+++ tests/manual 2014-11-05 16:48:46 +0000
340@@ -22,3 +22,102 @@
341 <dd>The menu is populated with items</dd>
342 </dl>
343
344+Test-case indicator-sound/unity8-sound-notifications
345+<dl>
346+ <dt>Adjust volume using HW keys if available</dt>
347+ <dd>A notification bubble should appear with the sound volume</dd>
348+ <dd>An audibule sound should play at the level of the audio</dd>
349+ <dt>Adjust volume with slider in sound indicator</dt>
350+ <dd>A notification bubble should appear with the sound volume</dd>
351+ <dd>An audibule sound should play at the level of the audio</dd>
352+ <dt>Open a video with sound and play in media player</dt>
353+ <dd>The video should play and the sound should be audible</dd>
354+ <dt>Adjust volume using HW keys if available</dt>
355+ <dd>A notification bubble should appear with the sound volume</dd>
356+ <dd>No notification sound should be heard</dd>
357+ <dt>Adjust volume with slider in sound indicator</dt>
358+ <dd>A notification bubble should appear with the sound volume</dd>
359+ <dd>No notification sound should be heard</dd>
360+</dl>
361+
362+Test-case indicator-sound/unity8-high-volume
363+<dl>
364+ <dt>Plug headphones into the headphone jack</dt>
365+ <dt>Adjust volume so that it is at the midpoint of volume range</dt>
366+ <dd>The slider should be in the middle of the scale</dd>
367+ <dt>Increase the volume once using HW keys if available</dt>
368+ <dd>A notification bubble should appear with the sound volume</dd>
369+ <dd>There should be no text on the notification</dd>
370+ <dt>Increase the volume using HW keys until it is roughly 90% of the range</dt>
371+ <dd>A notification bubble should appear with the sound volume</dd>
372+ <dd>The text on the notification should read "High volume"</dd>
373+ <dd>The range on the notification bubble should have a different color signifying the higher volume</dd>
374+ <dt>Decrease the volume using HW keys until it is roughly 50% of the range</dt>
375+ <dd>A notification bubble should appear with the sound volume</dd>
376+ <dd>There should be no text on the notification</dd>
377+ <dd>The range on the notification bubble should have a standard color</dd>
378+</dl>
379+
380+Test-case indicator-sound/unity8-silent-mode
381+<dl>
382+ <dt>NOTE: This test currently doesn't work because of a bug: http://pad.lv/1336715</dt>
383+ <dt>Open the Sound menu</dt>
384+ <dd>The sound menu includes an item "Silent Mode" which is a check box</dd>
385+ <dd>The checkbox is not checked</dd>
386+ <dt>Enable silent mode</dt>
387+ <dd>Selecting the "Silent Mode" item should cause the box to be checked</dd>
388+ <dt>Open the sound panel in system settings</dt>
389+ <dd>The sound panel includes an item "Silent Mode" which is a check box</dd>
390+ <dd>The checkbox is checked</dd>
391+ <dt>Disable silent mode in system settings</dt>
392+ <dd>The checkbox is not checked</dd>
393+ <dt>Open the Sound menu</dt>
394+ <dd>The sound menu includes an item "Silent Mode" which is a check box</dd>
395+ <dd>The checkbox is not checked</dd>
396+</dl>
397+
398+Test-case indicator-sound/unity8-audio-roles
399+<dl>
400+ <dt>Without playing anything (no active audio stream), change the volume on the indicator or with the volume buttons and then try playing one of the following audio streams: camera shutter, ringtone, message notification, dtmf</dt>
401+ <dd>The audio stream should reflect the volume set on the indicator</dd>
402+ <dt>Without playing anything (no active audio stream), change the volume on the indicator or with volume buttons and then try playing one of the following audio streams: music-app, webrowser (youtube)</dt>
403+ <dd>The audio stream should not be affected by the volume set on the indicator when there was no other active stream</dt>
404+ <dt>Play a multimedia stream (music-app, webrowser) and change the volume on the indicator when the stream is active</dt>
405+ <dd>The multimedia audio stream should reflect the volume set on the indicator</dd>
406+ <dd>When stopping/closing the multimedia stream, it should automatically show up the volume for the alert role (ringtone, notification, etc)</dd>
407+ <dd>No other role should be affected by the volume level used by the multimedia role</dd>
408+ <dt>Play a alarm stream (clock-app) and change the volume on the indicator when the stream is active</dt>
409+ <dd>The alarm audio stream should reflect the volume set on the indicator</dd>
410+ <dd>When stopping/closing the alarm stream, it should automatically show up the volume for the alert role (ringtone, notification, etc)</dd>
411+ <dd>No other role should be affected by the volume level used by the alarm role</dd>
412+ <dt>Start a voice call using the dialer-app and change the volume on the indicator when the call is active</dt>
413+ <dd>The phone audio stream should reflect the volume set on the indicator</dd>
414+ <dd>When hanging up the voice call it should automatically show up the volume for the alert role (ringtone, notification, etc)</dd>
415+ <dd>No other role should be affected by the volume level used by the phone role</dd>
416+</dl>
417+
418+Test-case indicator-sound/unity8-embedded-greeter
419+<dl>
420+ <dt>NOTE: Only works with embedded greeter, split greeter will require modifications to this test</dt>
421+ <dt>Ensure System Settings is set to "Show Messages on Greeter"</dt>
422+ <dt>Play a song in the media player</dt>
423+ <dd>The song should be heard</dd>
424+ <dd>There should be an entry in the sound menu with the meta data for the song being played</dd>
425+ <dt>Go to the greeter. This can be done by hitting the lock button twice.</dt>
426+ <dt>Ensure the sound menu has song meta data</dt>
427+ <dd>There should be an entry in the sound menu with the meta data for the song being played</dd>
428+ <dt>Pause the song in the greeter</dt>
429+ <dd>The song should stop playing</dd>
430+ <dt>Resume the song in the greeter</dt>
431+ <dd>The song should continue to play</dd>
432+ <dt>Disable System Settings value "Show Messages on Greeter"</dt>
433+ <dt>Ensure the sound menu has song meta data</dt>
434+ <dd>There should be an entry in the sound menu with the meta data for the song being played</dd>
435+ <dt>Go to the greeter. This can be done by hitting the lock button twice.</dt>
436+ <dt>Ensure the sound menu does not have song meta data</dt>
437+ <dd>There should be an entry for the player but it should have no information on the song being played</dd>
438+ <dt>Pause the song in the greeter</dt>
439+ <dd>The song should stop playing</dd>
440+ <dt>Resume the song in the greeter</dt>
441+ <dd>The song should continue to play</dd>
442+</dl>

Subscribers

People subscribed via source and target branches