summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2015-08-08 13:49:04 -0700
committerRobin H. Johnson <robbat2@gentoo.org>2015-08-08 17:38:18 -0700
commit56bd759df1d0c750a065b8c845e93d5dfa6b549d (patch)
tree3f91093cdb475e565ae857f1c5a7fd339e2d781e /net-misc/mediatomb/files
downloadgentoo-56bd759df1d0c750a065b8c845e93d5dfa6b549d.tar.gz
gentoo-56bd759df1d0c750a065b8c845e93d5dfa6b549d.tar.bz2
gentoo-56bd759df1d0c750a065b8c845e93d5dfa6b549d.zip
proj/gentoo: Initial commit
This commit represents a new era for Gentoo: Storing the gentoo-x86 tree in Git, as converted from CVS. This commit is the start of the NEW history. Any historical data is intended to be grafted onto this point. Creation process: 1. Take final CVS checkout snapshot 2. Remove ALL ChangeLog* files 3. Transform all Manifests to thin 4. Remove empty Manifests 5. Convert all stale $Header$/$Id$ CVS keywords to non-expanded Git $Id$ 5.1. Do not touch files with -kb/-ko keyword flags. Signed-off-by: Robin H. Johnson <robbat2@gentoo.org> X-Thanks: Alec Warner <antarus@gentoo.org> - did the GSoC 2006 migration tests X-Thanks: Robin H. Johnson <robbat2@gentoo.org> - infra guy, herding this project X-Thanks: Nguyen Thai Ngoc Duy <pclouds@gentoo.org> - Former Gentoo developer, wrote Git features for the migration X-Thanks: Brian Harring <ferringb@gentoo.org> - wrote much python to improve cvs2svn X-Thanks: Rich Freeman <rich0@gentoo.org> - validation scripts X-Thanks: Patrick Lauer <patrick@gentoo.org> - Gentoo dev, running new 2014 work in migration X-Thanks: Michał Górny <mgorny@gentoo.org> - scripts, QA, nagging X-Thanks: All of other Gentoo developers - many ideas and lots of paint on the bikeshed
Diffstat (limited to 'net-misc/mediatomb/files')
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.0.confd28
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.0.config144
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.0.initd22
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-avformatcontext-pointer.patch19
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-flac-metadata.patch446
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-inotify-hard-links.patch34
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-libav9.patch42
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-libextractor.patch675
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-libmp4v2.patch187
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-mozjs187.patch260
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-system-ar.patch35
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-system-uuid.patch36
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-thumb-cache.patch237
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-thumbnail-locking.patch71
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1-youtube-dl.patch141
-rw-r--r--net-misc/mediatomb/files/mediatomb-0.12.1.initd29
16 files changed, 2406 insertions, 0 deletions
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.0.confd b/net-misc/mediatomb/files/mediatomb-0.12.0.confd
new file mode 100644
index 000000000000..7f5c00830251
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.0.confd
@@ -0,0 +1,28 @@
+# /etc/conf.d/mediatomb: config file for /etc/init.d/mediatomb
+
+# See the mediatomb(1) manpage for more info.
+
+# MediaTomb Web UI port.
+# NOTE: The minimum value allowed is 49152
+MEDIATOMB_PORT=49152
+
+# Run MediaTomb as this user.
+# NOTE: For security reasons do not run MediaTomb as root.
+MEDIATOMB_USER="mediatomb"
+
+# Run MediaTomb as this group.
+# NOTE: For security reasons do not run MediaTomb as root.
+MEDIATOMB_GROUP="mediatomb"
+
+# Path to MediaTomb config file.
+MEDIATOMB_CONFIG="/etc/mediatomb/config.xml"
+
+# Path to MediaTomb log file.
+MEDIATOMB_LOGFILE="/var/log/mediatomb.log"
+
+# Path to MediaTomb pid file.
+MEDIATOMB_PIDFILE="/var/run/mediatomb.pid"
+
+# Other options you want to pass to MediaTomb.
+# Add "--interface ${MEDIATOMB_INTERFACE}" to bind to a named interface.
+MEDIATOMB_OPTIONS=""
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.0.config b/net-misc/mediatomb/files/mediatomb-0.12.0.config
new file mode 100644
index 000000000000..0cd03b15d8e8
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.0.config
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<config version="2" xmlns="http://mediatomb.cc/config/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mediatomb.cc/config/2 http://mediatomb.cc/config/2.xsd">
+ <server>
+ <ui enabled="yes" show-tooltips="yes">
+ <accounts enabled="no" session-timeout="30">
+ <account user="mediatomb" password="mediatomb"/>
+ </accounts>
+ </ui>
+ <name>MediaTomb</name>
+ <udn></udn>
+ <home>/var/lib/mediatomb</home>
+ <webroot>/usr/share/mediatomb/web</webroot>
+ <storage>
+ <sqlite3 enabled="yes">
+ <database-file>mediatomb.db</database-file>
+ </sqlite3>
+ <mysql enabled="no">
+ <host>host</host>
+ <database>database</database>
+ <username>username</username>
+ <password>password</password>
+ </mysql>
+ </storage>
+ <protocolInfo extend="yes"/>
+ <pc-directory upnp-hide="no"/>
+ <extended-runtime-options>
+ <ffmpegthumbnailer enabled="no">
+ <thumbnail-size>160</thumbnail-size>
+ <seek-percentage>10</seek-percentage>
+ <filmstrip-overlay>no</filmstrip-overlay>
+ <workaround-bugs>no</workaround-bugs>
+ <image-quality>8</image-quality>
+ </ffmpegthumbnailer>
+ <mark-played-items enabled="no" suppress-cds-updates="yes">
+ <string mode="prepend">*</string>
+ <mark>
+ <content>video</content>
+ </mark>
+ </mark-played-items>
+ <lastfm enabled="no">
+ <username>username</username>
+ <password>password</password>
+ </lastfm>
+ </extended-runtime-options>
+ </server>
+ <import hidden-files="no">
+ <scripting script-charset="UTF-8">
+ <common-script>/usr/share/mediatomb/js/common.js</common-script>
+ <playlist-script>/usr/share/mediatomb/js/playlists.js</playlist-script>
+ <virtual-layout type="builtin">
+ <import-script>/usr/share/mediatomb/js/import.js</import-script>
+ </virtual-layout>
+ </scripting>
+ <mappings>
+ <extension-mimetype ignore-unknown="no">
+ <map from="mp3" to="audio/mpeg"/>
+ <map from="ogx" to="application/ogg"/>
+ <map from="ogv" to="video/ogg"/>
+ <map from="oga" to="audio/ogg"/>
+ <map from="ogg" to="audio/ogg"/>
+ <map from="ogm" to="video/ogg"/>
+ <map from="asf" to="video/x-ms-asf"/>
+ <map from="asx" to="video/x-ms-asf"/>
+ <map from="wma" to="audio/x-ms-wma"/>
+ <map from="wax" to="audio/x-ms-wax"/>
+ <map from="wmv" to="video/x-ms-wmv"/>
+ <map from="wvx" to="video/x-ms-wvx"/>
+ <map from="wm" to="video/x-ms-wm"/>
+ <map from="wmx" to="video/x-ms-wmx"/>
+ <map from="m3u" to="audio/x-mpegurl"/>
+ <map from="pls" to="audio/x-scpls"/>
+ <map from="flv" to="video/x-flv"/>
+ <map from="mkv" to="video/x-matroska"/>
+ <map from="mka" to="audio/x-matroska"/>
+ <map from="avi" to="video/divx"/>
+ <map from="m2ts" to="video/avc"/>
+ <map from="cr2" to="image/raw"/>
+ <map from="nef" to="image/raw"/>
+ </extension-mimetype>
+ <mimetype-upnpclass>
+ <map from="audio/*" to="object.item.audioItem.musicTrack"/>
+ <map from="video/*" to="object.item.videoItem"/>
+ <map from="image/*" to="object.item.imageItem"/>
+ </mimetype-upnpclass>
+ <mimetype-contenttype>
+ <treat mimetype="audio/mpeg" as="mp3"/>
+ <treat mimetype="application/ogg" as="ogg"/>
+ <treat mimetype="video/ogg" as="ogg"/>
+ <treat mimetype="audio/ogg" as="ogg"/>
+ <treat mimetype="audio/x-flac" as="flac"/>
+ <treat mimetype="image/jpeg" as="jpg"/>
+ <treat mimetype="audio/x-mpegurl" as="playlist"/>
+ <treat mimetype="audio/x-scpls" as="playlist"/>
+ <treat mimetype="audio/x-wav" as="pcm"/>
+ <treat mimetype="audio/L16" as="pcm"/>
+ <treat mimetype="video/x-msvideo" as="avi"/>
+ <treat mimetype="video/mp4" as="mp4"/>
+ <treat mimetype="audio/mp4" as="mp4"/>
+ <treat mimetype="video/divx" as="avi"/>
+ </mimetype-contenttype>
+ </mappings>
+ <online-content>
+ <YouTube enabled="no" refresh="28800" update-at-start="yes" purge-after="604800" racy-content="exclude" format="mp4" hd="no">
+ <favorites user="NationalGeographic"/>
+ <playlists user="PlayStation"/>
+ <uploads user="Google"/>
+ <standardfeed feed="most_viewed" time-range="today"/>
+ <standardfeed feed="recently_featured" time-range="today"/>
+ </YouTube>
+ </online-content>
+ </import>
+ <transcoding enabled="no">
+ <mimetype-profile-mappings>
+ <transcode mimetype="audio/ogg" using="audio2pcm"/>
+ <transcode mimetype="audio/x-flac" using="audio2pcm"/>
+ <transcode mimetype="video/ogg" using="video2mpeg"/>
+ <transcode mimetype="video/x-flv" using="video2mpeg"/>
+ </mimetype-profile-mappings>
+ <profiles>
+ <profile name="audio2pcm" enabled="yes" type="external">
+ <mimetype>audio/L16</mimetype>
+ <accept-url>no</accept-url>
+ <first-resource>yes</first-resource>
+ <hide-original-resource>yes</hide-original-resource>
+ <accept-ogg-theora>no</accept-ogg-theora>
+ <sample-frequency>44100</sample-frequency>
+ <audio-channels>2</audio-channels>
+ <agent command="ffmpeg" arguments="-i %in -acodec pcm_s16be -ab 192k -ar 44100 -ac 2 -f s16be -y %out"/>
+ <buffer size="1048576" chunk-size="131072" fill-size="262144"/>
+ </profile>
+ <profile name="video2mpeg" enabled="yes" type="external">
+ <mimetype>video/mpeg</mimetype>
+ <accept-url>no</accept-url>
+ <first-resource>yes</first-resource>
+ <hide-original-resource>yes</hide-original-resource>
+ <accept-ogg-theora>yes</accept-ogg-theora>
+ <sample-frequency>48000</sample-frequency>
+ <audio-channels>2</audio-channels>
+ <agent command="ffmpeg" arguments="-i %in -vcodec mpeg2video -b 4096k -r 25 -acodec mp2 -ab 192k -ar 48000 -ac 2 -async 1 -f dvd -threads 2 -y %out"/>
+ <buffer size="10485760" chunk-size="262144" fill-size="524288"/>
+ </profile>
+ </profiles>
+ </transcoding>
+</config>
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.0.initd b/net-misc/mediatomb/files/mediatomb-0.12.0.initd
new file mode 100644
index 000000000000..5f6112b3499b
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.0.initd
@@ -0,0 +1,22 @@
+#!/sbin/runscript
+
+depend() {
+ need net #MYSQL#
+}
+
+start() {
+ ebegin "Starting MediaTomb"
+ start-stop-daemon --start --quiet --exec /usr/bin/mediatomb \
+ --pidfile ${MEDIATOMB_PIDFILE} -- --daemon \
+ --pidfile ${MEDIATOMB_PIDFILE} --user ${MEDIATOMB_USER} \
+ --group ${MEDIATOMB_GROUP} --logfile ${MEDIATOMB_LOGFILE} \
+ --config ${MEDIATOMB_CONFIG} --port ${MEDIATOMB_PORT} \
+ ${MEDIATOMB_OPTIONS}
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping MediaTomb"
+ start-stop-daemon --stop --retry 10 --quiet --pidfile ${MEDIATOMB_PIDFILE}
+ eend $?
+}
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-avformatcontext-pointer.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-avformatcontext-pointer.patch
new file mode 100644
index 000000000000..ab3e7cf7e17d
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-avformatcontext-pointer.patch
@@ -0,0 +1,19 @@
+When opening a file to check its avformat, the AVFormatContext pointer was
+not initialized to NULL before it was passed by reference to the open
+function.
+
+Patch by Bradley Broom <bmbroom@gmail.com>
+
+https://bugs.gentoo.org/show_bug.cgi?id=446922
+
+--- mediatomb-0.12.1/src/metadata/ffmpeg_handler.cc
++++ mediatomb-0.12.1/src/metadata/ffmpeg_handler.cc
+@@ -281,7 +281,7 @@
+ int x = 0;
+ int y = 0;
+
+- AVFormatContext *pFormatCtx;
++ AVFormatContext *pFormatCtx = NULL;
+
+ // Suppress all log messages
+ av_log_set_callback(FfmpegNoOutputStub);
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-flac-metadata.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-flac-metadata.patch
new file mode 100644
index 000000000000..0228dffd08d8
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-flac-metadata.patch
@@ -0,0 +1,446 @@
+diff -urpN a/build/Makefile.am b/build/Makefile.am
+--- a/build/Makefile.am 2010-03-22 21:39:46.000000000 +1100
++++ b/build/Makefile.am 2013-12-16 10:16:32.426878578 +1100
+@@ -18,6 +18,7 @@ libmediatomb_a_CXXFLAGS = \
+ $(ICONV_CXXFLAGS) \
+ $(LIBMAGIC_CFLAGS) \
+ $(ID3LIB_CFLAGS) \
++ $(FLAC_CFLAGS) \
+ $(LIBEXIF_CFLAGS) \
+ $(ZLIB_CFLAGS) \
+ $(PTHREAD_CFLAGS) \
+@@ -44,6 +45,7 @@ mediatomb_CXXFLAGS = -I$(top_srcdir)/src
+ $(ICONV_CXXFLAGS) \
+ $(LIBMAGIC_CFLAGS) \
+ $(ID3LIB_CFLAGS) \
++ $(FLAC_CFLAGS) \
+ $(LIBEXIF_CFLAGS) \
+ $(ZLIB_CFLAGS) \
+ $(PTHREAD_CFLAGS) \
+@@ -78,6 +80,7 @@ mediatomb_LDADD = \
+ $(JS_LIBS) \
+ $(LIBMAGIC_LIBS) \
+ $(ID3LIB_LIBS) \
++ $(FLAC_LIBS) \
+ $(LIBEXIF_LIBS) \
+ $(ZLIB_LIBS) \
+ $(RT_LIBS) \
+diff -urpN a/build/libmediatomb_src b/build/libmediatomb_src
+--- a/build/libmediatomb_src 2010-03-23 04:09:53.000000000 +1100
++++ b/build/libmediatomb_src 2013-12-16 10:14:49.730356868 +1100
+@@ -98,6 +98,8 @@ libmediatomb_a_SOURCES = \
+ ../src/metadata/libmp4v2_handler.h \
+ ../src/metadata/taglib_handler.cc \
+ ../src/metadata/taglib_handler.h \
++../src/metadata/flac_handler.cc \
++../src/metadata/flac_handler.h \
+ ../src/mpegdemux/buffer.c \
+ ../src/mpegdemux/buffer.h \
+ ../src/mpegdemux/mpegdemux.c \
+diff -urpN a/configure.ac b/configure.ac
+--- a/configure.ac 2010-04-08 08:38:51.000000000 +1000
++++ b/configure.ac 2013-12-16 10:24:16.547793225 +1100
+@@ -1314,6 +1314,35 @@ LDFLAGS="$LDFLAGS_SAVE"
+ LIBS="$LIBS_SAVE"
+ CXXFLAGS="$CXXFLAGS_SAVE"
+ CPPFLAGS="$CPPFLAGS_SAVE"
++
++######### FLAC
++
++FLAC_STATUS=
++
++MT_OPTION([FLAC], [enable],
++ [FLAC metadata extraction with the help of FLAC],[],[])
++
++if test "x$FLAC_OPTION_ENABLED" = xyes; then
++ MT_CHECK_PACKAGE([FLAC],
++ [FLAC/metadata],
++ [FLAC], [main])
++else
++ FLAC_STATUS=disabled
++fi
++
++if test "x$FLAC_STATUS" != xyes; then
++ if (test "x$FLAC_OPTION_REQUESTED" = xyes) &&
++ (test "x$FLAC_OPTION_ENABLED" = xyes); then
++ AC_MSG_ERROR([unable to configure FLAC support])
++ fi
++else
++ CFLAGS="$CFLAGS $FLAC_CFLAGS"
++ CXXFLAGS="$CXXFLAGS $FLAC_CFLAGS"
++ LDFLAGS="$LDFLAGS $FLAC_LDFLAGS $FLAC_LIBS"
++ AC_LANG_SAVE
++ AC_LANG_CPLUSPLUS
++fi
++
+ ######## curl
+
+ CURL_PROG_FOUND=0
+@@ -1914,7 +1943,7 @@ if (test "x$SOPCAST_OPTION_ENABLED" = xy
+ AC_DEFINE([SOPCAST], [1], [Enable support for the SopCast service])
+ fi
+
+-AC_DEFINE_UNQUOTED([COMPILE_INFO], "\thost:\t\t\t$host\n\tsqlite3:\t\t$SQLITE3_STATUS\n\tmysql:\t\t\t$MYSQL_STATUS\n\tlibjs:\t\t\t$JS_OK\n\tlibmagic:\t\t$LIBMAGIC_STATUS\n\tinotify:\t\t$INOTIFY_STATUS\n\tlibexif:\t\t$LIBEXIF_STATUS\n\tid3lib:\t\t\t$ID3LIB_STATUS\n\ttaglib:\t\t\t$TAGLIB_STATUS\n\tffmpeg\t\t\t$FFMPEG_STATUS\n\tlibmp4v2:\t\t$LIBMP4V2_STATUS\n\texternal transcoding:\t$EXTERNAL_TRANSCODING_OPTION_ENABLED\n\tcurl:\t\t\t$CURL_OK\n\tYouTube:\t\t$YOUTUBE_OPTION_ENABLED\n\tlibextractor\t\t$LIBEXTRACTOR_STATUS\n\tdb-autocreate:\t\t$DB_AUTOCREATE_OPTION_ENABLED\n\tdebug log:\t\t$DEBUG_LOG_OPTION_ENABLED\n\tprotocol info extension:$PROTOCOLINFO_EXTENSION_OPTION_ENABLED\n\tffmpegthumbnailer:\t$FFMPEGTHUMBNAILER_STATUS\n\tlastfmlib:\t\t$LASTFMLIB_STATUS\n\tdata directory:\t\t$PACKAGE_DATADIR", [compile option summary])
++AC_DEFINE_UNQUOTED([COMPILE_INFO], "\thost:\t\t\t$host\n\tsqlite3:\t\t$SQLITE3_STATUS\n\tmysql:\t\t\t$MYSQL_STATUS\n\tlibjs:\t\t\t$JS_OK\n\tlibmagic:\t\t$LIBMAGIC_STATUS\n\tinotify:\t\t$INOTIFY_STATUS\n\tlibexif:\t\t$LIBEXIF_STATUS\n\tid3lib:\t\t\t$ID3LIB_STATUS\n\ttaglib:\t\t\t$TAGLIB_STATUS\n\tFLAC:\t\t\t$FLAC_STATUS\n\tffmpeg\t\t\t$FFMPEG_STATUS\n\tlibmp4v2:\t\t$LIBMP4V2_STATUS\n\texternal transcoding:\t$EXTERNAL_TRANSCODING_OPTION_ENABLED\n\tcurl:\t\t\t$CURL_OK\n\tYouTube:\t\t$YOUTUBE_OPTION_ENABLED\n\tlibextractor\t\t$LIBEXTRACTOR_STATUS\n\tdb-autocreate:\t\t$DB_AUTOCREATE_OPTION_ENABLED\n\tdebug log:\t\t$DEBUG_LOG_OPTION_ENABLED\n\tprotocol info extension:$PROTOCOLINFO_EXTENSION_OPTION_ENABLED\n\tffmpegthumbnailer:\t$FFMPEGTHUMBNAILER_STATUS\n\tlastfmlib:\t\t$LASTFMLIB_STATUS\n\tdata directory:\t\t$PACKAGE_DATADIR", [compile option summary])
+
+ ###############
+ AC_CONFIG_FILES([
+@@ -1946,6 +1975,7 @@ echo "inotify : $INOTIFY_S
+ echo "libexif : $LIBEXIF_STATUS"
+ echo "id3lib : $ID3LIB_STATUS"
+ echo "taglib : $TAGLIB_STATUS"
++echo "FLAC : $FLAC_STATUS"
+ echo "libmp4v2 : $LIBMP4V2_STATUS"
+ echo "ffmpeg : $FFMPEG_STATUS"
+ echo "ffmpegthumbnailer : $FFMPEGTHUMBNAILER_STATUS"
+diff -urpN a/src/cds_resource_manager.cc b/src/cds_resource_manager.cc
+--- a/src/cds_resource_manager.cc 2010-03-26 01:58:11.000000000 +1100
++++ b/src/cds_resource_manager.cc 2013-12-16 10:25:15.277987292 +1100
+@@ -372,6 +372,7 @@ void CdsResourceManager::addResources(Re
+ // only add upnp:AlbumArtURI if we have an AA, skip the resource
+ if ((i > 0) && ((item->getResource(i)->getHandlerType() == CH_ID3) ||
+ (item->getResource(i)->getHandlerType() == CH_MP4) ||
++ (item->getResource(i)->getHandlerType() == CH_FLAC) ||
+ (item->getResource(i)->getHandlerType() == CH_EXTURL)))
+ {
+ String rct;
+diff -urpN a/src/config_manager.cc b/src/config_manager.cc
+--- a/src/config_manager.cc 2010-03-26 01:58:11.000000000 +1100
++++ b/src/config_manager.cc 2013-12-16 10:26:57.220886235 +1100
+@@ -624,6 +624,10 @@ String ConfigManager::createDefaultConfi
+ _(CONTENT_TYPE_OGG)));
+ mtcontent->appendElementChild(treat_as(_("audio/x-flac"),
+ _(CONTENT_TYPE_FLAC)));
++ mtcontent->appendElementChild(treat_as(_("audio/x-ms-wma"),
++ _(CONTENT_TYPE_WMA)));
++ mtcontent->appendElementChild(treat_as(_("audio/x-wavpack"),
++ _(CONTENT_TYPE_WAVPACK)));
+ mtcontent->appendElementChild(treat_as(_("image/jpeg"),
+ _(CONTENT_TYPE_JPG)));
+ mtcontent->appendElementChild(treat_as(_("audio/x-mpegurl"),
+diff -urpN a/src/metadata/flac_handler.cc b/src/metadata/flac_handler.cc
+--- a/src/metadata/flac_handler.cc 1970-01-01 10:00:00.000000000 +1000
++++ b/src/metadata/flac_handler.cc 2013-12-16 10:30:19.955604387 +1100
+@@ -0,0 +1,204 @@
++/*MT*
++
++ MediaTomb - http://www.mediatomb.cc/
++
++ flac_handler.cc - this file is part of MediaTomb.
++
++ Copyright (C) 2005 Gena Batyan <bgeradz@mediatomb.cc>,
++ Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>
++
++ Copyright (C) 2006-2009 Gena Batyan <bgeradz@mediatomb.cc>,
++ Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>,
++ Leonhard Wimmer <leo@mediatomb.cc>
++
++ MediaTomb is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License version 2
++ as published by the Free Software Foundation.
++
++ MediaTomb 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 General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ version 2 along with MediaTomb; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
++
++ # $Id$
++*/
++
++/// \file flac_handler.cc
++/// \brief Implementeation of the FlacHandler class.
++
++#ifdef HAVE_CONFIG_H
++ #include "autoconfig.h"
++#endif
++
++#ifdef HAVE_FLAC
++
++#include <FLAC/all.h>
++
++#include "flac_handler.h"
++#include "string_converter.h"
++#include "config_manager.h"
++#include "common.h"
++#include "tools.h"
++#include "mem_io_handler.h"
++
++#include "content_manager.h"
++
++using namespace zmm;
++
++FlacHandler::FlacHandler() : MetadataHandler()
++{
++}
++
++static void addField(metadata_fields_t field, const FLAC__StreamMetadata* tags, Ref<CdsItem> item)
++{
++ String value;
++ int i;
++
++ Ref<StringConverter> sc = StringConverter::i2i(); // sure is sure
++
++ switch (field)
++ {
++ case M_TITLE:
++ i = FLAC__metadata_object_vorbiscomment_find_entry_from(tags, /*offset=*/0, "TITLE");
++ break;
++ case M_ARTIST:
++ i = FLAC__metadata_object_vorbiscomment_find_entry_from(tags, /*offset=*/0, "ARTIST");
++ break;
++ case M_ALBUM:
++ i = FLAC__metadata_object_vorbiscomment_find_entry_from(tags, /*offset=*/0, "ALBUM");
++ break;
++ case M_DATE:
++ i = FLAC__metadata_object_vorbiscomment_find_entry_from(tags, /*offset=*/0, "DATE");
++ break;
++ case M_GENRE:
++ i = FLAC__metadata_object_vorbiscomment_find_entry_from(tags, /*offset=*/0, "GENRE");
++ break;
++ case M_DESCRIPTION:
++ i = FLAC__metadata_object_vorbiscomment_find_entry_from(tags, /*offset=*/0, "DESCRIPTION");
++ break;
++ case M_TRACKNUMBER:
++ i = FLAC__metadata_object_vorbiscomment_find_entry_from(tags, /*offset=*/0, "TRACKNUMBER");
++ break;
++ default:
++ return;
++ }
++
++ if( 0 <= i )
++ value = strchr((const char *)tags->data.vorbis_comment.comments[i].entry, '=') + 1;
++ else
++ return;
++
++ value = trim_string(value);
++
++ if (string_ok(value))
++ {
++ item->setMetadata(MT_KEYS[field].upnp, sc->convert(value));
++ log_debug("Setting metadata on item: %d, %s\n", field, sc->convert(value).c_str());
++ }
++}
++
++void FlacHandler::fillMetadata(Ref<CdsItem> item)
++{
++ FLAC__StreamMetadata* tags = NULL;
++ FLAC__StreamMetadata streaminfo;
++ Ref<StringConverter> sc = StringConverter::i2i(); // sure is sure
++
++ if( !FLAC__metadata_get_tags(item->getLocation().c_str(), &tags) )
++ return;
++
++ if( FLAC__METADATA_TYPE_VORBIS_COMMENT == tags->type )
++ {
++ for (int i = 0; i < M_MAX; i++)
++ addField((metadata_fields_t) i, tags, item);
++ }
++
++ FLAC__metadata_object_delete(tags);
++ tags = NULL;
++
++ if( !FLAC__metadata_get_streaminfo(item->getLocation().c_str(), &streaminfo) )
++ return;
++
++ if( FLAC__METADATA_TYPE_STREAMINFO == streaminfo.type )
++ {
++ // note: UPnP requires bytes/second
++ item->getResource(0)->addAttribute(MetadataHandler::getResAttrName(R_BITRATE), String::from((unsigned)((streaminfo.data.stream_info.bits_per_sample * streaminfo.data.stream_info.sample_rate) / 8)));
++ // note: UPnP requires HMS
++ item->getResource(0)->addAttribute(MetadataHandler::getResAttrName(R_DURATION), secondsToHMS((unsigned)(streaminfo.data.stream_info.total_samples / streaminfo.data.stream_info.sample_rate)));
++ item->getResource(0)->addAttribute(MetadataHandler::getResAttrName(R_SAMPLEFREQUENCY), String::from(streaminfo.data.stream_info.sample_rate));
++ item->getResource(0)->addAttribute(MetadataHandler::getResAttrName(R_NRAUDIOCHANNELS), String::from(streaminfo.data.stream_info.channels));
++ }
++
++ if( !FLAC__metadata_get_picture(item->getLocation().c_str(),
++ &tags,
++ FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER,
++ NULL,
++ NULL,
++ (unsigned)-1,
++ (unsigned)-1,
++ (unsigned)-1,
++ (unsigned)-1 ) )
++ return;
++
++ if( FLAC__METADATA_TYPE_PICTURE == tags->type )
++ {
++ String art_mimetype = tags->data.picture.mime_type;
++ log_debug("Mime type : %s\n", sc->convert(art_mimetype).c_str());
++
++ // saw that simply "PNG" was used with some mp3's, so mimetype setting
++ // was probably invalid
++ if (!string_ok(art_mimetype) || (art_mimetype.index('/') == -1))
++ {
++#ifdef HAVE_MAGIC
++ art_mimetype = ContentManager::getInstance()->getMimeTypeFromBuffer((void *)tags->data.picture.data, tags->data.picture.data_length);
++ if (!string_ok(art_mimetype))
++#endif
++ art_mimetype = _(MIMETYPE_DEFAULT);
++
++ log_debug("Mime type via magic: %s\n", sc->convert(art_mimetype).c_str());
++ }
++
++ // if we could not determine the mimetype, then there is no
++ // point to add the resource - it's probably garbage
++ if (art_mimetype != _(MIMETYPE_DEFAULT))
++ {
++ Ref<CdsResource> resource(new CdsResource(CH_FLAC));
++ resource->addAttribute(MetadataHandler::getResAttrName(R_PROTOCOLINFO), renderProtocolInfo(art_mimetype));
++ resource->addParameter(_(RESOURCE_CONTENT_TYPE), _(ID3_ALBUM_ART));
++ item->addResource(resource);
++ }
++ }
++
++ FLAC__metadata_object_delete(tags);
++}
++
++Ref<IOHandler> FlacHandler::serveContent(Ref<CdsItem> item, int resNum, off_t *data_size)
++{
++ FLAC__StreamMetadata* picture = NULL;
++
++ if( !FLAC__metadata_get_picture(item->getLocation().c_str(),
++ &picture,
++ FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER,
++ NULL,
++ NULL,
++ (unsigned)-1,
++ (unsigned)-1,
++ (unsigned)-1,
++ (unsigned)-1 ) )
++ throw _Exception(_("FlacHandler: could not exctract cover from: ") + item->getLocation());
++
++ if( FLAC__METADATA_TYPE_PICTURE != picture->type )
++ throw _Exception(_("TagHandler: resource has no album information"));
++
++ Ref<IOHandler> h(new MemIOHandler((void *)picture->data.picture.data, picture->data.picture.data_length));
++ *data_size = picture->data.picture.data_length;
++
++ FLAC__metadata_object_delete(picture);
++
++ return h;
++}
++
++#endif // HAVE_FLAC
+diff -urpN a/src/metadata/flac_handler.h b/src/metadata/flac_handler.h
+--- a/src/metadata/flac_handler.h 1970-01-01 10:00:00.000000000 +1000
++++ b/src/metadata/flac_handler.h 2013-12-16 10:31:24.061822827 +1100
+@@ -0,0 +1,47 @@
++/*MT*
++
++ MediaTomb - http://www.mediatomb.cc/
++
++ flac_handler.h - this file is part of MediaTomb.
++
++ Copyright (C) 2005 Gena Batyan <bgeradz@mediatomb.cc>,
++ Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>
++
++ Copyright (C) 2006-2009 Gena Batyan <bgeradz@mediatomb.cc>,
++ Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>,
++ Leonhard Wimmer <leo@mediatomb.cc>
++
++ MediaTomb is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License version 2
++ as published by the Free Software Foundation.
++
++ MediaTomb 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 General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ version 2 along with MediaTomb; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
++
++ # $Id$
++*/
++
++/// \file flac_handler.h
++/// \brief Definition of the FlacHandler class.
++
++#ifndef __METADATA_FLAC_H__
++#define __METADATA_FLAC_H__
++
++#include "metadata_handler.h"
++
++/// \brief This class is responsible for reading FLAC metadata
++class FlacHandler : public MetadataHandler
++{
++public:
++ FlacHandler();
++ virtual void fillMetadata(zmm::Ref<CdsItem> item);
++ virtual zmm::Ref<IOHandler> serveContent(zmm::Ref<CdsItem> item, int resNum, off_t *data_size);
++};
++
++#endif // __METADATA_FLAC_H__
+diff -urpN a/src/metadata_handler.cc b/src/metadata_handler.cc
+--- a/src/metadata_handler.cc 2010-03-26 01:58:11.000000000 +1100
++++ b/src/metadata_handler.cc 2013-12-16 10:35:48.783540865 +1100
+@@ -51,6 +51,10 @@
+ #endif // HAVE_ID3LIB
+ #endif // HAVE_TAGLIB
+
++#ifdef HAVE_FLAC
++#include "metadata/flac_handler.h"
++#endif
++
+ #ifdef HAVE_LIBMP4V2
+ #include "metadata/libmp4v2_handler.h"
+ #endif
+@@ -140,7 +144,8 @@ void MetadataHandler::setMetadata(Ref<Cd
+ if ((content_type == CONTENT_TYPE_MP3) ||
+ ((content_type == CONTENT_TYPE_OGG) &&
+ (!item->getFlag(OBJECT_FLAG_OGG_THEORA))) ||
+- (content_type == CONTENT_TYPE_FLAC))
++ (content_type == CONTENT_TYPE_WMA) ||
++ (content_type == CONTENT_TYPE_WAVPACK))
+ {
+ handler = Ref<MetadataHandler>(new TagHandler());
+ break;
+@@ -155,7 +160,13 @@ void MetadataHandler::setMetadata(Ref<Cd
+ #endif // HAVE_ID3LIB
+ #endif // HAVE_TAGLIB
+
+-
++#ifdef HAVE_FLAC
++ if (content_type == CONTENT_TYPE_FLAC)
++ {
++ handler = Ref<MetadataHandler>(new FlacHandler());
++ break;
++ }
++#endif
+
+ #ifdef HAVE_EXIV2
+ /*
+@@ -277,6 +288,10 @@ Ref<MetadataHandler> MetadataHandler::cr
+ case CH_FFTH:
+ return Ref<MetadataHandler>(new FfmpegHandler());
+ #endif
++#ifdef HAVE_FLAC
++ case CH_FLAC:
++ return Ref<MetadataHandler>(new FlacHandler());
++#endif
+ default:
+ throw _Exception(_("unknown content handler ID: ") + handlerType);
+ }
+diff -urpN a/src/metadata_handler.h b/src/metadata_handler.h
+--- a/src/metadata_handler.h 2010-03-26 01:58:11.000000000 +1100
++++ b/src/metadata_handler.h 2013-12-16 10:52:23.234353526 +1100
+@@ -45,10 +45,13 @@
+ #define CH_EXTURL 4
+ #define CH_MP4 5
+ #define CH_FFTH 6
++#define CH_FLAC 7
+
+ #define CONTENT_TYPE_MP3 "mp3"
+ #define CONTENT_TYPE_OGG "ogg"
+ #define CONTENT_TYPE_FLAC "flac"
++#define CONTENT_TYPE_WMA "wma"
++#define CONTENT_TYPE_WAVPACK "wv"
+ #define CONTENT_TYPE_JPG "jpg"
+ #define CONTENT_TYPE_PLAYLIST "playlist"
+ #define CONTENT_TYPE_MP4 "mp4"
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-inotify-hard-links.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-inotify-hard-links.patch
new file mode 100644
index 000000000000..af9a887befe0
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-inotify-hard-links.patch
@@ -0,0 +1,34 @@
+make sure new hard links get processed like new files by handling
+the IN_CREATE flag properly
+
+patch by Mike Frysinger
+
+--- a/src/autoscan_inotify.cc
++++ b/src/autoscan_inotify.cc
+@@ -281,7 +284,7 @@
+ }
+ }
+
+- if (adir != nil && mask & (IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF | IN_CLOSE_WRITE | IN_MOVED_FROM | IN_MOVED_TO | IN_UNMOUNT))
++ if (adir != nil && mask & (IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF | IN_CLOSE_WRITE | IN_MOVED_FROM | IN_MOVED_TO | IN_UNMOUNT | IN_CREATE))
+ {
+ String fullPath;
+ if (mask & IN_ISDIR)
+@@ -289,7 +292,7 @@
+ else
+ fullPath = path;
+
+- if (! (mask & IN_MOVED_TO))
++ if (! (mask & (IN_MOVED_TO | IN_CREATE)))
+ {
+ log_debug("deleting %s\n", fullPath.c_str());
+
+@@ -312,7 +315,7 @@
+ if (objectID != INVALID_OBJECT_ID)
+ cm->removeObject(objectID);
+ }
+- if (mask & (IN_CLOSE_WRITE | IN_MOVED_TO))
++ if (mask & (IN_CLOSE_WRITE | IN_MOVED_TO | IN_CREATE))
+ {
+ log_debug("adding %s\n", path.c_str());
+ // path, recursive, async, hidden, low priority, cancellable
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-libav9.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-libav9.patch
new file mode 100644
index 000000000000..7193b7c03cd4
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-libav9.patch
@@ -0,0 +1,42 @@
+diff -burN mediatomb-0.12.1.old//src/metadata/ffmpeg_handler.cc mediatomb-0.12.1/src/metadata/ffmpeg_handler.cc
+--- mediatomb-0.12.1.old//src/metadata/ffmpeg_handler.cc 2012-11-25 14:55:05.335753129 +0100
++++ mediatomb-0.12.1/src/metadata/ffmpeg_handler.cc 2012-11-25 15:29:42.840677486 +0100
+@@ -110,8 +110,8 @@
+ return;
+ for (const mapping_t *m = mapping; m->avname != NULL; m++)
+ {
+- AVMetadataTag *tag = NULL;
+- tag = av_metadata_get(pFormatCtx->metadata, m->avname, NULL, 0);
++ AVDictionaryEntry *tag = NULL;
++ tag = av_dict_get(pFormatCtx->metadata, m->avname, NULL, 0);
+ if (tag && tag->value && tag->value[0])
+ {
+ log_debug("Added metadata %s: %s\n", m->avname, tag->value);
+@@ -290,14 +290,14 @@
+ av_register_all();
+
+ // Open video file
+- if (av_open_input_file(&pFormatCtx,
+- item->getLocation().c_str(), NULL, 0, NULL) != 0)
++ if (avformat_open_input(&pFormatCtx,
++ item->getLocation().c_str(), NULL, NULL) != 0)
+ return; // Couldn't open file
+
+ // Retrieve stream information
+- if (av_find_stream_info(pFormatCtx) < 0)
++ if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
+ {
+- av_close_input_file(pFormatCtx);
++ avformat_close_input(&pFormatCtx);
+ return; // Couldn't find stream information
+ }
+ // Add metadata using ffmpeg library calls
+@@ -306,7 +306,7 @@
+ addFfmpegResourceFields(item, pFormatCtx, &x, &y);
+
+ // Close the video file
+- av_close_input_file(pFormatCtx);
++ avformat_close_input(&pFormatCtx);
+ }
+
+ static bool _mkdir(const char *path)
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-libextractor.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-libextractor.patch
new file mode 100644
index 000000000000..e46aca9c487f
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-libextractor.patch
@@ -0,0 +1,675 @@
+http://bugs.gentoo.org/435394
+
+port to libextractor-0.6.x
+
+patch by Mike Frysinger <vapier@gentoo.org>
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -1631,7 +1631,7 @@ MT_CHECK_OPTIONAL_PACKAGE([lastfmlib], [disable],
+ ######## extractor
+
+ if test "x$LIBEXTRACTOR_OPTION_ENABLED" = xyes; then
+- MT_CHECK_PACKAGE([libextractor], [extractor], [extractor], [EXTRACTOR_getKeywords])
++ MT_CHECK_PACKAGE([libextractor], [extractor], [extractor], [EXTRACTOR_extract])
+ fi
+
+ if test "x$LIBEXTRACTOR_STATUS" = xyes; then
+--- a/src/metadata/extractor_handler.cc
++++ b/src/metadata/extractor_handler.cc
+@@ -55,322 +55,344 @@ ExtractorHandler::ExtractorHandler() : MetadataHandler()
+ {
+ }
+
+-static EXTRACTOR_KeywordType getTagFromString(String tag)
++static EXTRACTOR_MetaType getTagFromString(String tag)
+ {
+- if (tag == "EXTRACTOR_UNKNOWN")
+- return EXTRACTOR_UNKNOWN;
+- if (tag == "EXTRACTOR_FILENAME")
+- return EXTRACTOR_FILENAME;
+- if (tag == "EXTRACTOR_MIMETYPE")
+- return EXTRACTOR_MIMETYPE;
+- if (tag == "EXTRACTOR_TITLE")
+- return EXTRACTOR_TITLE;
+- if (tag == "EXTRACTOR_AUTHOR")
+- return EXTRACTOR_AUTHOR;
+- if (tag == "EXTRACTOR_ARTIST")
+- return EXTRACTOR_ARTIST;
+- if (tag == "EXTRACTOR_DESCRIPTION")
+- return EXTRACTOR_DESCRIPTION;
+- if (tag == "EXTRACTOR_COMMENT")
+- return EXTRACTOR_COMMENT;
+- if (tag == "EXTRACTOR_DATE")
+- return EXTRACTOR_DATE;
+- if (tag == "EXTRACTOR_PUBLISHER")
+- return EXTRACTOR_PUBLISHER;
+- if (tag == "EXTRACTOR_LANGUAGE")
+- return EXTRACTOR_LANGUAGE;
+- if (tag == "EXTRACTOR_ALBUM")
+- return EXTRACTOR_ALBUM;
+- if (tag == "EXTRACTOR_GENRE")
+- return EXTRACTOR_GENRE;
+- if (tag == "EXTRACTOR_LOCATION")
+- return EXTRACTOR_LOCATION;
+- if (tag == "EXTRACTOR_VERSIONNUMBER")
+- return EXTRACTOR_VERSIONNUMBER;
+- if (tag == "EXTRACTOR_ORGANIZATION")
+- return EXTRACTOR_ORGANIZATION;
+- if (tag == "EXTRACTOR_COPYRIGHT")
+- return EXTRACTOR_COPYRIGHT;
+- if (tag == "EXTRACTOR_SUBJECT")
+- return EXTRACTOR_SUBJECT;
+- if (tag == "EXTRACTOR_KEYWORDS")
+- return EXTRACTOR_KEYWORDS;
+- if (tag == "EXTRACTOR_CONTRIBUTOR")
+- return EXTRACTOR_CONTRIBUTOR;
+- if (tag == "EXTRACTOR_RESOURCE_TYPE")
+- return EXTRACTOR_RESOURCE_TYPE;
+- if (tag == "EXTRACTOR_FORMAT")
+- return EXTRACTOR_FORMAT;
+- if (tag == "EXTRACTOR_RESOURCE_IDENTIFIER")
+- return EXTRACTOR_RESOURCE_IDENTIFIER;
+- if (tag == "EXTRACTOR_SOURCE")
+- return EXTRACTOR_SOURCE;
+- if (tag == "EXTRACTOR_RELATION")
+- return EXTRACTOR_RELATION;
+- if (tag == "EXTRACTOR_COVERAGE")
+- return EXTRACTOR_COVERAGE;
+- if (tag == "EXTRACTOR_SOFTWARE")
+- return EXTRACTOR_SOFTWARE;
+- if (tag == "EXTRACTOR_DISCLAIMER")
+- return EXTRACTOR_DISCLAIMER;
+- if (tag == "EXTRACTOR_WARNING")
+- return EXTRACTOR_WARNING;
+- if (tag == "EXTRACTOR_TRANSLATED")
+- return EXTRACTOR_TRANSLATED;
+- if (tag == "EXTRACTOR_CREATION_DATE")
+- return EXTRACTOR_CREATION_DATE;
+- if (tag == "EXTRACTOR_MODIFICATION_DATE")
+- return EXTRACTOR_MODIFICATION_DATE;
+- if (tag == "EXTRACTOR_CREATOR")
+- return EXTRACTOR_CREATOR;
+- if (tag == "EXTRACTOR_PRODUCER")
+- return EXTRACTOR_PRODUCER;
+- if (tag == "EXTRACTOR_PAGE_COUNT")
+- return EXTRACTOR_PAGE_COUNT;
+- if (tag == "EXTRACTOR_PAGE_ORIENTATION")
+- return EXTRACTOR_PAGE_ORIENTATION;
+- if (tag == "EXTRACTOR_PAPER_SIZE")
+- return EXTRACTOR_PAPER_SIZE;
+- if (tag == "EXTRACTOR_USED_FONTS")
+- return EXTRACTOR_USED_FONTS;
+- if (tag == "EXTRACTOR_PAGE_ORDER")
+- return EXTRACTOR_PAGE_ORDER;
+- if (tag == "EXTRACTOR_CREATED_FOR")
+- return EXTRACTOR_CREATED_FOR;
+- if (tag == "EXTRACTOR_MAGNIFICATION")
+- return EXTRACTOR_MAGNIFICATION;
+- if (tag == "EXTRACTOR_RELEASE")
+- return EXTRACTOR_RELEASE;
+- if (tag == "EXTRACTOR_GROUP")
+- return EXTRACTOR_GROUP;
+- if (tag == "EXTRACTOR_SIZE")
+- return EXTRACTOR_SIZE;
+- if (tag == "EXTRACTOR_SUMMARY")
+- return EXTRACTOR_SUMMARY;
+- if (tag == "EXTRACTOR_PACKAGER")
+- return EXTRACTOR_PACKAGER;
+- if (tag == "EXTRACTOR_VENDOR")
+- return EXTRACTOR_VENDOR;
+- if (tag == "EXTRACTOR_LICENSE")
+- return EXTRACTOR_LICENSE;
+- if (tag == "EXTRACTOR_DISTRIBUTION")
+- return EXTRACTOR_DISTRIBUTION;
+- if (tag == "EXTRACTOR_BUILDHOST")
+- return EXTRACTOR_BUILDHOST;
+- if (tag == "EXTRACTOR_OS")
+- return EXTRACTOR_OS;
+- if (tag == "EXTRACTOR_DEPENDENCY")
+- return EXTRACTOR_DEPENDENCY;
+- if (tag == "EXTRACTOR_HASH_MD4")
+- return EXTRACTOR_HASH_MD4;
+- if (tag == "EXTRACTOR_HASH_MD5")
+- return EXTRACTOR_HASH_MD5;
+- if (tag == "EXTRACTOR_HASH_SHA0")
+- return EXTRACTOR_HASH_SHA0;
+- if (tag == "EXTRACTOR_HASH_SHA1")
+- return EXTRACTOR_HASH_SHA1;
+- if (tag == "EXTRACTOR_HASH_RMD160")
+- return EXTRACTOR_HASH_RMD160;
+- if (tag == "EXTRACTOR_RESOLUTION")
+- return EXTRACTOR_RESOLUTION;
+- if (tag == "EXTRACTOR_CATEGORY")
+- return EXTRACTOR_CATEGORY;
+- if (tag == "EXTRACTOR_BOOKTITLE")
+- return EXTRACTOR_BOOKTITLE;
+- if (tag == "EXTRACTOR_PRIORITY")
+- return EXTRACTOR_PRIORITY;
+- if (tag == "EXTRACTOR_CONFLICTS")
+- return EXTRACTOR_CONFLICTS;
+- if (tag == "EXTRACTOR_REPLACES")
+- return EXTRACTOR_REPLACES;
+- if (tag == "EXTRACTOR_PROVIDES")
+- return EXTRACTOR_PROVIDES;
+- if (tag == "EXTRACTOR_CONDUCTOR")
+- return EXTRACTOR_CONDUCTOR;
+- if (tag == "EXTRACTOR_INTERPRET")
+- return EXTRACTOR_INTERPRET;
+- if (tag == "EXTRACTOR_OWNER")
+- return EXTRACTOR_OWNER;
+- if (tag == "EXTRACTOR_LYRICS")
+- return EXTRACTOR_LYRICS;
+- if (tag == "EXTRACTOR_MEDIA_TYPE")
+- return EXTRACTOR_MEDIA_TYPE;
+- if (tag == "EXTRACTOR_CONTACT")
+- return EXTRACTOR_CONTACT;
+- if (tag == "EXTRACTOR_THUMBNAIL_DATA")
+- return EXTRACTOR_THUMBNAIL_DATA;
+-
+-#ifdef EXTRACTOR_GE_0_5_2
+- if (tag == "EXTRACTOR_PUBLICATION_DATE")
+- return EXTRACTOR_PUBLICATION_DATE;
+- if (tag == "EXTRACTOR_CAMERA_MAKE")
+- return EXTRACTOR_CAMERA_MAKE;
+- if (tag == "EXTRACTOR_CAMERA_MODEL")
+- return EXTRACTOR_CAMERA_MODEL;
+- if (tag == "EXTRACTOR_EXPOSURE")
+- return EXTRACTOR_EXPOSURE;
+- if (tag == "EXTRACTOR_APERTURE")
+- return EXTRACTOR_APERTURE;
+- if (tag == "EXTRACTOR_EXPOSURE_BIAS")
+- return EXTRACTOR_EXPOSURE_BIAS;
+- if (tag == "EXTRACTOR_FLASH")
+- return EXTRACTOR_FLASH;
+- if (tag == "EXTRACTOR_FLASH_BIAS")
+- return EXTRACTOR_FLASH_BIAS;
+- if (tag == "EXTRACTOR_FOCAL_LENGTH")
+- return EXTRACTOR_FOCAL_LENGTH;
+- if (tag == "EXTRACTOR_FOCAL_LENGTH_35MM")
+- return EXTRACTOR_FOCAL_LENGTH_35MM;
+- if (tag == "EXTRACTOR_ISO_SPEED")
+- return EXTRACTOR_ISO_SPEED;
+- if (tag == "EXTRACTOR_EXPOSURE_MODE")
+- return EXTRACTOR_EXPOSURE_MODE;
+- if (tag == "EXTRACTOR_METERING_MODE")
+- return EXTRACTOR_METERING_MODE;
+- if (tag == "EXTRACTOR_MACRO_MODE")
+- return EXTRACTOR_MACRO_MODE;
+- if (tag == "EXTRACTOR_IMAGE_QUALITY")
+- return EXTRACTOR_IMAGE_QUALITY;
+- if (tag == "EXTRACTOR_WHITE_BALANCE")
+- return EXTRACTOR_WHITE_BALANCE;
+- if (tag == "EXTRACTOR_ORIENTATION")
+- return EXTRACTOR_ORIENTATION;
+-#endif // EXTRACTOR_GE_0_5_2
++#define T(x) [EXTRACTOR_METATYPE_##x] = "EXTRACTOR_METATYPE_"#x,
++ /* XXX: should convert to EXTRACTOR_metatype_to_string() somehow */
++ const char *types[] =
++ {
++ T(RESERVED)
++ T(MIMETYPE)
++ T(FILENAME)
++ T(COMMENT)
++
++ T(TITLE)
++ T(BOOK_TITLE)
++ T(BOOK_EDITION)
++ T(BOOK_CHAPTER_NUMBER)
++ T(JOURNAL_NAME)
++ T(JOURNAL_VOLUME)
++ T(JOURNAL_NUMBER)
++ T(PAGE_COUNT)
++ T(PAGE_RANGE)
++ T(AUTHOR_NAME)
++ T(AUTHOR_EMAIL)
++ T(AUTHOR_INSTITUTION)
++ T(PUBLISHER)
++ T(PUBLISHER_ADDRESS)
++ T(PUBLISHER_INSTITUTION)
++ T(PUBLISHER_SERIES)
++ T(PUBLICATION_TYPE)
++ T(PUBLICATION_YEAR)
++ T(PUBLICATION_MONTH)
++ T(PUBLICATION_DAY)
++ T(PUBLICATION_DATE)
++ T(BIBTEX_EPRINT)
++ T(BIBTEX_ENTRY_TYPE)
++ T(LANGUAGE)
++ T(CREATION_TIME)
++ T(URL)
++
++ T(URI)
++ T(ISRC)
++ T(HASH_MD4)
++ T(HASH_MD5)
++ T(HASH_SHA0)
++ T(HASH_SHA1)
++ T(HASH_RMD160)
++
++ T(GPS_LATITUDE_REF)
++ T(GPS_LATITUDE)
++ T(GPS_LONGITUDE_REF)
++ T(GPS_LONGITUDE)
++ T(LOCATION_CITY)
++ T(LOCATION_SUBLOCATION)
++ T(LOCATION_COUNTRY)
++ T(LOCATION_COUNTRY_CODE)
++
++ T(UNKNOWN)
++ T(DESCRIPTION)
++ T(COPYRIGHT)
++ T(RIGHTS)
++ T(KEYWORDS)
++ T(ABSTRACT)
++ T(SUMMARY)
++ T(SUBJECT)
++ T(CREATOR)
++ T(FORMAT)
++ T(FORMAT_VERSION)
++
++ T(CREATED_BY_SOFTWARE)
++ T(UNKNOWN_DATE)
++ T(CREATION_DATE)
++ T(MODIFICATION_DATE)
++ T(LAST_PRINTED)
++ T(LAST_SAVED_BY)
++ T(TOTAL_EDITING_TIME)
++ T(EDITING_CYCLES)
++ T(MODIFIED_BY_SOFTWARE)
++ T(REVISION_HISTORY)
++
++ T(EMBEDDED_FILE_SIZE)
++ T(FINDER_FILE_TYPE)
++ T(FINDER_FILE_CREATOR)
++
++ T(PACKAGE_NAME)
++ T(PACKAGE_VERSION)
++ T(SECTION)
++ T(UPLOAD_PRIORITY)
++ T(PACKAGE_DEPENDENCY)
++ T(PACKAGE_CONFLICTS)
++ T(PACKAGE_REPLACES)
++ T(PACKAGE_PROVIDES)
++ T(PACKAGE_RECOMMENDS)
++ T(PACKAGE_SUGGESTS)
++ T(PACKAGE_MAINTAINER)
++ T(PACKAGE_INSTALLED_SIZE)
++ T(PACKAGE_SOURCE)
++ T(PACKAGE_ESSENTIAL)
++ T(TARGET_ARCHITECTURE)
++ T(PACKAGE_PRE_DEPENDENCY)
++ T(LICENSE)
++ T(PACKAGE_DISTRIBUTION)
++ T(BUILDHOST)
++ T(VENDOR)
++ T(TARGET_OS)
++ T(SOFTWARE_VERSION)
++ T(TARGET_PLATFORM)
++ T(RESOURCE_TYPE)
++ T(LIBRARY_SEARCH_PATH)
++ T(LIBRARY_DEPENDENCY)
++
++ T(CAMERA_MAKE)
++ T(CAMERA_MODEL)
++ T(EXPOSURE)
++ T(APERTURE)
++ T(EXPOSURE_BIAS)
++ T(FLASH)
++ T(FLASH_BIAS)
++ T(FOCAL_LENGTH)
++ T(FOCAL_LENGTH_35MM)
++ T(ISO_SPEED)
++ T(EXPOSURE_MODE)
++ T(METERING_MODE)
++ T(MACRO_MODE)
++ T(IMAGE_QUALITY)
++ T(WHITE_BALANCE)
++ T(ORIENTATION)
++ T(MAGNIFICATION)
++
++ T(IMAGE_DIMENSIONS)
++ T(PRODUCED_BY_SOFTWARE)
++ T(THUMBNAIL)
++ T(IMAGE_RESOLUTION)
++ T(SOURCE)
++
++ T(CHARACTER_SET)
++ T(LINE_COUNT)
++ T(PARAGRAPH_COUNT)
++ T(WORD_COUNT)
++ T(CHARACTER_COUNT)
++ T(PAGE_ORIENTATION)
++ T(PAPER_SIZE)
++ T(TEMPLATE)
++ T(COMPANY)
++ T(MANAGER)
++ T(REVISION_NUMBER)
++
++ T(DURATION)
++ T(ALBUM)
++ T(ARTIST)
++ T(GENRE)
++ T(TRACK_NUMBER)
++ T(DISC_NUMBER)
++ T(PERFORMER)
++ T(CONTACT_INFORMATION)
++ T(SONG_VERSION)
++ T(PICTURE)
++ T(COVER_PICTURE)
++ T(CONTRIBUTOR_PICTURE)
++ T(EVENT_PICTURE)
++ T(LOGO)
++ T(BROADCAST_TELEVISION_SYSTEM)
++ T(SOURCE_DEVICE)
++ T(DISCLAIMER)
++ T(WARNING)
++ T(PAGE_ORDER)
++ T(WRITER)
++ T(PRODUCT_VERSION)
++ T(CONTRIBUTOR_NAME)
++ T(MOVIE_DIRECTOR)
++ T(NETWORK_NAME)
++ T(SHOW_NAME)
++ T(CHAPTER_NAME)
++ T(SONG_COUNT)
++ T(STARTING_SONG)
++ T(PLAY_COUNTER)
++ T(CONDUCTOR)
++ T(INTERPRETATION)
++ T(COMPOSER)
++ T(BEATS_PER_MINUTE)
++ T(ENCODED_BY)
++ T(ORIGINAL_TITLE)
++ T(ORIGINAL_ARTIST)
++ T(ORIGINAL_WRITER)
++ T(ORIGINAL_RELEASE_YEAR)
++ T(ORIGINAL_PERFORMER)
++ T(LYRICS)
++ T(POPULARITY_METER)
++ T(LICENSEE)
++ T(MUSICIAN_CREDITS_LIST)
++ T(MOOD)
++ T(SUBTITLE)
++
++ T(GNUNET_DISPLAY_TYPE)
++ T(GNUNET_FULL_DATA)
++ T(RATING)
++ T(ORGANIZATION)
++ T(RIPPER)
++ T(PRODUCER)
++ T(GROUP)
++ T(GNUNET_ORIGINAL_FILENAME)
++ };
++#undef T
++ size_t i;
++
++ for (i = 0; i < sizeof(types) / sizeof(types[0]); ++i)
++ if (!strcmp(types[i], tag.c_str()))
++ return (EXTRACTOR_MetaType) i;
+
+ log_warning("Ignoring unknown libextractor tag: %s\n", tag.c_str());
+- return EXTRACTOR_UNKNOWN;
++ return EXTRACTOR_METATYPE_UNKNOWN;
+ }
+
+-static void addMetaField(metadata_fields_t field, EXTRACTOR_KeywordList *keywords, Ref<CdsItem> item, Ref<StringConverter> sc)
++struct field_state {
++ Ref<CdsItem> item;
++ Ref<StringConverter> sc;
++ Ref<Array<StringBase> > aux;
++};
++
++static int addField(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
++ enum EXTRACTOR_MetaFormat format, const char *data_mime_type,
++ const char *data, size_t data_len)
+ {
+- String value;
+- const char *temp = NULL;
+-
++ metadata_fields_t field = M_MAX;
++ resource_attributes_t attr = R_MAX;
++
++ if (!data)
++ return 0;
++
++ log_debug("metadata %zu [%s] -> %s\n", (size_t)type, EXTRACTOR_metatype_to_string(type), data);
++
+ /// \todo check if UTF-8 conversion is needed, may already be in UTF-8
+-
+- switch (field)
++
++ switch (type)
+ {
+- case M_TITLE:
+- temp = EXTRACTOR_extractLast(EXTRACTOR_TITLE, keywords);
++ case EXTRACTOR_METATYPE_TITLE:
++ field = M_TITLE;
+ break;
+- case M_ARTIST:
+- temp = EXTRACTOR_extractLast(EXTRACTOR_ARTIST, keywords);
++ case EXTRACTOR_METATYPE_ARTIST:
++ field = M_ARTIST;
+ break;
+- case M_ALBUM:
+- temp = EXTRACTOR_extractLast(EXTRACTOR_ALBUM, keywords);
++ case EXTRACTOR_METATYPE_ALBUM:
++ field = M_ALBUM;
+ break;
+- case M_DATE:
+- temp = EXTRACTOR_extractLast(EXTRACTOR_DATE, keywords);
++ case EXTRACTOR_METATYPE_PUBLICATION_YEAR:
++ field = M_DATE;
+ break;
+- case M_GENRE:
+- temp = EXTRACTOR_extractLast(EXTRACTOR_GENRE, keywords);
++ case EXTRACTOR_METATYPE_GENRE:
++ field = M_GENRE;
+ break;
+- case M_DESCRIPTION:
+- temp = EXTRACTOR_extractLast(EXTRACTOR_DESCRIPTION, keywords);
+-
+- if (temp == NULL)
+- temp = EXTRACTOR_extractLast(EXTRACTOR_COMMENT, keywords);
++ case EXTRACTOR_METATYPE_DESCRIPTION:
++ field = M_DESCRIPTION;
++ break;
++ case EXTRACTOR_METATYPE_COMMENT:
++ field = M_DESCRIPTION;
++ break;
++ case EXTRACTOR_METATYPE_IMAGE_DIMENSIONS:
++ attr = R_RESOLUTION;
+ break;
+- default:
+- return;
+ }
+
+- if (temp != NULL)
+- value = temp;
++ String value;
++ struct field_state *field_state = (struct field_state *)cls;
++ Ref<CdsItem> item = field_state->item;
++ Ref<StringConverter> sc = field_state->sc;
++ Ref<Array<StringBase> > aux = field_state->aux;
++
++ if (field == M_MAX && attr == R_MAX && aux == nil)
++ {
++ log_debug("no match\n");
++ return 0;
++ }
+
++ value = data;
+ value = trim_string(value);
+-
+- if (string_ok(value))
++ if (!string_ok(value))
++ return 0;
++
++ if (field != M_MAX)
+ {
+ item->setMetadata(MT_KEYS[field].upnp, sc->convert(value));
+-// log_debug("Setting metadata on item: %d, %s\n", field, sc->convert(value).c_str());
++ log_debug("Setting metadata on item: %d, %s\n", field, sc->convert(value).c_str());
+ }
+-}
+
+-static void addResourceField(resource_attributes_t attr, EXTRACTOR_KeywordList *keywords, Ref<CdsItem> item, Ref<StringConverter> sc)
+-{
+- String value;
+- const char *temp = NULL;
+-
+- switch (attr)
++ if (attr != R_MAX)
+ {
+- case R_RESOLUTION:
+- temp = EXTRACTOR_extractLast(EXTRACTOR_SIZE, keywords);
+- break;
+-/* case R_SIZE:
+- temp = EXTRACTOR_extractLast(EXTRACTOR_SIZE, keywords);
+- break;
+-*/
+- default:
+- return;
++ item->getResource(0)->addAttribute(MetadataHandler::getResAttrName(attr), value);
++ log_debug("Setting attribute on item: %d, %s\n", attr, value.c_str());
+ }
+
+- if (temp != NULL)
+- value = temp;
+-
+- if (string_ok(value))
++ if (aux != nil)
+ {
+- item->getResource(0)->addAttribute(MetadataHandler::getResAttrName(attr), value);
++ String tmp;
++ for (int j = 0; j < aux->size(); j++)
++ {
++ tmp = aux->get(j);
++ if (string_ok(tmp))
++ {
++ if (type == getTagFromString(tmp))
++ {
++ value = sc->convert(value);
++ item->setAuxData(tmp, value);
++ log_debug(("Adding tag: %s with value %s\n", tmp.c_str(), value.c_str()));
++ }
++ }
++ }
+ }
++
++ return 0;
+ }
+
+
+
+-Ref<RExp> ReAudioFormat;
+-EXTRACTOR_ExtractorList *extractors = NULL;
+-bool load_libraries_failed = false;
++static Ref<RExp> ReAudioFormat;
++static EXTRACTOR_PluginList *plugins = NULL;
++static bool load_libraries_failed = false;
+
+ void ExtractorHandler::fillMetadata(Ref<CdsItem> item)
+ {
+ if (load_libraries_failed)
+ return;
+- Ref<Array<StringBase> > aux;
+- Ref<StringConverter> sc = StringConverter::i2i();
+-
+- if (! extractors)
++ if (! plugins)
+ {
+- extractors = EXTRACTOR_loadDefaultLibraries();
+- if (! extractors)
++ plugins = EXTRACTOR_plugin_add_defaults(EXTRACTOR_OPTION_DEFAULT_POLICY);
++ if (! plugins)
++ {
+ load_libraries_failed = true;
++ return;
++ }
+ }
+- EXTRACTOR_KeywordList *keywords = EXTRACTOR_getKeywords(extractors, item->getLocation().c_str());
+-
+- //EXTRACTOR_printKeywords(stdout, keywords);
+
+- for (int i = 0; i < M_MAX; i++)
+- addMetaField((metadata_fields_t)i, keywords, item, sc);
+-
+- for (int i = 0; i < R_MAX; i++)
+- addResourceField((resource_attributes_t)i, keywords, item, sc);
++ log_debug("processing %s\n", item->getLocation().c_str());
+
+ Ref<ConfigManager> cm = ConfigManager::getInstance();
+- aux = cm->getStringArrayOption(CFG_IMPORT_LIBOPTS_EXTRACTOR_AUXDATA_TAGS_LIST);
+- if (aux != nil)
+- {
+- String value;
+- String tmp;
+- const char *temp = NULL;
+-
+- for (int j = 0; j < aux->size(); j++)
+- {
+-
+- tmp = aux->get(j);
+- if (string_ok(tmp))
+- {
+- temp = EXTRACTOR_extractLast(getTagFromString(tmp), keywords);
+- if (temp != NULL)
+- {
+- value = temp;
+- if (string_ok(value))
+- {
+- value = sc->convert(value);
+- item->setAuxData(tmp, value);
+-// log_debug(("Adding tag: %s with value %s\n", tmp.c_str(), value.c_str()));
+- }
+- }
+- }
+- }
+- }
++ struct field_state field_state = {
++ .item = item,
++ .sc = StringConverter::i2i(),
++ .aux = cm->getStringArrayOption(CFG_IMPORT_LIBOPTS_EXTRACTOR_AUXDATA_TAGS_LIST),
++ };
++ EXTRACTOR_extract(plugins, item->getLocation().c_str(), NULL, 0, addField, &field_state);
+
+ if (ReAudioFormat == nil)
+ {
+@@ -379,35 +401,9 @@ void ExtractorHandler::fillMetadata(Ref<CdsItem> item)
+ ReAudioFormat->compile(_("([0-9]+)\\s+kbps,\\s*([0-9]+)\\s+hz,\\s*"
+ "(([0-9]+)h)?([0-9]+)m([0-9]+)\\s(\\S+)"), "i");
+ }
+-
+- /*
+- temp = EXTRACTOR_extractLast(EXTRACTOR_FORMAT, keywords);
+- log_debug("EXTRACTOR_FORMAT: %s\n", temp);
+-
+- if (temp)
+- {
+- Ref<Matcher> matcher = ReAudioFormat->match((char *)temp);
+- if (matcher != nil)
+- {
+- log_debug(("BR:%s FR:%s H:%s M:%s S:%s TYPE:%s\n",
+- matcher->group(1).c_str(),
+- matcher->group(2).c_str(),
+- matcher->group(4).c_str(),
+- matcher->group(5).c_str(),
+- matcher->group(6).c_str(),
+- matcher->group(7).c_str()));
+- }
+- else
+- {
+- log_debug(("format pattern unmatched!"));
+- }
+- }
+-
+- */
+- EXTRACTOR_freeKeywords(keywords);
+
+ // commented out for the sake of efficiency
+- // EXTRACTOR_removeAll(extractors);
++ // EXTRACTOR_plugin_remove_all(plugins);
+ }
+
+ Ref<IOHandler> ExtractorHandler::serveContent(Ref<CdsItem> item, int resNum, off_t *data_size)
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-libmp4v2.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-libmp4v2.patch
new file mode 100644
index 000000000000..6a6b51e1e05a
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-libmp4v2.patch
@@ -0,0 +1,187 @@
+diff -urN old/src/metadata/libmp4v2_handler.cc new/src/metadata/libmp4v2_handler.cc
+--- old/src/metadata/libmp4v2_handler.cc 2012-04-05 01:46:26.000000000 +0200
++++ new/src/metadata/libmp4v2_handler.cc 2012-04-05 02:01:24.000000000 +0200
+@@ -65,29 +65,28 @@
+ static void addMetaField(metadata_fields_t field, MP4FileHandle mp4, Ref<CdsItem> item)
+ {
+ String value;
+- char* mp4_retval = NULL;
+- u_int16_t track;
+- u_int16_t total_tracks;
+-
+ Ref<StringConverter> sc = StringConverter::i2i();
+
++ const MP4Tags* new_tags = MP4TagsAlloc();
++
++ if (!MP4TagsFetch(new_tags, mp4))
++ return;
++
+ switch (field)
+ {
+ case M_TITLE:
+- MP4GetMetadataName(mp4, &mp4_retval);
++ value = new_tags->name;
+ break;
+ case M_ARTIST:
+- MP4GetMetadataArtist(mp4, &mp4_retval);
++ value = new_tags->artist;
+ break;
+ case M_ALBUM:
+- MP4GetMetadataAlbum(mp4, &mp4_retval);
++ value = new_tags->album;
+ break;
+ case M_DATE:
+- MP4GetMetadataYear(mp4, &mp4_retval);
+- if (mp4_retval)
++ value = new_tags->releaseDate;
++ if (value.length() > 0)
+ {
+- value = mp4_retval;
+- free(mp4_retval);
+ if (string_ok(value))
+ value = value + "-01-01";
+ else
+@@ -95,34 +94,31 @@
+ }
+ break;
+ case M_GENRE:
+- MP4GetMetadataGenre(mp4, &mp4_retval);
++ value = new_tags->genre;
+ break;
+ case M_DESCRIPTION:
+- MP4GetMetadataComment(mp4, &mp4_retval);
++ value = new_tags->comments;
+ break;
+ case M_TRACKNUMBER:
+- MP4GetMetadataTrack(mp4, &track, &total_tracks);
+- if (track > 0)
++ if (new_tags->track)
+ {
+- value = String::from(track);
+- item->setTrackNumber((int)track);
++ value = String::from(new_tags->track->index);
++ item->setTrackNumber((int)new_tags->track->index);
+ }
+ else
++ {
++ MP4TagsFree( new_tags );
+ return;
++ }
+ break;
+ default:
++ MP4TagsFree( new_tags );
+ return;
+ }
+
+- if ((field != M_DATE) && (field != M_TRACKNUMBER) &&
+- (mp4_retval))
+- {
+- value = mp4_retval;
+- free(mp4_retval);
+- }
+-
++ MP4TagsFree( new_tags );
+ value = trim_string(value);
+-
++
+ if (string_ok(value))
+ {
+ item->setMetadata(MT_KEYS[field].upnp, sc->convert(value));
+@@ -190,14 +186,19 @@
+ }
+
+ #if defined(HAVE_MAGIC)
+- u_int8_t *art_data;
+- u_int32_t art_data_len;
++ void *art_data = 0;
++ u_int32_t art_data_len = 0;
+ String art_mimetype;
++
++ const MP4Tags* new_tags = MP4TagsAlloc();
++ MP4TagsFetch(new_tags, mp4);
++ if (new_tags->artworkCount)
++ {
++ art_data = new_tags->artwork->data;
++ art_data_len = new_tags->artwork->size;
++ }
+ #ifdef HAVE_MP4_GET_METADATA_COVER_ART_COUNT
+- if (MP4GetMetadataCoverArtCount(mp4) &&
+- MP4GetMetadataCoverArt(mp4, &art_data, &art_data_len))
+-#else
+- MP4GetMetadataCoverArt(mp4, &art_data, &art_data_len);
++ if (new_tags->artworkCount && art_data_len > 0)
+ #endif
+ {
+ if (art_data)
+@@ -211,11 +212,10 @@
+ }
+ catch (Exception ex)
+ {
+- free(art_data);
++ MP4TagsFree(new_tags);
+ throw ex;
+ }
+
+- free(art_data);
+ if (art_mimetype != _(MIMETYPE_DEFAULT))
+ {
+ Ref<CdsResource> resource(new CdsResource(CH_MP4));
+@@ -225,6 +225,7 @@
+ }
+ }
+ }
++ MP4TagsFree(new_tags);
+ #endif
+ MP4Close(mp4);
+ }
+@@ -249,26 +250,35 @@
+
+ if (ctype != ID3_ALBUM_ART)
+ throw _Exception(_("LibMP4V2Handler: got unknown content type: ") + ctype);
++
++ const MP4Tags* new_tags = MP4TagsAlloc();
++ if (MP4TagsFetch(new_tags, mp4))
++ {
+ #ifdef HAVE_MP4_GET_METADATA_COVER_ART_COUNT
+- if (!MP4GetMetadataCoverArtCount(mp4))
+- throw _Exception(_("LibMP4V2Handler: resource has no album art information"));
++ if (!new_tags->artworkCount)
++ throw _Exception(_("LibMP4V2Handler: resource has no album art information"));
+ #endif
+- u_int8_t *art_data;
+- u_int32_t art_data_len;
+- if (MP4GetMetadataCoverArt(mp4, &art_data, &art_data_len))
+- {
+- if (art_data)
++ void *art_data = 0;
++ u_int32_t art_data_len;
++
++ const MP4TagArtwork* art = new_tags->artwork;
++ art_data = art->data;
++ art_data_len = art->size;
++ if (art)
+ {
+- *data_size = (off_t)art_data_len;
+- Ref<IOHandler> h(new MemIOHandler((void *)art_data, art_data_len));
+- free(art_data);
+- return h;
++ if (art_data)
++ {
++ *data_size = (off_t)art_data_len;
++ Ref<IOHandler> h(new MemIOHandler(art_data, art_data_len));
++ MP4TagsFree(new_tags);
++ return h;
++ }
+ }
++ MP4TagsFree(new_tags);
+ }
+-
+ throw _Exception(_("LibMP4V2Handler: could not serve album art "
+- "for file") + item->getLocation() +
+- " - embedded image not found");
++ "for file") + item->getLocation() +
++ " - embedded image not found");
+ }
+
+ #endif // HAVE_LIBMP4V2
+De binära filerna old/src/metadata/.libmp4v2_handler.cc.swp och new/src/metadata/.libmp4v2_handler.cc.swp skiljer
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-mozjs187.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-mozjs187.patch
new file mode 100644
index 000000000000..c4b080a3656b
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-mozjs187.patch
@@ -0,0 +1,260 @@
+maybe this is correct, maybe it's not. spidermonkey's documentation blows, so
+who is to say!
+
+https://bugs.gentoo.org/423991
+
+--- a/src/scripting/dvd_image_import_script.cc
++++ b/src/scripting/dvd_image_import_script.cc
+@@ -232,8 +232,6 @@ DVDImportScript::DVDImportScript(Ref<Runtime> runtime) : Script(runtime)
+
+ String scriptPath = ConfigManager::getInstance()->getOption(CFG_IMPORT_SCRIPTING_DVD_SCRIPT);
+ load(scriptPath);
+- root = JS_NewScriptObject(cx, script);
+- JS_AddNamedRoot(cx, &root, "DVDImportScript");
+ log_info("Loaded %s\n", scriptPath.c_str());
+
+ Ref<Dictionary> mappings =
+@@ -296,21 +294,4 @@ void DVDImportScript::processDVDObject(Ref<CdsObject> obj)
+ #endif
+ }
+
+-DVDImportScript::~DVDImportScript()
+-{
+-#ifdef JS_THREADSAFE
+- JS_SetContextThread(cx);
+- JS_BeginRequest(cx);
+-#endif
+-
+- if (root)
+- JS_RemoveRoot(cx, &root);
+-
+-#ifdef JS_THREADSAFE
+- JS_EndRequest(cx);
+- JS_ClearContextThread(cx);
+-#endif
+-
+-}
+-
+ #endif // HAVE_JS
+--- a/src/scripting/dvd_image_import_script.h
++++ b/src/scripting/dvd_image_import_script.h
+@@ -41,7 +41,6 @@ class DVDImportScript : public Script
+ {
+ public:
+ DVDImportScript(zmm::Ref<Runtime> runtime);
+- ~DVDImportScript();
+ /// \brief Adds a DVD object to the database
+ ///
+ /// \param title DVD title number
+--- a/src/scripting/import_script.cc
++++ b/src/scripting/import_script.cc
+@@ -53,8 +53,6 @@ ImportScript::ImportScript(Ref<Runtime> runtime) : Script(runtime)
+ try
+ {
+ load(scriptPath);
+- root = JS_NewObject(cx, NULL, script, NULL);
+- JS_AddNamedObjectRoot(cx, &root, "ImportScript");
+ }
+ catch (Exception ex)
+ {
+@@ -109,21 +107,4 @@ void ImportScript::processCdsObject(Ref<CdsObject> obj, String rootpath)
+ #endif
+ }
+
+-ImportScript::~ImportScript()
+-{
+-#ifdef JS_THREADSAFE
+- JS_SetContextThread(cx);
+- JS_BeginRequest(cx);
+-#endif
+-
+- if (root)
+- JS_RemoveObjectRoot(cx, &root);
+-
+-#ifdef JS_THREADSAFE
+- JS_EndRequest(cx);
+- JS_ClearContextThread(cx);
+-#endif
+-
+-}
+-
+ #endif // HAVE_JS
+--- a/src/scripting/import_script.h
++++ b/src/scripting/import_script.h
+@@ -41,11 +41,8 @@ class ImportScript : public Script
+ {
+ public:
+ ImportScript(zmm::Ref<Runtime> runtime);
+- ~ImportScript();
+ void processCdsObject(zmm::Ref<CdsObject> obj, zmm::String rootpath);
+ virtual script_class_t whoami() { return S_IMPORT; }
+-private:
+- JSObject *root;
+ };
+
+ #endif // __SCRIPTING_IMPORT_SCRIPT_H__
+--- a/src/scripting/playlist_parser_script.cc
++++ b/src/scripting/playlist_parser_script.cc
+@@ -93,8 +93,6 @@ PlaylistParserScript::PlaylistParserScript(Ref<Runtime> runtime) : Script(runtim
+
+ String scriptPath = ConfigManager::getInstance()->getOption(CFG_IMPORT_SCRIPTING_PLAYLIST_SCRIPT);
+ load(scriptPath);
+- root = JS_NewObject(cx, NULL, script, NULL);
+- JS_AddNamedObjectRoot(cx, &root, "PlaylistScript");
+ }
+ catch (Exception ex)
+ {
+@@ -236,21 +234,4 @@ void PlaylistParserScript::processPlaylistObject(zmm::Ref<CdsObject> obj, Ref<Ge
+
+ }
+
+-
+-PlaylistParserScript::~PlaylistParserScript()
+-{
+-#ifdef JS_THREADSAFE
+- JS_SetContextThread(cx);
+- JS_BeginRequest(cx);
+-#endif
+-
+- if (root)
+- JS_RemoveObjectRoot(cx, &root);
+-
+-#ifdef JS_THREADSAFE
+- JS_EndRequest(cx);
+- JS_ClearContextThread(cx);
+-#endif
+-
+-}
+ #endif // HAVE_JS
+--- a/src/scripting/playlist_parser_script.h
++++ b/src/scripting/playlist_parser_script.h
+@@ -42,7 +42,6 @@ class PlaylistParserScript : public Script
+ {
+ public:
+ PlaylistParserScript(zmm::Ref<Runtime> runtime);
+- ~PlaylistParserScript();
+ zmm::String readln();
+ void processPlaylistObject(zmm::Ref<CdsObject> obj, zmm::Ref<GenericTask> task);
+ virtual script_class_t whoami() { return S_PLAYLIST; }
+@@ -52,7 +51,6 @@ private:
+ int currentObjectID;
+ char *currentLine;
+ zmm::Ref<GenericTask> currentTask;
+- JSObject *root;
+ };
+
+ #endif // __SCRIPTING_PLAYLIST_PARSER_SCRIPT_H__
+--- a/src/scripting/script.cc
++++ b/src/scripting/script.cc
+@@ -427,15 +427,10 @@ static JSFunctionSpec js_global_functions[] = {
+ try
+ {
+ common_script = _load(common_scr_path);
+- common_root = JS_NewObject(cx, NULL, common_script, NULL);
+- JS_AddNamedObjectRoot(cx, &common_root, "common-script");
+ _execute(common_script);
+ }
+ catch (Exception e)
+ {
+- if (common_root)
+- JS_RemoveObjectRoot(cx, &common_root);
+-
+ log_js("Unable to load %s: %s\n", common_scr_path.c_str(),
+ e.getMessage().c_str());
+ }
+@@ -459,8 +454,6 @@ Script::~Script()
+ JS_SetContextThread(cx);
+ JS_BeginRequest(cx);
+ #endif
+- if (common_root)
+- JS_RemoveObjectRoot(cx, &common_root);
+
+ /*
+ * scripts are unrooted and will be cleaned up by GC
+@@ -532,12 +532,12 @@ void Script::defineFunctions(JSFunctionSpec *functions)
+ throw _Exception(_("Scripting: JS_DefineFunctions failed"));
+ }
+
+-JSObject *Script::_load(zmm::String scriptPath)
++JSScript *Script::_load(zmm::String scriptPath)
+ {
+ if (glob == NULL)
+ initGlobalObject();
+
+- JSObject *scr;
++ JSScript *scr;
+
+ String scriptText = read_text_file(scriptPath);
+
+@@ -568,7 +568,7 @@ void Script::load(zmm::String scriptPath)
+ }
+
+
+-void Script::_execute(JSObject *scr)
++void Script::_execute(JSScript *scr)
+ {
+ jsval ret_val;
+
+--- a/src/scripting/script.h
++++ b/src/scripting/script.h
+@@ -66,8 +66,8 @@ public:
+ JSRuntime *rt;
+ JSContext *cx;
+ JSObject *glob;
+- JSObject *script;
+- JSObject *common_script;
++ JSScript *script;
++ JSScript *common_script;
+
+ public:
+ Script(zmm::Ref<Runtime> runtime);
+@@ -112,11 +112,9 @@ protected:
+ zmm::Ref<CdsObject> processed;
+
+ private:
+- JSObject *common_root;
+-
+ void initGlobalObject();
+- JSObject *_load(zmm::String scriptPath);
+- void _execute(JSObject *scr);
++ JSScript *_load(zmm::String scriptPath);
++ void _execute(JSScript *scr);
+ zmm::Ref<StringConverter> _p2i;
+ zmm::Ref<StringConverter> _j2i;
+ zmm::Ref<StringConverter> _f2i;
+--- a/configure.ac
++++ b/configure.ac
+@@ -1036,13 +1036,13 @@
+ ],
+ [
+ unset ac_cv_lib_smjs_JS_NewObject
+- AC_CHECK_LIB(mozjs185, JS_NewObject,
++ AC_CHECK_LIB(mozjs187, JS_NewObject,
+ [
+- MOZLIB=mozjs185
+- JS_LIBS="-lmozjs185"
++ MOZLIB=mozjs187
++ JS_LIBS="-lmozjs187"
+ ],
+ [
+- unset ac_cv_lib_mozjs185_JS_NewObject
++ unset ac_cv_lib_mozjs187_JS_NewObject
+ AC_CHECK_LIB(mozjs, JS_NewObject,
+ [
+ MOZLIB=mozjs
+@@ -1064,11 +1064,11 @@
+ MOZLIB=smjs
+ ],
+ [
+- unset ac_cv_lib_mozjs185_JS_NewObject
+- AC_CHECK_LIB(mozjs185, JS_NewObject,
++ unset ac_cv_lib_mozjs187_JS_NewObject
++ AC_CHECK_LIB(mozjs187, JS_NewObject,
+ [
+- JS_LIBS="-L$SEARCH_DIR_LIBS -lmozjs185"
+- MOZLIB=mozjs185
++ JS_LIBS="-L$SEARCH_DIR_LIBS -lmozjs187"
++ MOZLIB=mozjs187
+ ],
+ [
+ LDFLAGS="-L$SEARCH_DIR_LIBS $LDFLAGS_SAVE -lmozjs"
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-system-ar.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-system-ar.patch
new file mode 100644
index 000000000000..349bf7d8da74
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-system-ar.patch
@@ -0,0 +1,35 @@
+--- configure.ac 2010-04-08 00:38:51.000000000 +0200
++++ configure.ac 2013-05-30 12:27:55.620514386 +0200
+@@ -318,6 +318,10 @@
+ AC_PROG_CC
+ AC_PROG_RANLIB
+ AC_PROG_GCC_TRADITIONAL
++AN_MAKEVAR([AR], [AC_PROG_AR])
++AN_PROGRAM([ar], [AC_PROG_AR])
++AC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)])
++AC_PROG_AR
+ AC_HEADER_DIRENT
+ AC_HEADER_STDC
+ AC_HEADER_SYS_WAIT
+--- build/Makefile.in 2010-04-08 00:40:15.000000000 +0200
++++ build/Makefile.in 2013-05-30 12:25:55.310337928 +0200
+@@ -50,7 +50,7 @@
+ CONFIG_CLEAN_FILES =
+ CONFIG_CLEAN_VPATH_FILES =
+ LIBRARIES = $(noinst_LIBRARIES)
+-AR = ar
++AR = @AR@
+ ARFLAGS = cru
+ libmediatomb_a_AR = $(AR) $(ARFLAGS)
+ libmediatomb_a_LIBADD =
+--- tombupnp/build/Makefile.in 2010-04-08 00:40:16.000000000 +0200
++++ tombupnp/build/Makefile.in 2013-05-30 12:26:18.420371823 +0200
+@@ -48,7 +48,7 @@
+ CONFIG_CLEAN_FILES =
+ CONFIG_CLEAN_VPATH_FILES =
+ LIBRARIES = $(noinst_LIBRARIES)
+-AR = ar
++AR = @AR@
+ ARFLAGS = cru
+ libtombupnp_a_AR = $(AR) $(ARFLAGS)
+ libtombupnp_a_LIBADD =
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-system-uuid.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-system-uuid.patch
new file mode 100644
index 000000000000..053f18cea879
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-system-uuid.patch
@@ -0,0 +1,36 @@
+use libuuid from the system rather than local bundled code
+
+http://bugs.gentoo.org/270830
+
+--- a/build/Makefile.am
++++ b/build/Makefile.am
+@@ -58,6 +58,7 @@ mediatomb_CXXFLAGS = -I$(top_srcdir)/src \
+ mediatomb_LDADD = \
+ libmediatomb.a \
+ $(top_srcdir)/tombupnp/build/libtombupnp.a \
++ -luuid \
+ $(LIBEXIF_LDFLAGS) \
+ $(ZLIB_LDFLAGS) \
+ $(EXPAT_LDFLAGS) \
+--- a/build/libmediatomb_src
++++ b/build/libmediatomb_src
+@@ -231,19 +231,6 @@ libmediatomb_a_SOURCES = \
+ ../src/url.h \
+ ../src/url_request_handler.cc \
+ ../src/url_request_handler.h \
+-../src/uuid/clear.c \
+-../src/uuid/compare.c \
+-../src/uuid/copy.c \
+-../src/uuid/gen_uuid.c \
+-../src/uuid/isnull.c \
+-../src/uuid/pack.c \
+-../src/uuid/parse.c \
+-../src/uuid/unpack.c \
+-../src/uuid/unparse.c \
+-../src/uuid/uuid.h \
+-../src/uuid/uuidP.h \
+-../src/uuid/uuid_time.c \
+-../src/uuid/uuid_types.h \
+ ../src/web/action.cc \
+ ../src/web/add.cc \
+ ../src/web/add_object.cc \
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-thumb-cache.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-thumb-cache.patch
new file mode 100644
index 000000000000..3d357b4392aa
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-thumb-cache.patch
@@ -0,0 +1,237 @@
+http://sourceforge.net/tracker/?func=detail&aid=3291468&group_id=129766&atid=715782
+
+[PATCH] Add the cache feature of ffmpegthumbnailer.
+
+I want the cache feature of ffmpegthumbnailer because my machine
+is not powerful :-(
+So I created this patch for the cache feature.
+
+This patch adds a new option "cache-dir" in config.xml.
+If not specifying any string, the cache feature is disable.
+And specifying some directory, the cache feature is enable
+and the cache files will be created under the directory.
+
+Signed-off-by: Ken'ichi Ohmichi <ken1ohmichi@gmail.com>
+---
+diff --git a/src/common.h b/src/common.h
+index d1998b3..358f4d1 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -367,6 +367,8 @@
+ #define DEFAULT_FFMPEGTHUMBNAILER_FILMSTRIP_OVERLAY YES
+ #define DEFAULT_FFMPEGTHUMBNAILER_WORKAROUND_BUGS NO
+ #define DEFAULT_FFMPEGTHUMBNAILER_IMAGE_QUALITY 8
++ #define DEFAULT_FFMPEGTHUMBNAILER_CACHE_DIR_ENABLED YES
++ #define DEFAULT_FFMPEGTHUMBNAILER_CACHE_DIR ""
+ #endif
+
+ #if defined(HAVE_LASTFMLIB)
+diff --git a/src/config_manager.cc b/src/config_manager.cc
+index 8c975f8..2902090 100644
+--- a/src/config_manager.cc
++++ b/src/config_manager.cc
+@@ -1873,6 +1873,24 @@ void ConfigManager::validate(String serverhome)
+
+ NEW_INT_OPTION(temp_int);
+ SET_INT_OPTION(CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_IMAGE_QUALITY);
++
++ temp = getOption("/server/extended-runtime-options/ffmpegthumbnailer/"
++ "cache-dir", DEFAULT_FFMPEGTHUMBNAILER_CACHE_DIR);
++
++ NEW_OPTION(temp);
++ SET_OPTION(CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_CACHE_DIR);
++
++ temp = getOption("/server/extended-runtime-options/ffmpegthumbnailer/"
++ "cache-dir/attribute::enabled",
++ DEFAULT_FFMPEGTHUMBNAILER_CACHE_DIR_ENABLED);
++
++ if (!validateYesNo(temp))
++ throw _Exception(_("Error in config file: "
++ "invalid \"enabled\" attribute value in "
++ "ffmpegthumbnailer <cache-dir> tag"));
++
++ NEW_BOOL_OPTION(temp == YES ? true : false);
++ SET_BOOL_OPTION(CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_CACHE_DIR_ENABLED);
+ }
+ #endif
+
+diff --git a/src/config_manager.h b/src/config_manager.h
+index 52b9842..a447a60 100644
+--- a/src/config_manager.h
++++ b/src/config_manager.h
+@@ -110,6 +110,8 @@ typedef enum
+ CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_FILMSTRIP_OVERLAY,
+ CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_WORKAROUND_BUGS,
+ CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_IMAGE_QUALITY,
++ CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_CACHE_DIR_ENABLED,
++ CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_CACHE_DIR,
+ #endif
+ CFG_SERVER_EXTOPTS_MARK_PLAYED_ITEMS_ENABLED,
+ CFG_SERVER_EXTOPTS_MARK_PLAYED_ITEMS_STRING_MODE_PREPEND,
+diff --git a/src/metadata/ffmpeg_handler.cc b/src/metadata/ffmpeg_handler.cc
+index a637d9c..8e7ef23 100644
+--- a/src/metadata/ffmpeg_handler.cc
++++ b/src/metadata/ffmpeg_handler.cc
+@@ -50,6 +50,9 @@
+ // INT64_C is not defined in ffmpeg/avformat.h but is needed
+ // macro defines included via autoconfig.h
+ #include <stdint.h>
++#include <sys/stat.h>
++#include <errno.h>
++#include <string.h>
+
+ //#ifdef FFMPEG_NEEDS_EXTERN_C
+ extern "C"
+@@ -279,6 +282,122 @@ void FfmpegHandler::fillMetadata(Ref<CdsItem> item)
+ av_close_input_file(pFormatCtx);
+ }
+
++#ifdef HAVE_FFMPEGTHUMBNAILER
++
++static int _mkdir(const char *path)
++{
++ int ret = mkdir(path, 0777);
++
++ if (ret == 0) {
++ // Make sure we are +x in case of restrictive umask that strips +x.
++ struct stat st;
++ if (stat(path, &st)) {
++ log_warning("could not stat(%s): %s\n", path, strerror(errno));
++ return -1;
++ }
++ mode_t xbits = S_IXUSR | S_IXGRP | S_IXOTH;
++ if (!(st.st_mode & xbits)) {
++ if (chmod(path, st.st_mode | xbits)) {
++ log_warning("could not chmod(%s, +x): %s\n", path, strerror(errno));
++ return -1;
++ }
++ }
++ }
++
++ return ret;
++}
++
++static bool makeThumbnailCacheDir(String& path)
++{
++ char *path_temp = strdup(path.c_str());
++ char *last_slash = strrchr(path_temp, '/');
++ char *slash = last_slash;
++ bool ret = false;
++
++ if (!last_slash)
++ return ret;
++
++ // Assume most dirs exist, so scan backwards first.
++ // Avoid stat/access checks due to TOCTOU races.
++ errno = 0;
++ for (slash = last_slash; slash > path_temp; --slash) {
++ if (*slash != '/')
++ continue;
++ *slash = '\0';
++ if (_mkdir(path_temp) == 0) {
++ // Now we can forward scan.
++ while (slash < last_slash) {
++ *slash = DIR_SEPARATOR;
++ if (_mkdir(path_temp) < 0)
++ // Allow EEXIST in case of someone else doing `mkdir`.
++ if (errno != EEXIST)
++ goto done;
++ slash += strlen(slash);
++ }
++ if (slash == last_slash)
++ ret = true;
++ break;
++ } else if (errno == EEXIST) {
++ ret = true;
++ break;
++ } else if (errno != ENOENT) {
++ break;
++ }
++ }
++
++ done:
++ free(path_temp);
++ return ret;
++}
++
++static String getThumbnailCacheFilePath(String& movie_filename, bool create)
++{
++ Ref<ConfigManager> cfg = ConfigManager::getInstance();
++ String cache_dir = cfg->getOption(CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_CACHE_DIR);
++
++ if (cache_dir.length() == 0) {
++ String home_dir = cfg->getOption(CFG_SERVER_HOME);
++ cache_dir = home_dir + "/cache-dir";
++ }
++
++ cache_dir = cache_dir + movie_filename + "-thumb.jpg";
++ if (create && !makeThumbnailCacheDir(cache_dir))
++ cache_dir = "";
++ return cache_dir;
++}
++
++static bool readThumbnailCacheFile(String movie_filename, uint8_t **ptr_img, size_t *size_img)
++{
++ String path = getThumbnailCacheFilePath(movie_filename, false);
++ FILE *fp = fopen(path.c_str(), "rb");
++ if (!fp)
++ return false;
++
++ size_t bytesRead;
++ uint8_t buffer[1024];
++ *ptr_img = NULL;
++ *size_img = 0;
++ while ((bytesRead = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
++ *ptr_img = (uint8_t *)realloc(*ptr_img, *size_img + bytesRead);
++ memcpy(*ptr_img + *size_img, buffer, bytesRead);
++ *size_img += bytesRead;
++ }
++ fclose(fp);
++ return true;
++}
++
++static void writeThumbnailCacheFile(String movie_filename, uint8_t *ptr_img, int size_img)
++{
++ String path = getThumbnailCacheFilePath(movie_filename, true);
++ FILE *fp = fopen(path.c_str(), "wb");
++ if (!fp)
++ return;
++ fwrite(ptr_img, sizeof(uint8_t), size_img, fp);
++ fclose(fp);
++}
++
++#endif
++
+ Ref<IOHandler> FfmpegHandler::serveContent(Ref<CdsItem> item, int resNum, off_t *data_size)
+ {
+ *data_size = -1;
+@@ -288,6 +407,18 @@ Ref<IOHandler> FfmpegHandler::serveContent(Ref<CdsItem> item, int resNum, off_t
+ if (!cfg->getBoolOption(CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_ENABLED))
+ return nil;
+
++ if (cfg->getBoolOption(CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_CACHE_DIR_ENABLED)) {
++ uint8_t *ptr_image;
++ size_t size_image;
++ if (readThumbnailCacheFile(item->getLocation(),
++ &ptr_image, &size_image)) {
++ *data_size = (off_t)size_image;
++ Ref<IOHandler> h(new MemIOHandler(ptr_image, size_image));
++ free(ptr_image);
++ log_debug("Returning cached thumbnail for file: %s\n", item->getLocation().c_str());
++ return h;
++ }
++ }
+ #ifdef FFMPEGTHUMBNAILER_OLD_API
+ video_thumbnailer *th = create_thumbnailer();
+ image_data *img = create_image_data();
+@@ -318,6 +449,10 @@ Ref<IOHandler> FfmpegHandler::serveContent(Ref<CdsItem> item, int resNum, off_t
+ #endif // old api
+ throw _Exception(_("Could not generate thumbnail for ") +
+ item->getLocation());
++ if (cfg->getBoolOption(CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_CACHE_DIR_ENABLED)) {
++ writeThumbnailCacheFile(item->getLocation(),
++ img->image_data_ptr, img->image_data_size);
++ }
+
+ *data_size = (off_t)img->image_data_size;
+ Ref<IOHandler> h(new MemIOHandler((void *)img->image_data_ptr,
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-thumbnail-locking.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-thumbnail-locking.patch
new file mode 100644
index 000000000000..70658c495d25
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-thumbnail-locking.patch
@@ -0,0 +1,71 @@
+if you try to generate a bunch of thumbnails at once, it can crash:
+
+Program received signal SIGABRT, Aborted.
+[Switching to Thread 0x7fdb7a6cb700 (LWP 17295)]
+0x00007fdb8031c899 in __GI_raise (sig=sig@entry=0x6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
+56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
+(gdb) bt
+#0 0x00007fdb8031c899 in __GI_raise (sig=sig@entry=0x6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
+#1 0x00007fdb8031de27 in __GI_abort () at abort.c:89
+#2 0x00007fdb7f6b9222 in ff_unlock_avcodec () at /var/tmp/portage/media-video/ffmpeg-1.2.6/work/ffmpeg-1.2.6/libavcodec/utils.c:2767
+#3 0x00007fdb7f6b9662 in avcodec_open2 (avctx=0x7fdb64032080, codec=<optimized out>, options=0x0) at /var/tmp/portage/media-video/ffmpeg-1.2.6/work/ffmpeg-1.2.6/libavcodec/utils.c:1132
+#4 0x00007fdb81be57bb in ffmpegthumbnailer::MovieDecoder::initializeVideo (this=this@entry=0x7fdb7a6ca000) at libffmpegthumbnailer/moviedecoder.cpp:176
+#5 0x00007fdb81be599c in ffmpegthumbnailer::MovieDecoder::initialize (this=0x7fdb7a6ca000, filename=...) at libffmpegthumbnailer/moviedecoder.cpp:86
+#6 0x00007fdb81be92cc in ffmpegthumbnailer::VideoThumbnailer::generateThumbnail (this=this@entry=0x7fdb6402af90, videoFile=..., imageWriter=..., pAvContext=pAvContext@entry=0x0) at libffmpegthumbnailer/videothumbnailer.cpp:118
+#7 0x00007fdb81be97b4 in ffmpegthumbnailer::VideoThumbnailer::generateThumbnail (this=this@entry=0x7fdb6402af90, videoFile=..., type=<optimized out>, type@entry=Jpeg, buffer=..., pAvContext=pAvContext@entry=0x0) at libffmpegthumbnailer/videothumbnailer.cpp:191
+#8 0x00007fdb81bea23e in video_thumbnailer_generate_thumbnail_to_buffer (thumbnailer=<optimized out>, movie_filename=0x7fdb7003abc0 "........mp4", generated_image_data=0x7fdb64022680) at libffmpegthumbnailer/videothumbnailerc.cpp:113
+#9 0x00000000004ebfed in FfmpegHandler::serveContent (this=this@entry=0x7fdb64020ff0, item=..., resNum=resNum@entry=0x1, data_size=data_size@entry=0x7fdb7a6caaf0) at ../src/metadata/ffmpeg_handler.cc:475
+#10 0x00000000004e48d7 in FileRequestHandler::open (this=<optimized out>, filename=<optimized out>, info=0x7fdb7a6caaf0, mode=<optimized out>) at ../src/file_request_handler.cc:575
+#11 0x00000000004bba74 in web_open (filename=0x7fdb640175f0 "/content/media/object_id/16634/res_id/1/rh/6/ext/file.jpg", info=0x7fdb7a6caaf0, mode=UPNP_READ) at ../src/web_callbacks.cc:198
+#12 0x000000000052674b in process_request (Fp=<synthetic pointer>, RespInstr=0x7fdb7a6cab70, alias=0x7fdb7a6cab20, filename=0x7fdb7a6caad0, headers=0x7fdb7a6caab0, rtype=<synthetic pointer>, req=0x7fdb7a6cacd0) at ../upnp/src/genlib/net/http/webserver.c:1343
+#13 web_server_callback (parser=0x7fdb7a6cacd0, req=0x7fdb7a6cacd0, info=0x7fdb7a6cacc0) at ../upnp/src/genlib/net/http/webserver.c:1803
+#14 0x000000000051f29a in dispatch_request (hparser=0x7fdb7a6cacd0, info=0x7fdb7a6cacc0) at ../upnp/src/genlib/miniserver/miniserver.c:236
+#15 handle_request (args=0x7fdb6c000c40) at ../upnp/src/genlib/miniserver/miniserver.c:339
+#16 0x000000000052cc66 in WorkerThread (arg=0x7a80e0 <gRecvThreadPool>) at ../threadutil/src/ThreadPool.c:594
+#17 0x00007fdb80697333 in start_thread (arg=0x7fdb7a6cb700) at pthread_create.c:309
+#18 0x00007fdb803d226d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
+(gdb)
+
+--- a/src/metadata/ffmpeg_handler.cc
++++ b/src/metadata/ffmpeg_handler.cc
+@@ -311,6 +311,10 @@ void FfmpegHandler::fillMetadata(Ref<CdsItem> item)
+
+ #ifdef HAVE_FFMPEGTHUMBNAILER
+
++// The ffmpegthumbnailer code (ffmpeg?) is not threading safe.
++// Add a lock around the usage to avoid crashing randomly.
++static pthread_mutex_t thumb_lock;
++
+ static int _mkdir(const char *path)
+ {
+ int ret = mkdir(path, 0777);
+@@ -446,6 +450,9 @@ Ref<IOHandler> FfmpegHandler::serveContent(Ref<CdsItem> item, int resNum, off_t
+ return h;
+ }
+ }
++
++ pthread_mutex_lock(&thumb_lock);
++
+ #ifdef FFMPEGTHUMBNAILER_OLD_API
+ video_thumbnailer *th = create_thumbnailer();
+ image_data *img = create_image_data();
+@@ -474,8 +481,11 @@ Ref<IOHandler> FfmpegHandler::serveContent(Ref<CdsItem> item, int resNum, off_t
+ if (video_thumbnailer_generate_thumbnail_to_buffer(th,
+ item->getLocation().c_str(), img) != 0)
+ #endif // old api
++ {
++ pthread_mutex_unlock(&thumb_lock);
+ throw _Exception(_("Could not generate thumbnail for ") +
+ item->getLocation());
++ }
+ if (cfg->getBoolOption(CFG_SERVER_EXTOPTS_FFMPEGTHUMBNAILER_CACHE_DIR_ENABLED)) {
+ writeThumbnailCacheFile(item->getLocation(),
+ img->image_data_ptr, img->image_data_size);
+@@ -491,6 +501,7 @@ Ref<IOHandler> FfmpegHandler::serveContent(Ref<CdsItem> item, int resNum, off_t
+ video_thumbnailer_destroy_image_data(img);
+ video_thumbnailer_destroy(th);
+ #endif// old api
++ pthread_mutex_unlock(&thumb_lock);
+ return h;
+ #else
+ return nil;
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1-youtube-dl.patch b/net-misc/mediatomb/files/mediatomb-0.12.1-youtube-dl.patch
new file mode 100644
index 000000000000..6001d2fc5661
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1-youtube-dl.patch
@@ -0,0 +1,141 @@
+--- mediatomb-0.12.1.orig/src/youtube_video_url.cc 2013-12-17 22:46:24.272442249 +0000
++++ mediatomb-0.12.1/src/youtube_video_url.cc 2013-12-17 22:57:25.968039083 +0000
+@@ -117,89 +117,68 @@ String YouTubeVideoURL::getVideoURL(Stri
+
+ watch = _(YOUTUBE_URL_WATCH) + video_id;
+
+- Ref<URL> url(new URL(YOUTUBE_PAGESIZE));
++ /*
++ * NOTE ON PATCH:
++ *
++ * The original code does not seem to work anymore.
++ *
++ * I have commented-out all the original code, and instead
++ * replaced it with a call/exec to youtube-dl (this is a separate/stand-alone python script).
++ *
++ * Available at http://rg3.github.io/youtube-dl/
++ *
++ *
++ * The current code works on a/my samsung TV. I have not tested it further on other devices.
++ * (I needed a quick fix, because I wanted to watch some video's. :) )
++ *
++ * I thought I would share the results.
++ *
++ * Suggestions / feedback -> bas-patch@tcfaa.nl
++ *
++ * Regards, Bas Nedermeijer
++ */
++
++ int pipefd[2];
++ pipe(pipefd);
++
++ if (fork() == 0)
++ {
++ // close reading end in the child
++ close(pipefd[0]);
++
++ // send stdout to the pipe
++ dup2(pipefd[1], 1);
++ // send stderr to the pipe
++ dup2(pipefd[1], 2);
+
+- Ref<StringBuffer> buffer = url->download(watch, &retcode, curl_handle,
+- false, verbose, true);
+- if (retcode != 200)
+- {
+- throw _Exception(_("Failed to get URL for video with id ")
+- + watch + _("HTTP response code: ") +
+- String::from(retcode));
+- }
++ // this descriptor is no longer needed
++ close(pipefd[1]);
+
+- log_debug("------> GOT BUFFER %s\n", buffer->toString().c_str());
+-
+- Ref<Matcher> matcher = reVideoURLParams->matcher(buffer->toString());
+- String params;
+- if (matcher->next())
+- {
+-// params = trim_string(matcher->group(1));
+- params = trim_string( matcher->group( 0 ) );
+- /*
+- int brace = params.index( '{' );
+- if ( brace > 0 )
+- params = params.substring( brace );
+- brace = params.index( '}' );
+- if ( brace > 0 )
+- params = params.substring( 0, brace + 1 );
+- */
+- Ref<Matcher> m2 = param_t->matcher(params);
+- if (m2->next())
+- {
+- String hmm = m2->group(1);
+- if (string_ok(hmm))
+- params = hmm;
+- else
+- {
+- throw _Exception(_("Could not retrieve \"t\" parameter."));
+- }
+- }
++ // This code assumes youtube-dl is available for usage.
++ execl("/usr/bin/youtube-dl", "/usr/bin/youtube-dl","-g",watch.c_str(),NULL);
+ }
+ else
+ {
+- throw _Exception(_("Failed to get URL for video with id (step 1)") + video_id);
+- }
++ // parent
++ char buffery[8192];
++ memset(&buffery[0], 0, sizeof(buffery));
+
+- params = _(YOUTUBE_URL_GET) + YOUTUBE_URL_PARAM_VIDEO_ID + '=' +
+- video_id + '&' + YOUTUBE_URL_PARAM_T + '=' + params;
++ close(pipefd[1]); // close the write end of the pipe in the parent
+
+- if (mp4)
+- {
+- String format = _("&fmt=18");
+-
+- if (hd)
++ // Hopefully the read is never called twice, otherwise the buffer will become corrupt.
++ while (read(pipefd[0], buffery, sizeof(buffery)) != 0)
+ {
+- matcher = HD->matcher(buffer->toString());
+- if (matcher->next())
+- {
+- if (trim_string(matcher->group(1)) == "true")
+- format = _("&fmt=22");
+- }
+ }
+-
+- params = params + format;
+- }
+
+- buffer = url->download(params, &retcode, curl_handle, true, verbose, true);
++ log_debug("------> GOT BUFFER %s\n", buffery);
++ String result = _(buffery);
+
+- matcher = redirectLocation->matcher(buffer->toString());
+- if (matcher->next())
+- {
+- if (string_ok(trim_string(matcher->group(1))))
+- return trim_string(matcher->group(1));
+- else
+- throw _Exception(_("Failed to get URL for video with id (step 2)")+
+- video_id);
+- }
++ result = trim_string(result);
+
+- if (retcode != 303)
+- {
+- throw _Exception(_("Unexpected reply from YouTube: ") +
+- String::from(retcode));
+- }
++ log_debug("------> GOT BUFFER (after trimming) %s\n", result.c_str());
+
+- throw _Exception(_("Could not retrieve YouTube video URL"));
++ return result;
++ }
+ }
+
+ #endif//YOUTUBE
diff --git a/net-misc/mediatomb/files/mediatomb-0.12.1.initd b/net-misc/mediatomb/files/mediatomb-0.12.1.initd
new file mode 100644
index 000000000000..49ea8fa2c559
--- /dev/null
+++ b/net-misc/mediatomb/files/mediatomb-0.12.1.initd
@@ -0,0 +1,29 @@
+#!/sbin/runscript
+# Copyright 1999-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+depend() {
+ need net
+ # In order to properly support this (need vs use), we would have to
+ # parse ${MEDIATOMB_CONFIG} and see if mysql is enabled and if it is
+ # pointing to the local system. #368409
+ use mysql
+}
+
+start() {
+ ebegin "Starting MediaTomb"
+ start-stop-daemon --start --quiet --exec /usr/bin/mediatomb \
+ --pidfile ${MEDIATOMB_PIDFILE} -- --daemon \
+ --pidfile ${MEDIATOMB_PIDFILE} --user ${MEDIATOMB_USER} \
+ --group ${MEDIATOMB_GROUP} --logfile ${MEDIATOMB_LOGFILE} \
+ --config ${MEDIATOMB_CONFIG} --port ${MEDIATOMB_PORT} \
+ ${MEDIATOMB_OPTIONS}
+ eend $?
+}
+
+stop () {
+ ebegin "Stopping MediaTomb"
+ start-stop-daemon --stop --retry 10 --quiet --pidfile ${MEDIATOMB_PIDFILE}
+ eend $?
+}