aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/com.canonical.indicator.sound.gschema.xml11
-rw-r--r--src/service.vala15
-rw-r--r--src/sound-menu.vala107
-rw-r--r--tests/integration/indicator-sound-test-base.cpp43
-rw-r--r--tests/integration/indicator-sound-test-base.h9
-rw-r--r--tests/integration/test-indicator.cpp569
-rw-r--r--tests/service-mocks/media-player-mpris-mock/applications/testplayer2.desktop21
-rw-r--r--tests/service-mocks/media-player-mpris-mock/applications/testplayer3.desktop21
-rw-r--r--tests/sound-menu.cc25
9 files changed, 776 insertions, 45 deletions
diff --git a/data/com.canonical.indicator.sound.gschema.xml b/data/com.canonical.indicator.sound.gschema.xml
index b2ee856..8408883 100644
--- a/data/com.canonical.indicator.sound.gschema.xml
+++ b/data/com.canonical.indicator.sound.gschema.xml
@@ -102,5 +102,16 @@
</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 29b8670..cb30820 100644
--- a/src/service.vala
+++ b/src/service.vala
@@ -91,11 +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");
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));
- 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.SHOW_SILENT_MODE | 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, 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.@foreach ( (profile, menu) => {
this.volume_control.bind_property ("active-mic", menu, "show-mic-volume", BindingFlags.SYNC_CREATE);
@@ -109,6 +110,12 @@ public class IndicatorSound.Service: Object {
this.volume_control.active_output_changed.connect (menu.update_volume_slider);
});
+ this.menus.@foreach ( (profile, menu) => {
+ menu.last_player_updated.connect ((player_id) => {
+ this.settings.set_value ("last-running-player", player_id);
+ });
+ });
+
this.sync_preferred_players ();
this.settings.changed["interested-media-players"].connect ( () => {
this.sync_preferred_players ();
diff --git a/src/sound-menu.vala b/src/sound-menu.vala
index 604e484..630dca0 100644
--- a/src/sound-menu.vala
+++ b/src/sound-menu.vala
@@ -25,10 +25,20 @@ public class SoundMenu: Object
HIDE_INACTIVE_PLAYERS = 2,
HIDE_PLAYERS = 4,
GREETER_PLAYERS = 8,
- SHOW_SILENT_MODE = 16
+ SHOW_SILENT_MODE = 16,
+ HIDE_INACTIVE_PLAYERS_PLAY_CONTROLS = 32,
+ ADD_PLAY_CONTROL_INACTIVE_PLAYER = 64
}
- public SoundMenu (string? settings_action, DisplayFlags flags) {
+ public enum PlayerSectionPosition {
+ LABEL = 0,
+ PLAYER_CONTROLS = 1,
+ PLAYLIST = 2
+ }
+
+ const string PLAYBACK_ITEM_TYPE = "com.canonical.unity.playback-item";
+
+ public SoundMenu (string? settings_action, DisplayFlags flags, string default_player_id) {
/* 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.
@@ -68,10 +78,14 @@ public class SoundMenu: Object
this.hide_players = (flags & DisplayFlags.HIDE_PLAYERS) != 0;
this.hide_inactive = (flags & DisplayFlags.HIDE_INACTIVE_PLAYERS) != 0;
+ this.hide_inactive_player_controls = (flags & DisplayFlags.HIDE_INACTIVE_PLAYERS_PLAY_CONTROLS) != 0;
+ this.add_play_button_inactive_player = (flags & DisplayFlags.ADD_PLAY_CONTROL_INACTIVE_PLAYER) != 0;
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 () {
@@ -148,6 +162,15 @@ public class SoundMenu: Object
return -1;
}
+ public void update_all_players_play_section() {
+ foreach (var player_stored in notify_handlers.get_keys ()) {
+ int index = this.find_player_section(player_stored);
+ if (index != -1) {
+ // just update to verify if we must hide the player controls
+ update_player_section (player_stored, index);
+ }
+ }
+ }
public void add_player (MediaPlayer player) {
if (this.notify_handlers.contains (player))
@@ -158,21 +181,23 @@ public class SoundMenu: Object
this.update_playlists (player);
var handler_id = player.notify["is-running"].connect ( () => {
+ int index = this.find_player_section(player);
if (player.is_running) {
- int index = this.find_player_section(player);
if (index == -1) {
this.insert_player_section (player);
}
- else {
- update_player_section (player, index);
- }
+ number_of_running_players++;
}
else {
+ number_of_running_players--;
if (this.hide_inactive)
this.remove_player_section (player);
}
-
this.update_playlists (player);
+
+ // we need to update the rest of players, because we might have
+ // a non running player still showing the playback controls
+ update_all_players_play_section();
});
this.notify_handlers.insert (player, handler_id);
@@ -239,8 +264,12 @@ public class SoundMenu: Object
bool high_volume_warning_shown = false;
bool hide_inactive;
bool hide_players = false;
+ bool hide_inactive_player_controls = false;
+ bool add_play_button_inactive_player = false;
HashTable<MediaPlayer, ulong> notify_handlers;
bool greeter_players = false;
+ int number_of_running_players = 0;
+ string default_player = "";
/* returns the position in this.menu of the section that's associated with @player */
int find_player_section (MediaPlayer player) {
@@ -261,9 +290,21 @@ public class SoundMenu: Object
return -1;
}
+ int find_player_playback_controls_section (Menu player_menu) {
+ int n = player_menu.get_n_items ();
+ for (int i = 0; i < n; i++) {
+ string type;
+ player_menu.get_item_attribute (i, "x-canonical-type", "s", out type);
+ if (type == PLAYBACK_ITEM_TYPE)
+ return i;
+ }
+
+ return -1;
+ }
+
MenuItem create_playback_menu_item (MediaPlayer player) {
var playback_item = new MenuItem (null, null);
- playback_item.set_attribute ("x-canonical-type", "s", "com.canonical.unity.playback-item");
+ playback_item.set_attribute ("x-canonical-type", "s", PLAYBACK_ITEM_TYPE);
if (player.is_running) {
if (player.can_do_play) {
playback_item.set_attribute ("x-canonical-play-action", "s", "indicator.play." + player.id);
@@ -274,6 +315,10 @@ public class SoundMenu: Object
if (player.can_do_prev) {
playback_item.set_attribute ("x-canonical-previous-action", "s", "indicator.previous." + player.id);
}
+ } else {
+ if (this.add_play_button_inactive_player) {
+ playback_item.set_attribute ("x-canonical-play-action", "s", "indicator.play." + player.id);
+ }
}
return playback_item;
}
@@ -301,24 +346,10 @@ public class SoundMenu: Object
player_item.set_attribute_value ("icon", icon.serialize ());
section.append_item (player_item);
- var playback_item = new MenuItem (null, null);
- playback_item.set_attribute ("x-canonical-type", "s", "com.canonical.unity.playback-item");
- playback_item.set_attribute ("x-canonical-play-action", "s", "indicator.play." + player.id + ".disabled");
- playback_item.set_attribute ("x-canonical-next-action", "s", "indicator.next." + player.id + ".disabled");
- playback_item.set_attribute ("x-canonical-previous-action", "s", "indicator.previous." + player.id + ".disabled");
-
- if (player.is_running) {
- if (player.can_do_play) {
- playback_item.set_attribute ("x-canonical-play-action", "s", "indicator.play." + player.id);
- }
- if (player.can_do_next) {
- playback_item.set_attribute ("x-canonical-next-action", "s", "indicator.next." + player.id);
- }
- if (player.can_do_prev) {
- playback_item.set_attribute ("x-canonical-previous-action", "s", "indicator.previous." + player.id);
- }
+ if (player.is_running|| !this.hide_inactive_player_controls || player.id == this.default_player) {
+ var playback_item = create_playback_menu_item (player);
+ section.insert_item (PlayerSectionPosition.PLAYER_CONTROLS, playback_item);
}
- section.append_item (playback_item);
/* Add new players to the end of the player sections, just before the settings */
if (settings_shown) {
@@ -339,13 +370,25 @@ public class SoundMenu: Object
void update_player_section (MediaPlayer player, int index) {
var player_section = this.menu.get_item_link(index, Menu.LINK_SECTION) as Menu;
- if (player_section.get_n_items () == 2 || player_section.get_n_items () == 3) {
- // we have 2 items, the second one is the playback item
- // if we have 3 items, it means we also have the playlist item.
- // remove the playbak item first
- player_section.remove (1);
+
+ 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) {
MenuItem playback_item = create_playback_menu_item (player);
- player_section.insert_item (1, playback_item);
+ if (play_control_index != -1) {
+ player_section.remove (PlayerSectionPosition.PLAYER_CONTROLS);
+ }
+ player_section.insert_item (PlayerSectionPosition.PLAYER_CONTROLS, playback_item);
+ } else {
+ if (play_control_index != -1 && number_of_running_players >= 1) {
+ // remove both, playlist and play controls
+ player_section.remove (PlayerSectionPosition.PLAYLIST);
+ player_section.remove (PlayerSectionPosition.PLAYER_CONTROLS);
+ }
}
}
@@ -404,4 +447,6 @@ public class SoundMenu: Object
return slider;
}
+
+ public signal void last_player_updated (string player_id);
}
diff --git a/tests/integration/indicator-sound-test-base.cpp b/tests/integration/indicator-sound-test-base.cpp
index 91abf42..f61857e 100644
--- a/tests/integration/indicator-sound-test-base.cpp
+++ b/tests/integration/indicator-sound-test-base.cpp
@@ -192,16 +192,53 @@ bool IndicatorSoundTestBase::runProcess(QProcess& proc)
bool IndicatorSoundTestBase::startTestMprisPlayer(QString const& playerName)
{
- testPlayer1.terminate();
- testPlayer1.start(MEDIA_PLAYER_MPRIS_BIN, QStringList()
+ if (!stopTestMprisPlayer(playerName))
+ {
+ return false;
+ }
+ TestPlayer player;
+ player.name = playerName;
+ player.process.reset(new QProcess());
+ player.process->start(MEDIA_PLAYER_MPRIS_BIN, QStringList()
<< playerName);
- if (!testPlayer1.waitForStarted())
+ if (!player.process->waitForStarted())
+ {
+ qWarning() << "ERROR STARTING PLAYER " << playerName;
return false;
+ }
+ testPlayers.push_back(player);
return true;
}
+bool IndicatorSoundTestBase::stopTestMprisPlayer(QString const& playerName)
+{
+ bool terminateOK = true;
+ int index = findRunningTestMprisPlayer(playerName);
+ if (index != -1)
+ {
+ testPlayers[index].process->terminate();
+ if (!testPlayers[index].process->waitForFinished())
+ terminateOK = false;
+ testPlayers.remove(index);
+ }
+
+ return terminateOK;
+}
+
+int IndicatorSoundTestBase::findRunningTestMprisPlayer(QString const& playerName)
+{
+ for (int i = 0; i < testPlayers.size(); i++)
+ {
+ if (testPlayers.at(i).name == playerName)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
bool IndicatorSoundTestBase::setTestMprisPlayerProperty(QString const &testPlayer, QString const &property, bool value)
{
QProcess setProperty;
diff --git a/tests/integration/indicator-sound-test-base.h b/tests/integration/indicator-sound-test-base.h
index d9d3289..969fd69 100644
--- a/tests/integration/indicator-sound-test-base.h
+++ b/tests/integration/indicator-sound-test-base.h
@@ -81,6 +81,8 @@ protected:
bool runProcess(QProcess&);
bool startTestMprisPlayer(QString const& playerName);
+ bool stopTestMprisPlayer(QString const& playerName);
+ int findRunningTestMprisPlayer(QString const& playerName);
bool setTestMprisPlayerProperty(QString const &testPlayer, QString const &property, bool value);
@@ -156,6 +158,13 @@ protected:
QProcess testPlayer1;
+ struct TestPlayer
+ {
+ std::shared_ptr<QProcess> process;
+ QString name;
+ };
+ QVector<TestPlayer> testPlayers;
+
std::unique_ptr<MenusInterface> menu_interface_;
std::unique_ptr<DBusPropertiesInterface> accounts_interface_;
diff --git a/tests/integration/test-indicator.cpp b/tests/integration/test-indicator.cpp
index 9224b73..33a27af 100644
--- a/tests/integration/test-indicator.cpp
+++ b/tests/integration/test-indicator.cpp
@@ -367,6 +367,574 @@ TEST_F(TestIndicator, DesktopAddMprisPlayer)
.label("Sound Settings…")
)
).match());
+
+ // stop the test player
+ EXPECT_TRUE(stopTestMprisPlayer("testplayer1"));
+
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
+}
+
+TEST_F(TestIndicator, DesktopMprisPlayersPlaybackControls)
+{
+ double INITIAL_VOLUME = 0.0;
+
+ ASSERT_NO_THROW(startAccountsService());
+ EXPECT_TRUE(clearGSettingsPlayers());
+ ASSERT_NO_THROW(startPulseDesktop());
+
+ // initialize volumes in pulseaudio
+ EXPECT_FALSE(setStreamRestoreVolume("alert", INITIAL_VOLUME));
+ EXPECT_TRUE(setSinkVolume(INITIAL_VOLUME));
+
+ // start the test player
+ EXPECT_TRUE(startTestMprisPlayer("testplayer1"));
+
+ // start now the indicator, so it picks the new volumes
+ ASSERT_NO_THROW(startIndicator());
+
+ // check that the player is added
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
+
+ // start the second test player
+ EXPECT_TRUE(startTestMprisPlayer("testplayer2"));
+
+ // check that the player is added
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer2.desktop")
+ .label("TestPlayer2")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer2.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer2.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
+
+ // start the third test player
+ EXPECT_TRUE(startTestMprisPlayer("testplayer3"));
+
+ // check that the player is added
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer2.desktop")
+ .label("TestPlayer2")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer2.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer2.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer3.desktop")
+ .label("TestPlayer3")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer3.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer3.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer3.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
+
+ // stop the test player
+ EXPECT_TRUE(stopTestMprisPlayer("testplayer3"));
+
+ // check that player 3 is present, but it has no playback controls
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer2.desktop")
+ .label("TestPlayer2")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer2.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer2.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer3.desktop")
+ .label("TestPlayer3")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
+
+ EXPECT_TRUE(stopTestMprisPlayer("testplayer2"));
+
+ // check that player 2 is present, but it has no playback controls
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer2.desktop")
+ .label("TestPlayer2")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer3.desktop")
+ .label("TestPlayer3")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
+
+ EXPECT_TRUE(stopTestMprisPlayer("testplayer1"));
+
+ // check that player 1 is present, and it still has the playback controls
+ // as it was the last one being executed
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer2.desktop")
+ .label("TestPlayer2")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer3.desktop")
+ .label("TestPlayer3")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
+
+ // start the third test player
+ EXPECT_TRUE(startTestMprisPlayer("testplayer3"));
+
+ // check that player 3 is the only one with playback controls
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer2.desktop")
+ .label("TestPlayer2")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer3.desktop")
+ .label("TestPlayer3")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer3.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer3.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer3.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
+
+ // start the rest of players
+ EXPECT_TRUE(startTestMprisPlayer("testplayer1"));
+ EXPECT_TRUE(startTestMprisPlayer("testplayer2"));
+
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer1.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer1.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer1.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer2.desktop")
+ .label("TestPlayer2")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer2.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer2.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer2.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer3.desktop")
+ .label("TestPlayer3")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer3.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer3.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer3.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
+
+ // stop all players
+ EXPECT_TRUE(stopTestMprisPlayer("testplayer1"));
+ EXPECT_TRUE(stopTestMprisPlayer("testplayer2"));
+ EXPECT_TRUE(stopTestMprisPlayer("testplayer3"));
+
+ // check that player 3 is the only one with playback controls
+ // as it was the last one being stopped
+ EXPECT_MATCHRESULT(mh::MenuMatcher(desktopParameters())
+ .item(mh::MenuItemMatcher()
+ .action("indicator.root")
+ .string_attribute("x-canonical-type", "com.canonical.indicator.root")
+ .string_attribute("x-canonical-secondary-action", "indicator.mute")
+ .mode(mh::MenuItemMatcher::Mode::all)
+ .submenu()
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher().checkbox()
+ .label("Mute")
+ )
+ .item(volumeSlider(INITIAL_VOLUME, "Volume"))
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer1.desktop")
+ .label("TestPlayer1")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer2.desktop")
+ .label("TestPlayer2")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .section()
+ .item(mh::MenuItemMatcher()
+ .action("indicator.testplayer3.desktop")
+ .label("TestPlayer3")
+ .themed_icon("icon", {"testplayer"})
+ .string_attribute("x-canonical-type", "com.canonical.unity.media-player")
+ )
+ .item(mh::MenuItemMatcher()
+ .string_attribute("x-canonical-previous-action","indicator.previous.testplayer3.desktop")
+ .string_attribute("x-canonical-play-action","indicator.play.testplayer3.desktop")
+ .string_attribute("x-canonical-next-action","indicator.next.testplayer3.desktop")
+ .string_attribute("x-canonical-type","com.canonical.unity.playback-item")
+ )
+ )
+ .item(mh::MenuItemMatcher()
+ .label("Sound Settings…")
+ )
+ ).match());
}
TEST_F(TestIndicator, DesktopMprisPlayerButtonsState)
@@ -817,7 +1385,6 @@ TEST_F(TestIndicator, DISABLED_PhoneNotificationWarningVolume)
// try again...
notificationsSpy.clear();
- qWarning() << "-----------------------------------------------------------";
// change volume to 1.0... warning should be emitted
setActionValue("volume", QVariant::fromValue(1.0));
EXPECT_TRUE(waitVolumeChangedInIndicator());
diff --git a/tests/service-mocks/media-player-mpris-mock/applications/testplayer2.desktop b/tests/service-mocks/media-player-mpris-mock/applications/testplayer2.desktop
new file mode 100644
index 0000000..579a0bf
--- /dev/null
+++ b/tests/service-mocks/media-player-mpris-mock/applications/testplayer2.desktop
@@ -0,0 +1,21 @@
+[Desktop Entry]
+Name=TestPlayer2
+GenericName=Test Player 2
+X-GNOME-FullName=Test Player 2
+Comment=Play and organize your music collection
+Keywords=Audio;Song;MP3;CD;Podcast;MTP;iPod;Playlist;Last.fm;UPnP;DLNA;Radio;
+Exec=echo %U
+Terminal=false
+Type=Application
+Icon=testplayer
+X-GNOME-DocPath=testplayer/testplayer.xml
+Categories=GNOME;GTK;AudioVideo;Audio;Player;
+MimeType=application/x-ogg;application/ogg;audio/x-vorbis+ogg;audio/x-scpls;audio/x-mp3;audio/x-mpeg;audio/mpeg;audio/x-mpegurl;audio/x-flac;audio/mp4;x-scheme-handler/itms;x-scheme-handler/itmss;
+StartupNotify=true
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=testplayer
+X-GNOME-Bugzilla-Component=general
+X-GNOME-Bugzilla-OtherBinaries=rhythmbox-client;rhythmbox-metadata;
+X-GNOME-Bugzilla-Version=3.1
+X-GNOME-UsesNotifications=true
+
diff --git a/tests/service-mocks/media-player-mpris-mock/applications/testplayer3.desktop b/tests/service-mocks/media-player-mpris-mock/applications/testplayer3.desktop
new file mode 100644
index 0000000..b3bfc6b
--- /dev/null
+++ b/tests/service-mocks/media-player-mpris-mock/applications/testplayer3.desktop
@@ -0,0 +1,21 @@
+[Desktop Entry]
+Name=TestPlayer3
+GenericName=Test Player 3
+X-GNOME-FullName=Test Player 3
+Comment=Play and organize your music collection
+Keywords=Audio;Song;MP3;CD;Podcast;MTP;iPod;Playlist;Last.fm;UPnP;DLNA;Radio;
+Exec=echo %U
+Terminal=false
+Type=Application
+Icon=testplayer
+X-GNOME-DocPath=testplayer/testplayer.xml
+Categories=GNOME;GTK;AudioVideo;Audio;Player;
+MimeType=application/x-ogg;application/ogg;audio/x-vorbis+ogg;audio/x-scpls;audio/x-mp3;audio/x-mpeg;audio/mpeg;audio/x-mpegurl;audio/x-flac;audio/mp4;x-scheme-handler/itms;x-scheme-handler/itmss;
+StartupNotify=true
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=testplayer
+X-GNOME-Bugzilla-Component=general
+X-GNOME-Bugzilla-OtherBinaries=rhythmbox-client;rhythmbox-metadata;
+X-GNOME-Bugzilla-Version=3.1
+X-GNOME-UsesNotifications=true
+
diff --git a/tests/sound-menu.cc b/tests/sound-menu.cc
index 75a661b..2576d19 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,9 +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(canPlay ? "indicator.play.player-id" : "indicator.play.player-id.disabled"));
- verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string(canNext ? "indicator.next.player-id" : "indicator.next.player-id.disabled"));
- verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string(canPrev ? "indicator.previous.player-id" : "indicator.previous.player-id.disabled"));
+ //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) {
+ 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) {
+ 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"));
+ }
g_clear_object(&section);
@@ -112,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);
@@ -121,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");