Merge lp:~ted/indicator-sound/extreme-volume-warning into lp:indicator-sound/14.10

Proposed by Ted Gould
Status: Superseded
Proposed branch: lp:~ted/indicator-sound/extreme-volume-warning
Merge into: lp:indicator-sound/14.10
Prerequisite: lp:~ted/indicator-sound/synchronous-notification
Diff against target: 263 lines (+139/-15)
4 files modified
src/service.vala (+16/-0)
src/sound-menu.vala (+39/-1)
src/volume-control.vala (+66/-14)
tests/manual (+18/-0)
To merge this branch: bzr merge lp:~ted/indicator-sound/extreme-volume-warning
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+238168@code.launchpad.net

This proposal has been superseded by a proposal from 2014-10-31.

Commit message

Warn on high audio levels when using headphones

Description of the change

Both a notification change and a menu item for showing that there is high volume.

To post a comment you must log in.
Revision history for this message
Mirco Müller (macslow) wrote :

Ted, I think you can drop this branch. For fixing LP: #1373404 I've the more fitting solution with a patch to lp:unity-settings-daemon, which is the one process triggering volume-notifications upon hardware multi-media-keys already.

My branch lp:~macslow/unity-settings-daemon/max-volume-notification-warning does also fully comply with the dedicated design for the hig-volume-warning.

Revision history for this message
Mirco Müller (macslow) wrote :

Ignore my last comment. I've thought I was clever, but wasn't really :/ I'll take a look at your branch with my new sync.-notification-support in unity8's notification backend/frontend.

Revision history for this message
Ricardo Salveti (rsalveti) wrote :

One easy way to find out if the active port is a headphone/headset:
http://paste.ubuntu.com/8556022/

Revision history for this message
Michał Sawicz (saviq) wrote :

FYI, testing in rtm silo 6 yielded a few issues:
- sound played only once (I know Mirco explains this somewhere)
- I still had the sound when playing music, which got paused
- when the notification disappeared, the first subsequent volume button press resulted in an incorrect level notification displayed
- notification displayed and sound played when changing volume through the indicator menu slider
- no warning text displayed, just the bar went orange (when playing music with headphones plugged in)

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

New to this patch, indicator-sound is calling /org/freedesktop/Notifications's Notify() method on startup with an "audio-volume-muted" string. This appears to be a side-effect of constructing indicator-sound, as it shows muted regardless of whether sound is actually muted.

This is consistently reproducible by running "restart indicator-sound" from the shell after installing this patch.

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

NVM that last, I see ted's already got lars' fix for that queued into 15.04 in https://code.launchpad.net/~ted/indicator-sound/lp1381871-no-initial-value-for-utopic

WTF, in testing the only issue I found was bug #1389008, which interfered with testing but doesn't seem to be new to this patch.

review: Approve

Unmerged revisions

485. By Ted Gould

Make sure to check the item in the loop

484. By Ted Gould

Removing the remove code that was supposed to be removed earlier

483. By Ted Gould

Commenting out the sound for now

482. By Ted Gould

Make volume icons match the panel icons

481. By Ted Gould

Found other notification

480. By Ted Gould

Remove volume text from manual test

479. By Ted Gould

Get propery property name

478. By Ted Gould

Check more precisely the valid roles

477. By Mirco Müller <email address hidden>

Make High-volume text work correctly

476. By Ted Gould

Merge trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/service.vala'
--- src/service.vala 2014-10-03 14:27:38 +0000
+++ src/service.vala 2014-10-15 18:52:57 +0000
@@ -49,6 +49,7 @@
49 this.actions.add_action (this.create_mute_action ());49 this.actions.add_action (this.create_mute_action ());
50 this.actions.add_action (this.create_volume_action ());50 this.actions.add_action (this.create_volume_action ());
51 this.actions.add_action (this.create_mic_volume_action ());51 this.actions.add_action (this.create_mic_volume_action ());
52 this.actions.add_action (this.create_high_volume_actions ());
5253
53 this.menus = new HashTable<string, SoundMenu> (str_hash, str_equal);54 this.menus = new HashTable<string, SoundMenu> (str_hash, str_equal);
54 this.menus.insert ("desktop_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS));55 this.menus.insert ("desktop_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS));
@@ -60,6 +61,10 @@
60 this.volume_control.bind_property ("active-mic", menu, "show-mic-volume", BindingFlags.SYNC_CREATE);61 this.volume_control.bind_property ("active-mic", menu, "show-mic-volume", BindingFlags.SYNC_CREATE);
61 });62 });
6263
64 this.menus.@foreach ( (profile, menu) => {
65 this.volume_control.bind_property ("high-volume", menu, "show-high-volume-warning", BindingFlags.SYNC_CREATE);
66 });
67
63 this.sync_preferred_players ();68 this.sync_preferred_players ();
64 this.settings.changed["interested-media-players"].connect ( () => {69 this.settings.changed["interested-media-players"].connect ( () => {
65 this.sync_preferred_players ();70 this.sync_preferred_players ();
@@ -174,6 +179,8 @@
174 double v = this.volume_control.get_volume () + volume_step_percentage * delta;179 double v = this.volume_control.get_volume () + volume_step_percentage * delta;
175 this.volume_control.set_volume (v.clamp (0.0, this.max_volume));180 this.volume_control.set_volume (v.clamp (0.0, this.max_volume));
176181
182 /* TODO: Don't want to mess up the desktop today, but we should remove this
183 scrolling change and merge that into volume control's notification */
177 if (this.notification != null) {184 if (this.notification != null) {
178 string icon;185 string icon;
179 if (v <= 0.0)186 if (v <= 0.0)
@@ -388,6 +395,15 @@
388 return volume_action;395 return volume_action;
389 }396 }
390397
398 Action create_high_volume_actions () {
399 var high_volume_action = new SimpleAction.stateful("high-volume", null, new Variant.boolean (this.volume_control.high_volume));
400
401 this.volume_control.notify["high-volume"].connect( () =>
402 high_volume_action.set_state(new Variant.boolean (this.volume_control.high_volume)));
403
404 return high_volume_action;
405 }
406
391 void bus_acquired (DBusConnection connection, string name) {407 void bus_acquired (DBusConnection connection, string name) {
392 try {408 try {
393 connection.export_action_group ("/com/canonical/indicator/sound", this.actions);409 connection.export_action_group ("/com/canonical/indicator/sound", this.actions);
394410
=== modified file 'src/sound-menu.vala'
--- src/sound-menu.vala 2014-10-08 01:57:56 +0000
+++ src/sound-menu.vala 2014-10-15 18:52:57 +0000
@@ -93,12 +93,49 @@
93 this.mic_volume_shown = true;93 this.mic_volume_shown = true;
94 }94 }
95 else if (!value && this.mic_volume_shown) {95 else if (!value && this.mic_volume_shown) {
96 this.volume_section.remove (this.volume_section.get_n_items () -1);96 int location = -1;
97 while ((location = find_action(this.volume_section, "indicator.mic-volume")) != -1) {
98 this.volume_section.remove (location);
99 }
97 this.mic_volume_shown = false;100 this.mic_volume_shown = false;
98 }101 }
99 }102 }
100 }103 }
101104
105 public bool show_high_volume_warning {
106 get {
107 return this.high_volume_warning_shown;
108 }
109 set {
110 if (value && !this.high_volume_warning_shown) {
111 /* NOTE: Action doesn't really exist, just used to find below when removing */
112 var item = new MenuItem(_("High volume can damage your hearing."), "indicator.high-volume-warning-item");
113 volume_section.append_item (item);
114 this.high_volume_warning_shown = true;
115 }
116 else if (!value && this.high_volume_warning_shown) {
117 int location = -1;
118 while ((location = find_action(this.volume_section, "indicator.high-volume-warning-item")) != -1) {
119 this.volume_section.remove (location);
120 }
121 this.high_volume_warning_shown = false;
122 }
123 }
124 }
125
126 int find_action (Menu menu, string in_action) {
127 int n = menu.get_n_items ();
128 for (int i = 0; i < n; i++) {
129 string action;
130 menu.get_item_attribute (i, "action", "s", out action);
131 if (in_action == action)
132 return i;
133 }
134
135 return -1;
136 }
137
138
102 public void add_player (MediaPlayer player) {139 public void add_player (MediaPlayer player) {
103 if (this.notify_handlers.contains (player))140 if (this.notify_handlers.contains (player))
104 return;141 return;
@@ -141,6 +178,7 @@
141 Menu volume_section;178 Menu volume_section;
142 bool mic_volume_shown;179 bool mic_volume_shown;
143 bool settings_shown = false;180 bool settings_shown = false;
181 bool high_volume_warning_shown = false;
144 bool hide_inactive;182 bool hide_inactive;
145 bool hide_players = false;183 bool hide_players = false;
146 HashTable<MediaPlayer, ulong> notify_handlers;184 HashTable<MediaPlayer, ulong> notify_handlers;
147185
=== modified file 'src/volume-control.vala'
--- src/volume-control.vala 2014-10-15 18:52:57 +0000
+++ src/volume-control.vala 2014-10-15 18:52:57 +0000
@@ -70,6 +70,8 @@
70 private double _account_service_volume = 0.0;70 private double _account_service_volume = 0.0;
71 private Notify.Notification _notification;71 private Notify.Notification _notification;
7272
73 private bool _active_port_headphone = false;
74
73 public signal void volume_changed (double v);75 public signal void volume_changed (double v);
74 public signal void mic_volume_changed (double v);76 public signal void mic_volume_changed (double v);
7577
@@ -79,6 +81,9 @@
79 /** true when a microphone is active **/81 /** true when a microphone is active **/
80 public bool active_mic { get; private set; default = false; }82 public bool active_mic { get; private set; default = false; }
8183
84 /** true when high volume warnings should be shown */
85 public bool high_volume { get; set; }
86
82 public VolumeControl ()87 public VolumeControl ()
83 {88 {
84 if (loop == null)89 if (loop == null)
@@ -158,6 +163,8 @@
158163
159 private void sink_info_cb_for_props (Context c, SinkInfo? i, int eol)164 private void sink_info_cb_for_props (Context c, SinkInfo? i, int eol)
160 {165 {
166 bool old_active_port_headphone = this._active_port_headphone;
167
161 if (i == null)168 if (i == null)
162 return;169 return;
163170
@@ -174,12 +181,27 @@
174 this.notify_property ("is-playing");181 this.notify_property ("is-playing");
175 }182 }
176183
184 /* Check if the current active port is headset/headphone */
185 /* There is not easy way to check if the port is a headset/headphone besides
186 * checking for the port name. On touch (with the pulseaudio droid element)
187 * the headset/headphone port is called 'output-headset' and 'output-headphone'.
188 * On the desktop this is usually called 'analog-output-headphones' */
189 if (i.active_port.name == "output-wired_headset" ||
190 i.active_port.name == "output-wired_headphone" ||
191 i.active_port.name == "analog-output-headphones") {
192 _active_port_headphone = true;
193 } else {
194 _active_port_headphone = false;
195 }
196
177 if (_pulse_use_stream_restore == false &&197 if (_pulse_use_stream_restore == false &&
178 _volume != volume_to_double (i.volume.max ()))198 _volume != volume_to_double (i.volume.max ()))
179 {199 {
180 _volume = volume_to_double (i.volume.max ());200 _volume = volume_to_double (i.volume.max ());
181 volume_changed (_volume);201 volume_changed (_volume);
182 start_local_volume_timer();202 start_local_volume_timer();
203 } else if (this._active_port_headphone != old_active_port_headphone) {
204 volume_changed (_volume);
183 }205 }
184 }206 }
185207
@@ -583,22 +605,52 @@
583 {605 {
584 /* Using this to detect whether we're on the phone or not */606 /* Using this to detect whether we're on the phone or not */
585 if (_pulse_use_stream_restore) {607 if (_pulse_use_stream_restore) {
586 if (volume == 0.0)608 /* Watch for extreme */
587 _notification.update (_("Volume"), "", "audio-volume-muted");609 if (volume > 0.75 && _active_port_headphone)
588 if (volume > 0.0 && volume <= 0.33)610 high_volume = true;
589 _notification.update (_("Volume"), "", "audio-volume-low");611 else
590 if (volume > 0.33 && volume <= 0.66)612 high_volume = false;
591 _notification.update (_("Volume"), "", "audio-volume-medium");613
592 if (volume > 0.66 && volume <= 1.0)614 /* Determine Label */
593 _notification.update (_("Volume"), "", "audio-volume-high");615 string volume_label = "";
616 if (high_volume)
617 volume_label = _("High volume");
618
619 /* Choose an icon */
620 string icon = "audio-volume-muted";
621 if (volume <= 0.0)
622 icon = "audio-volume-muted";
623 else if (volume <= 0.3)
624 icon = "audio-volume-low";
625 else if (volume <= 0.7)
626 icon = "audio-volume-medium";
627 else
628 icon = "audio-volume-high";
629
630 /* Choose a sound */
631 string? sound = null;
632 if (!((_active_sink_input >= 0) && (_active_sink_input < _valid_roles.length)
633 && (_valid_roles[_active_sink_input] == "multimedia")))
634 sound = "/usr/share/sounds/ubuntu/stereo/message.ogg";
635
636 /* Check tint */
637 string tint = "false";
638 if (high_volume)
639 tint = "true";
640
641 /* Put it all into the notification */
642 _notification.clear_hints ();
643 _notification.update (_("Volume"), volume_label, icon);
594 _notification.set_hint ("value", (int32)(volume * 100.0));644 _notification.set_hint ("value", (int32)(volume * 100.0));
595 if (_active_sink_input == -1 || _valid_roles[_active_sink_input] != "multimedia") {645 /* TODO: Removing sound until we can get all the roles cleaned up for
596 /* No audio ping if we're playing multimedia */646 when to play it. We expect this to come back, but in another landing.
597 _notification.set_hint ("sound-file", "/usr/share/sounds/ubuntu/stereo/message.ogg");647 _notification.set_hint ("sound-file", sound);
598 } else {648 */
599 _notification.set_hint ("sound-file", null);649 _notification.set_hint ("x-canonical-value-bar-tint", tint);
600 }650 _notification.set_hint ("x-canonical-private-synchronous", "true");
651 _notification.set_hint ("x-canonical-non-shaped-icon", "true");
601652
653 /* Show it */
602 try {654 try {
603 _notification.show (); 655 _notification.show ();
604 } catch (GLib.Error e) {656 } catch (GLib.Error e) {
605657
=== modified file 'tests/manual'
--- tests/manual 2014-10-15 18:52:57 +0000
+++ tests/manual 2014-10-15 18:52:57 +0000
@@ -39,3 +39,21 @@
39 <dd>A notification bubble should appear with the sound volume</dd>39 <dd>A notification bubble should appear with the sound volume</dd>
40 <dd>No notification sound should be heard</dd>40 <dd>No notification sound should be heard</dd>
41</dl>41</dl>
42
43Test-case indicator-sound/unity8-high-volume
44<dl>
45 <dt>Plug headphones into the headphone jack</dt>
46 <dt>Adjust volume so that it is at the midpoint of volume range</dt>
47 <dd>The slider should be in the middle of the scale</dd>
48 <dt>Increase the volume once using HW keys if available</dt>
49 <dd>A notification bubble should appear with the sound volume</dd>
50 <dd>There should be no text on the notification</dd>
51 <dt>Increase the volume using HW keys until it is roughly 90% of the range</dt>
52 <dd>A notification bubble should appear with the sound volume</dd>
53 <dd>The text on the notification should read "High volume"</dd>
54 <dd>The range on the notification bubble should have a different color signifying the higher volume</dd>
55 <dt>Decrease the volume using HW keys until it is roughly 50% of the range</dt>
56 <dd>A notification bubble should appear with the sound volume</dd>
57 <dd>There should be no text on the notification</dd>
58 <dd>The range on the notification bubble should have a standard color</dd>
59</dl>

Subscribers

People subscribed via source and target branches