Ticket #8801: upnp_video.patch
File upnp_video.patch, 35.6 KB (added by , 14 years ago) |
---|
-
programs/mythbackend/mythxml.cpp
862 862 863 863 MSqlQuery query(MSqlQuery::InitCon()); 864 864 865 query.prepare("SELECT cover art FROM upnpmedia WHERE intid = :ITEMID");865 query.prepare("SELECT coverfile FROM videometadata WHERE intid = :ITEMID"); 866 866 query.bindValue(":ITEMID", sId); 867 867 868 868 if (!query.exec()) … … 885 885 return; 886 886 } 887 887 888 // ---------------------------------------------------------------------- 889 // Not there? Perhaps we need to look in a storage group? 890 // ---------------------------------------------------------------------- 891 StorageGroup sgroup("Coverart"); 892 sFileName = sgroup.FindRecordingFile( sFileName ); 893 894 if (sFileName != "") 895 { 896 VERBOSE(VB_IMPORTANT, 897 QString("Found coverart '%1'").arg(sFileName)); 898 899 pRequest->m_eResponseType = ResponseTypeFile; 900 pRequest->m_nResponseStatus = 200; 901 pRequest->m_sFileName = sFileName; 902 return; 903 } 904 905 VERBOSE(VB_IMPORTANT, 906 QString("Not found '%1'").arg(sFileName)); 907 888 908 } 889 909 890 910 void MythXML::GetAlbumArt( HTTPRequest *pRequest ) … … 1718 1738 1719 1739 if (pData == NULL) 1720 1740 { 1721 QString sBasePath = "";1722 1723 1741 // ------------------------------------------------------------------ 1724 1742 // Load Track's FileName 1725 1743 // ------------------------------------------------------------------ … … 1728 1746 1729 1747 if (query.isConnected()) 1730 1748 { 1731 query.prepare("SELECT file path FROM upnpmedia WHERE intid = :KEY" );1749 query.prepare("SELECT filename FROM videometadata WHERE intid = :KEY" ); 1732 1750 query.bindValue(":KEY", sId ); 1733 1751 1734 1752 if (!query.exec()) … … 1739 1757 1740 1758 if (query.next()) 1741 1759 { 1742 pRequest->m_sFileName = QString( "%1/%2" ).arg( sBasePath ) 1743 .arg( query.value(0).toString() ); 1760 QString sFileName = query.value(0).toString(); 1761 1762 if (!QFile::exists( sFileName )) 1763 { 1764 StorageGroup sgroup("Videos"); 1765 sFileName = sgroup.FindRecordingFile( sFileName ); 1766 } 1767 1768 pRequest->m_sFileName = sFileName; 1744 1769 } 1745 1770 } 1746 1771 -
programs/mythbackend/mediaserver.cpp
15 15 #include "upnpcdstv.h" 16 16 #include "upnpcdsmusic.h" 17 17 #include "upnpcdsvideo.h" 18 #include "upnpmedia.h"19 18 20 19 ////////////////////////////////////////////////////////////////////////////// 21 20 ////////////////////////////////////////////////////////////////////////////// … … 177 176 VERBOSE(VB_UPNP, "MediaServer::Registering UPnpCDSVideo Extension"); 178 177 179 178 RegisterExtension(new UPnpCDSVideo()); 180 181 upnpMedia = new UPnpMedia(true,true);182 //upnpMedia->BuildMediaMap();183 179 } 184 180 185 181 // VERBOSE(VB_UPNP, QString( "MediaServer::Adding Context Listener" )); -
programs/mythbackend/upnpcdsvideo.h
1 1 ////////////////////////////////////////////////////////////////////////////// 2 2 // Program Name: upnpcdstv.h 3 // 4 // Purpose - uPnp Content Directory Exten sion for Video5 // 3 // 4 // Purpose - uPnp Content Directory Extention for Recorded TV 5 // 6 6 // Created By : David Blain Created On : Jan. 24, 2005 7 // Modified By : Modified On: 8 // 7 // Modified By : Modified On: 8 // 9 9 ////////////////////////////////////////////////////////////////////////////// 10 10 11 11 #ifndef UPnpCDSVIDEO_H_ 12 12 #define UPnpCDSVIDEO_H_ 13 13 14 #include "mainserver.h" 14 15 #include "upnpcds.h" 15 16 16 17 typedef QMap<int, QString> IntMap; 17 18 18 19 ////////////////////////////////////////////////////////////////////////////// … … 31 32 32 33 protected: 33 34 34 virtual UPnpCDSExtensionResults *ProcessItem( UPnpCDSRequest *pRequest,35 UPnpCDSExtensionResults *pResults,36 QStringList &idPath );37 38 virtual void CreateItems ( UPnpCDSRequest *pRequest,39 UPnpCDSExtensionResults *pResults,40 int nNodeIdx,41 const QString &sKey,42 bool bAddRef );43 44 35 virtual bool IsBrowseRequestForUs( UPnpCDSRequest *pRequest ); 45 36 virtual bool IsSearchRequestForUs( UPnpCDSRequest *pRequest ); 46 37 … … 51 42 virtual QString GetTableName ( QString sColumn ); 52 43 virtual QString GetItemListSQL( QString sColumn = ""); 53 44 54 virtual void BuildItemQuery( MSqlQuery &query, 45 virtual void BuildItemQuery( MSqlQuery &query, 55 46 const QStringMap &mapParams ); 56 47 57 58 48 virtual void AddItem( const UPnpCDSRequest *pRequest, 59 49 const QString &sObjectId, 60 50 UPnpCDSExtensionResults *pResults, 61 bool bAddRef, 51 bool bAddRef, 62 52 MSqlQuery &query ); 63 53 64 54 public: -
programs/mythbackend/upnpmedia.h
1 #ifndef UPnpMEDIA_H_2 #define UPnpMEDIA_H_3 4 #include <QString>5 6 #include "upnputil.h" // for QStringMap7 8 #define STARTING_VIDEO_OBJECTID 1000009 10 //////////////////////////////////////////////////////////////////////////////11 //12 //////////////////////////////////////////////////////////////////////////////13 14 class MSqlQuery;15 class UPnpMedia16 {17 private:18 QStringMap m_mapTitleNames;19 QStringMap m_mapCoverArt;20 //QString sMediaType;21 22 void FillMetaMaps(void);23 int GetBaseCount(void);24 QString GetTitleName(QString fPath, QString fName);25 QString GetCoverArt(QString fPath);26 27 int buildFileList(QString directory, int rootID, int itemID,28 MSqlQuery &query);29 30 void RunRebuildLoop(void);31 static void *doUPnpMediaThread(void *param);32 33 public:34 UPnpMedia(bool runthread, bool master);35 ~UPnpMedia() {};36 37 void SetMediaType(QString mediatype) { sMediaType = mediatype; }38 39 void BuildMediaMap(void);40 QString sMediaType;41 };42 43 #endif -
programs/mythbackend/upnpcdsvideo.cpp
1 1 // Program Name: upnpcdsvideo.cpp 2 // 2 // 3 3 // Purpose - uPnp Content Directory Extension for MythVideo Videos 4 // 4 // 5 5 ////////////////////////////////////////////////////////////////////////////// 6 6 7 7 // POSIX headers … … 13 13 // MythTV headers 14 14 #include "upnpcdsvideo.h" 15 15 #include "httprequest.h" 16 #include "upnpmedia.h"17 16 #include "util.h" 18 17 #include "mythcorecontext.h" 18 #include "storagegroup.h" 19 19 20 20 #define LOC QString("UPnpCDSVideo: ") 21 21 #define LOC_WARN QString("UPnpCDSVideo, Warning: ") 22 22 #define LOC_ERR QString("UPnpCDSVideo, Error: ") 23 23 24 UPnpCDSRootInfo UPnpCDSVideo::g_RootNodes[] = 24 UPnpCDSRootInfo UPnpCDSVideo::g_RootNodes[] = 25 25 { 26 { " VideoRoot",26 { "All Videos", 27 27 "*", 28 28 "SELECT 0 as key, " 29 29 "title as name, " 30 30 "1 as children " 31 "FROM upnpmedia "31 "FROM videometadata " 32 32 "%1 " 33 33 "ORDER BY title", 34 34 "" } … … 47 47 UPnpCDSRootInfo *UPnpCDSVideo::GetRootInfo( int nIdx ) 48 48 { 49 49 if ((nIdx >=0 ) && ( nIdx < g_nRootCount )) 50 return &(g_RootNodes[ nIdx ]); 50 return &(g_RootNodes[ nIdx ]); 51 51 52 52 return NULL; 53 53 } … … 67 67 68 68 QString UPnpCDSVideo::GetTableName( QString sColumn ) 69 69 { 70 return " upnpmedia";70 return "videometadata"; 71 71 } 72 72 73 73 ///////////////////////////////////////////////////////////////////////////// … … 76 76 77 77 QString UPnpCDSVideo::GetItemListSQL( QString sColumn ) 78 78 { 79 return "SELECT intid, title, filepath, " \ 80 "itemtype, itemproperties, parentid, "\ 81 "coverart FROM upnpmedia WHERE class = 'VIDEO'"; 79 return "SELECT intid, title, filename, director, plot, " 80 "rating, year, userrating, length, " 81 "season, episode, coverfile, insertdate, host FROM videometadata"; 82 82 83 } 83 84 84 85 ///////////////////////////////////////////////////////////////////////////// … … 89 90 { 90 91 int nVideoID = mapParams[ "Id" ].toInt(); 91 92 92 QString sSQL = QString( " %1 AND intid=:VIDEOID ORDER BY title DESC" )93 QString sSQL = QString( "WHERE %1 AND intid=:VIDEOID ORDER BY title DESC" ) 93 94 .arg( GetItemListSQL( ) ); 94 95 95 96 query.prepare( sSQL ); … … 213 214 214 215 MSqlQuery query(MSqlQuery::InitCon()); 215 216 216 query.prepare("SELECT COUNT(*) FROM upnpmedia WHERE class = 'VIDEO' " 217 "AND parentid = :ROOTID"); 217 query.prepare("SELECT COUNT(*) FROM videometadata"); 218 218 219 query.bindValue(":ROOTID", STARTING_VIDEO_OBJECTID);220 221 219 if (query.exec() && query.next()) 222 220 { 223 221 nCount = query.value(0).toInt(); … … 226 224 return nCount; 227 225 } 228 226 227 229 228 ///////////////////////////////////////////////////////////////////////////// 230 229 // 231 230 ///////////////////////////////////////////////////////////////////////////// 232 231 233 UPnpCDSExtensionResults *UPnpCDSVideo::ProcessItem( UPnpCDSRequest *pRequest, 234 UPnpCDSExtensionResults *pResults, 235 QStringList &idPath ) 232 void UPnpCDSVideo::AddItem( const UPnpCDSRequest *pRequest, 233 const QString &sObjectId, 234 UPnpCDSExtensionResults *pResults, 235 bool bAddRef, 236 MSqlQuery &query ) 236 237 { 237 pResults->m_nTotalMatches = 0;238 pResults->m_nUpdateID = 1;239 238 240 if (pRequest->m_sObjectId.length() == 0) 241 return pResults; 239 int nVidID = query.value( 0).toInt(); 240 QString sTitle = query.value( 1).toString(); 241 QString sFilePath = query.value( 2).toString(); 242 QString sDirector = query.value( 3).toString(); 243 QString sPlot = query.value( 4).toString(); 244 QString sRating = query.value( 5).toString(); 245 // int nYear = query.value( 6).toInt(); 246 // int nUserRating = query.value( 7).toInt(); 247 int nLength = query.value( 8).toInt(); 248 // int nSeason = query.value( 9).toInt(); 249 // int nEpisode = query.value(10).toInt(); 250 QString sCoverArt = query.value(11).toString(); 251 QDateTime dtInsertDate = query.value(12).toDateTime(); 252 QString sHostName = query.value(13).toString(); 242 253 243 QStringList tokens = pRequest->m_sObjectId 244 .split('/', QString::SkipEmptyParts); 245 QString sId = tokens.last(); 254 // VERBOSE(VB_UPNP,QString("ID = %1, Title = %2, fname = %3 sObjectId = %4").arg(nVidID).arg(sTitle).arg(sFilePath).arg(sObjectId)); 246 255 247 if (sId.startsWith("Id")) 248 sId = sId.right( sId.length() - 2); 256 // ---------------------------------------------------------------------- 257 // Cache Host ip Address & Port 258 // ---------------------------------------------------------------------- 249 259 250 switch( pRequest->m_eBrowseFlag ) 260 // If the host-name is empty then we assume it is our local host 261 // otherwise, we look up the host's IP address and port. When the 262 // client then trys to play the video it will be directed to the 263 // host which actually has the content. 264 if (!m_mapBackendIp.contains( sHostName )) 251 265 { 252 case CDS_BrowseMetadata:266 if (sHostName.isEmpty()) 253 267 { 254 // -------------------------------------------------------------- 255 // Return 1 Item 256 // -------------------------------------------------------------- 257 258 QStringMap mapParams; 259 260 mapParams.insert( "Id", sId ); 261 262 MSqlQuery query(MSqlQuery::InitCon()); 263 264 if (query.isConnected()) 265 { 266 BuildItemQuery( query, mapParams ); 267 268 if (query.exec() && query.next()) 269 { 270 AddItem( pRequest, pRequest->m_sParentId, pResults, false, query ); 271 pResults->m_nTotalMatches = 1; 272 } 273 } 274 275 break; 268 m_mapBackendIp[ sHostName ] = gCoreContext->GetSetting( "BackendServerIP" ); 276 269 } 277 278 case CDS_BrowseDirectChildren: 279 { 280 pRequest->m_sParentId = sId; 281 282 CreateItems( pRequest, pResults, 0, "", false ); 283 284 break; 285 } 270 else 271 { 272 m_mapBackendIp[ sHostName ] = gCoreContext->GetSettingOnHost( "BackendServerIp", sHostName); 273 } 286 274 } 287 275 288 return pResults; 289 } 290 291 ///////////////////////////////////////////////////////////////////////////// 292 // 293 ///////////////////////////////////////////////////////////////////////////// 294 295 void UPnpCDSVideo::CreateItems( UPnpCDSRequest *pRequest, 296 UPnpCDSExtensionResults *pResults, 297 int nNodeIdx, 298 const QString &sKey, 299 bool bAddRef ) 300 { 301 pResults->m_nTotalMatches = 0; 302 pResults->m_nUpdateID = 1; 303 304 UPnpCDSRootInfo *pInfo = GetRootInfo( nNodeIdx ); 305 306 if (pInfo == NULL) 307 return; 308 309 if (pRequest->m_nRequestedCount == 0) 310 pRequest->m_nRequestedCount = SHRT_MAX; 311 312 MSqlQuery query(MSqlQuery::InitCon()); 313 314 if (query.isConnected()) 276 if (!m_mapBackendPort.contains( sHostName )) 315 277 { 316 QString ParentClause; 317 QString sWhere; 318 319 if ( sKey.length() > 0) 278 if (sHostName.isEmpty()) 320 279 { 321 sWhere = QString( "WHERE %1=:KEY " ) 322 .arg( pInfo->column ); 280 m_mapBackendPort[ sHostName ] = gCoreContext->GetSetting( "BackendStatusPort" ); 323 281 } 324 325 if (pRequest->m_sObjectId.startsWith("Videos"))326 {327 if (!pRequest->m_sParentId.isEmpty())328 {329 if (pRequest->m_sParentId == "Videos/0")330 {331 pRequest->m_sParentId = QString("%1")332 .arg(STARTING_VIDEO_OBJECTID);333 }334 }335 else336 {337 QStringList tokens =338 pRequest->m_sObjectId.split('=', QString::SkipEmptyParts);339 pRequest->m_sParentId = tokens.last();340 }341 342 if (pRequest->m_sSearchClass.isEmpty())343 ParentClause = " AND parentid = \"" + pRequest->m_sParentId + "\"";344 else345 pRequest->m_sParentId = '8';346 347 if (pRequest->m_sObjectId.startsWith("Videos/0"))348 {349 pRequest->m_sObjectId = "Videos/0";350 }351 352 /*353 VERBOSE(VB_UPNP, QString("pRequest->m_sParentId=:%1: , "354 "pRequest->m_sObjectId=:%2:, sKey=:%3:")355 .arg(pRequest->m_sParentId)356 .arg(pRequest->m_sObjectId)357 .arg(sKey));358 */359 360 if ((!pRequest->m_sParentId.isEmpty()) && (pRequest->m_sParentId != "8"))361 pResults->m_nTotalMatches = GetCount( "parentid", pRequest->m_sParentId );362 }363 282 else 364 VERBOSE( VB_UPNP, QString( "UPnpCDSVideo::CreateItems: ******* ParentID Does NOT Start with 'Videos' ParentId = {0}" )365 .arg( pRequest->m_sParentId ));366 367 QString sSQL = QString( "%1 %2 LIMIT %3, %4" )368 .arg( GetItemListSQL( pInfo->column ) )369 .arg( sWhere + ParentClause )370 .arg( pRequest->m_nStartingIndex )371 .arg( pRequest->m_nRequestedCount );372 373 query.prepare ( sSQL );374 //VERBOSE(VB_UPNP, QString("sSQL = %1").arg(sSQL));375 if ( sKey.length() )376 query.bindValue(":KEY", sKey );377 378 if (query.exec())379 283 { 380 while(query.next()) 381 AddItem( pRequest, pRequest->m_sObjectId, pResults, bAddRef, query ); 382 284 m_mapBackendPort[ sHostName ] = gCoreContext->GetSettingOnHost("BackendStatusPort", sHostName); 383 285 } 384 286 } 385 } 386 387 ///////////////////////////////////////////////////////////////////////////// 388 // 389 ///////////////////////////////////////////////////////////////////////////// 390 391 void UPnpCDSVideo::AddItem( const UPnpCDSRequest *pRequest, 392 const QString &sObjectId, 393 UPnpCDSExtensionResults *pResults, 394 bool bAddRef, 395 MSqlQuery &query ) 396 { 397 int nVidID = query.value( 0).toInt(); 398 QString sTitle = query.value( 1).toString(); 399 QString sFileName = query.value( 2).toString(); 400 QString sItemType = query.value( 3).toString(); 401 QString sParentID = query.value( 5).toString(); 402 QString sCoverArt = query.value( 6).toString(); 403 404 // VERBOSE(VB_UPNP,QString("ID = %1, Title = %2, fname = %3 sObjectId = %4").arg(nVidID).arg(sTitle).arg(sFileName).arg(sObjectId)); 405 287 288 406 289 // ---------------------------------------------------------------------- 407 // Cache Host ip Address & Port408 // ----------------------------------------------------------------------409 QString sServerIp = gCoreContext->GetSetting("BackendServerIp" );410 QString sPort = gCoreContext->GetSetting("BackendStatusPort" );411 412 // ----------------------------------------------------------------------413 290 // Build Support Strings 414 291 // ---------------------------------------------------------------------- 415 292 416 293 QString sName = sTitle; 417 294 418 419 .arg( sServerIp )420 .arg( sPort);295 QString sURIBase = QString( "http://%1:%2/Myth/" ) 296 .arg( m_mapBackendIp [ sHostName ] ) 297 .arg( m_mapBackendPort[ sHostName ] ); 421 298 422 299 QString sURIParams = QString( "/Id%1" ).arg( nVidID ); 423 300 QString sId = QString( "Videos/0/item%1").arg( sURIParams ); 424 301 425 if (sParentID == QString("%1").arg(STARTING_VIDEO_OBJECTID)) 426 { 427 sParentID = "Videos/0"; 428 } 429 else 430 { 431 sParentID = QString( "Videos/0/item/Id%1") 432 .arg( sParentID ); 433 } 302 QString sParentID = "Videos/0"; 434 303 435 304 QString sAlbumArtURI= QString( "%1GetVideoArt%2") 436 305 .arg( sURIBase ) 437 306 .arg( sURIParams ); 438 307 439 CDSObject *pItem = NULL;308 CDSObject *pItem = CDSObject::CreateVideoItem( sId, sName, sParentID ); 440 309 441 if (sItemType == "FOLDER")442 {443 pItem = CDSObject::CreateStorageFolder( sId, sName, sParentID);444 pItem->SetChildCount( GetCount( "parentid",QString( "%1" ).arg( nVidID )) );445 446 pItem->SetPropValue( "storageUsed", "0" ); //-=>TODO: need proper value447 }448 else if (sItemType == "FILE" )449 pItem = CDSObject::CreateVideoItem( sId, sName, sParentID );450 451 if (!pItem)452 {453 VERBOSE(VB_IMPORTANT, LOC_ERR + "AddItem(): " +454 QString("sItemType has unknown type '%1'").arg(sItemType));455 456 return;457 }458 459 310 pItem->m_bRestricted = false; 460 311 pItem->m_bSearchable = true; 461 312 pItem->m_sWriteStatus = "WRITABLE"; 462 313 463 pItem->SetPropValue( "genre" , "[Unknown Genre]" ); 314 pItem->SetPropValue( "longDescription", sPlot ); 315 // ?? pItem->SetPropValue( "description" , sTitle ); 316 pItem->SetPropValue( "director" , sDirector ); 317 318 pItem->SetPropValue( "genre" , "[Unknown Genre]" ); 464 319 pItem->SetPropValue( "actor" , "[Unknown Author]" ); 465 320 pItem->SetPropValue( "creator" , "[Unknown Author]" ); 466 321 pItem->SetPropValue( "album" , "[Unknown Series]" ); 467 322 468 if ((!sCoverArt.isEmpty()) && (sCoverArt != "No Cover")) 323 //pItem->SetPropValue( "producer" , ); 324 //pItem->SetPropValue( "rating" , ); 325 //pItem->SetPropValue( "actor" , ); 326 //pItem->SetPropValue( "publisher" , ); 327 //pItem->SetPropValue( "language" , ); 328 //pItem->SetPropValue( "relation" , ); 329 //pItem->SetPropValue( "region" , ); 330 331 if ((sCoverArt != "") && (sCoverArt != "No Cover")) 469 332 pItem->SetPropValue( "albumArtURI" , sAlbumArtURI); 470 333 471 334 if ( bAddRef ) … … 476 339 pItem->SetPropValue( "refID", sRefId ); 477 340 } 478 341 479 QFileInfo fInfo( sFileName ); 480 QDateTime fDate = fInfo.lastModified(); 342 QString sFullFileName = sFilePath; 343 if (!QFile::exists( sFullFileName )) 344 { 345 StorageGroup sgroup("Videos"); 346 sFullFileName = sgroup.FindRecordingFile( sFullFileName ); 347 } 348 QFileInfo fInfo( sFullFileName ); 481 349 482 pItem->SetPropValue( "date", fDate.toString( "yyyy-MM-dd"));350 pItem->SetPropValue( "date", dtInsertDate.toString( "yyyy-MM-dd")); 483 351 pResults->Add( pItem ); 484 352 485 353 // ---------------------------------------------------------------------- … … 496 364 Resource *pRes = pItem->AddResource( sProtocol, sURI ); 497 365 498 366 pRes->AddAttribute( "size" , QString("%1").arg(fInfo.size()) ); 499 pRes->AddAttribute( "duration" , "0:01:00.000" );500 367 501 } 368 QString sDur; 369 sDur.sprintf("%02d:%02d:00", 370 (nLength / 60), nLength % 60 ); 502 371 503 // vim:ts=4:sw=4:ai:et:si:sts=4 372 pRes->AddAttribute( "duration" , sDur ); 373 } -
programs/mythbackend/main_helpers.cpp
306 306 log_rotate(0); 307 307 } 308 308 309 void upnp_rebuild(int)310 {311 if (gCoreContext->IsMasterHost())312 {313 g_pUPnp->RebuildMediaMap();314 }315 316 }317 318 309 void showUsage(const MythCommandLineParser &cmdlineparser, const QString &version) 319 310 { 320 311 QString help = cmdlineparser.GetHelpString(false); … … 433 424 434 425 if (cmdline.WantUPnPRebuild()) 435 426 { 436 VERBOSE(VB_GENERAL, "Rebuilding UPNP Media Map ");427 VERBOSE(VB_GENERAL, "Rebuilding UPNP Media Map is no longer supported"); 437 428 438 UPnpMedia *rebuildit = new UPnpMedia(false,false);439 rebuildit->BuildMediaMap();440 441 429 return BACKEND_EXIT_OK; 442 430 } 443 431 … … 768 756 pHS->RegisterExtension(httpStatus); 769 757 } 770 758 771 if (ismaster)772 {773 // kill -USR1 mythbackendpid will force a upnpmedia rebuild774 signal(SIGUSR1, &upnp_rebuild);775 }776 777 759 VERBOSE(VB_IMPORTANT, QString("Enabled verbose msgs: %1") 778 760 .arg(verboseString)); 779 761 -
programs/mythbackend/mythbackend.pro
21 21 HEADERS += autoexpire.h encoderlink.h filetransfer.h httpstatus.h mainserver.h 22 22 HEADERS += playbacksock.h scheduler.h server.h housekeeper.h backendutil.h 23 23 HEADERS += upnpcdstv.h upnpcdsmusic.h upnpcdsvideo.h mediaserver.h 24 HEADERS += mythxml.h upnpmedia.hmain_helpers.h backendcontext.h24 HEADERS += mythxml.h main_helpers.h backendcontext.h 25 25 26 26 SOURCES += autoexpire.cpp encoderlink.cpp filetransfer.cpp httpstatus.cpp 27 27 SOURCES += main.cpp mainserver.cpp playbacksock.cpp scheduler.cpp server.cpp 28 28 SOURCES += housekeeper.cpp backendutil.cpp 29 29 SOURCES += upnpcdstv.cpp upnpcdsmusic.cpp upnpcdsvideo.cpp mediaserver.cpp 30 SOURCES += mythxml.cpp upnpmedia.cppmain_helpers.cpp backendcontext.cpp30 SOURCES += mythxml.cpp main_helpers.cpp backendcontext.cpp 31 31 32 32 using_oss:DEFINES += USING_OSS 33 33 -
programs/mythbackend/mediaserver.h
17 17 #include "upnpcds.h" 18 18 #include "upnpcmgr.h" 19 19 #include "upnpmsrr.h" 20 #include "upnpmedia.h"21 20 22 21 ////////////////////////////////////////////////////////////////////////////// 23 22 ////////////////////////////////////////////////////////////////////////////// … … 34 33 35 34 UPnpCDS *m_pUPnpCDS; // Do not delete (auto deleted) 36 35 UPnpCMGR *m_pUPnpCMGR; // Do not delete (auto deleted) 37 UPnpMedia *upnpMedia;38 36 39 37 QString m_sSharePath; 40 38 … … 43 41 44 42 virtual ~MediaServer(); 45 43 46 void RebuildMediaMap(void) { upnpMedia->BuildMediaMap(); };47 48 44 void RegisterExtension ( UPnpCDSExtension *pExtension ); 49 45 void UnregisterExtension( UPnpCDSExtension *pExtension ); 50 46 -
programs/mythbackend/upnpmedia.cpp
1 #include <limits.h>2 #include <unistd.h>3 4 #include <cstdlib>5 6 #include <QFileInfo>7 #include <QDir>8 9 #include "mythcorecontext.h"10 #include "httprequest.h"11 #include "upnpmedia.h"12 #include "mythdb.h"13 #include "util.h"14 #include "pthread.h"15 16 #define LOC QString("UPnpMedia: ")17 18 /////////////////////////////////////////////////////////////////////////////19 //20 /////////////////////////////////////////////////////////////////////////////21 22 UPnpMedia::UPnpMedia(bool runthread, bool ismaster)23 {24 25 if (gCoreContext->GetNumSetting("UPnP/RebuildDelay",30) > 0)26 {27 VERBOSE(VB_GENERAL,"Enabling Upnpmedia rebuild thread.");28 if ((runthread) && (ismaster))29 {30 pthread_t upnpmediathread;31 pthread_create(&upnpmediathread, NULL, doUPnpMediaThread, this);32 }33 }34 else35 {36 VERBOSE(VB_GENERAL,"Upnpmedia rebuild disabled.");37 }38 39 }40 41 void UPnpMedia::RunRebuildLoop(void)42 {43 44 // Sleep a few seconds to wait for other stuff to settle down.45 sleep(10);46 47 int irebuildDelay = 1800;48 49 irebuildDelay = gCoreContext->GetNumSetting("UPnP/RebuildDelay",30) * 60;50 51 if (irebuildDelay < 60)52 irebuildDelay = 60;53 54 while (1)55 {56 //VERBOSE(VB_UPNP, "UPnpMedia::RunRebuildLoop Calling BuildMediaMap");57 BuildMediaMap();58 59 sleep(irebuildDelay + (random()%8));60 }61 }62 63 void *UPnpMedia::doUPnpMediaThread(void *param)64 {65 UPnpMedia *upnpmedia = static_cast<UPnpMedia*>(param);66 upnpmedia->RunRebuildLoop();67 68 return NULL;69 }70 71 QString UPnpMedia::GetTitleName(QString fPath, QString fName)72 {73 if (!m_mapTitleNames[fPath].isNull())74 {75 return m_mapTitleNames[fPath];76 }77 else78 return fName;79 }80 81 QString UPnpMedia::GetCoverArt(QString fPath)82 {83 if (!m_mapCoverArt[fPath].isNull())84 {85 return m_mapCoverArt[fPath];86 }87 else88 return "";89 }90 91 /////////////////////////////////////////////////////////////////////////////92 //93 /////////////////////////////////////////////////////////////////////////////94 95 // this should dynamically generate the SQL query and such96 void UPnpMedia::FillMetaMaps(void)97 {98 MSqlQuery query(MSqlQuery::InitCon());99 100 QString sSQL = "SELECT filename, title, coverfile FROM videometadata";101 102 query.prepare ( sSQL );103 104 if (query.exec() && query.size() > 0)105 {106 while(query.next())107 {108 m_mapTitleNames[query.value(0).toString()] = query.value(1)109 .toString();110 m_mapCoverArt[query.value(0).toString()] = query.value(2)111 .toString();112 }113 }114 115 }116 117 118 int UPnpMedia::buildFileList(QString directory, int rootID, int itemID, MSqlQuery &query)119 {120 121 int parentid;122 QDir vidDir(directory);123 //VERBOSE(VB_UPNP, QString("buildFileList = %1, rootID = %2, itemID =124 //%3").arg(directory).arg(rootID).arg(itemID));125 126 if (rootID > 0)127 parentid = rootID;128 else129 parentid = itemID;130 131 vidDir.setSorting( QDir::DirsFirst | QDir::Name );132 QFileInfoList List = vidDir.entryInfoList();133 // If we can't read it's contents move on134 if (List.isEmpty())135 return itemID;136 137 for (QFileInfoList::iterator it = List.begin(); it != List.end(); ++it)138 {139 QFileInfo Info(*it);140 QString fName = Info.fileName();141 QString fPath = Info.filePath();142 143 if (fName == "." ||144 fName == "..")145 {146 continue;147 }148 149 if (Info.isDir())150 {151 itemID++;152 153 query.prepare("INSERT INTO upnpmedia "154 "(intid, class, itemtype, parentid, itemproperties, "155 "filepath, filename, title, coverart) "156 "VALUES (:ITEMID, :ITEMCLASS, 'FOLDER', :PARENTID, '', "157 ":FILEPATH, :FILENAME, :TITLE, :COVERART)");158 159 query.bindValue(":ITEMCLASS", sMediaType);160 query.bindValue(":ITEMID", itemID);161 query.bindValue(":PARENTID", parentid);162 query.bindValue(":FILEPATH", fPath);163 query.bindValue(":FILENAME", fName);164 165 query.bindValue(":TITLE", GetTitleName(fPath,fName));166 query.bindValue(":COVERART", GetCoverArt(fPath));167 168 if (!query.exec())169 MythDB::DBError("UPnpMedia::buildFileList", query);170 171 itemID = buildFileList(Info.filePath(), 0, itemID, query);172 continue;173 174 }175 else176 {177 /*178 if (handler->validextensions.count() > 0)179 {180 QRegExp r;181 182 r.setPattern("^" + Info.suffix() + "$");183 r.setCaseSensitive(false);184 QStringList result = handler->validextensions.grep(r);185 if (result.isEmpty()) {186 continue;187 }188 }189 */190 191 itemID++;192 193 // VERBOSE(VB_UPNP, QString("UPnpMedia Video File : (%1) (%2)")194 // .arg(itemID)195 // .arg(fName));196 197 query.prepare("INSERT INTO upnpmedia "198 "(intid, class, itemtype, parentid, itemproperties, "199 "filepath, filename, title, coverart) "200 "VALUES (:ITEMID, :ITEMCLASS, 'FILE', :PARENTID, '', "201 ":FILEPATH, :FILENAME, :TITLE, :COVERART)");202 203 query.bindValue(":ITEMCLASS", sMediaType);204 query.bindValue(":ITEMID", itemID);205 query.bindValue(":PARENTID", parentid);206 query.bindValue(":FILEPATH", fPath);207 query.bindValue(":FILENAME", fName);208 209 query.bindValue(":TITLE", GetTitleName(fPath,fName));210 query.bindValue(":COVERART", GetCoverArt(fPath));211 212 if (!query.exec())213 MythDB::DBError("UPnpMedia::buildFileList", query);214 215 }216 }217 218 return itemID;219 }220 221 void UPnpMedia::BuildMediaMap(void)222 {223 MSqlQuery query(MSqlQuery::InitCon());224 225 // For now this class only does the video stuff, but eventually other media too226 sMediaType = "VIDEO";227 228 if (sMediaType == "VIDEO")229 {230 QString RootVidDir = gCoreContext->GetSetting("VideoStartupDir");231 232 if (!RootVidDir.isEmpty())233 {234 235 FillMetaMaps();236 237 query.prepare("DELETE FROM upnpmedia WHERE class = :ITEMCLASS");238 query.bindValue(":ITEMCLASS", sMediaType);239 if (!query.exec())240 {241 MythDB::DBError("BuildMediaMap -- clearing table upnpmedia", query);242 VERBOSE(VB_IMPORTANT, LOC + "BuildMediaMap - aborting");243 return;244 }245 246 if (!query.exec("LOCK TABLES upnpmedia WRITE"))247 MythDB::DBError("BuildMediaMap -- lock tables", query);248 249 VERBOSE(VB_UPNP, LOC + QString("VideoStartupDir = %1")250 .arg(RootVidDir));251 252 QStringList parts = RootVidDir.split(':', QString::SkipEmptyParts);253 254 int nextID = STARTING_VIDEO_OBJECTID;255 256 for ( QStringList::Iterator it = parts.begin(); it != parts.end();257 ++it )258 {259 int filecount = nextID;260 261 VERBOSE(VB_GENERAL, LOC + QString("BuildMediaMap %1 scan "262 "starting in :%2:")263 .arg(sMediaType)264 .arg(*it));265 266 nextID = buildFileList(*it,STARTING_VIDEO_OBJECTID, nextID,267 query);268 269 if (!gCoreContext->GetSetting("UPnP/RecordingsUnderVideos").isEmpty())270 {271 VERBOSE(VB_ALL, "uPnP Unspecified error line 275, "272 "upnpmedia.cpp");273 // nextID = buildRecordingList(*it,STARTING_VIDEO_OBJECTID,274 // nextID,query);275 }276 277 filecount = (filecount - nextID) * -1;278 279 VERBOSE(VB_GENERAL, LOC + QString("BuildMediaMap Done. Found "280 "%1 objects").arg(filecount));281 282 }283 284 if (!query.exec("UNLOCK TABLES"))285 MythDB::DBError("BuildMediaMap -- unlock tables", query);286 287 }288 else289 {290 VERBOSE(VB_GENERAL, LOC + "BuildMediaMap - no VideoStartupDir set, "291 " skipping scan.");292 }293 294 }295 else296 {297 VERBOSE(VB_GENERAL, LOC + QString("BuildMediaMap UNKNOWN MediaType %1 "298 ", skipping scan.").arg(sMediaType));299 }300 301 }302 303