|
MythTV
0.26-pre
|
00001 00002 // Program Name: content.cpp 00003 // Created : Mar. 7, 2011 00004 // 00005 // Copyright (c) 2011 David Blain <dblain@mythtv.org> 00006 // 00007 // This library is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU Lesser General Public 00009 // License as published by the Free Software Foundation; either 00010 // version 2.1 of the License, or at your option any later version of the LGPL. 00011 // 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 // Lesser General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU Lesser General Public 00018 // License along with this library. If not, see <http://www.gnu.org/licenses/>. 00019 // 00021 00022 #include "content.h" 00023 00024 #include <QDir> 00025 #include <QImage> 00026 #include <math.h> 00027 00028 #include <compat.h> 00029 00030 #include "mythcorecontext.h" 00031 #include "storagegroup.h" 00032 #include "programinfo.h" 00033 #include "previewgenerator.h" 00034 #include "backendutil.h" 00035 #include "httprequest.h" 00036 #include "serviceUtil.h" 00037 #include "mythmiscutil.h" 00038 #include "mythdownloadmanager.h" 00039 #include "metadataimagehelper.h" 00040 #include "videometadatalistmanager.h" 00041 #include "HLS/httplivestream.h" 00042 00044 // 00046 00047 QFileInfo Content::GetFile( const QString &sStorageGroup, 00048 const QString &sFileName ) 00049 { 00050 QString sGroup = sStorageGroup; 00051 00052 if (sGroup.isEmpty()) 00053 { 00054 LOG(VB_UPNP, LOG_WARNING, 00055 "GetFile - StorageGroup missing... using 'Default'"); 00056 sGroup = "Default"; 00057 } 00058 00059 if (sFileName.isEmpty()) 00060 { 00061 QString sMsg ( "GetFile - FileName missing." ); 00062 00063 LOG(VB_UPNP, LOG_ERR, sMsg); 00064 00065 throw sMsg; 00066 } 00067 00068 // ------------------------------------------------------------------ 00069 // Search for the filename 00070 // ------------------------------------------------------------------ 00071 00072 StorageGroup storage( sGroup ); 00073 QString sFullFileName = storage.FindFile( sFileName ); 00074 00075 if (sFullFileName.isEmpty()) 00076 { 00077 LOG(VB_UPNP, LOG_ERR, 00078 QString("GetFile - Unable to find %1.").arg(sFileName)); 00079 00080 return QFileInfo(); 00081 } 00082 00083 // ---------------------------------------------------------------------- 00084 // check to see if the file (still) exists 00085 // ---------------------------------------------------------------------- 00086 00087 if (QFile::exists( sFullFileName )) 00088 { 00089 return QFileInfo( sFullFileName ); 00090 } 00091 00092 LOG(VB_UPNP, LOG_ERR, 00093 QString("GetFile - File Does not exist %1.").arg(sFullFileName)); 00094 00095 return QFileInfo(); 00096 } 00097 00099 // 00101 00102 QFileInfo Content::GetImageFile( const QString &sStorageGroup, 00103 const QString &sFileName, 00104 int nWidth, 00105 int nHeight) 00106 { 00107 QString sGroup = sStorageGroup; 00108 00109 if (sGroup.isEmpty()) 00110 { 00111 LOG(VB_UPNP, LOG_WARNING, 00112 "GetFile - StorageGroup missing... using 'Default'"); 00113 sGroup = "Default"; 00114 } 00115 00116 if (sFileName.isEmpty()) 00117 { 00118 QString sMsg ( "GetFile - FileName missing." ); 00119 00120 LOG(VB_UPNP, LOG_ERR, sMsg); 00121 00122 throw sMsg; 00123 } 00124 00125 // ------------------------------------------------------------------ 00126 // Search for the filename 00127 // ------------------------------------------------------------------ 00128 00129 StorageGroup storage( sGroup ); 00130 QString sFullFileName = storage.FindFile( sFileName ); 00131 00132 if (sFullFileName.isEmpty()) 00133 { 00134 LOG(VB_UPNP, LOG_ERR, 00135 QString("GetImageFile - Unable to find %1.").arg(sFileName)); 00136 00137 return QFileInfo(); 00138 } 00139 00140 // ---------------------------------------------------------------------- 00141 // check to see if the file (still) exists 00142 // ---------------------------------------------------------------------- 00143 00144 if ((nWidth == 0) && (nHeight == 0)) 00145 { 00146 if (QFile::exists( sFullFileName )) 00147 { 00148 return QFileInfo( sFullFileName ); 00149 } 00150 00151 LOG(VB_UPNP, LOG_ERR, 00152 QString("GetImageFile - File Does not exist %1.").arg(sFullFileName)); 00153 00154 return QFileInfo(); 00155 } 00156 00157 QString sNewFileName = QString( "%1.%2x%3.jpg" ) 00158 .arg( sFullFileName ) 00159 .arg( nWidth ) 00160 .arg( nHeight ); 00161 00162 // ---------------------------------------------------------------------- 00163 // check to see if image is already created. 00164 // ---------------------------------------------------------------------- 00165 00166 if (QFile::exists( sNewFileName )) 00167 return QFileInfo( sNewFileName ); 00168 00169 // ---------------------------------------------------------------------- 00170 // Must generate Generate Image and save. 00171 // ---------------------------------------------------------------------- 00172 00173 float fAspect = 0.0; 00174 00175 QImage *pImage = new QImage( sFullFileName); 00176 00177 if (!pImage) 00178 return QFileInfo(); 00179 00180 if (fAspect <= 0) 00181 fAspect = (float)(pImage->width()) / pImage->height(); 00182 00183 if ( nWidth == 0 ) 00184 nWidth = (int)rint(nHeight * fAspect); 00185 00186 if ( nHeight == 0 ) 00187 nHeight = (int)rint(nWidth / fAspect); 00188 00189 QImage img = pImage->scaled( nWidth, nHeight, Qt::IgnoreAspectRatio, 00190 Qt::SmoothTransformation); 00191 00192 QByteArray fname = sNewFileName.toAscii(); 00193 img.save( fname.constData(), "JPG", 60 ); 00194 00195 delete pImage; 00196 00197 return QFileInfo( sNewFileName ); 00198 } 00199 00201 // 00203 00204 QStringList Content::GetFileList( const QString &sStorageGroup ) 00205 { 00206 00207 if (sStorageGroup.isEmpty()) 00208 { 00209 QString sMsg( "GetFileList - StorageGroup missing."); 00210 LOG(VB_UPNP, LOG_ERR, sMsg); 00211 00212 throw sMsg; 00213 } 00214 00215 StorageGroup sgroup(sStorageGroup); 00216 00217 return sgroup.GetFileList("", true); 00218 } 00219 00221 // 00223 00224 QFileInfo Content::GetRecordingArtwork ( const QString &sType, 00225 const QString &sInetref, 00226 int nSeason, 00227 int nWidth, 00228 int nHeight) 00229 { 00230 ArtworkMap map = GetArtwork(sInetref, nSeason); 00231 00232 VideoArtworkType type = kArtworkCoverart; 00233 QString sgroup; 00234 00235 if (sType.toLower() == "coverart") 00236 { 00237 sgroup = "Coverart"; 00238 type = kArtworkCoverart; 00239 } 00240 else if (sType.toLower() == "fanart") 00241 { 00242 sgroup = "Fanart"; 00243 type = kArtworkFanart; 00244 } 00245 else if (sType.toLower() == "banner") 00246 { 00247 sgroup = "Banners"; 00248 type = kArtworkBanner; 00249 } 00250 00251 QUrl url(map.value(type).url); 00252 QString sFileName = url.path(); 00253 00254 return GetImageFile( sgroup, sFileName, nWidth, nHeight); 00255 } 00256 00258 // 00260 00261 DTC::ArtworkInfoList* Content::GetRecordingArtworkList( int nChanId, 00262 const QDateTime &dStartTime ) 00263 { 00264 if (nChanId <= 0 || !dStartTime.isValid()) 00265 throw( QString("Channel ID or StartTime appears invalid.")); 00266 00267 ProgramInfo pInfo = ProgramInfo(nChanId, dStartTime); 00268 00269 return GetProgramArtworkList(pInfo.GetInetRef(), pInfo.GetSeason()); 00270 } 00271 00272 DTC::ArtworkInfoList* Content::GetProgramArtworkList( const QString &sInetref, 00273 int nSeason ) 00274 { 00275 DTC::ArtworkInfoList *pArtwork = new DTC::ArtworkInfoList(); 00276 00277 FillArtworkInfoList (pArtwork, sInetref, nSeason); 00278 00279 return pArtwork; 00280 } 00282 // 00284 00285 QFileInfo Content::GetVideoArtwork( const QString &sType, 00286 int nId, int nWidth, int nHeight ) 00287 { 00288 LOG(VB_UPNP, LOG_INFO, QString("GetVideoArtwork ID = %1").arg(nId)); 00289 00290 QString sgroup = "Coverart"; 00291 QString column = "coverfile"; 00292 00293 if (sType.toLower() == "coverart") 00294 { 00295 sgroup = "Coverart"; 00296 column = "coverfile"; 00297 } 00298 else if (sType.toLower() == "fanart") 00299 { 00300 sgroup = "Fanart"; 00301 column = "fanart"; 00302 } 00303 else if (sType.toLower() == "banner") 00304 { 00305 sgroup = "Banners"; 00306 column = "banner"; 00307 } 00308 else if (sType.toLower() == "screenshot") 00309 { 00310 sgroup = "Screenshots"; 00311 column = "screenshot"; 00312 } 00313 00314 // ---------------------------------------------------------------------- 00315 // Read Video artwork file path from database 00316 // ---------------------------------------------------------------------- 00317 00318 MSqlQuery query(MSqlQuery::InitCon()); 00319 00320 QString querystr = QString("SELECT %1 FROM videometadata WHERE " 00321 "intid = :ITEMID").arg(column); 00322 00323 query.prepare(querystr); 00324 query.bindValue(":ITEMID", nId); 00325 00326 if (!query.exec()) 00327 MythDB::DBError("GetVideoArtwork ", query); 00328 00329 if (!query.next()) 00330 return QFileInfo(); 00331 00332 QString sFileName = query.value(0).toString(); 00333 00334 return GetImageFile( sgroup, sFileName, nWidth, nHeight ); 00335 } 00336 00338 // 00340 00341 QFileInfo Content::GetAlbumArt( int nId, int nWidth, int nHeight ) 00342 { 00343 QString sFullFileName; 00344 00345 // ---------------------------------------------------------------------- 00346 // Read AlbumArt file path from database 00347 // ---------------------------------------------------------------------- 00348 00349 MSqlQuery query(MSqlQuery::InitCon()); 00350 00351 query.prepare("SELECT CONCAT_WS('/', music_directories.path, " 00352 "music_albumart.filename) FROM music_albumart " 00353 "LEFT JOIN music_directories ON " 00354 "music_directories.directory_id=music_albumart.directory_id " 00355 "WHERE music_albumart.albumart_id = :ARTID;"); 00356 00357 query.bindValue(":ARTID", nId ); 00358 00359 if (!query.exec()) 00360 MythDB::DBError("Select ArtId", query); 00361 00362 QString sMusicBasePath = gCoreContext->GetSetting("MusicLocation", ""); 00363 00364 if (query.next()) 00365 { 00366 sFullFileName = QString( "%1/%2" ) 00367 .arg( sMusicBasePath ) 00368 .arg( query.value(0).toString() ); 00369 } 00370 00371 if (!QFile::exists( sFullFileName )) 00372 return QFileInfo(); 00373 00374 if ((nWidth == 0) && (nHeight == 0)) 00375 return QFileInfo( sFullFileName ); 00376 00377 QString sNewFileName = QString( "%1.%2x%3.png" ) 00378 .arg( sFullFileName ) 00379 .arg( nWidth ) 00380 .arg( nHeight ); 00381 00382 // ---------------------------------------------------------------------- 00383 // check to see if albumart image is already created. 00384 // ---------------------------------------------------------------------- 00385 00386 if (QFile::exists( sNewFileName )) 00387 return QFileInfo( sNewFileName ); 00388 00389 // ---------------------------------------------------------------------- 00390 // Must generate Albumart Image, Generate Image and save. 00391 // ---------------------------------------------------------------------- 00392 00393 float fAspect = 0.0; 00394 00395 QImage *pImage = new QImage( sFullFileName); 00396 00397 if (!pImage) 00398 return QFileInfo(); 00399 00400 if (fAspect <= 0) 00401 fAspect = (float)(pImage->width()) / pImage->height(); 00402 00403 if ( nWidth == 0 ) 00404 nWidth = (int)rint(nHeight * fAspect); 00405 00406 if ( nHeight == 0 ) 00407 nHeight = (int)rint(nWidth / fAspect); 00408 00409 QImage img = pImage->scaled( nWidth, nHeight, Qt::IgnoreAspectRatio, 00410 Qt::SmoothTransformation); 00411 00412 QByteArray fname = sNewFileName.toAscii(); 00413 img.save( fname.constData(), "PNG" ); 00414 00415 delete pImage; 00416 00417 return QFileInfo( sNewFileName ); 00418 } 00419 00421 // 00423 00424 QFileInfo Content::GetPreviewImage( int nChanId, 00425 const QDateTime &dtStartTime, 00426 int nWidth, 00427 int nHeight, 00428 int nSecsIn ) 00429 { 00430 if (!dtStartTime.isValid()) 00431 { 00432 QString sMsg = QString("GetPreviewImage: bad start time '%1'") 00433 .arg( dtStartTime.toString() ); 00434 00435 LOG(VB_GENERAL, LOG_ERR, sMsg); 00436 00437 throw sMsg; 00438 } 00439 00440 // ---------------------------------------------------------------------- 00441 // Read Recording From Database 00442 // ---------------------------------------------------------------------- 00443 00444 ProgramInfo pginfo( (uint)nChanId, dtStartTime); 00445 00446 if (!pginfo.GetChanID()) 00447 { 00448 LOG(VB_GENERAL, LOG_ERR, 00449 QString( "GetPreviewImage: no recording for start time '%1'" ) 00450 .arg( dtStartTime.toString() )); 00451 return QFileInfo(); 00452 } 00453 00454 if ( pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower()) 00455 { 00456 QString sMsg = 00457 QString("GetPreviewImage: Wrong Host '%1' request from '%2'") 00458 .arg( gCoreContext->GetHostName()) 00459 .arg( pginfo.GetHostname() ); 00460 00461 LOG(VB_UPNP, LOG_ERR, sMsg); 00462 00463 throw HttpRedirectException( pginfo.GetHostname() ); 00464 } 00465 00466 QString sFileName = GetPlaybackURL(&pginfo); 00467 00468 // ---------------------------------------------------------------------- 00469 // check to see if default preview image is already created. 00470 // ---------------------------------------------------------------------- 00471 00472 QString sPreviewFileName; 00473 00474 if (nSecsIn <= 0) 00475 { 00476 nSecsIn = -1; 00477 sPreviewFileName = sFileName + ".png"; 00478 } 00479 else 00480 { 00481 sPreviewFileName = QString("%1.%2.png").arg(sFileName).arg(nSecsIn); 00482 } 00483 00484 if (!QFile::exists( sPreviewFileName )) 00485 { 00486 // ------------------------------------------------------------------ 00487 // Must generate Preview Image, Generate Image and save. 00488 // ------------------------------------------------------------------ 00489 if (!pginfo.IsLocal() && sFileName.left(1) == "/") 00490 pginfo.SetPathname(sFileName); 00491 00492 if (!pginfo.IsLocal()) 00493 return QFileInfo(); 00494 00495 PreviewGenerator *previewgen = new PreviewGenerator( &pginfo, 00496 QString(), 00497 PreviewGenerator::kLocal); 00498 previewgen->SetPreviewTimeAsSeconds( nSecsIn ); 00499 previewgen->SetOutputFilename ( sPreviewFileName ); 00500 00501 bool ok = previewgen->Run(); 00502 00503 previewgen->deleteLater(); 00504 00505 if (!ok) 00506 return QFileInfo(); 00507 } 00508 00509 float fAspect = 0.0; 00510 00511 QImage *pImage = new QImage(sPreviewFileName); 00512 00513 if (!pImage) 00514 return QFileInfo(); 00515 00516 if (fAspect <= 0) 00517 fAspect = (float)(pImage->width()) / pImage->height(); 00518 00519 if (fAspect == 0) 00520 { 00521 delete pImage; 00522 return QFileInfo(); 00523 } 00524 00525 bool bDefaultPixmap = (nWidth == 0) && (nHeight == 0); 00526 00527 if ( nWidth == 0 ) 00528 nWidth = (int)rint(nHeight * fAspect); 00529 00530 if ( nHeight == 0 ) 00531 nHeight = (int)rint(nWidth / fAspect); 00532 00533 QString sNewFileName; 00534 00535 if (bDefaultPixmap) 00536 sNewFileName = sPreviewFileName; 00537 else 00538 sNewFileName = QString( "%1.%2.%3x%4.png" ) 00539 .arg( sFileName ) 00540 .arg( nSecsIn ) 00541 .arg( nWidth ) 00542 .arg( nHeight ); 00543 00544 // ---------------------------------------------------------------------- 00545 // check to see if scaled preview image is already created. 00546 // ---------------------------------------------------------------------- 00547 00548 if (QFile::exists( sNewFileName )) 00549 { 00550 delete pImage; 00551 return QFileInfo( sNewFileName ); 00552 } 00553 00554 PreviewGenerator *previewgen = new PreviewGenerator( &pginfo, 00555 QString(), 00556 PreviewGenerator::kLocal); 00557 previewgen->SetPreviewTimeAsSeconds( nSecsIn ); 00558 previewgen->SetOutputFilename ( sNewFileName ); 00559 previewgen->SetOutputSize (QSize(nWidth,nHeight)); 00560 00561 bool ok = previewgen->Run(); 00562 00563 previewgen->deleteLater(); 00564 00565 if (!ok) 00566 return QFileInfo(); 00567 00568 delete pImage; 00569 00570 return QFileInfo( sNewFileName ); 00571 } 00572 00574 // 00576 00577 QFileInfo Content::GetRecording( int nChanId, 00578 const QDateTime &dtStartTime ) 00579 { 00580 if (!dtStartTime.isValid()) 00581 throw( "StartTime is invalid" ); 00582 00583 // ------------------------------------------------------------------ 00584 // Read Recording From Database 00585 // ------------------------------------------------------------------ 00586 00587 ProgramInfo pginfo( (uint)nChanId, dtStartTime ); 00588 00589 if (!pginfo.GetChanID()) 00590 { 00591 LOG( VB_UPNP, LOG_ERR, QString("GetRecording - for %1, %2 failed") 00592 .arg( nChanId ) 00593 .arg( dtStartTime.toString() )); 00594 return QFileInfo(); 00595 } 00596 00597 if ( pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower()) 00598 { 00599 // We only handle requests for local resources 00600 00601 QString sMsg = 00602 QString("GetRecording: Wrong Host '%1' request from '%2'.") 00603 .arg( gCoreContext->GetHostName()) 00604 .arg( pginfo.GetHostname() ); 00605 00606 LOG(VB_UPNP, LOG_ERR, sMsg); 00607 00608 throw HttpRedirectException( pginfo.GetHostname() ); 00609 } 00610 00611 QString sFileName( GetPlaybackURL(&pginfo) ); 00612 00613 // ---------------------------------------------------------------------- 00614 // check to see if the file exists 00615 // ---------------------------------------------------------------------- 00616 00617 if (QFile::exists( sFileName )) 00618 return QFileInfo( sFileName ); 00619 00620 return QFileInfo(); 00621 } 00622 00624 // 00626 00627 QFileInfo Content::GetMusic( int nId ) 00628 { 00629 QString sBasePath = gCoreContext->GetSetting( "MusicLocation", ""); 00630 QString sFileName; 00631 00632 // ---------------------------------------------------------------------- 00633 // Load Track's FileName 00634 // ---------------------------------------------------------------------- 00635 00636 MSqlQuery query(MSqlQuery::InitCon()); 00637 00638 if (query.isConnected()) 00639 { 00640 query.prepare("SELECT CONCAT_WS('/', music_directories.path, " 00641 "music_songs.filename) AS filename FROM music_songs " 00642 "LEFT JOIN music_directories ON " 00643 "music_songs.directory_id=" 00644 "music_directories.directory_id " 00645 "WHERE music_songs.song_id = :KEY"); 00646 00647 query.bindValue(":KEY", nId ); 00648 00649 if (!query.exec()) 00650 { 00651 MythDB::DBError("GetMusic()", query); 00652 return QFileInfo(); 00653 } 00654 00655 if (query.next()) 00656 { 00657 sFileName = QString( "%1/%2" ) 00658 .arg( sBasePath ) 00659 .arg( query.value(0).toString() ); 00660 } 00661 } 00662 00663 // ---------------------------------------------------------------------- 00664 // check to see if the file exists 00665 // ---------------------------------------------------------------------- 00666 00667 if (QFile::exists( sFileName )) 00668 return QFileInfo( sFileName ); 00669 00670 return QFileInfo(); 00671 } 00672 00674 // 00676 00677 QFileInfo Content::GetVideo( int nId ) 00678 { 00679 QString sFileName; 00680 00681 // ---------------------------------------------------------------------- 00682 // Load Track's FileName 00683 // ---------------------------------------------------------------------- 00684 00685 MSqlQuery query(MSqlQuery::InitCon()); 00686 00687 if (query.isConnected()) 00688 { 00689 query.prepare("SELECT filename FROM videometadata WHERE intid = :KEY" ); 00690 query.bindValue(":KEY", nId ); 00691 00692 if (!query.exec()) 00693 { 00694 MythDB::DBError("GetVideo()", query); 00695 return QFileInfo(); 00696 } 00697 00698 if (query.next()) 00699 sFileName = query.value(0).toString(); 00700 } 00701 00702 if (sFileName.isEmpty()) 00703 return QFileInfo(); 00704 00705 if (!QFile::exists( sFileName )) 00706 return GetFile( "Videos", sFileName ); 00707 00708 return QFileInfo( sFileName ); 00709 } 00710 00712 // 00714 00715 QString Content::GetHash( const QString &sStorageGroup, 00716 const QString &sFileName ) 00717 { 00718 if ((sFileName.isEmpty()) || 00719 (sFileName.contains("/../")) || 00720 (sFileName.startsWith("../"))) 00721 { 00722 LOG(VB_GENERAL, LOG_ERR, 00723 QString("ERROR checking for file, filename '%1' " 00724 "fails sanity checks").arg(sFileName)); 00725 return QString(); 00726 } 00727 00728 QString storageGroup = "Default"; 00729 00730 if (!sStorageGroup.isEmpty()) 00731 storageGroup = sStorageGroup; 00732 00733 StorageGroup sgroup(storageGroup, gCoreContext->GetHostName()); 00734 00735 QString fullname = sgroup.FindFile(sFileName); 00736 QString hash = FileHash(fullname); 00737 00738 if (hash == "NULL") 00739 return QString(); 00740 00741 return hash; 00742 } 00743 00745 // 00747 00748 bool Content::DownloadFile( const QString &sURL, const QString &sStorageGroup ) 00749 { 00750 QFileInfo finfo(sURL); 00751 QString filename = finfo.fileName(); 00752 StorageGroup sgroup(sStorageGroup, gCoreContext->GetHostName(), false); 00753 QString outDir = sgroup.FindNextDirMostFree(); 00754 QString outFile; 00755 00756 if (outDir.isEmpty()) 00757 { 00758 LOG(VB_GENERAL, LOG_ERR, 00759 QString("Unable to determine directory " 00760 "to write to in %1 write command").arg(sURL)); 00761 return false; 00762 } 00763 00764 if ((filename.contains("/../")) || 00765 (filename.startsWith("../"))) 00766 { 00767 LOG(VB_GENERAL, LOG_ERR, 00768 QString("ERROR: %1 write filename '%2' does not " 00769 "pass sanity checks.") .arg(sURL).arg(filename)); 00770 return false; 00771 } 00772 00773 outFile = outDir + "/" + filename; 00774 00775 if (GetMythDownloadManager()->download(sURL, outFile)) 00776 return true; 00777 00778 return false; 00779 } 00780 00782 // 00784 00785 DTC::LiveStreamInfo *Content::AddLiveStream( const QString &sStorageGroup, 00786 const QString &sFileName, 00787 const QString &sHostName, 00788 int nMaxSegments, 00789 int nWidth, 00790 int nHeight, 00791 int nBitrate, 00792 int nAudioBitrate, 00793 int nSampleRate ) 00794 { 00795 QString sGroup = sStorageGroup; 00796 00797 if (sGroup.isEmpty()) 00798 { 00799 LOG(VB_UPNP, LOG_WARNING, 00800 "AddLiveStream - StorageGroup missing... using 'Default'"); 00801 sGroup = "Default"; 00802 } 00803 00804 if (sFileName.isEmpty()) 00805 { 00806 QString sMsg ( "AddLiveStream - FileName missing." ); 00807 00808 LOG(VB_UPNP, LOG_ERR, sMsg); 00809 00810 throw sMsg; 00811 } 00812 00813 // ------------------------------------------------------------------ 00814 // Search for the filename 00815 // ------------------------------------------------------------------ 00816 00817 QString sFullFileName; 00818 if (sHostName.isEmpty() || sHostName == gCoreContext->GetHostName()) 00819 { 00820 StorageGroup storage( sGroup ); 00821 sFullFileName = storage.FindFile( sFileName ); 00822 00823 if (sFullFileName.isEmpty()) 00824 { 00825 LOG(VB_UPNP, LOG_ERR, 00826 QString("AddLiveStream - Unable to find %1.").arg(sFileName)); 00827 00828 return NULL; 00829 } 00830 } 00831 else 00832 { 00833 sFullFileName = 00834 gCoreContext->GenMythURL(sHostName, 0, sFileName, sStorageGroup); 00835 } 00836 00837 HTTPLiveStream *hls = new 00838 HTTPLiveStream(sFullFileName, nWidth, nHeight, nBitrate, nAudioBitrate, 00839 nMaxSegments, 10, 32000, nSampleRate); 00840 00841 if (!hls) 00842 { 00843 LOG(VB_UPNP, LOG_ERR, 00844 "AddLiveStream - Unable to create HTTPLiveStream."); 00845 return NULL; 00846 } 00847 00848 DTC::LiveStreamInfo *lsInfo = hls->StartStream(); 00849 00850 delete hls; 00851 00852 return lsInfo; 00853 } 00854 00856 // 00858 00859 bool Content::RemoveLiveStream( int nId ) 00860 { 00861 return HTTPLiveStream::RemoveStream(nId); 00862 } 00863 00865 // 00867 00868 DTC::LiveStreamInfo *Content::StopLiveStream( int nId ) 00869 { 00870 return HTTPLiveStream::StopStream(nId); 00871 } 00872 00874 // 00876 00877 DTC::LiveStreamInfo *Content::GetLiveStream( int nId ) 00878 { 00879 HTTPLiveStream *hls = new HTTPLiveStream(nId); 00880 00881 if (!hls) 00882 { 00883 LOG( VB_UPNP, LOG_ERR, 00884 QString("GetLiveStream - for stream id %1 failed").arg( nId )); 00885 return NULL; 00886 } 00887 00888 DTC::LiveStreamInfo *hlsInfo = hls->GetLiveStreamInfo(); 00889 if (!hlsInfo) 00890 { 00891 LOG( VB_UPNP, LOG_ERR, 00892 QString("HLS::GetLiveStreamInfo - for stream id %1 failed") 00893 .arg( nId )); 00894 return NULL; 00895 } 00896 00897 delete hls; 00898 return hlsInfo; 00899 } 00900 00902 // 00904 00905 DTC::LiveStreamInfoList *Content::GetLiveStreamList( void ) 00906 { 00907 return HTTPLiveStream::GetLiveStreamInfoList(); 00908 } 00909 00911 // 00913 00914 DTC::LiveStreamInfoList *Content::GetFilteredLiveStreamList( const QString &FileName ) 00915 { 00916 return HTTPLiveStream::GetLiveStreamInfoList(FileName); 00917 } 00918 00920 // 00922 00923 DTC::LiveStreamInfo *Content::AddRecordingLiveStream( int nChanId, 00924 const QDateTime &dtStartTime, 00925 int nMaxSegments, 00926 int nWidth, 00927 int nHeight, 00928 int nBitrate, 00929 int nAudioBitrate, 00930 int nSampleRate ) 00931 { 00932 if (!dtStartTime.isValid()) 00933 throw( "StartTime is invalid" ); 00934 00935 // ------------------------------------------------------------------ 00936 // Read Recording From Database 00937 // ------------------------------------------------------------------ 00938 00939 ProgramInfo pginfo( (uint)nChanId, dtStartTime ); 00940 00941 if (!pginfo.GetChanID()) 00942 { 00943 LOG( VB_UPNP, LOG_ERR, QString("AddRecordingLiveStream - for %1, %2 failed") 00944 .arg( nChanId ) 00945 .arg( dtStartTime.toString() )); 00946 return NULL; 00947 } 00948 00949 if ( pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower()) 00950 { 00951 // We only handle requests for local resources 00952 00953 QString sMsg = 00954 QString("GetRecording: Wrong Host '%1' request from '%2'.") 00955 .arg( gCoreContext->GetHostName()) 00956 .arg( pginfo.GetHostname() ); 00957 00958 LOG(VB_UPNP, LOG_ERR, sMsg); 00959 00960 throw HttpRedirectException( pginfo.GetHostname() ); 00961 } 00962 00963 QString sFileName( GetPlaybackURL(&pginfo) ); 00964 00965 // ---------------------------------------------------------------------- 00966 // check to see if the file exists 00967 // ---------------------------------------------------------------------- 00968 00969 if (!QFile::exists( sFileName )) 00970 { 00971 LOG( VB_UPNP, LOG_ERR, QString("AddRecordingLiveStream - for %1, %2 failed") 00972 .arg( nChanId ) 00973 .arg( dtStartTime.toString() )); 00974 return NULL; 00975 } 00976 00977 QFileInfo fInfo( sFileName ); 00978 00979 return AddLiveStream( pginfo.GetStorageGroup(), fInfo.fileName(), 00980 pginfo.GetHostname(), nMaxSegments, nWidth, 00981 nHeight, nBitrate, nAudioBitrate, nSampleRate ); 00982 } 00983 00985 // 00987 00988 DTC::LiveStreamInfo *Content::AddVideoLiveStream( int nId, 00989 int nMaxSegments, 00990 int nWidth, 00991 int nHeight, 00992 int nBitrate, 00993 int nAudioBitrate, 00994 int nSampleRate ) 00995 { 00996 if (nId < 0) 00997 throw( "Id is invalid" ); 00998 00999 VideoMetadataListManager::VideoMetadataPtr metadata = 01000 VideoMetadataListManager::loadOneFromDatabase(nId); 01001 01002 if (!metadata) 01003 { 01004 LOG( VB_UPNP, LOG_ERR, QString("AddVideoLiveStream - no metadata for %1") 01005 .arg( nId )); 01006 return NULL; 01007 } 01008 01009 if ( metadata->GetHost().toLower() != gCoreContext->GetHostName().toLower()) 01010 { 01011 // We only handle requests for local resources 01012 01013 QString sMsg = 01014 QString("AddVideoLiveStream: Wrong Host '%1' request from '%2'.") 01015 .arg( gCoreContext->GetHostName()) 01016 .arg( metadata->GetHost() ); 01017 01018 LOG(VB_UPNP, LOG_ERR, sMsg); 01019 01020 throw HttpRedirectException( metadata->GetHost() ); 01021 } 01022 01023 StorageGroup sg("Videos", metadata->GetHost()); 01024 QString sFileName = sg.FindFile(metadata->GetFilename()); 01025 01026 // ---------------------------------------------------------------------- 01027 // check to see if the file exists 01028 // ---------------------------------------------------------------------- 01029 01030 if (!QFile::exists( sFileName )) 01031 { 01032 LOG( VB_UPNP, LOG_ERR, QString("AddVideoLiveStream - file does not exist.")); 01033 return NULL; 01034 } 01035 01036 return AddLiveStream( "Videos", metadata->GetFilename(), 01037 metadata->GetHost(), nMaxSegments, nWidth, 01038 nHeight, nBitrate, nAudioBitrate, nSampleRate ); 01039 }
1.7.6.1