aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rw-r--r--debian/changelog7
-rw-r--r--debian/control4
-rwxr-xr-xdebian/rules1
-rw-r--r--src/Makefile.am3
-rw-r--r--src/mpris2-controller.vala48
-rw-r--r--src/mpris2-watcher.vala124
-rw-r--r--src/music-player-bridge.vala17
-rw-r--r--src/player-controller.vala19
9 files changed, 160 insertions, 66 deletions
diff --git a/configure.ac b/configure.ac
index c9227cd..928ffff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -55,7 +55,8 @@ PKG_CHECK_MODULES(SOUNDSERVICE, dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION
indicator >= $INDICATOR_REQUIRED_VERSION
indicate >= $INDICATE_REQUIRED_VERSION
gee-1.0
- gio-unix-2.0)
+ gio-unix-2.0
+ libxml-2.0)
AC_SUBST(SOUNDSERVICE_CFLAGS)
AC_SUBST(SOUNDERVICE_LIBS)
diff --git a/debian/changelog b/debian/changelog
index 0572e06..c694a7d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -7,7 +7,12 @@ indicator-sound (0.5.4-0ubuntu1) UNRELEASED; urgency=low
- The players list should be customizable (LP: #685725)
- gio-unix-2.0 checks (LP: #694828)
- Desktop file loading should not manually use full path (LP: #693824)
-
+ * debian/control
+ - Added build depends for libxml2-dev
+ - Added build depends for dh-autoreconf
+ * debian/rules
+ - Added autoreconf.mk
+
-- Ken VanDine <ken.vandine@canonical.com> Tue, 11 Jan 2011 14:38:36 -0600
indicator-sound (0.5.3-0ubuntu1) natty; urgency=low
diff --git a/debian/control b/debian/control
index dab145b..b6a62ad 100644
--- a/debian/control
+++ b/debian/control
@@ -18,7 +18,9 @@ Build-Depends: debhelper (>= 7),
libgconf2-dev,
libgee-dev,
libindicate-dev (>= 0.4.1),
- valac
+ libxml2-dev,
+ dh-autoreconf,
+ valac-0.12
Standards-Version: 3.9.1
Homepage: https://launchpad.net/indicator-sound
diff --git a/debian/rules b/debian/rules
index 0bae2ff..d778ba1 100755
--- a/debian/rules
+++ b/debian/rules
@@ -3,6 +3,7 @@
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/gnome.mk
include /usr/share/cdbs/1/rules/simple-patchsys.mk
+include /usr/share/cdbs/1/rules/autoreconf.mk
# List any files which are not installed
include /usr/share/cdbs/1/rules/utils.mk
diff --git a/src/Makefile.am b/src/Makefile.am
index 82830e1..57f52d4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -81,7 +81,8 @@ music_bridge_VALAFLAGS = \
--pkg common-defs \
--pkg gio-2.0 \
--pkg gio-unix-2.0 \
- --pkg gdk-pixbuf-2.0
+ --pkg gdk-pixbuf-2.0 \
+ --pkg libxml-2.0
$(MAINTAINER_VALAFLAGS)
diff --git a/src/mpris2-controller.vala b/src/mpris2-controller.vala
index 5f98541..c43f5fe 100644
--- a/src/mpris2-controller.vala
+++ b/src/mpris2-controller.vala
@@ -50,10 +50,11 @@ 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" );
-
+ if ( this.owner.use_playlists == true ){
+ 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" );
@@ -95,19 +96,10 @@ public class Mpris2Controller : GLib.Object
metadata.populated(MetadataMenuitem.attributes_format()));
}
Variant? playlist_v = changed_properties.lookup("ActivePlaylist");
- if ( playlist_v != null ){
+ if ( playlist_v != null && this.owner.use_playlists == true ){
this.fetch_active_playlist();
- //Timeout.add ( 200, fetch_active_playlist );
}
}
-
- public bool playlists_support_exist()
- {
- if (this.playlists == null) return false;
- uint32? count = this.playlists.PlaylistCount;
- if ( count == null || count <= 0 ) return false;
- return true;
- }
private bool ensure_correct_playback_status(){
debug("TEST playback status = %s", this.player.PlaybackStatus);
@@ -154,8 +146,12 @@ 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();
- this.fetch_active_playlist();
+
+ if ( this.owner.use_playlists == true ){
+ debug ("it thinks that there is a valid playlist interface");
+ this.fetch_playlists();
+ this.fetch_active_playlist();
+ }
}
public void transport_update(TransportMenuitem.action command)
@@ -174,8 +170,6 @@ public class Mpris2Controller : GLib.Object
public void fetch_playlists()
{
- if (this.playlists == null) return;
-
PlaylistDetails[] current_playlists = this.playlists.GetPlaylists(0,
10,
"Alphabetical",
@@ -185,13 +179,17 @@ public class Mpris2Controller : GLib.Object
PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem;
playlists_item.update(current_playlists);
}
+ else{
+ warning(" Playlists are on but its returning no current_playlists" );
+ this.owner.use_playlists = false;
+ }
return;
}
private void fetch_active_playlist()
- {
- if (this.playlists == null && this.playlists.ActivePlaylist.valid == false){
- warning("Playlists object is null or we don't have an active playlist");
+ {
+ if (this.playlists.ActivePlaylist.valid == false){
+ debug("We don't have an active playlist");
}
PlaylistsMenuitem playlists_item = this.owner.custom_items[PlayerController.widget_order.PLAYLISTS] as PlaylistsMenuitem;
playlists_item.update_active_playlist ( this.playlists.ActivePlaylist.details );
@@ -202,7 +200,7 @@ public class Mpris2Controller : GLib.Object
{
return (this.player != null && this.mpris2_root != null);
}
-
+
public void expose()
{
if(this.connected() == true){
@@ -212,15 +210,11 @@ public class Mpris2Controller : GLib.Object
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-watcher.vala b/src/mpris2-watcher.vala
index 7814975..9ef9b2f 100644
--- a/src/mpris2-watcher.vala
+++ b/src/mpris2-watcher.vala
@@ -17,6 +17,8 @@ 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 Xml;
+
[DBus (name = "org.freedesktop.DBus")]
public interface FreeDesktopObject: Object {
public abstract async string[] list_names() throws IOError;
@@ -25,6 +27,16 @@ public interface FreeDesktopObject: Object {
string new_owner );
}
+[DBus (name = "org.freedesktop.DBus.Introspectable")]
+public interface FreeDesktopIntrospectable: Object {
+ public abstract string Introspect() throws IOError;
+}
+
+public errordomain XmlError {
+ FILE_NOT_FOUND,
+ XML_DOCUMENT_EMPTY
+}
+
public class Mpris2Watcher : GLib.Object
{
private const string FREEDESKTOP_SERVICE = "org.freedesktop.DBus";
@@ -33,14 +45,17 @@ public class Mpris2Watcher : GLib.Object
private const string MPRIS_MEDIA_PLAYER_PATH = "/org/mpris/MediaPlayer2";
FreeDesktopObject fdesktop_obj;
+ FreeDesktopIntrospectable introspectable;
- public signal void client_appeared ( string desktop_file_name, string dbus_name );
+ public signal void client_appeared ( string desktop_file_name,
+ string dbus_name,
+ bool use_playlists );
public signal void client_disappeared ( string dbus_name );
public Mpris2Watcher ()
{
}
-
+
construct
{
try {
@@ -57,6 +72,29 @@ public class Mpris2Watcher : GLib.Object
}
}
+ // At startup check to see if there are clients up that we are interested in
+ // More relevant for development and daemon's like mpd.
+ private async void check_for_active_clients()
+ {
+ string[] interfaces;
+ try{
+ interfaces = yield this.fdesktop_obj.list_names();
+ }
+ catch ( IOError e) {
+ warning( "Mpris2watcher could fetch active interfaces at startup: %s",
+ e.message );
+ return;
+ }
+ foreach (var address in interfaces) {
+ if (address.has_prefix (MPRIS_PREFIX)){
+ MprisRoot? mpris2_root = this.create_mpris_root(address);
+ if (mpris2_root == null) return;
+ bool use_playlists = this.supports_playlists ( address );
+ client_appeared (mpris2_root.DesktopEntry, address, use_playlists);
+ }
+ }
+ }
+
private void name_changes_detected ( FreeDesktopObject dbus_obj,
string name,
string previous_owner,
@@ -65,24 +103,25 @@ public class Mpris2Watcher : GLib.Object
MprisRoot? mpris2_root = this.create_mpris_root(name);
if (mpris2_root == null) return;
-
+
if (previous_owner != "" && current_owner == "") {
debug ("Client '%s' gone down", name);
client_disappeared (name);
}
else if (previous_owner == "" && current_owner != "") {
debug ("Client '%s' has appeared", name);
- client_appeared (mpris2_root.DesktopEntry, name);
+ bool use_playlists = this.supports_playlists ( name );
+ client_appeared (mpris2_root.DesktopEntry, name, use_playlists);
}
}
- private MprisRoot? create_mpris_root(string name){
+ private MprisRoot? create_mpris_root ( string name ){
MprisRoot mpris2_root = null;
if ( name.has_prefix (MPRIS_PREFIX) ){
try {
mpris2_root = Bus.get_proxy_sync ( BusType.SESSION,
- name,
- MPRIS_MEDIA_PLAYER_PATH );
+ name,
+ MPRIS_MEDIA_PLAYER_PATH );
}
catch (IOError e){
warning( "Mpris2watcher could not create a root interface: %s",
@@ -91,26 +130,65 @@ public class Mpris2Watcher : GLib.Object
}
return mpris2_root;
}
-
- // At startup check to see if there are clients up that we are interested in
- // More relevant for development and daemon's like mpd.
- private async void check_for_active_clients()
+
+ private bool supports_playlists ( string name )
{
- string[] interfaces;
- try{
- interfaces = yield this.fdesktop_obj.list_names();
+ try {
+ /* The dbusproxy flag parameter is needed to ensure Banshee does not
+ blow up. I suspect the issue is that if you
+ try to instantiate a dbus object which does not have any properties
+ associated with it, gdbus will attempt to fetch the properties (this is
+ in the documentation) but the banshee mpris dbus object more than likely
+ causes a crash because it doesn't check for the presence of properties
+ before attempting to access them.
+ */
+ this.introspectable = Bus.get_proxy_sync ( BusType.SESSION,
+ name,
+ MPRIS_MEDIA_PLAYER_PATH,
+ GLib.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES);
+
+ var results = introspectable.Introspect();
+ return this.parse_interfaces (results);
}
- catch ( IOError e) {
- warning( "Mpris2watcher could fetch active interfaces at startup: %s",
+ catch (IOError e){
+ warning( "Could not create an introspectable object: %s",
e.message );
- return;
}
- foreach (var address in interfaces) {
- if (address.has_prefix (MPRIS_PREFIX)){
- MprisRoot? mpris2_root = this.create_mpris_root(address);
- if (mpris2_root == null) return;
- client_appeared (mpris2_root.DesktopEntry, address);
+ return false;
+ }
+
+ private bool parse_interfaces( string interface_info )
+ {
+ //parse the document from path
+ bool result = false;
+ Xml.Doc* xml_doc = Parser.parse_doc (interface_info);
+ if (xml_doc == null) {
+ warning ("Mpris2Watcher - parse-interfaces - failed to instantiate xml doc");
+ return false;
+ }
+ //get the root node. notice the dereferencing operator -> instead of .
+ Xml.Node* root_node = xml_doc->get_root_element ();
+ if (root_node == null) {
+ //free the document manually before throwing because the garbage collector can't work on pointers
+ delete xml_doc;
+ warning ("Mpris2Watcher - the interface info xml is empty");
+ return false;
+ }
+
+ //let's parse those nodes
+ for (Xml.Node* iter = root_node->children; iter != null; iter = iter->next) {
+ //spaces btw. tags are also nodes, discard them
+ if (iter->type != ElementType.ELEMENT_NODE){
+ continue;
+ }
+ Xml.Attr* attributes = iter->properties; //get the node's name
+ string interface_name = attributes->children->content;
+ debug ( "this dbus object has interface %s ", interface_name );
+ if ( interface_name == MPRIS_PREFIX.concat("Playlists")){
+ result = true;
}
}
- }
+ delete xml_doc;
+ return result;
+ }
} \ No newline at end of file
diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala
index c7391cf..7587684 100644
--- a/src/music-player-bridge.vala
+++ b/src/music-player-bridge.vala
@@ -59,8 +59,9 @@ public class MusicPlayerBridge : GLib.Object
null,
this.fetch_icon_name(desktop),
calculate_menu_position(),
+ null,
PlayerController.state.OFFLINE );
- this.registered_clients.set(mpris_key, ctrl);
+ this.registered_clients.set(mpris_key, ctrl);
}
}
@@ -74,7 +75,9 @@ public class MusicPlayerBridge : GLib.Object
}
}
- public void client_has_become_available ( string desktop, string dbus_name )
+ public void client_has_become_available ( string desktop,
+ string dbus_name,
+ bool use_playlists )
{
if (desktop == null || desktop == ""){
warning("Client %s attempting to register without desktop entry being set on the mpris root",
@@ -82,8 +85,9 @@ public class MusicPlayerBridge : GLib.Object
return;
}
if (desktop in this.settings_manager.fetch_blacklist()) {
- debug ("Client %s attempting to register but it has been blacklisted",
+ debug ("Client %s attempting to register but I'm afraid it is blacklisted",
desktop);
+ return;
}
debug ( "client_has_become_available %s", desktop );
@@ -103,6 +107,7 @@ public class MusicPlayerBridge : GLib.Object
dbus_name,
this.fetch_icon_name(desktop),
this.calculate_menu_position(),
+ use_playlists,
PlayerController.state.READY );
this.registered_clients.set ( mpris_key, ctrl );
debug ( "Have not seen this %s before, new controller created.", desktop );
@@ -110,6 +115,7 @@ public class MusicPlayerBridge : GLib.Object
debug ( "application added to the interested list" );
}
else{
+ this.registered_clients[mpris_key].use_playlists = use_playlists;
this.registered_clients[mpris_key].update_state ( PlayerController.state.READY );
this.registered_clients[mpris_key].activate ( dbus_name );
debug("Application has already registered - awaken the hibernation: %s \n", dbus_name );
@@ -118,7 +124,8 @@ public class MusicPlayerBridge : GLib.Object
public void client_has_vanished ( string mpris_root_interface )
{
- debug("MusicPlayerBridge -> on_server_removed with value %s", mpris_root_interface);
+ debug("MusicPlayerBridge -> client with dbus interface %s has vanished",
+ mpris_root_interface );
if (root_menu != null){
debug("attempt to remove %s", mpris_root_interface);
var mpris_key = determine_key ( mpris_root_interface );
@@ -128,7 +135,7 @@ public class MusicPlayerBridge : GLib.Object
}
}
}
-
+
public void set_root_menu_item ( Dbusmenu.Menuitem menu )
{
this.root_menu = menu;
diff --git a/src/player-controller.vala b/src/player-controller.vala
index 3922ecf..adefb65 100644
--- a/src/player-controller.vala
+++ b/src/player-controller.vala
@@ -45,19 +45,22 @@ public class PlayerController : GLib.Object
private Dbusmenu.Menuitem root_menu;
public string dbus_name { get; set;}
- public ArrayList<PlayerItem> custom_items;
+ public ArrayList<PlayerItem> custom_items;
public Mpris2Controller mpris_bridge;
public AppInfo? app_info { get; set;}
public int menu_offset { get; set;}
public string icon_name { get; set; }
-
+ public bool? use_playlists;
+
public PlayerController(Dbusmenu.Menuitem root,
GLib.AppInfo app,
string? dbus_name,
string icon_name,
int offset,
+ bool? use_playlists,
state initial_state)
{
+ this.use_playlists = use_playlists;
this.root_menu = root;
this.app_info = app;
this.dbus_name = dbus_name;
@@ -67,7 +70,7 @@ public class PlayerController : GLib.Object
this.menu_offset = offset;
this.construct_widgets();
this.establish_mpris_connection();
- this.update_layout();
+ this.update_layout();
}
public void update_state(state new_state)
@@ -81,7 +84,7 @@ public class PlayerController : GLib.Object
public void activate( string dbus_name )
{
this.dbus_name = dbus_name;
- this.establish_mpris_connection();
+ this.establish_mpris_connection();
}
/*
@@ -109,6 +112,9 @@ public class PlayerController : GLib.Object
debug("establish_mpris_connection - Not ready to connect");
return;
}
+ debug ( " establish mpris connection - use playlists value = %s ",
+ this.use_playlists.to_string() );
+
this.mpris_bridge = new Mpris2Controller(this);
this.determine_state();
}
@@ -148,7 +154,7 @@ public class PlayerController : GLib.Object
this.custom_items[widget_order.TRANSPORT].property_set_bool(MENUITEM_PROP_VISIBLE,
true);
playlists_menuitem.root_item.property_set_bool ( MENUITEM_PROP_VISIBLE,
- this.mpris_bridge.playlists_support_exist() );
+ this.use_playlists );
}
private void construct_widgets()
@@ -181,9 +187,8 @@ public class PlayerController : GLib.Object
root_menu.child_add_position(playlists_menuitem.root_item, this.menu_offset + this.custom_items.index_of(item));
}
}
- }
+ }
-
private static string format_player_name(owned string app_info_name)
{
string result = app_info_name.down().strip();