00001
00002 #include <iostream>
00003 using namespace std;
00004
00005
00006 #include <unistd.h>
00007
00008
00009 #include "mythcorecontext.h"
00010 #include "encoderlink.h"
00011 #include "playbacksock.h"
00012 #include "tv_rec.h"
00013 #include "mythmiscutil.h"
00014 #include "previewgenerator.h"
00015 #include "storagegroup.h"
00016 #include "backendutil.h"
00017 #include "compat.h"
00018
00019 #define LOC QString("EncoderLink(%1): ").arg(m_capturecardnum)
00020 #define LOC_ERR QString("EncoderLink(%1) Error: ").arg(m_capturecardnum)
00021
00040 EncoderLink::EncoderLink(int capturecardnum, PlaybackSock *lsock,
00041 QString lhostname)
00042 : m_capturecardnum(capturecardnum), sock(lsock), hostname(lhostname),
00043 freeDiskSpaceKB(-1), tv(NULL), local(false), locked(false),
00044 sleepStatus(sStatus_Undefined), chanid(0)
00045 {
00046 endRecordingTime = QDateTime::currentDateTime().addDays(-2);
00047 startRecordingTime = endRecordingTime;
00048
00049 sleepStatusTime = QDateTime::currentDateTime();
00050 lastSleepTime = QDateTime::currentDateTime();
00051 lastWakeTime = QDateTime::currentDateTime();
00052
00053 if (sock)
00054 sock->UpRef();
00055 }
00056
00060 EncoderLink::EncoderLink(int capturecardnum, TVRec *ltv)
00061 : m_capturecardnum(capturecardnum), sock(NULL),
00062 freeDiskSpaceKB(-1), tv(ltv), local(true), locked(false),
00063 sleepStatus(sStatus_Undefined), chanid(0)
00064 {
00065 endRecordingTime = QDateTime::currentDateTime().addDays(-2);
00066 startRecordingTime = endRecordingTime;
00067
00068 sleepStatusTime = QDateTime::currentDateTime();
00069 lastSleepTime = QDateTime::currentDateTime();
00070 lastWakeTime = QDateTime::currentDateTime();
00071 }
00072
00077 EncoderLink::~EncoderLink(void)
00078 {
00079 if (tv)
00080 {
00081 delete tv;
00082 tv = NULL;
00083 }
00084 }
00085
00091 void EncoderLink::SetSocket(PlaybackSock *lsock)
00092 {
00093 if (lsock)
00094 {
00095 lsock->UpRef();
00096
00097 if (gCoreContext->GetSettingOnHost("SleepCommand", hostname).isEmpty())
00098 SetSleepStatus(sStatus_Undefined);
00099 else
00100 SetSleepStatus(sStatus_Awake);
00101 }
00102 else
00103 {
00104 if (IsFallingAsleep())
00105 SetSleepStatus(sStatus_Asleep);
00106 else
00107 SetSleepStatus(sStatus_Undefined);
00108 }
00109
00110 if (sock)
00111 sock->DownRef();
00112 sock = lsock;
00113 }
00114
00118 void EncoderLink::SetSleepStatus(SleepStatus newStatus)
00119 {
00120 sleepStatus = newStatus;
00121 sleepStatusTime = QDateTime::currentDateTime();
00122 }
00123
00129 bool EncoderLink::IsBusy(TunedInputInfo *busy_input, int time_buffer)
00130 {
00131 if (local)
00132 return tv->IsBusy(busy_input, time_buffer);
00133
00134 if (sock)
00135 return sock->IsBusy(m_capturecardnum, busy_input, time_buffer);
00136
00137 return false;
00138 }
00139
00148 bool EncoderLink::IsBusyRecording(void)
00149 {
00150 bool retval = false;
00151
00152 TVState state = GetState();
00153
00154 if (state == kState_RecordingOnly || state == kState_WatchingRecording ||
00155 state == kState_WatchingLiveTV)
00156 {
00157 retval = true;
00158 }
00159
00160 return retval;
00161 }
00162
00167 TVState EncoderLink::GetState(void)
00168 {
00169 TVState retval = kState_Error;
00170
00171 if (!IsConnected())
00172 return retval;
00173
00174 if (local)
00175 retval = tv->GetState();
00176 else if (sock)
00177 retval = (TVState)sock->GetEncoderState(m_capturecardnum);
00178 else
00179 LOG(VB_GENERAL, LOG_ERR, QString("Broken for card: %1")
00180 .arg(m_capturecardnum));
00181
00182 return retval;
00183 }
00184
00189 uint EncoderLink::GetFlags(void) const
00190 {
00191 uint retval = 0;
00192
00193 if (!IsConnected())
00194 return retval;
00195
00196 if (local)
00197 retval = tv->GetFlags();
00198 else if (sock)
00199 retval = sock->GetEncoderState(m_capturecardnum);
00200 else
00201 LOG(VB_GENERAL, LOG_ERR, LOC + "GetFlags failed");
00202
00203 return retval;
00204 }
00205
00211 bool EncoderLink::IsRecording(const ProgramInfo *rec)
00212 {
00213 return (rec->GetChanID() == chanid &&
00214 rec->GetRecordingStartTime() == startRecordingTime);
00215 }
00216
00225 bool EncoderLink::MatchesRecording(const ProgramInfo *rec)
00226 {
00227 bool retval = false;
00228 ProgramInfo *tvrec = NULL;
00229
00230 if (local)
00231 {
00232 while (kState_ChangingState == GetState())
00233 usleep(100);
00234
00235 if (IsBusyRecording())
00236 tvrec = tv->GetRecording();
00237
00238 if (tvrec)
00239 {
00240 retval = tvrec->IsSameRecording(*rec);
00241 delete tvrec;
00242 }
00243 }
00244 else
00245 {
00246 if (sock)
00247 retval = sock->EncoderIsRecording(m_capturecardnum, rec);
00248 }
00249
00250 return retval;
00251 }
00252
00261 void EncoderLink::RecordPending(const ProgramInfo *rec, int secsleft,
00262 bool hasLater)
00263 {
00264 if (local)
00265 tv->RecordPending(rec, secsleft, hasLater);
00266 else if (sock)
00267 sock->RecordPending(m_capturecardnum, rec, secsleft, hasLater);
00268 }
00269
00275 bool EncoderLink::WouldConflict(const ProgramInfo *rec)
00276 {
00277 if (!IsConnected())
00278 return true;
00279
00280 if (rec->GetRecordingStartTime() < endRecordingTime)
00281 return true;
00282
00283 return false;
00284 }
00285
00287 bool EncoderLink::CheckFile(ProgramInfo *pginfo)
00288 {
00289 if (sock)
00290 return sock->CheckFile(pginfo);
00291
00292 pginfo->SetPathname(GetPlaybackURL(pginfo));
00293 return pginfo->IsLocal();
00294 }
00295
00301 void EncoderLink::GetDiskSpace(QStringList &o_strlist)
00302 {
00303 if (sock)
00304 sock->GetDiskSpace(o_strlist);
00305 }
00306
00313 long long EncoderLink::GetMaxBitrate()
00314 {
00315 if (local)
00316 return tv->GetMaxBitrate();
00317 else if (sock)
00318 return sock->GetMaxBitrate(m_capturecardnum);
00319
00320 return -1;
00321 }
00322
00337 int EncoderLink::SetSignalMonitoringRate(int rate, int notifyFrontend)
00338 {
00339 if (local)
00340 return tv->SetSignalMonitoringRate(rate, notifyFrontend);
00341 else if (sock)
00342 return sock->SetSignalMonitoringRate(m_capturecardnum, rate,
00343 notifyFrontend);
00344 return -1;
00345 }
00346
00349 bool EncoderLink::GoToSleep(void)
00350 {
00351 if (IsLocal() || !sock)
00352 return false;
00353
00354 lastSleepTime = QDateTime::currentDateTime();
00355
00356 return sock->GoToSleep();
00357 }
00358
00363 int EncoderLink::LockTuner()
00364 {
00365 if (locked)
00366 return -2;
00367
00368 locked = true;
00369 return m_capturecardnum;
00370 }
00371
00379 RecStatusType EncoderLink::StartRecording(const ProgramInfo *rec)
00380 {
00381 RecStatusType retval = rsAborted;
00382
00383 endRecordingTime = rec->GetRecordingEndTime();
00384 startRecordingTime = rec->GetRecordingStartTime();
00385 chanid = rec->GetChanID();
00386
00387 if (local)
00388 retval = tv->StartRecording(rec);
00389 else if (sock)
00390 retval = sock->StartRecording(m_capturecardnum, rec);
00391 else
00392 LOG(VB_GENERAL, LOG_ERR,
00393 QString("Wanted to start recording on recorder %1,\n\t\t\t"
00394 "but the backend is not there anymore\n")
00395 .arg(m_capturecardnum));
00396
00397 if (retval != rsRecording && retval != rsTuning)
00398 {
00399 endRecordingTime = QDateTime::currentDateTime().addDays(-2);
00400 startRecordingTime = endRecordingTime;
00401 chanid = 0;
00402 }
00403
00404 return retval;
00405 }
00406
00407 RecStatusType EncoderLink::GetRecordingStatus(void)
00408 {
00409 RecStatusType retval = rsAborted;
00410
00411 if (local)
00412 retval = tv->GetRecordingStatus();
00413 else if (sock)
00414 retval = sock->GetRecordingStatus(m_capturecardnum);
00415 else
00416 LOG(VB_GENERAL, LOG_ERR,
00417 QString("Wanted to get status on recorder %1,\n\t\t\t"
00418 "but the backend is not there anymore\n")
00419 .arg(m_capturecardnum));
00420
00421 if (retval != rsRecording && retval != rsTuning)
00422 {
00423 endRecordingTime = QDateTime::currentDateTime().addDays(-2);
00424 startRecordingTime = endRecordingTime;
00425 chanid = 0;
00426 }
00427
00428 return retval;
00429 }
00430
00437 ProgramInfo *EncoderLink::GetRecording(void)
00438 {
00439 ProgramInfo *info = NULL;
00440
00441 if (local)
00442 info = tv->GetRecording();
00443 else if (sock)
00444 info = sock->GetRecording(m_capturecardnum);
00445
00446 return info;
00447 }
00448
00454 void EncoderLink::StopRecording(bool killFile)
00455 {
00456 endRecordingTime = QDateTime::currentDateTime().addDays(-2);
00457 startRecordingTime = endRecordingTime;
00458 chanid = 0;
00459
00460 if (local)
00461 {
00462 tv->StopRecording(killFile);
00463 return;
00464 }
00465 }
00466
00472 void EncoderLink::FinishRecording(void)
00473 {
00474 if (local)
00475 {
00476 tv->FinishRecording();
00477 return;
00478 }
00479 else
00480 {
00481 endRecordingTime = QDateTime::currentDateTime().addDays(-2);
00482 }
00483 }
00484
00490 bool EncoderLink::IsReallyRecording(void)
00491 {
00492 if (local)
00493 return tv->IsReallyRecording();
00494
00495 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: IsReallyRecording");
00496 return false;
00497 }
00498
00506 float EncoderLink::GetFramerate(void)
00507 {
00508 if (local)
00509 return tv->GetFramerate();
00510
00511 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: GetFramerate");
00512 return -1;
00513 }
00514
00522 long long EncoderLink::GetFramesWritten(void)
00523 {
00524 if (local)
00525 return tv->GetFramesWritten();
00526
00527 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: GetFramesWritten");
00528 return -1;
00529 }
00530
00537 long long EncoderLink::GetFilePosition(void)
00538 {
00539 if (local)
00540 return tv->GetFilePosition();
00541
00542 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: GetFilePosition");
00543 return -1;
00544 }
00545
00552 int64_t EncoderLink::GetKeyframePosition(uint64_t desired)
00553 {
00554 if (local)
00555 return tv->GetKeyframePosition(desired);
00556
00557 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: GetKeyframePosition");
00558 return -1;
00559 }
00560
00561 bool EncoderLink::GetKeyframePositions(
00562 int64_t start, int64_t end, frm_pos_map_t &map)
00563 {
00564 if (!local)
00565 {
00566 LOG(VB_GENERAL, LOG_ERR,
00567 "Should be local only query: GetKeyframePositions");
00568 return false;
00569 }
00570
00571 return tv->GetKeyframePositions(start, end, map);
00572 }
00573
00579 void EncoderLink::FrontendReady(void)
00580 {
00581 if (local)
00582 tv->FrontendReady();
00583 else
00584 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: FrontendReady");
00585 }
00586
00595 void EncoderLink::CancelNextRecording(bool cancel)
00596 {
00597 if (local)
00598 tv->CancelNextRecording(cancel);
00599 else
00600 sock->CancelNextRecording(m_capturecardnum, cancel);
00601 }
00602
00614 void EncoderLink::SpawnLiveTV(LiveTVChain *chain, bool pip, QString startchan)
00615 {
00616 if (local)
00617 tv->SpawnLiveTV(chain, pip, startchan);
00618 else
00619 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: SpawnLiveTV");
00620 }
00621
00625 QString EncoderLink::GetChainID(void)
00626 {
00627 if (local)
00628 return tv->GetChainID();
00629
00630 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: SpawnLiveTV");
00631 return "";
00632 }
00633
00639 void EncoderLink::StopLiveTV(void)
00640 {
00641 if (local)
00642 tv->StopLiveTV();
00643 else
00644 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: StopLiveTV");
00645 }
00646
00653 void EncoderLink::PauseRecorder(void)
00654 {
00655 if (local)
00656 tv->PauseRecorder();
00657 else
00658 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: PauseRecorder");
00659 }
00660
00666 void EncoderLink::SetLiveRecording(int recording)
00667 {
00668 if (local)
00669 tv->SetLiveRecording(recording);
00670 else
00671 LOG(VB_GENERAL, LOG_ERR,
00672 "Should be local only query: SetLiveRecording");
00673 }
00674
00678 void EncoderLink::SetNextLiveTVDir(QString dir)
00679 {
00680 if (local)
00681 tv->SetNextLiveTVDir(dir);
00682 else
00683 sock->SetNextLiveTVDir(m_capturecardnum, dir);
00684 }
00685
00691 vector<InputInfo> EncoderLink::GetFreeInputs(
00692 const vector<uint> &excluded_cardids) const
00693 {
00694 vector<InputInfo> list;
00695
00696 if (local)
00697 list = tv->GetFreeInputs(excluded_cardids);
00698 else
00699 list = sock->GetFreeInputs(m_capturecardnum, excluded_cardids);
00700
00701 return list;
00702 }
00703
00710 QString EncoderLink::GetInput(void) const
00711 {
00712 if (local)
00713 return tv->GetInput();
00714
00715 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: GetInput");
00716 return QString();
00717 }
00718
00729 QString EncoderLink::SetInput(QString input)
00730 {
00731 if (local)
00732 return tv->SetInput(input);
00733
00734 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: SetInput");
00735 return QString();
00736 }
00737
00743 void EncoderLink::ToggleChannelFavorite(QString changroup)
00744 {
00745 if (local)
00746 tv->ToggleChannelFavorite(changroup);
00747 else
00748 LOG(VB_GENERAL, LOG_ERR,
00749 "Should be local only query: ToggleChannelFavorite");
00750 }
00751
00758 void EncoderLink::ChangeChannel(ChannelChangeDirection channeldirection)
00759 {
00760 if (local)
00761 tv->ChangeChannel(channeldirection);
00762 else
00763 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: ChangeChannel");
00764 }
00765
00773 void EncoderLink::SetChannel(const QString &name)
00774 {
00775 if (local)
00776 tv->SetChannel(name);
00777 else
00778 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: SetChannel");
00779 }
00780
00789 int EncoderLink::GetPictureAttribute(PictureAttribute attr)
00790 {
00791 if (!local)
00792 {
00793 LOG(VB_GENERAL, LOG_ERR,
00794 "Should be local only query: GetPictureAttribute");
00795 return -1;
00796 }
00797
00798 return tv->GetPictureAttribute(attr);
00799 }
00800
00809 int EncoderLink::ChangePictureAttribute(PictureAdjustType type,
00810 PictureAttribute attr,
00811 bool direction)
00812 {
00813 if (!local)
00814 {
00815 LOG(VB_GENERAL, LOG_ERR,
00816 "Should be local only query: ChangePictureAttribute");
00817 return -1;
00818 }
00819
00820 return tv->ChangePictureAttribute(type, attr, direction);
00821 }
00822
00832 bool EncoderLink::CheckChannel(const QString &name)
00833 {
00834 if (local)
00835 return tv->CheckChannel(name);
00836
00837 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: CheckChannel");
00838 return false;
00839 }
00840
00850 bool EncoderLink::ShouldSwitchToAnotherCard(const QString &channelid)
00851 {
00852 if (local)
00853 return tv->ShouldSwitchToAnotherCard(channelid);
00854
00855 LOG(VB_GENERAL, LOG_ERR,
00856 "Should be local only query: ShouldSwitchToAnotherCard");
00857 return false;
00858 }
00859
00867 bool EncoderLink::CheckChannelPrefix(
00868 const QString &prefix,
00869 uint &is_complete_valid_channel_on_rec,
00870 bool &is_extra_char_useful,
00871 QString &needed_spacer)
00872 {
00873 if (local)
00874 {
00875 return tv->CheckChannelPrefix(
00876 prefix, is_complete_valid_channel_on_rec,
00877 is_extra_char_useful, needed_spacer);
00878 }
00879
00880 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: CheckChannelPrefix");
00881 is_complete_valid_channel_on_rec = false;
00882 is_extra_char_useful = false;
00883 needed_spacer = "";
00884 return false;
00885 }
00886
00892 void EncoderLink::GetNextProgram(BrowseDirection direction,
00893 QString &title, QString &subtitle,
00894 QString &desc, QString &category,
00895 QString &starttime, QString &endtime,
00896 QString &callsign, QString &iconpath,
00897 QString &channelname, uint &_chanid,
00898 QString &seriesid, QString &programid)
00899 {
00900 if (local)
00901 {
00902 tv->GetNextProgram(direction,
00903 title, subtitle, desc, category, starttime,
00904 endtime, callsign, iconpath, channelname,
00905 _chanid, seriesid, programid);
00906 }
00907 else
00908 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: GetNextProgram");
00909 }
00910
00911 bool EncoderLink::GetChannelInfo(uint &chanid, uint &sourceid,
00912 QString &callsign, QString &channum,
00913 QString &channame, QString &xmltv) const
00914 {
00915 if (!local)
00916 {
00917 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: GetChannelInfo");
00918 return false;
00919 }
00920
00921 return tv->GetChannelInfo(chanid, sourceid,
00922 callsign, channum, channame, xmltv);
00923 }
00924
00925 bool EncoderLink::SetChannelInfo(uint chanid, uint sourceid,
00926 QString oldchannum,
00927 QString callsign, QString channum,
00928 QString channame, QString xmltv)
00929 {
00930 if (!local)
00931 {
00932 LOG(VB_GENERAL, LOG_ERR, "Should be local only query: SetChannelInfo");
00933 return false;
00934 }
00935
00936 return tv->SetChannelInfo(chanid, sourceid, oldchannum,
00937 callsign, channum, channame, xmltv);
00938 }
00939
00940