# Ubuntu: https://bugs.launchpad.net/ubuntu/+source/totem/+bug/310610
# Description: show cover images embedded in audio streams if there are no
#  visualisations; by Collabora
#
Index: totem-2.25.92/src/backend/bacon-video-widget-gst-0.10.c
===================================================================
--- totem-2.25.92.orig/src/backend/bacon-video-widget-gst-0.10.c	2009-03-04 00:11:46.612386568 +0100
+++ totem-2.25.92/src/backend/bacon-video-widget-gst-0.10.c	2009-03-04 00:12:17.788390337 +0100
@@ -133,7 +133,8 @@
   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 */
@@ -229,6 +230,8 @@
 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;
 
@@ -341,9 +344,12 @@
 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;
@@ -659,7 +665,10 @@
       !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;
@@ -681,8 +690,8 @@
 			     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;
 
@@ -702,7 +711,7 @@
 	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,
@@ -1441,6 +1450,8 @@
       /* 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 ||
@@ -2907,6 +2918,10 @@
   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");
 }
 
@@ -3077,6 +3092,36 @@
   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)
 {
@@ -4448,21 +4493,21 @@
 					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;
 }
