diff options
-rw-r--r-- | data/com.canonical.indicator.sound.gschema.xml | 9 | ||||
-rw-r--r-- | debian/changelog | 29 | ||||
-rw-r--r-- | src/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/accounts-service-privacy-settings.vala | 26 | ||||
-rw-r--r-- | src/accounts-service-system-sound-settings.vala | 25 | ||||
-rw-r--r-- | src/accounts-service-user.vala | 74 | ||||
-rw-r--r-- | src/media-player-mpris.vala | 2 | ||||
-rw-r--r-- | src/service.vala | 96 | ||||
-rw-r--r-- | src/sound-menu.vala | 20 | ||||
-rw-r--r-- | src/volume-control.vala | 20 |
10 files changed, 258 insertions, 51 deletions
diff --git a/data/com.canonical.indicator.sound.gschema.xml b/data/com.canonical.indicator.sound.gschema.xml index c34dfd6..102a1db 100644 --- a/data/com.canonical.indicator.sound.gschema.xml +++ b/data/com.canonical.indicator.sound.gschema.xml @@ -48,14 +48,5 @@ Whether or not to show the sound indicator in the menu bar. </description> </key> - <key name="greeter-export" type="b"> - <default>true</default> - <summary>Whether or not to export the currently playing song to the greeter.</summary> - <description> - If enabled the sound indicator will export the current player and - song to the greeter so that it can be shown if the user is selected - and the sound menu is shown. - </description> - </key> </schema> </schemalist> diff --git a/debian/changelog b/debian/changelog index e472d77..79f21ea 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,32 @@ +indicator-sound (12.10.2+14.10.20141010-0ubuntu3) UNRELEASED; urgency=medium + + * Remove various Vala warnings + * Show notifications on volume change (LP: #1378564, #1378961) + + -- Ted Gould <ted@ubuntu.com> Wed, 05 Nov 2014 10:31:30 -0600 + +indicator-sound (12.10.2+14.10.20141010-0ubuntu1) utopic; urgency=low + + [ Ricardo Salveti de Araujo ] + * volume-control: making sure we're always in sync with accountservice + (LP: #1379618) + + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 10 Oct 2014 15:40:30 +0000 + +indicator-sound (12.10.2+14.10.20141009-0ubuntu1) utopic; urgency=low + + [ Ted Gould ] + * Show a silent mode checkbox (LP: #1342151) + + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 09 Oct 2014 13:32:54 +0000 + +indicator-sound (12.10.2+14.10.20141008-0ubuntu1) utopic; urgency=low + + [ Ted Gould ] + * Revert notifications on volume change. + + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 08 Oct 2014 18:55:06 +0000 + indicator-sound (12.10.2+14.10.20141007-0ubuntu1) utopic; urgency=low [ Ted Gould ] diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3cab736..c18726c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -104,12 +104,20 @@ vala_add(indicator-sound-service media-player mpris2-interfaces accounts-service-sound-settings + accounts-service-privacy-settings + accounts-service-system-sound-settings greeter-broadcast ) vala_add(indicator-sound-service accounts-service-sound-settings.vala ) vala_add(indicator-sound-service + accounts-service-privacy-settings.vala +) +vala_add(indicator-sound-service + accounts-service-system-sound-settings.vala +) +vala_add(indicator-sound-service greeter-broadcast.vala ) diff --git a/src/accounts-service-privacy-settings.vala b/src/accounts-service-privacy-settings.vala new file mode 100644 index 0000000..ef5c309 --- /dev/null +++ b/src/accounts-service-privacy-settings.vala @@ -0,0 +1,26 @@ +/* + * Copyright 2014 © Canonical Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Ted Gould <ted@canonical.com> + */ + +[DBus (name = "com.ubuntu.touch.AccountsService.SecurityPrivacy")] +public interface AccountsServicePrivacySettings : Object { + // properties + public abstract bool stats_welcome_screen {owned get; set;} + public abstract bool messages_welcome_screen {owned get; set;} +} + diff --git a/src/accounts-service-system-sound-settings.vala b/src/accounts-service-system-sound-settings.vala new file mode 100644 index 0000000..283a606 --- /dev/null +++ b/src/accounts-service-system-sound-settings.vala @@ -0,0 +1,25 @@ +/* + * Copyright 2014 © Canonical Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Ted Gould <ted@canonical.com> + */ + +[DBus (name = "com.ubuntu.touch.AccountsService.Sound")] +public interface AccountsServiceSystemSoundSettings : Object { + // properties + public abstract bool silent_mode {owned get; set;} +} + diff --git a/src/accounts-service-user.vala b/src/accounts-service-user.vala index 04c38cc..ec52730 100644 --- a/src/accounts-service-user.vala +++ b/src/accounts-service-user.vala @@ -21,10 +21,25 @@ public class AccountsServiceUser : Object { Act.UserManager accounts_manager = Act.UserManager.get_default(); Act.User? user = null; AccountsServiceSoundSettings? proxy = null; + AccountsServicePrivacySettings? privacyproxy = null; + AccountsServiceSystemSoundSettings? syssoundproxy = null; uint timer = 0; MediaPlayer? _player = null; GreeterBroadcast? greeter = null; + public bool showDataOnGreeter { get; set; } + + bool _silentMode = false; + public bool silentMode { + get { + return _silentMode; + } + set { + if (syssoundproxy != null) + syssoundproxy.silent_mode = value; + } + } + public MediaPlayer? player { set { this._player = value; @@ -124,7 +139,23 @@ public class AccountsServiceUser : Object { user.get_object_path(), DBusProxyFlags.GET_INVALIDATED_PROPERTIES, null, - new_proxy); + new_sound_proxy); + + Bus.get_proxy.begin<AccountsServicePrivacySettings> ( + BusType.SYSTEM, + "org.freedesktop.Accounts", + user.get_object_path(), + DBusProxyFlags.GET_INVALIDATED_PROPERTIES, + null, + new_privacy_proxy); + + Bus.get_proxy.begin<AccountsServiceSystemSoundSettings> ( + BusType.SYSTEM, + "org.freedesktop.Accounts", + user.get_object_path(), + DBusProxyFlags.GET_INVALIDATED_PROPERTIES, + null, + new_system_sound_proxy); } } @@ -138,7 +169,7 @@ public class AccountsServiceUser : Object { } } - void new_proxy (GLib.Object? obj, AsyncResult res) { + void new_sound_proxy (GLib.Object? obj, AsyncResult res) { try { this.proxy = Bus.get_proxy.end (res); this.player = _player; @@ -148,6 +179,45 @@ public class AccountsServiceUser : Object { } } + void new_privacy_proxy (GLib.Object? obj, AsyncResult res) { + try { + this.privacyproxy = Bus.get_proxy.end (res); + + (this.privacyproxy as DBusProxy).g_properties_changed.connect((proxy, changed, invalid) => { + var welcomeval = changed.lookup_value("MessagesWelcomeScreen", new VariantType("b")); + if (welcomeval != null) { + debug("Messages on welcome screen changed"); + this.showDataOnGreeter = welcomeval.get_boolean(); + } + }); + + this.showDataOnGreeter = this.privacyproxy.messages_welcome_screen; + } catch (Error e) { + this.privacyproxy = null; + warning("Unable to get proxy to user privacy settings: %s", e.message); + } + } + + void new_system_sound_proxy (GLib.Object? obj, AsyncResult res) { + try { + this.syssoundproxy = Bus.get_proxy.end (res); + + (this.syssoundproxy as DBusProxy).g_properties_changed.connect((proxy, changed, invalid) => { + var silentvar = changed.lookup_value("SilentMode", new VariantType("b")); + if (silentvar != null) { + debug("Silent Mode changed"); + this._silentMode = silentvar.get_boolean(); + this.notify_property("silentMode"); + } + }); + + this.silentMode = this.syssoundproxy.silent_mode; + } catch (Error e) { + this.syssoundproxy = null; + warning("Unable to get proxy to system sound settings: %s", e.message); + } + } + void greeter_proxy_new (GLib.Object? obj, AsyncResult res) { try { this.greeter = Bus.get_proxy.end (res); diff --git a/src/media-player-mpris.vala b/src/media-player-mpris.vala index 25ddac4..bf25e21 100644 --- a/src/media-player-mpris.vala +++ b/src/media-player-mpris.vala @@ -283,7 +283,7 @@ public class MediaPlayerMpris: MediaPlayer { this.fetch_playlists (); } - void update_current_track (Variant metadata) { + void update_current_track (Variant? metadata) { if (metadata != null) { this.current_track = new Track ( sanitize_metadata_value (metadata.lookup_value ("xesam:artist", null)), diff --git a/src/service.vala b/src/service.vala index 4e02769..4298ad7 100644 --- a/src/service.vala +++ b/src/service.vala @@ -27,30 +27,39 @@ public class IndicatorSound.Service: Object { this.volume_control = new VolumeControl (); + /* If we're on the greeter, don't export */ + if (GLib.Environment.get_user_name() != "lightdm") { + this.accounts_service = new AccountsServiceUser(); + + this.accounts_service.notify["showDataOnGreeter"].connect(() => { + this.export_to_accounts_service = this.accounts_service.showDataOnGreeter; + eventually_update_player_actions(); + }); + + this.export_to_accounts_service = this.accounts_service.showDataOnGreeter; + } + this.players = playerlist; this.players.player_added.connect (this.player_added); this.players.player_removed.connect (this.player_removed); this.actions = new SimpleActionGroup (); this.actions.add_action_entries (action_entries, this); + this.actions.add_action (this.create_silent_mode_action ()); this.actions.add_action (this.create_mute_action ()); this.actions.add_action (this.create_volume_action ()); this.actions.add_action (this.create_mic_volume_action ()); this.menus = new HashTable<string, SoundMenu> (str_hash, str_equal); - this.menus.insert ("desktop_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_PLAYERS)); - this.menus.insert ("phone_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS)); + this.menus.insert ("desktop_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS)); + this.menus.insert ("phone_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_SILENT_MODE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS)); this.menus.insert ("desktop", new SoundMenu ("indicator.desktop-settings", SoundMenu.DisplayFlags.SHOW_MUTE)); - this.menus.insert ("phone", new SoundMenu ("indicator.phone-settings", SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS)); + this.menus.insert ("phone", new SoundMenu ("indicator.phone-settings", SoundMenu.DisplayFlags.SHOW_SILENT_MODE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS)); this.menus.@foreach ( (profile, menu) => { this.volume_control.bind_property ("active-mic", menu, "show-mic-volume", BindingFlags.SYNC_CREATE); }); - /* Setup handling for the greeter-export setting */ - this.settings.changed["greeter-export"].connect( () => this.build_accountsservice() ); - build_accountsservice(); - this.sync_preferred_players (); this.settings.changed["interested-media-players"].connect ( () => { this.sync_preferred_players (); @@ -60,7 +69,7 @@ public class IndicatorSound.Service: Object { List<string> caps = Notify.get_server_caps (); if (caps.find_custom ("x-canonical-private-synchronous", strcmp) != null) { this.notification = new Notify.Notification ("indicator-sound", "", ""); - this.notification.set_hint_string ("x-canonical-private-synchronous", "indicator-sound"); + this.notification.set_hint ("x-canonical-private-synchronous", "indicator-sound"); } } @@ -74,25 +83,8 @@ public class IndicatorSound.Service: Object { } } - void build_accountsservice () { - clear_acts_player(); - this.accounts_service = null; - - /* If we're not exporting, don't build anything */ - if (!this.settings.get_boolean("greeter-export")) { - debug("Accounts service export disabled due to user setting"); - return; - } - - /* If we're on the greeter, don't export */ - if (GLib.Environment.get_user_name() == "lightdm") { - debug("Accounts service export disabled due to being used on the greeter"); - return; - } - - this.accounts_service = new AccountsServiceUser(); - - this.eventually_update_player_actions(); + bool greeter_show_track () { + return export_to_accounts_service; } void clear_acts_player () { @@ -167,6 +159,7 @@ public class IndicatorSound.Service: Object { Notify.Notification notification; bool syncing_preferred_players = false; AccountsServiceUser? accounts_service = null; + bool export_to_accounts_service = false; /* Maximum volume as a scaling factor between the volume action's state and the value in * this.volume_control. See create_volume_action(). @@ -193,7 +186,7 @@ public class IndicatorSound.Service: Object { icon = "notification-audio-volume-high"; this.notification.update ("indicator-sound", "", icon); - this.notification.set_hint_int32 ("value", ((int32) (100 * v / this.max_volume)).clamp (-1, 101)); + this.notification.set_hint ("value", ((int32) (100 * v / this.max_volume)).clamp (-1, 101)); try { this.notification.show (); } @@ -265,6 +258,36 @@ public class IndicatorSound.Service: Object { root_action.set_state (builder.end()); } + Action create_silent_mode_action () { + bool silentNow = false; + if (this.accounts_service != null) { + silentNow = this.accounts_service.silentMode; + } + + var silent_action = new SimpleAction.stateful ("silent-mode", null, new Variant.boolean (silentNow)); + + /* If we're not dealing with accounts service, we'll just always be out + of silent mode and that's cool. */ + if (this.accounts_service == null) { + return silent_action; + } + + this.accounts_service.notify["silentMode"].connect(() => { + silent_action.set_state(new Variant.boolean(this.accounts_service.silentMode)); + this.update_root_icon (); + }); + + silent_action.activate.connect ((action, param) => { + action.change_state (new Variant.boolean (!action.get_state().get_boolean())); + }); + + silent_action.change_state.connect ((action, val) => { + this.accounts_service.silentMode = val.get_boolean(); + }); + + return silent_action; + } + Action create_mute_action () { var mute_action = new SimpleAction.stateful ("mute", null, new Variant.boolean (this.volume_control.mute)); @@ -379,11 +402,11 @@ public class IndicatorSound.Service: Object { this.loop.quit (); } - Variant action_state_for_player (MediaPlayer player) { + Variant action_state_for_player (MediaPlayer player, bool show_track = true) { var builder = new VariantBuilder (new VariantType ("a{sv}")); builder.add ("{sv}", "running", new Variant ("b", player.is_running)); builder.add ("{sv}", "state", new Variant ("s", player.state)); - if (player.current_track != null) { + if (player.current_track != null && show_track) { builder.add ("{sv}", "title", new Variant ("s", player.current_track.title)); builder.add ("{sv}", "artist", new Variant ("s", player.current_track.artist)); builder.add ("{sv}", "album", new Variant ("s", player.current_track.album)); @@ -402,8 +425,14 @@ public class IndicatorSound.Service: Object { action.set_enabled (player.can_raise); } + SimpleAction? greeter_action = this.actions.lookup_action (player.id + ".greeter") as SimpleAction; + if (greeter_action != null) { + greeter_action.set_state (this.action_state_for_player (player, greeter_show_track())); + greeter_action.set_enabled (player.can_raise); + } + /* If we're playing then put that data in accounts service */ - if (player.is_running && accounts_service != null) { + if (player.is_running && export_to_accounts_service && accounts_service != null) { accounts_service.player = player; clear_accounts_player = false; } @@ -446,6 +475,11 @@ public class IndicatorSound.Service: Object { action.activate.connect ( () => { player.activate (); }); this.actions.add_action (action); + SimpleAction greeter_action = new SimpleAction.stateful (player.id + ".greeter", null, this.action_state_for_player (player, greeter_show_track())); + greeter_action.set_enabled (player.can_raise); + greeter_action.activate.connect ( () => { player.activate (); }); + this.actions.add_action (greeter_action); + var play_action = new SimpleAction.stateful ("play." + player.id, null, player.state); play_action.activate.connect ( () => player.play_pause () ); this.actions.add_action (play_action); diff --git a/src/sound-menu.vala b/src/sound-menu.vala index 03faa89..f245a1f 100644 --- a/src/sound-menu.vala +++ b/src/sound-menu.vala @@ -23,7 +23,9 @@ public class SoundMenu: Object NONE = 0, SHOW_MUTE = 1, HIDE_INACTIVE_PLAYERS = 2, - HIDE_PLAYERS = 4 + HIDE_PLAYERS = 4, + GREETER_PLAYERS = 8, + SHOW_SILENT_MODE = 16 } public SoundMenu (string? settings_action, DisplayFlags flags) { @@ -33,8 +35,15 @@ public class SoundMenu: Object */ this.volume_section = new Menu (); + if ((flags & DisplayFlags.SHOW_MUTE) != 0) volume_section.append (_("Mute"), "indicator.mute"); + if ((flags & DisplayFlags.SHOW_SILENT_MODE) != 0) { + var item = new MenuItem(_("Silent Mode"), "indicator.silent-mode"); + item.set_attribute("x-canonical-type", "s", "com.canonical.indicator.switch"); + volume_section.append_item(item); + } + volume_section.append_item (this.create_slider_menu_item (_("Volume"), "indicator.volume(0)", 0.0, 1.0, 0.01, "audio-volume-low-zero-panel", "audio-volume-high-panel")); @@ -59,6 +68,8 @@ public class SoundMenu: Object this.hide_players = (flags & DisplayFlags.HIDE_PLAYERS) != 0; this.hide_inactive = (flags & DisplayFlags.HIDE_INACTIVE_PLAYERS) != 0; this.notify_handlers = new HashTable<MediaPlayer, ulong> (direct_hash, direct_equal); + + this.greeter_players = (flags & DisplayFlags.GREETER_PLAYERS) != 0; } public void export (DBusConnection connection, string object_path) { @@ -133,6 +144,7 @@ public class SoundMenu: Object bool hide_inactive; bool hide_players = false; HashTable<MediaPlayer, ulong> notify_handlers; + bool greeter_players = false; /* returns the position in this.menu of the section that's associated with @player */ int find_player_section (MediaPlayer player) { @@ -166,7 +178,11 @@ public class SoundMenu: Object if (icon == null) icon = new ThemedIcon.with_default_fallbacks ("application-default-icon"); - var player_item = new MenuItem (player.name, "indicator." + player.id); + var base_action = "indicator." + player.id; + if (this.greeter_players) + base_action += ".greeter"; + + var player_item = new MenuItem (player.name, base_action); player_item.set_attribute ("x-canonical-type", "s", "com.canonical.unity.media-player"); if (icon != null) player_item.set_attribute_value ("icon", icon.serialize ()); diff --git a/src/volume-control.vala b/src/volume-control.vala index 0541397..dd1128c 100644 --- a/src/volume-control.vala +++ b/src/volume-control.vala @@ -179,6 +179,7 @@ public class VolumeControl : Object { _volume = volume_to_double (i.volume.max ()); volume_changed (_volume); + start_local_volume_timer(); } } @@ -247,6 +248,7 @@ public class VolumeControl : Object /* Someone else changed the volume for this role, reflect on the indicator */ _volume = volume_to_double (volume); volume_changed (_volume); + start_local_volume_timer(); } } } @@ -289,6 +291,7 @@ public class VolumeControl : Object _volume = volume_to_double (volume); volume_changed (_volume); + start_local_volume_timer(); } catch (GLib.Error e) { warning ("unable to get volume for active role %s (%s)", sink_input_objp, e.message); } @@ -561,7 +564,8 @@ public class VolumeControl : Object bool set_volume_internal (double volume) { - return_val_if_fail (context.get_state () == Context.State.READY, false); + if (context.get_state () != Context.State.READY) + return false; if (_volume != volume) { _volume = volume; @@ -720,7 +724,7 @@ public class VolumeControl : Object } /* AccountsService operations */ - private void accountsservice_props_changed_cb (DBusProxy proxy, Variant changed_properties, string[] invalidated_properties) + private void accountsservice_props_changed_cb (DBusProxy proxy, Variant changed_properties, string[]? invalidated_properties) { Variant volume_variant = changed_properties.lookup_value ("Volume", new VariantType ("d")); if (volume_variant != null) { @@ -778,10 +782,14 @@ public class VolumeControl : Object // Get current values and listen for changes _user_proxy.g_properties_changed.connect (accountsservice_props_changed_cb); - 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); - Variant props; - props_variant.get ("(@a{sv})", out props); - accountsservice_props_changed_cb(_user_proxy, props, null); + try { + 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); + Variant props; + props_variant.get ("(@a{sv})", out props); + accountsservice_props_changed_cb(_user_proxy, props, null); + } catch (GLib.Error e) { + debug("Unable to get properties for user %s at first try: %s", username, e.message); + } } private void greeter_user_changed (string username) |