[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