aboutsummaryrefslogtreecommitdiff
path: root/src/transport-widget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport-widget.c')
-rw-r--r--src/transport-widget.c233
1 files changed, 166 insertions, 67 deletions
diff --git a/src/transport-widget.c b/src/transport-widget.c
index 7c96684..ef2916d 100644
--- a/src/transport-widget.c
+++ b/src/transport-widget.c
@@ -27,7 +27,6 @@ Uses code from ctk
#include <math.h>
#include "transport-widget.h"
-#include "common-defs.h"
#define RECT_WIDTH 130.0f
@@ -77,15 +76,19 @@ typedef struct _TransportWidgetPrivate TransportWidgetPrivate;
struct _TransportWidgetPrivate
{
- TransportWidgetEvent current_command;
- TransportWidgetEvent key_event;
- TransportWidgetEvent motion_event;
- TransportWidgetState current_state;
- GHashTable* command_coordinates;
- DbusmenuMenuitem* twin_item;
- gboolean has_focus;
+ TransportAction current_command;
+ TransportAction key_event;
+ TransportAction motion_event;
+ TransportState current_state;
+ GHashTable* command_coordinates;
+ DbusmenuMenuitem* twin_item;
+ gboolean has_focus;
+ gint hold_timer;
+ gint skip_frequency;
};
+// TODO refactor the UI handlers, consolidate functionality between key press /release
+// and button press / release.
#define TRANSPORT_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRANSPORT_WIDGET_TYPE, TransportWidgetPrivate))
/* Gobject boiler plate */
@@ -119,17 +122,20 @@ static void transport_widget_menu_hidden ( GtkWidget *menu,
static void transport_widget_notify ( GObject *item,
GParamSpec *pspec,
gpointer user_data );
-static TransportWidgetEvent transport_widget_determine_button_event ( TransportWidget* button,
+static TransportAction transport_widget_determine_button_event ( TransportWidget* button,
GdkEventButton* event);
-static TransportWidgetEvent transport_widget_determine_motion_event ( TransportWidget* button,
+static TransportAction transport_widget_determine_motion_event ( TransportWidget* button,
GdkEventMotion* event);
static void transport_widget_react_to_button_release ( TransportWidget* button,
- TransportWidgetEvent command);
+ TransportAction command);
static void transport_widget_toggle_play_pause ( TransportWidget* button,
- TransportWidgetState update);
+ TransportState update);
static void transport_widget_select (GtkItem* menu, gpointer Userdata);
static void transport_widget_deselect (GtkItem* menu, gpointer Userdata);
-static TransportWidgetEvent transport_widget_collision_detection (gint x, gint y);
+static TransportAction transport_widget_collision_detection (gint x, gint y);
+static void transport_widget_start_timing (TransportWidget* widget);
+static gboolean transport_widget_trigger_seek (gpointer userdata);
+static gboolean transport_widget_seek (gpointer userdata);
/// Init functions //////////////////////////////////////////////////////////
@@ -155,11 +161,13 @@ static void
transport_widget_init (TransportWidget *self)
{
TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(self);
- priv->current_command = TRANSPORT_NADA;
- priv->current_state = PAUSE;
- priv->key_event = TRANSPORT_NADA;
- priv->motion_event = TRANSPORT_NADA;
+ priv->current_command = TRANSPORT_ACTION_NO_ACTION;
+ priv->current_state = TRANSPORT_STATE_PAUSED;
+ priv->key_event = TRANSPORT_ACTION_NO_ACTION;
+ priv->motion_event = TRANSPORT_ACTION_NO_ACTION;
priv->has_focus = FALSE;
+ priv->hold_timer = 0;
+ priv->skip_frequency = 0;
priv->command_coordinates = g_hash_table_new_full(g_direct_hash,
g_direct_equal,
NULL,
@@ -170,7 +178,7 @@ transport_widget_init (TransportWidget *self)
previous_list = g_list_insert(previous_list, GINT_TO_POINTER(60), 2);
previous_list = g_list_insert(previous_list, GINT_TO_POINTER(34), 3);
g_hash_table_insert(priv->command_coordinates,
- GINT_TO_POINTER(TRANSPORT_PREVIOUS),
+ GINT_TO_POINTER(TRANSPORT_ACTION_PREVIOUS),
previous_list);
GList* play_list = NULL;
@@ -180,7 +188,7 @@ transport_widget_init (TransportWidget *self)
play_list = g_list_insert(play_list, GINT_TO_POINTER(43), 3);
g_hash_table_insert(priv->command_coordinates,
- GINT_TO_POINTER(TRANSPORT_PLAY_PAUSE),
+ GINT_TO_POINTER(TRANSPORT_ACTION_PLAY_PAUSE),
play_list);
GList* next_list = NULL;
@@ -190,7 +198,7 @@ transport_widget_init (TransportWidget *self)
next_list = g_list_insert(next_list, GINT_TO_POINTER(34), 3);
g_hash_table_insert(priv->command_coordinates,
- GINT_TO_POINTER(TRANSPORT_NEXT),
+ GINT_TO_POINTER(TRANSPORT_ACTION_NEXT),
next_list);
gtk_widget_set_size_request(GTK_WIDGET(self), 200, 43);
g_signal_connect (G_OBJECT(self),
@@ -248,7 +256,7 @@ transport_widget_is_selected ( TransportWidget* widget )
static void
transport_widget_toggle_play_pause(TransportWidget* button,
- TransportWidgetState update)
+ TransportState update)
{
TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(button);
priv->current_state = update;
@@ -276,7 +284,7 @@ transport_widget_menu_hidden ( GtkWidget *menu,
TransportWidget *transport)
{
g_return_if_fail(IS_TRANSPORT_WIDGET(transport));
- transport_widget_react_to_button_release(transport, TRANSPORT_NADA);
+ transport_widget_react_to_button_release(transport, TRANSPORT_ACTION_NO_ACTION);
}
static gboolean
@@ -285,11 +293,18 @@ transport_widget_motion_notify_event (GtkWidget *menuitem,
{
g_return_val_if_fail ( IS_TRANSPORT_WIDGET(menuitem), FALSE );
TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE ( TRANSPORT_WIDGET(menuitem) );
- TransportWidgetEvent result = transport_widget_determine_motion_event ( TRANSPORT_WIDGET(menuitem),
+ TransportAction result = transport_widget_determine_motion_event ( TRANSPORT_WIDGET(menuitem),
event);
-
priv->motion_event = result;
gtk_widget_queue_draw (menuitem);
+ if (priv->hold_timer != 0){
+ g_source_remove (priv->hold_timer);
+ priv->hold_timer = 0;
+ }
+ if(priv->skip_frequency != 0){
+ g_source_remove (priv->skip_frequency);
+ priv->skip_frequency = 0;
+ }
return TRUE;
}
@@ -300,8 +315,8 @@ transport_widget_leave_notify_event (GtkWidget *menuitem,
g_return_val_if_fail ( IS_TRANSPORT_WIDGET(menuitem), FALSE );
TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE ( TRANSPORT_WIDGET(menuitem) );
- priv->motion_event = TRANSPORT_NADA;
- priv->current_command = TRANSPORT_NADA;
+ priv->motion_event = TRANSPORT_ACTION_NO_ACTION;
+ priv->current_command = TRANSPORT_ACTION_NO_ACTION;
gtk_widget_queue_draw (GTK_WIDGET(menuitem));
return TRUE;
@@ -313,15 +328,81 @@ transport_widget_button_press_event (GtkWidget *menuitem,
{
g_return_val_if_fail ( IS_TRANSPORT_WIDGET(menuitem), FALSE );
TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE ( TRANSPORT_WIDGET(menuitem) );
- TransportWidgetEvent result = transport_widget_determine_button_event ( TRANSPORT_WIDGET(menuitem),
+ TransportAction result = transport_widget_determine_button_event ( TRANSPORT_WIDGET(menuitem),
event);
- if(result != TRANSPORT_NADA){
+ if(result != TRANSPORT_ACTION_NO_ACTION){
priv->current_command = result;
gtk_widget_queue_draw (GTK_WIDGET(menuitem));
+ if (priv->current_command == TRANSPORT_ACTION_PREVIOUS ||
+ priv->current_command == TRANSPORT_ACTION_NEXT){
+ transport_widget_start_timing (TRANSPORT_WIDGET(menuitem));
+ }
}
return TRUE;
}
-
+/**
+ * TODO rename or merge
+ * @param widget
+ */
+static void
+transport_widget_start_timing (TransportWidget* widget)
+{
+ TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE (widget);
+ if (priv->hold_timer == 0){
+ priv->hold_timer = g_timeout_add (800,
+ transport_widget_trigger_seek,
+ widget);
+ }
+}
+
+static gboolean
+transport_widget_trigger_seek (gpointer userdata)
+{
+ g_return_val_if_fail ( IS_TRANSPORT_WIDGET(userdata), FALSE );
+ TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE (TRANSPORT_WIDGET(userdata));
+ if (priv->skip_frequency == 0){
+ priv->skip_frequency = g_timeout_add (100,
+ transport_widget_seek,
+ userdata);
+ }
+ priv->hold_timer = 0;
+ return FALSE;
+}
+
+/**
+ * This will be called repeatedly until a key/button release is received
+ * @param userdata
+ * @return
+ */
+static gboolean
+transport_widget_seek (gpointer userdata)
+{
+ g_return_val_if_fail ( IS_TRANSPORT_WIDGET(userdata), FALSE );
+ TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE (TRANSPORT_WIDGET(userdata));
+ GVariant* new_transport_state;
+ if(priv->current_command == TRANSPORT_ACTION_NEXT){
+ //g_debug ("we should be skipping forward");
+ new_transport_state = g_variant_new_int32 ((int)TRANSPORT_ACTION_FORWIND);
+
+ dbusmenu_menuitem_handle_event ( priv->twin_item,
+ "Transport state change",
+ new_transport_state,
+ 0 );
+
+ }
+ else if(priv->current_command == TRANSPORT_ACTION_PREVIOUS){
+ //g_debug ("we should be skipping back");
+ new_transport_state = g_variant_new_int32 ((int)TRANSPORT_ACTION_REWIND);
+
+ dbusmenu_menuitem_handle_event ( priv->twin_item,
+ "Transport state change",
+ new_transport_state,
+ 0 );
+ }
+
+ return TRUE;
+}
+
static gboolean
transport_widget_button_release_event (GtkWidget *menuitem,
GdkEventButton *event)
@@ -329,9 +410,11 @@ transport_widget_button_release_event (GtkWidget *menuitem,
g_return_val_if_fail(IS_TRANSPORT_WIDGET(menuitem), FALSE);
TransportWidget* transport = TRANSPORT_WIDGET(menuitem);
TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport );
- TransportWidgetEvent result = transport_widget_determine_button_event ( transport,
+ TransportAction result = transport_widget_determine_button_event ( transport,
event );
- if (result != TRANSPORT_NADA && priv->current_command == result){
+ if (result != TRANSPORT_ACTION_NO_ACTION &&
+ priv->current_command == result &&
+ priv->skip_frequency == 0){
GVariant* new_transport_state = g_variant_new_int32 ((int)result);
dbusmenu_menuitem_handle_event ( priv->twin_item,
"Transport state change",
@@ -361,28 +444,34 @@ transport_widget_deselect (GtkItem* item, gpointer Userdata)
void
transport_widget_react_to_key_press_event ( TransportWidget* transport,
- TransportWidgetEvent transport_event )
+ TransportAction transport_event )
{
- if(transport_event != TRANSPORT_NADA){
+ if(transport_event != TRANSPORT_ACTION_NO_ACTION){
TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport );
priv->current_command = transport_event;
priv->key_event = transport_event;
gtk_widget_realize ( GTK_WIDGET(transport) );
gtk_widget_queue_draw (GTK_WIDGET(transport) );
+ if (priv->current_command == TRANSPORT_ACTION_PREVIOUS ||
+ priv->current_command == TRANSPORT_ACTION_NEXT){
+ transport_widget_start_timing (transport);
+ }
}
}
void
transport_widget_react_to_key_release_event ( TransportWidget* transport,
- TransportWidgetEvent transport_event )
+ TransportAction transport_event )
{
- if(transport_event != TRANSPORT_NADA){
+ if(transport_event != TRANSPORT_ACTION_NO_ACTION){
TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport );
- GVariant* new_transport_event = g_variant_new_int32((int)transport_event);
- dbusmenu_menuitem_handle_event ( priv->twin_item,
- "Transport state change",
- new_transport_event,
- 0 );
+ GVariant* new_transport_event = g_variant_new_int32((int)transport_event);
+ if (priv->skip_frequency == 0){
+ dbusmenu_menuitem_handle_event ( priv->twin_item,
+ "Transport state change",
+ new_transport_event,
+ 0 );
+ }
}
transport_widget_react_to_button_release ( transport,
transport_event );
@@ -395,52 +484,60 @@ transport_widget_focus_update ( TransportWidget* transport, gboolean focus )
priv->has_focus = focus;
}
-static TransportWidgetEvent
+static TransportAction
transport_widget_determine_button_event( TransportWidget* button,
GdkEventButton* event )
{
return transport_widget_collision_detection (event->x, event->y);
}
-static TransportWidgetEvent
+static TransportAction
transport_widget_determine_motion_event( TransportWidget* button,
GdkEventMotion* event )
{
return transport_widget_collision_detection (event->x, event->y);
}
-static TransportWidgetEvent
+static TransportAction
transport_widget_collision_detection ( gint x,
gint y )
{
- TransportWidgetEvent event = TRANSPORT_NADA;
+ TransportAction event = TRANSPORT_ACTION_NO_ACTION;
if (x > 67 && x < 112
&& y > 12 && y < 40){
- event = TRANSPORT_PREVIOUS;
+ event = TRANSPORT_ACTION_PREVIOUS;
}
else if (x > 111 && x < 153
&& y > 5 && y < 47){
- event = TRANSPORT_PLAY_PAUSE;
+ event = TRANSPORT_ACTION_PLAY_PAUSE;
}
else if (x > 152 && x < 197
&& y > 12 && y < 40){
- event = TRANSPORT_NEXT;
+ event = TRANSPORT_ACTION_NEXT;
}
return event;
}
static void
transport_widget_react_to_button_release ( TransportWidget* button,
- TransportWidgetEvent command )
+ TransportAction command )
{
g_return_if_fail(IS_TRANSPORT_WIDGET(button));
TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(button);
- priv->current_command = TRANSPORT_NADA;
- priv->key_event = TRANSPORT_NADA;
+ priv->current_command = TRANSPORT_ACTION_NO_ACTION;
+ priv->key_event = TRANSPORT_ACTION_NO_ACTION;
gtk_widget_queue_draw (GTK_WIDGET(button));
+ if (priv->hold_timer != 0){
+ g_source_remove (priv->hold_timer);
+ priv->hold_timer = 0;
+ }
+ if(priv->skip_frequency != 0){
+ g_source_remove (priv->skip_frequency);
+ priv->skip_frequency = 0;
+ }
}
/// internal helper functions //////////////////////////////////////////////////
@@ -1218,7 +1315,7 @@ draw (GtkWidget* button, cairo_t *cr)
MIDDLE_END);
//prev/next button
- if(priv->current_command == TRANSPORT_PREVIOUS)
+ if(priv->current_command == TRANSPORT_ACTION_PREVIOUS)
{
draw_gradient (cr,
X,
@@ -1244,7 +1341,7 @@ draw (GtkWidget* button, cairo_t *cr)
INNER_COMPRESSED_START,
INNER_COMPRESSED_END);
}
- else if(priv->current_command == TRANSPORT_NEXT)
+ else if(priv->current_command == TRANSPORT_ACTION_NEXT)
{
draw_gradient (cr,
RECT_WIDTH / 2 + X,
@@ -1270,7 +1367,7 @@ draw (GtkWidget* button, cairo_t *cr)
INNER_COMPRESSED_START,
INNER_COMPRESSED_END);
}
- else if (priv->motion_event == TRANSPORT_PREVIOUS)
+ else if (priv->motion_event == TRANSPORT_ACTION_PREVIOUS)
{
draw_gradient (cr,
X,
@@ -1296,7 +1393,7 @@ draw (GtkWidget* button, cairo_t *cr)
MIDDLE_START_PRELIGHT,
MIDDLE_END_PRELIGHT);
}
- else if (priv->motion_event == TRANSPORT_NEXT)
+ else if (priv->motion_event == TRANSPORT_ACTION_NEXT)
{
draw_gradient (cr,
RECT_WIDTH / 2 + X,
@@ -1324,7 +1421,7 @@ draw (GtkWidget* button, cairo_t *cr)
}
// play/pause shadow
- if(priv->current_command != TRANSPORT_PLAY_PAUSE)
+ if(priv->current_command != TRANSPORT_ACTION_PLAY_PAUSE)
{
cairo_save (cr);
cairo_rectangle (cr, X, Y, RECT_WIDTH, MIDDLE_RADIUS*2);
@@ -1341,7 +1438,7 @@ draw (GtkWidget* button, cairo_t *cr)
}
// play/pause button
- if(priv->current_command == TRANSPORT_PLAY_PAUSE)
+ if(priv->current_command == TRANSPORT_ACTION_PLAY_PAUSE)
{
draw_circle (cr,
X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f,
@@ -1357,7 +1454,7 @@ draw (GtkWidget* button, cairo_t *cr)
INNER_COMPRESSED_START,
INNER_COMPRESSED_END);
}
- else if (priv->motion_event == TRANSPORT_PLAY_PAUSE)
+ else if (priv->motion_event == TRANSPORT_ACTION_PLAY_PAUSE)
{
/* this subtle offset is to fix alpha borders, should be removed once this draw routine will be refactored */
draw_circle (cr,
@@ -1392,7 +1489,7 @@ draw (GtkWidget* button, cairo_t *cr)
}
// draw previous-button drop-shadow
- if (priv->has_focus && priv->key_event == TRANSPORT_PREVIOUS)
+ if (priv->has_focus && priv->key_event == TRANSPORT_ACTION_PREVIOUS)
{
_setup (&cr_surf, &surf, PREV_WIDTH+6, PREV_HEIGHT+6);
_mask_prev (cr_surf,
@@ -1452,7 +1549,7 @@ draw (GtkWidget* button, cairo_t *cr)
_finalize (cr, &cr_surf, &surf, PREV_X, PREV_Y);
// draw next-button drop-shadow
- if (priv->has_focus && priv->key_event == TRANSPORT_NEXT)
+ if (priv->has_focus && priv->key_event == TRANSPORT_ACTION_NEXT)
{
_setup (&cr_surf, &surf, NEXT_WIDTH+6, NEXT_HEIGHT+6);
_mask_next (cr_surf,
@@ -1512,9 +1609,10 @@ draw (GtkWidget* button, cairo_t *cr)
_finalize (cr, &cr_surf, &surf, NEXT_X, NEXT_Y);
// draw pause-button drop-shadow
- if(priv->current_state == PLAY)
+ if(priv->current_state == TRANSPORT_STATE_PLAYING)
{
- if (priv->has_focus && (priv->key_event == TRANSPORT_NADA || priv->key_event == TRANSPORT_PLAY_PAUSE))
+ if (priv->has_focus && (priv->key_event == TRANSPORT_ACTION_NO_ACTION ||
+ priv->key_event == TRANSPORT_ACTION_PLAY_PAUSE))
{
_setup (&cr_surf, &surf, PAUSE_WIDTH+6, PAUSE_HEIGHT+6);
_mask_pause (cr_surf,
@@ -1573,9 +1671,10 @@ draw (GtkWidget* button, cairo_t *cr)
TRUE);
_finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y);
}
- else if(priv->current_state == PAUSE)
+ else if(priv->current_state == TRANSPORT_STATE_PAUSED)
{
- if (priv->has_focus && (priv->key_event == TRANSPORT_NADA || priv->key_event == TRANSPORT_PLAY_PAUSE))
+ if (priv->has_focus && (priv->key_event == TRANSPORT_ACTION_NO_ACTION ||
+ priv->key_event == TRANSPORT_ACTION_PLAY_PAUSE))
{
_setup (&cr_surf, &surf, PLAY_WIDTH+6, PLAY_HEIGHT+6);
_mask_play (cr_surf,
@@ -1644,11 +1743,11 @@ transport_widget_set_twin_item(TransportWidget* self,
priv->twin_item = twin_item;
g_signal_connect(G_OBJECT(priv->twin_item), "property-changed",
G_CALLBACK(transport_widget_property_update), self);
- gint initial_state = dbusmenu_menuitem_property_get_int( twin_item,
+ gint initial_state = dbusmenu_menuitem_property_get_int (twin_item,
DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE );
//g_debug("TRANSPORT WIDGET - INITIAL UPDATE = %i", initial_state);
- transport_widget_toggle_play_pause( self,
- (TransportWidgetState)initial_state);
+ transport_widget_toggle_play_pause (self,
+ (TransportState)initial_state);
}
/**
@@ -1667,7 +1766,7 @@ transport_widget_property_update(DbusmenuMenuitem* item, gchar* property,
{
int update_value = g_variant_get_int32(value);
//g_debug("transport_widget_update_state - with value %i", update_value);
- transport_widget_toggle_play_pause(bar, (TransportWidgetState)update_value);
+ transport_widget_toggle_play_pause(bar, (TransportState)update_value);
}
}