diff --git a/src/backend/bacon-video-widget-gst-0.10.c b/src/backend/bacon-video-widget-gst-0.10.c index 5c0f010..360f177 100644 --- a/src/backend/bacon-video-widget-gst-0.10.c +++ b/src/backend/bacon-video-widget-gst-0.10.c @@ -137,7 +137,8 @@ struct BaconVideoWidgetPrivate guint update_id; GdkPixbuf *logo_pixbuf; - + GdkPixbuf *cover_pixbuf; /* stream-specific image */ + gboolean media_has_video; gboolean media_has_audio; gint seekable; /* -1 = don't know, FALSE = no */ @@ -237,6 +238,8 @@ static void bvw_stop_play_pipeline (BaconVideoWidget * bvw); static GError* bvw_error_from_gst_error (BaconVideoWidget *bvw, GstMessage *m); static GList * get_stream_info_objects_for_type (BaconVideoWidget * bvw, const gchar * typestr); +static gboolean bvw_check_for_cover_pixbuf (BaconVideoWidget * bvw); +static const GdkPixbuf * bvw_get_logo_pixbuf (BaconVideoWidget * bvw); static GtkWidgetClass *parent_class = NULL; @@ -349,9 +352,12 @@ static void get_media_size (BaconVideoWidget *bvw, gint *width, gint *height) { if (bvw->priv->logo_mode) { - if (bvw->priv->logo_pixbuf) { - *width = gdk_pixbuf_get_width (bvw->priv->logo_pixbuf); - *height = gdk_pixbuf_get_height (bvw->priv->logo_pixbuf); + const GdkPixbuf *pixbuf; + + pixbuf = bvw_get_logo_pixbuf (bvw); + if (pixbuf) { + *width = gdk_pixbuf_get_width (pixbuf); + *height = gdk_pixbuf_get_height (pixbuf); } else { *width = 0; *height = 0; @@ -678,7 +684,10 @@ bacon_video_widget_expose_event (GtkWidget *widget, GdkEventExpose *event) !bvw->priv->media_has_video && !bvw->priv->show_vfx; if (bvw->priv->logo_mode || draw_logo) { - if (bvw->priv->logo_pixbuf != NULL) { + const GdkPixbuf *pixbuf; + + pixbuf = bvw_get_logo_pixbuf (bvw); + if (pixbuf != NULL) { /* draw logo here */ GdkPixbuf *logo = NULL; gint s_width, s_height, w_width, w_height; @@ -700,8 +709,8 @@ bacon_video_widget_expose_event (GtkWidget *widget, GdkEventExpose *event) widget->allocation.width, widget->allocation.height); - s_width = gdk_pixbuf_get_width (bvw->priv->logo_pixbuf); - s_height = gdk_pixbuf_get_height (bvw->priv->logo_pixbuf); + s_width = gdk_pixbuf_get_width (pixbuf); + s_height = gdk_pixbuf_get_height (pixbuf); w_width = widget->allocation.width; w_height = widget->allocation.height; @@ -721,7 +730,7 @@ bacon_video_widget_expose_event (GtkWidget *widget, GdkEventExpose *event) return TRUE; } - logo = gdk_pixbuf_scale_simple (bvw->priv->logo_pixbuf, + logo = gdk_pixbuf_scale_simple (pixbuf, s_width, s_height, GDK_INTERP_BILINEAR); gdk_draw_pixbuf (widget->window, widget->style->fg_gc[0], logo, @@ -1453,6 +1462,8 @@ bvw_bus_message_cb (GstBus * bus, GstMessage * message, gpointer data) /* clean up */ gst_tag_list_free (tag_list); + bvw_check_for_cover_pixbuf (bvw); + /* if we're not interactive, we want to announce metadata * only later when we can be sure we got it all */ if (bvw->priv->use_type == BVW_USE_TYPE_VIDEO || @@ -2944,6 +2955,10 @@ bvw_stop_play_pipeline (BaconVideoWidget * bvw) bvw->priv->buffering = FALSE; bvw->priv->plugin_install_in_progress = FALSE; bvw->priv->ignore_messages_mask = 0; + if (bvw->priv->cover_pixbuf) { + g_object_unref (bvw->priv->cover_pixbuf); + bvw->priv->cover_pixbuf = NULL; + } GST_DEBUG ("stopped"); } @@ -3113,6 +3128,36 @@ bacon_video_widget_get_logo_mode (BaconVideoWidget * bvw) return bvw->priv->logo_mode; } +static gboolean +bvw_check_for_cover_pixbuf (BaconVideoWidget * bvw) +{ + GValue value = { 0, }; + + /* for efficiency reasons (decoding of encoded image into pixbuf) we assume + * that all potential images come in the same taglist, so once we've + * determined the best image/cover, we assume that's really the best one + * for this stream, even if more tag messages come in later (this should + * not be a problem in practice) */ + if (bvw->priv->cover_pixbuf) + return TRUE; + + bacon_video_widget_get_metadata (bvw, BVW_INFO_COVER, &value); + if (G_VALUE_HOLDS_OBJECT (&value)) { + bvw->priv->cover_pixbuf = g_value_dup_object (&value); + g_value_unset (&value); + } + return (bvw->priv->cover_pixbuf != NULL); +} + +static const GdkPixbuf * +bvw_get_logo_pixbuf (BaconVideoWidget * bvw) +{ + if (bvw_check_for_cover_pixbuf (bvw)) + return bvw->priv->cover_pixbuf; + else + return bvw->priv->logo_pixbuf; +} + void bacon_video_widget_pause (BaconVideoWidget * bvw) { @@ -4574,21 +4619,21 @@ bacon_video_widget_get_metadata_pixbuf (BaconVideoWidget * bvw, GstBuffer *buffer) { GdkPixbufLoader *loader; - GdkPixbuf *pixbuf; + GdkPixbuf *pixbuf = NULL; + GError *err = NULL; loader = gdk_pixbuf_loader_new (); - if (!gdk_pixbuf_loader_write (loader, buffer->data, buffer->size, NULL)) { - g_object_unref (loader); - return NULL; - } - if (!gdk_pixbuf_loader_close (loader, NULL)) { - g_object_unref (loader); - return NULL; + + if (gdk_pixbuf_loader_write (loader, buffer->data, buffer->size, &err) && + gdk_pixbuf_loader_close (loader, &err)) { + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + if (pixbuf) + g_object_ref (pixbuf); + } else { + GST_WARNING("could not convert tag image to pixbuf: %s", err->message); + g_error_free (err); } - pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); - if (pixbuf) - g_object_ref (pixbuf); g_object_unref (loader); return pixbuf; }