[mediatomb/f16] Fix youtube support (RHBZ#747023) Enable FLAC cover art via libFLAC
rmattes
rmattes at fedoraproject.org
Wed Nov 2 23:14:37 UTC 2011
commit 8f6b34a1877049ff7c0f620e41fe0133155f4960
Author: Rich Mattes <richmattes at gmail.com>
Date: Tue Oct 18 20:56:43 2011 -0400
Fix youtube support (RHBZ#747023)
Enable FLAC cover art via libFLAC
mediatomb-0.12.1.fixyoutube.patch | 272 +++++++++++++++++
mediatomb-0.12.1.flacart.config.patch | 55 ++++
mediatomb-0.12.1.flacart.patch | 386 +++++++++++++++++++++++++
mediatomb-0.12.1.ps3_timeseekrange.patch | 464 ++++++++++++++++++++++++++++++
mediatomb.spec | 28 ++-
5 files changed, 1199 insertions(+), 6 deletions(-)
---
diff --git a/mediatomb-0.12.1.fixyoutube.patch b/mediatomb-0.12.1.fixyoutube.patch
new file mode 100644
index 0000000..21d80ef
--- /dev/null
+++ b/mediatomb-0.12.1.fixyoutube.patch
@@ -0,0 +1,272 @@
+diff -rup ../BUILD/mediatomb-0.12.1/src/cds_resource_manager.cc mediatomb-0.12.1/src/cds_resource_manager.cc
+--- ../BUILD/mediatomb-0.12.1/src/cds_resource_manager.cc 2011-08-09 00:34:40.741499912 +0900
++++ mediatomb-0.12.1/src/cds_resource_manager.cc 2011-08-06 17:01:48.000000000 +0900
+@@ -261,10 +261,13 @@ void CdsResourceManager::addResources(Re
+ String::from(chan);
+ }
+ }
+-
++//targetMimeType = targetMimeType + ";" + D_OP + "=01;" + D_CONVERSION_INDICATOR + "=" D_NO_CONVERSION;
++targetMimeType = targetMimeType + ";" + D_OP + "=10;" + D_CONVERSION_INDICATOR + "=" D_CONVERSION;// + ";DLNA.ORG_FLAGS=81100000000000000000000000000000";
+ t_res->addAttribute(MetadataHandler::getResAttrName(R_PROTOCOLINFO),
+ renderProtocolInfo(targetMimeType));
+
++ log_debug("// addResources targetMimeType::%s\n",targetMimeType.c_str() );
++
+ if (tp->isThumbnail())
+ t_res->addOption(_(RESOURCE_CONTENT_TYPE), _(EXIF_THUMBNAIL));
+
+@@ -289,6 +292,7 @@ void CdsResourceManager::addResources(Re
+ #endif // EXTERNAL_TRANSCODING
+
+ int resCount = item->getResourceCount();
++ log_debug("// addResources resCount::%d\n",resCount );
+ for (int i = 0; i < resCount; i++)
+ {
+ /// \todo what if the resource has a different mimetype than the item??
+mediatomb-0.12.1/srcだけに発見: cds_resource_manager.cc.orig
+../BUILD/mediatomb-0.12.1/srcだけに発見: tools.cc.orig
+mediatomb-0.12.1/srcだけに発見: youtube_video_url.BAK
+diff -rup ../BUILD/mediatomb-0.12.1/src/youtube_video_url.cc mediatomb-0.12.1/src/youtube_video_url.cc
+--- ../BUILD/mediatomb-0.12.1/src/youtube_video_url.cc 2010-04-04 05:23:31.000000000 +0900
++++ mediatomb-0.12.1/src/youtube_video_url.cc 2011-08-09 00:24:31.708378898 +0900
+@@ -48,9 +48,13 @@ using namespace zmm;
+ #define YOUTUBE_URL_LOCATION_REGEXP "\nLocation: (http://[^\n]+)\n"
+ #define YOUTUBE_URL_WATCH "http://www.youtube.com/watch?v="
+-#define YOUTUBE_URL_GET "http://www.youtube.com/get_video?"
+ #define YOUTUBE_URL_PARAM_VIDEO_ID "video_id"
+-#define YOUTUBE_URL_PARAM_T_REGEXP ".*\"t\": \"([^\"]+)\""
+-#define YOUTUBE_URL_PARAM_T "t"
++
++#define YOUTUBE_URL_EMBED_TAG "<embed type=\"application/x-shockwave-flash\" +([^>]*)>"
++#define YOUTUBE_URL_PARAM_FMT_MAP ";url_encoded_fmt_stream_map=([^&].*video/x-flv&itag=5)"
++#define YOUTUBE_URL_PARAM_FMT_SEPARATE "([^&].*)&fallback_host.*itag=([0-9]+)"
++
++// url_encoded_fmt_stream_map
++#define YOUTUBE_URL_PARAM_FMT "fmt_url_map"
+ #define YOUTUBE_IS_HD_AVAILABLE_REGEXP "IS_HD_AVAILABLE[^:]*: *([^,]*)"
+ YouTubeVideoURL::YouTubeVideoURL()
+ {
+@@ -58,13 +62,13 @@ YouTubeVideoURL::YouTubeVideoURL()
+ if (!curl_handle)
+ throw _Exception(_("failed to initialize curl!\n"));
+
+- reVideoURLParams = Ref<RExp>(new RExp());
+- reVideoURLParams->compile(_(YOUTUBE_URL_PARAMS_REGEXP));
+- redirectLocation = Ref<RExp>(new RExp());
+- redirectLocation->compile(_(YOUTUBE_URL_LOCATION_REGEXP));
+- param_t = Ref<RExp>(new RExp());
+- param_t->compile(_(YOUTUBE_URL_PARAM_T_REGEXP));
+-
++ EMBED = Ref<RExp>(new RExp());
++ EMBED->compile(_(YOUTUBE_URL_EMBED_TAG));
++ FMT = Ref<RExp>(new RExp());
++ FMT->compile(_(YOUTUBE_URL_PARAM_FMT_MAP));
++ FMTURL = Ref<RExp>(new RExp());
++ FMTURL->compile(_(YOUTUBE_URL_PARAM_FMT_SEPARATE));
++
+ HD = Ref<RExp>(new RExp());
+ HD->compile(_(YOUTUBE_IS_HD_AVAILABLE_REGEXP));
+
+@@ -82,8 +86,11 @@ YouTubeVideoURL::~YouTubeVideoURL()
+
+ String YouTubeVideoURL::getVideoURL(String video_id, bool mp4, bool hd)
+ {
++ Ref<StringBuffer> buffer;
++ Ref<Matcher> matcher;
++
+ long retcode;
+- String flv_location;
++ String urls;
+ String watch;
+ #ifdef TOMBDEBUG
+ bool verbose = true;
+@@ -91,27 +98,6 @@ String YouTubeVideoURL::getVideoURL(Stri
+ bool verbose = false;
+ #endif
+
+- /*
+-// ###########################################################
+-
+- String swfargs = read_text_file("/home/jin/Work/UPnP/MediaTomb/YouTube/swf_args_new2.txt");
+-
+- Ref<Matcher> m2 = param_t->matcher(swfargs);
+-
+- if (m2->next())
+- {
+- String hmm = m2->group(1);
+- if (string_ok(hmm))
+- log_debug("############### t: %s\n", hmm.c_str());
+- else
+- log_debug("no match?\n");
+- }
+- throw _Exception(_("OVER"));
+-*/
+-
+-// ###########################################################
+-
+-
+ if (!string_ok(video_id))
+ throw _Exception(_("No video ID specified!"));
+
+@@ -119,87 +105,71 @@ String YouTubeVideoURL::getVideoURL(Stri
+
+ Ref<URL> url(new URL(YOUTUBE_PAGESIZE));
+
+- Ref<StringBuffer> buffer = url->download(watch, &retcode, curl_handle,
+- false, verbose, true);
++ buffer = url->download(watch, &retcode, curl_handle, false, verbose, false);
+ if (retcode != 200)
+- {
+- throw _Exception(_("Failed to get URL for video with id ")
+- + watch + _("HTTP response code: ") +
+- String::from(retcode));
+- }
++ throw _Exception(_("Failed to get URL for video with id ") + watch + _("HTTP response code: ") + String::from(retcode));
+
+- log_debug("------> GOT BUFFER %s\n", buffer->toString().c_str());
++ //log_debug("------> REQUEST URL1: %s\n", watch.c_str());
++ //log_debug("------> GOT BUFFER1: %s\n", buffer->toString().c_str());
+
+- Ref<Matcher> matcher = reVideoURLParams->matcher(buffer->toString());
+- String params;
++ matcher = EMBED->matcher(buffer->toString());
+ 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."));
+- }
+- }
+- }
+- else
+- {
+- throw _Exception(_("Failed to get URL for video with id (step 1)") + video_id);
+- }
++ urls = url_unescape(trim_string(matcher->group(1)).c_str());
++ urls = url_unescape(urls);
++ //log_debug("------> GOT BUFFER EMBED: %s\n", urls.c_str());
+
+- params = _(YOUTUBE_URL_GET) + YOUTUBE_URL_PARAM_VIDEO_ID + '=' +
+- video_id + '&' + YOUTUBE_URL_PARAM_T + '=' + params;
+-
+- if (mp4)
+- {
+- String format = _("&fmt=18");
++ buffer->clear();
++ *buffer << urls;
+
+- if (hd)
++ matcher = FMT->matcher(buffer->toString());
++ if (matcher->next())
+ {
+- matcher = HD->matcher(buffer->toString());
+- if (matcher->next())
+- {
+- if (trim_string(matcher->group(1)) == "true")
+- format = _("&fmt=22");
+- }
++ urls = trim_string(matcher->group(1)).c_str();
++ //log_debug("------> GOT BUFFER FMT: %s\n", urls.c_str());
++ return whichURL(urls, mp4, hd);
+ }
+-
+- params = params + format;
+- }
+-
+- buffer = url->download(params, &retcode, curl_handle, true, verbose, true);
+-
+- 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);
+ }
++ throw _Exception(_("Could not retrieve YouTube video URL"));
++}
+
+- if (retcode != 303)
++String YouTubeVideoURL::whichURL(String tmpStr, bool mp4, bool hd)
++{
++ while( tmpStr.find("url=") >= 0 )
+ {
+- throw _Exception(_("Unexpected reply from YouTube: ") +
+- String::from(retcode)+" for url "+params);
++ Ref<Matcher> matcher;
++ String fmturl;
++ int length;
++
++ tmpStr = tmpStr.substring(tmpStr.find("url=") + 4);
++ length = tmpStr.find("url=");
++
++ fmturl = (length==-1)? tmpStr : tmpStr.substring(0,length);
++
++ //log_debug("------> GOT BUFFER witchURL:(len=%d) %s\n",length, fmturl.c_str() );
++
++ matcher = FMTURL->matcher( fmturl );
++ if( matcher->next() )
++ {
++ int fmt = atoi( trim_string(matcher->group(2)).c_str() );
++
++ fmturl = trim_string(matcher->group(1)).c_str();
++
++ log_debug("------> GOT BUFFER witchURL: %d -- %s\n", fmt, fmturl.c_str() );
++ log_debug("------> PLAYMODE %s %s\n",hd?"SD":"HD",mp4?"flv":"mp4");
++ // mp4 22:HD H264+AAC
++ if(hd && fmt == 37) return fmturl;
++ if(hd && fmt == 45) return fmturl;
++ if(hd && fmt == 22) return fmturl;
++ //
++ if((hd || mp4) && fmt == 18) return fmturl;
++ // flv 34:H264+AAC low 35:H264+AAC hi
++ if(fmt == 5 || fmt == 44 || fmt == 34 || fmt == 35) return fmturl;
++ }
++ continue;
+ }
+
+- throw _Exception(_("Could not retrieve YouTube video URL"));
++ throw _Exception(_("Could not retrieve YouTube video URL(wichURL)"));
+ }
+
+ #endif//YOUTUBE
+diff -rup ../BUILD/mediatomb-0.12.1/src/youtube_video_url.h mediatomb-0.12.1/src/youtube_video_url.h
+--- ../BUILD/mediatomb-0.12.1/src/youtube_video_url.h 2010-03-25 23:58:11.000000000 +0900
++++ mediatomb-0.12.1/src/youtube_video_url.h 2011-08-08 22:56:38.000000000 +0900
+@@ -57,14 +57,16 @@ public:
+ /// available
+ /// \return the url to the .flv or .mp4 file
+ zmm::String getVideoURL(zmm::String video_id, bool mp4, bool hd);
++ zmm::String whichURL(zmm::String tmpStr, bool mp4, bool hd);
+
+ protected:
+ // the handle *must never be used from multiple threads*
+ CURL *curl_handle;
+ pthread_t pid;
+- zmm::Ref<RExp> reVideoURLParams;
+- zmm::Ref<RExp> redirectLocation;
+- zmm::Ref<RExp> param_t;
++
++ zmm::Ref<RExp> EMBED;
++ zmm::Ref<RExp> FMT;
++ zmm::Ref<RExp> FMTURL;
+ zmm::Ref<RExp> HD;
+ };
diff --git a/mediatomb-0.12.1.flacart.config.patch b/mediatomb-0.12.1.flacart.config.patch
new file mode 100644
index 0000000..1631ae1
--- /dev/null
+++ b/mediatomb-0.12.1.flacart.config.patch
@@ -0,0 +1,55 @@
+--- mediatomb-0.12.1.orig/configure.ac 2010-04-07 17:38:51.000000000 -0500
++++ mediatomb-0.12.1/configure.ac 2011-09-19 00:53:57.346913297 -0500
+@@ -1314,6 +1314,35 @@
+ 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 @@
+ 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 "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 --git a/mediatomb-0.12.1.flacart.patch b/mediatomb-0.12.1.flacart.patch
new file mode 100644
index 0000000..d2cc40a
--- /dev/null
+++ b/mediatomb-0.12.1.flacart.patch
@@ -0,0 +1,386 @@
+Index: build/libmediatomb_src
+===================================================================
+--- build/libmediatomb_src (revision 2069)
++++ build/libmediatomb_src (working copy)
+@@ -98,6 +98,8 @@
+ ../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 \
+Index: build/Makefile.am
+===================================================================
+--- build/Makefile.am (revision 2069)
++++ build/Makefile.am (working copy)
+@@ -20,2 +20,3 @@
+ $(ID3LIB_CFLAGS) \
++ $(FLAC_CFLAGS) \
+ $(LIBEXIF_CFLAGS) \
+@@ -46,2 +47,3 @@
+ $(ID3LIB_CFLAGS) \
++ $(FLAC_CFLAGS) \
+ $(LIBEXIF_CFLAGS) \
+@@ -80,2 +82,3 @@
+ $(ID3LIB_LIBS) \
++ $(FLAC_LIBS) \
+ $(LIBEXIF_LIBS) \
+Index: src/cds_resource_manager.cc
+===================================================================
+--- src/cds_resource_manager.cc (revision 2069)
++++ src/cds_resource_manager.cc (working copy)
+@@ -372,6 +372,7 @@
+ // 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;
+Index: src/config_manager.cc
+===================================================================
+--- src/config_manager.cc (revision 2069)
++++ src/config_manager.cc (working copy)
+@@ -624,6 +624,10 @@
+ _(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"),
+Index: src/metadata/flac_handler.cc
+===================================================================
+--- src/metadata/flac_handler.cc (revision 0)
++++ src/metadata/flac_handler.cc (revision 0)
+@@ -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 at mediatomb.cc>,
++ Sergey 'Jin' Bostandzhyan <jin at mediatomb.cc>
++
++ Copyright (C) 2006-2009 Gena Batyan <bgeradz at mediatomb.cc>,
++ Sergey 'Jin' Bostandzhyan <jin at mediatomb.cc>,
++ Leonhard Wimmer <leo at 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: flac_handler.cc 2032 2009-12-21 22:58:57Z lww $
++*/
++
++/// \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
+Index: src/metadata/flac_handler.h
+===================================================================
+--- src/metadata/flac_handler.h (revision 0)
++++ src/metadata/flac_handler.h (revision 0)
+@@ -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 at mediatomb.cc>,
++ Sergey 'Jin' Bostandzhyan <jin at mediatomb.cc>
++
++ Copyright (C) 2006-2009 Gena Batyan <bgeradz at mediatomb.cc>,
++ Sergey 'Jin' Bostandzhyan <jin at mediatomb.cc>,
++ Leonhard Wimmer <leo at 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: flac_handler.h 2010 2009-01-11 19:10:43Z lww $
++*/
++
++/// \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__
+Index: src/metadata_handler.cc
+===================================================================
+--- src/metadata_handler.cc (revision 2069)
++++ src/metadata_handler.cc (working copy)
+@@ -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 @@
+ 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,14 @@
+ #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 +289,10 @@
+ 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);
+ }
+Index: src/metadata_handler.h
+===================================================================
+--- src/metadata_handler.h (revision 2069)
++++ src/metadata_handler.h (working copy)
+@@ -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/mediatomb-0.12.1.ps3_timeseekrange.patch b/mediatomb-0.12.1.ps3_timeseekrange.patch
new file mode 100644
index 0000000..06cb609
--- /dev/null
+++ b/mediatomb-0.12.1.ps3_timeseekrange.patch
@@ -0,0 +1,464 @@
+Index: src/transcoding/transcode_ext_handler.cc
+===================================================================
+--- src/transcoding/transcode_ext_handler.cc (wersja 2103)
++++ src/transcoding/transcode_ext_handler.cc (kopia robocza)
+@@ -82,7 +82,7 @@
+ Ref<IOHandler> TranscodeExternalHandler::open(Ref<TranscodingProfile> profile,
+ String location,
+ Ref<CdsObject> obj,
+- struct File_Info *info)
++ struct File_Info *info, String range)
+ {
+ bool isURL = false;
+ // bool is_srt = false;
+@@ -118,9 +118,11 @@
+ }
+
+ info->content_type = ixmlCloneDOMString(mimeType.c_str());
+-
+ #ifdef EXTEND_PROTOCOLINFO
+ String header;
++ header = header + _("TimeSeekRange.dlna.org: npt=")+range;
++
++ log_debug("Adding TimeSeekRange response HEADERS: %s\n", header.c_str());
+ header = getDLNAtransferHeader(mimeType, header);
+ if (string_ok(header))
+ info->http_header = ixmlCloneDOMString(header.c_str());
+@@ -328,7 +330,7 @@
+
+ chmod(fifo_name.c_str(), S_IWUSR | S_IRUSR);
+
+- arglist = parseCommandLine(profile->getArguments(), location, fifo_name);
++ arglist = parseCommandLine(profile->getArguments(), location, fifo_name, range);
+
+ log_info("Arguments: %s\n", profile->getArguments().c_str());
+ Ref<TranscodingProcessExecutor> main_proc(new TranscodingProcessExecutor(profile->getCommand(), arglist));
+Index: src/transcoding/transcode_ext_handler.h
+===================================================================
+--- src/transcoding/transcode_ext_handler.h (wersja 2103)
++++ src/transcoding/transcode_ext_handler.h (kopia robocza)
+@@ -43,7 +43,9 @@
+ virtual zmm::Ref<IOHandler> open(zmm::Ref<TranscodingProfile> profile,
+ zmm::String location,
+ zmm::Ref<CdsObject> obj,
+- struct File_Info *info);
++ struct File_Info *info,
++ zmm::String range
++ );
+ };
+
+
+Index: src/transcoding/transcode_handler.h
+===================================================================
+--- src/transcoding/transcode_handler.h (wersja 2103)
++++ src/transcoding/transcode_handler.h (kopia robocza)
+@@ -45,7 +45,9 @@
+ virtual zmm::Ref<IOHandler> open(zmm::Ref<TranscodingProfile> profile,
+ zmm::String location,
+ zmm::Ref<CdsObject> obj,
+- struct File_Info *info) = 0;
++ struct File_Info *info,
++ zmm::String range
++ ) = 0;
+ protected:
+ enum { UNKNOWN_CONTENT_LENGTH = -1 };
+ };
+Index: src/transcoding/transcode_dispatcher.cc
+===================================================================
+--- src/transcoding/transcode_dispatcher.cc (wersja 2103)
++++ src/transcoding/transcode_dispatcher.cc (kopia robocza)
+@@ -51,7 +51,9 @@
+ Ref<IOHandler> TranscodeDispatcher::open(Ref<TranscodingProfile> profile,
+ String location,
+ Ref<CdsObject> obj,
+- struct File_Info *info)
++ struct File_Info *info,
++ String range
++ )
+ {
+ if (profile == nil)
+ throw _Exception(_("Transcoding of file ") + location +
+@@ -62,7 +64,7 @@
+ if (profile->getType() == TR_External)
+ {
+ Ref<TranscodeExternalHandler> tr_ext(new TranscodeExternalHandler());
+- return tr_ext->open(profile, location, obj, info);
++ return tr_ext->open(profile, location, obj, info, range);
+ }
+ else
+ throw _Exception(_("Unknown transcoding type for profile ") +
+Index: src/transcoding/transcode_dispatcher.h
+===================================================================
+--- src/transcoding/transcode_dispatcher.h (wersja 2103)
++++ src/transcoding/transcode_dispatcher.h (kopia robocza)
+@@ -42,7 +42,9 @@
+ virtual zmm::Ref<IOHandler> open(zmm::Ref<TranscodingProfile> profile,
+ zmm::String location,
+ zmm::Ref<CdsObject> obj,
+- struct File_Info *info);
++ struct File_Info *info,
++ zmm::String range
++ );
+ };
+
+
+Index: src/tools.cc
+===================================================================
+--- src/tools.cc (wersja 2103)
++++ src/tools.cc (kopia robocza)
+@@ -1209,7 +1209,7 @@
+ return true;
+ }
+
+-Ref<Array<StringBase> > parseCommandLine(String line, String in, String out)
++Ref<Array<StringBase> > parseCommandLine(String line, String in, String out, String range)
+ {
+ Ref<Array<StringBase> > params = split_string(line, ' ');
+ if ((in == nil) && (out == nil))
+@@ -1220,6 +1220,7 @@
+ String param = params->get(i);
+ String newParam = param.replace(_("%in"), in);
+ newParam = newParam.replace(_("%out"), out);
++ newParam = newParam.replace(_("%range"), range);
+ if (param != newParam)
+ params->set(newParam, i);
+ }
+Index: src/youtube_video_url.cc
+===================================================================
+--- src/youtube_video_url.cc (wersja 2103)
++++ src/youtube_video_url.cc (kopia robocza)
+@@ -44,12 +44,12 @@
+
+ using namespace zmm;
+
+-#define YOUTUBE_URL_PARAMS_REGEXP "var swfHTML.*\\;"
++#define YOUTUBE_URL_PARAMS_REGEXP "var swfConfig.*\\;"
+ #define YOUTUBE_URL_LOCATION_REGEXP "\nLocation: (http://[^\n]+)\n"
+ #define YOUTUBE_URL_WATCH "http://www.youtube.com/watch?v="
+ #define YOUTUBE_URL_GET "http://www.youtube.com/get_video?"
+ #define YOUTUBE_URL_PARAM_VIDEO_ID "video_id"
+-#define YOUTUBE_URL_PARAM_T_REGEXP ".*&t=([^&]+)&"
++#define YOUTUBE_URL_PARAM_T_REGEXP ".*\"t\": \"([^\"]+)\""
+ #define YOUTUBE_URL_PARAM_T "t"
+ #define YOUTUBE_IS_HD_AVAILABLE_REGEXP "IS_HD_AVAILABLE[^:]*: *([^,]*)"
+ YouTubeVideoURL::YouTubeVideoURL()
+@@ -196,7 +196,7 @@
+ if (retcode != 303)
+ {
+ throw _Exception(_("Unexpected reply from YouTube: ") +
+- String::from(retcode));
++ String::from(retcode)+" for url "+params);
+ }
+
+ throw _Exception(_("Could not retrieve YouTube video URL"));
+Index: src/url_request_handler.h
+===================================================================
+--- src/url_request_handler.h (wersja 2103)
++++ src/url_request_handler.h (kopia robocza)
+@@ -43,7 +43,9 @@
+ virtual void get_info(IN const char *filename, OUT struct File_Info *info);
+ virtual zmm::Ref<IOHandler> open(IN const char *filename,
+ OUT struct File_Info *info,
+- IN enum UpnpOpenFileMode mode);
++ IN enum UpnpOpenFileMode mode,
++ IN zmm::String range
++ );
+ };
+
+ #endif // __URL_REQUEST_HANDLER_H__
+Index: src/file_request_handler.h
+===================================================================
+--- src/file_request_handler.h (wersja 2103)
++++ src/file_request_handler.h (kopia robocza)
+@@ -41,8 +41,10 @@
+ public:
+ FileRequestHandler();
+ virtual void get_info(IN const char *filename, OUT struct File_Info *info);
+- virtual zmm::Ref<IOHandler> open(IN const char *filename, OUT struct File_Info *info,
+- IN enum UpnpOpenFileMode mode);
++ virtual zmm::Ref<IOHandler> open(
++ IN const char *filename, OUT struct File_Info *info,
++ IN enum UpnpOpenFileMode mode,
++ IN zmm::String range);
+ };
+
+
+Index: src/cds_resource_manager.cc
+===================================================================
+--- src/cds_resource_manager.cc (wersja 2103)
++++ src/cds_resource_manager.cc (kopia robocza)
+@@ -465,7 +465,7 @@
+ // and the media is converted, so set CI to 1
+ if (!isExtThumbnail && transcoded)
+ {
+- extend = extend + D_OP + "=00;" +
++ extend = extend + D_OP + "=10;" +
+ D_CONVERSION_INDICATOR + "=" D_CONVERSION;
+
+ if (mimeType.startsWith(_("audio")) ||
+Index: src/web_callbacks.cc
+===================================================================
+--- src/web_callbacks.cc (wersja 2103)
++++ src/web_callbacks.cc (kopia robocza)
+@@ -63,12 +63,12 @@
+ using namespace zmm;
+ using namespace mxml;
+
+-static Ref<RequestHandler> create_request_handler(const char *filename)
++static Ref<RequestHandler> create_request_handler(const char *filename, const char *headers)
+ {
+ String path, parameters;
+
+ String link = url_unescape((char *) filename);
+-
++
+ log_debug("Filename: %s, Path: %s\n", filename, path.c_str());
+ // log_debug("create_handler: got url parameters: [%s]\n", parameters.c_str());
+
+@@ -150,11 +150,11 @@
+ ///
+ /// \return 0 Success.
+ /// \return -1 Error.
+-static int web_get_info(IN const char *filename, OUT struct File_Info *info)
++static int web_get_info(IN const char *filename, IN const char *headers, OUT struct File_Info *info)
+ {
+ try
+ {
+- Ref<RequestHandler> reqHandler = create_request_handler(filename);
++ Ref<RequestHandler> reqHandler = create_request_handler(filename, headers);
+ reqHandler->get_info(filename, info);
+ }
+ catch (ServerShutdownException se)
+@@ -189,13 +189,28 @@
+ ///
+ /// \return UpnpWebFileHandle A valid file handle.
+ /// \return NULL Error.
+-static UpnpWebFileHandle web_open(IN const char *filename, OUT struct File_Info *info,
++static UpnpWebFileHandle web_open(IN const char *filename, IN const char *headers, OUT struct File_Info *info,
+ IN enum UpnpOpenFileMode mode)
+ {
++ log_debug("web_open(): %s", headers);
++
++ String link = url_unescape((char *) filename);
++
++ char *line = strstr((char *)headers, "TimeSeekRange.dlna.org: npt=");
++ char *timeseek;
++ if(line != NULL) {
++ char *lineend = strstr(line, "\n");
++ int chars = lineend - (line+28);
++ timeseek = (char *)malloc(chars);
++ strncpy(timeseek, line+28, chars);
++ log_debug("timeseek range found: %s\n",timeseek);
++ link = link + "/range/"+timeseek;
++ }
++
+ try
+ {
+- Ref<RequestHandler> reqHandler = create_request_handler(filename);
+- Ref<IOHandler> ioHandler = reqHandler->open(filename, info, mode);
++ Ref<RequestHandler> reqHandler = create_request_handler(filename, headers);
++ Ref<IOHandler> ioHandler = reqHandler->open(link.c_str(), info, mode, nil);
+ ioHandler->retain();
+ return (UpnpWebFileHandle) ioHandler.getPtr();
+ }
+Index: src/file_request_handler.cc
+===================================================================
+--- src/file_request_handler.cc (wersja 2103)
++++ src/file_request_handler.cc (kopia robocza)
+@@ -332,7 +332,8 @@
+ log_debug("web_get_info(): end\n");
+ }
+
+-Ref<IOHandler> FileRequestHandler::open(IN const char *filename, OUT struct File_Info *info, IN enum UpnpOpenFileMode mode)
++Ref<IOHandler> FileRequestHandler::open(IN const char *filename, OUT struct File_Info *info, IN enum UpnpOpenFileMode mode,
++ IN zmm::String range)
+ {
+ int objectID;
+ String mimeType;
+@@ -581,9 +582,11 @@
+ #ifdef EXTERNAL_TRANSCODING
+ if (!is_srt && string_ok(tr_profile))
+ {
++ String range = dict->get(_("range"));
++
+ Ref<TranscodeDispatcher> tr_d(new TranscodeDispatcher());
+ Ref<TranscodingProfile> tp = ConfigManager::getInstance()->getTranscodingProfileListOption(CFG_TRANSCODING_PROFILE_LIST)->getByName(tr_profile);
+- return tr_d->open(tp, path, RefCast(item, CdsObject), info);
++ return tr_d->open(tp, path, RefCast(item, CdsObject), info, range);
+ }
+ else
+ #endif
+Index: src/request_handler.h
+===================================================================
+--- src/request_handler.h (wersja 2103)
++++ src/request_handler.h (kopia robocza)
+@@ -43,7 +43,9 @@
+ OUT struct File_Info *info) = 0;
+ virtual zmm::Ref<IOHandler> open(IN const char *filename,
+ OUT struct File_Info *info,
+- IN enum UpnpOpenFileMode mode) = 0;
++ IN enum UpnpOpenFileMode mode,
++ IN zmm::String range
++ ) = 0;
+
+ /// \brief Splits the url into a path and parameters string.
+ /// Only '?' and '/' separators are allowed, otherwise an exception will
+Index: src/serve_request_handler.cc
+===================================================================
+--- src/serve_request_handler.cc (wersja 2103)
++++ src/serve_request_handler.cc (kopia robocza)
+@@ -142,8 +142,10 @@
+ }
+ }
+
+-Ref<IOHandler> ServeRequestHandler::open(IN const char *filename, OUT struct File_Info *info,
+- IN enum UpnpOpenFileMode mode)
++Ref<IOHandler> ServeRequestHandler::open(IN const char *filename,
++ OUT struct File_Info *info,
++ IN enum UpnpOpenFileMode mode,
++ IN zmm::String range)
+ {
+ struct stat statbuf;
+ int ret = 0;
+Index: src/tools.h
+===================================================================
+--- src/tools.h (wersja 2103)
++++ src/tools.h (kopia robocza)
+@@ -300,7 +300,7 @@
+ /// separator. In addition special %in and %out tokens are replaced by given
+ /// strings.
+ /// \todo add escaping
+-zmm::Ref<zmm::Array<zmm::StringBase> > parseCommandLine(zmm::String line, zmm::String in, zmm::String out);
++zmm::Ref<zmm::Array<zmm::StringBase> > parseCommandLine(zmm::String line, zmm::String in, zmm::String out, zmm::String range);
+
+ /// \brief this is the mkstemp routine from glibc, the only difference is that
+ /// it does not return an fd but just the name that we could use.
+Index: src/web_request_handler.cc
+===================================================================
+--- src/web_request_handler.cc (wersja 2103)
++++ src/web_request_handler.cc (kopia robocza)
+@@ -242,7 +242,9 @@
+
+ Ref<IOHandler> WebRequestHandler::open(IN const char *filename,
+ OUT struct File_Info *info,
+- IN enum UpnpOpenFileMode mode)
++ IN enum UpnpOpenFileMode mode,
++ IN String range
++ )
+ {
+ log_debug("request: %s\n", filename);
+ this->filename = filename;
+Index: src/serve_request_handler.h
+===================================================================
+--- src/serve_request_handler.h (wersja 2103)
++++ src/serve_request_handler.h (kopia robocza)
+@@ -42,7 +42,9 @@
+ ServeRequestHandler();
+ virtual void get_info(IN const char *filename, OUT struct File_Info *info);
+ virtual zmm::Ref<IOHandler> open(IN const char *filename, OUT struct File_Info *info,
+- IN enum UpnpOpenFileMode mode);
++ IN enum UpnpOpenFileMode mode,
++ IN zmm::String range
++ );
+ };
+
+
+Index: src/url_request_handler.cc
+===================================================================
+--- src/url_request_handler.cc (wersja 2103)
++++ src/url_request_handler.cc (kopia robocza)
+@@ -170,7 +170,7 @@
+ /// \todo transcoding for get_info
+ }
+
+-Ref<IOHandler> URLRequestHandler::open(IN const char *filename, OUT struct File_Info *info, IN enum UpnpOpenFileMode mode)
++Ref<IOHandler> URLRequestHandler::open(IN const char *filename, OUT struct File_Info *info, IN enum UpnpOpenFileMode mode, IN String range)
+ {
+ int objectID;
+ String mimeType;
+@@ -248,7 +248,7 @@
+ tr_profile + " found");
+
+ Ref<TranscodeDispatcher> tr_d(new TranscodeDispatcher());
+- return tr_d->open(tp, url, RefCast(item, CdsObject), info);
++ return tr_d->open(tp, url, RefCast(item, CdsObject), info, range);
+ }
+ else
+ #endif
+Index: src/web_request_handler.h
+===================================================================
+--- src/web_request_handler.h (wersja 2103)
++++ src/web_request_handler.h (kopia robocza)
+@@ -145,7 +145,11 @@
+ /// \param filename The requested URL
+ /// \param mode either UPNP_READ or UPNP_WRITE
+ /// \return the appropriate IOHandler for the request.
+- virtual zmm::Ref<IOHandler> open(IN const char *filename, OUT struct File_Info *info, IN enum UpnpOpenFileMode mode);
++ virtual zmm::Ref<IOHandler> open(IN const char *filename,
++ OUT struct File_Info *info,
++ IN enum UpnpOpenFileMode mode,
++ IN zmm::String range
++ );
+
+ /// \brief This method must be overriden by the subclasses that actually process the given request.
+ virtual void process() = 0;
+Index: tombupnp/upnp/src/genlib/net/http/webserver.c
+===================================================================
+--- tombupnp/upnp/src/genlib/net/http/webserver.c (wersja 2103)
++++ tombupnp/upnp/src/genlib/net/http/webserver.c (kopia robocza)
+@@ -1340,7 +1340,7 @@
+ {
+ // use urlbuf instead of filename, because the filename
+ // is already unescaped, but we want the escaped version
+- *Fp = pVirtualDirCallback->open( req->urlbuf, &finfo, UPNP_READ );
++ *Fp = pVirtualDirCallback->open( req->urlbuf, req->msg.buf, &finfo, UPNP_READ );
+ if( *Fp == NULL )
+ {
+ err_code = HTTP_NOT_FOUND;
+@@ -1352,7 +1352,7 @@
+ // use urlbuf instead of filename, because the filename
+ // is already unescaped, but we want the escaped version
+
+- if( pVirtualDirCallback->get_info( req->urlbuf, &finfo ) !=
++ if( pVirtualDirCallback->get_info( req->urlbuf, req->msg.buf, &finfo ) !=
+ 0 ) {
+ err_code = HTTP_NOT_FOUND;
+ goto error_handler;
+@@ -1373,7 +1373,7 @@
+ goto error_handler;
+ }
+ // get info
+- *Fp = pVirtualDirCallback->open( filename->buf, &finfo, UPNP_READ );
++ *Fp = pVirtualDirCallback->open( req->urlbuf, req->msg.buf, &finfo, UPNP_READ );
+ if( (*Fp == NULL) || finfo.is_directory ) {
+ err_code = HTTP_NOT_FOUND;
+ goto error_handler;
+@@ -1632,7 +1632,7 @@
+
+ if( Instr && Instr->IsVirtualFile ) {
+
+- Fp = virtualDirCallback.open( filename, finfo, UPNP_WRITE );
++ Fp = virtualDirCallback.open( filename, parser->msg.msg.buf, finfo, UPNP_WRITE );
+ if( Fp == NULL ) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+Index: tombupnp/upnp/inc/upnp.h
+===================================================================
+--- tombupnp/upnp/inc/upnp.h (wersja 2103)
++++ tombupnp/upnp/inc/upnp.h (kopia robocza)
+@@ -942,6 +942,7 @@
+ * should return 0 on success or -1 on an error. */
+ int (*get_info) (
+ IN const char *filename, /** The name of the file to query. */
++ IN const char *headers, /** Request headers */
+ OUT struct File_Info *info /** Pointer to a structure to store the
+ information on the file. */
+ );
+@@ -951,6 +952,7 @@
+ * {\tt NULL} to signify an error. */
+ UpnpWebFileHandle (*open)(
+ IN const char *filename, /** The name of the file to open. */
++ IN const char *headers, /** Request headers */
+ OUT struct File_Info *info, /** Pointer to a structure to store the
+ information on the file. */
+ IN enum UpnpOpenFileMode Mode /** The mode in which to open the file.
diff --git a/mediatomb.spec b/mediatomb.spec
index 223b15a..a0daee3 100644
--- a/mediatomb.spec
+++ b/mediatomb.spec
@@ -1,24 +1,32 @@
Version: 0.12.1
Summary: UPnP AV MediaServer
Name: mediatomb
-Release: 12%{?dist}
+Release: 13%{?dist}
Summary: MediaTomb - UPnP AV Mediaserver for Linux
License: GPLv2
Group: Applications/Multimedia
URL: http://mediatomb.cc
Source: http://downloads.sourceforge.net/mediatomb/%{name}-%{version}.tar.gz
-# Adds handler for ogg audio metadata by default. Submitted upstream
+# Adds handler for ogg audio metadata by default. Submitted upstream: http://sourceforge.net/tracker/?func=detail&aid=3064466&group_id=129766&atid=715782
Patch0: mediatomb-0.12.1.fixogg.patch
# Fixes issue where video files > 999 minutes in length overrun the minutes buffer.
Patch1: mediatomb-0.12.1.fixbufferoverrun.patch
# Fix build issues related to GCC 4.6 (missing definitions.) Submitted upstream
Patch2: mediatomb-0.12.1.fixbuild.patch
-#Port to js-1.8 (thanks Jan!) Not yet submitted upstream
+#Port to js-1.8 (thanks Jan!) Submitted upstream: http://sourceforge.net/tracker/?func=detail&aid=3409482&group_id=129766&atid=715782
Patch3: mediatomb-0.12.1.tonewjs.patch
-# Fixes to the js/native code to allow custom js parsing. Not yet submitted upstream
+# Fixes to the js/native code to allow custom js parsing. Submitted upstream (with above)
Patch4: mediatomb-0.12.1-jsparse.patch
+# Allows timeseeking on ps3. http://sourceforge.net/tracker/?func=detail&aid=3309436&group_id=129766&atid=715782
+Patch5: mediatomb-0.12.1.ps3_timeseekrange.patch
+# Enable album art for FLAC based on libflac. http://sourceforge.net/tracker/?func=detail&aid=2960326&group_id=129766&atid=715782
+Patch6: mediatomb-0.12.1.flacart.patch
+Patch7: mediatomb-0.12.1.flacart.config.patch
+# Fix youtube support. RHBZ#747023, upstream bug http://sourceforge.net/tracker/?func=detail&aid=3382320&group_id=129766&atid=715780
+Patch8: mediatomb-0.12.1.fixyoutube.patch
+
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-BuildRequires: sqlite-devel, mysql-devel, libexif-devel, id3lib-devel, file-devel, js-devel, zlib-devel, taglib-devel
+BuildRequires: sqlite-devel, mysql-devel, libexif-devel, id3lib-devel, file-devel, js-devel, zlib-devel, taglib-devel flac-devel
BuildRequires: expat-devel, libcurl-devel
BuildRequires: libmp4v2-devel
BuildRequires: lastfmlib-devel
@@ -51,11 +59,15 @@ be found on http://www.upnp.org/.
%patch2 -p0
%patch3 -p1
%patch4 -p1
+%patch5 -p0
+%patch6 -p0
+%patch7 -p1
+%patch8 -p3
%build
# Fedora 13 on use system jsapi.h
%if 0%{?fedora} >= 13
-%configure --enable-inotify --enable-taglib --enable-libjs
+%configure --enable-inotify --enable-taglib --enable-libjs --enable-FLAC
%else
# Fedora 11 and 12 use xulrunner 1.9.1 for jsapi.h
%if 0%{?fedora} >= 11
@@ -131,6 +143,10 @@ fi
%{_initrddir}/mediatomb
%changelog
+* Tue Oct 18 2011 Rich Mattes <richmattes at gmail.com> - 0.12.1-13
+- Fix youtube support (RHBZ#747023)
+- Enable FLAC cover art via libFLAC
+
* Wed Jun 29 2011 Rich Mattes <richmattes at gmail.com> - 0.12.1-12
- Update to fix js printing routine
More information about the scm-commits
mailing list