aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/metadata-widget.c181
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