From b330119b4942c94db7bbb5e7ad4758fba0383a44 Mon Sep 17 00:00:00 2001 From: Jens Georg Date: Sat, 24 Jul 2010 23:19:03 +0300 Subject: [PATCH] media-export: Extract embedded album art --- configure.ac | 4 ++ src/plugins/media-export/Makefile.am | 7 +++ .../media-export/rygel-media-export-item.vala | 26 ++++++++- .../rygel-media-export-jpeg-writer.vala | 66 ++++++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/plugins/media-export/rygel-media-export-jpeg-writer.vala diff --git a/configure.ac b/configure.ac index 2735b76..84e0ef9 100644 --- a/configure.ac +++ b/configure.ac @@ -27,6 +27,8 @@ GUPNP_DLNA_REQUIRED=0.2.1 GUPNP_VALA_REQUIRED=0.6.7 DBUS_GLIB_REQUIRED=0.74 GSTREAMER_REQUIRED=0.10.23 +GSTREAMER_TAG_REQUIRED=0.10.28 +GSTREAMER_APP_REQUIRED=0.10.28 GIO_REQUIRED=2.16 GEE_REQUIRED=0.5.2 UUID_REQUIRED=1.41.3 @@ -278,6 +280,8 @@ AM_CONDITIONAL([BUILD_GST_LAUNCH_PLUGIN], [test "x$enable_gst_launch_plugin" = " if test "x$enable_media_export_plugin" = "xyes"; then PKG_CHECK_MODULES(LIBSQLITE3, sqlite3 >= $LIBSQLITE3_REQUIRED) + PKG_CHECK_MODULES(GSTREAMER_TAG, gstreamer-tag-0.10 >= $GSTREAMER_TAG_REQUIRED); + PKG_CHECK_MODULES(GSTREAMER_APP, gstreamer-app-0.10 >= $GSTREAMER_APP_REQUIRED); fi # Gettext diff --git a/src/plugins/media-export/Makefile.am b/src/plugins/media-export/Makefile.am index c65cb0b..34e1c8a 100644 --- a/src/plugins/media-export/Makefile.am +++ b/src/plugins/media-export/Makefile.am @@ -15,6 +15,8 @@ AM_CFLAGS = $(LIBGUPNP_CFLAGS) \ $(LIBSQLITE3_CFLAGS) \ $(GEE_CFLAGS) \ $(UUID_CFLAGS) \ + $(GSTREAMER_TAG_CFLAGS) \ + $(GSTREAMER_APP_CFLAGS) \ -I$(top_srcdir)/src/rygel -DDATA_DIR='"$(datadir)"' \ -include config.h @@ -32,6 +34,7 @@ librygel_media_export_la_SOURCES = rygel-media-export-plugin.vala \ rygel-media-export-recursive-file-monitor.vala \ rygel-media-export-harvester.vala \ rygel-media-export-item.vala \ + rygel-media-export-jpeg-writer.vala \ rygel-media-export-writable-container.vala \ rygel-media-export-object-factory.vala @@ -44,6 +47,8 @@ librygel_media_export_la_VALAFLAGS = --vapidir=$(top_srcdir)/src/rygel \ --pkg libsoup-2.4 \ --pkg gee-1.0 \ --pkg libxml-2.0 \ + --pkg gstreamer-tag-0.10 \ + --pkg gstreamer-app-0.10 \ --pkg sqlite3 -g librygel_media_export_la_LIBADD = $(LIBGUPNP_LIBS) \ @@ -51,6 +56,8 @@ librygel_media_export_la_LIBADD = $(LIBGUPNP_LIBS) \ $(LIBGUPNP_DLNA_LIBS) \ $(LIBDBUS_GLIB_LIBS) \ $(LIBGSTREAMER_LIBS) \ + $(GSTREAMER_TAG_LIBS) \ + $(GSTREAMER_APP_LIBS) \ $(LIBSQLITE3_LIBS) \ $(GEE_LIBS) \ $(UUID_LIBS) diff --git a/src/plugins/media-export/rygel-media-export-item.vala b/src/plugins/media-export/rygel-media-export-item.vala index 9b73808..f9c7114 100644 --- a/src/plugins/media-export/rygel-media-export-item.vala +++ b/src/plugins/media-export/rygel-media-export-item.vala @@ -188,8 +188,32 @@ public class Rygel.MediaExport.Item : Rygel.MediaItem { MediaItem.MUSIC_CLASS); if (audio_info.tags != null) { - uint tmp; + unowned Gst.Buffer buffer; + audio_info.tags.get_buffer (TAG_IMAGE, out buffer); + if (buffer != null) { + var structure = buffer.caps.get_structure (0); + int image_type; + structure.get_enum ("image-type", + typeof (Gst.TagImageType), + out image_type); + switch (image_type) { + case TagImageType.UNDEFINED: + case TagImageType.FRONT_COVER: + var store = MediaArtStore.get_default (); + var thumb = store.get_media_art_file ("album", + this, + true); + try { + var writer = new JPEGWriter (); + writer.write (buffer, thumb); + } catch (Error error) {} + break; + default: + break; + } + } + uint tmp; audio_info.tags.get_uint (TAG_BITRATE, out tmp); this.bitrate = (int) tmp / 8; } diff --git a/src/plugins/media-export/rygel-media-export-jpeg-writer.vala b/src/plugins/media-export/rygel-media-export-jpeg-writer.vala new file mode 100644 index 0000000..675bfd2 --- /dev/null +++ b/src/plugins/media-export/rygel-media-export-jpeg-writer.vala @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 Jens Georg . + * + * Author: Jens Georg + * + * This file is part of Rygel. + * + * Rygel is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Rygel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using Gst; + +/** + * Utility class to write media-art content to JPEG files + * + * This uses a gstreamer pipeline to transcode the image tag as contained in + * MP3 files. This class is single-shot, use and then throw away. + */ +internal class Rygel.MediaExport.JPEGWriter : GLib.Object { + private Bin bin; + private AppSrc appsrc; + private MainLoop loop; + private dynamic Element sink; + + public JPEGWriter () throws Error { + this.bin = Gst.parse_launch ("appsrc name=src ! decodebin2 ! " + + "ffmpegcolorspace ! " + + "jpegenc ! giosink name=sink") as Bin; + this.appsrc = bin.get_by_name ("src") as AppSrc; + this.sink = bin.get_by_name ("sink"); + var bus = bin.get_bus (); + bus.add_signal_watch (); + bus.message["eos"].connect(() => { this.loop.quit (); }); + bus.message["error"].connect(() => { this.loop.quit (); }); + this.loop = new MainLoop (null, false); + } + + /** + * Write a Gst.Buffer as retrieved from the Gst.TagList to disk. + * + * @param buffer The Gst.Buffer as obtained from tag list + * @param file A GLib.File pointing to the target location + * + * FIXME This uses a nested main-loop to block which is ugly. + */ + public void write (Gst.Buffer buffer, File file) { + this.sink.file = file; + this.appsrc.push_buffer (buffer); + this.appsrc.end_of_stream (); + this.bin.set_state (State.PLAYING); + this.loop.run (); + this.bin.set_state (State.NULL); + } +} -- 2.7.4