00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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
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
00164
00165
00166 if (QFile::exists( sNewFileName ))
00167 return QFileInfo( sNewFileName );
00168
00169
00170
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
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
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
00384
00385
00386 if (QFile::exists( sNewFileName ))
00387 return QFileInfo( sNewFileName );
00388
00389
00390
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }