diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 11 | ||||
-rw-r--r-- | src/common-defs.h | 2 | ||||
-rw-r--r-- | src/mpris2-watcher.vala | 2 | ||||
-rw-r--r-- | src/music-player-bridge.vala | 27 | ||||
-rw-r--r-- | src/player-controller.vala | 43 | ||||
-rw-r--r-- | src/playlists-menu-item.vala | 1 | ||||
-rw-r--r-- | src/sound-service-dbus.c | 56 | ||||
-rw-r--r-- | src/sound-service-marshal.list | 2 | ||||
-rw-r--r-- | src/sound-service.c | 49 | ||||
-rw-r--r-- | src/sound-service.xml | 11 | ||||
-rw-r--r-- | src/specific-items-manager.vala | 107 |
11 files changed, 287 insertions, 24 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 60c7249..2381429 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,6 +32,7 @@ libsoundmenu_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Werror -DG_LOG_DOMAIN=\"Indicat libsoundmenu_la_LIBADD = $(APPLET_LIBS) libsoundmenu_la_LDFLAGS = -module -avoid-version + checkxml: $(srcdir)/sound-service.xml @xmllint -valid -noout $< @echo $< checks out ok @@ -41,6 +42,9 @@ checkxml: $(srcdir)/sound-service.xml # Sound Service #################################################################### +glib_marshal_list = sound-service-marshal.list +glib_marshal_prefix = _sound_service_marshal + ##################### # Sound service vala @@ -48,6 +52,7 @@ checkxml: $(srcdir)/sound-service.xml music_bridge_VALASOURCES = \ music-player-bridge.vala \ transport-menu-item.vala \ + specific-items-manager.vala \ metadata-menu-item.vala \ player-controller.vala \ mpris2-interfaces.vala \ @@ -107,6 +112,8 @@ indicator_sound_service_SOURCES = \ mute-menu-item.c \ gen-sound-service.xml.h \ gen-sound-service.xml.c \ + sound-service-marshal.c \ + sound-service-marshal.h \ $(music_bridge_VALASOURCES:.vala=.c) indicator_sound_service_CFLAGS = $(PULSEAUDIO_CFLAGS) $(SOUNDSERVICE_CFLAGS) $(GCONF_CFLAGS) -DLIBEXECDIR=\"$(libexecdir)\" -Wall @@ -147,3 +154,7 @@ BUILT_SOURCES = \ CLEANFILES = \ $(BUILT_SOURCES) + +DISTCLEANFILES = + +include $(top_srcdir)/Makefile.am.marshal diff --git a/src/common-defs.h b/src/common-defs.h index b1b001e..a20fb03 100644 --- a/src/common-defs.h +++ b/src/common-defs.h @@ -67,6 +67,8 @@ typedef enum { #define DBUSMENU_TRANSPORT_MENUITEM_TYPE "x-canonical-sound-menu-player-transport-type" #define DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE "x-canonical-sound-menu-player-transport-state" +#define DBUSMENU_TRACK_SPECIFIC_MENUITEM_TYPE "x-canonical-sound-menu-player-track-specific-type" + #define DBUSMENU_METADATA_MENUITEM_TYPE "x-canonical-sound-menu-player-metadata-type" #define DBUSMENU_METADATA_MENUITEM_ARTIST "x-canonical-sound-menu-player-metadata-xesam:artist" #define DBUSMENU_METADATA_MENUITEM_TITLE "x-canonical-sound-menu-player-metadata-xesam:title" diff --git a/src/mpris2-watcher.vala b/src/mpris2-watcher.vala index d508959..06ccb6e 100644 --- a/src/mpris2-watcher.vala +++ b/src/mpris2-watcher.vala @@ -38,7 +38,7 @@ public class Mpris2Watcher : GLib.Object this.fdesktop_obj = Bus.get_proxy_sync ( BusType.SESSION, FREEDESKTOP_SERVICE, FREEDESKTOP_OBJECT, - DBusProxyFlags.DO_NOT_LOAD_PROPERTIES ); + DBusProxyFlags.DO_NOT_LOAD_PROPERTIES ); this.fdesktop_obj.name_owner_changed.connect (this.name_changes_detected); this.check_for_active_clients.begin(); } diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala index b5932fa..72c9bdb 100644 --- a/src/music-player-bridge.vala +++ b/src/music-player-bridge.vala @@ -27,7 +27,7 @@ public class MusicPlayerBridge : GLib.Object private SettingsManager settings_manager; private Dbusmenu.Menuitem root_menu; - private HashMap<string, PlayerController> registered_clients; + private HashMap<string, PlayerController> registered_clients; private Mpris2Watcher watcher; public MusicPlayerBridge() @@ -158,10 +158,31 @@ public class MusicPlayerBridge : GLib.Object this.watcher.client_disappeared.connect (this.client_has_vanished); } - private static AppInfo? create_app_info ( string desktop ) + public void enable_player_specific_items_for_client (string object_path, + string desktop_id) { - DesktopAppInfo info = new DesktopAppInfo ( desktop ) ; + var mpris_key = determine_key ( desktop_id ); + if (this.registered_clients.has_key (mpris_key) == false){ + warning ("we don't have a client with desktop id %s registered", desktop_id); + return; + } + this.registered_clients[mpris_key].enable_player_specific_items(object_path); + } + public void enable_track_specific_items_for_client (string object_path, + string desktop_id) + { + var mpris_key = determine_key ( desktop_id ); + if (this.registered_clients.has_key (mpris_key) == false){ + warning ("we don't have a client with desktop id %s registered", desktop_id); + return; + } + this.registered_clients[mpris_key].enable_track_specific_items(object_path); + } + + private static AppInfo? create_app_info ( string desktop ) + { + DesktopAppInfo info = new DesktopAppInfo ( desktop ); if ( desktop == null || info == null ){ warning ( "Could not create a desktopappinfo instance from app: %s", desktop ); return null; diff --git a/src/player-controller.vala b/src/player-controller.vala index a08f692..ced7d96 100644 --- a/src/player-controller.vala +++ b/src/player-controller.vala @@ -1,5 +1,4 @@ /* -This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel. Copyright 2010 Canonical Ltd. Authors: @@ -42,7 +41,7 @@ public class PlayerController : GLib.Object public int current_state = state.OFFLINE; - private Dbusmenu.Menuitem root_menu; + public Dbusmenu.Menuitem root_menu; public string dbus_name { get; set;} public ArrayList<PlayerItem> custom_items; public Mpris2Controller mpris_bridge; @@ -50,6 +49,8 @@ public class PlayerController : GLib.Object public int menu_offset { get; set;} public string icon_name { get; set; } public bool? use_playlists; + private SpecificItemsManager track_specific_mgr; + private SpecificItemsManager player_specific_mgr; public PlayerController(Dbusmenu.Menuitem root, GLib.AppInfo app, @@ -105,7 +106,33 @@ public class PlayerController : GLib.Object error.message ); } } + + public void enable_track_specific_items (string object_path) + { + if (this.track_specific_mgr == null){ + track_specific_mgr = new SpecificItemsManager (this, + object_path, + SpecificItemsManager.category.TRACK); + } + } + + public void enable_player_specific_items (string object_path) + { + if (this.player_specific_mgr == null){ + player_specific_mgr = new SpecificItemsManager (this, + object_path, + SpecificItemsManager.category.PLAYER); + } + } + public int track_specific_count () + { + if (this.track_specific_mgr == null) { + return 0; + } + return this.track_specific_mgr.proxy_items.size; + } + private void establish_mpris_connection() { if(this.current_state != state.READY || this.dbus_name == null ){ @@ -114,9 +141,8 @@ public class PlayerController : GLib.Object } debug ( " establish mpris connection - use playlists value = %s ", this.use_playlists.to_string() ); - - this.mpris_bridge = new Mpris2Controller(this); - this.determine_state(); + this.mpris_bridge = new Mpris2Controller (this); + this.determine_state (); } public void remove_from_menu() @@ -186,16 +212,17 @@ public class PlayerController : GLib.Object this.custom_items.add(playlist_menuitem); foreach(PlayerItem item in this.custom_items){ - if (this.custom_items.index_of(item) == 3) { + if (this.custom_items.index_of(item) == 4) { PlaylistsMenuitem playlists_menuitem = item as PlaylistsMenuitem; root_menu.child_add_position(playlists_menuitem.root_item, this.menu_offset + this.custom_items.index_of(item)); } else{ - root_menu.child_add_position(item, this.menu_offset + this.custom_items.index_of(item)); + root_menu.child_add_position (item, + this.menu_offset + this.custom_items.index_of(item)); } } } - + private void determine_state() { if(this.mpris_bridge.connected() == true){ diff --git a/src/playlists-menu-item.vala b/src/playlists-menu-item.vala index 7faa214..452a586 100644 --- a/src/playlists-menu-item.vala +++ b/src/playlists-menu-item.vala @@ -39,7 +39,6 @@ public class PlaylistsMenuitem : PlayerItem this.root_item = new Menuitem(); this.root_item.property_set ( MENUITEM_PROP_LABEL, _("Choose Playlist") ); this.root_item.property_set ( MENUITEM_PATH, "" ); - } public new void update (PlaylistDetails[] playlists) diff --git a/src/sound-service-dbus.c b/src/sound-service-dbus.c index 0db03d4..b69f081 100644 --- a/src/sound-service-dbus.c +++ b/src/sound-service-dbus.c @@ -32,6 +32,7 @@ #include "device.h" #include "gen-sound-service.xml.h" #include "dbus-shared-names.h" +#include "sound-service-marshal.h" // DBUS methods static void bus_method_call (GDBusConnection * connection, @@ -59,6 +60,14 @@ struct _SoundServiceDbusPrivate { gboolean greeter_mode; }; +enum { + TRACK_SPECIFIC_ITEM, + PLAYER_SPECIFIC_ITEM, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + static GDBusNodeInfo * node_info = NULL; static GDBusInterfaceInfo * interface_info = NULL; @@ -111,6 +120,22 @@ sound_service_dbus_class_init (SoundServiceDbusClass *klass) g_error("Unable to find interface '" INDICATOR_SOUND_DBUS_INTERFACE "'"); } } + signals[TRACK_SPECIFIC_ITEM] = g_signal_new("track-specific-item-requested", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + _sound_service_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, G_TYPE_STRING, + G_TYPE_STRING); + signals[PLAYER_SPECIFIC_ITEM] = g_signal_new("player-specific-item-requested", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + _sound_service_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, G_TYPE_STRING, + G_TYPE_STRING); } static void @@ -150,7 +175,6 @@ sound_service_dbus_create_root_item (SoundServiceDbus* self, gboolean greeter_mo SoundServiceDbusPrivate * priv = SOUND_SERVICE_DBUS_GET_PRIVATE(self); priv->greeter_mode = greeter_mode; priv->root_menuitem = dbusmenu_menuitem_new(); - //g_debug("Root ID: %d", dbusmenu_menuitem_get_id(priv->root_menuitem)); DbusmenuServer *server = dbusmenu_server_new (INDICATOR_SOUND_MENU_DBUS_OBJECT_PATH); dbusmenu_server_set_root (server, priv->root_menuitem); g_object_unref (priv->root_menuitem); @@ -301,6 +325,36 @@ bus_method_call (GDBusConnection * connection, player_name); retval = g_variant_new ("(b)", result); } + else if (g_strcmp0(method, "EnableTrackSpecificItems") == 0) { + g_debug ("EnableTrackSpecificItems"); + gchar* player_object_path; + gchar* player_id; + g_variant_get (params, "(os)", &player_object_path, &player_id); + //g_debug ("object path = %s and id = %s", player_object_path, player_id); + g_signal_emit (service, + signals[TRACK_SPECIFIC_ITEM], + 0, + player_object_path, + player_id); + g_free (player_object_path); + g_free (player_id); + + } + else if (g_strcmp0(method, "EnablePlayerSpecificItems") == 0) { + gchar* player_object_path; + gchar* player_id; + g_variant_get (params, "(os)", &player_object_path, &player_id); + g_debug ("PLayer specific item - object path = %s and id = %s", + player_object_path, + player_id); + g_signal_emit (service, + signals[PLAYER_SPECIFIC_ITEM], + 0, + player_object_path, + player_id); + g_free (player_object_path); + g_free (player_id); + } else { g_warning("Calling method '%s' on the sound service but it's unknown", method); } diff --git a/src/sound-service-marshal.list b/src/sound-service-marshal.list new file mode 100644 index 0000000..4c756d4 --- /dev/null +++ b/src/sound-service-marshal.list @@ -0,0 +1,2 @@ +VOID:STRING,STRING + diff --git a/src/sound-service.c b/src/sound-service.c index a368081..0170f81 100644 --- a/src/sound-service.c +++ b/src/sound-service.c @@ -17,19 +17,18 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <locale.h> + #include "sound-service.h" #include "pulseaudio-mgr.h" #include "sound-service-dbus.h" #include "music-player-bridge.h" -#include <locale.h> - static GMainLoop *mainloop = NULL; - -/**********************************************************************************************************************/ +static MusicPlayerBridge* player_bridge = NULL; +/***********************************************************************************************************/ // Init and exit functions /**********************************************************************************************************************/ - /** service_shutdown: When the service interface starts to shutdown, we @@ -55,6 +54,32 @@ get_greeter_mode (void) return (g_strcmp0(var, "1") == 0); } +void +on_player_specific_item_requested (SoundServiceDbus* sound_service, + const gchar* desktop_id, + const gchar* player_object_path, + gpointer userdata) +{ + if (player_bridge != NULL){ + music_player_bridge_enable_player_specific_items_for_client (player_bridge, + desktop_id, + player_object_path); + } +} + +void +on_track_specific_item_requested (SoundServiceDbus* sound_service, + const gchar* desktop_id, + const gchar* player_object_path, + gpointer userdata) +{ + if (player_bridge != NULL){ + music_player_bridge_enable_track_specific_items_for_client (player_bridge, + desktop_id, + player_object_path); + } +} + /** main: **/ @@ -68,20 +93,26 @@ main (int argc, char ** argv) bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); setlocale (LC_ALL, ""); - IndicatorService *service = indicator_service_new_version(INDICATOR_SOUND_DBUS_NAME, - INDICATOR_SOUND_DBUS_VERSION); + IndicatorService *service = indicator_service_new_version (INDICATOR_SOUND_DBUS_NAME, + INDICATOR_SOUND_DBUS_VERSION); g_signal_connect(G_OBJECT(service), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), NULL); SoundServiceDbus* sound_service = g_object_new(SOUND_SERVICE_DBUS_TYPE, NULL); + g_signal_connect(G_OBJECT(sound_service), + "track-specific-item-requested", + G_CALLBACK(on_track_specific_item_requested), NULL); + g_signal_connect(G_OBJECT(sound_service), + "player-specific-item-requested", + G_CALLBACK(on_player_specific_item_requested), NULL); greeter_mode = get_greeter_mode(); DbusmenuMenuitem* root_menuitem = sound_service_dbus_create_root_item(sound_service, greeter_mode); if (!greeter_mode) { - MusicPlayerBridge* server = music_player_bridge_new(); - music_player_bridge_set_root_menu_item(server, root_menuitem); + player_bridge = music_player_bridge_new(); + music_player_bridge_set_root_menu_item(player_bridge, root_menuitem); } // Run the loop diff --git a/src/sound-service.xml b/src/sound-service.xml index 517088e..796fa22 100644 --- a/src/sound-service.xml +++ b/src/sound-service.xml @@ -12,11 +12,20 @@ <arg type='s' name='player_desktop_name' direction="in"/> <arg type='b' name='result' direction="out"/> </method> - <method name = "GetSoundState"> <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> <arg type='i' name='current_state' direction="out"/> </method> + <method name = "EnableTrackSpecificItems"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <arg type='o' name='player_object_path' direction="in"/> + <arg type='s' name='player_desktop_id' direction="in"/> + </method> + <method name = "EnablePlayerSpecificItems"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <arg type='o' name='player_object_path' direction="in"/> + <arg type='s' name='player_desktop_id' direction="in"/> + </method> <signal name="SoundStateUpdate"> <arg name="new_state" type="i" direction="out"/> </signal> diff --git a/src/specific-items-manager.vala b/src/specific-items-manager.vala new file mode 100644 index 0000000..d26199f --- /dev/null +++ b/src/specific-items-manager.vala @@ -0,0 +1,107 @@ +/* +Copyright 2011 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 Gee; + +public class SpecificItemsManager : GLib.Object +{ + public static enum category{ + TRACK, + PLAYER + } + + private PlayerController owner {get; set;} + private string dbus_path; + private Dbusmenu.Client client; + public Gee.ArrayList<Dbusmenu.MenuitemProxy> proxy_items {get; construct;} + private int of_type; + + public SpecificItemsManager (PlayerController controller, + string path, + category which_type) + { + this.of_type = which_type; + this.owner = controller; + this.dbus_path = path; + this.client = new Dbusmenu.Client (this.owner.dbus_name, this.dbus_path); + this.client.root_changed.connect (on_root_changed); + } + construct{ + this.proxy_items = new ArrayList<Dbusmenu.MenuitemProxy>(); + } + + private int figure_out_positioning() + { + int result = 0 ; + if (this.of_type == category.TRACK){ + result = this.owner.menu_offset + 4 + this.proxy_items.size; + } + else if (this.of_type == category.PLAYER){ + int pos = this.owner.menu_offset + 4 + this.owner.track_specific_count(); + pos += this.owner.use_playlists == true ? 1 : 0; + result = pos; + } + debug ("!!!!! Menu pos of type %i is = %i", this.of_type, result); + return result; + } + + private void on_root_changed (GLib.Object? newroot) + { + if (newroot == null){ + debug ("root disappeared -remove proxyitems"); + foreach(var p in proxy_items){ + this.owner.root_menu.child_delete (p); + } + this.proxy_items.clear(); + debug ("array list size is now %i", this.proxy_items.size); + //this.proxy_items = new ArrayList<Dbusmenu.MenuitemProxy>(); + return; + } + + Dbusmenu.Menuitem? root = this.client.get_root(); + root.child_added.connect (on_child_added); + root.child_removed.connect (on_child_removed); + + // Fetch what children are there already. + GLib.List<weak void*> children = root.get_children().copy(); + + foreach (void* child in children) { + int pos = figure_out_positioning(); + unowned Dbusmenu.Menuitem item = (Dbusmenu.Menuitem)child; + Dbusmenu.MenuitemProxy proxy = new Dbusmenu.MenuitemProxy(item); + proxy_items.add (proxy); + debug ("Proxy item of label = %s added to collection", + item.property_get (MENUITEM_PROP_LABEL)); + this.owner.root_menu.child_add_position (proxy, pos); + + } + } + + private void on_child_added (GLib.Object child, uint position) + { + debug ("On child added Specific root node"); + } + + private void on_child_removed (GLib.Object child) + { + debug ("On child removed Specific root node"); + } + +} |