From 70748b69495c62140e43bd579c654250da4b3f18 Mon Sep 17 00:00:00 2001
From: Sascha Hinck <SHinck@web.de>
Date: Tue, 7 Aug 2012 01:10:11 +0200
Subject: [PATCH] libmythtv: Stop EIT-Active scan during recording
During recording and Live-TV EIT-Active scan will be stopped on all
Capture-Cards. Active-Scan-IdleTimer will be restarted after the last
recording exited.
---
mythtv/libs/libmythtv/eitscanner.cpp | 14 ++-
mythtv/libs/libmythtv/tv_rec.cpp | 171 +++++++++++++++++++++++---
mythtv/libs/libmythtv/tv_rec.h | 6 +-
mythtv/programs/mythbackend/main_helpers.cpp | 4 +-
4 files changed, 175 insertions(+), 24 deletions(-)
diff --git a/mythtv/libs/libmythtv/eitscanner.cpp b/mythtv/libs/libmythtv/eitscanner.cpp
index 6135e08..e419a8f 100644
a
|
b
|
void EITScanner::run(void) |
133 | 133 | if (!(*activeScanNextChan).isEmpty()) |
134 | 134 | { |
135 | 135 | eitHelper->WriteEITCache(); |
136 | | rec->SetChannel(*activeScanNextChan, TVRec::kFlagEITScan); |
137 | | LOG(VB_EIT, LOG_INFO, |
138 | | LOC_ID + QString("Now looking for EIT data on " |
139 | | "multiplex of channel %1") |
| 136 | if (rec->QueueEITChannelChange(*activeScanNextChan)) |
| 137 | { |
| 138 | LOG(VB_EIT, LOG_INFO, |
| 139 | LOC_ID + QString("Now looking for EIT data on " |
| 140 | "multiplex of channel %1") |
140 | 141 | .arg(*activeScanNextChan)); |
| 142 | } |
141 | 143 | } |
142 | 144 | |
143 | 145 | activeScanNextTrig = QDateTime::currentDateTime() |
… |
… |
void EITScanner::StopPassiveScan(void) |
216 | 218 | |
217 | 219 | eitHelper->WriteEITCache(); |
218 | 220 | eitHelper->SetSourceID(0); |
| 221 | |
| 222 | LOG(VB_EIT, LOG_INFO, LOC_ID + "Stopped passive scan."); |
219 | 223 | } |
220 | 224 | |
221 | 225 | void EITScanner::StartActiveScan(TVRec *_rec, uint max_seconds_per_source) |
… |
… |
void EITScanner::StopActiveScan() |
280 | 284 | activeScan = false; |
281 | 285 | rec = NULL; |
282 | 286 | StopPassiveScan(); |
| 287 | |
| 288 | LOG(VB_EIT, LOG_INFO, LOC_ID + "Stopped active scan."); |
283 | 289 | } |
diff --git a/mythtv/libs/libmythtv/tv_rec.cpp b/mythtv/libs/libmythtv/tv_rec.cpp
index 3d38c6d..9b53f5f 100644
a
|
b
|
|
36 | 36 | #include "tv_rec.h" |
37 | 37 | #include "mythmiscutil.h" |
38 | 38 | #include "osd.h" |
| 39 | #include "cardutil.h" |
39 | 40 | |
40 | 41 | #define DEBUG_CHANNEL_PREFIX 0 /**< set to 1 to channel prefixing */ |
41 | 42 | |
… |
… |
static QString load_profile(QString,void*,RecordingInfo*,RecordingProfile&); |
52 | 53 | static int init_jobs(const RecordingInfo *rec, RecordingProfile &profile, |
53 | 54 | bool on_host, bool transcode_bfr_comm, bool on_line_comm); |
54 | 55 | static void apply_broken_dvb_driver_crc_hack(ChannelBase*, MPEGStreamData*); |
55 | | |
| 56 | static int eit_start_rand(uint cardid, int eitTransportTimeout); |
56 | 57 | |
57 | 58 | /** \class TVRec |
58 | 59 | * \brief This is the coordinating class of the \ref recorder_subsystem. |
… |
… |
bool TVRec::Init(void) |
161 | 162 | gCoreContext->GetNumSetting("AutoTranscodeBeforeAutoCommflag", 0); |
162 | 163 | earlyCommFlag = gCoreContext->GetNumSetting("AutoCommflagWhileRecording", 0); |
163 | 164 | runJobOnHostOnly = gCoreContext->GetNumSetting("JobsRunOnRecordHost", 0); |
164 | | eitTransportTimeout=gCoreContext->GetNumSetting("EITTransportTimeout", 5) * 60; |
| 165 | eitTransportTimeout = |
| 166 | max(gCoreContext->GetNumSetting("EITTransportTimeout", 5) * 60, 6); |
165 | 167 | eitCrawlIdleStart = gCoreContext->GetNumSetting("EITCrawIdleStart", 60); |
166 | 168 | audioSampleRateDB = gCoreContext->GetNumSetting("AudioSampleRate"); |
167 | 169 | overRecordSecNrml = gCoreContext->GetNumSetting("RecordOverTime"); |
… |
… |
void TVRec::HandleStateChange(void) |
974 | 976 | |
975 | 977 | bool changed = false; |
976 | 978 | |
| 979 | LOG(VB_GENERAL, LOG_INFO, LOC + "GetCardIDs to stop EITscan"); |
| 980 | vector<uint> cardids = CardUtil::GetCardIDs("","DVB",""); |
| 981 | uint no_cards = cardids.size(); |
| 982 | |
977 | 983 | QString transMsg = QString(" %1 to %2") |
978 | 984 | .arg(StateToString(nextState)) |
979 | 985 | .arg(StateToString(desiredNextState)); |
… |
… |
void TVRec::HandleStateChange(void) |
998 | 1004 | if (TRANSITION(kState_None, kState_WatchingLiveTV)) |
999 | 1005 | { |
1000 | 1006 | tuningRequests.enqueue(TuningRequest(kFlagLiveTV)); |
| 1007 | for (uint i = 0; i < no_cards; i++) |
| 1008 | { |
| 1009 | if (cardids[i] != cardid) |
| 1010 | { |
| 1011 | TVRec *rec = GetTVRec(cardids[i]); |
| 1012 | if (rec && !rec->HasFlags(kFlagEITScanPaused)) |
| 1013 | rec->SetFlags(kFlagEITScanPaused); |
| 1014 | } |
| 1015 | } |
1001 | 1016 | SET_NEXT(); |
1002 | 1017 | } |
1003 | 1018 | else if (TRANSITION(kState_WatchingLiveTV, kState_None)) |
1004 | 1019 | { |
1005 | 1020 | tuningRequests.enqueue(TuningRequest(kFlagKillRec|kFlagKillRingBuffer)); |
| 1021 | eitScanStartTime = QDateTime::currentDateTime(); |
| 1022 | uint j = 0; |
| 1023 | TVRec *arec = NULL; |
| 1024 | for (uint i = 0; i < no_cards; i++) |
| 1025 | { |
| 1026 | if (cardids[i] != cardid) |
| 1027 | { |
| 1028 | TVRec *rec = GetTVRec(cardids[i]); |
| 1029 | if (!HasFlags(kFlagEITScanPaused)) |
| 1030 | { |
| 1031 | if (rec && rec->HasFlags(kFlagEITScanPaused)) |
| 1032 | { |
| 1033 | rec->eitScanStartTime = eitScanStartTime.addSecs( |
| 1034 | eitCrawlIdleStart + eit_start_rand(cardids[i], eitTransportTimeout)); |
| 1035 | rec->ClearFlags(kFlagEITScanPaused); |
| 1036 | LOG(VB_IDLE, LOG_INFO, LOC + "Start EIT-ActiveScanIdle-Timer for " + |
| 1037 | QString("cardid %1, next start time: ").arg(cardids[i]) + |
| 1038 | rec->eitScanStartTime.toString(Qt::ISODate)); |
| 1039 | } |
| 1040 | } |
| 1041 | else if (rec && rec->GetState() != kState_None) |
| 1042 | arec = rec; j++; |
| 1043 | } |
| 1044 | } |
| 1045 | if (j == 1) |
| 1046 | arec->ClearFlags(kFlagEITScanPaused); |
1006 | 1047 | SET_NEXT(); |
1007 | 1048 | } |
1008 | 1049 | else if (TRANSITION(kState_WatchingLiveTV, kState_RecordingOnly)) |
… |
… |
void TVRec::HandleStateChange(void) |
1015 | 1058 | { |
1016 | 1059 | SetPseudoLiveTVRecording(NULL); |
1017 | 1060 | tuningRequests.enqueue(TuningRequest(kFlagRecording, curRecording)); |
| 1061 | for (uint i = 0; i < no_cards; i++) |
| 1062 | { |
| 1063 | if (cardids[i] != cardid) |
| 1064 | { |
| 1065 | TVRec *rec = GetTVRec(cardids[i]); |
| 1066 | if (rec && !rec->HasFlags(kFlagEITScanPaused)) |
| 1067 | rec->SetFlags(kFlagEITScanPaused); |
| 1068 | } |
| 1069 | } |
1018 | 1070 | SET_NEXT(); |
1019 | 1071 | } |
1020 | 1072 | else if (TRANSITION(kState_RecordingOnly, kState_None)) |
… |
… |
void TVRec::HandleStateChange(void) |
1022 | 1074 | tuningRequests.enqueue( |
1023 | 1075 | TuningRequest(kFlagCloseRec|kFlagKillRingBuffer| |
1024 | 1076 | (GetFlags()&kFlagKillRec))); |
| 1077 | eitScanStartTime = QDateTime::currentDateTime(); |
| 1078 | uint j = 0; |
| 1079 | TVRec *arec = NULL; |
| 1080 | for (uint i = 0; i < no_cards; i++) |
| 1081 | { |
| 1082 | if (cardids[i] != cardid) |
| 1083 | { |
| 1084 | TVRec *rec = GetTVRec(cardids[i]); |
| 1085 | if (!HasFlags(kFlagEITScanPaused)) |
| 1086 | { |
| 1087 | if (rec && rec->HasFlags(kFlagEITScanPaused)) |
| 1088 | { |
| 1089 | rec->eitScanStartTime = eitScanStartTime.addSecs( |
| 1090 | eitCrawlIdleStart + eit_start_rand(cardids[i], eitTransportTimeout)); |
| 1091 | rec->ClearFlags(kFlagEITScanPaused); |
| 1092 | LOG(VB_IDLE, LOG_INFO, LOC + "Start EIT-ActiveScanIdle-Timer for " + |
| 1093 | QString("cardid %1, next start time: ").arg(cardids[i]) + |
| 1094 | rec->eitScanStartTime.toString(Qt::ISODate)); |
| 1095 | } |
| 1096 | } |
| 1097 | else if (rec && rec->GetState() != kState_None) |
| 1098 | arec = rec; j++; |
| 1099 | } |
| 1100 | } |
| 1101 | if (j == 1) |
| 1102 | arec->ClearFlags(kFlagEITScanPaused); |
1025 | 1103 | SET_NEXT(); |
1026 | 1104 | } |
1027 | 1105 | |
… |
… |
void TVRec::HandleStateChange(void) |
1034 | 1114 | |
1035 | 1115 | eitScanStartTime = QDateTime::currentDateTime(); |
1036 | 1116 | if (scanner && (internalState == kState_None)) |
1037 | | eitScanStartTime = eitScanStartTime.addSecs(eitCrawlIdleStart); |
| 1117 | { |
| 1118 | eitScanStartTime = eitScanStartTime.addSecs( |
| 1119 | eitCrawlIdleStart + eit_start_rand(cardid, eitTransportTimeout)); |
| 1120 | } |
1038 | 1121 | else |
1039 | 1122 | eitScanStartTime = eitScanStartTime.addYears(1); |
1040 | 1123 | } |
… |
… |
void TVRec::CloseChannel(void) |
1130 | 1213 | CardUtil::IsV4L(genOpt.cardtype))) |
1131 | 1214 | { |
1132 | 1215 | channel->Close(); |
| 1216 | LOG(VB_GENERAL, LOG_INFO, LOC + QString("Close Card %1") |
| 1217 | .arg(CardUtil::ProbeDVBFrontendName(CardUtil::GetVideoDevice(cardid))) ); |
| 1218 | // GetDeviceLabel(cardid)) |
1133 | 1219 | } |
1134 | 1220 | } |
1135 | 1221 | |
… |
… |
static int no_capturecards(uint cardid) |
1213 | 1299 | return -1; |
1214 | 1300 | } |
1215 | 1301 | |
| 1302 | static int eit_start_rand(uint cardid, int eitTransportTimeout) |
| 1303 | { |
| 1304 | // randomize start time a bit |
| 1305 | int timeout = random() % (eitTransportTimeout / 3); |
| 1306 | // get the number of capture cards and the position of the current card |
| 1307 | // to distribute the the scan start evenly over eitTransportTimeout |
| 1308 | int card_pos = no_capturecards(cardid); |
| 1309 | int no_cards = no_capturecards(0); |
| 1310 | if (no_cards > 0 && card_pos >= 0) |
| 1311 | timeout += eitTransportTimeout * card_pos / no_cards; |
| 1312 | return timeout; |
| 1313 | } |
| 1314 | |
1216 | 1315 | /// \brief Event handling method, contains event loop. |
1217 | 1316 | void TVRec::run(void) |
1218 | 1317 | { |
… |
… |
void TVRec::run(void) |
1227 | 1326 | (dvbOpt.dvb_eitscan || get_use_eit(cardid))) |
1228 | 1327 | { |
1229 | 1328 | scanner = new EITScanner(cardid); |
1230 | | uint timeout = eitCrawlIdleStart; |
1231 | | // get the number of capture cards and the position of the current card |
1232 | | // to distribute the the scan start evenly over eitTransportTimeout |
1233 | | int card_pos = no_capturecards(cardid); |
1234 | | int no_cards = no_capturecards(0); |
1235 | | if (no_cards > 0 && card_pos >= 0) |
1236 | | timeout += eitTransportTimeout * card_pos / no_cards; |
1237 | | else |
1238 | | timeout += random() % eitTransportTimeout; |
1239 | | |
1240 | | eitScanStartTime = eitScanStartTime.addSecs(timeout); |
| 1329 | eitScanStartTime = eitScanStartTime.addSecs( |
| 1330 | eitCrawlIdleStart + eit_start_rand(cardid, eitTransportTimeout)); |
1241 | 1331 | } |
1242 | 1332 | else |
1243 | 1333 | eitScanStartTime = eitScanStartTime.addYears(1); |
… |
… |
void TVRec::run(void) |
1370 | 1460 | } |
1371 | 1461 | |
1372 | 1462 | if (scanner && channel && |
1373 | | QDateTime::currentDateTime() > eitScanStartTime) |
| 1463 | QDateTime::currentDateTime() > eitScanStartTime && |
| 1464 | !HasFlags(kFlagEITScanPaused)) |
1374 | 1465 | { |
1375 | 1466 | if (!dvbOpt.dvb_eitscan) |
1376 | 1467 | { |
… |
… |
void TVRec::run(void) |
1392 | 1483 | } |
1393 | 1484 | } |
1394 | 1485 | |
| 1486 | //Stop EIT-Scanning if recording begins on another card, |
| 1487 | if (scanner && HasFlags(kFlagEITScanPaused) && |
| 1488 | HasFlags(kFlagEITScannerRunning)) |
| 1489 | { |
| 1490 | scanner->StopActiveScan(); |
| 1491 | ClearFlags(kFlagEITScannerRunning); |
| 1492 | TuningShutdowns(TuningRequest(kFlagNoRec)); |
| 1493 | } |
| 1494 | |
1395 | 1495 | // We should be no more than a few thousand milliseconds, |
1396 | 1496 | // as the end recording code does not have a trigger... |
1397 | 1497 | // NOTE: If you change anything here, make sure that |
… |
… |
void TVRec::SetChannel(QString name, uint requestType) |
3052 | 3152 | // Clear the RingBuffer reset flag, in case we wait for a reset below |
3053 | 3153 | ClearFlags(kFlagRingBufferReady); |
3054 | 3154 | |
| 3155 | // Clear out any EITScan channel change requests |
| 3156 | TuningQueue::iterator it = tuningRequests.begin(); |
| 3157 | while (it != tuningRequests.end()) |
| 3158 | { |
| 3159 | if ((*it).flags & kFlagEITScan) |
| 3160 | it = tuningRequests.erase(it); |
| 3161 | else |
| 3162 | ++it; |
| 3163 | } |
| 3164 | |
3055 | 3165 | // Actually add the tuning request to the queue, and |
3056 | 3166 | // then wait for it to start tuning |
3057 | 3167 | tuningRequests.enqueue(TuningRequest(requestType, name)); |
… |
… |
void TVRec::SetChannel(QString name, uint requestType) |
3066 | 3176 | LOG(VB_CHANNEL, LOG_INFO, LOC + QString("SetChannel(%1) -- end").arg(name)); |
3067 | 3177 | } |
3068 | 3178 | |
| 3179 | /** \brief Queues up a channel change for the EITScanner. |
| 3180 | * |
| 3181 | * Unlike the normal SetChannel() this does not block until |
| 3182 | * the channel change occurs to avoid a deadlock if |
| 3183 | * EITScanner::StopActiveScan() is called with the stateChangeLock |
| 3184 | * held while the EITScanner is calling TVRec::SetChannel(). |
| 3185 | */ |
| 3186 | bool TVRec::QueueEITChannelChange(const QString &name) |
| 3187 | { |
| 3188 | LOG(VB_CHANNEL, LOG_INFO, LOC + |
| 3189 | QString("QueueEITChannelChange(%1) -- begin").arg(name)); |
| 3190 | |
| 3191 | bool ok = false; |
| 3192 | if (stateChangeLock.tryLock()) |
| 3193 | { |
| 3194 | if (tuningRequests.empty()) |
| 3195 | { |
| 3196 | tuningRequests.enqueue(TuningRequest(kFlagEITScan, name)); |
| 3197 | ok = true; |
| 3198 | } |
| 3199 | stateChangeLock.unlock(); |
| 3200 | } |
| 3201 | |
| 3202 | LOG(VB_CHANNEL, LOG_INFO, LOC + |
| 3203 | QString("QueueEITChannelChange(%1) -- end --> %2").arg(name).arg(ok)); |
| 3204 | |
| 3205 | return ok; |
| 3206 | } |
| 3207 | |
3069 | 3208 | void TVRec::GetNextProgram(BrowseDirection direction, |
3070 | 3209 | QString &title, QString &subtitle, |
3071 | 3210 | QString &desc, QString &category, |
… |
… |
QString TVRec::FlagToString(uint f) |
4204 | 4343 | msg += "Errored,"; |
4205 | 4344 | if (kFlagCancelNextRecording & f) |
4206 | 4345 | msg += "CancelNextRecording,"; |
| 4346 | if (kFlagEITScanPaused & f) |
| 4347 | msg += "EITScanPaused,"; |
4207 | 4348 | |
4208 | 4349 | // Tuning flags |
4209 | 4350 | if ((kFlagRec & f) == kFlagRec) |
diff --git a/mythtv/libs/libmythtv/tv_rec.h b/mythtv/libs/libmythtv/tv_rec.h
index a830c33..b169434 100644
a
|
b
|
class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable |
156 | 156 | void FinishRecording(void) { SetFlags(kFlagFinishRecording); } |
157 | 157 | /// \brief Tells TVRec that the frontend's TV class is ready for messages. |
158 | 158 | void FrontendReady(void) { SetFlags(kFlagFrontendReady); } |
| 159 | void PauseEITActiveScan(void) { SetFlags(kFlagEITScanPaused); } |
| 160 | void RestartEITActiveScan(void) { ClearFlags(kFlagEITScanPaused); } |
159 | 161 | void CancelNextRecording(bool cancel); |
160 | 162 | ProgramInfo *GetRecording(void); |
161 | 163 | |
… |
… |
class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable |
198 | 200 | void ChangeChannel(ChannelChangeDirection dir) |
199 | 201 | { SetChannel(QString("NextChannel %1").arg((int)dir)); } |
200 | 202 | void SetChannel(QString name, uint requestType = kFlagDetect); |
| 203 | bool QueueEITChannelChange(const QString &name); |
201 | 204 | |
202 | 205 | int SetSignalMonitoringRate(int msec, int notifyFrontend = 1); |
203 | 206 | int GetPictureAttribute(PictureAttribute attr); |
… |
… |
class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable |
409 | 412 | static const uint kFlagFinishRecording = 0x00000008; |
410 | 413 | static const uint kFlagErrored = 0x00000010; |
411 | 414 | static const uint kFlagCancelNextRecording = 0x00000020; |
| 415 | static const uint kFlagEITScanPaused = 0x00000040; |
412 | 416 | |
413 | 417 | // Tuning flags |
414 | 418 | /// final result desired is LiveTV recording |
… |
… |
class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable |
432 | 436 | |
433 | 437 | // Waiting stuff |
434 | 438 | static const uint kFlagWaitingForRecPause = 0x00100000; |
435 | | static const uint kFlagWaitingForSignal = 0x00200000; |
| 439 | static const uint kFlagWaitingForSignal = 0x00200000; |
436 | 440 | static const uint kFlagNeedToStartRecorder = 0x00800000; |
437 | 441 | static const uint kFlagPendingActions = 0x00F00000; |
438 | 442 | |
diff --git a/mythtv/programs/mythbackend/main_helpers.cpp b/mythtv/programs/mythbackend/main_helpers.cpp
index 28d5a4a..d2283ca 100644
a
|
b
|
bool setupTVs(bool ismaster, bool &error) |
192 | 192 | } |
193 | 193 | else |
194 | 194 | { |
195 | | LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards" + |
196 | | cidmsg + "failed init"); |
| 195 | LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards - " + |
| 196 | cidmsg + " failed init"); |
197 | 197 | delete tv; |
198 | 198 | } |
199 | 199 | } |