Go to the documentation of this file.
15 #include "libmythbase/mythconfig.h"
46 #define DEBUG_CHANNEL_PREFIX 0
48 #define LOC QString("TVRec[%1]: ").arg(m_inputId)
49 #define LOC2 QString("TVRec[%1]: ").arg(inputid) // for static functions
56 bool on_host,
bool transcode_bfr_comm,
bool on_line_comm);
58 static std::chrono::seconds
eit_start_rand(
uint inputId, std::chrono::seconds eitTransportTimeout);
86 : m_eventThread(new
MThread(
"TVRecEvent", this)),
94 bool enter_power_save_mode)
96 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"CreateChannel(%1)")
109 startchannel, enter_power_save_mode,
m_rbFileExt, setchan);
117 LOG(VB_GENERAL, LOG_ERR,
LOC +
118 QString(
"CreateChannel(%1) failed due to VBOX not responding "
119 "to network check on inputid [%2]")
129 if (!CardUtil::IsSatIPPresent(
m_inputId))
132 LOG(VB_GENERAL, LOG_ERR,
LOC +
133 QString(
"CreateChannel(%1) failed due to SatIP box not responding "
134 "to network check on inputid [%2]")
166 if (startchannel.isEmpty())
216 LOG(VB_RECORD, LOG_INFO,
LOC +
"TeardownAll");
298 LOG(VB_RECORD, LOG_INFO,
LOC +
"Pending recording revoked on " +
299 QString(
"inputid [%1]").arg(rcinfo->
GetInputID()));
305 (*it).m_doNotAsk = (*it).m_canceled =
true;
310 LOG(VB_RECORD, LOG_INFO,
LOC +
311 QString(
"RecordPending on inputid [%1]").arg(rcinfo->
GetInputID()));
317 pending.
m_ask =
true;
333 for (
uint inputid : inputids)
368 LOG(VB_RECORD, LOG_INFO,
LOC +
369 QString(
"CancelNextRecording(%1) -- begin").arg(cancel));
374 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"CancelNextRecording(%1) -- "
375 "error, unknown recording").arg(cancel));
381 std::vector<unsigned int> &inputids = (*it).m_possibleConflicts;
382 for (
uint inputid : inputids)
384 LOG(VB_RECORD, LOG_INFO,
LOC +
385 QString(
"CancelNextRecording -- inputid 0x%1")
386 .arg((uint64_t)inputid,0,16));
393 LOG(VB_RECORD, LOG_INFO,
LOC +
394 QString(
"CancelNextRecording -- inputid [%1]")
401 (*it).m_canceled =
false;
404 LOG(VB_RECORD, LOG_INFO,
LOC +
405 QString(
"CancelNextRecording(%1) -- end").arg(cancel));
422 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"StartRecording(%1)")
448 .addSecs(post_roll_seconds);
450 QString msg = QString(
"updating recording: %1 %2 %3 %4")
455 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
463 bool cancelNext =
false;
465 PendingMap::iterator it;
470 (*it).m_ask = (*it).m_doNotAsk =
false;
471 cancelNext = (*it).m_canceled;
492 LOG(VB_RECORD, LOG_INFO,
LOC +
493 "Checking input group recorders - begin");
499 std::vector<unsigned int> inputids2;
500 std::vector<TVState> states;
503 for (
uint inputid : inputids)
508 if (is_busy && !sourceid)
518 ((mplexid == 0 || mplexid == 32767) &&
522 inputids2.push_back(inputid);
527 for (
uint i = 0; (i < inputids2.size()) && ok; i++)
529 LOG(VB_RECORD, LOG_INFO,
LOC +
530 QString(
"Attempting to stop input [%1] in state %2")
537 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"a [%1]: %2")
545 QString message = QString(
"QUIT_LIVETV %1").arg(inputids2[i]);
550 LOG(VB_RECORD, LOG_INFO,
LOC +
551 QString(
"Stopping recording on [%1], %2") .arg(inputids2[i])
552 .arg(success ?
"succeeded" :
"failed"));
566 LOG(VB_RECORD, LOG_INFO,
LOC +
"Checking input group recorders - done");
569 bool did_switch =
false;
573 did_switch = (
nullptr != ri2);
594 QString message = QString(
"LIVETV_EXITED");
616 LOG(VB_RECORD, LOG_WARNING,
LOC +
"Still failing.");
628 QString message = QString(
"LIVETV_WATCH %1 1").arg(
m_inputId);
634 else if (!did_switch)
636 QString msg = QString(
"Wanted to record: %1 %2 %3 %4\n\t\t\t")
644 msg +=
"But a user has canceled this recording";
649 msg += QString(
"But the current state is: %1")
656 msg += QString(
"\n\t\t\tCurrently recording: %1 %2 %3 %4")
663 LOG(VB_GENERAL, LOG_INFO,
LOC + msg);
712 LOG(VB_RECORD, LOG_INFO,
LOC +
713 QString(
"SetRecordingStatus(%1->%2) on line %3")
716 QString::number(line)));
735 if (now < m_curRecording->GetDesiredEndTime())
777 LOG(VB_GENERAL, LOG_ERR,
LOC +
778 QString(
"Unknown state in RemoveRecording: %1")
797 QString msg =
"Unknown state in RemovePlaying: %1";
814 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"StartedRecording(%1) fn(%2)")
846 LOG((recq->
IsDamaged()) ? VB_GENERAL : VB_RECORD, LOG_INFO,
847 LOC + QString(
"FinishedRecording(%1) %2 recq:\n%3")
849 (recq->
IsDamaged()) ?
"damaged" :
"good",
866 bool was_finished =
false;
867 static QMutex s_finRecLock;
868 static QHash<QString,QDateTime> s_finRecMap;
870 QMutexLocker locker(&s_finRecLock);
872 QDateTime expired = now.addSecs(-60*5);
873 QHash<QString,QDateTime>::iterator it = s_finRecMap.begin();
874 while (it != s_finRecMap.end())
877 it = s_finRecMap.erase(it);
882 it = s_finRecMap.find(key);
883 if (it != s_finRecMap.end())
886 s_finRecMap[key] = now;
890 LOG(VB_RECORD, LOG_INFO,
LOC +
891 QString(
"FinishedRecording(%1) %2 quality"
892 "\n\t\t\ttitle: %3\n\t\t\t"
893 "in recgroup: %4 status: %5:%6 %7 %8")
895 is_good ?
"Good" :
"Bad",
901 was_finished?
"already_finished":
"finished_now"));
924 (VID_4K | VID_1080 | VID_720 | VID_DAMAGED |
925 VID_WIDESCREEN | VID_PROGRESSIVE,
926 ((avg_height > 2000) ? VID_4K :
927 ((avg_height > 1000) ? VID_1080 :
928 ((avg_height > 700) ? VID_720 : 0))) |
929 (progressive ? VID_PROGRESSIVE : 0) |
930 ((is_good) ? 0 : VID_DAMAGED) |
948 if (curRec->
IsLocal() && (fsize >= 1000) &&
958 if (recgrp !=
"LiveTV")
960 LOG(VB_RECORD, LOG_INFO,
LOC +
961 QString(
"FinishedRecording -- UPDATE_RECORDING_STATUS: %1")
964 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
978 QString message = QString(
"DONE_RECORDING %1 %2 %3")
984 QHash<QString,int>::iterator autoJob =
988 LOG(VB_GENERAL, LOG_INFO,
989 "autoRunJobs not initialized until FinishedRecording()");
995 LOG(VB_JOBQUEUE, LOG_INFO, QString(
"AutoRunJobs 0x%1").arg(*autoJob,0,16));
996 if ((recgrp ==
"LiveTV") || (fsize < 1000) ||
1009 #define TRANSITION(ASTATE,BSTATE) \
1010 ((m_internalState == (ASTATE)) && (m_desiredNextState == (BSTATE)))
1011 #define SET_NEXT() do { nextState = m_desiredNextState; changed = true; } while(false)
1012 #define SET_LAST() do { nextState = m_internalState; changed = true; } while(false)
1025 bool changed =
false;
1027 QString transMsg = QString(
" %1 to %2")
1032 LOG(VB_GENERAL, LOG_ERR,
LOC +
1033 "HandleStateChange(): Null transition" + transMsg);
1042 LOG(VB_EIT, LOG_INFO,
LOC + QString(
"Stop EIT scan on input %1").arg(
GetInputId()));
1081 QString msg = (changed) ?
"Changing from" :
"Unknown state transition:";
1082 LOG(VB_GENERAL, LOG_INFO,
LOC + msg + transMsg);
1130 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"TeardownRecorder(%1)")
1131 .arg((request_flags &
kFlagKillRec) ?
"kFlagKillRec" :
""));
1144 __FILE__, __LINE__);
1161 LOG(VB_FILE, LOG_INFO,
LOC +
"calling StopReads()");
1213 #endif // USING_V4L2
1220 "SELECT SUM(useeit) "
1221 "FROM videosource, capturecard "
1222 "WHERE videosource.sourceid = capturecard.sourceid AND"
1223 " capturecard.cardid = :INPUTID");
1232 return query.
value(0).toBool();
1240 "SELECT SUM(dishnet_eit) "
1241 "FROM videosource, capturecard "
1242 "WHERE videosource.sourceid = capturecard.sourceid AND"
1243 " capturecard.cardid = :INPUTID");
1252 return query.
value(0).toBool();
1262 "SELECT MAX(cardid) "
1263 "FROM capturecard ";
1273 return query.
value(0).toInt();
1280 auto timeout = std::chrono::seconds(
MythRandom(0, eitTransportTimeout.count() / 3));
1285 if (highest_input > 0)
1286 timeout += eitTransportTimeout * inputId / highest_input;
1321 __FILE__, __LINE__);
1327 LOG(VB_GENERAL, LOG_ERR,
LOC +
1328 "RunTV encountered fatal error, exiting event thread.");
1377 QString message = QString(
"QUIT_LIVETV %1").arg(
m_inputId);
1393 bool enable_ui =
true;
1409 LOG(VB_RECORD, LOG_INFO,
LOC +
1410 "Switching Buffer (" +
1411 QString(
"!has_rec(%1) && ").arg(has_rec) +
1412 QString(
"!rec_soon(%1) && (").arg(rec_soon) +
1425 LOG(VB_RECORD, LOG_INFO,
"Waiting for ringbuffer switch");
1433 LOG(VB_RECORD, LOG_INFO,
LOC +
"Enabling Full LiveTV UI.");
1434 QString message = QString(
"LIVETV_WATCH %1 0").arg(
m_inputId);
1457 LOG(VB_EIT, LOG_INFO,
LOC +
1458 "EIT scanning disabled for this input.");
1463 LOG(VB_EIT, LOG_INFO,
LOC +
1464 "EIT scanning disabled for all channels on this input.");
1473 bool allow_eit =
true;
1474 std::vector<unsigned int> inputids =
1477 for (
uint i = 0; i < inputids.size() && allow_eit; ++i)
1484 QDateTime::currentDateTime().addYears(1);
1488 LOG(VB_EIT, LOG_INFO,
LOC + QString(
1489 "Postponing EIT scan on input [%1] "
1490 "because input %2 is busy")
1551 while (!ok && (
t.elapsed() < time))
1575 std::chrono::milliseconds te = t2.
elapsed();
1576 if (!ok && te < 10ms)
1577 std::this_thread::sleep_for(10ms - te);
1590 LOG(VB_RECORD, LOG_INFO,
LOC +
"Deleting stale pending recording " +
1591 QString(
"[%1] '%2'")
1592 .arg((*it).m_info->GetInputID())
1593 .arg((*it).m_info->GetTitle()));
1595 delete (*it).m_info;
1610 LOG(VB_CHANNEL, LOG_INFO,
1611 LOC +
"Stopping active EIT scan for pending recording.");
1619 bool has_rec =
false;
1623 ((*it).m_info->GetInputID() ==
m_inputId) &&
1629 (*it).m_recordingStart);
1634 if (!(*it).m_ask && !(*it).m_doNotAsk)
1637 auto timeuntil = ((*it).m_doNotAsk) ?
1641 (*it).m_canceled =
true;
1643 QString query = QString(
"ASK_RECORDING %1 %2 %3 %4")
1645 .arg(timeuntil.count())
1646 .arg(has_rec ? 1 : 0)
1647 .arg((*it).m_hasLaterShowing ? 1 : 0);
1649 LOG(VB_GENERAL, LOG_INFO,
LOC + query);
1652 (*it).m_info->ToStringList(msg);
1656 (*it).m_ask = (*it).m_doNotAsk =
false;
1671 "SELECT videodevice, vbidevice, audiodevice, "
1672 " audioratelimit, cardtype, "
1673 " skipbtaudio, signal_timeout, channel_timeout, "
1674 " dvb_wait_for_seqstart, "
1676 " dvb_on_demand, dvb_tuning_delay, dvb_eitscan,"
1678 " firewire_speed, firewire_model, firewire_connection, "
1682 "WHERE cardid = :INPUTID");
1695 test = query.
value(0).toString();
1696 if (!test.isEmpty())
1699 test = query.
value(1).toString();
1700 if (!test.isEmpty())
1703 test = query.
value(2).toString();
1704 if (!test.isEmpty())
1709 test = query.
value(4).toString();
1710 if (!test.isEmpty())
1721 if (table_timeout < 1000)
1733 uint fireoff = dvboff + 3;
1734 firewire_opts.
m_speed = query.
value(fireoff + 0).toUInt();
1736 test = query.
value(fireoff + 1).toString();
1737 if (!test.isEmpty())
1742 parentid = query.
value(15).toUInt();
1759 pid_cache.push_back(item);
1768 bool vctpid_cached =
false;
1769 for (
auto pid : pid_cache)
1774 vctpid_cached =
true;
1778 return vctpid_cached;
1798 LOG(VB_RECORD, LOG_INFO,
LOC +
"Setting up table monitoring.");
1802 if (!sm || !dtvchan)
1804 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Setting up table monitoring.");
1815 QString recording_type =
"all";
1821 recording_type = setting->
getValue();
1828 if ((
minor > 0) && (tuningmode ==
"atsc"))
1830 QString msg = QString(
"ATSC channel: %1_%2").arg(major).arg(
minor);
1831 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
1852 LOG(VB_RECORD, LOG_INFO,
LOC +
1853 "Successfully set up ATSC table monitoring.");
1873 LOG(VB_RECORD, LOG_INFO,
LOC +
1874 QString(
"DVB service_id %1 on net_id %2 tsid %3")
1875 .arg(progNum).arg(netid).arg(tsid));
1895 LOG(VB_RECORD, LOG_INFO,
LOC +
1896 "Successfully set up DVB table monitoring.");
1911 QString msg = QString(
"MPEG program number: %1").arg(progNum);
1912 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
1932 LOG(VB_RECORD, LOG_INFO,
LOC +
1933 "Successfully set up MPEG table monitoring.");
1944 for (
auto item = pid_cache.cbegin(); !ok && item != pid_cache.cend(); ++item)
1945 ok |= item->IsPermanent();
1950 QString msg =
"No valid DTV info, ATSC maj(%1) min(%2), MPEG pn(%3)";
1951 LOG(VB_GENERAL, LOG_ERR,
LOC + msg.arg(major).arg(
minor).arg(progNum));
1955 LOG(VB_RECORD, LOG_INFO,
LOC +
1956 "Successfully set up raw pid monitoring.");
1978 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetupSignalMonitor(%1, %2)")
1979 .arg(tablemon).arg(notify));
2002 LOG(VB_RECORD, LOG_INFO,
LOC +
"Signal monitor successfully created");
2007 LOG(VB_GENERAL, LOG_ERR,
LOC +
2008 "Failed to setup digital signal monitoring");
2035 LOG(VB_RECORD, LOG_INFO,
LOC +
"TeardownSignalMonitor() -- begin");
2040 if (dtvMon && dtvChan)
2044 if (!pid_cache.empty())
2054 LOG(VB_RECORD, LOG_INFO,
LOC +
"TeardownSignalMonitor() -- end");
2070 QString msg =
"SetSignalMonitoringRate(%1, %2)";
2071 LOG(VB_RECORD, LOG_INFO,
LOC +
2072 msg.arg(rate.count()).arg(notifyFrontend) +
"-- start");
2078 LOG(VB_GENERAL, LOG_ERR,
LOC +
2079 "Signal Monitoring is notsupported by your hardware.");
2085 LOG(VB_GENERAL, LOG_ERR,
LOC +
2086 "Signal can only be monitored in LiveTV Mode.");
2101 LOG(VB_RECORD, LOG_INFO,
LOC +
2102 msg.arg(rate.count()).arg(notifyFrontend) +
" -- end");
2130 query.
prepare(
"SELECT channel.channum, channel.callsign "
2132 "WHERE channel.chanid = :CHANID");
2134 if (!query.
exec() || !query.
next())
2140 QString channelname = query.
value(0).toString();
2141 QString callsign = query.
value(1).toString();
2144 "SELECT channel.channum "
2145 "FROM channel, capturecard "
2146 "WHERE deleted IS NULL AND "
2147 " ( channel.chanid = :CHANID OR "
2148 " ( channel.channum = :CHANNUM AND "
2149 " channel.callsign = :CALLSIGN ) "
2151 " channel.sourceid = capturecard.sourceid AND "
2152 " capturecard.cardid = :INPUTID");
2154 query.
bindValue(
":CHANNUM", channelname);
2162 else if (query.
size() > 0)
2164 msg =
"Found channel (%1) on current input[%2].";
2171 "SELECT channel.channum, capturecard.cardid "
2172 "FROM channel, capturecard "
2173 "WHERE deleted IS NULL AND "
2174 " ( channel.chanid = :CHANID OR "
2175 " ( channel.channum = :CHANNUM AND "
2176 " channel.callsign = :CALLSIGN ) "
2178 " channel.sourceid = capturecard.sourceid AND "
2179 " capturecard.cardid != :INPUTID");
2181 query.
bindValue(
":CHANNUM", channelname);
2189 else if (query.
next())
2191 msg = QString(
"Found channel (%1) on different input(%2).")
2192 .arg(query.
value(0).toString(), query.
value(1).toString());
2193 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
2197 msg = QString(
"Did not find channel(%1) on any input.").arg(channelname);
2198 LOG(VB_RECORD, LOG_ERR,
LOC + msg);
2223 static QString
add_spacer(
const QString &channel,
const QString &spacer)
2225 QString chan = channel;
2226 if ((chan.length() >= 2) && !spacer.isEmpty())
2227 return chan.left(chan.length()-1) + spacer + chan.right(1);
2259 uint &complete_valid_channel_on_rec,
2260 bool &is_extra_char_useful,
2261 QString &needed_spacer)
const
2263 #if DEBUG_CHANNEL_PREFIX
2264 LOG(VB_GENERAL, LOG_DEBUG, QString(
"CheckChannelPrefix(%1)").arg(
prefix));
2267 static const std::array<const QString,5> s_spacers = {
"",
"_",
"-",
"#",
"." };
2270 QString basequery = QString(
2271 "SELECT channel.chanid, channel.channum, capturecard.cardid "
2272 "FROM channel, capturecard "
2273 "WHERE deleted IS NULL AND "
2274 " channel.channum LIKE '%1%' AND "
2275 " channel.sourceid = capturecard.sourceid");
2277 const std::array<const QString,2> inputquery
2279 QString(
" AND capturecard.cardid = '%1'").arg(
m_inputId),
2280 QString(
" AND capturecard.cardid != '%1'").arg(
m_inputId),
2283 std::vector<unsigned int> fchanid;
2284 std::vector<QString> fchannum;
2285 std::vector<unsigned int> finputid;
2286 std::vector<QString> fspacer;
2288 for (
const auto & str : inputquery)
2290 for (
const auto & spacer : s_spacers)
2293 prefix, (spacer ==
"_") ?
"\\_" : spacer);
2294 query.
prepare(basequery.arg(qprefix) + str);
2300 else if (query.
size())
2302 while (query.
next())
2304 fchanid.push_back(query.
value(0).toUInt());
2305 fchannum.push_back(query.
value(1).toString());
2306 finputid.push_back(query.
value(2).toUInt());
2307 fspacer.emplace_back(spacer);
2308 #if DEBUG_CHANNEL_PREFIX
2309 LOG(VB_GENERAL, LOG_DEBUG,
2310 QString(
"(%1,%2) Adding %3 rec %4")
2311 .arg(i).arg(j).arg(query.
value(1).toString(),6)
2312 .arg(query.
value(2).toUInt()));
2323 is_extra_char_useful =
false;
2324 complete_valid_channel_on_rec = 0;
2325 needed_spacer.clear();
2327 if (fchanid.empty())
2330 if (fchanid.size() == 1)
2332 needed_spacer = fspacer[0];
2335 complete_valid_channel_on_rec = (nc) ? 0 : finputid[0];
2336 is_extra_char_useful = nc;
2344 is_extra_char_useful =
false;
2345 for (
uint i = 0; (i < fchannum.size()) && !is_extra_char_useful; i++)
2348 #if DEBUG_CHANNEL_PREFIX
2349 LOG(VB_GENERAL, LOG_DEBUG, QString(
"is_extra_char_useful(%1!=%2): %3")
2351 .arg(is_extra_char_useful));
2358 for (
size_t i = 0; i < fchannum.size(); i++)
2360 if (fchannum[i] ==
prefix)
2362 complete_valid_channel_on_rec = finputid[i];
2368 if (complete_valid_channel_on_rec != 0)
2372 bool spacer_needed =
true;
2373 for (
uint i = 0; (i < fspacer.size() && spacer_needed); i++)
2374 spacer_needed = !fspacer[i].isEmpty();
2376 needed_spacer = fspacer[0];
2380 for (
size_t i = 0; i < ((is_extra_char_useful) ? 0 : fchanid.size()); i++)
2384 needed_spacer = fspacer[i];
2385 complete_valid_channel_on_rec = finputid[i];
2394 const QString &channum)
2400 if (!videoFilters.isEmpty())
2428 busy_input = &dummy;
2430 busy_input->
Clear();
2447 bool has_pending =
false;
2457 if (!busy_input->
m_inputId && has_pending)
2461 if (timeLeft <= time_buffer)
2584 long long bitrate = 0;
2587 bitrate = 10080000LL;
2591 bitrate = 20200000LL;
2595 bitrate = 22200000LL;
2599 bitrate = 10080000LL;
2727 MythEvent me(
"SCHEDULER_ADD_RECORDING", prog);
2754 LOG(VB_JOBQUEUE, LOG_INFO,
2755 QString(
"InitAutoRunJobs for %1, line %2 -> 0x%3")
2773 LOG(VB_GENERAL, LOG_INFO,
LOC +
2774 QString(
"SetLiveRecording(%1)").arg(recording));
2784 LOG(VB_GENERAL, LOG_INFO,
LOC +
"SetLiveRecording() -- cancel");
2792 LOG(VB_GENERAL, LOG_INFO,
LOC +
"SetLiveRecording() -- record");
2805 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
2822 LOG(VB_RECORD, LOG_INFO,
LOC +
2823 QString(
"StopLiveTV(void) curRec: 0x%1 pseudoRec: 0x%2")
2872 LOG(VB_GENERAL, LOG_ERR,
LOC +
2873 "PauseRecorder() called with no recorder");
2908 LOG(VB_GENERAL, LOG_ERR,
LOC +
2909 QString(
"Channel: \'%1\' was not found in the database.\n"
2910 "\t\tMost likely, the 'starting channel' for this "
2911 "Input Connection is invalid.\n"
2912 "\t\tCould not toggle favorite.").arg(channum));
2919 LOG(VB_RECORD, LOG_ERR,
LOC +
2920 QString(
"ToggleChannelFavorite: Invalid channel group name %1,")
2921 .arg(changroupname));
2928 LOG(VB_RECORD, LOG_ERR,
LOC +
"Unable to toggle channel favorite.");
2931 LOG(VB_RECORD, LOG_INFO,
LOC +
2932 QString(
"Toggled channel favorite.channum %1, chan group %2")
2933 .arg(channum, changroupname));
2951 return (ret < 0) ? -1 : ret / 655;
2971 return (ret < 0) ? -1 : ret / 655;
3005 QString origIn = input;
3006 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetInput(" + input +
") -- begin");
3010 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetInput() -- end no channel class");
3014 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetInput(" + origIn +
":" + input +
3015 ") -- end nothing to do");
3033 LOG(VB_CHANNEL, LOG_INFO,
LOC +
3034 QString(
"SetChannel(%1) -- begin").arg(name));
3067 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"SetChannel(%1) -- end").arg(name));
3079 LOG(VB_CHANNEL, LOG_INFO,
LOC +
3080 QString(
"QueueEITChannelChange(%1) -- begin").arg(name));
3097 LOG(VB_CHANNEL, LOG_INFO,
LOC +
3098 QString(
"QueueEITChannelChange(%1) -- end --> %2").arg(name).arg(ok));
3104 QString &title, QString &subtitle,
3105 QString &desc, QString &category,
3106 QString &starttime, QString &endtime,
3107 QString &callsign, QString &iconpath,
3108 QString &channum,
uint &sourceChanid,
3109 QString &seriesid, QString &programid)
3111 QString compare =
"<=";
3112 QString sortorder =
"desc";
3117 chanid = sourceChanid;
3165 QString querystr = QString(
3166 "SELECT title, subtitle, description, category, "
3167 " starttime, endtime, callsign, icon, "
3168 " channum, seriesid, programid "
3169 "FROM program, channel "
3170 "WHERE program.chanid = channel.chanid AND "
3171 " channel.chanid = :CHANID AND "
3172 " starttime %1 :STARTTIME "
3173 "ORDER BY starttime %2 "
3174 "LIMIT 1").arg(compare, sortorder);
3179 query.
bindValue(
":STARTTIME", starttime);
3182 title = subtitle = desc = category =
"";
3183 starttime = endtime = callsign = iconpath =
"";
3184 channum = seriesid = programid =
"";
3192 else if (query.
next())
3194 title = query.
value(0).toString();
3195 subtitle = query.
value(1).toString();
3196 desc = query.
value(2).toString();
3197 category = query.
value(3).toString();
3198 starttime = query.
value(4).toString();
3199 endtime = query.
value(5).toString();
3200 callsign = query.
value(6).toString();
3201 iconpath = query.
value(7).toString();
3202 channum = query.
value(8).toString();
3203 seriesid = query.
value(9).toString();
3204 programid = query.
value(10).toString();
3205 sourceChanid = chanid;
3211 "SELECT channum, callsign, icon "
3213 "WHERE chanid = :CHANID");
3220 else if (query.
next())
3222 sourceChanid = chanid;
3223 channum = query.
value(0).toString();
3224 callsign = query.
value(1).toString();
3225 iconpath = query.
value(2).toString();
3230 QString &callsign, QString &channum,
3231 QString &channame, QString &xmltvid)
const
3238 if ((!chanid || !sourceid) && !
m_channel)
3249 "SELECT callsign, channum, name, xmltvid "
3251 "WHERE chanid = :CHANID");
3262 callsign = query.
value(0).toString();
3263 channum = query.
value(1).toString();
3264 channame = query.
value(2).toString();
3265 xmltvid = query.
value(3).toString();
3271 const QString& oldchannum,
3272 const QString& callsign,
const QString& channum,
3273 const QString& channame,
const QString& xmltvid)
3275 if (!chanid || !sourceid || channum.isEmpty())
3281 "SET callsign = :CALLSIGN, "
3282 " channum = :CHANNUM, "
3283 " name = :CHANNAME, "
3284 " xmltvid = :XMLTVID "
3285 "WHERE chanid = :CHANID AND "
3286 " sourceid = :SOURCEID");
3316 if (oldbuffer && (oldbuffer !=
Buffer))
3328 LOG(VB_GENERAL, LOG_INFO,
LOC +
"RingBufferChanged()");
3348 QString &input)
const
3375 if (
m_channel && !channum.isEmpty() && (channum.indexOf(
"NextChannel") >= 0))
3378 int dir = channum.right(channum.length() - 12).toInt();
3420 if (
mpeg->HasProgram(progNum))
3443 LOG(VB_RECORD, LOG_INFO,
LOC +
3444 "HandleTuning Request: " + request.
toString());
3451 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"On same multiplex");
3465 LOG(VB_RECORD, LOG_INFO,
LOC +
3466 "No recorder yet, calling TuningFrequency");
3471 LOG(VB_RECORD, LOG_INFO,
LOC +
"Waiting for recorder pause..");
3484 LOG(VB_RECORD, LOG_INFO,
LOC +
3485 "Recorder paused, calling TuningFrequency");
3512 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"TuningShutdowns(%1)")
3539 if (sd && (sd != rec_sd))
3573 LOG(VB_RECORD, LOG_INFO,
LOC +
"Tearing down RingBuffer");
3601 LOG(VB_GENERAL, LOG_INFO,
LOC +
"TuningFrequency");
3621 if (request.
m_minorChan && (tuningmode ==
"atsc"))
3646 slist<<
"message"<<QObject::tr(
"On known multiplex...");
3660 if (!channum.isEmpty())
3673 LOG(VB_GENERAL, LOG_ERR,
LOC +
3674 QString(
"Failed to set channel to %1. Reverting to kState_None")
3683 LOG(VB_GENERAL, LOG_ERR,
LOC +
3684 QString(
"Failed to set channel to %1.").arg(channum));
3704 bool use_dr = use_sm && (livetv || antadj);
3705 bool has_dummy =
false;
3726 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create RingBuffer 1");
3736 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting Signal Monitor");
3741 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to setup signal monitor");
3759 SetVideoStreamsRequired(0);
3786 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
3787 QString(
"Pre-fail start deadline: %1 "
3788 "Start recording deadline: %2 "
3789 "Good signal deadline: %3")
3791 .toString(
"hh:mm:ss.zzz"),
3793 .toString(
"hh:mm:ss.zzz"),
3795 .toString(
"hh:mm:ss.zzz")));
3819 LOG(VB_RECORD, LOG_INFO,
"DummyDTVRecorder -- started");
3845 bool keep_trying =
false;
3858 LOG(VB_RECORD, LOG_INFO,
LOC +
"TuningSignalCheck: Good signal");
3864 QString desc = tr(
"Good signal seen after %1 ms")
3873 tr(
"See 'Tuning timeout' in mythtv-setup "
3874 "for this input."));
3877 LOG(VB_GENERAL, LOG_WARNING,
LOC +
3878 QString(
"It took longer than %1 ms to get a signal lock. "
3879 "Keeping status of '%2'")
3882 LOG(VB_GENERAL, LOG_WARNING,
LOC +
3883 "See 'Tuning timeout' in mythtv-setup for this input");
3892 LOG(VB_GENERAL, LOG_ERR,
LOC +
"TuningSignalCheck: SignalMonitor " +
3905 LOG(VB_GENERAL, LOG_ERR,
LOC +
3906 "TuningSignalCheck: Hit pre-fail timeout");
3920 QString desc = tr(
"Taking more than %1 ms to get a lock.")
3928 tr(
"See 'Tuning timeout' in mythtv-setup "
3929 "for this input."));
3933 LOG(VB_GENERAL, LOG_WARNING,
LOC +
3934 QString(
"TuningSignalCheck: taking more than %1 ms to get a lock. "
3935 "marking this recording as '%2'.")
3938 LOG(VB_GENERAL, LOG_WARNING,
LOC +
3939 "See 'Tuning timeout' in mythtv-setup for this input");
3947 LOG(VB_RECORD, LOG_INFO,
LOC +
3948 QString(
"TuningSignalCheck: Still waiting. Will timeout @ %1")
3950 .toString(
"hh:mm:ss.zzz")));
3961 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
3993 LOG(VB_EIT, LOG_INFO,
LOC +
3994 "EIT scanning disabled for all sources on this input.");
4004 bool on_host,
bool transcode_bfr_comm,
bool on_line_comm)
4020 if ((!autoTrans) || (autoTrans->
getValue().toInt() == 0))
4044 !transcode_bfr_comm;
4068 QString profileName =
"Live TV";
4069 if (!tvchain && rec)
4072 QString profileRequested = profileName;
4077 LOG(VB_RECORD, LOG_INFO,
LOC +
4078 QString(
"Using profile '%1' to record")
4083 profileName =
"Default";
4086 LOG(VB_RECORD, LOG_INFO,
LOC +
4087 QString(
"Profile '%1' not found, using "
4088 "fallback profile '%2' to record")
4089 .arg(profileRequested, profileName));
4093 LOG(VB_RECORD, LOG_ERR,
LOC +
4094 QString(
"Profile '%1' not found, and unable "
4095 "to load fallback profile '%2'. Results "
4096 "may be unpredicable")
4097 .arg(profileRequested, profileName));
4109 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting Recorder");
4111 bool had_dummyrec =
false;
4117 had_dummyrec =
true;
4138 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create RingBuffer 2");
4147 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"rec->GetPathname(): '%1'")
4152 LOG(VB_GENERAL, LOG_ERR,
LOC +
4153 QString(
"RingBuffer '%1' not open...")
4163 LOG(VB_GENERAL, LOG_ERR,
LOC +
4164 QString(
"Failed to start recorder! ringBuffer is NULL\n"
4165 "\t\t\t\t Tuning request was %1\n")
4170 QString message = QString(
"QUIT_LIVETV %1").arg(
m_inputId);
4180 LOG(VB_GENERAL, LOG_INFO,
LOC +
"TuningNewRecorder - CreateRecorder()");
4189 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to initialize recorder!");
4197 LOG(VB_GENERAL, LOG_ERR,
LOC +
4198 QString(
"Failed to start recorder!\n"
4199 "\t\t\t\t Tuning request was %1\n")
4204 QString message = QString(
"QUIT_LIVETV %1").arg(
m_inputId);
4245 std::this_thread::sleep_for(5us);
4274 LOG(VB_RECORD, LOG_INFO,
LOC +
4275 QString(
"TuningNewRecorder -- UPDATE_RECORDING_STATUS: %1")
4277 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
4295 LOG(VB_RECORD, LOG_INFO,
LOC +
"Restarting Recorder");
4297 bool had_dummyrec =
false;
4308 had_dummyrec =
true;
4334 QString msg1 = QString(
"Recording: %1 %2 %3 %4")
4339 QString msg2 = QString(
"Recording: %1 %2 %3 %4")
4344 LOG(VB_RECORD, LOG_INFO,
LOC +
"Pseudo LiveTV recording starting." +
4345 "\n\t\t\t" + msg1 +
"\n\t\t\t" + msg2);
4362 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetFlags(%1) -> %2 @ %3:%4")
4371 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"ClearFlags(%1) -> %2 @ %3:%4")
4382 msg +=
"FrontendReady,";
4384 msg +=
"RunMainLoop,";
4386 msg +=
"ExitPlayer,";
4388 msg +=
"FinishRecording,";
4392 msg +=
"CancelNextRecording,";
4402 msg +=
"Recording,";
4415 msg +=
"AntennaAdjust,";
4418 msg +=
"PENDINGACTIONS,";
4422 msg +=
"WaitingForRecPause,";
4424 msg +=
"WaitingForSignal,";
4426 msg +=
"NeedToStartRecorder,";
4428 msg +=
"KillRingBuffer,";
4431 msg +=
"ANYRUNNING,";
4435 msg +=
"SignalMonitorRunning,";
4437 msg +=
"EITScannerRunning,";
4439 msg +=
"ANYRECRUNNING,";
4443 msg +=
"DummyRecorderRunning,";
4445 msg +=
"RecorderRunning,";
4449 msg +=
"RingBufferReady,";
4452 msg = QString(
"0x%1").arg(f,0,16);
4480 const QString & channum)
4482 LOG(VB_RECORD, LOG_INFO,
LOC +
"GetProgramRingBufferForLiveTV()");
4504 LOG(VB_GENERAL, LOG_ERR,
LOC +
4505 QString(
"Channel: \'%1\' was not found in the database.\n"
4506 "\t\tMost likely, the 'starting channel' for this "
4507 "Input Connection is invalid.\n"
4508 "\t\tCould not start livetv.").arg(channum));
4531 LOG(VB_GENERAL, LOG_ERR,
LOC +
"GetProgramRingBufferForLiveTV()"
4532 "\n\t\t\tProgramInfo is invalid."
4562 if (!(*
Buffer) || !(*Buffer)->IsOpen())
4564 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"RingBuffer '%1' not open...")
4579 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"CreateLiveTVRingBuffer(%1)")
4596 LOG(VB_GENERAL, LOG_ERR,
LOC +
4597 QString(
"CreateLiveTVRingBuffer(%1) failed").arg(channum));
4624 bool discont,
bool set_rec)
4629 msg = QString(
" curRec(%1) curRec.size(%2)")
4633 LOG(VB_RECORD, LOG_INFO,
LOC +
4634 QString(
"SwitchLiveTVRingBuffer(discont %1, set_next_rec %2)")
4635 .arg(discont).arg(set_rec) + msg);
4693 LOG(VB_RECORD, LOG_INFO,
LOC +
"SwitchRecordingRingBuffer()");
4697 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4698 "already switching.");
4704 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4705 "invalid recorder.");
4711 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4712 "invalid recording.");
4718 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4719 "Not the same channel.");
4730 LOG(VB_RECORD, LOG_ERR,
LOC +
4731 QString(
"SwitchRecordingRingBuffer() -> "
4732 "cannot switch profile '%1' to '%2'")
4744 if (!buffer || !buffer->
IsOpen())
4751 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer() -> "
4752 "Failed to create new RB.");
4761 LOG(VB_RECORD, LOG_INFO,
LOC +
"SwitchRecordingRingBuffer -> done");
4767 QMap<uint,TVRec*>::const_iterator it =
s_inputs.constFind(inputid);
4775 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.
bool isActive(void) const
@ BROWSE_LEFT
Fetch information on current channel in the past.
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.
@ BROWSE_UP
Fetch information on previous channel.
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.
ChannelChangeDirection
ChannelChangeDirection is an enumeration of possible channel changing directions.
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 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
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.
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.
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
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.
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.
@ kState_Error
Error State, if we ever try to enter this state errored is set.
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.
QDateTime m_recordEndTime
QString GetTuningMode(void) const
Returns tuning mode last set by SetTuningMode().
@ kState_ChangingState
This is a placeholder state which we never actually enter, but is returned by GetState() when we are ...
uint GetOriginalNetworkID(void) const
Returns DVB original_network_id, 0 if unknown.
ProgramInfo * GetProgramAt(int at) const
Returns program at the desired location.
@ kState_None
None State, this is the initial state in both TV and TVRec, it indicates that we are ready to change ...
void StopActiveScan(void)
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
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.
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
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,...
@ CHANNEL_DIRECTION_FAVORITE
bool isConnected(void) const
Only updated once during object creation.
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.
@ BROWSE_DOWN
Fetch information on next channel.
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.
@ BROWSE_RIGHT
Fetch information on current channel in the future.
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)
This table tells the decoder on which PIDs to find other tables, and their sizes and each table's cur...
SignalMonitor * m_signalMonitor
@ BROWSE_FAVORITE
Fetch information on the next favorite channel.
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)
@ kState_WatchingPreRecorded
Watching Pre-recorded is a TV only state for when we are watching a pre-existing recording.
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
TVState
TVState is an enumeration of the states used by TV and TVRec.
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.
@ BROWSE_SAME
Fetch browse information on current channel and time.
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
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
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
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.
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)
BrowseDirection
Used to request ProgramInfo for channel browsing.
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
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)
static QString toString(Type recstatus, uint id)
Converts "recstatus" into a short (unreadable) string.
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.