diff options
-rw-r--r-- | src/metadata-widget.c | 181 |
1 files changed, 165 insertions, 16 deletions
diff --git a/src/metadata-widget.c b/src/metadata-widget.c index fae3198..f600238 100644 --- a/src/metadata-widget.c +++ b/src/metadata-widget.c @@ -35,6 +35,7 @@ struct _MetadataWidgetPrivate GtkWidget* hbox; GtkWidget* album_art; GString* image_path; + GString* old_image_path; GtkWidget* artist_label; GtkWidget* piece_label; GtkWidget* container_label; @@ -60,11 +61,14 @@ static void metadata_widget_property_update (DbusmenuMenuitem* item, GValue* value, gpointer userdata); -static void metadata_widget_update_album_art(MetadataWidget* self); static void metadata_widget_style_labels(MetadataWidget* self, GtkLabel* label); void metadata_widget_set_style(GtkWidget* button, GtkStyle* style); +static void image_set_from_pixbuf (GtkWidget *widget, + MetadataWidget* metadata, + GdkPixbuf *source); + G_DEFINE_TYPE (MetadataWidget, metadata_widget, GTK_TYPE_MENU_ITEM); @@ -99,11 +103,12 @@ metadata_widget_init (MetadataWidget *self) // image priv->album_art = gtk_image_new(); priv->image_path = g_string_new(dbusmenu_menuitem_property_get(twin_item, DBUSMENU_METADATA_MENUITEM_ARTURL)); - + priv->old_image_path = g_string_new(""); g_debug("Metadata::At startup and image path = %s", priv->image_path->str); - metadata_widget_update_album_art(self); - g_signal_connect(priv->album_art, "expose-event", G_CALLBACK(metadata_image_expose), GTK_WIDGET(self)); + g_signal_connect(priv->album_art, "expose-event", + G_CALLBACK(metadata_image_expose), + GTK_WIDGET(self)); gtk_widget_set_size_request(GTK_WIDGET(priv->album_art), 60, 60); gtk_box_pack_start (GTK_BOX (priv->hbox), priv->album_art, FALSE, FALSE, 0); @@ -181,9 +186,22 @@ metadata_image_expose (GtkWidget *metadata, GdkEventExpose *event, gpointer user g_return_val_if_fail(IS_METADATA_WIDGET(user_data), FALSE); MetadataWidget* widget = METADATA_WIDGET(user_data); MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(widget); - + if(priv->image_path->len > 0){ - return FALSE; + + if(g_string_equal(priv->image_path, priv->old_image_path) == FALSE){ + GdkPixbuf* pixbuf; + pixbuf = gdk_pixbuf_new_from_file(priv->image_path->str, NULL); + g_debug("metadata_widget_expose, album art update -> pixbuf from %s", + priv->image_path->str); + pixbuf = gdk_pixbuf_scale_simple(pixbuf,60, 60, GDK_INTERP_BILINEAR); + image_set_from_pixbuf (metadata, widget, pixbuf); + g_string_erase(priv->old_image_path, 0, -1); + g_string_overwrite(priv->old_image_path, 0, priv->image_path->str); + + g_object_unref(pixbuf); + } + return FALSE; } cairo_t *cr; @@ -297,20 +315,151 @@ metadata_widget_property_update(DbusmenuMenuitem* item, gchar* property, else if(g_ascii_strcasecmp(DBUSMENU_METADATA_MENUITEM_ARTURL, property) == 0){ g_string_erase(priv->image_path, 0, -1); g_string_overwrite(priv->image_path, 0, g_value_get_string (value)); - metadata_widget_update_album_art(mitem); } } + +static cairo_surface_t * +surface_from_pixbuf (GdkPixbuf *pixbuf) +{ + cairo_surface_t *surface; + cairo_t *cr; + + surface = cairo_image_surface_create (gdk_pixbuf_get_has_alpha (pixbuf) ? + CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + cr = cairo_create (surface); + gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); + cairo_paint (cr); + cairo_destroy (cr); + + return surface; +} + +static void +rounded_rectangle (cairo_t *cr, + gdouble aspect, + gdouble x, + gdouble y, + gdouble corner_radius, + gdouble width, + gdouble height) +{ + gdouble radius; + gdouble degrees; + + radius = corner_radius / aspect; + degrees = G_PI / 180.0; + + cairo_new_sub_path (cr); + cairo_arc (cr, + x + width - radius, + y + radius, + radius, + -90 * degrees, + 0 * degrees); + cairo_arc (cr, + x + width - radius, + y + height - radius, + radius, + 0 * degrees, + 90 * degrees); + cairo_arc (cr, + x + radius, + y + height - radius, + radius, + 90 * degrees, + 180 * degrees); + cairo_arc (cr, + x + radius, + y + radius, + radius, + 180 * degrees, + 270 * degrees); + cairo_close_path (cr); +} + static void -metadata_widget_update_album_art(MetadataWidget* self){ - MetadataWidgetPrivate * priv = METADATA_WIDGET_GET_PRIVATE(self); - GdkPixbuf* pixbuf; - pixbuf = gdk_pixbuf_new_from_file(priv->image_path->str, NULL); - g_debug("metadata_widget_update_album_art -> pixbuf from %s", - priv->image_path->str); - pixbuf = gdk_pixbuf_scale_simple(pixbuf,60, 60, GDK_INTERP_BILINEAR); - gtk_image_set_from_pixbuf(GTK_IMAGE(priv->album_art), pixbuf); - g_object_unref(pixbuf); +image_set_from_pixbuf (GtkWidget *widget, + MetadataWidget* metadata, + GdkPixbuf *source) +{ + cairo_t *cr; + cairo_t *cr_mask; + cairo_surface_t *surface; + GdkPixmap *pixmap; + GdkPixmap *bitmask; + int w; + int h; + int frame_width; + double radius; + GdkColor color; + double r; + double g; + double b; + + MetadataWidgetPrivate* priv = METADATA_WIDGET_GET_PRIVATE(metadata); + GtkImage* image = GTK_IMAGE(priv->album_art); + frame_width = 5; + + w = gdk_pixbuf_get_width (source) + frame_width * 2; + h = gdk_pixbuf_get_height (source) + frame_width * 2; + + radius = w / 10; + + pixmap = gdk_pixmap_new (gtk_widget_get_window (widget), w, h, -1); + bitmask = gdk_pixmap_new (gtk_widget_get_window (widget), w, h, 1); + + if (gtk_widget_get_window (widget) == NULL) + return; + + cr = gdk_cairo_create (pixmap); + cr_mask = gdk_cairo_create (bitmask); + + /* setup mask */ + cairo_rectangle (cr_mask, 0, 0, w, h); + cairo_set_operator (cr_mask, CAIRO_OPERATOR_CLEAR); + cairo_fill (cr_mask); + + rounded_rectangle (cr_mask, 1.0, 0.5, 0.5, radius, w - 1, h - 1); + cairo_set_operator (cr_mask, CAIRO_OPERATOR_OVER); + cairo_set_source_rgb (cr_mask, 1, 1, 1); + cairo_fill (cr_mask); + + color = gtk_widget_get_style (GTK_WIDGET (image))->bg [GTK_STATE_NORMAL]; + r = (float)color.red / 65535.0; + g = (float)color.green / 65535.0; + b = (float)color.blue / 65535.0; + + /* set up image */ + cairo_rectangle (cr, 0, 0, w, h); + cairo_set_source_rgb (cr, r, g, b); + cairo_fill (cr); + + rounded_rectangle (cr, + 1.0, + frame_width + 0.5, + frame_width + 0.5, + radius, + w - frame_width * 2 - 1, + h - frame_width * 2 - 1); + cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 0.3); + cairo_fill_preserve (cr); + + surface = surface_from_pixbuf (source); + cairo_set_source_surface (cr, surface, frame_width, frame_width); + cairo_fill (cr); + + gtk_image_set_from_pixmap (image, pixmap, bitmask); + + cairo_surface_destroy (surface); + + g_object_unref (bitmask); + g_object_unref (pixmap); + + cairo_destroy (cr_mask); + cairo_destroy (cr); } // TODO refactor next 3 methods into one once the style has been |