Merge lp:~xavi-garcia-mena/indicator-sound/next-play-prev-buttons-bug-1373313 into lp:indicator-sound/15.10

Proposed by Xavi Garcia on 2015-09-15
Status: Merged
Approved by: Charles Kerr on 2015-09-17
Approved revision: 506
Merged at revision: 506
Proposed branch: lp:~xavi-garcia-mena/indicator-sound/next-play-prev-buttons-bug-1373313
Merge into: lp:indicator-sound/15.10
Diff against target: 538 lines (+275/-91)
7 files modified
debian/changelog (+24/-6)
src/media-player-mpris.vala (+22/-0)
src/media-player.vala (+4/-0)
src/mpris2-interfaces.vala (+4/-1)
src/sound-menu.vala (+61/-6)
tests/media-player-mock.vala (+6/-0)
tests/sound-menu.cc (+154/-78)
To merge this branch: bzr merge lp:~xavi-garcia-mena/indicator-sound/next-play-prev-buttons-bug-1373313
Reviewer Review Type Date Requested Status
Charles Kerr (community) 2015-09-15 Approve on 2015-09-17
PS Jenkins bot continuous-integration Approve on 2015-09-17
Review via email: mp+271114@code.launchpad.net

Commit Message

Synchronize the state of the Previous/Play/Next buttons with the state obtained from MPRIS.

The state is updated every time the properties are modified.

Description of the Change

Synchronize the state of the Previous/Play/Next buttons with the state obtained from MPRIS.

The state is updated every time the properties are modified.

To post a comment you must log in.
Charles Kerr (charlesk) wrote :

Mostly looks good. A couple of questions inline below.

review: Needs Information
505. By Xavi Garcia on 2015-09-16

Unit tests refactored

506. By Xavi Garcia on 2015-09-17

merged with trunk

Charles Kerr (charlesk) wrote :

Thanks for the test changes, Xavi. LGTM.

review: Approve
507. By Xavi Garcia on 2015-09-28

Fixed property name when checking if CanGoPrevious changed

508. By Xavi Garcia on 2015-10-13

Fixed version in changelog

509. By Xavi Garcia on 2015-10-14

Updating MPRIS control in the menu not only when next and previous are updated

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2015-09-15 08:19:51 +0000
3+++ debian/changelog 2015-10-14 14:58:07 +0000
4@@ -1,4 +1,11 @@
5-indicator-sound (12.10.2+15.10.20150915-0ubuntu1) wily; urgency=medium
6+indicator-sound (12.10.2+15.04.20150917-0ubuntu1) vivid; urgency=medium
7+
8+ [ Xavi Garcia Mena ]
9+ * Merged lp:~xavi-garcia-mena/indicator-sound/icon-volume-zero
10+
11+ -- Sebastien Bacher <seb128@ubuntu.com> Tue, 15 Sep 2015 08:19:51 +0000
12+
13+indicator-sound (12.10.2+15.04.20150915-0ubuntu1) vivid; urgency=medium
14
15 [ Sebastien Bacher ]
16 * under unity8 start system-settings instead unity-control-center (LP:
17@@ -9,7 +16,7 @@
18
19 -- Sebastien Bacher <seb128@ubuntu.com> Tue, 15 Sep 2015 08:19:51 +0000
20
21-indicator-sound (12.10.2+15.10.20150812.3-0ubuntu1) wily; urgency=medium
22+indicator-sound (12.10.2+15.04.20150812.3-0ubuntu1) vivid; urgency=medium
23
24 [ CI Train Bot ]
25 * New rebuild forced.
26@@ -20,7 +27,7 @@
27
28 -- CI Train Bot <ci-train-bot@canonical.com> Wed, 12 Aug 2015 20:55:05 +0000
29
30-indicator-sound (12.10.2+15.10.20150807.6-0ubuntu1) wily; urgency=medium
31+indicator-sound (12.10.2+15.04.20150807.6-0ubuntu1) vivid; urgency=medium
32
33 [ CI Train Bot ]
34 * New rebuild forced.
35@@ -31,19 +38,19 @@
36
37 -- CI Train Bot <ci-train-bot@canonical.com> Fri, 07 Aug 2015 22:35:58 +0000
38
39-indicator-sound (12.10.2+15.10.20150605-0ubuntu1) wily; urgency=medium
40+indicator-sound (12.10.2+15.04.20150605-0ubuntu1) vivid; urgency=medium
41
42 *
43
44 -- CI Train Bot <ci-train-bot@canonical.com> Fri, 05 Jun 2015 19:50:06 +0000
45
46-indicator-sound (12.10.2+15.10.20150507+eventually4-0ubuntu1) wily; urgency=medium
47+indicator-sound (12.10.2+15.04.20150507+eventually4-0ubuntu1) vivid; urgency=medium
48
49 * Using eventually to avoid arbitrary timeouts in tests
50
51 -- Ted Gould <ted@ubuntu.com> Wed, 27 May 2015 11:11:19 -0500
52
53-indicator-sound (12.10.2+15.10.20150507-0ubuntu1) wily; urgency=medium
54+indicator-sound (12.10.2+15.04.20150507-0ubuntu1) vivid; urgency=medium
55
56 [ Charles Kerr ]
57 * Use the BusWatcher to look for org.freedesktop.Notifications
58@@ -51,6 +58,17 @@
59
60 -- CI Train Bot <ci-train-bot@canonical.com> Thu, 07 May 2015 15:27:00 +0000
61
62+indicator-sound (12.10.2+15.04.20150508-0ubuntu1) vivid; urgency=medium
63+
64+ [ CI Train Bot ]
65+ * New rebuild forced.
66+
67+ [ Charles Kerr ]
68+ * Use the BusWatcher to look for org.freedesktop.Notifications
69+ ownership changes on the bus. (LP: #1432446)
70+
71+ -- CI Train Bot <ci-train-bot@canonical.com> Fri, 08 May 2015 12:20:07 +0000
72+
73 indicator-sound (12.10.2+15.04.20150421-0ubuntu1) vivid; urgency=medium
74
75 [ Ted Gould ]
76
77=== modified file 'src/media-player-mpris.vala'
78--- src/media-player-mpris.vala 2015-03-26 15:56:49 +0000
79+++ src/media-player-mpris.vala 2015-10-14 14:58:07 +0000
80@@ -79,6 +79,24 @@
81 }
82 }
83
84+ public override bool can_do_play {
85+ get {
86+ return this.proxy.CanPlay;
87+ }
88+ }
89+
90+ public override bool can_do_prev {
91+ get {
92+ return this.proxy.CanGoPrevious;
93+ }
94+ }
95+
96+ public override bool can_do_next {
97+ get {
98+ return this.proxy.CanGoNext;
99+ }
100+ }
101+
102 /**
103 * Attach this object to a process of the associated media player. The player must own @dbus_name and
104 * implement the org.mpris.MediaPlayer2.Player interface.
105@@ -272,6 +290,10 @@
106 if (changed_properties.lookup ("PlaybackStatus", "s", null)) {
107 this.state = this.proxy.PlaybackStatus != null ? this.proxy.PlaybackStatus : "Unknown";
108 }
109+ if (changed_properties.lookup ("CanGoNext", "b", null) || changed_properties.lookup ("CanGoPrevious", "b", null) ||
110+ changed_properties.lookup ("CanPlay", "b", null) || changed_properties.lookup ("CanPause", "b", null)) {
111+ this.playbackstatus_changed ();
112+ }
113
114 var metadata = changed_properties.lookup_value ("Metadata", new VariantType ("a{sv}"));
115 if (metadata != null)
116
117=== modified file 'src/media-player.vala'
118--- src/media-player.vala 2014-02-12 16:21:32 +0000
119+++ src/media-player.vala 2015-10-14 14:58:07 +0000
120@@ -26,6 +26,9 @@
121
122 public virtual bool is_running { get { not_implemented(); return false; } }
123 public virtual bool can_raise { get { not_implemented(); return false; } }
124+ public virtual bool can_do_next { get { not_implemented(); return false; } }
125+ public virtual bool can_do_prev { get { not_implemented(); return false; } }
126+ public virtual bool can_do_play { get { not_implemented(); return false; } }
127
128 public class Track : Object {
129 public string artist { get; construct; }
130@@ -44,6 +47,7 @@
131 }
132
133 public signal void playlists_changed ();
134+ public signal void playbackstatus_changed ();
135
136 public abstract void activate ();
137 public abstract void play_pause ();
138
139=== modified file 'src/mpris2-interfaces.vala'
140--- src/mpris2-interfaces.vala 2015-03-26 15:56:49 +0000
141+++ src/mpris2-interfaces.vala 2015-10-14 14:58:07 +0000
142@@ -37,7 +37,10 @@
143 // properties
144 public abstract HashTable<string, Variant?> Metadata{owned get; set;}
145 public abstract int32 Position{owned get; set;}
146- public abstract string? PlaybackStatus{owned get; set;}
147+ public abstract string? PlaybackStatus{owned get; set;}
148+ public abstract bool CanPlay{owned get; set;}
149+ public abstract bool CanGoNext{owned get; set;}
150+ public abstract bool CanGoPrevious{owned get; set;}
151 // methods
152 public abstract async void PlayPause() throws IOError;
153 public abstract async void Next() throws IOError;
154
155=== modified file 'src/sound-menu.vala'
156--- src/sound-menu.vala 2015-02-12 00:44:34 +0000
157+++ src/sound-menu.vala 2015-10-14 14:58:07 +0000
158@@ -157,18 +157,26 @@
159 this.update_playlists (player);
160
161 var handler_id = player.notify["is-running"].connect ( () => {
162- if (player.is_running)
163- if (this.find_player_section(player) == -1)
164+ if (player.is_running) {
165+ int index = this.find_player_section(player);
166+ if (index == -1) {
167 this.insert_player_section (player);
168- else
169+ }
170+ else {
171+ update_player_section (player, index);
172+ }
173+ }
174+ else {
175 if (this.hide_inactive)
176 this.remove_player_section (player);
177+ }
178
179 this.update_playlists (player);
180 });
181 this.notify_handlers.insert (player, handler_id);
182
183 player.playlists_changed.connect (this.update_playlists);
184+ player.playbackstatus_changed.connect (this.update_playbackstatus);
185 }
186
187 public void remove_player (MediaPlayer player) {
188@@ -215,6 +223,23 @@
189 return -1;
190 }
191
192+ MenuItem create_playback_menu_item (MediaPlayer player) {
193+ var playback_item = new MenuItem (null, null);
194+ playback_item.set_attribute ("x-canonical-type", "s", "com.canonical.unity.playback-item");
195+ if (player.is_running) {
196+ if (player.can_do_play) {
197+ playback_item.set_attribute ("x-canonical-play-action", "s", "indicator.play." + player.id);
198+ }
199+ if (player.can_do_next) {
200+ playback_item.set_attribute ("x-canonical-next-action", "s", "indicator.next." + player.id);
201+ }
202+ if (player.can_do_prev) {
203+ playback_item.set_attribute ("x-canonical-previous-action", "s", "indicator.previous." + player.id);
204+ }
205+ }
206+ return playback_item;
207+ }
208+
209 void insert_player_section (MediaPlayer player) {
210 if (this.hide_players)
211 return;
212@@ -240,9 +265,21 @@
213
214 var playback_item = new MenuItem (null, null);
215 playback_item.set_attribute ("x-canonical-type", "s", "com.canonical.unity.playback-item");
216- playback_item.set_attribute ("x-canonical-play-action", "s", "indicator.play." + player.id);
217- playback_item.set_attribute ("x-canonical-next-action", "s", "indicator.next." + player.id);
218- playback_item.set_attribute ("x-canonical-previous-action", "s", "indicator.previous." + player.id);
219+ playback_item.set_attribute ("x-canonical-play-action", "s", "indicator.play." + player.id + ".disabled");
220+ playback_item.set_attribute ("x-canonical-next-action", "s", "indicator.next." + player.id + ".disabled");
221+ playback_item.set_attribute ("x-canonical-previous-action", "s", "indicator.previous." + player.id + ".disabled");
222+
223+ if (player.is_running) {
224+ if (player.can_do_play) {
225+ playback_item.set_attribute ("x-canonical-play-action", "s", "indicator.play." + player.id);
226+ }
227+ if (player.can_do_next) {
228+ playback_item.set_attribute ("x-canonical-next-action", "s", "indicator.next." + player.id);
229+ }
230+ if (player.can_do_prev) {
231+ playback_item.set_attribute ("x-canonical-previous-action", "s", "indicator.previous." + player.id);
232+ }
233+ }
234 section.append_item (playback_item);
235
236 /* Add new players to the end of the player sections, just before the settings */
237@@ -262,6 +299,17 @@
238 this.menu.remove (index);
239 }
240
241+ void update_player_section (MediaPlayer player, int index) {
242+ var player_section = this.menu.get_item_link(index, Menu.LINK_SECTION) as Menu;
243+ if (player_section.get_n_items () == 2) {
244+ // we have 2 items, the second one is the playback item
245+ // remove it first
246+ player_section.remove (1);
247+ MenuItem playback_item = create_playback_menu_item (player);
248+ player_section.append_item (playback_item);
249+ }
250+ }
251+
252 void update_playlists (MediaPlayer player) {
253 int index = find_player_section (player);
254 if (index < 0)
255@@ -292,6 +340,13 @@
256 submenu.append_section (null, playlists_section);
257 player_section.append_submenu (_("Choose Playlist"), submenu);
258 }
259+
260+ void update_playbackstatus (MediaPlayer player) {
261+ int index = find_player_section (player);
262+ if (index != -1) {
263+ update_player_section (player, index);
264+ }
265+ }
266
267 MenuItem create_slider_menu_item (string label, string action, double min, double max, double step, string min_icon_name, string max_icon_name) {
268 var min_icon = new ThemedIcon.with_default_fallbacks (min_icon_name);
269
270=== modified file 'tests/media-player-mock.vala'
271--- tests/media-player-mock.vala 2014-02-12 19:54:59 +0000
272+++ tests/media-player-mock.vala 2015-10-14 14:58:07 +0000
273@@ -28,6 +28,9 @@
274
275 public override bool is_running { get { return mock_is_running; } }
276 public override bool can_raise { get { return mock_can_raise; } }
277+ public override bool can_do_next { get { return mock_can_do_next; } }
278+ public override bool can_do_prev { get { return mock_can_do_prev; } }
279+ public override bool can_do_play { get { return mock_can_do_play; } }
280
281 public override MediaPlayer.Track? current_track { get { return mock_current_track; } set { this.mock_current_track = value; } }
282
283@@ -40,6 +43,9 @@
284
285 public bool mock_is_running { get; set; }
286 public bool mock_can_raise { get; set; }
287+ public bool mock_can_do_next { get; set; }
288+ public bool mock_can_do_prev { get; set; }
289+ public bool mock_can_do_play { get; set; }
290
291 public MediaPlayer.Track? mock_current_track { get; set; }
292
293
294=== modified file 'tests/sound-menu.cc'
295--- tests/sound-menu.cc 2014-03-03 21:38:38 +0000
296+++ tests/sound-menu.cc 2015-10-14 14:58:07 +0000
297@@ -27,87 +27,163 @@
298
299 class SoundMenuTest : public ::testing::Test
300 {
301- protected:
302- GTestDBus * bus = nullptr;
303-
304- virtual void SetUp() {
305- bus = g_test_dbus_new(G_TEST_DBUS_NONE);
306- g_test_dbus_up(bus);
307- }
308-
309- virtual void TearDown() {
310- g_test_dbus_down(bus);
311- g_clear_object(&bus);
312- }
313-
314- void verify_item_attribute (GMenuModel * mm, guint index, const gchar * name, GVariant * value) {
315- g_variant_ref_sink(value);
316-
317- gchar * variantstr = g_variant_print(value, TRUE);
318- g_debug("Expecting item %d to have a '%s' attribute: %s", index, name, variantstr);
319-
320- const GVariantType * type = g_variant_get_type(value);
321- GVariant * itemval = g_menu_model_get_item_attribute_value(mm, index, name, type);
322-
323- ASSERT_NE(nullptr, itemval);
324- EXPECT_TRUE(g_variant_equal(itemval, value));
325-
326- g_variant_unref(value);
327- }
328+ protected:
329+ GTestDBus * bus = nullptr;
330+
331+ virtual void SetUp() {
332+ bus = g_test_dbus_new(G_TEST_DBUS_NONE);
333+ g_test_dbus_up(bus);
334+ }
335+
336+ virtual void TearDown() {
337+ g_test_dbus_down(bus);
338+ g_clear_object(&bus);
339+ }
340+
341+ void verify_item_attribute (GMenuModel * mm, guint index, const gchar * name, GVariant * value) {
342+ g_variant_ref_sink(value);
343+
344+ gchar * variantstr = g_variant_print(value, TRUE);
345+ g_debug("Expecting item %d to have a '%s' attribute: %s", index, name, variantstr);
346+
347+ const GVariantType * type = g_variant_get_type(value);
348+ GVariant * itemval = g_menu_model_get_item_attribute_value(mm, index, name, type);
349+
350+ ASSERT_NE(nullptr, itemval);
351+ EXPECT_TRUE(g_variant_equal(itemval, value));
352+
353+ g_variant_unref(value);
354+ }
355+
356+ void verify_item_attribute_is_not_set(GMenuModel * mm, guint index, const gchar * name, const GVariantType * type) {
357+ GVariant * itemval = g_menu_model_get_item_attribute_value(mm, index, name, type);
358+ EXPECT_EQ(itemval, nullptr);
359+ }
360+
361+ void check_player_control_buttons(bool canPlay, bool canNext, bool canPrev)
362+ {
363+ SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE);
364+
365+ MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url");
366+
367+ MediaPlayerMock * media = MEDIA_PLAYER_MOCK(
368+ g_object_new(TYPE_MEDIA_PLAYER_MOCK,
369+ "mock-id", "player-id",
370+ "mock-name", "Test Player",
371+ "mock-state", "Playing",
372+ "mock-is-running", TRUE,
373+ "mock-can-raise", FALSE,
374+ "mock-current-track", track,
375+ "mock-can-do-play", canPlay,
376+ "mock-can-do-next", canNext,
377+ "mock-can-do-prev", canPrev,
378+ NULL)
379+ );
380+ g_clear_object(&track);
381+
382+ sound_menu_add_player(menu, MEDIA_PLAYER(media));
383+
384+ ASSERT_NE(nullptr, menu->menu);
385+ EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu)));
386+
387+ GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION);
388+ ASSERT_NE(nullptr, section);
389+ EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */
390+
391+ /* Player display */
392+ verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id"));
393+ verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player"));
394+
395+ /* Player control */
396+ verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item"));
397+ verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string(canPlay ? "indicator.play.player-id" : "indicator.play.player-id.disabled"));
398+ verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string(canNext ? "indicator.next.player-id" : "indicator.next.player-id.disabled"));
399+ verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string(canPrev ? "indicator.previous.player-id" : "indicator.previous.player-id.disabled"));
400+
401+ g_clear_object(&section);
402+
403+ sound_menu_remove_player(menu, MEDIA_PLAYER(media));
404+
405+ EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu)));
406+
407+ g_clear_object(&media);
408+ g_clear_object(&menu);
409+ }
410 };
411
412 TEST_F(SoundMenuTest, BasicObject) {
413- SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE);
414-
415- ASSERT_NE(nullptr, menu);
416-
417- g_clear_object(&menu);
418- return;
419+ SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE);
420+
421+ ASSERT_NE(nullptr, menu);
422+
423+ g_clear_object(&menu);
424+ return;
425 }
426
427 TEST_F(SoundMenuTest, AddRemovePlayer) {
428- SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE);
429-
430- MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url");
431-
432- MediaPlayerMock * media = MEDIA_PLAYER_MOCK(
433- g_object_new(TYPE_MEDIA_PLAYER_MOCK,
434- "mock-id", "player-id",
435- "mock-name", "Test Player",
436- "mock-state", "Playing",
437- "mock-is-running", TRUE,
438- "mock-can-raise", FALSE,
439- "mock-current-track", track,
440- NULL)
441- );
442- g_clear_object(&track);
443-
444- sound_menu_add_player(menu, MEDIA_PLAYER(media));
445-
446- ASSERT_NE(nullptr, menu->menu);
447- EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu)));
448-
449- GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION);
450- ASSERT_NE(nullptr, section);
451- EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */
452-
453- /* Player display */
454- verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id"));
455- verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player"));
456-
457- /* Player control */
458- verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item"));
459- verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id"));
460- verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id"));
461- verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id"));
462-
463- g_clear_object(&section);
464-
465- sound_menu_remove_player(menu, MEDIA_PLAYER(media));
466-
467- EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu)));
468-
469- g_clear_object(&media);
470- g_clear_object(&menu);
471- return;
472-}
473+ SoundMenu * menu = sound_menu_new (nullptr, SOUND_MENU_DISPLAY_FLAGS_NONE);
474+
475+ MediaPlayerTrack * track = media_player_track_new("Artist", "Title", "Album", "http://art.url");
476+
477+ MediaPlayerMock * media = MEDIA_PLAYER_MOCK(
478+ g_object_new(TYPE_MEDIA_PLAYER_MOCK,
479+ "mock-id", "player-id",
480+ "mock-name", "Test Player",
481+ "mock-state", "Playing",
482+ "mock-is-running", TRUE,
483+ "mock-can-raise", FALSE,
484+ "mock-current-track", track,
485+ "mock-can-do-play", TRUE,
486+ "mock-can-do-next", TRUE,
487+ "mock-can-do-prev", TRUE,
488+ NULL)
489+ );
490+ g_clear_object(&track);
491+
492+ sound_menu_add_player(menu, MEDIA_PLAYER(media));
493+
494+ ASSERT_NE(nullptr, menu->menu);
495+ EXPECT_EQ(2, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu)));
496+
497+ GMenuModel * section = g_menu_model_get_item_link(G_MENU_MODEL(menu->menu), 1, G_MENU_LINK_SECTION);
498+ ASSERT_NE(nullptr, section);
499+ EXPECT_EQ(2, g_menu_model_get_n_items(section)); /* No playlists, so two items */
500+
501+ /* Player display */
502+ verify_item_attribute(section, 0, "action", g_variant_new_string("indicator.player-id"));
503+ verify_item_attribute(section, 0, "x-canonical-type", g_variant_new_string("com.canonical.unity.media-player"));
504+
505+ /* Player control */
506+ verify_item_attribute(section, 1, "x-canonical-type", g_variant_new_string("com.canonical.unity.playback-item"));
507+ verify_item_attribute(section, 1, "x-canonical-play-action", g_variant_new_string("indicator.play.player-id"));
508+ verify_item_attribute(section, 1, "x-canonical-next-action", g_variant_new_string("indicator.next.player-id"));
509+ verify_item_attribute(section, 1, "x-canonical-previous-action", g_variant_new_string("indicator.previous.player-id"));
510+
511+ g_clear_object(&section);
512+
513+ sound_menu_remove_player(menu, MEDIA_PLAYER(media));
514+
515+ EXPECT_EQ(1, g_menu_model_get_n_items(G_MENU_MODEL(menu->menu)));
516+
517+ g_clear_object(&media);
518+ g_clear_object(&menu);
519+ return;
520+}
521+
522+TEST_F(SoundMenuTest, AddRemovePlayerNoPlayNextPrev) {
523+ check_player_control_buttons(false, false, false);
524+}
525+
526+TEST_F(SoundMenuTest, AddRemovePlayerNoNext) {
527+ check_player_control_buttons(true, false, true);
528+}
529+
530+TEST_F(SoundMenuTest, AddRemovePlayerNoPrev) {
531+ check_player_control_buttons(true, true, false);
532+}
533+
534+TEST_F(SoundMenuTest, AddRemovePlayerNoPlay) {
535+ check_player_control_buttons(false, true, true);
536+}
537+
538+//

Subscribers

People subscribed via source and target branches