diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/indicator-sound.c | 29 | ||||
-rw-r--r-- | src/mpris-controller.vala | 19 | ||||
-rw-r--r-- | src/player-controller.vala | 18 | ||||
-rw-r--r-- | src/player-item.vala | 4 | ||||
-rw-r--r-- | src/scrub-menu-item.vala | 6 | ||||
-rw-r--r-- | src/scrub-widget.c | 92 | ||||
-rw-r--r-- | src/scrub-widget.h | 1 |
8 files changed, 145 insertions, 26 deletions
diff --git a/configure.ac b/configure.ac index 0a41bc5..8aeb96d 100644 --- a/configure.ac +++ b/configure.ac @@ -33,7 +33,7 @@ INDICATOR_REQUIRED_VERSION=0.3.6 DBUSMENUGTK_REQUIRED_VERSION=0.2.2 POLKIT_REQUIRED_VERSION=0.92 PULSE_AUDIO_REQUIRED_VERSION=0.9.19 -INDICATOR_DISPLAY_OBJECTS=0.1.4 +INDICATOR_DISPLAY_OBJECTS=0.1.8 INDICATE_REQUIRED_VERSION=0.4.1 DBUSMENUGLIB_REQUIRED_VERSION=0.3.1 diff --git a/src/indicator-sound.c b/src/indicator-sound.c index a2d9762..e18125a 100644 --- a/src/indicator-sound.c +++ b/src/indicator-sound.c @@ -41,6 +41,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include "transport-widget.h" #include "metadata-widget.h" #include "title-widget.h" +#include "scrub-widget.h" #include "dbus-shared-names.h" #include "sound-service-client.h" #include "common-defs.h" @@ -94,10 +95,11 @@ static void slider_grabbed(GtkWidget *widget, gpointer user_data); static void slider_released(GtkWidget *widget, gpointer user_data); static void style_changed_cb(GtkWidget *widget, gpointer user_data); -//player widgets related +//player widget realisation methods static gboolean new_transport_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); static gboolean new_metadata_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); static gboolean new_title_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); +static gboolean new_scrub_bar_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); // DBUS communication static DBusGProxy *sound_dbus_proxy = NULL; @@ -246,7 +248,9 @@ get_menu (IndicatorObject * io) dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_TRANSPORT_MENUITEM_TYPE, new_transport_widget); dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_METADATA_MENUITEM_TYPE, new_metadata_widget); dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_TITLE_MENUITEM_TYPE, new_title_widget); - // register Key-press listening on the menu widget as the slider does not allow this. + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(client), DBUSMENU_SCRUB_MENUITEM_TYPE, new_scrub_bar_widget); + + // register Key-press listening on the menu widget as the slider does not allow this. g_signal_connect(menu, "key-press-event", G_CALLBACK(key_press_cb), NULL); return GTK_MENU(menu); } @@ -274,6 +278,7 @@ new_slider_item(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuC io = g_object_get_data (G_OBJECT (client), "indicator"); volume_slider = ido_scale_menu_item_new_with_range ("Volume", initial_volume_percent, 0, 100, 1); + ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (volume_slider), IDO_SCALE_MENU_ITEM_STYLE_IMAGE); g_object_set(volume_slider, "reverse-scroll-events", TRUE, NULL); g_signal_connect (volume_slider, @@ -373,6 +378,26 @@ new_title_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusmenu return TRUE; } +static gboolean +new_scrub_bar_widget(DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) +{ + g_debug("indicator-sound: new_scrub_bar_widget"); + + GtkWidget* scrub_bar = NULL; + + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); + g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); + + scrub_bar = scrub_widget_new (newitem); + GtkMenuItem *menu_scrub_widget = GTK_MENU_ITEM(scrub_widget_get_ido_bar(SCRUB_WIDGET(scrub_bar))); + + gtk_widget_show_all(scrub_widget_get_ido_bar(SCRUB_WIDGET(scrub_bar))); + + dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, menu_scrub_widget, parent); + + return TRUE; +} + static void connection_changed (IndicatorServiceManager * sm, gboolean connected, gpointer userdata) diff --git a/src/mpris-controller.vala b/src/mpris-controller.vala index c3f21d8..afe9190 100644 --- a/src/mpris-controller.vala +++ b/src/mpris-controller.vala @@ -71,10 +71,6 @@ public class MprisController : GLib.Object MetadataMenuitem.attributes_format()); } - /** - * TRUE => Playing - * FALSE => Paused - **/ public void transport_event(TransportMenuitem.action command) { debug("transport_event input = %i", (int)command); @@ -101,6 +97,21 @@ public class MprisController : GLib.Object } } + public void set_position(double position) + { + debug("Set position with pos (0-100) %f", position); + HashTable<string, Value?> data = this.mpris_player.GetMetadata(); + Value? time_value = data.lookup("time"); + if(time_value == null){ + warning("Can't fetch the duration of the track therefore cant set the position"); + return; + } + uint32 total_time = time_value.get_uint32(); + debug("total time of track = %i", (int)total_time); + double new_time_position = total_time * position/100.0; + this.mpris_player.SetPosition((int)(new_time_position * 1000)); + } + public bool connected() { return (this.mpris_player != null); diff --git a/src/player-controller.vala b/src/player-controller.vala index db81ee2..48416b9 100644 --- a/src/player-controller.vala +++ b/src/player-controller.vala @@ -23,16 +23,15 @@ using Gee; public class PlayerController : GLib.Object { - public const int WIDGET_QUANTITY = 4;//for now //5; + public const int WIDGET_QUANTITY = 5; public static enum widget_order{ SEPARATOR, TITLE, METADATA, + SCRUB, TRANSPORT } - //public const int METADATA = 2; - //private const int TRANSPORT = 3; public enum state{ OFFLINE, @@ -134,14 +133,14 @@ public class PlayerController : GLib.Object } debug("about the set the visibility on both the transport and metadata widget to %s", visibility.to_string()); this.custom_items[widget_order.TRANSPORT].property_set_bool(MENUITEM_PROP_VISIBLE, visibility); - this.custom_items[widget_order.METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, visibility); + this.custom_items[widget_order.SCRUB].property_set_bool(MENUITEM_PROP_VISIBLE, visibility); + this.custom_items[widget_order.METADATA].property_set_bool(MENUITEM_PROP_VISIBLE, visibility); // DEBUG if(this.mpris_adaptor == null){ warning("Why is the mpris object null"); } } - - + private void construct_widgets() { // Separator item @@ -154,11 +153,16 @@ public class PlayerController : GLib.Object // Metadata item MetadataMenuitem metadata_item = new MetadataMenuitem(); this.custom_items.add(metadata_item); - + + // Scrub item + ScrubMenuitem scrub_item = new ScrubMenuitem(this); + this.custom_items.add(scrub_item); + // Transport item TransportMenuitem transport_item = new TransportMenuitem(this); this.custom_items.add(transport_item); + foreach(PlayerItem item in this.custom_items){ root_menu.child_add_position(item, this.menu_offset + this.custom_items.index_of(item)); } diff --git a/src/player-item.vala b/src/player-item.vala index 3e10b7b..e7f7c67 100644 --- a/src/player-item.vala +++ b/src/player-item.vala @@ -47,7 +47,8 @@ public class PlayerItem : Dbusmenu.Menuitem if(ensure_valid_updates(data, attributes) == false){ debug("PlayerItem::Update -> The hashtable update does not contain what we were expecting - just leave it!"); return; - } + } + foreach(string property in attributes){ string[] input_keys = property.split("-"); string search_key = input_keys[input_keys.length-1 : input_keys.length][0]; @@ -57,6 +58,7 @@ public class PlayerItem : Dbusmenu.Menuitem if (v.holds (typeof (string))){ string update = v.get_string().strip(); debug("with value : %s", update); + // Special case for the arturl URI's. if(property.contains("arturl")){ try{ update = Filename.from_uri(update.strip()); diff --git a/src/scrub-menu-item.vala b/src/scrub-menu-item.vala index 409494a..9988378 100644 --- a/src/scrub-menu-item.vala +++ b/src/scrub-menu-item.vala @@ -25,12 +25,14 @@ public class ScrubMenuitem : PlayerItem { public ScrubMenuitem(PlayerController parent) { - Object(item_type: MENUITEM_TYPE); + debug("Transport object constructor - service side"); + Object(item_type: MENUITEM_TYPE, owner: parent); } public override void handle_event(string name, GLib.Value input_value, uint timestamp) { - debug("handle_event for owner %s with owner state = %i", this.owner.name, this.owner.current_state); + debug("handle_event for owner %s with value: %f", this.owner.name, input_value.get_double()); + this.owner.mpris_adaptor.set_position(input_value.get_double()); } public static HashSet<string> attributes_format() diff --git a/src/scrub-widget.c b/src/scrub-widget.c index 748cd19..4595ede 100644 --- a/src/scrub-widget.c +++ b/src/scrub-widget.c @@ -24,12 +24,15 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <glib/gi18n.h> #include "scrub-widget.h" #include "common-defs.h" +#include <libido/idoscalemenuitem.h> typedef struct _ScrubWidgetPrivate ScrubWidgetPrivate; struct _ScrubWidgetPrivate { DbusmenuMenuitem* twin_item; + GtkWidget* ido_scrub_bar; + GtkStyle* style; }; #define SCRUB_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SCRUB_WIDGET_TYPE, ScrubWidgetPrivate)) @@ -39,11 +42,17 @@ static void scrub_widget_class_init (ScrubWidgetClass *klass); static void scrub_widget_init (ScrubWidget *self); static void scrub_widget_dispose (GObject *object); static void scrub_widget_finalize (GObject *object); - -static void scrub_widget_property_update(DbusmenuMenuitem* item, gchar* property, - GValue* value, gpointer userdata); +static void scrub_widget_property_update( DbusmenuMenuitem* item, gchar* property, + GValue* value, gpointer userdata); static void scrub_widget_set_twin_item( ScrubWidget* self, DbusmenuMenuitem* twin_item); +static void scrub_widget_parent_changed ( GtkWidget *widget, gpointer user_data); +static gchar* scrub_widget_format_time(gint time); +static gboolean scrub_widget_change_value_cb (GtkRange *range, + GtkScrollType scroll, + gdouble value, + gpointer user_data); + G_DEFINE_TYPE (ScrubWidget, scrub_widget, G_TYPE_OBJECT); @@ -58,11 +67,26 @@ scrub_widget_class_init (ScrubWidgetClass *klass) gobject_class->finalize = scrub_widget_finalize; } + static void scrub_widget_init (ScrubWidget *self) { g_debug("ScrubWidget::scrub_widget_init"); - //ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(self); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(self); + + priv->ido_scrub_bar = ido_scale_menu_item_new_with_range ("Scrub", 0, 0, 100, 1); + ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), IDO_SCALE_MENU_ITEM_STYLE_LABEL); + ido_scale_menu_item_set_primary_label(IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), "00:00"); + ido_scale_menu_item_set_secondary_label(IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), "05:35"); + g_object_set(priv->ido_scrub_bar, "reverse-scroll-events", TRUE, NULL); + + //g_signal_connect (priv->ido_scrub_bar, + // "notify::parent", G_CALLBACK (scrub_widget_parent_changed), + // NULL); + + // register slider changes listening on the range + GtkWidget* scrub_widget = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_scrub_bar); + g_signal_connect(scrub_widget, "change-value", G_CALLBACK(scrub_widget_change_value_cb), self); } static void @@ -82,15 +106,27 @@ scrub_widget_property_update(DbusmenuMenuitem* item, gchar* property, GValue* value, gpointer userdata) { g_return_if_fail (IS_SCRUB_WIDGET (userdata)); - //ScrubWidget* mitem = SCRUB_WIDGET(userdata); - //ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(mitem); + ScrubWidget* mitem = SCRUB_WIDGET(userdata); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(mitem); - if(g_ascii_strcasecmp(DBUSMENU_SCRUB_MENUITEM_DURATION, property) == 0){ + if(g_ascii_strcasecmp(DBUSMENU_SCRUB_MENUITEM_DURATION, property) == 0){ + ido_scale_menu_item_set_secondary_label(IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), + scrub_widget_format_time(g_value_get_int(value))); } - else if(g_ascii_strcasecmp(DBUSMENU_SCRUB_MENUITEM_POSITION, property) == 0){ + else if(g_ascii_strcasecmp(DBUSMENU_SCRUB_MENUITEM_POSITION, property) == 0){ + ido_scale_menu_item_set_primary_label(IDO_SCALE_MENU_ITEM(priv->ido_scrub_bar), + scrub_widget_format_time(g_value_get_int(value))); } } +/*static void +scrub_widget_parent_changed (GtkWidget *widget, + gpointer user_data) +{ + gtk_widget_set_size_request (widget, 200, -1); + g_debug("slider parent changed"); +}*/ + static void scrub_widget_set_twin_item(ScrubWidget* self, DbusmenuMenuitem* twin_item) @@ -99,7 +135,45 @@ scrub_widget_set_twin_item(ScrubWidget* self, priv->twin_item = twin_item; g_signal_connect(G_OBJECT(twin_item), "property-changed", - G_CALLBACK(scrub_widget_property_update), self); + G_CALLBACK(scrub_widget_property_update), self); +} + +static gboolean +scrub_widget_change_value_cb (GtkRange *range, + GtkScrollType scroll, + gdouble new_value, + gpointer user_data) +{ + g_return_val_if_fail (IS_SCRUB_WIDGET (user_data), FALSE); + ScrubWidget* mitem = SCRUB_WIDGET(user_data); + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(mitem); + + GValue value = {0}; + g_value_init(&value, G_TYPE_DOUBLE); + gdouble clamped = CLAMP(new_value, 0, 100); + g_value_set_double(&value, clamped); + g_debug("scrub-widget-change-value callback - = %f", clamped); + dbusmenu_menuitem_handle_event (priv->twin_item, "scrubbing", &value, 0); + return FALSE; +} + +GtkWidget* +scrub_widget_get_ido_bar(ScrubWidget* self) +{ + ScrubWidgetPrivate * priv = SCRUB_WIDGET_GET_PRIVATE(self); + return priv->ido_scrub_bar; +} + +static gchar* +scrub_widget_format_time(gint time) +{ + // Assuming its in seconds for now ... + gint minutes = time/60; + gint seconds = time % 60; + gchar* prefix="0"; + if(minutes > 9) + prefix=""; + return g_strdup_printf("%s%i:%i", prefix, minutes, seconds); } /** diff --git a/src/scrub-widget.h b/src/scrub-widget.h index 32455e3..cebe890 100644 --- a/src/scrub-widget.h +++ b/src/scrub-widget.h @@ -45,6 +45,7 @@ struct _ScrubWidget { GType scrub_widget_get_type (void) G_GNUC_CONST; GtkWidget* scrub_widget_new(DbusmenuMenuitem* twin_item); +GtkWidget* scrub_widget_get_ido_bar(ScrubWidget* self); G_END_DECLS |