aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/com.canonical.indicator.sound.gschema.xml15
-rw-r--r--src/service.vala18
-rw-r--r--src/sound-menu.vala33
-rw-r--r--src/volume-control-pulse.vala39
-rw-r--r--src/volume-control.vala2
-rw-r--r--tests/integration/indicator-sound-test-base.cpp33
-rw-r--r--tests/integration/indicator-sound-test-base.h4
-rw-r--r--tests/sound-menu.cc32
8 files changed, 127 insertions, 49 deletions
diff --git a/data/com.canonical.indicator.sound.gschema.xml b/data/com.canonical.indicator.sound.gschema.xml
index 8408883..06bfe74 100644
--- a/data/com.canonical.indicator.sound.gschema.xml
+++ b/data/com.canonical.indicator.sound.gschema.xml
@@ -59,10 +59,10 @@
<description>
How long to remember a user's approval of the confirmation dialog discussed in the
description of 'warning-volume-enabled'.
-
+
The default value (72,000 seconds) corresponds to the 20 hours suggested by
EU standard EN 60950-1/Al2: “The acknowledgement does not need to be repeated
- more than once every 20 h of cumulative listening time.”
+ more than once every 20 h of cumulative listening time.”
</description>
</key>
<key name="warning-volume-decibels" type="d">
@@ -102,16 +102,5 @@
</description>
</key>
- <key name="last-running-player" type="s">
- <default>""</default>
- <summary>Stores which was the last running music player.</summary>
- <description>
- To make the last running player persistent and be able to set its playback controls
- we store which was the last player running id.
-
- The default value ("") corresponds to no player.
- </description>
- </key>
-
</schema>
</schemalist>
diff --git a/src/service.vala b/src/service.vala
index cb30820..d55a3c8 100644
--- a/src/service.vala
+++ b/src/service.vala
@@ -91,12 +91,12 @@ public class IndicatorSound.Service: Object {
this.actions.add_action (this.create_high_volume_action ());
this.actions.add_action (this.create_volume_sync_action ());
- string last_player = this.settings.get_string ("last-running-player");
+ // OLD string last_player = this.settings.get_string ("last-running-player");
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 | SoundMenu.DisplayFlags.GREETER_PLAYERS, last_player));
- this.menus.insert ("phone_greeter", new SoundMenu (null, SoundMenu.DisplayFlags.SHOW_SILENT_MODE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS | SoundMenu.DisplayFlags.GREETER_PLAYERS, last_player));
- this.menus.insert ("desktop", new SoundMenu ("indicator.desktop-settings", SoundMenu.DisplayFlags.SHOW_MUTE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS_PLAY_CONTROLS | SoundMenu.DisplayFlags.ADD_PLAY_CONTROL_INACTIVE_PLAYER, last_player));
- this.menus.insert ("phone", new SoundMenu ("indicator.phone-settings", SoundMenu.DisplayFlags.SHOW_SILENT_MODE | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS, last_player));
+ 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 | SoundMenu.DisplayFlags.HIDE_INACTIVE_PLAYERS_PLAY_CONTROLS | SoundMenu.DisplayFlags.ADD_PLAY_CONTROL_INACTIVE_PLAYER));
+ 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);
@@ -112,7 +112,13 @@ public class IndicatorSound.Service: Object {
this.menus.@foreach ( (profile, menu) => {
menu.last_player_updated.connect ((player_id) => {
- this.settings.set_value ("last-running-player", player_id);
+ this.volume_control.last_running_player = player_id;
+ });
+ });
+
+ this.volume_control.notify["last-running-player"].connect(() => {
+ this.menus.@foreach ( (profile, menu) => {
+ menu.set_default_player (this.volume_control.last_running_player);
});
});
diff --git a/src/sound-menu.vala b/src/sound-menu.vala
index 630dca0..5aa94fe 100644
--- a/src/sound-menu.vala
+++ b/src/sound-menu.vala
@@ -38,7 +38,7 @@ public class SoundMenu: Object
const string PLAYBACK_ITEM_TYPE = "com.canonical.unity.playback-item";
- public SoundMenu (string? settings_action, DisplayFlags flags, string default_player_id) {
+ public SoundMenu (string? settings_action, DisplayFlags flags) {
/* A sound menu always has at least two sections: the volume section (this.volume_section)
* at the start of the menu, and the settings section at the end. Between those two,
* it has a dynamic amount of player sections, one for each registered player.
@@ -83,9 +83,6 @@ public class SoundMenu: Object
this.notify_handlers = new HashTable<MediaPlayer, ulong> (direct_hash, direct_equal);
this.greeter_players = (flags & DisplayFlags.GREETER_PLAYERS) != 0;
-
- this.default_player = default_player_id;
-
}
~SoundMenu () {
@@ -95,6 +92,16 @@ public class SoundMenu: Object
}
}
+ public void set_default_player (string default_player_id) {
+ this.default_player = default_player_id;
+ foreach (var player_stored in notify_handlers.get_keys ()) {
+ int index = this.find_player_section(player_stored);
+ if (index != -1 && player_stored.id == this.default_player) {
+ add_player_playback_controls (player_stored, index, true);
+ }
+ }
+ }
+
DBusConnection? bus = null;
uint export_id = 0;
@@ -368,16 +375,11 @@ public class SoundMenu: Object
this.menu.remove (index);
}
- void update_player_section (MediaPlayer player, int index) {
+ void add_player_playback_controls (MediaPlayer player, int index, bool adding_default_player) {
var player_section = this.menu.get_item_link(index, Menu.LINK_SECTION) as Menu;
int play_control_index = find_player_playback_controls_section (player_section);
- if (player.is_running && number_of_running_players == 1) {
- // this is the first or the last player running...
- // store its id
- this.last_player_updated (player.id);
- }
- if (player.is_running || !this.hide_inactive_player_controls) {
+ if (player.is_running || !this.hide_inactive_player_controls || (number_of_running_players == 0 && adding_default_player) ) {
MenuItem playback_item = create_playback_menu_item (player);
if (play_control_index != -1) {
player_section.remove (PlayerSectionPosition.PLAYER_CONTROLS);
@@ -389,7 +391,16 @@ public class SoundMenu: Object
player_section.remove (PlayerSectionPosition.PLAYLIST);
player_section.remove (PlayerSectionPosition.PLAYER_CONTROLS);
}
+ }
+ }
+
+ void update_player_section (MediaPlayer player, int index) {
+ if (player.is_running && number_of_running_players == 1) {
+ // this is the first or the last player running...
+ // store its id
+ this.last_player_updated (player.id);
}
+ add_player_playback_controls (player, index, false);
}
void update_playlists (MediaPlayer player) {
diff --git a/src/volume-control-pulse.vala b/src/volume-control-pulse.vala
index 6021447..cdc6953 100644
--- a/src/volume-control-pulse.vala
+++ b/src/volume-control-pulse.vala
@@ -59,15 +59,29 @@ public class VolumeControlPulse : VolumeControl
private GreeterListInterface _greeter_proxy;
private Cancellable _mute_cancellable;
private Cancellable _volume_cancellable;
+ private Cancellable _last_running_player_cancellable;
private uint _local_volume_timer = 0;
private uint _accountservice_volume_timer = 0;
private bool _send_next_local_volume = false;
private double _account_service_volume = 0.0;
private VolumeControl.ActiveOutput _active_output = VolumeControl.ActiveOutput.SPEAKERS;
+ private string _last_running_player = "";
/** true when a microphone is active **/
public override bool active_mic { get; private set; default = false; }
+ public override string last_running_player
+ {
+ get
+ {
+ return _last_running_player;
+ }
+ set
+ {
+ sync_last_running_player_to_accountsservice.begin (value);
+ }
+ }
+
public VolumeControlPulse (IndicatorSound.Options options, PulseAudio.GLibMainLoop loop)
{
base(options);
@@ -79,6 +93,7 @@ public class VolumeControlPulse : VolumeControl
_mute_cancellable = new Cancellable ();
_volume_cancellable = new Cancellable ();
+ _last_running_player_cancellable = new Cancellable();
setup_accountsservice.begin ();
@@ -790,6 +805,13 @@ public class VolumeControlPulse : VolumeControl
var mute = mute_variant.get_boolean ();
set_mute_internal (mute);
}
+
+ Variant last_running_player_variant = changed_properties.lookup_value ("LastRunningPlayer", VariantType.STRING);
+ if (last_running_player_variant != null) {
+ var last_player = last_running_player_variant.get_string ();
+ _last_running_player = last_player;
+ this.notify_property("last-running-player");
+ }
}
private async void setup_user_proxy (string? username_in = null)
@@ -881,6 +903,22 @@ public class VolumeControlPulse : VolumeControl
}
}
+ private async void sync_last_running_player_to_accountsservice (string last_running_player)
+ {
+ if (_user_proxy == null)
+ return;
+
+ _last_running_player_cancellable.cancel ();
+ _last_running_player_cancellable.reset ();
+
+ try {
+ 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 (), "LastRunningPlayer", new Variant ("s", last_running_player)), null, DBusCallFlags.NONE, -1, _last_running_player_cancellable);
+ } catch (GLib.Error e) {
+ warning ("unable to sync last running player to AccountsService: %s", e.message);
+ }
+ _last_running_player = last_running_player;
+ }
+
private async void sync_volume_to_accountsservice (VolumeControl.Volume volume)
{
if (_user_proxy == null)
@@ -889,6 +927,7 @@ public class VolumeControlPulse : VolumeControl
_volume_cancellable.cancel ();
_volume_cancellable.reset ();
+ warning("Interface name: %s", _user_proxy.get_interface_name ());
try {
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);
} catch (GLib.Error e) {
diff --git a/src/volume-control.vala b/src/volume-control.vala
index 3d02f70..137e7b6 100644
--- a/src/volume-control.vala
+++ b/src/volume-control.vala
@@ -84,4 +84,6 @@ public abstract class VolumeControl : Object
public abstract VolumeControl.ActiveOutput active_output();
public signal void active_output_changed (VolumeControl.ActiveOutput active_output);
+
+ public virtual string last_running_player { get { return ""; } set { } }
}
diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp
index f61857e..8242fb6 100644
--- a/tests/integration/indicator-sound-test-base.cpp
+++ b/tests/integration/indicator-sound-test-base.cpp
@@ -448,13 +448,40 @@ bool IndicatorSoundTestBase::initializeMenuChangedSignal()
return true;
}
-bool IndicatorSoundTestBase::waitVolumeChangedInIndicator()
+QVariant IndicatorSoundTestBase::waitPropertyChanged(QString property)
{
+ QVariant ret_val;
if (signal_spy_volume_changed_)
{
- return signal_spy_volume_changed_->wait();
+ signal_spy_volume_changed_->wait();
+ if (signal_spy_volume_changed_->count())
+ {
+ QList<QVariant> arguments = signal_spy_volume_changed_->takeFirst();
+ if (arguments.size() == 3 && static_cast<QMetaType::Type>(arguments.at(1).type()) == QMetaType::QVariantMap)
+ {
+ QVariantMap map = arguments.at(1).toMap();
+ QMapIterator<QString, QVariant> iter(map);
+ while (iter.hasNext()) {
+ iter.next();
+ if (iter.key() == property)
+ {
+ return iter.value();
+ }
+ }
+ }
+ }
}
- return false;
+ return ret_val;
+}
+bool IndicatorSoundTestBase::waitVolumeChangedInIndicator()
+{
+ QVariant val = waitPropertyChanged("Volume");
+ return !val.isNull();
+}
+
+QVariant IndicatorSoundTestBase::waitLastRunningPlayerChanged()
+{
+ return waitPropertyChanged("LastRunningPlayer");
}
void IndicatorSoundTestBase::initializeAccountsInterface()
diff --git a/tests/integration/indicator-sound-test-base.h b/tests/integration/indicator-sound-test-base.h
index 969fd69..ecdbd7d 100644
--- a/tests/integration/indicator-sound-test-base.h
+++ b/tests/integration/indicator-sound-test-base.h
@@ -144,6 +144,10 @@ protected:
float getVolumeValue(bool *isValid = nullptr);
+ QVariant waitPropertyChanged(QString property);
+
+ QVariant waitLastRunningPlayerChanged();
+
QtDBusTest::DBusTestRunner dbusTestRunner;
QtDBusMock::DBusMock dbusMock;
diff --git a/tests/sound-menu.cc b/tests/sound-menu.cc
index 2576d19..79ae703 100644
--- a/tests/sound-menu.cc
+++ b/tests/sound-menu.cc
@@ -62,7 +62,7 @@ class SoundMenuTest : public ::testing::Test
void check_player_control_buttons(bool canPlay, bool canNext, bool canPrev)
{
- SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE, "");
+ SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE);
MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url");
@@ -96,22 +96,22 @@ class SoundMenuTest : public ::testing::Test
/* Player control */
verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item"));
- //verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string(""));
- if (!canPlay) {
+ //verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string(""));
+ if (!canPlay) {
verify_item_attribute_is_not_set(section, 1, "x-canonical-play-action", G_VARIANT_TYPE_STRING);
- } else {
- verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id"));
- }
- if (!canNext) {
+ } else {
+ verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id"));
+ }
+ if (!canNext) {
verify_item_attribute_is_not_set(section, 1, "x-canonical-next-action", G_VARIANT_TYPE_STRING);
- } else {
- verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id"));
- }
- if (!canPrev) {
+ } else {
+ verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id"));
+ }
+ if (!canPrev) {
verify_item_attribute_is_not_set(section, 1, "x-canonical-previous-action", G_VARIANT_TYPE_STRING);
- } else {
- verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id"));
- }
+ } else {
+ verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id"));
+ }
g_clear_object(&section);
@@ -125,7 +125,7 @@ class SoundMenuTest : public ::testing::Test
};
TEST_F(SoundMenuTest, BasicObject) {
- SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE, "");
+ SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE);
ASSERT_NE(nullptr, menu);
@@ -134,7 +134,7 @@ TEST_F(SoundMenuTest, BasicObject) {
}
TEST_F(SoundMenuTest, AddRemovePlayer) {
- SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE, "");
+ SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE);
MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url");