Go to the documentation of this file.
13 #include "libmythbase/mythconfig.h"
47 #define DEBUG_CHANNEL_PREFIX 0
49 #define LOC QString("TVRec[%1]: ").arg(m_inputId)
50 #define LOC2 QString("TVRec[%1]: ").arg(inputid) // for static functions
58 bool on_host,
bool transcode_bfr_comm,
bool on_line_comm);
60 static std::chrono::seconds
eit_start_rand(
uint inputId, std::chrono::seconds eitTransportTimeout);
88 : m_eventThread(new
MThread(
"TVRecEvent", this)),
96 bool enter_power_save_mode)
98 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"CreateChannel(%1)")
111 startchannel, enter_power_save_mode,
m_rbFileExt, setchan);
119 LOG(VB_GENERAL, LOG_ERR,
LOC +
120 QString(
"CreateChannel(%1) failed due to VBOX not responding "
121 "to network check on inputid [%2]")
131 if (!CardUtil::IsSatIPPresent(
m_inputId))
134 LOG(VB_GENERAL, LOG_ERR,
LOC +
135 QString(
"CreateChannel(%1) failed due to SatIP box not responding "
136 "to network check on inputid [%2]")
163 LOG(VB_CHANNEL, LOG_ERR,
LOC +
164 QString(
"Failed to GetDevices for input %1")
173 if (startchannel.isEmpty())
177 LOG(VB_CHANNEL, LOG_ERR,
LOC +
178 QString(
"Failed to create channel instance for %1")
236 LOG(VB_RECORD, LOG_INFO,
LOC +
"TeardownAll");
320 LOG(VB_RECORD, LOG_INFO,
LOC +
"Pending recording revoked on " +
321 QString(
"inputid [%1]").arg(rcinfo->
GetInputID()));
327 (*it).m_doNotAsk =
true;
328 (*it).m_canceled =
true;
333 LOG(VB_RECORD, LOG_INFO,
LOC +
334 QString(
"RecordPending on inputid [%1]").arg(rcinfo->
GetInputID()));
340 pending.
m_ask =
true;
356 for (
uint inputid : inputids)
391 LOG(VB_RECORD, LOG_INFO,
LOC +
392 QString(
"CancelNextRecording(%1) -- begin").arg(cancel));
397 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"CancelNextRecording(%1) -- "
398 "error, unknown recording").arg(cancel));
404 std::vector<unsigned int> &inputids = (*it).m_possibleConflicts;
405 for (
uint inputid : inputids)
407 LOG(VB_RECORD, LOG_INFO,
LOC +
408 QString(
"CancelNextRecording -- inputid 0x%1")
409 .arg((uint64_t)inputid,0,16));
416 LOG(VB_RECORD, LOG_INFO,
LOC +
417 QString(
"CancelNextRecording -- inputid [%1]")
424 (*it).m_canceled =
false;
427 LOG(VB_RECORD, LOG_INFO,
LOC +
428 QString(
"CancelNextRecording(%1) -- end").arg(cancel));
445 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"StartRecording(%1)")
471 .addSecs(post_roll_seconds);
473 QString msg = QString(
"updating recording: %1 %2 %3 %4")
478 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
486 bool cancelNext =
false;
493 (*it).m_ask = (*it).m_doNotAsk =
false;
494 cancelNext = (*it).m_canceled;
515 LOG(VB_RECORD, LOG_INFO,
LOC +
516 "Checking input group recorders - begin");
522 std::vector<unsigned int> inputids2;
523 std::vector<TVState> states;
526 for (
uint inputid : inputids)
531 if (is_busy && !sourceid)
541 ((mplexid == 0 || mplexid == 32767) &&
545 inputids2.push_back(inputid);
550 for (
uint i = 0; (i < inputids2.size()) && ok; i++)
552 LOG(VB_RECORD, LOG_INFO,
LOC +
553 QString(
"Attempting to stop input [%1] in state %2")
560 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"a [%1]: %2")
568 QString message = QString(
"QUIT_LIVETV %1").arg(inputids2[i]);
573 LOG(VB_RECORD, LOG_INFO,
LOC +
574 QString(
"Stopping recording on [%1], %2") .arg(inputids2[i])
575 .arg(success ?
"succeeded" :
"failed"));
589 LOG(VB_RECORD, LOG_INFO,
LOC +
"Checking input group recorders - done");
592 bool did_switch =
false;
596 did_switch = (
nullptr != ri2);
617 QString message = QString(
"LIVETV_EXITED");
639 LOG(VB_RECORD, LOG_WARNING,
LOC +
"Still failing.");
651 QString message = QString(
"LIVETV_WATCH %1 1").arg(
m_inputId);
657 else if (!did_switch)
659 QString msg = QString(
"Wanted to record: %1 %2 %3 %4\n\t\t\t")
667 msg +=
"But a user has canceled this recording";
672 msg += QString(
"But the current state is: %1")
679 msg += QString(
"\n\t\t\tCurrently recording: %1 %2 %3 %4")
686 LOG(VB_GENERAL, LOG_INFO,
LOC + msg);
735 LOG(VB_RECORD, LOG_INFO,
LOC +
736 QString(
"SetRecordingStatus(%1->%2) on line %3")
739 QString::number(line)));
758 if (now < m_curRecording->GetDesiredEndTime())
800 LOG(VB_GENERAL, LOG_ERR,
LOC +
801 QString(
"Unknown state in RemoveRecording: %1")
820 QString msg =
"Unknown state in RemovePlaying: %1";
837 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"StartedRecording(%1) fn(%2)")
869 LOG((recq->
IsDamaged()) ? VB_GENERAL : VB_RECORD, LOG_INFO,
870 LOC + QString(
"FinishedRecording(%1) %2 recq:\n%3")
872 (recq->
IsDamaged()) ?
"damaged" :
"good",
889 bool was_finished =
false;
890 static QMutex s_finRecLock;
891 static QHash<QString,QDateTime> s_finRecMap;
893 QMutexLocker locker(&s_finRecLock);
895 QDateTime expired = now.addSecs(-5LL * 60);
896 QHash<QString,QDateTime>::iterator it = s_finRecMap.begin();
897 while (it != s_finRecMap.end())
900 it = s_finRecMap.erase(it);
905 it = s_finRecMap.find(key);
906 if (it != s_finRecMap.end())
909 s_finRecMap[key] = now;
913 LOG(VB_RECORD, LOG_INFO,
LOC +
914 QString(
"FinishedRecording(%1) %2 quality"
915 "\n\t\t\ttitle: %3\n\t\t\t"
916 "in recgroup: %4 status: %5:%6 %7 %8")
918 is_good ?
"Good" :
"Bad",
924 was_finished?
"already_finished":
"finished_now"));
948 if (avg_height > 2000)
950 else if (avg_height > 1000)
952 else if (avg_height > 700)
955 flags |= VID_PROGRESSIVE;
957 flags |= VID_DAMAGED;
960 flags |= VID_WIDESCREEN;
963 (VID_4K | VID_1080 | VID_720 | VID_DAMAGED |
964 VID_WIDESCREEN | VID_PROGRESSIVE, flags);
980 if (curRec->
IsLocal() && (fsize >= 1000) &&
990 if (recgrp !=
"LiveTV")
992 LOG(VB_RECORD, LOG_INFO,
LOC +
993 QString(
"FinishedRecording -- UPDATE_RECORDING_STATUS: %1")
996 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
1010 QString message = QString(
"DONE_RECORDING %1 %2 %3")
1016 QHash<QString,int>::iterator autoJob =
1020 LOG(VB_GENERAL, LOG_INFO,
1021 "autoRunJobs not initialized until FinishedRecording()");
1027 LOG(VB_JOBQUEUE, LOG_INFO, QString(
"AutoRunJobs 0x%1").arg(*autoJob,0,16));
1028 if ((recgrp ==
"LiveTV") || (fsize < 1000) ||
1042 #define TRANSITION(ASTATE,BSTATE) \
1043 ((m_internalState == (ASTATE)) && (m_desiredNextState == (BSTATE)))
1044 #define SET_NEXT() do { nextState = m_desiredNextState; changed = true; } while(false)
1045 #define SET_LAST() do { nextState = m_internalState; changed = true; } while(false)
1059 bool changed =
false;
1061 QString transMsg = QString(
" %1 to %2")
1066 LOG(VB_GENERAL, LOG_ERR,
LOC +
1067 "HandleStateChange(): Null transition" + transMsg);
1076 LOG(VB_EIT, LOG_INFO,
LOC + QString(
"Stop EIT scan on input %1").arg(
GetInputId()));
1095 auto *tv_rec =
s_inputs.value(input);
1098 LOG(VB_EIT, LOG_INFO,
LOC +
1099 QString(
"Stop EIT scan active on conflicting input %1")
1101 tv_rec->m_scanner->StopActiveScan();
1143 QString msg = (changed) ?
"Changing from" :
"Unknown state transition:";
1144 LOG(VB_GENERAL, LOG_INFO,
LOC + msg + transMsg);
1191 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"TeardownRecorder(%1)")
1192 .arg((request_flags &
kFlagKillRec) ?
"kFlagKillRec" :
""));
1205 __FILE__, __LINE__);
1222 LOG(VB_FILE, LOG_INFO,
LOC +
"calling StopReads()");
1274 #endif // USING_V4L2
1282 "SELECT SUM(useeit) "
1283 "FROM videosource, capturecard "
1284 "WHERE videosource.sourceid = capturecard.sourceid AND"
1285 " capturecard.cardid = :INPUTID");
1294 return query.
value(0).toBool();
1302 "SELECT SUM(dishnet_eit) "
1303 "FROM videosource, capturecard "
1304 "WHERE videosource.sourceid = capturecard.sourceid AND"
1305 " capturecard.cardid = :INPUTID");
1314 return query.
value(0).toBool();
1323 "SELECT MAX(cardid) "
1324 "FROM capturecard ");
1332 return query.
value(0).toInt();
1339 auto timeout = std::chrono::seconds(
MythRandom(0, eitTransportTimeout.count() / 3));
1344 if (highest_input > 0)
1345 timeout += eitTransportTimeout * inputId / highest_input;
1378 __FILE__, __LINE__);
1384 LOG(VB_GENERAL, LOG_ERR,
LOC +
1385 "RunTV encountered fatal error, exiting event thread.");
1434 QString message = QString(
"QUIT_LIVETV %1").arg(
m_inputId);
1452 bool enable_ui =
true;
1468 LOG(VB_RECORD, LOG_INFO,
LOC +
1469 "Switching Buffer (" +
1470 QString(
"!has_rec(%1) && ").arg(has_rec) +
1471 QString(
"!rec_soon(%1) && (").arg(rec_soon) +
1484 LOG(VB_RECORD, LOG_INFO,
"Waiting for ringbuffer switch");
1494 LOG(VB_RECORD, LOG_INFO,
LOC +
"Enabling Full LiveTV UI.");
1495 QString message = QString(
"LIVETV_WATCH %1 0").arg(
m_inputId);
1513 bool conflicting_input =
false;
1519 LOG(VB_EIT, LOG_INFO,
LOC +
1520 QString(
"EIT scanning disabled for input %1")
1526 LOG(VB_EIT, LOG_INFO,
LOC +
1527 QString(
"EIT scanning disabled for video source %1")
1533 LOG(VB_EIT, LOG_INFO,
LOC +
1534 QString(
"EIT scanning enabled for input %1 connected to video source %2 '%3'")
1541 bool allow_eit =
true;
1544 for (
uint i = 0; i < inputids.size() && allow_eit; ++i)
1553 for (
auto input : inputids)
1555 auto *tv_rec =
s_inputs.value(input);
1556 if (tv_rec && tv_rec->m_scanner)
1558 conflicting_input =
true;
1561 LOG(VB_EIT, LOG_INFO,
LOC +
1562 QString(
"EIT scan on conflicting input %1").arg(input));
1564 busy_input.
m_inputId = tv_rec->m_inputId;
1573 LOG(VB_EIT, LOG_INFO,
LOC +
1574 QString(
"Start EIT active scan on input %1")
1579 if (conflicting_input)
1586 const int seconds_postpone = 300;
1587 LOG(VB_EIT, LOG_INFO,
LOC +
1588 QString(
"Postponing EIT scan on input %1 for %2 seconds because input %3 is busy")
1601 LOG(VB_EIT, LOG_INFO,
LOC +
1602 QString(
"Stop EIT scan on input %1 to allow scan on a conflicting input")
1667 while (!ok && (
t.elapsed() < time))
1691 std::chrono::milliseconds te = t2.
elapsed();
1692 if (!ok && te < 10ms)
1693 std::this_thread::sleep_for(10ms - te);
1706 LOG(VB_RECORD, LOG_INFO,
LOC +
"Deleting stale pending recording " +
1707 QString(
"[%1] '%2'")
1708 .arg((*it).m_info->GetInputID())
1709 .arg((*it).m_info->GetTitle()));
1711 delete (*it).m_info;
1726 LOG(VB_CHANNEL, LOG_INFO,
1727 LOC +
"Stopping active EIT scan for pending recording.");
1735 bool has_rec =
false;
1739 ((*it).m_info->GetInputID() ==
m_inputId) &&
1745 (*it).m_recordingStart);
1750 if (!(*it).m_ask && !(*it).m_doNotAsk)
1753 auto timeuntil = ((*it).m_doNotAsk) ?
1757 (*it).m_canceled =
true;
1759 QString query = QString(
"ASK_RECORDING %1 %2 %3 %4")
1761 .arg(timeuntil.count())
1762 .arg(has_rec ? 1 : 0)
1763 .arg((*it).m_hasLaterShowing ? 1 : 0);
1765 LOG(VB_GENERAL, LOG_INFO,
LOC + query);
1768 (*it).m_info->ToStringList(msg);
1772 (*it).m_ask = (*it).m_doNotAsk =
false;
1787 "SELECT videodevice, vbidevice, audiodevice, "
1788 " audioratelimit, cardtype, "
1789 " skipbtaudio, signal_timeout, channel_timeout, "
1790 " dvb_wait_for_seqstart, "
1792 " dvb_on_demand, dvb_tuning_delay, dvb_eitscan,"
1794 " firewire_speed, firewire_model, firewire_connection, "
1798 "WHERE cardid = :INPUTID");
1811 test = query.
value(0).toString();
1812 if (!test.isEmpty())
1815 test = query.
value(1).toString();
1816 if (!test.isEmpty())
1819 test = query.
value(2).toString();
1820 if (!test.isEmpty())
1825 test = query.
value(4).toString();
1826 if (!test.isEmpty())
1837 if (table_timeout < 1000)
1849 uint fireoff = dvboff + 3;
1850 firewire_opts.
m_speed = query.
value(fireoff + 0).toUInt();
1852 test = query.
value(fireoff + 1).toString();
1853 if (!test.isEmpty())
1858 parentid = query.
value(15).toUInt();
1875 pid_cache.push_back(item);
1884 bool vctpid_cached =
false;
1885 for (
const auto& pid : pid_cache)
1890 vctpid_cached =
true;
1895 return vctpid_cached;
1915 LOG(VB_RECORD, LOG_INFO,
LOC +
"Setting up table monitoring.");
1919 if (!sm || !dtvchan)
1921 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Setting up table monitoring.");
1932 QString recording_type =
"all";
1938 recording_type = setting->
getValue();
1945 if ((
minor > 0) && (tuningmode ==
"atsc"))
1947 QString msg = QString(
"ATSC channel: %1_%2").arg(major).arg(
minor);
1948 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
1969 LOG(VB_RECORD, LOG_INFO,
LOC +
1970 "Successfully set up ATSC table monitoring.");
1990 LOG(VB_RECORD, LOG_INFO,
LOC +
1991 QString(
"DVB service_id %1 on net_id %2 tsid %3")
1992 .arg(progNum).arg(netid).arg(tsid));
2012 LOG(VB_RECORD, LOG_INFO,
LOC +
2013 "Successfully set up DVB table monitoring.");
2028 QString msg = QString(
"MPEG program number: %1").arg(progNum);
2029 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
2049 LOG(VB_RECORD, LOG_INFO,
LOC +
2050 "Successfully set up MPEG table monitoring.");
2061 for (
auto item = pid_cache.cbegin(); !ok && item != pid_cache.cend(); ++item)
2062 ok |= item->IsPermanent();
2067 QString msg =
"No valid DTV info, ATSC maj(%1) min(%2), MPEG pn(%3)";
2068 LOG(VB_GENERAL, LOG_ERR,
LOC + msg.arg(major).arg(
minor).arg(progNum));
2072 LOG(VB_RECORD, LOG_INFO,
LOC +
2073 "Successfully set up raw pid monitoring.");
2095 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetupSignalMonitor(%1, %2)")
2096 .arg(tablemon).arg(notify));
2119 LOG(VB_RECORD, LOG_INFO,
LOC +
"Signal monitor successfully created");
2124 LOG(VB_GENERAL, LOG_ERR,
LOC +
2125 "Failed to setup digital signal monitoring");
2152 LOG(VB_RECORD, LOG_INFO,
LOC +
"TeardownSignalMonitor() -- begin");
2157 if (dtvMon && dtvChan)
2161 if (!pid_cache.empty())
2171 LOG(VB_RECORD, LOG_INFO,
LOC +
"TeardownSignalMonitor() -- end");
2187 QString msg =
"SetSignalMonitoringRate(%1, %2)";
2188 LOG(VB_RECORD, LOG_INFO,
LOC +
2189 msg.arg(rate.count()).arg(notifyFrontend) +
"-- start");
2195 LOG(VB_GENERAL, LOG_ERR,
LOC +
2196 "Signal Monitoring is notsupported by your hardware.");
2202 LOG(VB_GENERAL, LOG_ERR,
LOC +
2203 "Signal can only be monitored in LiveTV Mode.");
2218 LOG(VB_RECORD, LOG_INFO,
LOC +
2219 msg.arg(rate.count()).arg(notifyFrontend) +
" -- end");
2247 query.
prepare(
"SELECT channel.channum, channel.callsign "
2249 "WHERE channel.chanid = :CHANID");
2251 if (!query.
exec() || !query.
next())
2257 QString channelname = query.
value(0).toString();
2258 QString callsign = query.
value(1).toString();
2261 "SELECT channel.channum "
2262 "FROM channel, capturecard "
2263 "WHERE deleted IS NULL AND "
2264 " ( channel.chanid = :CHANID OR "
2265 " ( channel.channum = :CHANNUM AND "
2266 " channel.callsign = :CALLSIGN ) "
2268 " channel.sourceid = capturecard.sourceid AND "
2269 " capturecard.cardid = :INPUTID");
2271 query.
bindValue(
":CHANNUM", channelname);
2279 else if (query.
size() > 0)
2281 msg =
"Found channel (%1) on current input[%2].";
2288 "SELECT channel.channum, capturecard.cardid "
2289 "FROM channel, capturecard "
2290 "WHERE deleted IS NULL AND "
2291 " ( channel.chanid = :CHANID OR "
2292 " ( channel.channum = :CHANNUM AND "
2293 " channel.callsign = :CALLSIGN ) "
2295 " channel.sourceid = capturecard.sourceid AND "
2296 " capturecard.cardid != :INPUTID");
2298 query.
bindValue(
":CHANNUM", channelname);
2306 else if (query.
next())
2308 msg = QString(
"Found channel (%1) on different input(%2).")
2309 .arg(query.
value(0).toString(), query.
value(1).toString());
2310 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
2314 msg = QString(
"Did not find channel(%1) on any input.").arg(channelname);
2315 LOG(VB_RECORD, LOG_ERR,
LOC + msg);
2340 static QString
add_spacer(
const QString &channel,
const QString &spacer)
2342 QString chan = channel;
2343 if ((chan.length() >= 2) && !spacer.isEmpty())
2344 return chan.left(chan.length()-1) + spacer + chan.right(1);
2376 uint &complete_valid_channel_on_rec,
2377 bool &is_extra_char_useful,
2378 QString &needed_spacer)
const
2380 #if DEBUG_CHANNEL_PREFIX
2381 LOG(VB_GENERAL, LOG_DEBUG, QString(
"CheckChannelPrefix(%1)").arg(
prefix));
2384 static const std::array<const QString,5> s_spacers = {
"",
"_",
"-",
"#",
"." };
2387 QString basequery = QString(
2388 "SELECT channel.chanid, channel.channum, capturecard.cardid "
2389 "FROM channel, capturecard "
2390 "WHERE deleted IS NULL AND "
2391 " channel.channum LIKE '%1%' AND "
2392 " channel.sourceid = capturecard.sourceid");
2394 const std::array<const QString,2> inputquery
2396 QString(
" AND capturecard.cardid = '%1'").arg(
m_inputId),
2397 QString(
" AND capturecard.cardid != '%1'").arg(
m_inputId),
2400 std::vector<unsigned int> fchanid;
2401 std::vector<QString> fchannum;
2402 std::vector<unsigned int> finputid;
2403 std::vector<QString> fspacer;
2405 for (
const auto & str : inputquery)
2407 for (
const auto & spacer : s_spacers)
2410 prefix, (spacer ==
"_") ?
"\\_" : spacer);
2411 query.
prepare(basequery.arg(qprefix) + str);
2417 else if (query.
size())
2419 while (query.
next())
2421 fchanid.push_back(query.
value(0).toUInt());
2422 fchannum.push_back(query.
value(1).toString());
2423 finputid.push_back(query.
value(2).toUInt());
2424 fspacer.emplace_back(spacer);
2425 #if DEBUG_CHANNEL_PREFIX
2426 LOG(VB_GENERAL, LOG_DEBUG,
2427 QString(
"(%1,%2) Adding %3 rec %4")
2428 .arg(i).arg(j).arg(query.
value(1).toString(),6)
2429 .arg(query.
value(2).toUInt()));
2440 is_extra_char_useful =
false;
2441 complete_valid_channel_on_rec = 0;
2442 needed_spacer.clear();
2444 if (fchanid.empty())
2447 if (fchanid.size() == 1)
2449 needed_spacer = fspacer[0];
2452 complete_valid_channel_on_rec = (nc) ? 0 : finputid[0];
2453 is_extra_char_useful = nc;
2461 is_extra_char_useful =
false;
2462 for (
uint i = 0; (i < fchannum.size()) && !is_extra_char_useful; i++)
2465 #if DEBUG_CHANNEL_PREFIX
2466 LOG(VB_GENERAL, LOG_DEBUG, QString(
"is_extra_char_useful(%1!=%2): %3")
2468 .arg(is_extra_char_useful));
2475 for (
size_t i = 0; i < fchannum.size(); i++)
2477 if (fchannum[i] ==
prefix)
2479 complete_valid_channel_on_rec = finputid[i];
2485 if (complete_valid_channel_on_rec != 0)
2489 bool spacer_needed =
true;
2490 for (
uint i = 0; (i < fspacer.size() && spacer_needed); i++)
2491 spacer_needed = !fspacer[i].isEmpty();
2493 needed_spacer = fspacer[0];
2497 for (
size_t i = 0; i < ((is_extra_char_useful) ? 0 : fchanid.size()); i++)
2501 needed_spacer = fspacer[i];
2502 complete_valid_channel_on_rec = finputid[i];
2511 const QString &channum)
2517 if (!videoFilters.isEmpty())
2545 busy_input = &dummy;
2547 busy_input->
Clear();
2564 bool has_pending =
false;
2574 if (!busy_input->
m_inputId && has_pending)
2578 if (timeLeft <= time_buffer)
2701 long long bitrate = 0;
2704 bitrate = 10080000LL;
2708 bitrate = 20200000LL;
2712 bitrate = 22200000LL;
2716 bitrate = 10080000LL;
2844 MythEvent me(
"SCHEDULER_ADD_RECORDING", prog);
2871 LOG(VB_JOBQUEUE, LOG_INFO,
2872 QString(
"InitAutoRunJobs for %1, line %2 -> 0x%3")
2890 LOG(VB_GENERAL, LOG_INFO,
LOC +
2891 QString(
"SetLiveRecording(%1)").arg(recording));
2899 LOG(VB_GENERAL, LOG_INFO,
LOC +
"SetLiveRecording() -- cancel");
2907 LOG(VB_GENERAL, LOG_INFO,
LOC +
"SetLiveRecording() -- record");
2920 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
2937 LOG(VB_RECORD, LOG_INFO,
LOC +
2938 QString(
"StopLiveTV(void) curRec: 0x%1 pseudoRec: 0x%2")
2987 LOG(VB_GENERAL, LOG_ERR,
LOC +
2988 "PauseRecorder() called with no recorder");
3023 LOG(VB_GENERAL, LOG_ERR,
LOC +
3024 QString(
"Channel: \'%1\' was not found in the database.\n"
3025 "\t\tMost likely, the 'starting channel' for this "
3026 "Input Connection is invalid.\n"
3027 "\t\tCould not toggle favorite.").arg(channum));
3034 LOG(VB_RECORD, LOG_ERR,
LOC +
3035 QString(
"ToggleChannelFavorite: Invalid channel group name %1,")
3036 .arg(changroupname));
3043 LOG(VB_RECORD, LOG_ERR,
LOC +
"Unable to toggle channel favorite.");
3046 LOG(VB_RECORD, LOG_INFO,
LOC +
3047 QString(
"Toggled channel favorite.channum %1, chan group %2")
3048 .arg(channum, changroupname));
3066 return (ret < 0) ? -1 : ret / 655;
3086 return (ret < 0) ? -1 : ret / 655;
3120 QString origIn = input;
3121 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetInput(" + input +
") -- begin");
3125 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetInput() -- end no channel class");
3129 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetInput(" + origIn +
":" + input +
3130 ") -- end nothing to do");
3148 LOG(VB_CHANNEL, LOG_INFO,
LOC +
3149 QString(
"SetChannel(%1) -- begin").arg(name));
3182 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"SetChannel(%1) -- end").arg(name));
3194 LOG(VB_CHANNEL, LOG_INFO,
LOC +
3195 QString(
"QueueEITChannelChange(%1)").arg(name));
3212 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
3213 QString(
"QueueEITChannelChange(%1) %2")
3214 .arg(name, ok ?
"done" :
"failed"));
3220 QString &title, QString &subtitle,
3221 QString &desc, QString &category,
3222 QString &starttime, QString &endtime,
3223 QString &callsign, QString &iconpath,
3224 QString &channum,
uint &sourceChanid,
3225 QString &seriesid, QString &programid)
3227 QString compare =
"<=";
3228 QString sortorder =
"desc";
3233 chanid = sourceChanid;
3281 QString querystr = QString(
3282 "SELECT title, subtitle, description, category, "
3283 " starttime, endtime, callsign, icon, "
3284 " channum, seriesid, programid "
3285 "FROM program, channel "
3286 "WHERE program.chanid = channel.chanid AND "
3287 " channel.chanid = :CHANID AND "
3288 " starttime %1 :STARTTIME "
3289 "ORDER BY starttime %2 "
3290 "LIMIT 1").arg(compare, sortorder);
3295 query.
bindValue(
":STARTTIME", starttime);
3298 title = subtitle = desc = category =
"";
3299 starttime = endtime = callsign = iconpath =
"";
3300 channum = seriesid = programid =
"";
3308 else if (query.
next())
3310 title = query.
value(0).toString();
3311 subtitle = query.
value(1).toString();
3312 desc = query.
value(2).toString();
3313 category = query.
value(3).toString();
3314 starttime = query.
value(4).toString();
3315 endtime = query.
value(5).toString();
3316 callsign = query.
value(6).toString();
3317 iconpath = query.
value(7).toString();
3318 channum = query.
value(8).toString();
3319 seriesid = query.
value(9).toString();
3320 programid = query.
value(10).toString();
3321 sourceChanid = chanid;
3327 "SELECT channum, callsign, icon "
3329 "WHERE chanid = :CHANID");
3336 else if (query.
next())
3338 sourceChanid = chanid;
3339 channum = query.
value(0).toString();
3340 callsign = query.
value(1).toString();
3341 iconpath = query.
value(2).toString();
3346 QString &callsign, QString &channum,
3347 QString &channame, QString &xmltvid)
const
3354 if ((!chanid || !sourceid) && !
m_channel)
3365 "SELECT callsign, channum, name, xmltvid "
3367 "WHERE chanid = :CHANID");
3378 callsign = query.
value(0).toString();
3379 channum = query.
value(1).toString();
3380 channame = query.
value(2).toString();
3381 xmltvid = query.
value(3).toString();
3387 const QString& oldchannum,
3388 const QString& callsign,
const QString& channum,
3389 const QString& channame,
const QString& xmltvid)
3391 if (!chanid || !sourceid || channum.isEmpty())
3397 "SET callsign = :CALLSIGN, "
3398 " channum = :CHANNUM, "
3399 " name = :CHANNAME, "
3400 " xmltvid = :XMLTVID "
3401 "WHERE chanid = :CHANID AND "
3402 " sourceid = :SOURCEID");
3432 if (oldbuffer && (oldbuffer !=
Buffer))
3444 LOG(VB_GENERAL, LOG_INFO,
LOC +
"RingBufferChanged()");
3466 QString &input)
const
3493 if (
m_channel && !channum.isEmpty() && (channum.indexOf(
"NextChannel") >= 0))
3496 int dir = channum.right(channum.length() - 12).toInt();
3538 if (
mpeg->HasProgram(progNum))
3561 LOG(VB_RECORD, LOG_INFO,
LOC +
3562 "HandleTuning Request: " + request.
toString());
3569 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"On same multiplex");
3583 LOG(VB_RECORD, LOG_INFO,
LOC +
3584 "No recorder yet, calling TuningFrequency");
3589 LOG(VB_RECORD, LOG_INFO,
LOC +
"Waiting for recorder pause..");
3602 LOG(VB_RECORD, LOG_INFO,
LOC +
3603 "Recorder paused, calling TuningFrequency");
3611 if (streamData ==
nullptr)
3634 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"TuningShutdowns(%1)")
3661 if (sd && (sd != rec_sd))
3695 LOG(VB_RECORD, LOG_INFO,
LOC +
"Tearing down RingBuffer");
3723 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"TuningFrequency(%1)")
3744 if (request.
m_minorChan && (tuningmode ==
"atsc"))
3769 slist<<
"message"<<QObject::tr(
"On known multiplex...");
3783 if (!channum.isEmpty())
3796 LOG(VB_GENERAL, LOG_ERR,
LOC +
3797 QString(
"Failed to set channel to %1. Reverting to kState_None")
3806 LOG(VB_GENERAL, LOG_ERR,
LOC +
3807 QString(
"Failed to set channel to %1.").arg(channum));
3826 bool use_dr = use_sm && (livetv || antadj);
3827 bool has_dummy =
false;
3848 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create RingBuffer 1");
3858 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting Signal Monitor");
3863 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to setup signal monitor");
3881 SetVideoStreamsRequired(0);
3908 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
3909 QString(
"Pre-fail start deadline: %1 "
3910 "Start recording deadline: %2 "
3911 "Good signal deadline: %3")
3913 .toString(
"hh:mm:ss.zzz"),
3915 .toString(
"hh:mm:ss.zzz"),
3917 .toString(
"hh:mm:ss.zzz")));
3941 LOG(VB_RECORD, LOG_INFO,
"DummyDTVRecorder -- started");
3967 bool keep_trying =
false;
3980 LOG(VB_RECORD, LOG_INFO,
LOC +
"TuningSignalCheck: Good signal");
3986 QString desc = tr(
"Good signal seen after %1 ms")
3995 tr(
"See 'Tuning timeout' in mythtv-setup "
3996 "for this input."));
3999 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4000 QString(
"It took longer than %1 ms to get a signal lock. "
4001 "Keeping status of '%2'")
4004 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4005 "See 'Tuning timeout' in mythtv-setup for this input");
4014 LOG(VB_GENERAL, LOG_ERR,
LOC +
"TuningSignalCheck: SignalMonitor " +
4027 LOG(VB_GENERAL, LOG_ERR,
LOC +
4028 "TuningSignalCheck: Hit pre-fail timeout");
4042 QString desc = tr(
"Taking more than %1 ms to get a lock.")
4050 tr(
"See 'Tuning timeout' in mythtv-setup "
4051 "for this input."));
4055 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4056 QString(
"TuningSignalCheck: taking more than %1 ms to get a lock. "
4057 "marking this recording as '%2'.")
4060 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4061 "See 'Tuning timeout' in mythtv-setup for this input");
4069 LOG(VB_RECORD, LOG_INFO,
LOC +
4070 QString(
"TuningSignalCheck: Still waiting. Will timeout @ %1")
4072 .toString(
"hh:mm:ss.zzz")));
4083 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
4121 LOG(VB_EIT, LOG_INFO,
LOC +
4122 QString(
"EIT scanning disabled for video source %1")
4131 bool on_host,
bool transcode_bfr_comm,
bool on_line_comm)
4147 if ((!autoTrans) || (autoTrans->
getValue().toInt() == 0))
4171 !transcode_bfr_comm;
4195 QString profileName =
"Live TV";
4196 if (!tvchain && rec)
4199 QString profileRequested = profileName;
4204 LOG(VB_RECORD, LOG_INFO,
LOC +
4205 QString(
"Using profile '%1' to record")
4210 profileName =
"Default";
4213 LOG(VB_RECORD, LOG_INFO,
LOC +
4214 QString(
"Profile '%1' not found, using "
4215 "fallback profile '%2' to record")
4216 .arg(profileRequested, profileName));
4220 LOG(VB_RECORD, LOG_ERR,
LOC +
4221 QString(
"Profile '%1' not found, and unable "
4222 "to load fallback profile '%2'. Results "
4223 "may be unpredicable")
4224 .arg(profileRequested, profileName));
4236 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting Recorder");
4238 bool had_dummyrec =
false;
4244 had_dummyrec =
true;
4267 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create RingBuffer 2");
4276 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"rec->GetPathname(): '%1'")
4281 LOG(VB_GENERAL, LOG_ERR,
LOC +
4282 QString(
"RingBuffer '%1' not open...")
4292 LOG(VB_GENERAL, LOG_ERR,
LOC +
4293 QString(
"Failed to start recorder! ringBuffer is NULL\n"
4294 "\t\t\t\t Tuning request was %1\n")
4299 QString message = QString(
"QUIT_LIVETV %1").arg(
m_inputId);
4309 LOG(VB_GENERAL, LOG_INFO,
LOC +
"TuningNewRecorder - CreateRecorder()");
4318 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to initialize recorder!");
4326 LOG(VB_GENERAL, LOG_ERR,
LOC +
4327 QString(
"Failed to start recorder!\n"
4328 "\t\t\t\t Tuning request was %1\n")
4333 QString message = QString(
"QUIT_LIVETV %1").arg(
m_inputId);
4376 std::this_thread::sleep_for(5us);
4405 LOG(VB_RECORD, LOG_INFO,
LOC +
4406 QString(
"TuningNewRecorder -- UPDATE_RECORDING_STATUS: %1")
4408 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
4426 LOG(VB_RECORD, LOG_INFO,
LOC +
"Restarting Recorder");
4428 bool had_dummyrec =
false;
4439 had_dummyrec =
true;
4465 QString msg1 = QString(
"Recording: %1 %2 %3 %4")
4470 QString msg2 = QString(
"Recording: %1 %2 %3 %4")
4475 LOG(VB_RECORD, LOG_INFO,
LOC +
"Pseudo LiveTV recording starting." +
4476 "\n\t\t\t" + msg1 +
"\n\t\t\t" + msg2);
4493 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetFlags(%1) -> %2 @ %3:%4")
4502 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"ClearFlags(%1) -> %2 @ %3:%4")
4513 msg +=
"FrontendReady,";
4515 msg +=
"RunMainLoop,";
4517 msg +=
"ExitPlayer,";
4519 msg +=
"FinishRecording,";
4523 msg +=
"CancelNextRecording,";
4533 msg +=
"Recording,";
4546 msg +=
"AntennaAdjust,";
4549 msg +=
"PENDINGACTIONS,";
4553 msg +=
"WaitingForRecPause,";
4555 msg +=
"WaitingForSignal,";
4557 msg +=
"NeedToStartRecorder,";
4559 msg +=
"KillRingBuffer,";
4562 msg +=
"ANYRUNNING,";
4566 msg +=
"SignalMonitorRunning,";
4568 msg +=
"EITScannerRunning,";
4570 msg +=
"ANYRECRUNNING,";
4574 msg +=
"DummyRecorderRunning,";
4576 msg +=
"RecorderRunning,";
4580 msg +=
"RingBufferReady,";
4583 msg = QString(
"0x%1").arg(f,0,16);
4611 const QString & channum)
4613 LOG(VB_RECORD, LOG_INFO,
LOC +
"GetProgramRingBufferForLiveTV()");
4635 LOG(VB_GENERAL, LOG_ERR,
LOC +
4636 QString(
"Channel: \'%1\' was not found in the database.\n"
4637 "\t\tMost likely, the 'starting channel' for this "
4638 "Input Connection is invalid.\n"
4639 "\t\tCould not start livetv.").arg(channum));
4662 LOG(VB_GENERAL, LOG_ERR,
LOC +
"GetProgramRingBufferForLiveTV()"
4663 "\n\t\t\tProgramInfo is invalid."
4693 if (!(*
Buffer) || !(*Buffer)->IsOpen())
4695 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"RingBuffer '%1' not open...")
4710 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"CreateLiveTVRingBuffer(%1)")
4727 LOG(VB_GENERAL, LOG_ERR,
LOC +
4728 QString(
"CreateLiveTVRingBuffer(%1) failed").arg(channum));
4755 bool discont,
bool set_rec)
4760 msg = QString(
" curRec(%1) curRec.size(%2)")
4764 LOG(VB_RECORD, LOG_INFO,
LOC +
4765 QString(
"SwitchLiveTVRingBuffer(discont %1, set_next_rec %2)")
4766 .arg(discont).arg(set_rec) + msg);
4824 LOG(VB_RECORD, LOG_INFO,
LOC +
"SwitchRecordingRingBuffer()");
4828 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4829 "already switching.");
4835 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4836 "invalid recorder.");
4842 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4843 "invalid recording.");
4849 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4850 "Not the same channel.");
4861 LOG(VB_RECORD, LOG_ERR,
LOC +
4862 QString(
"SwitchRecordingRingBuffer() -> "
4863 "cannot switch profile '%1' to '%2'")
4875 if (!buffer || !buffer->
IsOpen())
4882 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer() -> "
4883 "Failed to create new RB.");
4892 LOG(VB_RECORD, LOG_INFO,
LOC +
"SwitchRecordingRingBuffer -> done");
4898 QMap<uint,TVRec*>::const_iterator it =
s_inputs.constFind(inputid);
4906 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"enable:%1").arg(enable));
4933 return QString(
"Program(%1) channel(%2) input(%3) flags(%4)")
bool CreateLiveTVRingBuffer(const QString &channum)
uint GetMajorChannel(void) const
Returns major channel, 0 if unknown.
BrowseDirection
Used to request ProgramInfo for channel browsing.
bool isActive(void) const
@ BROWSE_SAME
Fetch browse information on current channel and time.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
virtual void Close(void)=0
Closes the channel changing hardware to use.
void SetFlags(uint f, const QString &file, int line)
bool GetKeyframeDurations(int64_t start, int64_t end, frm_pos_map_t &map) const
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
void AddFlags(uint64_t _flags) override
bool IsReallyRecording(void)
Returns true if frontend can consider the recorder started.
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
std::vector< uint > m_possibleConflicts
virtual bool Init(QString &startchannel, bool setchan)
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
static const uint kFlagNoRec
void RecordPending(const ProgramInfo *rcinfo, std::chrono::seconds secsleft, bool hasLater)
Tells TVRec "rcinfo" is the next pending recording.
static const uint kFlagErrored
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
QDateTime m_startRecordingDeadline
static void RemoveJobsFromMask(int jobs, int &mask)
static const uint kFlagEITScannerRunning
void FinishedRecording(bool allowReRecord)
If not a premature stop, adds program to history of recorded programs.
@ kState_None
None State, this is the initial state in both TV and TVRec, it indicates that we are ready to change ...
static bool JobIsInMask(int job, int mask)
void SetPseudoLiveTVRecording(RecordingInfo *pi)
Sets the pseudo LiveTV RecordingInfo.
void SetVideoStreamsRequired(uint num)
void SetDVBService(uint network_id, uint transport_id, int service_id)
void StopEITEventProcessing(void)
Stops inserting Event Information Tables into DB.
bool WaitForEventThreadSleep(bool wake=true, std::chrono::milliseconds time=std::chrono::milliseconds::max())
static void error(const char *str,...)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
void SetRecordingStatus(RecStatus::Type status)
uint QueryMplexID(void) const
Queries multiplex any recording would be made on, zero if unknown.
static RecorderBase * CreateRecorder(TVRec *tvrec, ChannelBase *channel, RecordingProfile &profile, const GeneralDBOptions &genOpt)
bool ShouldSwitchToAnotherInput(const QString &chanid) const
Checks if named channel exists on current tuner, or another tuner.
static QString GetSourceName(uint sourceid)
static const uint kFlagRecording
final result desired is a timed recording
bool Save(bool sendSig=true)
virtual bool IsAllGood(void) const
static bool QueueJob(int jobType, uint chanid, const QDateTime &recstartts, const QString &args="", const QString &comment="", QString host="", int flags=0, int status=JOB_QUEUED, QDateTime schedruntime=QDateTime())
static QString GetInputName(uint inputid)
A QElapsedTimer based timer to replace use of QTime as a timer.
QMutex m_triggerEventSleepLock
virtual bool Open(void)=0
Opens the channel changing hardware for use.
TuningQueue m_tuningRequests
std::chrono::seconds m_eitScanPeriod
uint RemoteGetState(uint inputid)
virtual QString GetInputName(void) const
const QString kRecorderInUseID
void SetDuration(std::chrono::seconds Duration)
Contains a duration during which the notification will be displayed for. The duration is informative ...
void ApplyRecordRecID(void)
Sets recordid to match RecordingRule recordid.
void SetCaching(bool cacheTables)
virtual void SetRecordingID(uint _recordedid)
bool Init(void)
Performs instance initialization, returns true on success.
static bool IsSupported(const QString &cardtype)
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
ChannelChangeDirection
ChannelChangeDirection is an enumeration of possible channel changing directions.
bool IsBusy(InputInfo *busy_input=nullptr, std::chrono::seconds time_buffer=5s) const
Returns true if the recorder is busy, or will be within the next time_buffer seconds.
void StartEITEventProcessing(ChannelBase *channel, EITSource *eitSource)
Start inserting Event Information Tables from the multiplex we happen to be tuned to into the databas...
Holds information on a TV Program one might wish to record.
void ToggleChannelFavorite(const QString &changroupname)
Toggles whether the current channel should be on our favorites list.
std::chrono::seconds m_eitTransportTimeout
uint64_t GetFilesize(void) const override
virtual bool IsOpen(void) const =0
Reports whether channel is already open.
bool QueryAverageScanProgressive(void) const
If present in recording this loads average video scan type of the main video stream from database's s...
virtual void Unpause(void)
Unpause tells recorder to unpause.
static const uint kFlagRingBufferReady
uint GetRecordingID(void) const
MythMediaBuffer * m_buffer
virtual bool IsErrored(void)=0
Tells us whether an unrecoverable error has been encountered.
QString GetID(void) const
QWaitCondition m_triggerLiveTVDir
MThread * m_eventThread
Event processing thread, runs TVRec::run().
static const uint kFlagRecorderRunning
This class is used as a container for messages.
static const uint kFlagRec
RecStatus::Type m_recStatus
static bool GetATSCChannel(uint sourceid, const QString &channum, uint &major, uint &minor)
QString SetInput(QString input)
Changes to the specified input.
def write(text, progress=True)
static int GetProgramNumber(uint sourceid, const QString &channum)
static const uint64_t kDTVSigMon_WaitForMGT
uint GetSourceID(void) const
Returns current source id.
static bool QueueRecordingJobs(const RecordingInfo &recinfo, int jobTypes=JOB_NONE)
QVariant value(int i) const
QString m_overRecordCategory
QString GetCategory(void) const
virtual void SetStreamData(MPEGStreamData *data)
bool GetProgramRingBufferForLiveTV(RecordingInfo **pginfo, MythMediaBuffer **Buffer, const QString &channum)
uint GetMinorChannel(void) const
Returns minor channel, 0 if unknown.
static void apply_broken_dvb_driver_crc_hack(ChannelBase *, MPEGStreamData *)
QString toString(void) const
static ChannelBase * CreateChannel(TVRec *tvrec, const GeneralDBOptions &genOpt, const DVBDBOptions &dvbOpt, const FireWireDBOptions &fwOpt, const QString &startchannel, bool enter_power_save_mode, QString &rbFileExt, bool setchan)
MPEGStreamData * GetStreamData()
Returns the MPEG stream data if it exists.
int TotalSize(void) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void EnableActiveScan(bool enable)
@ BROWSE_UP
Fetch information on previous channel.
RecordingInfo * m_curRecording
void SaveCommFlagged(CommFlagStatus flag)
Set "commflagged" field in "recorded" table to "flag".
void StopRecording(bool killFile=false)
Changes from a recording state to kState_None.
bool GetKeyframePositions(long long start, long long end, frm_pos_map_t &map) const
@ CHANNEL_DIRECTION_FAVORITE
void start(void)
starts measuring elapsed time.
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
long long GetFramesWritten(void)
Returns number of frames written to disk by recorder.
static bool GetDevices(uint inputid, uint &parentid, GeneralDBOptions &gen_opts, DVBDBOptions &dvb_opts, FireWireDBOptions &firewire_opts)
void UpdateInUseMark(bool force=false)
QString GetInput(void) const
Returns current input.
static uint GetMplexID(uint sourceid, const QString &channum)
static const uint kFlagDummyRecorderRunning
virtual QString GetChannelName(void) const
bool IsDamaged(void) const
void UpdateRecordingEnd(void)
Update information in the recorded table when the end-time of a recording is changed.
DTVChannel * GetDTVChannel(void)
static const uint kFlagPendingActions
bool CheckChannelPrefix(const QString &prefix, uint &complete_valid_channel_on_rec, bool &is_extra_char_useful, QString &needed_spacer) const
Checks a prefix against the channels in the DB.
virtual void Pause(bool clear=true)
Pause tells recorder to pause, it should not block.
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
virtual int GetPictureAttribute(PictureAttribute) const
QString GetRecordingGroup(void) const
QString GetChainID(void)
Get the chainid of the livetv instance.
QDateTime m_eitScanStopTime
std::chrono::seconds m_overRecordSecCat
bool GetKeyframeDurations(long long start, long long end, frm_pos_map_t &map) const
bool QueryTuningInfo(QString &channum, QString &input) const
Returns the channel and input needed to record the program.
static void GetPidsToCache(DTVSignalMonitor *dtvMon, pid_cache_t &pid_cache)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
bool TuningOnSameMultiplex(TuningRequest &request)
void TeardownRecorder(uint request_flags)
Tears down the recorder.
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
long long GetFilePosition(void)
Returns total number of bytes written by RingBuffer.
QString GetPathname(void) const
static const uint kFlagCancelNextRecording
QString toStringXML(void) const
virtual void Renumber(uint sourceid, const QString &oldChanNum, const QString &newChanNum)
Changes a channum if we have it cached anywhere.
RecordingInfo * SwitchRecordingRingBuffer(const RecordingInfo &rcinfo)
QDateTime GetRecordEndTime(const ProgramInfo *pi) const
Returns recording end time with proper post-roll.
static QString toString(RecStatus::Type recstatus, uint id)
Converts "recstatus" into a short (unreadable) string.
QDateTime m_recordEndTime
QString GetTuningMode(void) const
Returns tuning mode last set by SetTuningMode().
uint GetOriginalNetworkID(void) const
Returns DVB original_network_id, 0 if unknown.
ProgramInfo * GetProgramAt(int at) const
Returns program at the desired location.
void StopActiveScan(void)
Stop active EIT scan.
static bool IsRequired(const QString &cardtype)
Returns true iff the card type supports signal monitoring.
void SetIgnoreCRC(bool haveCRCbug)
std::chrono::seconds m_overRecordSecNrml
void RecorderPaused(void)
This is a callback, called by the "recorder" instance when it has actually paused.
std::chrono::seconds secsInFuture(const QDateTime &future)
PendingMap m_pendingRecordings
#define TRANSITION(ASTATE, BSTATE)
static const uint kFlagAnyRecRunning
virtual bool InitPictureAttributes(void)
uint GetInputId(void) const
Returns the inputid.
void MarkAsInUse(bool inuse, const QString &usedFor="")
Tracks a recording's in use status, to prevent deletion and to allow the storage scheduler to perform...
uint GetTransportID(void) const
Returns DVB transport_stream_id, 0 if unknown.
virtual void ReturnCachedTable(const PSIPTable *psip) const
@ BROWSE_RIGHT
Fetch information on current channel in the future.
static const uint kFlagWaitingForSignal
static const uint kFlagDetect
void SetPathname(const QString &pn)
void SaveVideoProperties(uint mask, uint video_property_flags)
void SetRecordingEndTime(const QDateTime &dt)
bool CreateChannel(const QString &startchannel, bool enter_power_save_mode)
QHash< QString, int > m_autoRunJobs
RecordingFile * GetRecordingFile() const
void PauseRecorder(void)
Tells "recorder" to pause, used for channel and input changes.
void NotifySchedulerOfRecording(RecordingInfo *rec)
Tell scheduler about the recording.
void SetDesiredChannel(int major, int minor)
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
static const uint64_t kDVBSigMon_WaitForPos
Wait for rotor to complete turning the antenna.
RecStatus::Type GetRecordingStatus(void) const
void SetRecordingStatus(RecStatus::Type new_status, int line, bool have_lock=false)
MarkTypes QueryAverageAspectRatio(void) const
static bool is_dishnet_eit(uint inputid)
void SetDishNetEIT(bool use_dishnet_eit)
void SetHostPrefix(const QString &prefix)
static QString GenMythURL(const QString &host=QString(), int port=0, QString path=QString(), const QString &storageGroup=QString())
bool RemoteStopRecording(uint inputid)
Abstract class providing a generic interface to tuning hardware.
void SetRingBuffer(MythMediaBuffer *Buffer)
Tells recorder to use an externally created ringbuffer.
uint TablePID(uint i) const
static bool IsEncoder(const QString &rawtype)
bool RemoteIsBusy(uint inputid, InputInfo &busy_input)
static const uint kFlagKillRec
close recorder, discard recording
void SetScheduledEndTime(const QDateTime &dt)
void SaveCachedPids(const pid_cache_t &pid_cache) const
Saves MPEG PIDs to cache to database.
int GetBackendServerPort(void)
Returns the locally defined backend control port.
RecorderBase * m_recorder
void SendSystemEvent(const QString &msg)
virtual void StoreInputChannels(void)
Saves current channel as the default channel for the current input.
long long GetMaxBitrate(void) const
Returns the maximum bits per second this recorder can produce.
void SendEvent(const MythEvent &event)
static const uint kFlagRunMainLoop
void SetRecordingRuleType(RecordingType type)
TVState RemoveRecording(TVState state) const
If "state" is kState_RecordingOnly or kState_WatchingLiveTV, returns a kState_None,...
RecordingInfo * m_pseudoLiveTVRecording
void SetRecordingType(const QString &recording_type)
static QString FlagToString(uint f)
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
QString GetTitle(void) const
void HandleStateChange(void)
Changes the internalState to the desiredNextState if possible.
std::vector< pid_cache_item_t > pid_cache_t
void SetInputType(const QString &type)
Encapsulates data about ATSC stream and emits events for most tables.
static void DBError(const QString &where, const MSqlQuery &query)
bool CheckChannel(const QString &name) const
Checks if named channel exists on current tuner.
static const uint64_t kDTVSigMon_WaitForPMT
virtual void Reset(void)=0
Reset the recorder to the startup state.
static const uint kFlagSignalMonitorRunning
void SetRecordingGroup(const QString &group)
bool SetupSignalMonitor(bool tablemon, bool EITscan, bool notify)
This creates a SignalMonitor instance and begins signal monitoring.
static const uint64_t kDTVSigMon_WaitForPAT
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
QString TuningGetChanNum(const TuningRequest &request, QString &input) const
static const uint kFlagEITScan
final result desired is an EIT Scan
static const uint64_t kDTVSigMon_WaitForSDT
void TeardownSignalMonitor(void)
If a SignalMonitor instance exists, the monitoring thread is stopped and the instance is deleted.
virtual RecordingQuality * GetRecordingQuality(const RecordingInfo *ri) const
Returns a report about the current recordings quality.
bool WaitForNextLiveTVDir(void)
void SetDesiredStartTime(const QDateTime &dt)
static const uint kFlagCloseRec
close recorder, keep recording
int GetAutoRunJobs(void) const
Returns a bitmap of which jobs are attached to this RecordingInfo.
uint GetSourceID(void) const
Encapsulates data about MPEG stream and emits events for each table.
QWaitCondition m_triggerEventSleepWait
double GetFrameRate(void) const
Returns the latest frame rate.
static bool JobIsNotInMask(int job, int mask)
static const uint kFlagKillRingBuffer
void ChangeState(TVState nextState)
Puts a state change on the nextState queue.
void StartActiveScan(TVRec *rec, std::chrono::seconds max_seconds_per_multiplex)
Start active EIT scan.
TVState m_desiredNextState
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
void run(void) override
Event handling method, contains event loop.
bool m_triggerEventLoopSignal
MPEGStreamData * GetStreamData(void) const
static QString add_spacer(const QString &channel, const QString &spacer)
Adds the spacer before the last character in chan.
virtual bool IsRecording(void)
Tells whether the StartRecorder() loop is running.
AutoExpireType GetAutoExpire(void) const
void TuningShutdowns(const TuningRequest &request)
This shuts down anything that needs to be shut down before handling the passed in tuning request.
QString m_liveTVStartChannel
@ kState_Error
Error State, if we ever try to enter this state errored is set.
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
friend class TuningRequest
virtual int GetVideoFd(void)=0
Returns file descriptor of recorder device.
virtual QString getValue(void) const
void ReloadAll(const QStringList &data=QStringList())
QDateTime m_eitScanStartTime
int GetPictureAttribute(PictureAttribute attr)
void TuningNewRecorder(MPEGStreamData *streamData)
Creates a recorder instance.
void StartedRecording(const QString &ext)
Inserts this RecordingInfo into the database as an existing recording.
bool GetKeyframePositions(int64_t start, int64_t end, frm_pos_map_t &map) const
Returns byte position in RingBuffer of a keyframes according to recorder.
static QReadWriteLock s_inputsLock
static const uint kFlagWaitingForRecPause
This is a specialization of RecorderBase used to handle MPEG-2, MPEG-4, MPEG-4 AVC,...
@ kState_ChangingState
This is a placeholder state which we never actually enter, but is returned by GetState() when we are ...
bool isConnected(void) const
Only updated once during object creation.
std::vector< uint > m_eitInputs
static const uint kFlagLiveTV
final result desired is LiveTV recording
void SetNextLiveTVDir(QString dir)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
float GetFramerate(void)
Returns recordering frame rate from the recorder.
bool m_signalEventCmdSent
RecStatus::Type GetRecordingStatus(void) const
bool QueueEITChannelChange(const QString &name)
Queues up a channel change for the EITScanner.
std::chrono::seconds m_eitCrawlIdleStart
ATSCStreamData * GetATSCStreamData()
Returns the ATSC stream data if it exists.
QWaitCondition m_triggerEventLoopWait
virtual bool EnterPowerSavingMode(void)
Enters power saving mode if the card supports it.
static bool IsV4L(const QString &rawtype)
bool IsErrored(void) const
Returns true is "errored" is true, false otherwise.
int GetNumSetting(const QString &key, int defaultval=0)
virtual long long GetFramesWritten(void)=0
Returns number of frames written to disk.
void SaveAutoExpire(AutoExpireType autoExpire, bool updateDelete=false)
Set "autoexpire" field in "recorded" table to "autoExpire".
virtual void SetFd(int fd)
Sets file descriptor.
ProgramInfo * GetRecording(void)
Allocates and returns a ProgramInfo for the current recording.
void SpawnLiveTV(LiveTVChain *newchain, bool pip, QString startchan)
Tells TVRec to spawn a "Live TV" recorder.
void CancelNextRecording(bool cancel)
Tells TVRec to cancel the upcoming recording.
QMap< long long, long long > frm_pos_map_t
Frame # -> File offset map.
static SignalMonitor * Init(const QString &cardtype, int db_cardnum, ChannelBase *channel, bool release_stream)
virtual void StopRecording(void)
StopRecording() signals to the recorder that it should stop recording and exit cleanly.
bool m_triggerEventSleepSignal
static QString GetVideoFilters(uint sourceid, const QString &channum)
virtual void Initialize(void)=0
This is called between SetOptionsFromProfile() and run() to initialize any devices,...
QString GetSIStandard(void) const
Returns PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
void GetNextProgram(BrowseDirection direction, QString &title, QString &subtitle, QString &desc, QString &category, QString &starttime, QString &endtime, QString &callsign, QString &iconpath, QString &channum, uint &chanid, QString &seriesid, QString &programid)
virtual bool HasExtraSlowTuning(void) const
bool GetBoolSetting(const QString &key, bool defaultval=false)
void SetProgramNumber(int progNum)
@ kState_WatchingPreRecorded
Watching Pre-recorded is a TV only state for when we are watching a pre-existing recording.
This table tells the decoder on which PIDs to find other tables, and their sizes and each table's cur...
SignalMonitor * m_signalMonitor
int64_t GetKeyframePosition(uint64_t desired) const
Returns byte position in RingBuffer of a keyframe according to recorder.
static bool ToggleChannel(uint chanid, int changrpid, bool delete_chan)
uint GetInputID(void) const
void SetUpdateRate(std::chrono::milliseconds msec)
Sets the number of milliseconds between signal monitoring attempts in the signal monitoring thread.
void SavePositionMap(bool force=false, bool finished=false)
Save the seektable to the DB.
void SetChanID(uint _chanid)
Provides interface to the tuning hardware when using DVB drivers.
QString GetInputType(int pos=-1) const
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
QMutex m_nextLiveTVDirLock
void CheckForRecGroupChange(void)
Check if frontend changed the recording group.
virtual bool SetChannelByString(const QString &chan)=0
RecordingType GetRecordingRuleType(void) const
void IgnoreEncrypted(bool ignore)
QDateTime m_signalEventCmdTimeout
void SetChannel(int major, int minor)
Holds information on recordings and videos.
std::chrono::seconds secsInPast(const QDateTime &past)
bool m_reachedRecordingDeadline
bool GetChannelInfo(uint &chanid, uint &sourceid, QString &callsign, QString &channum, QString &channame, QString &xmltvid) const
void ToStringList(QStringList &list) const
Serializes ProgramInfo into a QStringList which can be passed over a socket.
void AddListener(SignalMonitorListener *listener)
V4LChannel * GetV4LChannel(void)
GeneralDBOptions m_genOpt
QString FindNextDirMostFree(void)
QRecursiveMutex m_pendingRecLock
void RingBufferChanged(MythMediaBuffer *Buffer, RecordingInfo *pginfo, RecordingQuality *recq)
static void AddJobsToMask(int jobs, int &mask)
void TuningRestartRecorder(void)
Restarts a stopped recorder or unpauses a paused recorder.
static constexpr std::chrono::milliseconds kSignalMonitoringRate
How many milliseconds the signal monitor should wait between checks.
bool CheckChannel(const QString &channum) const
uint QueryAverageHeight(void) const
If present in recording this loads average height of the main video stream from database's stream mar...
bool SetupDTVSignalMonitor(bool EITscan)
Tells DTVSignalMonitor what channel to look for.
static int GetChannelGroupId(const QString &changroupname)
static const uint kFlagAnyRunning
void SetNextRecording(const RecordingInfo *ri, MythMediaBuffer *Buffer)
Sets next recording info, to be applied as soon as practical.
std::chrono::milliseconds SetSignalMonitoringRate(std::chrono::milliseconds rate, int notifyFrontend=1)
Sets the signal monitoring rate.
static void GetPreviewImage(const ProgramInfo &pginfo, const QString &token)
Submit a request for the generation of a preview image.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
static const uint kFlagFinishRecording
void SetTuningMode(const QString &tuning_mode)
Sets tuning mode: "mpeg", "dvb", "atsc", etc.
virtual void SetStreamData(MPEGStreamData *data)
Sets the MPEG stream data for DTVSignalMonitor to use, and connects the table signals to the monitor.
This is the coordinating class of the Recorder Subsystem.
void AddHistory(bool resched=true, bool forcedup=false, bool future=false)
Adds recording history, creating "record" it if necessary.
void FinishedRecording(RecordingInfo *curRec, RecordingQuality *recq)
If not a premature stop, adds program to history of recorded programs.
uint m_signalMonitorCheckCnt
virtual void SetRotorTarget(float)
Sets rotor target pos from 0.0 to 1.0.
virtual void SetVideoFilters(QString &filters)=0
Tells recorder which filters to use.
bool IsOnSameMultiplex(void) const
TVState
TVState is an enumeration of the states used by TV and TVRec.
This is a wrapper around QThread that does several additional things.
int GetProgramNumber(void) const
Returns program number in PAT, -1 if unknown.
void AppendNewProgram(ProgramInfo *pginfo, const QString &channum, const QString &inputname, bool discont)
TVState GetState(void) const
Returns the TVState of the recorder.
QDateTime m_signalMonitorDeadline
static uint GetSourceID(uint inputid)
std::chrono::milliseconds m_dvbTuningDelay
bool SwitchLiveTVRingBuffer(const QString &channum, bool discont, bool set_rec)
This class is intended to detect the presence of needed tables.
static bool StateIsPlaying(TVState state)
Returns true if we are in any state associated with a player.
virtual int GetInputID(void) const
bool RemoteRecordPending(uint inputid, const ProgramInfo *pginfo, std::chrono::seconds secsleft, bool hasLater)
virtual void Start()
Start signal monitoring thread.
TuningRequest m_lastTuningRequest
void SetNotifyFrontend(bool notify)
Enables or disables frontend notification of the current signal value.
@ kState_RecordingOnly
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
MThread * m_recorderThread
Recorder thread, runs RecorderBase::run().
void StartedRecording(RecordingInfo *curRec)
Inserts a "curRec" into the database.
void InitAutoRunJobs(RecordingInfo *rec, AutoRunInitType t, RecordingProfile *recpro, int line)
void SendMythSystemRecEvent(const QString &msg, const RecordingInfo *pginfo)
uint GetFlags(void) const
virtual void AddListeningPID(uint pid, PIDPriority priority=kPIDPriorityNormal)
static bool GetInputInfo(InputInfo &input, std::vector< uint > *groupids=nullptr)
QString GetHostName(void)
TVRec(int _inputid)
Performs instance initialization not requiring access to database.
virtual uint GetSourceID(void) const
static bool IsEITCapable(const QString &rawtype)
static const uint kFlagAntennaAdjust
antenna adjusting mode (LiveTV without recording).
static const uint kFlagExitPlayer
QString StateToString(TVState state)
Returns a human readable QString representing a TVState.
Class providing a generic interface to digital tuning hardware.
long long GetKeyframePosition(long long desired) const
Returns closest keyframe position before the desired frame.
bool IsErrored(void) const
@ BROWSE_DOWN
Fetch information on next channel.
void SetRecordingRuleID(uint id)
MPEGStreamData * TuningSignalCheck(void)
This checks if we have a channel lock.
~TVRec(void) override
Stops the event and scanning threads and deletes any ChannelBase, RingBuffer, and RecorderBase instan...
virtual uint GetNextChannel(uint chanid, ChannelChangeDirection direction) const
void GetCachedPids(pid_cache_t &pid_cache) const
Returns cached MPEG PIDs for last tuned channel.
static int get_highest_input(void)
@ BROWSE_FAVORITE
Fetch information on the next favorite channel.
bool SetVideoFiltersForChannel(uint sourceid, const QString &channum)
QString GetSuggestedTuningMode(bool is_live_tv) const
Returns suggested tuning mode: "mpeg", "dvb", or "atsc".
QDateTime m_recordingStart
FireWireDBOptions m_fwOpt
bool HasFlags(uint f) const
DTVRecorder * GetDTVRecorder(void)
static QString GetChanNum(int chan_id)
Returns the channel-number string of the given channel.
RecordingRule * GetRecordingRule(void)
Returns the "record" field, creating it if necessary.
uint GetRecordingRuleID(void) const
RecStatus::Type StartRecording(ProgramInfo *pginfo)
Tells TVRec to Start recording the program "rcinfo" as soon as possible.
bool SetChannelInfo(uint chanid, uint sourceid, const QString &oldchannum, const QString &callsign, const QString &channum, const QString &channame, const QString &xmltvid)
void ApplyRecordRecGroupChange(const QString &newrecgroup)
Sets the recording group, both in this RecordingInfo and in the database.
void SetLiveRecording(int recording)
Tells the Scheduler about changes to the recording status of the LiveTV recording.
static const uint kFlagFrontendReady
uint TableType(uint i) const
void SetChannel(const QString &name, uint requestType=kFlagDetect)
Changes to a named channel on the current tuner.
void StopLiveTV(void)
Tells TVRec to stop a "Live TV" recorder.
static bool get_use_eit(uint inputid)
T dequeue()
Removes item from front of list and returns a copy. O(1).
virtual bool CheckForRingBufferSwitch(void)
If requested, switch to new RingBuffer/ProgramInfo objects.
virtual int IncrRef(void)
Increments reference count.
static std::vector< uint > GetConflictingInputs(uint inputid)
QString QueryRecordingGroup(void) const
Query recgroup from recorded.
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
void HandlePendingRecordings(void)
void TuningFrequency(const TuningRequest &request)
Performs initial tuning required for any tuning event.
TVState RemovePlaying(TVState state) const
Returns TVState that would remove the playing, but potentially keep recording if we are watching an i...
int ChangePictureAttribute(PictureAdjustType type, PictureAttribute attr, bool direction)
Returns current value [0,100] if it succeeds, -1 otherwise.
static bool ApplyCachedPids(DTVSignalMonitor *dtvMon, const DTVChannel *channel)
static bool StateIsRecording(TVState state)
Returns true if "state" is kState_RecordingOnly, or kState_WatchingLiveTV.
volatile bool m_switchingBuffer
RecordingInfo * m_program
void dispatch(const MythEvent &event)
static int init_jobs(const RecordingInfo *rec, RecordingProfile &profile, bool on_host, bool transcode_bfr_comm, bool on_line_comm)
static bool IsChannelReusable(const QString &rawtype)
static bool IsOnSameMultiplex(uint srcid, const QString &new_channum, const QString &old_channum)
uint32_t MythRandom()
generate 32 random bits
void HandleTuning(void)
Handles all tuning events.
bool IsCommercialFree(void) const
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
void SetRecording(const RecordingInfo *pginfo)
Changes the Recording from the one set initially with SetOptionsFromProfile().
static const uint kFlagNeedToStartRecorder
QString LoadProfile(void *tvchain, RecordingInfo *rec, RecordingProfile &profile) const
Acts as glue between ChannelBase, EITSource and EITHelper.
DTVSignalMonitor * GetDTVSignalMonitor(void)
void SetStorageGroup(const QString &group)
void SetRingBuffer(MythMediaBuffer *Buffer)
Sets "ringBuffer", deleting any existing RingBuffer.
static QString GetStartChannel(uint inputid)
const MasterGuideTable * GetCachedMGT(bool current=true) const
QRecursiveMutex m_stateChangeLock
bool IsSameProgramWeakCheck(const ProgramInfo &other) const
Checks for duplicate using only title, chanid and startts.
void ClearFlags(uint f, const QString &file, int line)
static TVRec * GetTVRec(uint inputid)
virtual int ChangePictureAttribute(PictureAdjustType, PictureAttribute, bool)
QMutex m_triggerEventLoopLock
void SetDesiredEndTime(const QDateTime &dt)
QString GetSetting(const QString &key, const QString &defaultval="")
@ BROWSE_LEFT
Fetch information on current channel in the past.
void enqueue(const T &d)
Adds item to the back of the list. O(1).
void FinishedRecording(ProgramInfo *pginfo)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
static QMap< uint, TVRec * > s_inputs
virtual int GetChanID(void) const
QString GetSubtitle(void) const
static std::chrono::seconds eit_start_rand(uint inputId, std::chrono::seconds eitTransportTimeout)
Keeps track of recordings in a current LiveTV instance.
static void Init()
Initializes the some static constants needed by SignalMonitorValue.
void SetRecordingStartTime(const QDateTime &dt)
QDateTime m_preFailDeadline