13#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)
57 bool on_host,
bool transcode_bfr_comm,
bool on_line_comm);
59static std::chrono::seconds
eit_start_rand(
uint inputId, std::chrono::seconds eitTransportTimeout);
87 : m_eventThread(new
MThread(
"TVRecEvent", this)),
95 bool enter_power_save_mode)
97 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"CreateChannel(%1)")
110 startchannel, enter_power_save_mode,
m_rbFileExt, setchan);
118 LOG(VB_GENERAL, LOG_ERR,
LOC +
119 QString(
"CreateChannel(%1) failed due to VBOX not responding "
120 "to network check on inputid [%2]")
130 if (!CardUtil::IsSatIPPresent(
m_inputId))
133 LOG(VB_GENERAL, LOG_ERR,
LOC +
134 QString(
"CreateChannel(%1) failed due to SatIP box not responding "
135 "to network check on inputid [%2]")
162 LOG(VB_CHANNEL, LOG_ERR,
LOC +
163 QString(
"Failed to GetDevices for input %1")
172 if (startchannel.isEmpty())
176 LOG(VB_CHANNEL, LOG_ERR,
LOC +
177 QString(
"Failed to create channel instance for %1")
235 LOG(VB_RECORD, LOG_INFO,
LOC +
"TeardownAll");
319 LOG(VB_RECORD, LOG_INFO,
LOC +
"Pending recording revoked on " +
320 QString(
"inputid [%1]").arg(rcinfo->
GetInputID()));
326 (*it).m_doNotAsk =
true;
327 (*it).m_canceled =
true;
332 LOG(VB_RECORD, LOG_INFO,
LOC +
333 QString(
"RecordPending on inputid [%1]").arg(rcinfo->
GetInputID()));
339 pending.
m_ask =
true;
355 for (
uint inputid : inputids)
390 LOG(VB_RECORD, LOG_INFO,
LOC +
391 QString(
"CancelNextRecording(%1) -- begin").arg(cancel));
396 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"CancelNextRecording(%1) -- "
397 "error, unknown recording").arg(cancel));
403 std::vector<unsigned int> &inputids = (*it).m_possibleConflicts;
404 for (
uint inputid : inputids)
406 LOG(VB_RECORD, LOG_INFO,
LOC +
407 QString(
"CancelNextRecording -- inputid 0x%1")
408 .arg((uint64_t)inputid,0,16));
415 LOG(VB_RECORD, LOG_INFO,
LOC +
416 QString(
"CancelNextRecording -- inputid [%1]")
423 (*it).m_canceled =
false;
426 LOG(VB_RECORD, LOG_INFO,
LOC +
427 QString(
"CancelNextRecording(%1) -- end").arg(cancel));
444 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"StartRecording(%1)")
470 .addSecs(post_roll_seconds);
472 QString msg = QString(
"updating recording: %1 %2 %3 %4")
477 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
485 bool cancelNext =
false;
492 (*it).m_ask = (*it).m_doNotAsk =
false;
493 cancelNext = (*it).m_canceled;
514 LOG(VB_RECORD, LOG_INFO,
LOC +
515 "Checking input group recorders - begin");
521 std::vector<unsigned int> inputids2;
522 std::vector<TVState> states;
524 inputids2.reserve(inputids.size());
525 states.reserve(inputids.size());
528 for (
uint inputid : inputids)
533 if (is_busy && !sourceid)
543 ((mplexid == 0 || mplexid == 32767) &&
547 inputids2.push_back(inputid);
552 for (
uint i = 0; (i < inputids2.size()) && ok; i++)
554 LOG(VB_RECORD, LOG_INFO,
LOC +
555 QString(
"Attempting to stop input [%1] in state %2")
562 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"a [%1]: %2")
570 QString message = QString(
"QUIT_LIVETV %1").arg(inputids2[i]);
575 LOG(VB_RECORD, LOG_INFO,
LOC +
576 QString(
"Stopping recording on [%1], %2") .arg(inputids2[i])
577 .arg(success ?
"succeeded" :
"failed"));
591 LOG(VB_RECORD, LOG_INFO,
LOC +
"Checking input group recorders - done");
594 bool did_switch =
false;
598 did_switch = (
nullptr != ri2);
619 QString message = QString(
"LIVETV_EXITED");
641 LOG(VB_RECORD, LOG_WARNING,
LOC +
"Still failing.");
653 QString message = QString(
"LIVETV_WATCH %1 1").arg(
m_inputId);
659 else if (!did_switch)
661 QString msg = QString(
"Wanted to record: %1 %2 %3 %4\n\t\t\t")
669 msg +=
"But a user has canceled this recording";
674 msg += QString(
"But the current state is: %1")
681 msg += QString(
"\n\t\t\tCurrently recording: %1 %2 %3 %4")
688 LOG(VB_GENERAL, LOG_INFO,
LOC + msg);
737 LOG(VB_RECORD, LOG_INFO,
LOC +
738 QString(
"SetRecordingStatus(%1->%2) on line %3")
741 QString::number(line)));
762 if (now < m_curRecording->GetDesiredEndTime())
804 LOG(VB_GENERAL, LOG_ERR,
LOC +
805 QString(
"Unknown state in RemoveRecording: %1")
824 QString msg =
"Unknown state in RemovePlaying: %1";
841 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"StartedRecording(%1) fn(%2)")
873 LOG((recq->
IsDamaged()) ? VB_GENERAL : VB_RECORD, LOG_INFO,
874 LOC + QString(
"FinishedRecording(%1) %2 recq:\n%3")
876 (recq->
IsDamaged()) ?
"damaged" :
"good",
893 bool was_finished =
false;
894 static QMutex s_finRecLock;
895 static QHash<QString,QDateTime> s_finRecMap;
897 QMutexLocker locker(&s_finRecLock);
899 QDateTime expired = now.addSecs(-5LL * 60);
900 QHash<QString,QDateTime>::iterator it = s_finRecMap.begin();
901 while (it != s_finRecMap.end())
904 it = s_finRecMap.erase(it);
909 it = s_finRecMap.find(key);
910 if (it != s_finRecMap.end())
913 s_finRecMap[key] = now;
917 LOG(VB_RECORD, LOG_INFO,
LOC +
918 QString(
"FinishedRecording(%1) %2 quality"
919 "\n\t\t\ttitle: %3\n\t\t\t"
920 "in recgroup: %4 status: %5:%6 %7 %8")
922 is_good ?
"Good" :
"Bad",
928 was_finished?
"already_finished":
"finished_now"));
952 if (avg_height > 2000)
954 else if (avg_height > 1000)
956 else if (avg_height > 700)
959 flags |= VID_PROGRESSIVE;
961 flags |= VID_DAMAGED;
964 flags |= VID_WIDESCREEN;
967 (VID_4K | VID_1080 | VID_720 | VID_DAMAGED |
968 VID_WIDESCREEN | VID_PROGRESSIVE, flags);
984 if (curRec->
IsLocal() && (fsize >= 1000) &&
994 LOG(VB_RECORD, LOG_INFO,
LOC +
995 QString(
"FinishedRecording -- UPDATE_RECORDING_STATUS: %1")
998 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
1011 QString message = QString(
"DONE_RECORDING %1 %2 %3")
1017 QHash<QString,int>::iterator autoJob =
1021 LOG(VB_GENERAL, LOG_INFO,
1022 "autoRunJobs not initialized until FinishedRecording()");
1028 LOG(VB_JOBQUEUE, LOG_INFO, QString(
"AutoRunJobs 0x%1").arg(*autoJob,0,16));
1029 if ((recgrp ==
"LiveTV") || (fsize < 1000) ||
1043#define TRANSITION(ASTATE,BSTATE) \
1044 ((m_internalState == (ASTATE)) && (m_desiredNextState == (BSTATE)))
1045#define SET_NEXT() do { nextState = m_desiredNextState; changed = true; } while(false)
1046#define SET_LAST() do { nextState = m_internalState; changed = true; } while(false)
1060 bool changed =
false;
1062 QString transMsg = QString(
" %1 to %2")
1067 LOG(VB_GENERAL, LOG_ERR,
LOC +
1068 "HandleStateChange(): Null transition" + transMsg);
1077 LOG(VB_EIT, LOG_INFO,
LOC + QString(
"Stop EIT scan on input %1").arg(
GetInputId()));
1096 auto *tv_rec =
s_inputs.value(input);
1099 LOG(VB_EIT, LOG_INFO,
LOC +
1100 QString(
"Stop EIT scan active on conflicting input %1")
1102 tv_rec->m_scanner->StopActiveScan();
1144 QString msg = changed ?
"Changing from" :
"Unknown state transition:";
1145 LOG(VB_GENERAL, LOG_INFO,
LOC + msg + transMsg);
1192 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"TeardownRecorder(%1)")
1193 .arg((request_flags &
kFlagKillRec) ?
"kFlagKillRec" :
""));
1206 __FILE__, __LINE__);
1223 LOG(VB_FILE, LOG_INFO,
LOC +
"calling StopReads()");
1284 "SELECT SUM(useeit) "
1285 "FROM videosource, capturecard "
1286 "WHERE videosource.sourceid = capturecard.sourceid AND"
1287 " capturecard.cardid = :INPUTID");
1296 return query.
value(0).toBool();
1304 "SELECT SUM(dishnet_eit) "
1305 "FROM videosource, capturecard "
1306 "WHERE videosource.sourceid = capturecard.sourceid AND"
1307 " capturecard.cardid = :INPUTID");
1316 return query.
value(0).toBool();
1325 "SELECT MAX(cardid) "
1326 "FROM capturecard ");
1334 return query.
value(0).toInt();
1341 auto timeout = std::chrono::seconds(
MythRandom(0, eitTransportTimeout.count() / 3));
1346 if (highest_input > 0)
1347 timeout += eitTransportTimeout * inputId / highest_input;
1380 __FILE__, __LINE__);
1386 LOG(VB_GENERAL, LOG_ERR,
LOC +
1387 "RunTV encountered fatal error, exiting event thread.");
1436 QString message = QString(
"QUIT_LIVETV %1").arg(
m_inputId);
1454 bool enable_ui =
true;
1469 LOG(VB_RECORD, LOG_INFO,
LOC +
1470 "Switching Buffer (" +
1471 QString(
"!has_rec(%1) && ").arg(has_rec) +
1472 QString(
"!rec_soon(%1) && (").arg(rec_soon) +
1485 LOG(VB_RECORD, LOG_INFO,
"Waiting for ringbuffer switch");
1495 LOG(VB_RECORD, LOG_INFO,
LOC +
"Enabling Full LiveTV UI.");
1496 QString message = QString(
"LIVETV_WATCH %1 0").arg(
m_inputId);
1514 bool conflicting_input =
false;
1520 LOG(VB_EIT, LOG_INFO,
LOC +
1521 QString(
"EIT scanning disabled for input %1")
1527 LOG(VB_EIT, LOG_INFO,
LOC +
1528 QString(
"EIT scanning disabled for video source %1")
1534 LOG(VB_EIT, LOG_INFO,
LOC +
1535 QString(
"EIT scanning enabled for input %1 connected to video source %2 '%3'")
1542 bool allow_eit =
true;
1545 for (
uint i = 0; i < inputids.size() && allow_eit; ++i)
1554 for (
auto input : inputids)
1556 auto *tv_rec =
s_inputs.value(input);
1557 if (tv_rec && tv_rec->m_scanner)
1559 conflicting_input =
true;
1562 LOG(VB_EIT, LOG_INFO,
LOC +
1563 QString(
"EIT scan on conflicting input %1").arg(input));
1565 busy_input.
m_inputId = tv_rec->m_inputId;
1574 LOG(VB_EIT, LOG_INFO,
LOC +
1575 QString(
"Start EIT active scan on input %1")
1580 if (conflicting_input)
1587 const int seconds_postpone = 300;
1588 LOG(VB_EIT, LOG_INFO,
LOC +
1589 QString(
"Postponing EIT scan on input %1 for %2 seconds because input %3 is busy")
1602 LOG(VB_EIT, LOG_INFO,
LOC +
1603 QString(
"Stop EIT scan on input %1 to allow scan on a conflicting input")
1668 while (!ok && (
t.elapsed() < time))
1692 std::chrono::milliseconds te = t2.
elapsed();
1693 if (!ok && te < 10ms)
1694 std::this_thread::sleep_for(10ms - te);
1707 LOG(VB_RECORD, LOG_INFO,
LOC +
"Deleting stale pending recording " +
1708 QString(
"[%1] '%2'")
1709 .arg((*it).m_info->GetInputID())
1710 .arg((*it).m_info->GetTitle()));
1712 delete (*it).m_info;
1727 LOG(VB_CHANNEL, LOG_INFO,
1728 LOC +
"Stopping active EIT scan for pending recording.");
1736 bool has_rec =
false;
1740 ((*it).m_info->GetInputID() ==
m_inputId) &&
1746 (*it).m_recordingStart);
1751 if (!(*it).m_ask && !(*it).m_doNotAsk)
1754 auto timeuntil = ((*it).m_doNotAsk) ?
1758 (*it).m_canceled =
true;
1760 QString query = QString(
"ASK_RECORDING %1 %2 %3 %4")
1762 .arg(timeuntil.count())
1763 .arg(has_rec ? 1 : 0)
1764 .arg((*it).m_hasLaterShowing ? 1 : 0);
1766 LOG(VB_GENERAL, LOG_INFO,
LOC + query);
1769 (*it).m_info->ToStringList(msg);
1773 (*it).m_ask = (*it).m_doNotAsk =
false;
1788 "SELECT videodevice, vbidevice, audiodevice, "
1789 " audioratelimit, cardtype, "
1790 " skipbtaudio, signal_timeout, channel_timeout, "
1791 " dvb_wait_for_seqstart, "
1793 " dvb_on_demand, dvb_tuning_delay, dvb_eitscan,"
1795 " firewire_speed, firewire_model, firewire_connection, "
1799 "WHERE cardid = :INPUTID");
1812 test = query.
value(0).toString();
1813 if (!test.isEmpty())
1816 test = query.
value(1).toString();
1817 if (!test.isEmpty())
1820 test = query.
value(2).toString();
1821 if (!test.isEmpty())
1826 test = query.
value(4).toString();
1827 if (!test.isEmpty())
1838 if (table_timeout < 1000)
1850 uint fireoff = dvboff + 3;
1851 firewire_opts.
m_speed = query.
value(fireoff + 0).toUInt();
1853 test = query.
value(fireoff + 1).toString();
1854 if (!test.isEmpty())
1859 parentid = query.
value(15).toUInt();
1876 pid_cache.push_back(item);
1885 bool vctpid_cached =
false;
1886 for (
const auto& pid : pid_cache)
1891 vctpid_cached =
true;
1896 return vctpid_cached;
1916 LOG(VB_RECORD, LOG_INFO,
LOC +
"Setting up table monitoring.");
1920 if (!sm || !dtvchan)
1922 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Setting up table monitoring.");
1933 QString recording_type =
"all";
1939 recording_type = setting->
getValue();
1946 if ((
minor > 0) && (tuningmode ==
"atsc"))
1948 QString msg = QString(
"ATSC channel: %1_%2").arg(major).arg(
minor);
1949 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
1970 LOG(VB_RECORD, LOG_INFO,
LOC +
1971 "Successfully set up ATSC table monitoring.");
1991 LOG(VB_RECORD, LOG_INFO,
LOC +
1992 QString(
"DVB service_id %1 on net_id %2 tsid %3")
1993 .arg(progNum).arg(netid).arg(tsid));
2013 LOG(VB_RECORD, LOG_INFO,
LOC +
2014 "Successfully set up DVB table monitoring.");
2029 QString msg = QString(
"MPEG program number: %1").arg(progNum);
2030 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
2050 LOG(VB_RECORD, LOG_INFO,
LOC +
2051 "Successfully set up MPEG table monitoring.");
2062 for (
auto item = pid_cache.cbegin(); !ok && item != pid_cache.cend(); ++item)
2063 ok |= item->IsPermanent();
2068 QString msg =
"No valid DTV info, ATSC maj(%1) min(%2), MPEG pn(%3)";
2069 LOG(VB_GENERAL, LOG_ERR,
LOC + msg.arg(major).arg(
minor).arg(progNum));
2073 LOG(VB_RECORD, LOG_INFO,
LOC +
2074 "Successfully set up raw pid monitoring.");
2096 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetupSignalMonitor(%1, %2)")
2097 .arg(tablemon).arg(notify));
2120 LOG(VB_RECORD, LOG_INFO,
LOC +
"Signal monitor successfully created");
2125 LOG(VB_GENERAL, LOG_ERR,
LOC +
2126 "Failed to setup digital signal monitoring");
2153 LOG(VB_RECORD, LOG_INFO,
LOC +
"TeardownSignalMonitor() -- begin");
2158 if (dtvMon && dtvChan)
2162 if (!pid_cache.empty())
2172 LOG(VB_RECORD, LOG_INFO,
LOC +
"TeardownSignalMonitor() -- end");
2188 QString msg =
"SetSignalMonitoringRate(%1, %2)";
2189 LOG(VB_RECORD, LOG_INFO,
LOC +
2190 msg.arg(rate.count()).arg(notifyFrontend) +
"-- start");
2196 LOG(VB_GENERAL, LOG_ERR,
LOC +
2197 "Signal Monitoring is notsupported by your hardware.");
2203 LOG(VB_GENERAL, LOG_ERR,
LOC +
2204 "Signal can only be monitored in LiveTV Mode.");
2219 LOG(VB_RECORD, LOG_INFO,
LOC +
2220 msg.arg(rate.count()).arg(notifyFrontend) +
" -- end");
2248 query.
prepare(
"SELECT channel.channum, channel.callsign "
2250 "WHERE channel.chanid = :CHANID");
2252 if (!query.
exec() || !query.
next())
2258 QString channelname = query.
value(0).toString();
2259 QString callsign = query.
value(1).toString();
2262 "SELECT channel.channum "
2263 "FROM channel, capturecard "
2264 "WHERE deleted IS NULL AND "
2265 " ( channel.chanid = :CHANID OR "
2266 " ( channel.channum = :CHANNUM AND "
2267 " channel.callsign = :CALLSIGN ) "
2269 " channel.sourceid = capturecard.sourceid AND "
2270 " capturecard.cardid = :INPUTID");
2272 query.
bindValue(
":CHANNUM", channelname);
2280 else if (query.
size() > 0)
2282 msg =
"Found channel (%1) on current input[%2].";
2289 "SELECT channel.channum, capturecard.cardid "
2290 "FROM channel, capturecard "
2291 "WHERE deleted IS NULL AND "
2292 " ( channel.chanid = :CHANID OR "
2293 " ( channel.channum = :CHANNUM AND "
2294 " channel.callsign = :CALLSIGN ) "
2296 " channel.sourceid = capturecard.sourceid AND "
2297 " capturecard.cardid != :INPUTID");
2299 query.
bindValue(
":CHANNUM", channelname);
2307 else if (query.
next())
2309 msg = QString(
"Found channel (%1) on different input(%2).")
2310 .arg(query.
value(0).toString(), query.
value(1).toString());
2311 LOG(VB_RECORD, LOG_INFO,
LOC + msg);
2315 msg = QString(
"Did not find channel(%1) on any input.").arg(channelname);
2316 LOG(VB_RECORD, LOG_ERR,
LOC + msg);
2341static QString
add_spacer(
const QString &channel,
const QString &spacer)
2343 QString chan = channel;
2344 if ((chan.length() >= 2) && !spacer.isEmpty())
2345 return chan.left(chan.length()-1) + spacer + chan.right(1);
2377 uint &complete_valid_channel_on_rec,
2378 bool &is_extra_char_useful,
2379 QString &needed_spacer)
const
2381#if DEBUG_CHANNEL_PREFIX
2382 LOG(VB_GENERAL, LOG_DEBUG, QString(
"CheckChannelPrefix(%1)").arg(
prefix));
2385 static const std::array<const QString,5> s_spacers = {
"",
"_",
"-",
"#",
"." };
2388 QString basequery = QString(
2389 "SELECT channel.chanid, channel.channum, capturecard.cardid "
2390 "FROM channel, capturecard "
2391 "WHERE deleted IS NULL AND "
2392 " channel.channum LIKE '%1%' AND "
2393 " channel.sourceid = capturecard.sourceid");
2395 const std::array<const QString,2> inputquery
2397 QString(
" AND capturecard.cardid = '%1'").arg(
m_inputId),
2398 QString(
" AND capturecard.cardid != '%1'").arg(
m_inputId),
2401 std::vector<unsigned int> fchanid;
2402 std::vector<QString> fchannum;
2403 std::vector<unsigned int> finputid;
2404 std::vector<QString> fspacer;
2406 for (
const auto & str : inputquery)
2408 for (
const auto & spacer : s_spacers)
2411 prefix, (spacer ==
"_") ?
"\\_" : spacer);
2412 query.
prepare(basequery.arg(qprefix) + str);
2418 else if (query.
size())
2420 while (query.
next())
2422 fchanid.push_back(query.
value(0).toUInt());
2423 fchannum.push_back(query.
value(1).toString());
2424 finputid.push_back(query.
value(2).toUInt());
2425 fspacer.emplace_back(spacer);
2426#if DEBUG_CHANNEL_PREFIX
2427 LOG(VB_GENERAL, LOG_DEBUG,
2428 QString(
"(%1,%2) Adding %3 rec %4")
2429 .arg(i).arg(j).arg(query.
value(1).toString(),6)
2430 .arg(query.
value(2).toUInt()));
2441 is_extra_char_useful =
false;
2442 complete_valid_channel_on_rec = 0;
2443 needed_spacer.clear();
2445 if (fchanid.empty())
2448 if (fchanid.size() == 1)
2450 needed_spacer = fspacer[0];
2453 complete_valid_channel_on_rec = nc ? 0 : finputid[0];
2454 is_extra_char_useful = nc;
2462 is_extra_char_useful =
false;
2463 for (
uint i = 0; (i < fchannum.size()) && !is_extra_char_useful; i++)
2466#if DEBUG_CHANNEL_PREFIX
2467 LOG(VB_GENERAL, LOG_DEBUG, QString(
"is_extra_char_useful(%1!=%2): %3")
2469 .arg(is_extra_char_useful));
2476 for (
size_t i = 0; i < fchannum.size(); i++)
2478 if (fchannum[i] ==
prefix)
2480 complete_valid_channel_on_rec = finputid[i];
2486 if (complete_valid_channel_on_rec != 0)
2490 bool spacer_needed =
true;
2491 for (
uint i = 0; (i < fspacer.size() && spacer_needed); i++)
2492 spacer_needed = !fspacer[i].isEmpty();
2494 needed_spacer = fspacer[0];
2498 for (
size_t i = 0; i < (is_extra_char_useful ? 0 : fchanid.size()); i++)
2502 needed_spacer = fspacer[i];
2503 complete_valid_channel_on_rec = finputid[i];
2512 const QString &channum)
2518 if (!videoFilters.isEmpty())
2546 busy_input = &dummy;
2548 busy_input->
Clear();
2565 bool has_pending =
false;
2575 if (!busy_input->
m_inputId && has_pending)
2579 if (timeLeft <= time_buffer)
2702 long long bitrate = 0;
2705 bitrate = 10080000LL;
2709 bitrate = 20200000LL;
2713 bitrate = 22200000LL;
2717 bitrate = 10080000LL;
2845 MythEvent me(
"SCHEDULER_ADD_RECORDING", prog);
2872 LOG(VB_JOBQUEUE, LOG_INFO,
2873 QString(
"InitAutoRunJobs for %1, line %2 -> 0x%3")
2891 LOG(VB_GENERAL, LOG_INFO,
LOC +
2892 QString(
"SetLiveRecording(%1)").arg(recording));
2900 LOG(VB_GENERAL, LOG_INFO,
LOC +
"SetLiveRecording() -- cancel");
2908 LOG(VB_GENERAL, LOG_INFO,
LOC +
"SetLiveRecording() -- record");
2921 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
2938 LOG(VB_RECORD, LOG_INFO,
LOC +
2939 QString(
"StopLiveTV(void) curRec: 0x%1 pseudoRec: 0x%2")
2988 LOG(VB_GENERAL, LOG_ERR,
LOC +
2989 "PauseRecorder() called with no recorder");
3024 LOG(VB_GENERAL, LOG_ERR,
LOC +
3025 QString(
"Channel: \'%1\' was not found in the database.\n"
3026 "\t\tMost likely, the 'starting channel' for this "
3027 "Input Connection is invalid.\n"
3028 "\t\tCould not toggle favorite.").arg(channum));
3035 LOG(VB_RECORD, LOG_ERR,
LOC +
3036 QString(
"ToggleChannelFavorite: Invalid channel group name %1,")
3037 .arg(changroupname));
3045 LOG(VB_RECORD, LOG_ERR,
LOC +
"Unable to toggle channel favorite.");
3049 LOG(VB_RECORD, LOG_INFO,
LOC +
3050 QString(
"Toggled channel favorite.channum %1, chan group %2")
3051 .arg(channum, changroupname));
3069 return (ret < 0) ? -1 : ret / 655;
3089 return (ret < 0) ? -1 : ret / 655;
3123 QString origIn = input;
3124 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetInput(" + input +
") -- begin");
3128 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetInput() -- end no channel class");
3132 LOG(VB_RECORD, LOG_INFO,
LOC +
"SetInput(" + origIn +
":" + input +
3133 ") -- end nothing to do");
3151 LOG(VB_CHANNEL, LOG_INFO,
LOC +
3152 QString(
"SetChannel(%1) -- begin").arg(name));
3185 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"SetChannel(%1) -- end").arg(name));
3197 LOG(VB_CHANNEL, LOG_INFO,
LOC +
3198 QString(
"QueueEITChannelChange(%1)").arg(name));
3215 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
3216 QString(
"QueueEITChannelChange(%1) %2")
3217 .arg(name, ok ?
"done" :
"failed"));
3223 QString &title, QString &subtitle,
3224 QString &desc, QString &category,
3225 QString &starttime, QString &endtime,
3226 QString &callsign, QString &iconpath,
3227 QString &channum,
uint &sourceChanid,
3228 QString &seriesid, QString &programid)
3230 QString compare =
"<=";
3231 QString sortorder =
"desc";
3236 chanid = sourceChanid;
3274 QString querystr = QString(
3275 "SELECT title, subtitle, description, category, "
3276 " starttime, endtime, callsign, icon, "
3277 " channum, seriesid, programid "
3278 "FROM program, channel "
3279 "WHERE program.chanid = channel.chanid AND "
3280 " channel.chanid = :CHANID AND "
3281 " starttime %1 :STARTTIME "
3282 "ORDER BY starttime %2 "
3283 "LIMIT 1").arg(compare, sortorder);
3288 query.
bindValue(
":STARTTIME", starttime);
3291 title = subtitle = desc = category =
"";
3292 starttime = endtime = callsign = iconpath =
"";
3293 channum = seriesid = programid =
"";
3301 else if (query.
next())
3303 title = query.
value(0).toString();
3304 subtitle = query.
value(1).toString();
3305 desc = query.
value(2).toString();
3306 category = query.
value(3).toString();
3307 starttime = query.
value(4).toString();
3308 endtime = query.
value(5).toString();
3309 callsign = query.
value(6).toString();
3310 iconpath = query.
value(7).toString();
3311 channum = query.
value(8).toString();
3312 seriesid = query.
value(9).toString();
3313 programid = query.
value(10).toString();
3314 sourceChanid = chanid;
3320 "SELECT channum, callsign, icon "
3322 "WHERE chanid = :CHANID");
3329 else if (query.
next())
3331 sourceChanid = chanid;
3332 channum = query.
value(0).toString();
3333 callsign = query.
value(1).toString();
3334 iconpath = query.
value(2).toString();
3339 QString &callsign, QString &channum,
3340 QString &channame, QString &xmltvid)
const
3347 if ((!chanid || !sourceid) && !
m_channel)
3358 "SELECT callsign, channum, name, xmltvid "
3360 "WHERE chanid = :CHANID");
3371 callsign = query.
value(0).toString();
3372 channum = query.
value(1).toString();
3373 channame = query.
value(2).toString();
3374 xmltvid = query.
value(3).toString();
3380 const QString& oldchannum,
3381 const QString& callsign,
const QString& channum,
3382 const QString& channame,
const QString& xmltvid)
3384 if (!chanid || !sourceid || channum.isEmpty())
3390 "SET callsign = :CALLSIGN, "
3391 " channum = :CHANNUM, "
3392 " name = :CHANNAME, "
3393 " xmltvid = :XMLTVID "
3394 "WHERE chanid = :CHANID AND "
3395 " sourceid = :SOURCEID");
3418 LOG(VB_CHANNEL, LOG_INFO,
LOC +
3419 QString(
"Override tune timeout: %1ms")
3433 if (oldbuffer && (oldbuffer !=
Buffer))
3445 LOG(VB_GENERAL, LOG_INFO,
LOC +
"RingBufferChanged()");
3467 QString &input)
const
3496 if (
m_channel && !channum.isEmpty() && (channum.indexOf(
"NextChannel") >= 0))
3499#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
3500 int dir = channum.rightRef(channum.length() - 12).toInt();
3502 int dir = QStringView(channum).right(channum.length() - 12).toInt();
3545 if (
mpeg->HasProgram(progNum))
3568 LOG(VB_RECORD, LOG_INFO,
LOC +
3569 "HandleTuning Request: " + request.
toString());
3576 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"On same multiplex");
3590 LOG(VB_RECORD, LOG_INFO,
LOC +
3591 "No recorder yet, calling TuningFrequency");
3596 LOG(VB_RECORD, LOG_INFO,
LOC +
"Waiting for recorder pause..");
3609 LOG(VB_RECORD, LOG_INFO,
LOC +
3610 "Recorder paused, calling TuningFrequency");
3618 if (streamData ==
nullptr)
3641 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"TuningShutdowns(%1)")
3668 if (sd && (sd != rec_sd))
3702 LOG(VB_RECORD, LOG_INFO,
LOC +
"Tearing down RingBuffer");
3730 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"TuningFrequency(%1)")
3751 if (request.
m_minorChan && (tuningmode ==
"atsc"))
3776 slist<<
"message"<<QObject::tr(
"On known multiplex...");
3790 if (!channum.isEmpty())
3803 LOG(VB_GENERAL, LOG_ERR,
LOC +
3804 QString(
"Failed to set channel to %1. Reverting to kState_None")
3813 LOG(VB_GENERAL, LOG_ERR,
LOC +
3814 QString(
"Failed to set channel to %1.").arg(channum));
3833 bool use_dr = use_sm && (livetv || antadj);
3834 bool has_dummy =
false;
3855 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create RingBuffer 1");
3865 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting Signal Monitor");
3870 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to setup signal monitor");
3888 SetVideoStreamsRequired(0);
3915 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
3916 QString(
"Pre-fail start deadline: %1 "
3917 "Start recording deadline: %2 "
3918 "Good signal deadline: %3")
3920 .toString(
"hh:mm:ss.zzz"),
3922 .toString(
"hh:mm:ss.zzz"),
3924 .toString(
"hh:mm:ss.zzz")));
3948 LOG(VB_RECORD, LOG_INFO,
"DummyDTVRecorder -- started");
3974 bool keep_trying =
false;
3987 LOG(VB_RECORD, LOG_INFO,
LOC +
"TuningSignalCheck: Good signal");
3993 QString desc = tr(
"Good signal seen after %1 ms")
4002 tr(
"See 'Tuning timeout' in mythtv-setup "
4003 "for this input."));
4006 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4007 QString(
"It took longer than %1 ms to get a signal lock. "
4008 "Keeping status of '%2'")
4011 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4012 "See 'Tuning timeout' in mythtv-setup for this input");
4021 LOG(VB_GENERAL, LOG_ERR,
LOC +
"TuningSignalCheck: SignalMonitor " +
4034 LOG(VB_GENERAL, LOG_ERR,
LOC +
4035 "TuningSignalCheck: Hit pre-fail timeout");
4049 QString desc = tr(
"Taking more than %1 ms to get a lock.")
4057 tr(
"See 'Tuning timeout' in mythtv-setup "
4058 "for this input."));
4062 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4063 QString(
"TuningSignalCheck: taking more than %1 ms to get a lock. "
4064 "marking this recording as '%2'.")
4067 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4068 "See 'Tuning timeout' in mythtv-setup for this input");
4078 LOG(VB_RECORD, LOG_INFO,
LOC +
4079 QString(
"TuningSignalCheck: Still waiting. Will timeout @ %1")
4081 .toString(
"hh:mm:ss.zzz")));
4092 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
4130 LOG(VB_EIT, LOG_INFO,
LOC +
4131 QString(
"EIT scanning disabled for video source %1")
4140 bool on_host,
bool transcode_bfr_comm,
bool on_line_comm)
4156 if ((!autoTrans) || (autoTrans->
getValue().toInt() == 0))
4180 !transcode_bfr_comm;
4204 QString profileName =
"Live TV";
4205 if (!tvchain && rec)
4208 QString profileRequested = profileName;
4213 LOG(VB_RECORD, LOG_INFO,
LOC +
4214 QString(
"Using profile '%1' to record")
4219 profileName =
"Default";
4222 LOG(VB_RECORD, LOG_INFO,
LOC +
4223 QString(
"Profile '%1' not found, using "
4224 "fallback profile '%2' to record")
4225 .arg(profileRequested, profileName));
4229 LOG(VB_RECORD, LOG_ERR,
LOC +
4230 QString(
"Profile '%1' not found, and unable "
4231 "to load fallback profile '%2'. Results "
4232 "may be unpredicable")
4233 .arg(profileRequested, profileName));
4263 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create RingBuffer 2");
4272 QString pathname = (*rec)->GetPathname();
4273 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"rec->GetPathname(): '%1'")
4278 LOG(VB_GENERAL, LOG_ERR,
LOC +
4279 QString(
"RingBuffer '%1' not open...")
4289 LOG(VB_GENERAL, LOG_ERR,
LOC +
4290 QString(
"Failed to start recorder! ringBuffer is NULL\n"
4291 "\t\t\t\t Tuning request was %1\n")
4296 QString message = QString(
"QUIT_LIVETV %1").arg(
m_inputId);
4306 LOG(VB_GENERAL, LOG_INFO,
LOC +
"TuningNewRecorder - CreateRecorder()");
4315 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to initialize recorder!");
4323 LOG(VB_GENERAL, LOG_ERR,
LOC +
4324 QString(
"Failed to start recorder!\n"
4325 "\t\t\t\t Tuning request was %1\n")
4330 QString message = QString(
"QUIT_LIVETV %1").arg(
m_inputId);
4373 std::this_thread::sleep_for(5us);
4401 LOG(VB_RECORD, LOG_INFO,
LOC +
"Starting Recorder");
4403 bool had_dummyrec =
false;
4409 had_dummyrec =
true;
4427 LOG(VB_RECORD, LOG_INFO,
LOC +
4428 QString(
"TuningNewRecorder -- UPDATE_RECORDING_STATUS: %1")
4430 MythEvent me(QString(
"UPDATE_RECORDING_STATUS %1 %2 %3 %4 %5")
4448 LOG(VB_RECORD, LOG_INFO,
LOC +
"Restarting Recorder");
4450 bool had_dummyrec =
false;
4461 had_dummyrec =
true;
4487 QString msg1 = QString(
"Recording: %1 %2 %3 %4")
4492 QString msg2 = QString(
"Recording: %1 %2 %3 %4")
4497 LOG(VB_RECORD, LOG_INFO,
LOC +
"Pseudo LiveTV recording starting." +
4498 "\n\t\t\t" + msg1 +
"\n\t\t\t" + msg2);
4515 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"SetFlags(%1) -> %2 @ %3:%4")
4524 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"ClearFlags(%1) -> %2 @ %3:%4")
4535 msg +=
"FrontendReady,";
4537 msg +=
"RunMainLoop,";
4539 msg +=
"ExitPlayer,";
4541 msg +=
"FinishRecording,";
4545 msg +=
"CancelNextRecording,";
4557 msg +=
"Recording,";
4572 msg +=
"AntennaAdjust,";
4576 msg +=
"PENDINGACTIONS,";
4581 msg +=
"WaitingForRecPause,";
4583 msg +=
"WaitingForSignal,";
4585 msg +=
"NeedToStartRecorder,";
4587 msg +=
"KillRingBuffer,";
4591 msg +=
"ANYRUNNING,";
4596 msg +=
"SignalMonitorRunning,";
4598 msg +=
"EITScannerRunning,";
4601 msg +=
"ANYRECRUNNING,";
4606 msg +=
"DummyRecorderRunning,";
4608 msg +=
"RecorderRunning,";
4612 msg +=
"RingBufferReady,";
4615 msg = QString(
"0x%1").arg(f,0,16);
4643 const QString & channum)
4645 LOG(VB_RECORD, LOG_INFO,
LOC +
"GetProgramRingBufferForLiveTV()");
4669 LOG(VB_GENERAL, LOG_ERR,
LOC +
4670 QString(
"Channel: \'%1\' was not found in the database.\n"
4671 "\t\tMost likely, the 'starting channel' for this "
4672 "Input Connection is invalid.\n"
4673 "\t\tCould not start livetv.").arg(channum));
4698 LOG(VB_GENERAL, LOG_ERR,
LOC +
"GetProgramRingBufferForLiveTV()"
4699 "\n\t\t\tProgramInfo is invalid."
4729 if (!(*
Buffer) || !(*Buffer)->IsOpen())
4731 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"RingBuffer '%1' not open...")
4746 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"CreateLiveTVRingBuffer(%1)")
4763 LOG(VB_GENERAL, LOG_ERR,
LOC +
4764 QString(
"CreateLiveTVRingBuffer(%1) failed").arg(channum));
4791 bool discont,
bool set_rec)
4796 msg = QString(
" curRec(%1) curRec.size(%2)")
4800 LOG(VB_RECORD, LOG_INFO,
LOC +
4801 QString(
"SwitchLiveTVRingBuffer(discont %1, set_next_rec %2)")
4802 .arg(discont).arg(set_rec) + msg);
4860 LOG(VB_RECORD, LOG_INFO,
LOC +
"SwitchRecordingRingBuffer()");
4864 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4865 "already switching.");
4871 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4872 "invalid recorder.");
4878 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4879 "invalid recording.");
4885 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer -> "
4886 "Not the same channel.");
4897 LOG(VB_RECORD, LOG_ERR,
LOC +
4898 QString(
"SwitchRecordingRingBuffer() -> "
4899 "cannot switch profile '%1' to '%2'")
4911 if (!buffer || !buffer->
IsOpen())
4918 LOG(VB_RECORD, LOG_ERR,
LOC +
"SwitchRecordingRingBuffer() -> "
4919 "Failed to create new RB.");
4928 LOG(VB_RECORD, LOG_INFO,
LOC +
"SwitchRecordingRingBuffer -> done");
4934 QMap<uint,TVRec*>::const_iterator it =
s_inputs.constFind(inputid);
4942 LOG(VB_RECORD, LOG_INFO,
LOC + QString(
"enable:%1").arg(enable));
4969 return QString(
"Program(%1) channel(%2) input(%3) flags(%4)")
std::vector< pid_cache_item_t > pid_cache_t
Encapsulates data about ATSC stream and emits events for most tables.
const MasterGuideTable * GetCachedMGT(bool current=true) const
void SetDesiredChannel(int major, int minor)
static bool GetInputInfo(InputInfo &input, std::vector< uint > *groupids=nullptr)
static QString GetStartChannel(uint inputid)
static bool IsEITCapable(const QString &rawtype)
static QString GetInputName(uint inputid)
static bool IsV4L(const QString &rawtype)
static uint GetSourceID(uint inputid)
static bool IsEncoder(const QString &rawtype)
static std::vector< uint > GetConflictingInputs(uint inputid)
static bool IsChannelReusable(const QString &rawtype)
Abstract class providing a generic interface to tuning hardware.
virtual QString GetInputName(void) const
virtual int ChangePictureAttribute(PictureAdjustType, PictureAttribute, bool)
virtual uint GetSourceID(void) const
virtual bool Open(void)=0
Opens the channel changing hardware for use.
virtual uint GetNextChannel(uint chanid, ChannelChangeDirection direction) const
virtual void StoreInputChannels(void)
Saves current channel as the default channel for the current input.
virtual void Close(void)=0
Closes the channel changing hardware to use.
virtual bool IsOpen(void) const =0
Reports whether channel is already open.
virtual QString GetChannelName(void) const
virtual void Renumber(uint sourceid, const QString &oldChanNum, const QString &newChanNum)
Changes a channum if we have it cached anywhere.
bool CheckChannel(const QString &channum) const
virtual int GetPictureAttribute(PictureAttribute) const
virtual int GetChanID(void) const
virtual void SetFd(int fd)
Sets file descriptor.
virtual bool Init(QString &startchannel, bool setchan)
virtual int GetInputID(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)
virtual bool InitPictureAttributes(void)
virtual bool SetChannelByString(const QString &chan)=0
static bool ToggleChannel(uint chanid, int changrpid, bool delete_chan)
static int GetChannelGroupId(const QString &changroupname)
static uint GetMplexID(uint sourceid, const QString &channum)
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
static int GetProgramNumber(uint sourceid, const QString &channum)
static QString GetVideoFilters(uint sourceid, const QString &channum)
static bool IsOnSameMultiplex(uint srcid, const QString &new_channum, const QString &old_channum)
static QString GetChanNum(int chan_id)
Returns the channel-number string of the given channel.
static bool GetATSCChannel(uint sourceid, const QString &channum, uint &major, uint &minor)
Class providing a generic interface to digital tuning hardware.
int GetProgramNumber(void) const
Returns program number in PAT, -1 if unknown.
void SaveCachedPids(const pid_cache_t &pid_cache) const
Saves MPEG PIDs to cache to database.
QString GetTuningMode(void) const
Returns tuning mode last set by SetTuningMode().
uint GetTransportID(void) const
Returns DVB transport_stream_id, 0 if unknown.
QString GetSIStandard(void) const
Returns PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
void SetTuningMode(const QString &tuning_mode)
Sets tuning mode: "mpeg", "dvb", "atsc", etc.
uint GetMajorChannel(void) const
Returns major channel, 0 if unknown.
uint GetMinorChannel(void) const
Returns minor channel, 0 if unknown.
void GetCachedPids(pid_cache_t &pid_cache) const
Returns cached MPEG PIDs for last tuned channel.
QString GetSuggestedTuningMode(bool is_live_tv) const
Returns suggested tuning mode: "mpeg", "dvb", or "atsc".
virtual bool EnterPowerSavingMode(void)
Enters power saving mode if the card supports it.
uint GetOriginalNetworkID(void) const
Returns DVB original_network_id, 0 if unknown.
This is a specialization of RecorderBase used to handle MPEG-2, MPEG-4, MPEG-4 AVC,...
MPEGStreamData * GetStreamData(void) const
virtual void SetStreamData(MPEGStreamData *data)
This class is intended to detect the presence of needed tables.
void SetDVBService(uint network_id, uint transport_id, int service_id)
void AddFlags(uint64_t _flags) override
ATSCStreamData * GetATSCStreamData()
Returns the ATSC stream data if it exists.
void SetChannel(int major, int minor)
virtual void SetRotorTarget(float)
Sets rotor target pos from 0.0 to 1.0.
void IgnoreEncrypted(bool ignore)
MPEGStreamData * GetStreamData()
Returns the MPEG stream data if it exists.
void SetProgramNumber(int progNum)
virtual void SetStreamData(MPEGStreamData *data)
Sets the MPEG stream data for DTVSignalMonitor to use, and connects the table signals to the monitor.
Provides interface to the tuning hardware when using DVB drivers.
std::chrono::milliseconds m_dvbTuningDelay
void SetDishNetEIT(bool use_dishnet_eit)
Acts as glue between ChannelBase, EITSource and EITHelper.
void StopEITEventProcessing(void)
Stops inserting Event Information Tables into DB.
void StartEITEventProcessing(ChannelBase *channel, EITSource *eitSource)
Start inserting Event Information Tables from the multiplex we happen to be tuned to into the databas...
void StartActiveScan(TVRec *rec, std::chrono::seconds max_seconds_per_multiplex)
Start active EIT scan.
void StopActiveScan(void)
Stop active EIT scan.
static bool QueueRecordingJobs(const RecordingInfo &recinfo, int jobTypes=JOB_NONE)
static void RemoveJobsFromMask(int jobs, int &mask)
static void AddJobsToMask(int jobs, int &mask)
static bool JobIsInMask(int job, int mask)
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 bool JobIsNotInMask(int job, int mask)
Keeps track of recordings in a current LiveTV instance.
int TotalSize(void) const
QString GetID(void) const
void FinishedRecording(ProgramInfo *pginfo)
void ReloadAll(const QStringList &data=QStringList())
void SetInputType(const QString &type)
ProgramInfo * GetProgramAt(int at) const
Returns program at the desired location.
void SetHostPrefix(const QString &prefix)
QString GetInputType(int pos=-1) const
void AppendNewProgram(ProgramInfo *pginfo, const QString &channum, const QString &inputname, bool discont)
Encapsulates data about MPEG stream and emits events for each table.
void SetRecordingType(const QString &recording_type)
virtual void ReturnCachedTable(const PSIPTable *psip) const
void SetIgnoreCRC(bool haveCRCbug)
void SetVideoStreamsRequired(uint num)
void SetCaching(bool cacheTables)
virtual void AddListeningPID(uint pid, PIDPriority priority=kPIDPriorityNormal)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool isActive(void) const
bool isConnected(void) const
Only updated once during object creation.
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
This is a wrapper around QThread that does several additional things.
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
This table tells the decoder on which PIDs to find other tables, and their sizes and each table's cur...
uint TableType(uint i) const
uint TablePID(uint i) const
QString GetHostName(void)
QString GetSetting(const QString &key, const QString &defaultval="")
void SendSystemEvent(const QString &msg)
int GetBackendServerPort(void)
Returns the locally defined backend control port.
T GetDurSetting(const QString &key, T defaultval=T::zero())
void dispatch(const MythEvent &event)
static QString GenMythURL(const QString &host=QString(), int port=0, QString path=QString(), const QString &storageGroup=QString())
int GetNumSetting(const QString &key, int defaultval=0)
void SendEvent(const MythEvent &event)
bool GetBoolSetting(const QString &key, bool defaultval=false)
static void DBError(const QString &where, const MSqlQuery &query)
T dequeue()
Removes item from front of list and returns a copy. O(1).
void enqueue(const T &d)
Adds item to the back of the list. O(1).
This class is used as a container for messages.
void SetDuration(std::chrono::seconds Duration)
Contains a duration during which the notification will be displayed for. The duration is informative ...
A QElapsedTimer based timer to replace use of QTime as a timer.
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
void start(void)
starts measuring elapsed time.
std::vector< uint > m_possibleConflicts
QDateTime m_recordingStart
static void GetPreviewImage(const ProgramInfo &pginfo, const QString &token)
Submit a request for the generation of a preview image.
Holds information on recordings and videos.
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
uint GetRecordingRuleID(void) const
bool IsSameProgramWeakCheck(const ProgramInfo &other) const
Checks for duplicate using only title, chanid and startts.
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
bool QueryTuningInfo(QString &channum, QString &input) const
Returns the channel and input needed to record the program.
void UpdateInUseMark(bool force=false)
QString GetRecordingGroup(void) const
void SaveAutoExpire(AutoExpireType autoExpire, bool updateDelete=false)
Set "autoexpire" field in "recorded" table to "autoExpire".
void SetRecordingRuleType(RecordingType type)
uint GetRecordingID(void) const
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
uint QueryMplexID(void) const
Queries multiplex any recording would be made on, zero if unknown.
void SetRecordingStatus(RecStatus::Type status)
void SetRecordingGroup(const QString &group)
uint GetSourceID(void) const
void SetScheduledEndTime(const QDateTime &dt)
void SetRecordingStartTime(const QDateTime &dt)
void SaveVideoProperties(uint mask, uint video_property_flags)
QString GetTitle(void) const
uint QueryAverageHeight(void) const
If present in recording this loads average height of the main video stream from database's stream mar...
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...
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
bool QueryAverageScanProgressive(void) const
If present in recording this loads average video scan type of the main video stream from database's s...
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
void SetChanID(uint _chanid)
bool IsCommercialFree(void) const
MarkTypes QueryAverageAspectRatio(void) const
void SetRecordingRuleID(uint id)
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
QString GetPathname(void) const
uint GetInputID(void) const
void ToStringList(QStringList &list) const
Serializes ProgramInfo into a QStringList which can be passed over a socket.
void SetRecordingEndTime(const QDateTime &dt)
void SetStorageGroup(const QString &group)
RecStatus::Type GetRecordingStatus(void) const
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
void SaveCommFlagged(CommFlagStatus flag)
Set "commflagged" field in "recorded" table to "flag".
QString GetSubtitle(void) const
QString GetCategory(void) const
virtual void SetRecordingID(uint _recordedid)
void SetPathname(const QString &pn)
RecordingType GetRecordingRuleType(void) const
QString QueryRecordingGroup(void) const
Query recgroup from recorded.
static QString toString(RecStatus::Type recstatus, uint id)
Converts "recstatus" into a short (unreadable) string.
virtual void Reset(void)=0
Reset the recorder to the startup state.
virtual bool IsRecording(void)
Tells whether the StartRecorder() loop is running.
virtual void Pause(bool clear=true)
Pause tells recorder to pause, it should not block.
virtual void SetVideoFilters(QString &filters)=0
Tells recorder which filters to use.
virtual int GetVideoFd(void)=0
Returns file descriptor of recorder device.
virtual void Unpause(void)
Unpause tells recorder to unpause.
virtual bool CheckForRingBufferSwitch(void)
If requested, switch to new RingBuffer/ProgramInfo objects.
virtual void Initialize(void)=0
This is called between SetOptionsFromProfile() and run() to initialize any devices,...
void SetRecording(const RecordingInfo *pginfo)
Changes the Recording from the one set initially with SetOptionsFromProfile().
double GetFrameRate(void) const
Returns the latest frame rate.
bool GetKeyframePositions(long long start, long long end, frm_pos_map_t &map) const
void SetNextRecording(const RecordingInfo *ri, MythMediaBuffer *Buffer)
Sets next recording info, to be applied as soon as practical.
virtual void StopRecording(void)
StopRecording() signals to the recorder that it should stop recording and exit cleanly.
virtual RecordingQuality * GetRecordingQuality(const RecordingInfo *ri) const
Returns a report about the current recordings quality.
bool GetKeyframeDurations(long long start, long long end, frm_pos_map_t &map) const
virtual long long GetFramesWritten(void)=0
Returns number of frames written to disk.
long long GetKeyframePosition(long long desired) const
Returns closest keyframe position before the desired frame.
virtual bool IsPaused(bool holding_lock=false) const
Returns true iff recorder is paused.
void SavePositionMap(bool force=false, bool finished=false)
Save the seektable to the DB.
static RecorderBase * CreateRecorder(TVRec *tvrec, ChannelBase *channel, RecordingProfile &profile, const GeneralDBOptions &genOpt)
virtual bool IsErrored(void)=0
Tells us whether an unrecoverable error has been encountered.
void SetRingBuffer(MythMediaBuffer *Buffer)
Tells recorder to use an externally created ringbuffer.
Holds information on a TV Program one might wish to record.
void FinishedRecording(bool allowReRecord)
If not a premature stop, adds program to history of recorded programs.
void SetDesiredStartTime(const QDateTime &dt)
RecordingRule * GetRecordingRule(void)
Returns the "record" field, creating it if necessary.
void ApplyRecordRecGroupChange(const QString &newrecgroup)
Sets the recording group, both in this RecordingInfo and in the database.
int GetAutoRunJobs(void) const
Returns a bitmap of which jobs are attached to this RecordingInfo.
void AddHistory(bool resched=true, bool forcedup=false, bool future=false)
Adds recording history, creating "record" it if necessary.
void ApplyRecordRecID(void)
Sets recordid to match RecordingRule recordid.
void UpdateRecordingEnd(void)
Update information in the recorded table when the end-time of a recording is changed.
uint64_t GetFilesize(void) const override
void StartedRecording(const QString &ext)
Inserts this RecordingInfo into the database as an existing recording.
void SetDesiredEndTime(const QDateTime &dt)
RecordingFile * GetRecordingFile() const
bool IsDamaged(void) const
QString toStringXML(void) const
AutoExpireType GetAutoExpire(void) const
bool Save(bool sendSig=true)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
static void Init()
Initializes the some static constants needed by SignalMonitorValue.
void AddListener(SignalMonitorListener *listener)
static SignalMonitor * Init(const QString &cardtype, int db_cardnum, ChannelBase *channel, bool release_stream)
static const uint64_t kDVBSigMon_WaitForPos
Wait for rotor to complete turning the antenna.
static const uint64_t kDTVSigMon_WaitForSDT
bool IsErrored(void) const
virtual bool HasExtraSlowTuning(void) const
virtual bool IsAllGood(void) const
static bool IsSupported(const QString &cardtype)
static const uint64_t kDTVSigMon_WaitForPMT
void SetUpdateRate(std::chrono::milliseconds msec)
Sets the number of milliseconds between signal monitoring attempts in the signal monitoring thread.
static const uint64_t kDTVSigMon_WaitForPAT
void SetNotifyFrontend(bool notify)
Enables or disables frontend notification of the current signal value.
static const uint64_t kDTVSigMon_WaitForMGT
static bool IsRequired(const QString &cardtype)
Returns true iff the card type supports signal monitoring.
virtual void Start()
Start signal monitoring thread.
static QString GetSourceName(uint sourceid)
virtual QString getValue(void) const
QString FindNextDirMostFree(void)
This is the coordinating class of the Recorder Subsystem.
bool SwitchLiveTVRingBuffer(const QString &channum, bool discont, bool set_rec)
V4LChannel * GetV4LChannel(void)
bool ShouldSwitchToAnotherInput(const QString &chanid) const
Checks if named channel exists on current tuner, or another tuner.
bool GetChannelInfo(uint &chanid, uint &sourceid, QString &callsign, QString &channum, QString &channame, QString &xmltvid) const
static const uint kFlagRecording
final result desired is a timed recording
static const uint kFlagAnyRecRunning
TuningQueue m_tuningRequests
bool SetupDTVSignalMonitor(bool EITscan)
Tells DTVSignalMonitor what channel to look for.
QHash< QString, int > m_autoRunJobs
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 bool GetDevices(uint inputid, uint &parentid, GeneralDBOptions &gen_opts, DVBDBOptions &dvb_opts, FireWireDBOptions &firewire_opts)
void NotifySchedulerOfRecording(RecordingInfo *rec)
Tell scheduler about the recording.
void PauseRecorder(void)
Tells "recorder" to pause, used for channel and input changes.
void SetChannelTimeout(std::chrono::milliseconds timeout)
DTVChannel * GetDTVChannel(void)
uint GetFlags(void) const
bool CreateChannel(const QString &startchannel, bool enter_power_save_mode)
void FinishedRecording(RecordingInfo *curRec, RecordingQuality *recq)
If not a premature stop, adds program to history of recorded programs.
QDateTime m_signalEventCmdTimeout
static const uint kFlagErrored
TVState RemoveRecording(TVState state) const
If "state" is kState_RecordingOnly or kState_WatchingLiveTV, returns a kState_None,...
bool SetVideoFiltersForChannel(uint sourceid, const QString &channum)
void SetPseudoLiveTVRecording(RecordingInfo *pi)
Sets the pseudo LiveTV RecordingInfo.
static const uint kFlagEITScannerRunning
TVRec(int _inputid)
Performs instance initialization not requiring access to database.
bool SetChannelInfo(uint chanid, uint sourceid, const QString &oldchannum, const QString &callsign, const QString &channum, const QString &channame, const QString &xmltvid)
QString GetChainID(void)
Get the chainid of the livetv instance.
void TuningFrequency(const TuningRequest &request)
Performs initial tuning required for any tuning event.
QMutex m_nextLiveTVDirLock
static const uint kFlagExitPlayer
void SetFlags(uint f, const QString &file, int line)
static const uint kFlagFinishRecording
static const uint kFlagEITScan
final result desired is an EIT Scan
TVState m_desiredNextState
static bool StateIsRecording(TVState state)
Returns true if "state" is kState_RecordingOnly, or kState_WatchingLiveTV.
QDateTime m_recordEndTime
~TVRec(void) override
Stops the event and scanning threads and deletes any ChannelBase, RingBuffer, and RecorderBase instan...
void SetChannel(const QString &name, uint requestType=kFlagDetect)
Changes to a named channel on the current tuner.
bool Init(void)
Performs instance initialization, returns true on success.
GeneralDBOptions m_genOpt
void TuningNewRecorder(MPEGStreamData *streamData)
Creates a recorder instance.
RecordingInfo * m_curRecording
bool QueueEITChannelChange(const QString &name)
Queues up a channel change for the EITScanner.
std::chrono::seconds m_eitTransportTimeout
QString m_liveTVStartChannel
QString m_overRecordCategory
ProgramInfo * GetRecording(void)
Allocates and returns a ProgramInfo for the current recording.
friend class TuningRequest
QWaitCondition m_triggerEventSleepWait
void SetNextLiveTVDir(QString dir)
RecStatus::Type GetRecordingStatus(void) const
static const uint kFlagFrontendReady
static const uint kFlagKillRingBuffer
long long GetMaxBitrate(void) const
Returns the maximum bits per second this recorder can produce.
RecStatus::Type StartRecording(ProgramInfo *pginfo)
Tells TVRec to Start recording the program "rcinfo" as soon as possible.
bool WaitForEventThreadSleep(bool wake=true, std::chrono::milliseconds time=std::chrono::milliseconds::max())
You MUST HAVE the stateChange-lock locked when you call this method!
static const uint kFlagRecorderRunning
void ToggleChannelFavorite(const QString &changroupname)
Toggles whether the current channel should be on our favorites list.
std::chrono::seconds m_eitCrawlIdleStart
void HandleStateChange(void)
Changes the internalState to the desiredNextState if possible.
QRecursiveMutex m_pendingRecLock
void RecorderPaused(void)
This is a callback, called by the "recorder" instance when it has actually paused.
QDateTime m_eitScanStopTime
static const uint kFlagKillRec
close recorder, discard recording
QMutex m_triggerEventLoopLock
bool m_reachedRecordingDeadline
int ChangePictureAttribute(PictureAdjustType type, PictureAttribute attr, bool direction)
Returns current value [0,100] if it succeeds, -1 otherwise.
TuningRequest m_lastTuningRequest
bool IsErrored(void) const
Returns true is "errored" is true, false otherwise.
QDateTime m_eitScanStartTime
RecordingInfo * SwitchRecordingRingBuffer(const RecordingInfo &rcinfo)
long long GetFramesWritten(void)
Returns number of frames written to disk by recorder.
void StartedRecording(RecordingInfo *curRec)
Inserts a "curRec" into the database.
QDateTime m_preFailDeadline
void TuningShutdowns(const TuningRequest &request)
This shuts down anything that needs to be shut down before handling the passed in tuning request.
void RecordPending(const ProgramInfo *rcinfo, std::chrono::seconds secsleft, bool hasLater)
Tells TVRec "rcinfo" is the next pending recording.
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.
void StopLiveTV(void)
Tells TVRec to stop a "Live TV" recorder.
PendingMap m_pendingRecordings
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)
RecorderBase * m_recorder
long long GetFilePosition(void)
Returns total number of bytes written by RingBuffer.
static const uint kFlagRunMainLoop
bool m_triggerEventSleepSignal
static const uint kFlagRingBufferReady
SignalMonitor * m_signalMonitor
std::chrono::seconds m_eitScanPeriod
void TeardownRecorder(uint request_flags)
Tears down the recorder.
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 CheckForRecGroupChange(void)
Check if frontend changed the recording group.
QString TuningGetChanNum(const TuningRequest &request, QString &input) const
FireWireDBOptions m_fwOpt
void run(void) override
Event handling method, contains event loop.
static const uint kFlagRec
QWaitCondition m_triggerEventLoopWait
static const uint kFlagAnyRunning
void SetRecordingStatus(RecStatus::Type new_status, int line, bool have_lock=false)
void CancelNextRecording(bool cancel)
Tells TVRec to cancel the upcoming recording.
uint m_signalMonitorCheckCnt
MythMediaBuffer * m_buffer
static const uint kFlagLiveTV
final result desired is LiveTV recording
QWaitCondition m_triggerLiveTVDir
static const uint kFlagCancelNextRecording
void SetRingBuffer(MythMediaBuffer *Buffer)
Sets "ringBuffer", deleting any existing RingBuffer.
QString GetInput(void) const
Returns current input.
QDateTime m_startRecordingDeadline
static TVRec * GetTVRec(uint inputid)
void SetLiveRecording(int recording)
Tells the Scheduler about changes to the recording status of the LiveTV recording.
static QReadWriteLock s_inputsLock
TVState RemovePlaying(TVState state) const
Returns TVState that would remove the playing, but potentially keep recording if we are watching an i...
void RingBufferChanged(MythMediaBuffer *Buffer, RecordingInfo *pginfo, RecordingQuality *recq)
static const uint kFlagDummyRecorderRunning
QRecursiveMutex m_stateChangeLock
RecordingInfo * m_pseudoLiveTVRecording
bool WaitForNextLiveTVDir(void)
static const uint kFlagSignalMonitorRunning
static QString FlagToString(uint f)
TVState GetState(void) const
Returns the TVState of the recorder.
bool CreateLiveTVRingBuffer(const QString &channum)
static const uint kFlagPendingActions
bool m_triggerEventLoopSignal
void TuningRestartRecorder(void)
Restarts a stopped recorder or unpauses a paused recorder.
DTVRecorder * GetDTVRecorder(void)
int GetPictureAttribute(PictureAttribute attr)
std::chrono::seconds m_overRecordSecNrml
bool SetupSignalMonitor(bool tablemon, bool EITscan, bool notify)
This creates a SignalMonitor instance and begins signal monitoring.
QMutex m_triggerEventSleepLock
volatile bool m_switchingBuffer
static const uint kFlagAntennaAdjust
antenna adjusting mode (LiveTV without recording).
uint GetInputId(void) const
Returns the inputid.
void InitAutoRunJobs(RecordingInfo *rec, AutoRunInitType t, RecordingProfile *recpro, int line)
static const uint kFlagNoRec
bool m_signalEventCmdSent
static const uint kFlagCloseRec
close recorder, keep recording
static const uint kFlagDetect
QDateTime m_signalMonitorDeadline
QDateTime GetRecordEndTime(const ProgramInfo *pi) const
Returns recording end time with proper post-roll.
RecStatus::Type m_recStatus
void HandlePendingRecordings(void)
static QMap< uint, TVRec * > s_inputs
void SpawnLiveTV(LiveTVChain *newchain, bool pip, QString startchan)
Tells TVRec to spawn a "Live TV" recorder.
void HandleTuning(void)
Handles all tuning events.
void StopRecording(bool killFile=false)
Changes from a recording state to kState_None.
void EnableActiveScan(bool enable)
std::chrono::milliseconds SetSignalMonitoringRate(std::chrono::milliseconds rate, int notifyFrontend=1)
Sets the signal monitoring rate.
void ClearFlags(uint f, const QString &file, int line)
bool IsReallyRecording(void)
Returns true if frontend can consider the recorder started.
int64_t GetKeyframePosition(uint64_t desired) const
Returns byte position in RingBuffer of a keyframe according to recorder.
static constexpr std::chrono::milliseconds kSignalMonitoringRate
How many milliseconds the signal monitor should wait between checks.
static const uint kFlagNeedToStartRecorder
bool TuningOnSameMultiplex(TuningRequest &request)
MThread * m_recorderThread
Recorder thread, runs RecorderBase::run().
std::chrono::seconds m_overRecordSecCat
bool CheckChannel(const QString &name) const
Checks if named channel exists on current tuner.
static const uint kFlagWaitingForSignal
void TeardownSignalMonitor(void)
If a SignalMonitor instance exists, the monitoring thread is stopped and the instance is deleted.
MPEGStreamData * TuningSignalCheck(void)
This checks if we have a channel lock.
bool GetKeyframeDurations(int64_t start, int64_t end, frm_pos_map_t &map) const
std::vector< uint > m_eitInputs
void ChangeState(TVState nextState)
Puts a state change on the nextState queue.
bool GetProgramRingBufferForLiveTV(RecordingInfo **pginfo, MythMediaBuffer **Buffer, const QString &channum)
bool TuningNewRecorderReal(MPEGStreamData *streamData, RecordingInfo **rec, RecordingProfile &profile, bool had_dummyrec)
Helper function for TVRec::TuningNewRecorder.
MThread * m_eventThread
Event processing thread, runs TVRec::run().
bool HasFlags(uint f) const
float GetFramerate(void)
Returns recordering frame rate from the recorder.
DTVSignalMonitor * GetDTVSignalMonitor(void)
uint GetSourceID(void) const
Returns current source id.
static const uint kFlagWaitingForRecPause
QString SetInput(QString input)
Changes to the specified input.
static bool StateIsPlaying(TVState state)
Returns true if we are in any state associated with a player.
QString LoadProfile(void *tvchain, RecordingInfo *rec, RecordingProfile &profile) const
bool IsOnSameMultiplex(void) const
RecordingInfo * m_program
QString toString(void) const
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Convenience inline random number generator functions.
void SendMythSystemRecEvent(const QString &msg, const RecordingInfo *pginfo)
std::chrono::seconds secsInPast(const QDateTime &past)
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
std::chrono::seconds secsInFuture(const QDateTime &future)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
uint32_t MythRandom()
generate 32 random bits
def write(text, progress=True)
const QString kRecorderInUseID
QMap< long long, long long > frm_pos_map_t
Frame # -> File offset map.
QString StateToString(TVState state)
Returns a human readable QString representing a TVState.
BrowseDirection
Used to request ProgramInfo for channel browsing.
@ BROWSE_SAME
Fetch browse information on current channel and time.
@ BROWSE_RIGHT
Fetch information on current channel in the future.
@ BROWSE_LEFT
Fetch information on current channel in the past.
@ BROWSE_UP
Fetch information on previous channel.
@ BROWSE_FAVORITE
Fetch information on the next favorite channel.
@ BROWSE_DOWN
Fetch information on next channel.
ChannelChangeDirection
ChannelChangeDirection is an enumeration of possible channel changing directions.
@ CHANNEL_DIRECTION_FAVORITE
TVState
TVState is an enumeration of the states used by TV and TVRec.
@ kState_None
None State, this is the initial state in both TV and TVRec, it indicates that we are ready to change ...
@ kState_RecordingOnly
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
@ kState_Error
Error State, if we ever try to enter this state errored is set.
@ kState_WatchingPreRecorded
Watching Pre-recorded is a TV only state for when we are watching a pre-existing recording.
@ kState_ChangingState
This is a placeholder state which we never actually enter, but is returned by GetState() when we are ...
static std::chrono::seconds eit_start_rand(uint inputId, std::chrono::seconds eitTransportTimeout)
static void GetPidsToCache(DTVSignalMonitor *dtvMon, pid_cache_t &pid_cache)
static int get_highest_input(void)
static void apply_broken_dvb_driver_crc_hack(ChannelBase *, MPEGStreamData *)
static int init_jobs(const RecordingInfo *rec, RecordingProfile &profile, bool on_host, bool transcode_bfr_comm, bool on_line_comm)
static bool get_use_eit(uint inputid)
static QString add_spacer(const QString &channel, const QString &spacer)
Adds the spacer before the last character in chan.
static bool ApplyCachedPids(DTVSignalMonitor *dtvMon, const DTVChannel *channel)
static bool is_dishnet_eit(uint inputid)
#define TRANSITION(ASTATE, BSTATE)
bool RemoteStopRecording(uint inputid)
bool RemoteIsBusy(uint inputid, InputInfo &busy_input)
bool RemoteRecordPending(uint inputid, const ProgramInfo *pginfo, std::chrono::seconds secsleft, bool hasLater)
uint RemoteGetState(uint inputid)