From 971d6d40e356dc2750242fa4ee6b7764d4e824b3 Mon Sep 17 00:00:00 2001
From: Gavin Hurlbut <gjhurlbu@gmail.com>
Date: Sat, 21 Aug 2010 23:29:02 -0700
Subject: [PATCH] Added patch from #8801 - redo upnp + video

Modified to include subtitle where applicable

diff --git a/mythtv/programs/mythbackend/main_helpers.cpp b/mythtv/programs/mythbackend/main_helpers.cpp
index 190fbf2..d022bfe 100644
--- a/mythtv/programs/mythbackend/main_helpers.cpp
+++ b/mythtv/programs/mythbackend/main_helpers.cpp
@@ -305,15 +305,6 @@ void log_rotate_handler(int)
     log_rotate(0);
 }
 
-void upnp_rebuild(int)
-{
-    if (gCoreContext->IsMasterHost())
-    {
-        g_pUPnp->RebuildMediaMap();
-    }
-
-}
-
 void showUsage(const MythCommandLineParser &cmdlineparser, const QString &version)
 {
     QString    help  = cmdlineparser.GetHelpString(false);
@@ -432,10 +423,7 @@ int handle_command(const MythCommandLineParser &cmdline)
 
     if (cmdline.WantUPnPRebuild())
     {
-        VERBOSE(VB_GENERAL, "Rebuilding UPNP Media Map");
-
-        UPnpMedia *rebuildit = new UPnpMedia(false,false);
-        rebuildit->BuildMediaMap();
+        VERBOSE(VB_GENERAL, "Rebuilding UPNP Media Map is no longer supported");
 
         return BACKEND_EXIT_OK;
     }
@@ -757,12 +745,6 @@ int run_backend(const MythCommandLineParser &cmdline)
             pHS->RegisterExtension(httpStatus);
     }
 
-    if (ismaster)
-    {
-        // kill -USR1 mythbackendpid will force a upnpmedia rebuild
-        signal(SIGUSR1, &upnp_rebuild);
-    }
-
     VERBOSE(VB_IMPORTANT, QString("Enabled verbose msgs: %1")
             .arg(verboseString));
 
diff --git a/mythtv/programs/mythbackend/mediaserver.cpp b/mythtv/programs/mythbackend/mediaserver.cpp
index b7a6fd4..5d8e4c7 100644
--- a/mythtv/programs/mythbackend/mediaserver.cpp
+++ b/mythtv/programs/mythbackend/mediaserver.cpp
@@ -15,7 +15,6 @@
 #include "upnpcdstv.h"
 #include "upnpcdsmusic.h"
 #include "upnpcdsvideo.h"
-#include "upnpmedia.h"
 
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
@@ -177,9 +176,6 @@ MediaServer::MediaServer( bool bIsMaster, bool bDisableUPnp /* = FALSE */ )
             VERBOSE(VB_UPNP, "MediaServer::Registering UPnpCDSVideo Extension");
 
             RegisterExtension(new UPnpCDSVideo());
-
-            upnpMedia = new UPnpMedia(true,true);
-            //upnpMedia->BuildMediaMap();
         }
 
         // VERBOSE(VB_UPNP, QString( "MediaServer::Adding Context Listener" ));
diff --git a/mythtv/programs/mythbackend/mediaserver.h b/mythtv/programs/mythbackend/mediaserver.h
index 12fbda5..de48b25 100644
--- a/mythtv/programs/mythbackend/mediaserver.h
+++ b/mythtv/programs/mythbackend/mediaserver.h
@@ -17,7 +17,6 @@
 #include "upnpcds.h"
 #include "upnpcmgr.h"
 #include "upnpmsrr.h"
-#include "upnpmedia.h"
 
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
@@ -34,7 +33,6 @@ class MediaServer : public UPnp
 
         UPnpCDS         *m_pUPnpCDS;     // Do not delete (auto deleted)
         UPnpCMGR        *m_pUPnpCMGR;    // Do not delete (auto deleted)
-        UPnpMedia       *upnpMedia;
 
         QString          m_sSharePath;
 
@@ -43,8 +41,6 @@ class MediaServer : public UPnp
 
         virtual ~MediaServer();
 
-        void RebuildMediaMap(void) { upnpMedia->BuildMediaMap(); };
-
         void     RegisterExtension  ( UPnpCDSExtension    *pExtension );
         void     UnregisterExtension( UPnpCDSExtension    *pExtension );
 
diff --git a/mythtv/programs/mythbackend/mythbackend.pro b/mythtv/programs/mythbackend/mythbackend.pro
index 6bc4cac..226fa91 100644
--- a/mythtv/programs/mythbackend/mythbackend.pro
+++ b/mythtv/programs/mythbackend/mythbackend.pro
@@ -21,13 +21,13 @@ QMAKE_CLEAN += $(TARGET)
 HEADERS += autoexpire.h encoderlink.h filetransfer.h httpstatus.h mainserver.h
 HEADERS += playbacksock.h scheduler.h server.h housekeeper.h backendutil.h
 HEADERS += upnpcdstv.h upnpcdsmusic.h upnpcdsvideo.h mediaserver.h
-HEADERS += mythxml.h upnpmedia.h main_helpers.h backendcontext.h
+HEADERS += mythxml.h main_helpers.h backendcontext.h
 
 SOURCES += autoexpire.cpp encoderlink.cpp filetransfer.cpp httpstatus.cpp
 SOURCES += main.cpp mainserver.cpp playbacksock.cpp scheduler.cpp server.cpp
 SOURCES += housekeeper.cpp backendutil.cpp
 SOURCES += upnpcdstv.cpp upnpcdsmusic.cpp upnpcdsvideo.cpp mediaserver.cpp
-SOURCES += mythxml.cpp upnpmedia.cpp main_helpers.cpp backendcontext.cpp
+SOURCES += mythxml.cpp main_helpers.cpp backendcontext.cpp
 
 using_oss:DEFINES += USING_OSS
 
diff --git a/mythtv/programs/mythbackend/mythxml.cpp b/mythtv/programs/mythbackend/mythxml.cpp
index 5e1bde2..43fee8c 100644
--- a/mythtv/programs/mythbackend/mythxml.cpp
+++ b/mythtv/programs/mythbackend/mythxml.cpp
@@ -862,7 +862,7 @@ void MythXML::GetVideoArt( HTTPRequest *pRequest )
 
     MSqlQuery query(MSqlQuery::InitCon());
 
-    query.prepare("SELECT coverart FROM upnpmedia WHERE intid = :ITEMID");
+    query.prepare("SELECT coverfile FROM videometadata WHERE intid = :ITEMID");
     query.bindValue(":ITEMID", sId);
 
     if (!query.exec())
@@ -885,6 +885,24 @@ void MythXML::GetVideoArt( HTTPRequest *pRequest )
         return;
     }
 
+    // ----------------------------------------------------------------------
+    // Not there? Perhaps we need to look in a storage group?
+    // ----------------------------------------------------------------------
+    StorageGroup sgroup("Coverart");
+    sFileName = sgroup.FindRecordingFile( sFileName );
+
+    if (sFileName != "")
+    {
+        VERBOSE(VB_IMPORTANT, QString("Found coverart '%1'").arg(sFileName));
+
+        pRequest->m_eResponseType   = ResponseTypeFile;
+        pRequest->m_nResponseStatus = 200;
+        pRequest->m_sFileName = sFileName;
+        return;
+    }
+
+    VERBOSE(VB_IMPORTANT, QString("Not found '%1'").arg(sFileName));
+
 }
 
 void MythXML::GetAlbumArt( HTTPRequest *pRequest )
@@ -1718,8 +1736,6 @@ void MythXML::GetVideo( HttpWorkerThread *pThread,
 
     if (pData == NULL)
     {
-        QString sBasePath = "";
-
         // ------------------------------------------------------------------
         // Load Track's FileName
         // ------------------------------------------------------------------
@@ -1728,7 +1744,7 @@ void MythXML::GetVideo( HttpWorkerThread *pThread,
 
         if (query.isConnected())
         {
-            query.prepare("SELECT filepath FROM upnpmedia WHERE intid = :KEY" );
+            query.prepare("SELECT filename FROM videometadata WHERE intid = :KEY" );
             query.bindValue(":KEY", sId );
 
             if (!query.exec())
@@ -1739,8 +1755,15 @@ void MythXML::GetVideo( HttpWorkerThread *pThread,
 
             if (query.next())
             {
-                pRequest->m_sFileName = QString( "%1/%2" ).arg( sBasePath )
-                                        .arg( query.value(0).toString() );
+                QString sFileName = query.value(0).toString();
+
+                if (!QFile::exists( sFileName ))
+                {
+                    StorageGroup sgroup("Videos");
+                    sFileName = sgroup.FindRecordingFile( sFileName );
+                }
+
+                pRequest->m_sFileName = sFileName;
             }
         }
 
diff --git a/mythtv/programs/mythbackend/upnpcdsvideo.cpp b/mythtv/programs/mythbackend/upnpcdsvideo.cpp
index d204e21..52b7c10 100644
--- a/mythtv/programs/mythbackend/upnpcdsvideo.cpp
+++ b/mythtv/programs/mythbackend/upnpcdsvideo.cpp
@@ -1,7 +1,7 @@
 // Program Name: upnpcdsvideo.cpp
-//
-// Purpose - uPnp Content Directory Extension for MythVideo Videos
-//
+//                                                                            
+// Purpose - UPnP Content Directory Extension for MythVideo Videos
+//                                                                            
 //////////////////////////////////////////////////////////////////////////////
 
 // POSIX headers
@@ -13,22 +13,22 @@
 // MythTV headers
 #include "upnpcdsvideo.h"
 #include "httprequest.h"
-#include "upnpmedia.h"
 #include "util.h"
 #include "mythcorecontext.h"
+#include "storagegroup.h"
 
 #define LOC QString("UPnpCDSVideo: ")
 #define LOC_WARN QString("UPnpCDSVideo, Warning: ")
 #define LOC_ERR QString("UPnpCDSVideo, Error: ")
 
-UPnpCDSRootInfo UPnpCDSVideo::g_RootNodes[] =
+UPnpCDSRootInfo UPnpCDSVideo::g_RootNodes[] = 
 {
-    {   "VideoRoot",
+    {   "All Videos", 
         "*",
         "SELECT 0 as key, "
           "title as name, "
           "1 as children "
-            "FROM upnpmedia "
+            "FROM videometadata "
             "%1 "
             "ORDER BY title",
         "" }
@@ -47,7 +47,7 @@ int UPnpCDSVideo::g_nRootCount = 1;
 UPnpCDSRootInfo *UPnpCDSVideo::GetRootInfo( int nIdx )
 {
     if ((nIdx >=0 ) && ( nIdx < g_nRootCount ))
-        return &(g_RootNodes[ nIdx ]);
+        return &(g_RootNodes[ nIdx ]); 
 
     return NULL;
 }
@@ -67,7 +67,7 @@ int UPnpCDSVideo::GetRootCount()
 
 QString UPnpCDSVideo::GetTableName( QString sColumn )
 {
-    return "upnpmedia";
+    return "videometadata";
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -76,9 +76,10 @@ QString UPnpCDSVideo::GetTableName( QString sColumn )
 
 QString UPnpCDSVideo::GetItemListSQL( QString sColumn )
 {
-    return "SELECT intid, title, filepath, " \
-           "itemtype, itemproperties, parentid, "\
-           "coverart FROM upnpmedia WHERE class = 'VIDEO'";
+    return "SELECT intid, title, subtitle, filename, director, plot, "
+            "rating, year, userrating, length, " 
+            "season, episode, coverfile, insertdate, host FROM videometadata";
+
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -89,12 +90,12 @@ void UPnpCDSVideo::BuildItemQuery( MSqlQuery &query, const QStringMap &mapParams
 {
     int nVideoID = mapParams[ "Id" ].toInt();
 
-    QString sSQL = QString( "%1 AND intid=:VIDEOID ORDER BY title DESC" )
-                                                    .arg( GetItemListSQL( ) );
+    QString sSQL = QString( "WHERE %1 AND intid=:VIDEOID ORDER BY title DESC" )
+                    .arg( GetItemListSQL( ) );
 
     query.prepare( sSQL );
 
-    query.bindValue( ":VIDEOID", (int)nVideoID    );
+    query.bindValue( ":VIDEOID", (int)nVideoID );
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -213,10 +214,7 @@ int UPnpCDSVideo::GetDistinctCount( UPnpCDSRootInfo *pInfo )
 
     MSqlQuery query(MSqlQuery::InitCon());
 
-    query.prepare("SELECT COUNT(*) FROM upnpmedia WHERE class = 'VIDEO' "
-                    "AND parentid = :ROOTID");
-
-    query.bindValue(":ROOTID", STARTING_VIDEO_OBJECTID);
+    query.prepare("SELECT COUNT(*) FROM videometadata");
 
     if (query.exec() && query.next())
     {
@@ -226,246 +224,118 @@ int UPnpCDSVideo::GetDistinctCount( UPnpCDSRootInfo *pInfo )
     return nCount;
 }
 
+
 /////////////////////////////////////////////////////////////////////////////
 //
 /////////////////////////////////////////////////////////////////////////////
 
-UPnpCDSExtensionResults *UPnpCDSVideo::ProcessItem( UPnpCDSRequest          *pRequest,
-                                                    UPnpCDSExtensionResults *pResults,
-                                                    QStringList             &idPath )
+void UPnpCDSVideo::AddItem( const UPnpCDSRequest    *pRequest, 
+                            const QString           &sObjectId,
+                            UPnpCDSExtensionResults *pResults,
+                            bool                     bAddRef,
+                            MSqlQuery               &query )
 {
-    pResults->m_nTotalMatches   = 0;
-    pResults->m_nUpdateID       = 1;
 
-    if (pRequest->m_sObjectId.length() == 0)
-        return pResults;
-
-    QStringList tokens = pRequest->m_sObjectId
-        .split('/', QString::SkipEmptyParts);
-    QString     sId    = tokens.last();
+    int            nVidID       = query.value( 0).toInt();
+    QString        sTitle       = query.value( 1).toString();
+    QString        sSubtitle    = query.value( 2).toString();
+    QString        sFilePath    = query.value( 3).toString();
+    QString        sDirector    = query.value( 4).toString();
+    QString        sPlot        = query.value( 5).toString();
+    QString        sRating      = query.value( 6).toString();
+    // int             nYear        = query.value( 7).toInt();
+    // int             nUserRating  = query.value( 8).toInt();
+    int            nLength      = query.value( 9).toInt();
+    // int             nSeason      = query.value(10).toInt();
+    // int             nEpisode     = query.value(11).toInt();
+    QString        sCoverArt    = query.value(12).toString();
+    QDateTime      dtInsertDate = query.value(13).toDateTime();
+    QString        sHostName    = query.value(14).toString();
 
-    if (sId.startsWith("Id"))
-        sId = sId.right( sId.length() - 2);
+    // ----------------------------------------------------------------------
+    // Cache Host ip Address & Port
+    // ----------------------------------------------------------------------
 
-    switch( pRequest->m_eBrowseFlag )
+    // If the host-name is empty then we assume it is our local host
+    // otherwise, we look up the host's IP address and port.  When the
+    // client then trys to play the video it will be directed to the
+    // host which actually has the content.
+    if (!m_mapBackendIp.contains( sHostName ))
     {
-        case CDS_BrowseMetadata:
+        if (sHostName.isEmpty())
         {
-            // --------------------------------------------------------------
-            // Return 1 Item
-            // --------------------------------------------------------------
-
-            QStringMap  mapParams;
-
-            mapParams.insert( "Id", sId );
-
-            MSqlQuery query(MSqlQuery::InitCon());
-
-            if (query.isConnected())
-            {
-                BuildItemQuery( query, mapParams );
-
-                if (query.exec() && query.next())
-                {
-                        AddItem( pRequest, pRequest->m_sParentId, pResults, false, query );
-                        pResults->m_nTotalMatches = 1;
-                }
-            }
-
-            break;
+            m_mapBackendIp[sHostName] = 
+                gCoreContext->GetSetting( "BackendServerIP" );
         }
-
-        case CDS_BrowseDirectChildren:
+        else
         {
-            pRequest->m_sParentId = sId;
-
-            CreateItems( pRequest, pResults, 0, "", false );
-
-            break;
+            m_mapBackendIp[sHostName] = 
+                gCoreContext->GetSettingOnHost( "BackendServerIp", sHostName);
         }
     }
 
-    return pResults;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-/////////////////////////////////////////////////////////////////////////////
-
-void UPnpCDSVideo::CreateItems( UPnpCDSRequest          *pRequest,
-                                UPnpCDSExtensionResults *pResults,
-                                int                      nNodeIdx,
-                                const QString           &sKey,
-                                bool                     bAddRef )
-{
-    pResults->m_nTotalMatches = 0;
-    pResults->m_nUpdateID     = 1;
-
-    UPnpCDSRootInfo *pInfo = GetRootInfo( nNodeIdx );
-
-    if (pInfo == NULL)
-        return;
-
-    if (pRequest->m_nRequestedCount == 0)
-        pRequest->m_nRequestedCount = SHRT_MAX;
-
-    MSqlQuery query(MSqlQuery::InitCon());
-
-    if (query.isConnected())
+    if (!m_mapBackendPort.contains( sHostName ))
     {
-        QString ParentClause;
-        QString sWhere;
-
-        if ( sKey.length() > 0)
+        if (sHostName.isEmpty())
         {
-           sWhere = QString( "WHERE %1=:KEY " )
-                       .arg( pInfo->column );
-        }
-
-        if (pRequest->m_sObjectId.startsWith("Videos"))
-        {
-            if (!pRequest->m_sParentId.isEmpty())
-            {
-                if (pRequest->m_sParentId == "Videos/0")
-                {
-                    pRequest->m_sParentId = QString("%1")
-                                .arg(STARTING_VIDEO_OBJECTID);
-                }
-            }
-            else
-            {
-                QStringList tokens =
-                    pRequest->m_sObjectId.split('=', QString::SkipEmptyParts);
-                pRequest->m_sParentId = tokens.last();
-            }
-
-            if (pRequest->m_sSearchClass.isEmpty())
-                ParentClause = " AND parentid = \"" + pRequest->m_sParentId + "\"";
-            else
-                pRequest->m_sParentId = '8';
-
-            if (pRequest->m_sObjectId.startsWith("Videos/0"))
-            {
-                pRequest->m_sObjectId = "Videos/0";
-            }
-
-            /*
-            VERBOSE(VB_UPNP, QString("pRequest->m_sParentId=:%1: , "
-                                     "pRequest->m_sObjectId=:%2:, sKey=:%3:")
-                                                 .arg(pRequest->m_sParentId)
-                                                 .arg(pRequest->m_sObjectId)
-                                                 .arg(sKey));
-             */
-
-            if ((!pRequest->m_sParentId.isEmpty()) && (pRequest->m_sParentId != "8"))
-                pResults->m_nTotalMatches = GetCount( "parentid", pRequest->m_sParentId );
+            m_mapBackendPort[sHostName] = 
+                gCoreContext->GetSetting( "BackendStatusPort" );
         }
         else
-            VERBOSE( VB_UPNP, QString( "UPnpCDSVideo::CreateItems: ******* ParentID Does NOT Start with 'Videos' ParentId = {0}" )
-                                  .arg( pRequest->m_sParentId ));
-
-        QString sSQL = QString( "%1 %2 LIMIT %3, %4" )
-                          .arg( GetItemListSQL( pInfo->column )  )
-                          .arg( sWhere + ParentClause )
-                          .arg( pRequest->m_nStartingIndex  )
-                          .arg( pRequest->m_nRequestedCount );
-
-        query.prepare  ( sSQL );
-        //VERBOSE(VB_UPNP, QString("sSQL = %1").arg(sSQL));
-        if ( sKey.length() )
-            query.bindValue(":KEY", sKey );
-
-        if (query.exec())
         {
-            while(query.next())
-                AddItem( pRequest, pRequest->m_sObjectId, pResults, bAddRef, query );
-
+            m_mapBackendPort[sHostName] = 
+                gCoreContext->GetSettingOnHost("BackendStatusPort", sHostName);
         }
     }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-/////////////////////////////////////////////////////////////////////////////
-
-void UPnpCDSVideo::AddItem( const UPnpCDSRequest    *pRequest,
-                            const QString           &sObjectId,
-                            UPnpCDSExtensionResults *pResults,
-                            bool                     bAddRef,
-                            MSqlQuery               &query )
-{
-    int            nVidID       = query.value( 0).toInt();
-    QString        sTitle       = query.value( 1).toString();
-    QString        sFileName    = query.value( 2).toString();
-    QString        sItemType    = query.value( 3).toString();
-    QString        sParentID    = query.value( 5).toString();
-    QString        sCoverArt    = query.value( 6).toString();
-
-    // VERBOSE(VB_UPNP,QString("ID = %1, Title = %2, fname = %3 sObjectId = %4").arg(nVidID).arg(sTitle).arg(sFileName).arg(sObjectId));
-
-    // ----------------------------------------------------------------------
-    // Cache Host ip Address & Port
-    // ----------------------------------------------------------------------
-    QString sServerIp = gCoreContext->GetSetting("BackendServerIp"   );
-    QString sPort     = gCoreContext->GetSetting("BackendStatusPort" );
-
+    
+    
     // ----------------------------------------------------------------------
     // Build Support Strings
     // ----------------------------------------------------------------------
 
     QString sName      = sTitle;
+    if( not sSubtitle.isEmpty() )
+    {
+        sName += " - " + sSubtitle;
+    }
 
     QString sURIBase   = QString( "http://%1:%2/Myth/" )
-                            .arg( sServerIp )
-                            .arg( sPort     );
+                            .arg( m_mapBackendIp  [sHostName] ) 
+                            .arg( m_mapBackendPort[sHostName] );
 
     QString sURIParams = QString( "/Id%1" ).arg( nVidID );
     QString sId        = QString( "Videos/0/item%1").arg( sURIParams );
 
-    if (sParentID == QString("%1").arg(STARTING_VIDEO_OBJECTID))
-    {
-        sParentID = "Videos/0";
-    }
-    else
-    {
-        sParentID = QString( "Videos/0/item/Id%1")
-                       .arg( sParentID );
-    }
+    QString sParentID = "Videos/0";
 
     QString sAlbumArtURI= QString( "%1GetVideoArt%2")
                         .arg( sURIBase   )
                         .arg( sURIParams );
 
-    CDSObject *pItem = NULL;
-
-    if (sItemType == "FOLDER")
-    {
-        pItem   = CDSObject::CreateStorageFolder( sId, sName, sParentID);
-        pItem->SetChildCount( GetCount( "parentid",QString( "%1" ).arg( nVidID )) );
-
-        pItem->SetPropValue( "storageUsed", "0" );  //-=>TODO: need proper value
-    }
-    else if (sItemType == "FILE" )
-        pItem   = CDSObject::CreateVideoItem( sId, sName, sParentID );
-
-    if (!pItem)
-    {
-        VERBOSE(VB_IMPORTANT, LOC_ERR + "AddItem(): " +
-        QString("sItemType has unknown type '%1'").arg(sItemType));
-
-        return;
-    }
+    CDSObject *pItem = CDSObject::CreateVideoItem( sId, sName, sParentID );
 
     pItem->m_bRestricted  = false;
     pItem->m_bSearchable  = true;
     pItem->m_sWriteStatus = "WRITABLE";
 
+    pItem->SetPropValue( "longDescription", sPlot );
+    // ?? pItem->SetPropValue( "description"    , sTitle );
+    pItem->SetPropValue( "director"       , sDirector );
+
     pItem->SetPropValue( "genre"          , "[Unknown Genre]"     );
     pItem->SetPropValue( "actor"          , "[Unknown Author]"    );
-    pItem->SetPropValue( "creator"        , "[Unknown Author]"    );
-    pItem->SetPropValue( "album"          , "[Unknown Series]"    );
-
-    if ((!sCoverArt.isEmpty()) && (sCoverArt != "No Cover"))
+    pItem->SetPropValue( "creator"        , "[Unknown Creator]"   );
+    pItem->SetPropValue( "album"          , "[Unknown Album]"     );
+
+    //pItem->SetPropValue( "producer"       , );
+    //pItem->SetPropValue( "rating"         , );
+    //pItem->SetPropValue( "actor"          , );
+    //pItem->SetPropValue( "publisher"      , );
+    //pItem->SetPropValue( "language"       , );
+    //pItem->SetPropValue( "relation"       , );
+    //pItem->SetPropValue( "region"         , );
+
+    if ((sCoverArt != "") && (sCoverArt != "No Cover"))
         pItem->SetPropValue( "albumArtURI"    , sAlbumArtURI);
 
     if ( bAddRef )
@@ -476,10 +346,15 @@ void UPnpCDSVideo::AddItem( const UPnpCDSRequest    *pRequest,
         pItem->SetPropValue( "refID", sRefId );
     }
 
-    QFileInfo fInfo( sFileName );
-    QDateTime fDate = fInfo.lastModified();
+    QString sFullFileName = sFilePath;
+    if (!QFile::exists( sFullFileName ))
+    {
+        StorageGroup sgroup("Videos");
+        sFullFileName = sgroup.FindRecordingFile( sFullFileName );
+    }
+    QFileInfo fInfo( sFullFileName );
 
-    pItem->SetPropValue( "date", fDate.toString( "yyyy-MM-dd"));
+    pItem->SetPropValue( "date", dtInsertDate.toString( "yyyy-MM-dd"));
     pResults->Add( pItem );
 
     // ----------------------------------------------------------------------
@@ -496,8 +371,9 @@ void UPnpCDSVideo::AddItem( const UPnpCDSRequest    *pRequest,
     Resource *pRes = pItem->AddResource( sProtocol, sURI );
 
     pRes->AddAttribute( "size"      , QString("%1").arg(fInfo.size()) );
-    pRes->AddAttribute( "duration"  , "0:01:00.000"      );
 
-}
+    QString sDur;
+    sDur.sprintf("%02d:%02d:00", (nLength / 60), nLength % 60 );
 
-// vim:ts=4:sw=4:ai:et:si:sts=4
+    pRes->AddAttribute( "duration"  , sDur      );
+}
diff --git a/mythtv/programs/mythbackend/upnpcdsvideo.h b/mythtv/programs/mythbackend/upnpcdsvideo.h
index 074e344..56e98d5 100644
--- a/mythtv/programs/mythbackend/upnpcdsvideo.h
+++ b/mythtv/programs/mythbackend/upnpcdsvideo.h
@@ -1,18 +1,19 @@
 //////////////////////////////////////////////////////////////////////////////
-// Program Name: upnpcdstv.h
-//
-// Purpose - uPnp Content Directory Extension for Video
-//
+// Program Name: upnpcdsvideo.h
+//                                                                            
+// Purpose - UPnP Content Directory Extention for Videos
+//                                                                            
 // Created By  : David Blain                    Created On : Jan. 24, 2005
-// Modified By :                                Modified On:
-//
+// Modified By :                                Modified On:                  
+//                                                                            
 //////////////////////////////////////////////////////////////////////////////
 
 #ifndef UPnpCDSVIDEO_H_
 #define UPnpCDSVIDEO_H_
 
+#include "mainserver.h"
 #include "upnpcds.h"
-
+              
 typedef QMap<int, QString> IntMap;
 
 //////////////////////////////////////////////////////////////////////////////
@@ -31,16 +32,6 @@ class UPnpCDSVideo : public UPnpCDSExtension
 
     protected:
 
-        virtual UPnpCDSExtensionResults *ProcessItem( UPnpCDSRequest          *pRequest,
-                                                      UPnpCDSExtensionResults *pResults,
-                                                      QStringList             &idPath );
-
-        virtual void             CreateItems   ( UPnpCDSRequest          *pRequest,
-                                                 UPnpCDSExtensionResults *pResults,
-                                                 int                      nNodeIdx,
-                                                 const QString           &sKey,
-                                                 bool                     bAddRef );
-
         virtual bool             IsBrowseRequestForUs( UPnpCDSRequest *pRequest );
         virtual bool             IsSearchRequestForUs( UPnpCDSRequest *pRequest );
 
@@ -51,14 +42,13 @@ class UPnpCDSVideo : public UPnpCDSExtension
         virtual QString          GetTableName  ( QString sColumn );
         virtual QString          GetItemListSQL( QString sColumn = "");
 
-        virtual void             BuildItemQuery( MSqlQuery        &query,
+        virtual void             BuildItemQuery( MSqlQuery        &query, 
                                                  const QStringMap &mapParams );
 
-                                                 
         virtual void             AddItem( const UPnpCDSRequest    *pRequest, 
                                           const QString           &sObjectId,
                                           UPnpCDSExtensionResults *pResults,
-                                          bool                     bAddRef,
+                                          bool                     bAddRef, 
                                           MSqlQuery               &query );
 
     public:
diff --git a/mythtv/programs/mythbackend/upnpmedia.cpp b/mythtv/programs/mythbackend/upnpmedia.cpp
deleted file mode 100644
index 732ec62..0000000
--- a/mythtv/programs/mythbackend/upnpmedia.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-#include <limits.h>
-#include <unistd.h>
-
-#include <cstdlib>
-
-#include <QFileInfo>
-#include <QDir>
-
-#include "mythcorecontext.h"
-#include "httprequest.h"
-#include "upnpmedia.h"
-#include "mythdb.h"
-#include "util.h"
-#include "pthread.h"
-
-#define LOC QString("UPnpMedia: ")
-
-/////////////////////////////////////////////////////////////////////////////
-//
-/////////////////////////////////////////////////////////////////////////////
-
-UPnpMedia::UPnpMedia(bool runthread, bool ismaster)
-{
-
-    if (gCoreContext->GetNumSetting("UPnP/RebuildDelay",30) > 0)
-    {
-        VERBOSE(VB_GENERAL,"Enabling Upnpmedia rebuild thread.");
-        if ((runthread) && (ismaster))
-        {
-            pthread_t upnpmediathread;
-            pthread_create(&upnpmediathread, NULL, doUPnpMediaThread, this);
-        }
-    }
-    else
-    {
-        VERBOSE(VB_GENERAL,"Upnpmedia rebuild disabled.");
-    }
-
-}
-
-void UPnpMedia::RunRebuildLoop(void)
-{
-
-    // Sleep a few seconds to wait for other stuff to settle down.
-    sleep(10);
-
-    int irebuildDelay = 1800;
-
-    irebuildDelay = gCoreContext->GetNumSetting("UPnP/RebuildDelay",30) * 60;
-
-    if (irebuildDelay < 60)
-        irebuildDelay = 60;
-
-    while (1)
-    {
-        //VERBOSE(VB_UPNP, "UPnpMedia::RunRebuildLoop Calling BuildMediaMap");
-        BuildMediaMap();
-
-        sleep(irebuildDelay + (random()%8));
-    }
-}
-
-void *UPnpMedia::doUPnpMediaThread(void *param)
-{
-    UPnpMedia *upnpmedia = static_cast<UPnpMedia*>(param);
-    upnpmedia->RunRebuildLoop();
-
-    return NULL;
-}
-
-QString UPnpMedia::GetTitleName(QString fPath, QString fName)
-{
-    if (!m_mapTitleNames[fPath].isNull())
-    {
-        return m_mapTitleNames[fPath];
-    }
-    else
-        return fName;
-}
-
-QString UPnpMedia::GetCoverArt(QString fPath)
-{
-    if (!m_mapCoverArt[fPath].isNull())
-    {
-        return m_mapCoverArt[fPath];
-    }
-    else
-        return "";
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-/////////////////////////////////////////////////////////////////////////////
-
-// this should dynamically generate the SQL query and such
-void UPnpMedia::FillMetaMaps(void)
-{
-    MSqlQuery query(MSqlQuery::InitCon());
-
-    QString sSQL = "SELECT filename, title, coverfile FROM videometadata";
-
-    query.prepare  ( sSQL );
-
-    if (query.exec() && query.size() > 0)
-    {
-        while(query.next())
-        {
-            m_mapTitleNames[query.value(0).toString()] = query.value(1)
-                                                                .toString();
-            m_mapCoverArt[query.value(0).toString()] = query.value(2)
-                                                                .toString();
-        }
-    }
-
-}
-
-
-int UPnpMedia::buildFileList(QString directory, int rootID, int itemID, MSqlQuery &query)
-{
-
-    int parentid;
-    QDir vidDir(directory);
-    //VERBOSE(VB_UPNP, QString("buildFileList = %1, rootID = %2, itemID =
-    //%3").arg(directory).arg(rootID).arg(itemID));
-
-    if (rootID > 0)
-        parentid = rootID;
-    else
-        parentid = itemID;
-
-    vidDir.setSorting( QDir::DirsFirst | QDir::Name );
-    QFileInfoList List = vidDir.entryInfoList();
-    // If we can't read it's contents move on
-    if (List.isEmpty())
-        return itemID;
-
-    for (QFileInfoList::iterator it = List.begin(); it != List.end(); ++it)
-    {
-        QFileInfo Info(*it);
-        QString fName = Info.fileName();
-        QString fPath = Info.filePath();
-
-        if (fName == "." ||
-            fName == "..")
-        {
-            continue;
-        }
-
-        if (Info.isDir())
-        {
-            itemID++;
-
-            query.prepare("INSERT INTO upnpmedia "
-                        "(intid, class, itemtype, parentid, itemproperties, "
-            "filepath, filename, title, coverart) "
-            "VALUES (:ITEMID, :ITEMCLASS, 'FOLDER', :PARENTID, '', "
-            ":FILEPATH, :FILENAME, :TITLE, :COVERART)");
-
-            query.bindValue(":ITEMCLASS", sMediaType);
-            query.bindValue(":ITEMID", itemID);
-            query.bindValue(":PARENTID", parentid);
-            query.bindValue(":FILEPATH", fPath);
-            query.bindValue(":FILENAME", fName);
-
-            query.bindValue(":TITLE", GetTitleName(fPath,fName));
-            query.bindValue(":COVERART", GetCoverArt(fPath));
-
-            if (!query.exec())
-                MythDB::DBError("UPnpMedia::buildFileList", query);
-
-            itemID = buildFileList(Info.filePath(), 0, itemID, query);
-            continue;
-
-        }
-        else
-        {
-/*
-            if (handler->validextensions.count() > 0)
-            {
-                QRegExp r;
-
-                r.setPattern("^" + Info.suffix() + "$");
-                r.setCaseSensitive(false);
-                QStringList result = handler->validextensions.grep(r);
-                if (result.isEmpty()) {
-                    continue;
-                }
-            }
-*/
-
-            itemID++;
-
-//            VERBOSE(VB_UPNP, QString("UPnpMedia Video File : (%1) (%2)")
-//                      .arg(itemID)
-//                                .arg(fName));
-
-            query.prepare("INSERT INTO upnpmedia "
-                        "(intid, class, itemtype, parentid, itemproperties, "
-                        "filepath, filename, title, coverart) "
-                        "VALUES (:ITEMID, :ITEMCLASS, 'FILE', :PARENTID, '', "
-                        ":FILEPATH, :FILENAME, :TITLE, :COVERART)");
-
-            query.bindValue(":ITEMCLASS", sMediaType);
-            query.bindValue(":ITEMID", itemID);
-            query.bindValue(":PARENTID", parentid);
-            query.bindValue(":FILEPATH", fPath);
-            query.bindValue(":FILENAME", fName);
-
-            query.bindValue(":TITLE", GetTitleName(fPath,fName));
-            query.bindValue(":COVERART", GetCoverArt(fPath));
-
-            if (!query.exec())
-                MythDB::DBError("UPnpMedia::buildFileList", query);
-
-        }
-    }
-
-    return itemID;
-}
-
-void UPnpMedia::BuildMediaMap(void)
-{
-    MSqlQuery query(MSqlQuery::InitCon());
-
-    // For now this class only does the video stuff, but eventually other media too
-    sMediaType = "VIDEO";
-
-    if (sMediaType == "VIDEO")
-    {
-        QString RootVidDir = gCoreContext->GetSetting("VideoStartupDir");
-
-        if (!RootVidDir.isEmpty())
-        {
-
-            FillMetaMaps();
-
-            query.prepare("DELETE FROM upnpmedia WHERE class = :ITEMCLASS");
-            query.bindValue(":ITEMCLASS", sMediaType);
-            if (!query.exec())
-            {
-                MythDB::DBError("BuildMediaMap -- clearing table upnpmedia", query);
-                VERBOSE(VB_IMPORTANT, LOC + "BuildMediaMap - aborting");
-                return;
-            }
-
-            if (!query.exec("LOCK TABLES upnpmedia WRITE"))
-                MythDB::DBError("BuildMediaMap -- lock tables", query);
-
-            VERBOSE(VB_UPNP, LOC + QString("VideoStartupDir = %1")
-                                            .arg(RootVidDir));
-
-            QStringList parts = RootVidDir.split(':', QString::SkipEmptyParts);
-
-            int nextID = STARTING_VIDEO_OBJECTID;
-
-            for ( QStringList::Iterator it = parts.begin(); it != parts.end();
-                                                                        ++it )
-            {
-                int filecount = nextID;
-
-                VERBOSE(VB_GENERAL, LOC + QString("BuildMediaMap %1 scan "
-                                                "starting in :%2:")
-                                                    .arg(sMediaType)
-                                                    .arg(*it));
-
-                nextID = buildFileList(*it,STARTING_VIDEO_OBJECTID, nextID,
-                                                                        query);
-
-                if (!gCoreContext->GetSetting("UPnP/RecordingsUnderVideos").isEmpty())
-                {
-                    VERBOSE(VB_ALL, "uPnP Unspecified error line 275, "
-                                    "upnpmedia.cpp");
-                    //   nextID = buildRecordingList(*it,STARTING_VIDEO_OBJECTID,
-                    //                                        nextID,query);
-                }
-
-                filecount = (filecount - nextID) * -1;
-
-                VERBOSE(VB_GENERAL, LOC + QString("BuildMediaMap Done. Found "
-                                                "%1 objects").arg(filecount));
-
-            }
-
-            if (!query.exec("UNLOCK TABLES"))
-                MythDB::DBError("BuildMediaMap -- unlock tables", query);
-
-        }
-        else
-        {
-            VERBOSE(VB_GENERAL, LOC + "BuildMediaMap - no VideoStartupDir set, "
-                                " skipping scan.");
-        }
-
-    }
-    else
-    {
-        VERBOSE(VB_GENERAL, LOC + QString("BuildMediaMap UNKNOWN MediaType %1 "
-                            ", skipping scan.").arg(sMediaType));
-    }
-
-}
-
-
diff --git a/mythtv/programs/mythbackend/upnpmedia.h b/mythtv/programs/mythbackend/upnpmedia.h
deleted file mode 100644
index a4db394..0000000
--- a/mythtv/programs/mythbackend/upnpmedia.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef UPnpMEDIA_H_
-#define UPnpMEDIA_H_
-
-#include <QString>
-
-#include "upnputil.h" // for QStringMap
-
-#define STARTING_VIDEO_OBJECTID 100000
-
-//////////////////////////////////////////////////////////////////////////////
-//
-//////////////////////////////////////////////////////////////////////////////
-
-class MSqlQuery;
-class UPnpMedia
-{
-  private:
-    QStringMap           m_mapTitleNames;
-    QStringMap           m_mapCoverArt;
-    //QString              sMediaType;
-
-    void FillMetaMaps(void);
-    int GetBaseCount(void);
-    QString GetTitleName(QString fPath, QString fName);
-    QString GetCoverArt(QString fPath);
-
-    int buildFileList(QString directory, int rootID, int itemID,
-                      MSqlQuery &query);
-
-    void RunRebuildLoop(void);
-    static void *doUPnpMediaThread(void *param);
-
-  public:
-    UPnpMedia(bool runthread, bool master);
-    ~UPnpMedia() {};
-
-    void SetMediaType(QString mediatype) { sMediaType = mediatype; }
-
-    void BuildMediaMap(void);
-    QString sMediaType;
-};
-
-#endif
-- 
1.7.0.4

