MythTV  0.26-pre
dvr.cpp
Go to the documentation of this file.
00001 
00002 // Program Name: dvr.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 <QMap>
00023 #include <QRegExp>
00024 
00025 #include "dvr.h"
00026 
00027 #include "compat.h"
00028 #include "mythversion.h"
00029 #include "mythcorecontext.h"
00030 #include "mythevent.h"
00031 #include "scheduler.h"
00032 #include "autoexpire.h"
00033 #include "jobqueue.h"
00034 #include "encoderlink.h"
00035 #include "remoteutil.h"
00036 
00037 #include "serviceUtil.h"
00038 
00039 extern QMap<int, EncoderLink *> tvList;
00040 extern AutoExpire  *expirer;
00041 
00043 //
00045 
00046 DTC::ProgramList* Dvr::GetRecordedList( bool bDescending,
00047                                         int  nStartIndex,
00048                                         int  nCount      )
00049 {
00050     return GetFilteredRecordedList( bDescending, nStartIndex, nCount,
00051                                     QString(), QString(), QString() );
00052 }
00053 
00054 DTC::ProgramList* Dvr::GetFilteredRecordedList( bool           bDescending,
00055                                                 int            nStartIndex,
00056                                                 int            nCount,
00057                                                 const QString &sTitleRegEx,
00058                                                 const QString &sRecGroup,
00059                                                 const QString &sStorageGroup )
00060 {
00061     QMap< QString, ProgramInfo* > recMap;
00062 
00063     if (gCoreContext->GetScheduler())
00064         recMap = gCoreContext->GetScheduler()->GetRecording();
00065 
00066     QMap< QString, uint32_t > inUseMap    = ProgramInfo::QueryInUseMap();
00067     QMap< QString, bool >     isJobRunning= ProgramInfo::QueryJobsRunning(JOB_COMMFLAG);
00068 
00069     ProgramList progList;
00070 
00071     int desc = 0;
00072     if (bDescending)
00073         desc = -1;
00074 
00075     LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, desc );
00076 
00077     QMap< QString, ProgramInfo* >::iterator mit = recMap.begin();
00078 
00079     for (; mit != recMap.end(); mit = recMap.erase(mit))
00080         delete *mit;
00081 
00082     // ----------------------------------------------------------------------
00083     // Build Response
00084     // ----------------------------------------------------------------------
00085 
00086     DTC::ProgramList *pPrograms = new DTC::ProgramList();
00087     int nAvailable = 0;
00088 
00089     if ((sTitleRegEx.isEmpty()) &&
00090         (sRecGroup.isEmpty()) &&
00091         (sStorageGroup.isEmpty()))
00092     {
00093         nStartIndex   = min( nStartIndex, (int)progList.size() );
00094         nCount        = (nCount > 0) ? min( nCount, (int)progList.size() ) : progList.size();
00095         int nEndIndex = min((nStartIndex + nCount), (int)progList.size() );
00096         nCount        = nEndIndex - nStartIndex;
00097 
00098         nAvailable = progList.size();
00099 
00100         for( int n = nStartIndex; n < nEndIndex; n++)
00101         {
00102             ProgramInfo *pInfo = progList[ n ];
00103             if (pInfo->GetRecordingGroup() != "Deleted")
00104             {
00105                 DTC::Program *pProgram = pPrograms->AddNewProgram();
00106 
00107                 FillProgramInfo( pProgram, pInfo, true );
00108             }
00109         }
00110     }
00111     else
00112     {
00113         int nMax      = nCount;
00114 
00115         nAvailable = 0;
00116         nCount = 0;
00117 
00118         QRegExp rTitleRegEx        = QRegExp(sTitleRegEx, Qt::CaseInsensitive);
00119 
00120         for( unsigned int n = 0; n < progList.size(); n++)
00121         {
00122             ProgramInfo *pInfo = progList[ n ];
00123 
00124             if ((!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) ||
00125                 (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) ||
00126                 (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup()))
00127                 continue;
00128 
00129             ++nAvailable;
00130 
00131             if ((nAvailable < nStartIndex) ||
00132                 (nCount >= nMax))
00133                 continue;
00134 
00135             ++nCount;
00136 
00137             DTC::Program *pProgram = pPrograms->AddNewProgram();
00138 
00139             FillProgramInfo( pProgram, pInfo, true );
00140         }
00141     }
00142 
00143     // ----------------------------------------------------------------------
00144 
00145     pPrograms->setStartIndex    ( nStartIndex     );
00146     pPrograms->setCount         ( nCount          );
00147     pPrograms->setTotalAvailable( nAvailable      );
00148     pPrograms->setAsOf          ( QDateTime::currentDateTime() );
00149     pPrograms->setVersion       ( MYTH_BINARY_VERSION );
00150     pPrograms->setProtoVer      ( MYTH_PROTO_VERSION  );
00151 
00152     return pPrograms;
00153 }
00154 
00156 //
00158 
00159 DTC::Program* Dvr::GetRecorded( int              nChanId,
00160                                 const QDateTime &dStartTime  )
00161 {
00162     if (nChanId <= 0 || !dStartTime.isValid())
00163         throw( QString("Channel ID or StartTime appears invalid."));
00164 
00165     ProgramInfo *pInfo = new ProgramInfo(nChanId, dStartTime);
00166 
00167     DTC::Program *pProgram = new DTC::Program();
00168     FillProgramInfo( pProgram, pInfo, true );
00169 
00170     return pProgram;
00171 }
00172 
00174 //
00176 
00177 bool Dvr::RemoveRecorded( int              nChanId,
00178                           const QDateTime &dStartTime  )
00179 {
00180     if (nChanId <= 0 || !dStartTime.isValid())
00181         throw( QString("Channel ID or StartTime appears invalid."));
00182 
00183     bool bResult = false;
00184 
00185     ProgramInfo *pInfo = new ProgramInfo(nChanId, dStartTime);
00186 
00187     QString cmd = QString("DELETE_RECORDING %1 %2")
00188                 .arg(nChanId)
00189                 .arg(dStartTime.toString(Qt::ISODate));
00190     MythEvent me(cmd);
00191 
00192     if (pInfo->HasPathname())
00193     {
00194         gCoreContext->dispatch(me);
00195         bResult = true;
00196     }
00197 
00198     return bResult;
00199 }
00200 
00202 //
00204 
00205 DTC::ProgramList* Dvr::GetExpiringList( int nStartIndex, 
00206                                         int nCount      )
00207 {
00208     pginfolist_t  infoList;
00209 
00210     if (expirer)
00211         expirer->GetAllExpiring( infoList );
00212 
00213     // ----------------------------------------------------------------------
00214     // Build Response
00215     // ----------------------------------------------------------------------
00216 
00217     DTC::ProgramList *pPrograms = new DTC::ProgramList();
00218 
00219     nStartIndex   = min( nStartIndex, (int)infoList.size() );
00220     nCount        = (nCount > 0) ? min( nCount, (int)infoList.size() ) : infoList.size();
00221     int nEndIndex = min((nStartIndex + nCount), (int)infoList.size() );
00222 
00223     for( int n = nStartIndex; n < nEndIndex; n++)
00224     {
00225         ProgramInfo *pInfo = infoList[ n ];
00226 
00227         if (pInfo != NULL)
00228         {
00229             DTC::Program *pProgram = pPrograms->AddNewProgram();
00230 
00231             FillProgramInfo( pProgram, pInfo, true );
00232 
00233             delete pInfo;
00234         }
00235     }
00236 
00237     // ----------------------------------------------------------------------
00238 
00239     pPrograms->setStartIndex    ( nStartIndex     );
00240     pPrograms->setCount         ( nCount          );
00241     pPrograms->setTotalAvailable( infoList.size() );
00242     pPrograms->setAsOf          ( QDateTime::currentDateTime() );
00243     pPrograms->setVersion       ( MYTH_BINARY_VERSION );
00244     pPrograms->setProtoVer      ( MYTH_PROTO_VERSION  );
00245 
00246     return pPrograms;
00247 }
00248 
00250 //
00252 
00253 DTC::EncoderList* Dvr::GetEncoderList()
00254 {
00255     DTC::EncoderList* pList = new DTC::EncoderList();
00256 
00257     QMap<int, EncoderLink *>::Iterator iter = tvList.begin();
00258 
00259     for (; iter != tvList.end(); ++iter)
00260     {
00261         EncoderLink *elink = *iter;
00262 
00263         if (elink != NULL)
00264         {
00265             DTC::Encoder *pEncoder = pList->AddNewEncoder();
00266             
00267             pEncoder->setId            ( elink->GetCardID()       );
00268             pEncoder->setState         ( elink->GetState()        );
00269             pEncoder->setLocal         ( elink->IsLocal()         );
00270             pEncoder->setConnected     ( elink->IsConnected()     );
00271             pEncoder->setSleepStatus   ( elink->GetSleepStatus()  );
00272           //  pEncoder->setLowOnFreeSpace( elink->isLowOnFreeSpace());
00273 
00274             if (pEncoder->Local())
00275                 pEncoder->setHostName( gCoreContext->GetHostName() );
00276             else
00277                 pEncoder->setHostName( elink->GetHostName() );
00278 
00279             switch ( pEncoder->State() )
00280             {
00281                 case kState_WatchingLiveTV:
00282                 case kState_RecordingOnly:
00283                 case kState_WatchingRecording:
00284                 {
00285                     ProgramInfo  *pInfo = elink->GetRecording();
00286 
00287                     if (pInfo)
00288                     {
00289                         DTC::Program *pProgram = pEncoder->Recording();
00290 
00291                         FillProgramInfo( pProgram, pInfo, true, true );
00292 
00293                         delete pInfo;
00294                     }
00295 
00296                     break;
00297                 }
00298 
00299                 default:
00300                     break;
00301             }
00302         }
00303     }
00304     return pList;
00305 }
00306 
00308 //
00310 
00311 DTC::ProgramList* Dvr::GetUpcomingList( int  nStartIndex,
00312                                         int  nCount,
00313                                         bool bShowAll )
00314 {
00315     RecordingList  recordingList;
00316     RecordingList  tmpList;
00317     bool hasConflicts;
00318     LoadFromScheduler(tmpList, hasConflicts);
00319 
00320     // Sort the upcoming into only those which will record
00321     RecordingList::iterator it = tmpList.begin();
00322     for(; it < tmpList.end(); ++it)
00323     {
00324         if (!bShowAll && ((*it)->GetRecordingStatus() <= rsWillRecord) &&
00325             ((*it)->GetRecordingStartTime() >=
00326              QDateTime::currentDateTime()))
00327         {
00328             recordingList.push_back(new RecordingInfo(**it));
00329         }
00330         else if (bShowAll && ((*it)->GetRecordingStartTime() >=
00331              QDateTime::currentDateTime()))
00332         {
00333             recordingList.push_back(new RecordingInfo(**it));
00334         }
00335     }
00336 
00337     // ----------------------------------------------------------------------
00338     // Build Response
00339     // ----------------------------------------------------------------------
00340 
00341     DTC::ProgramList *pPrograms = new DTC::ProgramList();
00342 
00343     nStartIndex   = min( nStartIndex, (int)recordingList.size() );
00344     nCount        = (nCount > 0) ? min( nCount, (int)recordingList.size() ) : recordingList.size();
00345     int nEndIndex = min((nStartIndex + nCount), (int)recordingList.size() );
00346 
00347     for( int n = nStartIndex; n < nEndIndex; n++)
00348     {
00349         ProgramInfo *pInfo = recordingList[ n ];
00350 
00351         DTC::Program *pProgram = pPrograms->AddNewProgram();
00352 
00353         FillProgramInfo( pProgram, pInfo, true );
00354     }
00355 
00356     // ----------------------------------------------------------------------
00357 
00358     pPrograms->setStartIndex    ( nStartIndex     );
00359     pPrograms->setCount         ( nCount          );
00360     pPrograms->setTotalAvailable( recordingList.size() );
00361     pPrograms->setAsOf          ( QDateTime::currentDateTime() );
00362     pPrograms->setVersion       ( MYTH_BINARY_VERSION );
00363     pPrograms->setProtoVer      ( MYTH_PROTO_VERSION  );
00364 
00365     return pPrograms;
00366 }
00367 
00369 //
00371 
00372 DTC::ProgramList* Dvr::GetConflictList( int  nStartIndex,
00373                                         int  nCount       )
00374 {
00375     RecordingList  recordingList;
00376     RecordingList  tmpList;
00377     bool hasConflicts;
00378     LoadFromScheduler(tmpList, hasConflicts);
00379 
00380     // Sort the upcoming into only those which are conflicts
00381     RecordingList::iterator it = tmpList.begin();
00382     for(; it < tmpList.end(); ++it)
00383     {
00384         if (((*it)->GetRecordingStatus() == rsConflict) &&
00385             ((*it)->GetRecordingStartTime() >=
00386              QDateTime::currentDateTime()))
00387         {
00388             recordingList.push_back(new RecordingInfo(**it));
00389         }
00390     }
00391 
00392     // ----------------------------------------------------------------------
00393     // Build Response
00394     // ----------------------------------------------------------------------
00395 
00396     DTC::ProgramList *pPrograms = new DTC::ProgramList();
00397 
00398     nStartIndex   = min( nStartIndex, (int)recordingList.size() );
00399     nCount        = (nCount > 0) ? min( nCount, (int)recordingList.size() ) : recordingList.size();
00400     int nEndIndex = min((nStartIndex + nCount), (int)recordingList.size() );
00401 
00402     for( int n = nStartIndex; n < nEndIndex; n++)
00403     {
00404         ProgramInfo *pInfo = recordingList[ n ];
00405 
00406         DTC::Program *pProgram = pPrograms->AddNewProgram();
00407 
00408         FillProgramInfo( pProgram, pInfo, true );
00409     }
00410 
00411     // ----------------------------------------------------------------------
00412 
00413     pPrograms->setStartIndex    ( nStartIndex     );
00414     pPrograms->setCount         ( nCount          );
00415     pPrograms->setTotalAvailable( recordingList.size() );
00416     pPrograms->setAsOf          ( QDateTime::currentDateTime() );
00417     pPrograms->setVersion       ( MYTH_BINARY_VERSION );
00418     pPrograms->setProtoVer      ( MYTH_PROTO_VERSION  );
00419 
00420     return pPrograms;
00421 }
00422 
00423 int Dvr::AddRecordSchedule   ( int       nChanId,
00424                                QDateTime dStartTime,
00425                                int       nParentId,
00426                                bool      bInactive,
00427                                uint      nSeason,
00428                                uint      nEpisode,
00429                                QString   sInetref,
00430                                int       nFindId,
00431                                QString   sType,
00432                                QString   sSearchType,
00433                                int       nRecPriority,
00434                                uint      nPreferredInput,
00435                                int       nStartOffset,
00436                                int       nEndOffset,
00437                                QString   sDupMethod,
00438                                QString   sDupIn,
00439                                uint      nFilter,
00440                                QString   sRecProfile,
00441                                QString   sRecGroup,
00442                                QString   sStorageGroup,
00443                                QString   sPlayGroup,
00444                                bool      bAutoExpire,
00445                                int       nMaxEpisodes,
00446                                bool      bMaxNewest,
00447                                bool      bAutoCommflag,
00448                                bool      bAutoTranscode,
00449                                bool      bAutoMetaLookup,
00450                                bool      bAutoUserJob1,
00451                                bool      bAutoUserJob2,
00452                                bool      bAutoUserJob3,
00453                                bool      bAutoUserJob4,
00454                                int       nTranscoder)
00455 {
00456     RecordingInfo *info = new RecordingInfo(nChanId, dStartTime, false);
00457     RecordingRule *rule = info->GetRecordingRule();
00458 
00459     if (sType.isEmpty())
00460         sType = "single";
00461 
00462     if (sSearchType.isEmpty())
00463         sSearchType = "none";
00464 
00465     if (sDupMethod.isEmpty())
00466         sDupMethod = "subtitleanddescription";
00467 
00468     if (sDupIn.isEmpty())
00469         sDupIn = "all";
00470 
00471     rule->m_title = info->GetTitle();
00472     rule->m_type = recTypeFromString(sType);
00473     rule->m_searchType = searchTypeFromString(sSearchType);
00474     rule->m_dupMethod = dupMethodFromString(sDupMethod);
00475     rule->m_dupIn = dupInFromString(sDupIn);
00476 
00477     if (sRecProfile.isEmpty())
00478         sRecProfile = "Default";
00479 
00480     if (sRecGroup.isEmpty())
00481         sRecGroup = "Default";
00482 
00483     if (sStorageGroup.isEmpty())
00484         sStorageGroup = "Default";
00485 
00486     if (sPlayGroup.isEmpty())
00487         sPlayGroup = "Default";
00488 
00489     rule->m_recProfile = sRecProfile;
00490     rule->m_recGroup = sRecGroup;
00491     rule->m_storageGroup = sStorageGroup;
00492     rule->m_playGroup = sPlayGroup;
00493 
00494     rule->m_parentRecID = nParentId;
00495     rule->m_isInactive = bInactive;
00496 
00497     rule->m_season = nSeason;
00498     rule->m_episode = nEpisode;
00499     rule->m_inetref = sInetref;
00500     rule->m_findid = nFindId;
00501 
00502     rule->m_recPriority = nRecPriority;
00503     rule->m_prefInput = nPreferredInput;
00504     rule->m_startOffset = nStartOffset;
00505     rule->m_endOffset = nEndOffset;
00506     rule->m_filter = nFilter;
00507 
00508     rule->m_autoExpire = bAutoExpire;
00509     rule->m_maxEpisodes = nMaxEpisodes;
00510     rule->m_maxNewest = bMaxNewest;
00511 
00512     rule->m_autoCommFlag = bAutoCommflag;
00513     rule->m_autoTranscode = bAutoTranscode;
00514     rule->m_autoMetadataLookup = bAutoMetaLookup;
00515 
00516     rule->m_autoUserJob1 = bAutoUserJob1;
00517     rule->m_autoUserJob2 = bAutoUserJob2;
00518     rule->m_autoUserJob3 = bAutoUserJob3;
00519     rule->m_autoUserJob4 = bAutoUserJob4;
00520 
00521     rule->m_transcoder = nTranscoder;
00522 
00523     rule->Save();
00524 
00525     int recid = rule->m_recordID;
00526 
00527     delete rule;
00528     rule = NULL;
00529 
00530     return recid;
00531 }
00532 
00533 bool Dvr::RemoveRecordSchedule ( uint nRecordId )
00534 {
00535     bool bResult = false;
00536 
00537     if (nRecordId <= 0 )
00538         throw( QString("Record ID appears invalid."));
00539 
00540     RecordingRule pRule;
00541     pRule.m_recordID = nRecordId;
00542 
00543     bResult = pRule.Delete();
00544 
00545     return bResult;
00546 }
00547 
00548 DTC::RecRuleList* Dvr::GetRecordScheduleList( int nStartIndex,
00549                                               int nCount      )
00550 {
00551     RecList recList;
00552     Scheduler::GetAllScheduled(recList);
00553 
00554     // ----------------------------------------------------------------------
00555     // Build Response
00556     // ----------------------------------------------------------------------
00557 
00558     DTC::RecRuleList *pRecRules = new DTC::RecRuleList();
00559 
00560     nStartIndex   = min( nStartIndex, (int)recList.size() );
00561     nCount        = (nCount > 0) ? min( nCount, (int)recList.size() ) : recList.size();
00562     int nEndIndex = min((nStartIndex + nCount), (int)recList.size() );
00563 
00564     for( int n = nStartIndex; n < nEndIndex; n++)
00565     {
00566         RecordingInfo *info = recList[n];
00567 
00568         if (info != NULL)
00569         {
00570             DTC::RecRule *pRecRule = pRecRules->AddNewRecRule();
00571 
00572             FillRecRuleInfo( pRecRule, info->GetRecordingRule() );
00573 
00574             delete info;
00575         }
00576     }
00577 
00578     // ----------------------------------------------------------------------
00579 
00580     pRecRules->setStartIndex    ( nStartIndex     );
00581     pRecRules->setCount         ( nCount          );
00582     pRecRules->setTotalAvailable( recList.size() );
00583     pRecRules->setAsOf          ( QDateTime::currentDateTime() );
00584     pRecRules->setVersion       ( MYTH_BINARY_VERSION );
00585     pRecRules->setProtoVer      ( MYTH_PROTO_VERSION  );
00586 
00587     return pRecRules;
00588 }
00589 
00590 DTC::RecRule* Dvr::GetRecordSchedule( uint nRecordId )
00591 {
00592     if (nRecordId <= 0 )
00593         throw( QString("Record ID appears invalid."));
00594 
00595     RecordingRule *pRule = new RecordingRule();
00596     pRule->m_recordID = nRecordId;
00597     pRule->Load();
00598 
00599     DTC::RecRule *pRecRule = new DTC::RecRule();
00600     FillRecRuleInfo( pRecRule, pRule );
00601     delete pRule;
00602 
00603     return pRecRule;
00604 }
00605 
00606 bool Dvr::EnableRecordSchedule ( uint nRecordId )
00607 {
00608     bool bResult = false;
00609 
00610     if (nRecordId <= 0 )
00611         throw( QString("Record ID appears invalid."));
00612 
00613     RecordingRule pRule;
00614     pRule.m_recordID = nRecordId;
00615     pRule.Load();
00616 
00617     if (pRule.IsLoaded())
00618     {
00619         pRule.m_isInactive = false;
00620         pRule.Save();
00621         bResult = true;
00622     }
00623 
00624     return bResult;
00625 }
00626 
00627 bool Dvr::DisableRecordSchedule( uint nRecordId )
00628 {
00629     bool bResult = false;
00630 
00631     if (nRecordId <= 0 )
00632         throw( QString("Record ID appears invalid."));
00633 
00634     RecordingRule pRule;
00635     pRule.m_recordID = nRecordId;
00636     pRule.Load();
00637 
00638     if (pRule.IsLoaded())
00639     {
00640         pRule.m_isInactive = true;
00641         pRule.Save();
00642         bResult = true;
00643     }
00644 
00645     return bResult;
00646 }
00647 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends