diff options
Diffstat (limited to 'src/transport-widget.c')
-rw-r--r-- | src/transport-widget.c | 1886 |
1 files changed, 0 insertions, 1886 deletions
diff --git a/src/transport-widget.c b/src/transport-widget.c deleted file mode 100644 index ebe8282..0000000 --- a/src/transport-widget.c +++ /dev/null @@ -1,1886 +0,0 @@ -/* -Copyright 2010 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - Mirco Müller <mirco.mueller@canonical.com> - Andrea Cimitan <andrea.cimitan@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/>. - -Uses code from ctk -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <math.h> -#include "transport-widget.h" - - -#define RECT_WIDTH 130.0f -#define Y 7.0f -#define X 70.0f -#define INNER_RADIUS 12.5 -#define MIDDLE_RADIUS 13.0f -#define OUTER_RADIUS 14.5f -#define CIRCLE_RADIUS 21.0f -#define PREV_WIDTH 25.0f -#define PREV_HEIGHT 17.0f -#define NEXT_WIDTH 25.0f //PREV_WIDTH -#define NEXT_HEIGHT 17.0f //PREV_HEIGHT -#define TRI_WIDTH 11.0f -#define TRI_HEIGHT 13.0f -#define TRI_OFFSET 6.0f -#define PREV_X 68.0f -#define PREV_Y 13.0f -#define NEXT_X 146.0f -#define NEXT_Y 13.0f //prev_y -#define PAUSE_WIDTH 21.0f -#define PAUSE_HEIGHT 27.0f -#define BAR_WIDTH 4.5f -#define BAR_HEIGHT 24.0f -#define BAR_OFFSET 10.0f -#define PAUSE_X 111.0f -#define PAUSE_Y 7.0f -#define PLAY_WIDTH 28.0f -#define PLAY_HEIGHT 29.0f -#define PLAY_PADDING 5.0f -#define INNER_START_SHADE 0.98 -#define INNER_END_SHADE 0.98 -#define MIDDLE_START_SHADE 1.0 -#define MIDDLE_END_SHADE 1.0 -#define OUTER_START_SHADE 0.75 -#define OUTER_END_SHADE 1.3 -#define SHADOW_BUTTON_SHADE 0.8 -#define OUTER_PLAY_START_SHADE 0.7 -#define OUTER_PLAY_END_SHADE 1.38 -#define BUTTON_START_SHADE 1.1 -#define BUTTON_END_SHADE 0.9 -#define BUTTON_SHADOW_SHADE 0.8 -#define INNER_COMPRESSED_START_SHADE 1.0 -#define INNER_COMPRESSED_END_SHADE 1.0 - -typedef struct _TransportWidgetPrivate TransportWidgetPrivate; - -struct _TransportWidgetPrivate -{ - 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; -}; - -#if GTK_CHECK_VERSION(3, 0, 0) -static GList *transport_widget_list = NULL; -static GtkStyleContext *spinner_style_context = NULL; -static GtkWidgetPath *spinner_widget_path = NULL; -#endif - -// 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 */ -static void transport_widget_class_init (TransportWidgetClass *klass); -static void transport_widget_init (TransportWidget *self); -static void transport_widget_dispose (GObject *object); -static void transport_widget_finalize (GObject *object); -G_DEFINE_TYPE (TransportWidget, transport_widget, GTK_TYPE_MENU_ITEM); - -/* essentials */ -static void transport_widget_set_twin_item ( TransportWidget* self, - DbusmenuMenuitem* twin_item); -#if ! GTK_CHECK_VERSION(3, 0, 0) -static gboolean transport_widget_expose ( GtkWidget *button, GdkEventExpose *event); -#endif -static gboolean draw (GtkWidget* button, cairo_t *cr); - -/* UI and dbusmenu callbacks */ -static gboolean transport_widget_button_press_event (GtkWidget *menuitem, - GdkEventButton *event); -static gboolean transport_widget_button_release_event (GtkWidget *menuitem, - GdkEventButton *event); -static gboolean transport_widget_motion_notify_event (GtkWidget *menuitem, - GdkEventMotion *event); -static gboolean transport_widget_leave_notify_event (GtkWidget *menuitem, - GdkEventCrossing *event); -static void transport_widget_property_update ( DbusmenuMenuitem* item, - gchar * property, - GVariant * value, - gpointer userdata ); -static void transport_widget_menu_hidden ( GtkWidget *menu, - TransportWidget *transport); -static void transport_widget_notify ( GObject *item, - GParamSpec *pspec, - gpointer user_data ); -static TransportAction transport_widget_determine_button_event ( TransportWidget* button, - GdkEventButton* event); -static TransportAction transport_widget_determine_motion_event ( TransportWidget* button, - GdkEventMotion* event); -static void transport_widget_react_to_button_release ( TransportWidget* button, - TransportAction command); -static void transport_widget_toggle_play_pause ( TransportWidget* button, - TransportState update); -static void transport_widget_select (GtkWidget* menu, gpointer Userdata); -static void transport_widget_deselect (GtkWidget* menu, gpointer Userdata); -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 ////////////////////////////////////////////////////////// -static void -transport_widget_class_init (TransportWidgetClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass); - - g_type_class_add_private (klass, sizeof (TransportWidgetPrivate)); - - widget_class->button_press_event = transport_widget_button_press_event; - widget_class->button_release_event = transport_widget_button_release_event; - widget_class->motion_notify_event = transport_widget_motion_notify_event; - widget_class->leave_notify_event = transport_widget_leave_notify_event; -#if GTK_CHECK_VERSION(3, 0, 0) - widget_class->draw = draw; -#else - widget_class->expose_event = transport_widget_expose; -#endif - - gobject_class->dispose = transport_widget_dispose; - gobject_class->finalize = transport_widget_finalize; -} - -static void -transport_widget_init (TransportWidget *self) -{ - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(self); - #if GTK_CHECK_VERSION(3, 0, 0) - if (transport_widget_list == NULL){ - /* append the object to the static linked list. */ - transport_widget_list = g_list_append (transport_widget_list, self); - - /* create widget path */ - spinner_widget_path = gtk_widget_path_new(); - - gtk_widget_path_append_type (spinner_widget_path, GTK_TYPE_MENU); - gtk_widget_path_append_type (spinner_widget_path, GTK_TYPE_MENU_ITEM); - gint pos = gtk_widget_path_append_type (spinner_widget_path, GTK_TYPE_SPINNER); - gtk_widget_path_iter_set_name (spinner_widget_path, pos, "IndicatorSoundSpinner"); - - /* create style context and append path */ - spinner_style_context = gtk_style_context_new(); - - gtk_style_context_set_path (spinner_style_context, spinner_widget_path); - gtk_style_context_add_class (spinner_style_context, GTK_STYLE_CLASS_MENU); - gtk_style_context_add_class (spinner_style_context, GTK_STYLE_CLASS_MENUITEM); - gtk_style_context_add_class (spinner_style_context, GTK_STYLE_CLASS_SPINNER); - } - #endif - 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, - (GDestroyNotify)g_list_free); - GList* previous_list = NULL; - previous_list = g_list_insert(previous_list, GINT_TO_POINTER(15), 0); - previous_list = g_list_insert(previous_list, GINT_TO_POINTER(5), 1); - 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_ACTION_PREVIOUS), - previous_list); - - GList* play_list = NULL; - play_list = g_list_insert(play_list, GINT_TO_POINTER(58), 0); - play_list = g_list_insert(play_list, GINT_TO_POINTER(0), 1); - play_list = g_list_insert(play_list, GINT_TO_POINTER(50), 2); - play_list = g_list_insert(play_list, GINT_TO_POINTER(43), 3); - - g_hash_table_insert(priv->command_coordinates, - GINT_TO_POINTER(TRANSPORT_ACTION_PLAY_PAUSE), - play_list); - - GList* next_list = NULL; - next_list = g_list_insert(next_list, GINT_TO_POINTER(100), 0); - next_list = g_list_insert(next_list, GINT_TO_POINTER(5), 1); - next_list = g_list_insert(next_list, GINT_TO_POINTER(60), 2); - next_list = g_list_insert(next_list, GINT_TO_POINTER(34), 3); - - g_hash_table_insert(priv->command_coordinates, - GINT_TO_POINTER(TRANSPORT_ACTION_NEXT), - next_list); - gtk_widget_set_size_request(GTK_WIDGET(self), 200, 43); - g_signal_connect (G_OBJECT(self), - "notify", - G_CALLBACK (transport_widget_notify), - NULL); - g_signal_connect (G_OBJECT(self), - "select", - G_CALLBACK (transport_widget_select), - NULL); - g_signal_connect (G_OBJECT(self), - "deselect", - G_CALLBACK (transport_widget_deselect), - NULL); - gtk_widget_realize ( GTK_WIDGET (self) ); - -} - -static void -transport_widget_dispose (GObject *object) -{ - #if GTK_CHECK_VERSION(3, 0, 0) - transport_widget_list = g_list_remove (transport_widget_list, object); - - if (transport_widget_list == NULL){ - if (spinner_widget_path != NULL){ - gtk_widget_path_free (spinner_widget_path); - spinner_widget_path = NULL; - } - - if (spinner_style_context != NULL){ - g_object_unref (spinner_style_context); - spinner_style_context = NULL; - } - } - #endif - - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(object); - if (priv->command_coordinates != NULL) { - g_hash_table_destroy (priv->command_coordinates); - priv->command_coordinates = NULL; - } - - G_OBJECT_CLASS (transport_widget_parent_class)->dispose (object); -} - -static void -transport_widget_finalize (GObject *object) -{ - - - G_OBJECT_CLASS (transport_widget_parent_class)->finalize (object); -} - -#if ! GTK_CHECK_VERSION(3, 0, 0) -static gboolean -transport_widget_expose (GtkWidget *button, GdkEventExpose *event) -{ - cairo_t *cr; - cr = gdk_cairo_create (gtk_widget_get_window (button)); - - cairo_rectangle (cr, - event->area.x, event->area.y, - event->area.width, event->area.height); - - cairo_clip(cr); - draw (button, cr); - - cairo_destroy (cr); - return FALSE; -} -#endif - -gboolean -transport_widget_is_selected ( TransportWidget* widget ) -{ - g_return_val_if_fail (IS_TRANSPORT_WIDGET (widget), FALSE); - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(widget); - return priv->has_focus; -} - -static void -transport_widget_toggle_play_pause(TransportWidget* button, - TransportState update) -{ - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(button); - priv->current_state = update; - gtk_widget_queue_draw (GTK_WIDGET(button)); -} - -static void -transport_widget_notify ( GObject *item, - GParamSpec *pspec, - gpointer user_data ) -{ - if (g_strcmp0 (pspec->name, "parent")){ - GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (item)); - if (parent){ - g_signal_connect ( parent, "hide", - G_CALLBACK (transport_widget_menu_hidden), - item ); - } - } -} - -static void -transport_widget_menu_hidden ( GtkWidget *menu, - TransportWidget *transport) -{ - g_return_if_fail(IS_TRANSPORT_WIDGET(transport)); - transport_widget_react_to_button_release(transport, TRANSPORT_ACTION_NO_ACTION); -} - -static gboolean -transport_widget_motion_notify_event (GtkWidget *menuitem, - GdkEventMotion *event) -{ - //g_debug("transport_widget_motion_notify_event()"); - - g_return_val_if_fail ( IS_TRANSPORT_WIDGET(menuitem), FALSE ); - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE ( 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; -} - -static gboolean -transport_widget_leave_notify_event (GtkWidget *menuitem, - GdkEventCrossing *event) -{ - //g_debug("transport_widget_leave_notify_event()"); - - g_return_val_if_fail ( IS_TRANSPORT_WIDGET(menuitem), FALSE ); - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE ( TRANSPORT_WIDGET(menuitem) ); - - priv->motion_event = TRANSPORT_ACTION_NO_ACTION; - priv->current_command = TRANSPORT_ACTION_NO_ACTION; - gtk_widget_queue_draw (GTK_WIDGET(menuitem)); - - return TRUE; -} - -static gboolean -transport_widget_button_press_event (GtkWidget *menuitem, - GdkEventButton *event) -{ - //g_debug("transport_widget_button_press_event()"); - - g_return_val_if_fail ( IS_TRANSPORT_WIDGET(menuitem), FALSE ); - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE ( TRANSPORT_WIDGET(menuitem) ); - TransportAction result = transport_widget_determine_button_event ( TRANSPORT_WIDGET(menuitem), - event); - 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) -{ - g_return_val_if_fail(IS_TRANSPORT_WIDGET(menuitem), FALSE); - TransportWidget* transport = TRANSPORT_WIDGET(menuitem); - TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport ); - TransportAction result = transport_widget_determine_button_event ( transport, - event ); - 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", - new_transport_state, - 0 ); - } - transport_widget_react_to_button_release ( transport, - result ); - return TRUE; -} - -static void -transport_widget_select (GtkWidget* item, gpointer Userdata) -{ - TransportWidget* transport = TRANSPORT_WIDGET(item); - TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport ); - priv->has_focus = TRUE; -} - -static void -transport_widget_deselect (GtkWidget* item, gpointer Userdata) -{ - TransportWidget* transport = TRANSPORT_WIDGET(item); - TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport ); - priv->has_focus = FALSE; -} - -void -transport_widget_react_to_key_press_event ( TransportWidget* transport, - TransportAction transport_event ) -{ - 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, - TransportAction transport_event ) -{ - 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); - 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 ); -} - -void -transport_widget_focus_update ( TransportWidget* transport, gboolean focus ) -{ - TransportWidgetPrivate * priv = TRANSPORT_WIDGET_GET_PRIVATE ( transport ); - priv->has_focus = focus; -} - -static TransportAction -transport_widget_determine_button_event( TransportWidget* button, - GdkEventButton* event ) -{ - return transport_widget_collision_detection (event->x, event->y); -} - -static TransportAction -transport_widget_determine_motion_event( TransportWidget* button, - GdkEventMotion* event ) -{ - return transport_widget_collision_detection (event->x, event->y); -} - -static TransportAction -transport_widget_collision_detection ( gint x, - gint y ) -{ - TransportAction event = TRANSPORT_ACTION_NO_ACTION; - - if (x > 57 && x < 102 - && y > 12 && y < 40){ - event = TRANSPORT_ACTION_PREVIOUS; - } - else if (x > 101 && x < 143 - && y > 5 && y < 47){ - event = TRANSPORT_ACTION_PLAY_PAUSE; - } - else if (x > 142 && x < 187 - && y > 12 && y < 40){ - event = TRANSPORT_ACTION_NEXT; - } - return event; -} - -static void -transport_widget_react_to_button_release ( TransportWidget* button, - TransportAction command ) -{ - g_return_if_fail(IS_TRANSPORT_WIDGET(button)); - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(button); - - 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 ////////////////////////////////////////////////// - -static void -draw_gradient (cairo_t* cr, - double x, - double y, - double w, - double r, - double* rgba_start, - double* rgba_end) -{ - cairo_pattern_t* pattern = NULL; - - cairo_move_to (cr, x, y); - cairo_line_to (cr, x + w - 2.0f * r, y); - cairo_arc (cr, - x + w - 2.0f * r, - y + r, - r, - -90.0f * G_PI / 180.0f, - 90.0f * G_PI / 180.0f); - cairo_line_to (cr, x, y + 2.0f * r); - cairo_arc (cr, - x, - y + r, - r, - 90.0f * G_PI / 180.0f, - 270.0f * G_PI / 180.0f); - cairo_close_path (cr); - - pattern = cairo_pattern_create_linear (x, y, x, y + 2.0f * r); - cairo_pattern_add_color_stop_rgba (pattern, - 0.0f, - rgba_start[0], - rgba_start[1], - rgba_start[2], - rgba_start[3]); - cairo_pattern_add_color_stop_rgba (pattern, - 1.0f, - rgba_end[0], - rgba_end[1], - rgba_end[2], - rgba_end[3]); - cairo_set_source (cr, pattern); - cairo_fill (cr); - cairo_pattern_destroy (pattern); -} - -static void -draw_circle (cairo_t* cr, - double x, - double y, - double r, - double* rgba_start, - double* rgba_end) -{ - cairo_pattern_t* pattern = NULL; - - cairo_move_to (cr, x, y); - cairo_arc (cr, - x + r, - y + r, - r, - 0.0f * G_PI / 180.0f, - 360.0f * G_PI / 180.0f); - - pattern = cairo_pattern_create_linear (x, y, x, y + 2.0f * r); - cairo_pattern_add_color_stop_rgba (pattern, - 0.0f, - rgba_start[0], - rgba_start[1], - rgba_start[2], - rgba_start[3]); - cairo_pattern_add_color_stop_rgba (pattern, - 1.0f, - rgba_end[0], - rgba_end[1], - rgba_end[2], - rgba_end[3]); - cairo_set_source (cr, pattern); - cairo_fill (cr); - cairo_pattern_destroy (pattern); -} - -static void -_setup (cairo_t** cr, - cairo_surface_t** surf, - gint width, - gint height) -{ - if (!cr || !surf) - return; - - *surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - *cr = cairo_create (*surf); - cairo_scale (*cr, 1.0f, 1.0f); - cairo_set_operator (*cr, CAIRO_OPERATOR_CLEAR); - cairo_paint (*cr); - cairo_set_operator (*cr, CAIRO_OPERATOR_OVER); -} - -static void -_mask_prev (cairo_t* cr, - double x, - double y, - double tri_width, - double tri_height, - double tri_offset) -{ - if (!cr) - return; - - cairo_move_to (cr, x, y + tri_height / 2.0f); - cairo_line_to (cr, x + tri_width, y); - cairo_line_to (cr, x + tri_width, y + tri_height); - x += tri_offset; - cairo_move_to (cr, x, y + tri_height / 2.0f); - cairo_line_to (cr, x + tri_width, y); - cairo_line_to (cr, x + tri_width, y + tri_height); - x -= tri_offset; - cairo_rectangle (cr, x, y, 2.5f, tri_height); - cairo_close_path (cr); -} - -static void -_mask_next (cairo_t* cr, - double x, - double y, - double tri_width, - double tri_height, - double tri_offset) -{ - if (!cr) - return; - - cairo_move_to (cr, x, y); - cairo_line_to (cr, x + tri_width, y + tri_height / 2.0f); - cairo_line_to (cr, x, y + tri_height); - x += tri_offset; - cairo_move_to (cr, x, y); - cairo_line_to (cr, x + tri_width, y + tri_height / 2.0f); - cairo_line_to (cr, x, y + tri_height); - x -= tri_offset; - x += 2.0f * tri_width - tri_offset - 1.0f; - cairo_rectangle (cr, x, y, 2.5f, tri_height); - - cairo_close_path (cr); -} - -static void -_mask_pause (cairo_t* cr, - double x, - double y, - double bar_width, - double bar_height, - double bar_offset) -{ - if (!cr) - return; - - cairo_set_line_width (cr, bar_width); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - - x += bar_width; - y += bar_width; - cairo_move_to (cr, x, y); - cairo_line_to (cr, x, y + bar_height); - cairo_move_to (cr, x + bar_offset, y); - cairo_line_to (cr, x + bar_offset, y + bar_height); - -} - -static void -_mask_play (cairo_t* cr, - double x, - double y, - double tri_width, - double tri_height) -{ - if (!cr) - return; - - cairo_move_to (cr, x, y); - cairo_line_to (cr, x + tri_width, y + tri_height / 2.0f); - cairo_line_to (cr, x, y + tri_height); - cairo_close_path (cr); - -} - -static void -_fill (cairo_t* cr, - double x_start, - double y_start, - double x_end, - double y_end, - double* rgba_start, - double* rgba_end, - gboolean stroke) -{ - cairo_pattern_t* pattern = NULL; - - if (!cr || !rgba_start || !rgba_end) - return; - - pattern = cairo_pattern_create_linear (x_start, y_start, x_end, y_end); - cairo_pattern_add_color_stop_rgba (pattern, - 0.0f, - rgba_start[0], - rgba_start[1], - rgba_start[2], - rgba_start[3]); - cairo_pattern_add_color_stop_rgba (pattern, - 1.0f, - rgba_end[0], - rgba_end[1], - rgba_end[2], - rgba_end[3]); - cairo_set_source (cr, pattern); - if (stroke) - cairo_stroke (cr); - else - cairo_fill (cr); - cairo_pattern_destroy (pattern); -} - -static void -_finalize (cairo_t* cr, - cairo_t** cr_surf, - cairo_surface_t** surf, - double x, - double y) -{ - if (!cr || !cr_surf || !surf) - return; - - cairo_set_source_surface (cr, *surf, x, y); - cairo_paint (cr); - cairo_surface_destroy (*surf); - cairo_destroy (*cr_surf); -} - -static void -_finalize_repaint (cairo_t* cr, - cairo_t** cr_surf, - cairo_surface_t** surf, - double x, - double y, - int repaints) -{ - if (!cr || !cr_surf || !surf) - return; - - while (repaints > 0) - { - cairo_set_source_surface (cr, *surf, x, y); - cairo_paint (cr); - repaints--; - } - - cairo_surface_destroy (*surf); - cairo_destroy (*cr_surf); -} - -static void -_color_rgb_to_hls (gdouble *r, - gdouble *g, - gdouble *b) -{ - gdouble min; - gdouble max; - gdouble red; - gdouble green; - gdouble blue; - gdouble h = 0; - gdouble l; - gdouble s; - gdouble delta; - - red = *r; - green = *g; - blue = *b; - - if (red > green) - { - if (red > blue) - max = red; - else - max = blue; - - if (green < blue) - min = green; - else - min = blue; - } - else - { - if (green > blue) - max = green; - else - max = blue; - - if (red < blue) - min = red; - else - min = blue; - } - l = (max+min)/2; - if (fabs (max-min) < 0.0001) - { - h = 0; - s = 0; - } - else - { - if (l <= 0.5) - s = (max-min)/(max+min); - else - s = (max-min)/(2-max-min); - - delta = (max -min) != 0 ? (max -min) : 1; - - if(delta == 0) - delta = 1; - if (red == max) - h = (green-blue)/delta; - else if (green == max) - h = 2+(blue-red)/delta; - else if (blue == max) - h = 4+(red-green)/delta; - - h *= 60; - if (h < 0.0) - h += 360; - } - - *r = h; - *g = l; - *b = s; -} - -static void -_color_hls_to_rgb (gdouble *h, - gdouble *l, - gdouble *s) -{ - gdouble hue; - gdouble lightness; - gdouble saturation; - gdouble m1, m2; - gdouble r, g, b; - - lightness = *l; - saturation = *s; - - if (lightness <= 0.5) - m2 = lightness*(1+saturation); - else - m2 = lightness+saturation-lightness*saturation; - - m1 = 2*lightness-m2; - - if (saturation == 0) - { - *h = lightness; - *l = lightness; - *s = lightness; - } - else - { - hue = *h+120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - r = m1+(m2-m1)*hue/60; - else if (hue < 180) - r = m2; - else if (hue < 240) - r = m1+(m2-m1)*(240-hue)/60; - else - r = m1; - - hue = *h; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - g = m1+(m2-m1)*hue/60; - else if (hue < 180) - g = m2; - else if (hue < 240) - g = m1+(m2-m1)*(240-hue)/60; - else - g = m1; - - hue = *h-120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - b = m1+(m2-m1)*hue/60; - else if (hue < 180) - b = m2; - else if (hue < 240) - b = m1+(m2-m1)*(240-hue)/60; - else - b = m1; - - *h = r; - *l = g; - *s = b; - } -} - -void -_color_shade (const CairoColorRGB *a, float k, CairoColorRGB *b) -{ - double red; - double green; - double blue; - - red = a->r; - green = a->g; - blue = a->b; - - if (k == 1.0) - { - b->r = red; - b->g = green; - b->b = blue; - return; - } - - _color_rgb_to_hls (&red, &green, &blue); - - green *= k; - if (green > 1.0) - green = 1.0; - else if (green < 0.0) - green = 0.0; - - blue *= k; - if (blue > 1.0) - blue = 1.0; - else if (blue < 0.0) - blue = 0.0; - - _color_hls_to_rgb (&red, &green, &blue); - - b->r = red; - b->g = green; - b->b = blue; -} - -static inline void -_blurinner (guchar* pixel, - gint* zR, - gint* zG, - gint* zB, - gint* zA, - gint alpha, - gint aprec, - gint zprec) -{ - gint R; - gint G; - gint B; - guchar A; - - R = *pixel; - G = *(pixel + 1); - B = *(pixel + 2); - A = *(pixel + 3); - - *zR += (alpha * ((R << zprec) - *zR)) >> aprec; - *zG += (alpha * ((G << zprec) - *zG)) >> aprec; - *zB += (alpha * ((B << zprec) - *zB)) >> aprec; - *zA += (alpha * ((A << zprec) - *zA)) >> aprec; - - *pixel = *zR >> zprec; - *(pixel + 1) = *zG >> zprec; - *(pixel + 2) = *zB >> zprec; - *(pixel + 3) = *zA >> zprec; -} - -static inline void -_blurrow (guchar* pixels, - gint width, - gint height, - gint channels, - gint line, - gint alpha, - gint aprec, - gint zprec) -{ - gint zR; - gint zG; - gint zB; - gint zA; - gint index; - guchar* scanline; - - scanline = &(pixels[line * width * channels]); - - zR = *scanline << zprec; - zG = *(scanline + 1) << zprec; - zB = *(scanline + 2) << zprec; - zA = *(scanline + 3) << zprec; - - for (index = 0; index < width; index ++) - _blurinner (&scanline[index * channels], - &zR, - &zG, - &zB, - &zA, - alpha, - aprec, - zprec); - - for (index = width - 2; index >= 0; index--) - _blurinner (&scanline[index * channels], - &zR, - &zG, - &zB, - &zA, - alpha, - aprec, - zprec); -} - -static inline void -_blurcol (guchar* pixels, - gint width, - gint height, - gint channels, - gint x, - gint alpha, - gint aprec, - gint zprec) -{ - gint zR; - gint zG; - gint zB; - gint zA; - gint index; - guchar* ptr; - - ptr = pixels; - - ptr += x * channels; - - zR = *((guchar*) ptr ) << zprec; - zG = *((guchar*) ptr + 1) << zprec; - zB = *((guchar*) ptr + 2) << zprec; - zA = *((guchar*) ptr + 3) << zprec; - - for (index = width; index < (height - 1) * width; index += width) - _blurinner ((guchar*) &ptr[index * channels], - &zR, - &zG, - &zB, - &zA, - alpha, - aprec, - zprec); - - for (index = (height - 2) * width; index >= 0; index -= width) - _blurinner ((guchar*) &ptr[index * channels], - &zR, - &zG, - &zB, - &zA, - alpha, - aprec, - zprec); -} - -void -_expblur (guchar* pixels, - gint width, - gint height, - gint channels, - gint radius, - gint aprec, - gint zprec) -{ - gint alpha; - gint row = 0; - gint col = 0; - - if (radius < 1) - return; - - // calculate the alpha such that 90% of - // the kernel is within the radius. - // (Kernel extends to infinity) - alpha = (gint) ((1 << aprec) * (1.0f - expf (-2.3f / (radius + 1.f)))); - - for (; row < height; row++) - _blurrow (pixels, - width, - height, - channels, - row, - alpha, - aprec, - zprec); - - for(; col < width; col++) - _blurcol (pixels, - width, - height, - channels, - col, - alpha, - aprec, - zprec); - - return; -} - -void -_surface_blur (cairo_surface_t* surface, - guint radius) -{ - guchar* pixels; - guint width; - guint height; - cairo_format_t format; - - // before we mess with the surface execute any pending drawing - cairo_surface_flush (surface); - - pixels = cairo_image_surface_get_data (surface); - width = cairo_image_surface_get_width (surface); - height = cairo_image_surface_get_height (surface); - format = cairo_image_surface_get_format (surface); - - switch (format) - { - case CAIRO_FORMAT_ARGB32: - _expblur (pixels, width, height, 4, radius, 16, 7); - break; - - case CAIRO_FORMAT_RGB24: - _expblur (pixels, width, height, 3, radius, 16, 7); - break; - - case CAIRO_FORMAT_A8: - _expblur (pixels, width, height, 1, radius, 16, 7); - break; - - default : - // do nothing - break; - } - - // inform cairo we altered the surfaces contents - cairo_surface_mark_dirty (surface); -} - -static gboolean -draw (GtkWidget* button, cairo_t *cr) -{ - g_return_val_if_fail(IS_TRANSPORT_WIDGET(button), FALSE); - g_return_val_if_fail(cr != NULL, FALSE); - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(button); - - //g_debug("transport-widget draw()"); - - cairo_surface_t* surf = NULL; - cairo_t* cr_surf = NULL; - -#if ! GTK_CHECK_VERSION(3, 0, 0) - GtkAllocation allocation; - gtk_widget_get_allocation (button, &allocation); - cairo_translate (cr, allocation.x, allocation.y); -#endif - - GtkStyle *style; - -#if GTK_CHECK_VERSION(3, 0, 0) - gtk_style_context_add_class (gtk_widget_get_style_context (button), - GTK_STYLE_CLASS_MENU); -#endif - CairoColorRGB bg_color, fg_color, bg_selected, bg_prelight; - CairoColorRGB color_middle[2], color_middle_prelight[2], color_outer[2], color_outer_prelight[2], - color_play_outer[2], color_play_outer_prelight[2], - color_button[4], color_button_shadow, color_inner[2], color_inner_compressed[2]; - - /* Use the menu's style instead of that of the menuitem ('button' is a - * menuitem that is packed in a menu directly). The menuitem's style - * can't be used due to a change in light-themes (lp #1130183). - * Menuitems now have a transparent background, which confuses - * GtkStyle. - * - * This is a workaround until this code gets refactored to use - * GtkStyleContext. - */ - style = gtk_widget_get_style (gtk_widget_get_parent (button)); - - bg_color.r = style->bg[0].red/65535.0; - bg_color.g = style->bg[0].green/65535.0; - bg_color.b = style->bg[0].blue/65535.0; - - bg_prelight.r = style->bg[GTK_STATE_PRELIGHT].red/65535.0; - bg_prelight.g = style->bg[GTK_STATE_PRELIGHT].green/65535.0; - bg_prelight.b = style->bg[GTK_STATE_PRELIGHT].blue/65535.0; - - bg_selected.r = style->bg[GTK_STATE_SELECTED].red/65535.0; - bg_selected.g = style->bg[GTK_STATE_SELECTED].green/65535.0; - bg_selected.b = style->bg[GTK_STATE_SELECTED].blue/65535.0; - - fg_color.r = style->fg[0].red/65535.0; - fg_color.g = style->fg[0].green/65535.0; - fg_color.b = style->fg[0].blue/65535.0; - - _color_shade (&bg_color, MIDDLE_START_SHADE, &color_middle[0]); - _color_shade (&bg_color, MIDDLE_END_SHADE, &color_middle[1]); - _color_shade (&bg_prelight, MIDDLE_START_SHADE, &color_middle_prelight[0]); - _color_shade (&bg_prelight, MIDDLE_END_SHADE, &color_middle_prelight[1]); - _color_shade (&bg_color, OUTER_START_SHADE, &color_outer[0]); - _color_shade (&bg_color, OUTER_END_SHADE, &color_outer[1]); - _color_shade (&bg_prelight, OUTER_START_SHADE, &color_outer_prelight[0]); - _color_shade (&bg_prelight, OUTER_END_SHADE, &color_outer_prelight[1]); - _color_shade (&bg_color, OUTER_PLAY_START_SHADE, &color_play_outer[0]); - _color_shade (&bg_color, OUTER_PLAY_END_SHADE, &color_play_outer[1]); - _color_shade (&bg_prelight, OUTER_PLAY_START_SHADE, &color_play_outer_prelight[0]); - _color_shade (&bg_prelight, OUTER_PLAY_END_SHADE, &color_play_outer_prelight[1]); - _color_shade (&bg_color, INNER_START_SHADE, &color_inner[0]); - _color_shade (&bg_color, INNER_END_SHADE, &color_inner[1]); - _color_shade (&fg_color, BUTTON_START_SHADE, &color_button[0]); - _color_shade (&fg_color, BUTTON_END_SHADE, &color_button[1]); - _color_shade (&bg_color, BUTTON_SHADOW_SHADE, &color_button[2]); - _color_shade (&bg_color, SHADOW_BUTTON_SHADE, &color_button_shadow); - _color_shade (&bg_selected, 1.0, &color_button[3]); - _color_shade (&bg_color, INNER_COMPRESSED_START_SHADE, &color_inner_compressed[0]); - _color_shade (&bg_color, INNER_COMPRESSED_END_SHADE, &color_inner_compressed[1]); - - double MIDDLE_END[] = {color_middle[0].r, color_middle[0].g, color_middle[0].b, 1.0f}; - double MIDDLE_START[] = {color_middle[1].r, color_middle[1].g, color_middle[1].b, 1.0f}; - double MIDDLE_END_PRELIGHT[] = {color_middle_prelight[0].r, color_middle_prelight[0].g, color_middle_prelight[0].b, 1.0f}; - double MIDDLE_START_PRELIGHT[] = {color_middle_prelight[1].r, color_middle_prelight[1].g, color_middle_prelight[1].b, 1.0f}; - double OUTER_END[] = {color_outer[0].r, color_outer[0].g, color_outer[0].b, 1.0f}; - double OUTER_START[] = {color_outer[1].r, color_outer[1].g, color_outer[1].b, 1.0f}; - double OUTER_END_PRELIGHT[] = {color_outer_prelight[0].r, color_outer_prelight[0].g, color_outer_prelight[0].b, 1.0f}; - double OUTER_START_PRELIGHT[] = {color_outer_prelight[1].r, color_outer_prelight[1].g, color_outer_prelight[1].b, 1.0f}; - double SHADOW_BUTTON[] = {color_button_shadow.r, color_button_shadow.g, color_button_shadow.b, 0.3f}; - double OUTER_PLAY_END[] = {color_play_outer[0].r, color_play_outer[0].g, color_play_outer[0].b, 1.0f}; - double OUTER_PLAY_START[] = {color_play_outer[1].r, color_play_outer[1].g, color_play_outer[1].b, 1.0f}; - double OUTER_PLAY_END_PRELIGHT[] = {color_play_outer_prelight[0].r, color_play_outer_prelight[0].g, color_play_outer_prelight[0].b, 1.0f}; - double OUTER_PLAY_START_PRELIGHT[] = {color_play_outer_prelight[1].r, color_play_outer_prelight[1].g, color_play_outer_prelight[1].b, 1.0f}; - double BUTTON_END[] = {color_button[0].r, color_button[0].g, color_button[0].b, 1.0f}; - double BUTTON_START[] = {color_button[1].r, color_button[1].g, color_button[1].b, 1.0f}; - double BUTTON_SHADOW[] = {color_button[2].r, color_button[2].g, color_button[2].b, 0.75f}; - double BUTTON_SHADOW_FOCUS[] = {color_button[3].r, color_button[3].g, color_button[3].b, 1.0f}; - double INNER_COMPRESSED_END[] = {color_inner_compressed[1].r, color_inner_compressed[1].g, color_inner_compressed[1].b, 1.0f}; - double INNER_COMPRESSED_START[] = {color_inner_compressed[0].r, color_inner_compressed[0].g, color_inner_compressed[0].b, 1.0f}; - - - draw_gradient (cr, - X, - Y, - RECT_WIDTH, - OUTER_RADIUS, - OUTER_START, - OUTER_END); - - draw_gradient (cr, - X, - Y + 1, - RECT_WIDTH - 2, - MIDDLE_RADIUS, - MIDDLE_START, - MIDDLE_END); - - draw_gradient (cr, - X, - Y + 2, - RECT_WIDTH - 4, - MIDDLE_RADIUS, - MIDDLE_START, - MIDDLE_END); - - //prev/next button - if(priv->current_command == TRANSPORT_ACTION_PREVIOUS) - { - draw_gradient (cr, - X, - Y, - RECT_WIDTH/2, - OUTER_RADIUS, - OUTER_END, - OUTER_START); - - draw_gradient (cr, - X, - Y + 1, - RECT_WIDTH/2, - MIDDLE_RADIUS, - INNER_COMPRESSED_START, - INNER_COMPRESSED_END); - - draw_gradient (cr, - X, - Y + 2, - RECT_WIDTH/2, - MIDDLE_RADIUS, - INNER_COMPRESSED_START, - INNER_COMPRESSED_END); - } - else if(priv->current_command == TRANSPORT_ACTION_NEXT) - { - draw_gradient (cr, - RECT_WIDTH / 2 + X, - Y, - RECT_WIDTH/2, - OUTER_RADIUS, - OUTER_END, - OUTER_START); - - draw_gradient (cr, - RECT_WIDTH / 2 + X, - Y + 1, - (RECT_WIDTH - 4.5)/2, - MIDDLE_RADIUS, - INNER_COMPRESSED_START, - INNER_COMPRESSED_END); - - draw_gradient (cr, - RECT_WIDTH / 2 + X, - Y + 2, - (RECT_WIDTH - 7)/2, - MIDDLE_RADIUS, - INNER_COMPRESSED_START, - INNER_COMPRESSED_END); - } - else if (priv->motion_event == TRANSPORT_ACTION_PREVIOUS) - { - draw_gradient (cr, - X, - Y, - RECT_WIDTH/2, - OUTER_RADIUS, - OUTER_START_PRELIGHT, - OUTER_END_PRELIGHT); - - draw_gradient (cr, - X, - Y + 1, - RECT_WIDTH/2, - MIDDLE_RADIUS, - MIDDLE_START_PRELIGHT, - MIDDLE_END_PRELIGHT); - - draw_gradient (cr, - X, - Y + 2, - RECT_WIDTH/2, - MIDDLE_RADIUS, - MIDDLE_START_PRELIGHT, - MIDDLE_END_PRELIGHT); - } - else if (priv->motion_event == TRANSPORT_ACTION_NEXT) - { - draw_gradient (cr, - RECT_WIDTH / 2 + X, - Y, - RECT_WIDTH/2, - OUTER_RADIUS, - OUTER_START_PRELIGHT, - OUTER_END_PRELIGHT); - - draw_gradient (cr, - RECT_WIDTH / 2 + X, - Y + 1, - (RECT_WIDTH - 4.5)/2, - MIDDLE_RADIUS, - MIDDLE_START_PRELIGHT, - MIDDLE_END_PRELIGHT); - - draw_gradient (cr, - RECT_WIDTH / 2 + X, - Y + 2, - (RECT_WIDTH - 7)/2, - MIDDLE_RADIUS, - MIDDLE_START_PRELIGHT, - MIDDLE_END_PRELIGHT); - } - - // play/pause shadow - if(priv->current_command != TRANSPORT_ACTION_PLAY_PAUSE) - { - cairo_save (cr); - cairo_rectangle (cr, X, Y, RECT_WIDTH, MIDDLE_RADIUS*2); - cairo_clip (cr); - - draw_circle (cr, - X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f - 1.0f, - Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) - 1.0f, - CIRCLE_RADIUS + 1.0f, - SHADOW_BUTTON, - SHADOW_BUTTON); - - cairo_restore (cr); - } - - // play/pause button - if(priv->current_command == TRANSPORT_ACTION_PLAY_PAUSE) - { - draw_circle (cr, - X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f, - Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) , - CIRCLE_RADIUS, - OUTER_PLAY_END, - OUTER_PLAY_START); - - draw_circle (cr, - X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 1.25f, - Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.25f, - CIRCLE_RADIUS - 1.25, - INNER_COMPRESSED_START, - INNER_COMPRESSED_END); - } - 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, - X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 0.1, - Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 0.1, - CIRCLE_RADIUS - 0.1, - OUTER_PLAY_START_PRELIGHT, - OUTER_PLAY_END_PRELIGHT); - - draw_circle (cr, - X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 1.25f, - Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.25f, - CIRCLE_RADIUS - 1.25, - MIDDLE_START_PRELIGHT, - MIDDLE_END_PRELIGHT); - } - else - { - draw_circle (cr, - X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f, - Y - ((CIRCLE_RADIUS - OUTER_RADIUS)), - CIRCLE_RADIUS, - OUTER_PLAY_START, - OUTER_PLAY_END); - - draw_circle (cr, - X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 1.25f, - Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.25f, - CIRCLE_RADIUS - 1.25, - MIDDLE_START, - MIDDLE_END); - } - - // draw previous-button drop-shadow - if (priv->has_focus && priv->key_event == TRANSPORT_ACTION_PREVIOUS) - { - _setup (&cr_surf, &surf, PREV_WIDTH+6, PREV_HEIGHT+6); - _mask_prev (cr_surf, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, - TRI_WIDTH, - TRI_HEIGHT, - TRI_OFFSET); - _fill (cr_surf, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (double) TRI_HEIGHT, - BUTTON_SHADOW_FOCUS, - BUTTON_SHADOW_FOCUS, - FALSE); - _surface_blur (surf, 3); - _finalize_repaint (cr, &cr_surf, &surf, PREV_X, PREV_Y + 0.5f, 3); - } - else - { - _setup (&cr_surf, &surf, PREV_WIDTH, PREV_HEIGHT); - _mask_prev (cr_surf, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, - TRI_WIDTH, - TRI_HEIGHT, - TRI_OFFSET); - _fill (cr_surf, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (double) TRI_HEIGHT, - BUTTON_SHADOW, - BUTTON_SHADOW, - FALSE); - _surface_blur (surf, 1); - _finalize (cr, &cr_surf, &surf, PREV_X, PREV_Y + 1.0f); - } - - // draw previous-button - _setup (&cr_surf, &surf, PREV_WIDTH, PREV_HEIGHT); - _mask_prev (cr_surf, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, - TRI_WIDTH, - TRI_HEIGHT, - TRI_OFFSET); - _fill (cr_surf, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, - (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (double) TRI_HEIGHT, - BUTTON_START, - BUTTON_END, - FALSE); - _finalize (cr, &cr_surf, &surf, PREV_X, PREV_Y); - - // draw next-button drop-shadow - if (priv->has_focus && priv->key_event == TRANSPORT_ACTION_NEXT) - { - _setup (&cr_surf, &surf, NEXT_WIDTH+6, NEXT_HEIGHT+6); - _mask_next (cr_surf, - (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, - TRI_WIDTH, - TRI_HEIGHT, - TRI_OFFSET); - _fill (cr_surf, - (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, - (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (double) TRI_HEIGHT, - BUTTON_SHADOW_FOCUS, - BUTTON_SHADOW_FOCUS, - FALSE); - _surface_blur (surf, 3); - _finalize_repaint (cr, &cr_surf, &surf, NEXT_X, NEXT_Y + 0.5f, 3); - } - else - { - _setup (&cr_surf, &surf, NEXT_WIDTH, NEXT_HEIGHT); - _mask_next (cr_surf, - (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, - TRI_WIDTH, - TRI_HEIGHT, - TRI_OFFSET); - _fill (cr_surf, - (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, - (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (double) TRI_HEIGHT, - BUTTON_SHADOW, - BUTTON_SHADOW, - FALSE); - _surface_blur (surf, 1); - _finalize (cr, &cr_surf, &surf, NEXT_X, NEXT_Y + 1.0f); - } - - // draw next-button - _setup (&cr_surf, &surf, NEXT_WIDTH, NEXT_HEIGHT); - _mask_next (cr_surf, - (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, - TRI_WIDTH, - TRI_HEIGHT, - TRI_OFFSET); - _fill (cr_surf, - (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, - (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, - (double) TRI_HEIGHT, - BUTTON_START, - BUTTON_END, - FALSE); - _finalize (cr, &cr_surf, &surf, NEXT_X, NEXT_Y); - - // draw pause-button drop-shadow - if(priv->current_state == TRANSPORT_STATE_PLAYING) - { - 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, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - BAR_WIDTH, - BAR_HEIGHT - 2.0f * BAR_WIDTH, - BAR_OFFSET); - _fill (cr_surf, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (double) BAR_HEIGHT, - BUTTON_SHADOW_FOCUS, - BUTTON_SHADOW_FOCUS, - TRUE); - _surface_blur (surf, 3); - _finalize_repaint (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y + 0.5f, 3); - } - else - { - _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT); - _mask_pause (cr_surf, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - BAR_WIDTH, - BAR_HEIGHT - 2.0f * BAR_WIDTH, - BAR_OFFSET); - _fill (cr_surf, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (double) BAR_HEIGHT, - BUTTON_SHADOW, - BUTTON_SHADOW, - TRUE); - _surface_blur (surf, 1); - _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y + 1.0f); - } - - // draw pause-button - _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT); - _mask_pause (cr_surf, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - BAR_WIDTH, - BAR_HEIGHT - 2.0f * BAR_WIDTH, - BAR_OFFSET); - _fill (cr_surf, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, - (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, - (double) BAR_HEIGHT, - BUTTON_START, - BUTTON_END, - TRUE); - _finalize (cr, &cr_surf, &surf, PAUSE_X, PAUSE_Y); - } - else if(priv->current_state == TRANSPORT_STATE_PAUSED) - { - 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, - PLAY_PADDING, - PLAY_PADDING, - PLAY_WIDTH - (2*PLAY_PADDING), - PLAY_HEIGHT - (2*PLAY_PADDING)); - _fill (cr_surf, - PLAY_PADDING, - PLAY_PADDING, - PLAY_WIDTH - (2*PLAY_PADDING), - PLAY_HEIGHT - (2*PLAY_PADDING), - BUTTON_SHADOW_FOCUS, - BUTTON_SHADOW_FOCUS, - FALSE); - _surface_blur (surf, 3); - _finalize_repaint (cr, &cr_surf, &surf, PAUSE_X-0.5f, PAUSE_Y + 0.5f, 3); - } - else - { - _setup (&cr_surf, &surf, PLAY_WIDTH, PLAY_HEIGHT); - _mask_play (cr_surf, - PLAY_PADDING, - PLAY_PADDING, - PLAY_WIDTH - (2*PLAY_PADDING), - PLAY_HEIGHT - (2*PLAY_PADDING)); - _fill (cr_surf, - PLAY_PADDING, - PLAY_PADDING, - PLAY_WIDTH - (2*PLAY_PADDING), - PLAY_HEIGHT - (2*PLAY_PADDING), - BUTTON_SHADOW, - BUTTON_SHADOW, - FALSE); - _surface_blur (surf, 1); - _finalize (cr, &cr_surf, &surf, PAUSE_X-0.75f, PAUSE_Y + 1.0f); - } - - // draw play-button - _setup (&cr_surf, &surf, PLAY_WIDTH, PLAY_HEIGHT); - cairo_set_line_width (cr, 10.5); - cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); - cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); - _mask_play (cr_surf, - PLAY_PADDING, - PLAY_PADDING, - PLAY_WIDTH - (2*PLAY_PADDING), - PLAY_HEIGHT - (2*PLAY_PADDING)); - _fill (cr_surf, - PLAY_PADDING, - PLAY_PADDING, - PLAY_WIDTH - (2*PLAY_PADDING), - PLAY_HEIGHT - (2*PLAY_PADDING), - BUTTON_START, - BUTTON_END, - FALSE); - _finalize (cr, &cr_surf, &surf, PAUSE_X-0.5f, PAUSE_Y); - } - #if GTK_CHECK_VERSION(3, 0, 0) - else if(priv->current_state == TRANSPORT_STATE_LAUNCHING) - { - // the spinner is not aligned, why? because the play button has odd width/height numbers - gtk_render_activity (spinner_style_context, cr, 106, 6, 30, 30); - } - #endif - return FALSE; -} - -static void -transport_widget_set_twin_item(TransportWidget* self, - DbusmenuMenuitem* twin_item) -{ - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(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, - DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE ); - //g_debug("TRANSPORT WIDGET - INITIAL UPDATE = %i", initial_state); - transport_widget_toggle_play_pause (self, - (TransportState)initial_state); -} - -/** -* transport_widget_update_state() -* Callback for updates from the other side of dbus -**/ -static void -transport_widget_property_update(DbusmenuMenuitem* item, gchar* property, - GVariant* value, gpointer userdata) -{ - //g_debug("transport_widget_update_state - with property %s", property); - TransportWidget* bar = (TransportWidget*)userdata; - g_return_if_fail(IS_TRANSPORT_WIDGET(bar)); - TransportWidgetPrivate* priv = TRANSPORT_WIDGET_GET_PRIVATE(bar); - - if(g_ascii_strcasecmp(DBUSMENU_TRANSPORT_MENUITEM_PLAY_STATE, property) == 0) - { - TransportState new_state = (TransportState)g_variant_get_int32(value); - //g_debug("transport_widget_update_state - with value %i", new_state); - if (new_state == TRANSPORT_STATE_LAUNCHING){ - #if GTK_CHECK_VERSION(3, 0, 0) - gtk_style_context_set_state (spinner_style_context, GTK_STATE_FLAG_ACTIVE); - #endif - - priv->current_state = TRANSPORT_STATE_LAUNCHING; - g_debug("TransportWidget::toggle play state : %i", priv->current_state); - } - else{ - transport_widget_toggle_play_pause(bar, new_state); - } - } -} - - -/** -* transport_widget_new: -* @returns: a new #TransportWidget. -**/ -GtkWidget* -transport_widget_new ( DbusmenuMenuitem *item ) -{ - GtkWidget* widget = g_object_new(TRANSPORT_WIDGET_TYPE, NULL); - gtk_widget_set_app_paintable (widget, TRUE); - transport_widget_set_twin_item((TransportWidget*)widget, item); - return widget; -} - |