diff options
author | Conor Curran <conor.curran@canonical.com> | 2010-12-17 16:25:04 +0000 |
---|---|---|
committer | Conor Curran <conor.curran@canonical.com> | 2010-12-17 16:25:04 +0000 |
commit | 80ce8f642c251dc765267fa1b1978fec59d23c97 (patch) | |
tree | 3966c20e333cc79744fe54e4aa699a693b934efd /src | |
parent | 7ea64f857b5f76cd06e01bfe49eda27c2d2da335 (diff) | |
parent | 032797fd7a92bc8a4fd979ddc12cacb0918ca73b (diff) | |
download | ayatana-indicator-sound-80ce8f642c251dc765267fa1b1978fec59d23c97.tar.gz ayatana-indicator-sound-80ce8f642c251dc765267fa1b1978fec59d23c97.tar.bz2 ayatana-indicator-sound-80ce8f642c251dc765267fa1b1978fec59d23c97.zip |
playlists - working nicely
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/common-defs.h | 3 | ||||
-rw-r--r-- | src/dbus-menu-manager.c | 1 | ||||
-rw-r--r-- | src/mpris2-controller.vala | 84 | ||||
-rw-r--r-- | src/mpris2-interfaces.vala | 30 | ||||
-rw-r--r-- | src/music-player-bridge.vala | 2 | ||||
-rw-r--r-- | src/player-controller.vala | 27 | ||||
-rw-r--r-- | src/player-item.vala | 4 | ||||
-rw-r--r-- | src/playlists-menu-item.vala | 76 | ||||
-rw-r--r-- | src/sound-service.c | 4 |
10 files changed, 213 insertions, 19 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 5ef9ef0..82830e1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -65,6 +65,7 @@ music_bridge_VALASOURCES = \ mpris2-controller.vala \ player-item.vala \ settings-manager.vala \ + playlists-menu-item.vala \ fetch-file.vala diff --git a/src/common-defs.h b/src/common-defs.h index 214f60a..8ec69e8 100644 --- a/src/common-defs.h +++ b/src/common-defs.h @@ -49,3 +49,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #define DBUSMENU_SCRUB_MENUITEM_POSITION "x-canonical-sound-menu-player-scrub-position" #define DBUSMENU_SCRUB_MENUITEM_PLAY_STATE "x-canonical-sound-menu-player-scrub-play-state" +#define DBUSMENU_PLAYLISTS_MENUITEM_TYPE "x-canonical-sound-menu-player-playlists-type" +#define DBUSMENU_PLAYLISTS_MENUITEM_TITLE "x-canonical-sound-menu-player-playlists-title" +#define DBUSMENU_PLAYLISTS_MENUITEM_PLAYLISTS "x-canonical-sound-menu-player-playlists-playlists"
\ No newline at end of file diff --git a/src/dbus-menu-manager.c b/src/dbus-menu-manager.c index 37e1c18..f92c324 100644 --- a/src/dbus-menu-manager.c +++ b/src/dbus-menu-manager.c @@ -214,6 +214,7 @@ static void rebuild_sound_menu(DbusmenuMenuitem *root, SoundServiceDbus *service // Sound preferences dialog DbusmenuMenuitem *settings_mi = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(settings_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Sound Preferences...")); + //_("Sound Preferences...")); dbusmenu_menuitem_child_append(root, settings_mi); g_signal_connect(G_OBJECT(settings_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, diff --git a/src/mpris2-controller.vala b/src/mpris2-controller.vala index 7f14efe..58a1906 100644 --- a/src/mpris2-controller.vala +++ b/src/mpris2-controller.vala @@ -18,11 +18,10 @@ with this program. If not, see <http://www.gnu.org/licenses/>. */ using Dbusmenu; - [DBus (name = "org.freedesktop.DBus.Properties")] - public interface FreeDesktopProperties : Object{ - public signal void PropertiesChanged(string source, HashTable<string, Variant?> changed_properties, - string[] invalid); +public interface FreeDesktopProperties : Object{ + public signal void PropertiesChanged (string source, HashTable<string, Variant?> changed_properties, + string[] invalid ); } /* @@ -33,13 +32,14 @@ public class Mpris2Controller : GLib.Object { public MprisRoot mpris2_root {get; construct;} public MprisPlayer player {get; construct;} + public MprisPlaylists playlists {get; construct;} public FreeDesktopProperties properties_interface {get; construct;} public PlayerController owner {get; construct;} - + public Mpris2Controller(PlayerController ctrl) { - GLib.Object(owner: ctrl); + GLib.Object(owner: ctrl); } construct{ @@ -50,10 +50,13 @@ public class Mpris2Controller : GLib.Object this.player = Bus.get_proxy_sync ( BusType.SESSION, this.owner.dbus_name, "/org/mpris/MediaPlayer2" ); + this.playlists = Bus.get_proxy_sync ( BusType.SESSION, + this.owner.dbus_name, + "/org/mpris/MediaPlayer2" ); this.properties_interface = Bus.get_proxy_sync ( BusType.SESSION, "org.freedesktop.Properties.PropertiesChanged", - "/org/mpris/MediaPlayer2" ); + "/org/mpris/MediaPlayer2" ); this.properties_interface.PropertiesChanged.connect ( property_changed_cb ); } catch (IOError e) { @@ -91,8 +94,19 @@ public class Mpris2Controller : GLib.Object metadata.property_set_bool ( MENUITEM_PROP_VISIBLE, metadata.populated(MetadataMenuitem.attributes_format())); } + Variant? playlist_v = changed_properties.lookup("ActivePlaylist"); + if ( playlist_v != null ){ + this.fetch_active_playlist(); + } } + public bool playlist_support() + { + // awaiting spec updates + // return this.mpris2_root.HasPlaylists; + return true; + } + private bool ensure_correct_playback_status(){ debug("TEST playback status = %s", this.player.PlaybackStatus); TransportMenuitem.state p = (TransportMenuitem.state)this.determine_play_state(this.player.PlaybackStatus); @@ -138,6 +152,7 @@ public class Mpris2Controller : GLib.Object GLib.HashTable<string, Value?>? cleaned_metadata = this.clean_metadata(); this.owner.custom_items[PlayerController.widget_order.METADATA].update(cleaned_metadata, MetadataMenuitem.attributes_format()); + this.fetch_playlists(); } public void transport_update(TransportMenuitem.action command) @@ -154,6 +169,47 @@ public class Mpris2Controller : GLib.Object } } + public void fetch_playlists() + { + if (this.playlists == null){ + warning("Playlists object is null"); + return; + } + PlaylistDetails[] current_playlists = this.playlists.GetPlaylists(0, + 10, + "Alphabetical", + false); + if( current_playlists != null ){ + debug( "Size of the playlist array = %i", current_playlists.length ); + PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem; + playlists_item.update(current_playlists); + /*foreach(PlaylistDetails detail in current_playlists){ + debug(" \n \n "); + debug( "Playlist Name = %s", detail.name); + debug( "Playlist path = %s", detail.path); + debug( "Playlist icon path = %s", detail.icon_path); + debug(" \n \n "); + }*/ + } + } + + public void fetch_active_playlist() + { + if (this.playlists == null && this.playlists.ActivePlaylist.valid == true){ + warning("Playlists object is null or we don't have an active playlist"); + return; + } + PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem; + playlists_item.update_active_playlist ( this.playlists.ActivePlaylist.details ); + /*debug(" \n \n "); + debug( "Active Playlist Name = %s", active_details.name); + debug( "Active Playlist path = %s", active_details.path); + debug( "Active Playlist icon path = %s", active_details.icon_path); + debug(" \n \n "); + */ + } + + public bool connected() { return (this.player != null && this.mpris2_root != null); @@ -165,4 +221,18 @@ public class Mpris2Controller : GLib.Object this.mpris2_root.Raise.begin(); } } + + public void activate_playlist (ObjectPath path) + { + if(this.playlists == null){ + warning("playlists mpris instance is null !"); + return; + } + try{ + this.playlists.ActivatePlaylist.begin(path); + } + catch(IOError e){ + debug("Could not activate playlist %s because %s", (string)path, e.message); + } + } }
\ No newline at end of file diff --git a/src/mpris2-interfaces.vala b/src/mpris2-interfaces.vala index ebea135..4f01c4c 100644 --- a/src/mpris2-interfaces.vala +++ b/src/mpris2-interfaces.vala @@ -1,6 +1,5 @@ /* Copyright 2010 Canonical Ltd. - Authors: Conor Curran <conor.curran@canonical.com> @@ -22,6 +21,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>. public interface MprisRoot : Object { // properties public abstract bool HasTracklist{owned get; set;} + //waiting for MPRIS approval + //public abstract bool HasPlaylist{owned get; set;} public abstract bool CanQuit{owned get; set;} public abstract bool CanRaise{owned get; set;} public abstract string Identity{owned get; set;} @@ -44,3 +45,30 @@ public interface MprisPlayer : Object { // signals public signal void Seeked(int64 new_position); } + +// Playlist container +public struct PlaylistDetails{ + public ObjectPath path; + public string name; + public string icon_path; +} +// Active playlist property container +public struct ActivePlaylistContainer{ + public bool valid; + public PlaylistDetails details; +} + +[DBus (name = "org.mpris.MediaPlayer2.Playlists")] +public interface MprisPlaylists : Object { + //properties + public abstract string[] Orderings{owned get; set;} + public abstract uint32 PlaylistCount{owned get; set;} + public abstract ActivePlaylistContainer ActivePlaylist {owned get; set;} + + //methods + public abstract async void ActivatePlaylist(ObjectPath playlist_id) throws IOError; + public abstract PlaylistDetails[] GetPlaylists ( uint32 index, + uint32 max_count, + string order, + bool reverse_order ) throws IOError; +}
\ No newline at end of file diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala index 327a775..239a40b 100644 --- a/src/music-player-bridge.vala +++ b/src/music-player-bridge.vala @@ -129,10 +129,10 @@ public class MusicPlayerBridge : GLib.Object public void set_root_menu_item ( Dbusmenu.Menuitem menu ) { this.root_menu = menu; + this.try_to_add_inactive_familiar_clients(); this.watcher = new Mpris2Watcher (); this.watcher.client_appeared += this.client_has_become_available; this.watcher.client_disappeared += this.client_has_vanished; - this.try_to_add_inactive_familiar_clients(); } private static AppInfo? create_app_info ( string path ) diff --git a/src/player-controller.vala b/src/player-controller.vala index 97f5303..24fd090 100644 --- a/src/player-controller.vala +++ b/src/player-controller.vala @@ -23,13 +23,14 @@ using Gee; public class PlayerController : GLib.Object { - public const int WIDGET_QUANTITY = 4; + public const int WIDGET_QUANTITY = 5; public static enum widget_order{ SEPARATOR, TITLE, METADATA, - TRANSPORT + TRANSPORT, + PLAYLISTS } public enum state{ @@ -135,12 +136,16 @@ public class PlayerController : GLib.Object false); this.custom_items[widget_order.METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, false); + this.custom_items[widget_order.PLAYLISTS].property_set_bool ( MENUITEM_PROP_ENABLED, + false ); return; } this.custom_items[widget_order.METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, this.custom_items[widget_order.METADATA].populated(MetadataMenuitem.attributes_format())); this.custom_items[widget_order.TRANSPORT].property_set_bool(MENUITEM_PROP_VISIBLE, true); + this.custom_items[widget_order.PLAYLISTS].property_set_bool(MENUITEM_PROP_VISIBLE, + true); } private void construct_widgets() @@ -159,9 +164,19 @@ public class PlayerController : GLib.Object // Transport item TransportMenuitem transport_item = new TransportMenuitem(this); this.custom_items.add(transport_item); - + + // Playlist item + PlaylistsMenuitem playlist_menuitem = new PlaylistsMenuitem(this); + this.custom_items.add(playlist_menuitem); + foreach(PlayerItem item in this.custom_items){ - root_menu.child_add_position(item, this.menu_offset + this.custom_items.index_of(item)); + if (this.custom_items.index_of(item) != 4) { + root_menu.child_add_position(item, this.menu_offset + this.custom_items.index_of(item)); + } + else{ + PlaylistsMenuitem playlists_menuitem = item as PlaylistsMenuitem; + root_menu.child_add_position(playlists_menuitem.root_item, this.menu_offset + this.custom_items.index_of(item)); + } } } @@ -184,11 +199,11 @@ public class PlayerController : GLib.Object if(this.mpris_bridge.connected() == true){ this.update_state(state.CONNECTED); TitleMenuitem title = this.custom_items[widget_order.TITLE] as TitleMenuitem; - title.toggle_active_triangle(true); + title.toggle_active_triangle(true); this.mpris_bridge.initial_update(); } else{ this.update_state(state.DISCONNECTED); } - } + } } diff --git a/src/player-item.vala b/src/player-item.vala index c80a17d..75f673b 100644 --- a/src/player-item.vala +++ b/src/player-item.vala @@ -28,7 +28,7 @@ public class PlayerItem : Dbusmenu.Menuitem public PlayerItem(string type) { - Object(item_type: type); + Object(item_type: type); } construct { @@ -54,7 +54,7 @@ public class PlayerItem : Dbusmenu.Menuitem if(data == null){ debug("PlayerItem::Update -> The hashtable was null - just leave it!"); return; - } + } foreach(string property in attributes){ string[] input_keys = property.split("-"); diff --git a/src/playlists-menu-item.vala b/src/playlists-menu-item.vala new file mode 100644 index 0000000..30ffdc7 --- /dev/null +++ b/src/playlists-menu-item.vala @@ -0,0 +1,76 @@ +/* +Copyright 2010 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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/>. +*/ + +using Dbusmenu; +using DbusmenuPlaylists; +using Gee; + +public class PlaylistsMenuitem : PlayerItem +{ + private HashMap<int, PlaylistDetails?> current_playlists; + public Menuitem root_item; + public PlaylistsMenuitem ( PlayerController parent ) + { + Object ( item_type: MENUITEM_TYPE, owner: parent ); + } + construct{ + this.current_playlists = new HashMap<int, PlaylistDetails?>(); + this.root_item = new Menuitem(); + this.root_item.property_set ( MENUITEM_PROP_LABEL, "Choose Playlist" ); + } + + public new void update (PlaylistDetails[] playlists) + { + foreach ( PlaylistDetails detail in playlists ){ + Dbusmenu.Menuitem menuitem = new Menuitem(); + menuitem.property_set (MENUITEM_PROP_LABEL, detail.name); + menuitem.property_set (MENUITEM_PROP_ICON_NAME, "source-smart-playlist"); + menuitem.property_set_bool (MENUITEM_PROP_VISIBLE, true); + menuitem.property_set_bool (MENUITEM_PROP_ENABLED, true); + this.current_playlists.set( menuitem.id, detail ); + menuitem.item_activated.connect(() => { + submenu_item_activated (menuitem.id );}); + this.root_item.child_append( menuitem ); + } + } + + public void update_active_playlist(PlaylistDetails detail) + { + this.root_item.property_set ( MENUITEM_PROP_LABEL, detail.name ); + } + + private void submenu_item_activated (int menu_item_id) + { + if(!this.current_playlists.has_key(menu_item_id)){ + warning( "item %i was activated but we don't have a corresponding playlist", + menu_item_id ); + return; + } + this.owner.mpris_bridge.activate_playlist ( this.current_playlists[menu_item_id].path ); + } + + public static HashSet<string> attributes_format() + { + HashSet<string> attrs = new HashSet<string>(); + attrs.add(MENUITEM_TITLE); + attrs.add(MENUITEM_PLAYLISTS); + return attrs; + } + +} diff --git a/src/sound-service.c b/src/sound-service.c index 98f1881..defcb94 100644 --- a/src/sound-service.c +++ b/src/sound-service.c @@ -40,8 +40,8 @@ service_shutdown (IndicatorService *service, gpointer user_data) { if (mainloop != NULL) { g_debug("Service shutdown !"); - close_pulse_activites(); - g_main_loop_quit(mainloop); + //close_pulse_activites(); + //g_main_loop_quit(mainloop); } return; } |