diff options
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/metadata-menu-item.vala | 23 | ||||
-rw-r--r-- | src/metadata-widget.c | 75 | ||||
-rw-r--r-- | src/metadata-widget.h | 2 | ||||
-rw-r--r-- | src/mpris-controller-v2.vala | 28 | ||||
-rw-r--r-- | src/mpris-controller.vala | 101 | ||||
-rw-r--r-- | src/music-player-bridge.vala | 21 | ||||
-rw-r--r-- | src/player-controller.vala | 47 | ||||
-rw-r--r-- | src/transport-menu-item.vala | 39 | ||||
-rw-r--r-- | src/transport-widget.c | 32 |
10 files changed, 331 insertions, 41 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 2a19c3d..ac7beb9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,7 +54,9 @@ music_bridge_VALASOURCES = \ 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 \ diff --git a/src/metadata-menu-item.vala b/src/metadata-menu-item.vala index ef72143..82926b1 100644 --- a/src/metadata-menu-item.vala +++ b/src/metadata-menu-item.vala @@ -13,15 +13,26 @@ public class MetadataMenuitem : Dbusmenu.Menuitem 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.has_prefix("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!"); diff --git a/src/metadata-widget.c b/src/metadata-widget.c index a451ad7..c4d3b50 100644 --- a/src/metadata-widget.c +++ b/src/metadata-widget.c @@ -34,7 +34,7 @@ struct _MetadataWidgetPrivate { 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_press_event (GtkWidget *menuitem, 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 @@ metadata_widget_init (MetadataWidget *self) 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 @@ metadata_widget_init (MetadataWidget *self) 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,11 +158,49 @@ metadata_widget_button_release_event (GtkWidget *menuitem, return TRUE; } -static void metadata_widget_update_state(gchar *property, GValue *value, gpointer userdata) +// TODO: Manage empty/mangled music details <unknown artist> etc. +static void +metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property, + GValue* value, gpointer userdata) { - g_debug("metadata_widget_update_state - with property %s", property); + g_return_if_fail (IS_METADATA_WIDGET (userdata)); + + 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){ + if(priv->image_path != NULL){ + g_free(priv->image_path); + } + + priv->image_path = g_value_dup_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: * @returns: a new #MetadataWidget. diff --git a/src/metadata-widget.h b/src/metadata-widget.h index ce7df5f..6f1d4d3 100644 --- a/src/metadata-widget.h +++ b/src/metadata-widget.h @@ -25,7 +25,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. 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)) diff --git a/src/mpris-controller-v2.vala b/src/mpris-controller-v2.vala new file mode 100644 index 0000000..0392cfc --- /dev/null +++ b/src/mpris-controller-v2.vala @@ -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@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 Gee; + +public class MprisControllerV2 : MprisController +{ + public MprisControllerV2(string name, PlayerController controller){ + base(name, controller, "org.mpris.MediaPlayer.Player"); + } + +} diff --git a/src/mpris-controller.vala b/src/mpris-controller.vala new file mode 100644 index 0000000..7e65594 --- /dev/null +++ b/src/mpris-controller.vala @@ -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@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 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; + } + +} diff --git a/src/music-player-bridge.vala b/src/music-player-bridge.vala index 89f633b..b03ecbd 100644 --- a/src/music-player-bridge.vala +++ b/src/music-player-bridge.vala @@ -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@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 Indicate; using Dbusmenu; using Gee; @@ -23,7 +43,6 @@ public class MusicPlayerBridge : GLib.Object public void set_root_menu_item(Dbusmenu.Menuitem menu) { - debug("MusicPlayerBridge -> set_root_menu_item"); root_menu = menu; } diff --git a/src/player-controller.vala b/src/player-controller.vala index dcb428b..aa72cac 100644 --- a/src/player-controller.vala +++ b/src/player-controller.vala @@ -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@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 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 @@ public class PlayerController : GLib.Object 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 @@ public class PlayerController : GLib.Object } 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) { diff --git a/src/transport-menu-item.vala b/src/transport-menu-item.vala index 7687a92..2e1ed0b 100644 --- a/src/transport-menu-item.vala +++ b/src/transport-menu-item.vala @@ -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@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; @@ -6,14 +26,29 @@ public class TransportMenuitem : Dbusmenu.Menuitem /* 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 diff --git a/src/transport-widget.c b/src/transport-widget.c index 2c32315..c53513d 100644 --- a/src/transport-widget.c +++ b/src/transport-widget.c @@ -62,12 +62,12 @@ static gboolean transport_widget_button_press_event (GtkWidget *men 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 @@ transport_widget_init (TransportWidget *self) GtkWidget *hbox; hbox = gtk_hbox_new(TRUE, 2); - priv->play_button = gtk_button_new_with_label(">"); - gtk_box_pack_start (GTK_BOX (hbox), priv->play_button, FALSE, TRUE, 0); + 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 @@ transport_widget_button_press_event (GtkWidget *menuitem, { 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), 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_button_release_event (GtkWidget *menuitem, * 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 @@ static void transport_widget_update_state(DbusmenuMenuitem* item, gchar* propert 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){ |