aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am11
-rw-r--r--src/common-defs.h2
-rw-r--r--src/mpris2-watcher.vala2
-rw-r--r--src/music-player-bridge.vala27
-rw-r--r--src/player-controller.vala43
-rw-r--r--src/playlists-menu-item.vala1
-rw-r--r--src/sound-service-dbus.c56
-rw-r--r--src/sound-service-marshal.list2
-rw-r--r--src/sound-service.c49
-rw-r--r--src/sound-service.xml11
-rw-r--r--src/specific-items-manager.vala107
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");
+ }
+
+}