summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2008-06-10 21:16:49 +0000
committerBastien Nocera <hadess@src.gnome.org>2008-06-10 21:16:49 +0000
commit9505320afc41bade135ccf43f113a2317bcdb03a (patch)
treee4e2408b60eb3742d5b1de91421a70cb0b716560
parent6f75c77e5492e34774a05939fae0c3e3caea0175 (diff)
downloadtotem-9505320afc41bade135ccf43f113a2317bcdb03a.tar.gz
Require gstreamer-tag as well
2008-06-10 Bastien Nocera <hadess@hadess.net> * configure.in: Require gstreamer-tag as well * src/backend/bacon-video-widget.h: * src/backend/bacon-video-widget-gst-0.10.c (bacon_video_widget_get_metadata_pixbuf), (bacon_video_widget_get_best_image), (bacon_video_widget_get_metadata): Add code to read covers from video and audio files, through the tags * src/backend/bacon-video-widget-xine.c (bacon_video_widget_get_metadata): Implement stubs of the above * src/totem-video-thumbnailer.c (capture_interesting_frame), (capture_frame_at_time), (has_audio), (on_got_metadata_event), (main): Implement saving the cover of a video/audio file (Closes: #318748) svn path=/trunk/; revision=5462
-rw-r--r--ChangeLog16
-rw-r--r--src/backend/bacon-video-widget-gst-0.10.c89
-rw-r--r--src/backend/bacon-video-widget-xine.c2
-rw-r--r--src/backend/bacon-video-widget.h1
-rw-r--r--src/totem-video-thumbnailer.c85
5 files changed, 175 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 14305a2ff..53d07eac0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
2008-06-10 Bastien Nocera <hadess@hadess.net>
+ * configure.in: Require gstreamer-tag as well
+ * src/backend/bacon-video-widget.h:
+ * src/backend/bacon-video-widget-gst-0.10.c
+ (bacon_video_widget_get_metadata_pixbuf),
+ (bacon_video_widget_get_best_image),
+ (bacon_video_widget_get_metadata): Add code to read covers from
+ video and audio files, through the tags
+ * src/backend/bacon-video-widget-xine.c
+ (bacon_video_widget_get_metadata): Implement stubs of the above
+ * src/totem-video-thumbnailer.c (capture_interesting_frame),
+ (capture_frame_at_time), (has_audio), (on_got_metadata_event),
+ (main): Implement saving the cover of a video/audio file
+ (Closes: #318748)
+
+2008-06-10 Bastien Nocera <hadess@hadess.net>
+
* browser-plugin/totem-plugin-viewer.c
(on_video_button_press_event): Patch from Baptiste Mille-Mathias
<bmm80@free.fr> to add double-click -> fullscreen support
diff --git a/src/backend/bacon-video-widget-gst-0.10.c b/src/backend/bacon-video-widget-gst-0.10.c
index 3fc529073..5223b7db0 100644
--- a/src/backend/bacon-video-widget-gst-0.10.c
+++ b/src/backend/bacon-video-widget-gst-0.10.c
@@ -50,6 +50,9 @@
/* for missing decoder/demuxer detection */
#include <gst/pbutils/pbutils.h>
+/* for the cover metadata info */
+#include <gst/tag/tag.h>
+
/* system */
#include <unistd.h>
#include <time.h>
@@ -4568,6 +4571,67 @@ bvw_process_pending_tag_messages (BaconVideoWidget * bvw)
gst_object_unref (bus);
}
+static GdkPixbuf *
+bacon_video_widget_get_metadata_pixbuf (BaconVideoWidget * bvw,
+ GstBuffer *buffer)
+{
+ GdkPixbufLoader *loader;
+ GdkPixbuf *pixbuf;
+
+ 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;
+ }
+
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ if (pixbuf)
+ g_object_ref (pixbuf);
+ g_object_unref (loader);
+ return pixbuf;
+}
+
+static const GValue *
+bacon_video_widget_get_best_image (BaconVideoWidget *bvw)
+{
+ const GValue *cover_value;
+ guint i;
+
+ for (i = 0; ; i++) {
+ const GValue *value;
+ GstBuffer *buffer;
+ GstStructure *caps_struct;
+ int type;
+
+ value = gst_tag_list_get_value_index (bvw->priv->tagcache,
+ GST_TAG_IMAGE,
+ i);
+ if (value == NULL)
+ break;
+
+ buffer = gst_value_get_buffer (value);
+
+ caps_struct = gst_caps_get_structure (buffer->caps, 0);
+ gst_structure_get_enum (caps_struct,
+ "image-type",
+ GST_TYPE_TAG_IMAGE_TYPE,
+ &type);
+ if (type == GST_TAG_IMAGE_TYPE_UNDEFINED) {
+ if (cover_value == NULL)
+ cover_value = value;
+ } else if (type == GST_TAG_IMAGE_TYPE_FRONT_COVER) {
+ cover_value = value;
+ break;
+ }
+ }
+
+ return cover_value;
+}
+
void
bacon_video_widget_get_metadata (BaconVideoWidget * bvw,
BaconVideoWidgetMetadataType type,
@@ -4603,6 +4667,31 @@ bacon_video_widget_get_metadata (BaconVideoWidget * bvw,
case BVW_INFO_HAS_AUDIO:
bacon_video_widget_get_metadata_bool (bvw, type, value);
break;
+ case BVW_INFO_COVER:
+ {
+ const GValue *cover_value;
+
+ g_value_init (value, GDK_TYPE_PIXBUF);
+
+ if (bvw->priv->tagcache == NULL)
+ break;
+ cover_value = bacon_video_widget_get_best_image (bvw);
+ if (!cover_value) {
+ cover_value = gst_tag_list_get_value_index (bvw->priv->tagcache,
+ GST_TAG_PREVIEW_IMAGE,
+ 0);
+ }
+ if (cover_value) {
+ GstBuffer *buffer;
+ GdkPixbuf *pixbuf;
+
+ buffer = gst_value_get_buffer (cover_value);
+ pixbuf = bacon_video_widget_get_metadata_pixbuf (bvw, buffer);
+ if (pixbuf)
+ g_value_take_object (value, pixbuf);
+ }
+ }
+ break;
default:
g_return_if_reached ();
}
diff --git a/src/backend/bacon-video-widget-xine.c b/src/backend/bacon-video-widget-xine.c
index fb19d5ed3..fdd406de4 100644
--- a/src/backend/bacon-video-widget-xine.c
+++ b/src/backend/bacon-video-widget-xine.c
@@ -4032,6 +4032,8 @@ bacon_video_widget_get_metadata (BaconVideoWidget *bvw,
case BVW_INFO_HAS_AUDIO:
bacon_video_widget_get_metadata_bool (bvw, type, value);
break;
+ case BVW_INFO_COVER:
+ break;
default:
g_assert_not_reached ();
}
diff --git a/src/backend/bacon-video-widget.h b/src/backend/bacon-video-widget.h
index e5ee77f86..50bc2c45b 100644
--- a/src/backend/bacon-video-widget.h
+++ b/src/backend/bacon-video-widget.h
@@ -199,6 +199,7 @@ typedef enum {
BVW_INFO_ALBUM,
BVW_INFO_DURATION,
BVW_INFO_TRACK_NUMBER,
+ BVW_INFO_COVER,
/* Video */
BVW_INFO_HAS_VIDEO,
BVW_INFO_DIMENSION_X,
diff --git a/src/totem-video-thumbnailer.c b/src/totem-video-thumbnailer.c
index b9fcf2399..5b3765fc5 100644
--- a/src/totem-video-thumbnailer.c
+++ b/src/totem-video-thumbnailer.c
@@ -57,6 +57,11 @@ static gboolean g_fatal_warnings = FALSE;
static gint64 second_index = -1;
static char **filenames = NULL;
+typedef struct {
+ const char *output;
+ const char *input;
+} callback_data;
+
#ifdef THUMB_DEBUG
static void
show_pixbuf (GdkPixbuf *pix)
@@ -326,7 +331,9 @@ save_pixbuf (GdkPixbuf *pixbuf, const char *path,
}
static GdkPixbuf *
-capture_interesting_frame (BaconVideoWidget * bvw, char *input, char *output)
+capture_interesting_frame (BaconVideoWidget *bvw,
+ const char *input,
+ const char *output)
{
GdkPixbuf* pixbuf;
guint current;
@@ -343,9 +350,9 @@ capture_interesting_frame (BaconVideoWidget * bvw, char *input, char *output)
* interesting frame */
for (current = 0; current < G_N_ELEMENTS(frame_locations); current++)
{
- PROGRESS_DEBUG("About to seek to %f\n", frame_locations[current]);
+ PROGRESS_DEBUG("About to seek to %f", frame_locations[current]);
if (bacon_video_widget_seek (bvw, frame_locations[current], NULL) == FALSE) {
- PROGRESS_DEBUG("Couldn't seek to %f\n", frame_locations[current]);
+ PROGRESS_DEBUG("Couldn't seek to %f", frame_locations[current]);
bacon_video_widget_play (bvw, NULL);
}
@@ -362,10 +369,10 @@ capture_interesting_frame (BaconVideoWidget * bvw, char *input, char *output)
}
/* Pull the frame, if it's interesting we bail early */
- PROGRESS_DEBUG("About to get frame for iter %d\n", current);
+ PROGRESS_DEBUG("About to get frame for iter %d", current);
pixbuf = bacon_video_widget_get_current_frame (bvw);
if (pixbuf != NULL && is_image_interesting (pixbuf) != FALSE) {
- PROGRESS_DEBUG("Frame for iter %d is interesting\n", current);
+ PROGRESS_DEBUG("Frame for iter %d is interesting", current);
break;
}
@@ -377,13 +384,16 @@ capture_interesting_frame (BaconVideoWidget * bvw, char *input, char *output)
pixbuf = NULL;
}
}
- PROGRESS_DEBUG("Frame for iter %d was not interesting\n", current);
+ PROGRESS_DEBUG("Frame for iter %d was not interesting", current);
}
return pixbuf;
}
static GdkPixbuf *
-capture_frame_at_time(BaconVideoWidget *bvw, char *input, char *output, gint64 seconds)
+capture_frame_at_time(BaconVideoWidget *bvw,
+ const char *input,
+ const char *output,
+ gint64 seconds)
{
GError *err = NULL;
@@ -412,6 +422,42 @@ capture_frame_at_time(BaconVideoWidget *bvw, char *input, char *output, gint64
return bacon_video_widget_get_current_frame (bvw);
}
+static gboolean
+has_audio (BaconVideoWidget *bvw)
+{
+ GValue value = { 0, };
+
+ bacon_video_widget_get_metadata (bvw, BVW_INFO_HAS_VIDEO, &value);
+ return g_value_get_boolean (&value);
+}
+
+static void
+on_got_metadata_event (BaconVideoWidget *bvw, callback_data *data)
+{
+ GValue value = { 0, };
+ GdkPixbuf *pixbuf;
+
+ PROGRESS_DEBUG("Got metadata, checking if we have a cover");
+ bacon_video_widget_get_metadata (bvw, BVW_INFO_COVER, &value);
+ pixbuf = g_value_get_object (&value);
+
+ if (pixbuf) {
+ PROGRESS_DEBUG("Saving cover image");
+
+ bacon_video_widget_close (bvw);
+ totem_resources_monitor_stop ();
+ gtk_widget_destroy (GTK_WIDGET (bvw));
+
+ save_pixbuf (pixbuf, data->output, data->input, output_size, TRUE);
+ g_object_unref (pixbuf);
+
+ exit (0);
+ } else if (has_audio (bvw) == FALSE) {
+ PROGRESS_DEBUG("No covers, and no video, exiting");
+ exit (0);
+ }
+}
+
static const GOptionEntry entries[] = {
{ "jpeg", 'j', 0, G_OPTION_ARG_NONE, &jpeg_output, "Output the thumbnail as a JPEG instead of PNG", NULL },
{ "size", 's', 0, G_OPTION_ARG_INT, &output_size, "Size of the thumbnail in pixels", NULL },
@@ -432,7 +478,8 @@ int main (int argc, char *argv[])
GError *err = NULL;
BaconVideoWidget *bvw;
GdkPixbuf *pixbuf;
- char *input, *output;
+ const char *input, *output;
+ callback_data data;
#ifdef G_OS_UNIX
nice (20);
@@ -456,7 +503,6 @@ int main (int argc, char *argv[])
return 1;
}
-#ifndef THUMB_DEBUG
if (g_fatal_warnings) {
GLogLevelFlags fatal_mask;
@@ -464,7 +510,6 @@ int main (int argc, char *argv[])
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
g_log_set_always_fatal (fatal_mask);
}
-#endif /* THUMB_DEBUG */
if (filenames == NULL || g_strv_length (filenames) != 2) {
char *help;
@@ -476,7 +521,7 @@ int main (int argc, char *argv[])
input = filenames[0];
output = filenames[1];
- PROGRESS_DEBUG("Initialised libraries, about to create video widget\n");
+ PROGRESS_DEBUG("Initialised libraries, about to create video widget");
bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (-1, -1, BVW_USE_TYPE_CAPTURE, &err));
if (err != NULL) {
@@ -485,13 +530,18 @@ int main (int argc, char *argv[])
g_error_free (err);
exit (1);
}
+ data.input = input;
+ data.output = output;
+ g_signal_connect (G_OBJECT (bvw), "got-metadata",
+ G_CALLBACK (on_got_metadata_event),
+ &data);
- PROGRESS_DEBUG("Video widget created\n");
+ PROGRESS_DEBUG("Video widget created");
if (time_limit != FALSE)
totem_resources_monitor_start (input, 0);
- PROGRESS_DEBUG("About to open video file\n");
+ PROGRESS_DEBUG("About to open video file");
if (bacon_video_widget_open (bvw, input, &err) == FALSE) {
g_print ("totem-video-thumbnailer couldn't open file '%s'\n"
@@ -501,8 +551,8 @@ int main (int argc, char *argv[])
exit (1);
}
- PROGRESS_DEBUG("Opened video file: '%s'\n", input);
- PROGRESS_DEBUG("About to play file\n");
+ PROGRESS_DEBUG("Opened video file: '%s'", input);
+ PROGRESS_DEBUG("About to play file");
bacon_video_widget_play (bvw, &err);
if (err != NULL) {
@@ -511,8 +561,7 @@ int main (int argc, char *argv[])
g_error_free (err);
exit (1);
}
-
- PROGRESS_DEBUG("Started playing file\n");
+ PROGRESS_DEBUG("Started playing file");
/* If the user has told us to use a frame at a specific second
* into the video, just use that frame no matter how boring it
@@ -533,7 +582,7 @@ int main (int argc, char *argv[])
exit (1);
}
- PROGRESS_DEBUG("Saving captured screenshot\n");
+ PROGRESS_DEBUG("Saving captured screenshot");
save_pixbuf (pixbuf, output, input, output_size, FALSE);
g_object_unref (pixbuf);