← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~cjcurran/indicator-sound/mpris-backend into lp:indicator-sound

 

Conor Curran has proposed merging lp:~cjcurran/indicator-sound/mpris-backend into lp:indicator-sound.

Requested reviews:
  Indicator Applet Developers (indicator-applet-developers)


Introduces MPRIS V1 and V2 backends to the service along with the corresponding custom dbusmenuitem objects inorder to facilitate functional requirements. UI needs alot of work but back end for remote player control is mainly taken care of (once I can overcome some Vala problems ...)
-- 
https://code.launchpad.net/~cjcurran/indicator-sound/mpris-backend/+merge/27847
Your team ayatana-commits is subscribed to branch lp:indicator-sound.
=== modified file 'src/Makefile.am'
--- src/Makefile.am	2010-06-14 18:48:11 +0000
+++ src/Makefile.am	2010-06-17 15:45:41 +0000
@@ -54,7 +54,9 @@
 	music-player-bridge.vala \
 	transport-menu-item.vala \
 	metadata-menu-item.vala \
-	player-controller.vala
+	player-controller.vala \
+	mpris-controller-v2.vala \
+	mpris-controller.vala
 
 music_bridge_VALAFLAGS = \
   --ccode \

=== modified file 'src/metadata-menu-item.vala'
--- src/metadata-menu-item.vala	2010-06-14 10:07:28 +0000
+++ src/metadata-menu-item.vala	2010-06-17 15:45:41 +0000
@@ -13,15 +13,26 @@
 	public MetadataMenuitem()
   {
 		this.property_set(MENUITEM_PROP_TYPE, DBUSMENU_METADATA_MENUITEM_TYPE);
-		this.property_set(DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST, "Sonnamble");
-		this.property_set(DBUSMENU_METADATA_MENUITEM_TEXT_PIECE, "Nocturne");
-		this.property_set(DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER, "Seven Months in E minor");
-		this.property_set(DBUSMENU_METADATA_MENUITEM_IMAGE_PATH, "/home/ronoc/Desktop/Sonnamble/Sonnamble_CD.jpg");
-
-		debug("image_path property set %s:", this.property_get(DBUSMENU_METADATA_MENUITEM_IMAGE_PATH));
-
-	}
-
+	}
+
+	public void update(HashMap<string, string> data)
+	{
+		this.property_set(DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST, data.get("artist").strip());
+		this.property_set(DBUSMENU_METADATA_MENUITEM_TEXT_PIECE, data.get("title").strip());
+		this.property_set(DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER, data.get("album").strip());
+		this.property_set(DBUSMENU_METADATA_MENUITEM_IMAGE_PATH, sanitize_image_path(data.get("arturl")));
+	}
+
+	public static string sanitize_image_path(string path)
+	{
+		string result = path.strip();
+		if(result.contains("file:///")){
+			result = result.slice(7, result.len());		                   
+		}
+		debug("Sanitize image path - result = %s", result);
+		return result;
+	}
+		
 	public override void handle_event(string name, GLib.Value input_value, uint timestamp)
 	{
 		debug("MetadataItem -> handle event caught!");

=== modified file 'src/metadata-widget.c'
--- src/metadata-widget.c	2010-06-14 18:48:11 +0000
+++ src/metadata-widget.c	2010-06-17 15:45:41 +0000
@@ -34,7 +34,7 @@
 {
 	GtkWidget* hbox;
 	GtkWidget* album_art;
-  gchar* 		 our_path;
+  gchar* 		 image_path;
 	GtkWidget* artist_label;
 	GtkWidget* piece_label;
 	GtkWidget* container_label;	
@@ -53,10 +53,10 @@
 static gboolean metadata_widget_button_release_event (GtkWidget *menuitem, 
                                   										GdkEventButton *event);
 // Dbusmenuitem properties update callback
-static void metadata_widget_update_state(gchar * property, 
-                                       GValue * value,
-                                       gpointer userdata);
-//static void update_content( 
+static void metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property, 
+                                       GValue* value, gpointer userdata);
+
+static void update_album_art(MetadataWidget* self);
 
 
 G_DEFINE_TYPE (MetadataWidget, metadata_widget, GTK_TYPE_MENU_ITEM);
@@ -92,14 +92,9 @@
 	priv->hbox = hbox;
 	
 	// image
-	const gchar* path = dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_IMAGE_PATH);
-	g_debug("MetadataWidget:init - path = %s", path);
-	priv->our_path = g_strdup(path);
-	GdkPixbuf* pixbuf;
-	pixbuf=gdk_pixbuf_new_from_file(path, NULL);
-  pixbuf=gdk_pixbuf_scale_simple(pixbuf,60,60,GDK_INTERP_BILINEAR);
-	priv->album_art = gtk_image_new_from_pixbuf(pixbuf);
-	g_object_unref(pixbuf);
+	priv->album_art = gtk_image_new();
+	priv->image_path = g_strdup(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_IMAGE_PATH));
+	update_album_art(self);	
 	gtk_box_pack_start (GTK_BOX (priv->hbox), priv->album_art, FALSE, FALSE, 0);	
 	GtkWidget* vbox = gtk_vbox_new(TRUE, 0);
 
@@ -107,24 +102,28 @@
 	GtkWidget* artist;
 	artist = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST));
 	priv->artist_label = artist;
-	gtk_box_pack_start (GTK_BOX (vbox), priv->artist_label, FALSE, FALSE, 0);	
+	
 	
 	// piece
 	GtkWidget* piece;
 	piece = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_PIECE));
 	priv->piece_label =  piece;
-	gtk_box_pack_start (GTK_BOX (vbox), priv->piece_label, FALSE, FALSE, 0);	
-	
+
+
 	// container
 	GtkWidget* container;
 	container = gtk_label_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER));
 	priv->container_label = container;
+
+	// Pack in the right order
+	gtk_box_pack_start (GTK_BOX (vbox), priv->piece_label, FALSE, FALSE, 0);	
+	gtk_box_pack_start (GTK_BOX (vbox), priv->artist_label, FALSE, FALSE, 0);	
 	gtk_box_pack_start (GTK_BOX (vbox), priv->container_label, FALSE, FALSE, 0);	
 	
 	gtk_box_pack_start (GTK_BOX (priv->hbox), vbox, FALSE, FALSE, 0);	
 
 	g_signal_connect(G_OBJECT(twin_item), "property-changed", 
-	                 G_CALLBACK(metadata_widget_update_state), self);
+	                 G_CALLBACK(metadata_widget_property_update), self);
 	gtk_widget_show_all (priv->hbox);
   gtk_container_add (GTK_CONTAINER (self), hbox);
 	
@@ -159,10 +158,40 @@
 	return TRUE;
 }
 
-static void metadata_widget_update_state(gchar *property, GValue *value, gpointer userdata)
+static void 
+metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property, 
+                                       GValue* value, gpointer userdata)
 {
-	g_debug("metadata_widget_update_state - with property  %s", property);  
-}
+	MetadataWidget* mitem = METADATA_WIDGET(userdata);
+	MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(mitem);
+	
+	if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_ARTIST, property) == 0){  
+		gtk_label_set_text(GTK_LABEL(priv->artist_label), g_value_get_string(value));
+	}
+	else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_PIECE, property) == 0){  
+		gtk_label_set_text(GTK_LABEL(priv->piece_label), g_value_get_string(value));
+	}	
+	else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_TEXT_CONTAINER, property) == 0){  
+		gtk_label_set_text(GTK_LABEL(priv->container_label), g_value_get_string(value));
+	}	
+	else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_IMAGE_PATH, property) == 0){
+		priv->image_path = g_strdup(g_value_get_string(value));
+		if(priv->image_path != NULL){			
+			update_album_art(mitem);
+		}
+	}		
+}
+
+static void update_album_art(MetadataWidget* self){
+	MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(self);	
+	GdkPixbuf* pixbuf;
+	pixbuf = gdk_pixbuf_new_from_file(priv->image_path, NULL);
+  pixbuf = gdk_pixbuf_scale_simple(pixbuf,60, 60,GDK_INTERP_BILINEAR);
+	g_debug("attempting to set the image with path %s", priv->image_path);
+	gtk_image_set_from_pixbuf(GTK_IMAGE(priv->album_art), pixbuf);
+	g_object_unref(pixbuf);	
+}
+
 
  /**
  * transport_new:

=== modified file 'src/metadata-widget.h'
--- src/metadata-widget.h	2010-06-11 14:09:07 +0000
+++ src/metadata-widget.h	2010-06-17 15:45:41 +0000
@@ -25,7 +25,7 @@
 G_BEGIN_DECLS
 
 #define METADATA_WIDGET_TYPE            (metadata_widget_get_type ())
-#define METADATA_WIDGET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), METADATA_WIDGET_TYPE, TransportBar))
+#define METADATA_WIDGET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), METADATA_WIDGET_TYPE, MetadataWidget))
 #define METADATA_WIDGET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), METADATA_WIDGET_TYPE, MetadataWidgetClass))
 #define IS_METADATA_WIDGET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), METADATA_WIDGET_TYPE))
 #define IS_METADATA_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), METADATA_WIDGET_TYPE))

=== added file 'src/mpris-controller-v2.vala'
--- src/mpris-controller-v2.vala	1970-01-01 00:00:00 +0000
+++ src/mpris-controller-v2.vala	2010-06-17 15:45:41 +0000
@@ -0,0 +1,28 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+Copyright 2010 Canonical Ltd.
+
+Authors:
+    Conor Curran <conor.curran@xxxxxxxxxxxxx>
+
+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 Gee;
+
+public class MprisControllerV2 : MprisController
+{		
+	public MprisControllerV2(string name, PlayerController controller){
+		base(name, controller, "org.mpris.MediaPlayer.Player");
+	}
+
+}

=== added file 'src/mpris-controller.vala'
--- src/mpris-controller.vala	1970-01-01 00:00:00 +0000
+++ src/mpris-controller.vala	2010-06-17 15:45:41 +0000
@@ -0,0 +1,101 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+Copyright 2010 Canonical Ltd.
+
+Authors:
+    Conor Curran <conor.curran@xxxxxxxxxxxxx>
+
+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 Gee;
+
+
+public class MprisController : GLib.Object
+{
+  private DBus.Connection connection;
+  public dynamic DBus.Object mpris_player;
+	private PlayerController controller;
+  struct status {
+    public int32 playback;
+    public int32 shuffle;
+    public int32 repeat;
+    public int32 endless;
+  }
+		
+	
+	public MprisController(string name, PlayerController controller, string mpris_interface="org.freedesktop.MediaPlayer"){
+    try {
+      this.connection = DBus.Bus.get (DBus.BusType.SESSION);
+    } catch (Error e) {
+      error("Problems connecting to the session bus - %s", e.message);
+    }		
+		this.controller = controller;
+		this.mpris_player = this.connection.get_object ("org.mpris.".concat(name.down()) , "/Player", mpris_interface);				
+    this.mpris_player.TrackChange += onTrackChange;	
+    this.mpris_player.StatusChange += onStatusChange;		
+		this.controller.update_playing_info(get_track_data());
+	}
+
+	public HashMap<string, string> get_track_data()
+	{
+		return format_metadata(this.mpris_player.GetMetadata());
+	}
+
+	private void onTrackChange(dynamic DBus.Object mpris_client, HashTable<string,Value?> ht)
+	{
+		this.controller.update_playing_info(format_metadata(ht));
+	}
+
+	/**
+	 * TRUE  => Playing
+	 * FALSE => Paused
+	 **/
+	public void toggle_playback(bool state)
+	{
+		if(state == true){
+			debug("about to play");
+			this.mpris_player.Play();				
+		}
+		else{
+			debug("about to pause");
+			this.mpris_player.Pause();						
+		}		
+	}
+	
+	private void onStatusChange(dynamic DBus.Object mpris_client, status st)
+  {
+    debug("onStatusChange - signal received");	
+		//ValueArray a = new ValueArray(4);
+		//Value v = new Value(typeof(int32));          
+		//v.set_int(st.playback);
+		//a.append(v);
+		//debug("onStatusChange - play %i", a.get_nth(0).get_int());
+		//int playback = (ValueArray)st.get_nth(0).get_int();
+		//int shuffle = ar.get_nth(1).get_int();
+		//int repeat = ar.get_nth(2).get_int();
+		//int endless = ar.get_nth(3).get_int();		
+	}
+
+	private static HashMap<string, string> format_metadata(HashTable<string,Value?> data)
+	{
+		HashMap<string,string> results = new HashMap<string, string>();
+		debug("format_metadata - title = %s", (string)data.lookup("title"));
+		results.set("title", (string)data.lookup("title"));
+    results.set("artist", (string)data.lookup("artist"));
+    results.set("album", (string)data.lookup("album"));
+    results.set("arturl", (string)data.lookup("arturl"));
+		return results;                          				
+	}
+	
+}

=== modified file 'src/music-player-bridge.vala'
--- src/music-player-bridge.vala	2010-06-10 11:46:17 +0000
+++ src/music-player-bridge.vala	2010-06-17 15:45:41 +0000
@@ -1,3 +1,23 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+Copyright 2010 Canonical Ltd.
+
+Authors:
+    Conor Curran <conor.curran@xxxxxxxxxxxxx>
+
+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 Indicate;
 using Dbusmenu;
 using Gee;
@@ -23,7 +43,6 @@
 
   public void set_root_menu_item(Dbusmenu.Menuitem menu)
   {
-    debug("MusicPlayerBridge -> set_root_menu_item");
 		root_menu = menu;
   }
 

=== modified file 'src/player-controller.vala'
--- src/player-controller.vala	2010-06-13 21:27:50 +0000
+++ src/player-controller.vala	2010-06-17 15:45:41 +0000
@@ -1,14 +1,37 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+Copyright 2010 Canonical Ltd.
+
+Authors:
+    Conor Curran <conor.curran@xxxxxxxxxxxxx>
+
+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 PlayerController : GLib.Object
 {
+	private const int METADATA = 2;	
+	private const int TRANSPORT = 3;
+	
 	private Dbusmenu.Menuitem root_menu;
 	private string name;
 	private bool is_active;
 	private ArrayList<Dbusmenu.Menuitem> custom_items;	
+	private MprisController mpris_adaptor;
 
-	// TODO: pass in the appropriate position for the menu (to handle multiple players)
 	public PlayerController(Dbusmenu.Menuitem root, string client_name, bool active)
 	{
 		this.root_menu = root;
@@ -16,6 +39,20 @@
 		this.is_active = active;
 		this.custom_items = new ArrayList<Dbusmenu.Menuitem>();
 		self_construct();
+		
+		// Temporary scenario to handle both v1 and v2 of MPRIS.
+		if(this.name == "Vlc"){
+			this.mpris_adaptor = new MprisControllerV2(this.name, this);
+		}
+		else{
+			this.mpris_adaptor = new MprisController(this.name, this);
+		}			
+
+		// TODO subclass dbusmenuMenuitem to something like a playermenuitem 
+		// and use this type to collectively 
+		// control widgets.
+		TransportMenuitem t = (TransportMenuitem)this.custom_items[TRANSPORT];
+		t.set_adaptor(this.mpris_adaptor);
 	}
 
 	public void vanish()
@@ -52,7 +89,13 @@
 		}
 		return true;
 	}	
-	
+
+	public void update_playing_info(HashMap<string, string> data)
+	{
+		debug("PlayerController - update_playing_info");
+		MetadataMenuitem item = (MetadataMenuitem)this.custom_items[METADATA];		
+		item.update(data);
+	}
 
 	private static string format_client_name(string client_name)
 	{

=== modified file 'src/transport-menu-item.vala'
--- src/transport-menu-item.vala	2010-06-14 23:32:27 +0000
+++ src/transport-menu-item.vala	2010-06-17 15:45:41 +0000
@@ -1,3 +1,23 @@
+/*
+This service primarily controls PulseAudio and is driven by the sound indicator menu on the panel.
+Copyright 2010 Canonical Ltd.
+
+Authors:
+    Conor Curran <conor.curran@xxxxxxxxxxxxx>
+
+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;
 
@@ -6,14 +26,29 @@
 	/* Not ideal duplicate definition of const - see common-defs/h */
  	const string DBUSMENU_TRANSPORT_MENUITEM_TYPE = "x-canonical-transport-bar";
  	const string DBUSMENU_TRANSPORT_MENUITEM_STATE = "x-canonical-transport-state";
-
+	private MprisController mpris_adaptor;
+	
 	public TransportMenuitem()
   {
 		this.property_set(MENUITEM_PROP_TYPE, DBUSMENU_TRANSPORT_MENUITEM_TYPE);
-		this.property_set(DBUSMENU_TRANSPORT_MENUITEM_STATE, "play");
+		// Hardcode the set up state until we can get the struct vala bug fixed
+		this.property_set_bool(DBUSMENU_TRANSPORT_MENUITEM_STATE, false);
+		debug("transport on the vala side");
 	}
 
+	public void set_adaptor(MprisController adaptor)
+	{
+		this.mpris_adaptor = adaptor;		
+	}
+	
+	/**
+	 Callback method for the handle_event
+	 * TRUE  => Playing
+	 * FALSE => Paused
+	 **/
 	public override void handle_event(string name, GLib.Value input_value, uint timestamp)
 	{
+		debug("handle_event with bool value %s", input_value.get_boolean().to_string());
+		this.mpris_adaptor.toggle_playback(input_value.get_boolean());
 	}	
 }
\ No newline at end of file

=== modified file 'src/transport-widget.c'
--- src/transport-widget.c	2010-06-15 11:19:01 +0000
+++ src/transport-widget.c	2010-06-17 15:45:41 +0000
@@ -62,12 +62,12 @@
 static gboolean transport_widget_button_release_event (GtkWidget             *menuitem,
                                                     	GdkEventButton        *event);
 
-static void transport_widget_update_state(DbusmenuMenuitem* item,
+static void transport_widget_property_update(DbusmenuMenuitem* item,
                                        gchar * property, 
                                        GValue * value,
                                        gpointer userdata);
 // utility methods
-static gchar* transport_widget_determine_play_label(const gchar* state);
+static gchar* transport_widget_toggle_play_label(const gchar* state);
 
 G_DEFINE_TYPE (TransportWidget, transport_widget, GTK_TYPE_MENU_ITEM);
 
@@ -130,14 +130,18 @@
 	GtkWidget *hbox;
 
 	hbox = gtk_hbox_new(TRUE, 2);
-	priv->play_button =	gtk_button_new_with_label(">");
-
+
+	gchar* label = ">";
+	if(dbusmenu_menuitem_property_get_bool(twin_item, DBUSMENU_TRANSPORT_MENUITEM_STATE) == TRUE){
+		label = "||";
+	}
+
+	priv->play_button =	gtk_button_new_with_label(g_strdup(label));
 	gtk_box_pack_start (GTK_BOX (hbox), priv->play_button, FALSE, TRUE, 0);
 
-
 	priv->hbox = hbox;
 	
-	g_signal_connect(G_OBJECT(twin_item), "property-changed", G_CALLBACK(transport_widget_update_state), self);
+	g_signal_connect(G_OBJECT(twin_item), "property-changed", G_CALLBACK(transport_widget_property_update), self);
 
 	gtk_container_add (GTK_CONTAINER (self), priv->hbox);
 
@@ -163,7 +167,16 @@
 {
 	g_debug("TransportWidget::menu_press_event");
 	TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE(TRANSPORT_WIDGET(menuitem));
-	gtk_button_set_label(GTK_BUTTON(priv->play_button), g_strdup(transport_widget_determine_play_label(gtk_button_get_label(GTK_BUTTON(priv->play_button)))));
+
+	gboolean state = g_ascii_strcasecmp(gtk_button_get_label(GTK_BUTTON(priv->play_button)), ">") == 0;
+
+	gtk_button_set_label(GTK_BUTTON(priv->play_button), g_strdup(transport_widget_toggle_play_label(gtk_button_get_label(GTK_BUTTON(priv->play_button)))));
+ 	GValue value = {0};
+  g_value_init(&value, G_TYPE_BOOLEAN);
+	g_debug("TransportWidget::menu_press_event - going to send value %i", state);
+
+	g_value_set_boolean(&value, state);	
+	dbusmenu_menuitem_handle_event (twin_item, "Transport state change", &value, 0);
 	
 	return TRUE;
 }
@@ -180,7 +193,8 @@
 * transport_widget_update_state()
 * Callback for updates from the other side of dbus
 **/
-static void transport_widget_update_state(DbusmenuMenuitem* item, gchar* property, 
+static void 
+transport_widget_property_update(DbusmenuMenuitem* item, gchar* property, 
                                        GValue* value, gpointer userdata)
 {
 	g_debug("transport_widget_update_state - with property  %s", property);  
@@ -190,11 +204,11 @@
 	TransportWidget* bar = (TransportWidget*)userdata;
 	TransportWidgetPrivate *priv = TRANSPORT_WIDGET_GET_PRIVATE(bar);
 	
-	gtk_button_set_label(GTK_BUTTON(priv->play_button), g_strdup(transport_widget_determine_play_label(property)));
+	gtk_button_set_label(GTK_BUTTON(priv->play_button), g_strdup(transport_widget_toggle_play_label(property)));
 }
 
 // will be needed for image swapping
-static gchar* transport_widget_determine_play_label(const gchar* state)
+static gchar* transport_widget_toggle_play_label(const gchar* state)
 {
 	gchar* label = ">";
 	if(g_strcmp0(state, ">") == 0){


Follow ups