14#include <QCoreApplication>
19#include "libmythbase/mythconfig.h"
23#if CONFIG_FIREWIRE_OSX
26#if CONFIG_FIREWIRE_LINUX
48#define LOC QString("ChannelBase[%1]: ").arg(m_inputId)
78 QString msg1 = QString(
"Setting start channel '%1' failed ").arg(startchannel);
79 QString msg2 =
"and no suitable channel found.";
80 bool msg_error =
true;
85 if (channel.m_chanNum == startchannel &&
88 LOG(VB_CHANNEL, LOG_INFO,
LOC +
89 QString(
"Found startchannel '%1'").arg(startchannel));
94 uint mplexid_restriction = 0;
95 uint chanid_restriction = 0;
106 if ((chanid != 0U) && (cit !=
m_channels.end()))
110 ok =
IsTunable((mplexid_restriction || chanid_restriction)
111 ? (*cit).m_chanNum : startchannel);
120 startchannel = (*cit).m_chanNum;
121 msg2 = QString(
"selected '%1' instead.").arg(startchannel);
127 LOG(VB_GENERAL, ((msg_error) ? LOG_ERR : LOG_WARNING),
LOC + msg1 + msg2);
134 QString loc =
LOC + QString(
"IsTunable(%1)").arg(channum);
138 LOG(VB_GENERAL, LOG_ERR, loc +
" " +
139 QString(
"Requested non-existant input"));
144 uint mplexid_restriction = 0;
145 uint chanid_restriction = 0;
148 LOG(VB_GENERAL, LOG_ERR, loc +
" " +
149 QString(
"Requested channel is on input '%1' "
150 "which is in a busy input group")
165 uint64_t frequency = 0;
166 int mpeg_prog_num = 0;
173 bool commfree =
false;
177 tvformat, modulation, freqtable, freqid,
178 finetune, frequency, dtv_si_std,
179 mpeg_prog_num, atsc_major, atsc_minor,
180 tsid, netid, mplexid, commfree))
182 LOG(VB_GENERAL, LOG_ERR, loc +
" " +
183 QString(
"Failed to find channel in DB on input '%1' ")
189 if ((mplexid_restriction && (mplexid != mplexid_restriction)) ||
190 (!mplexid_restriction &&
191 chanid_restriction && (chanid != chanid_restriction)))
193 LOG(VB_GENERAL, LOG_ERR, loc +
" " +
194 QString(
"Channel is valid, but tuner is busy "
195 "on different multiplex/channel (%1 != %2) / (%3 != %4)")
196 .arg(mplexid).arg(mplexid_restriction)
197 .arg(chanid).arg(chanid_restriction));
215 uint mplexid_restriction = 0;
216 uint chanid_restriction = 0;
220 m_channels, chanid, mplexid_restriction, chanid_restriction,
234 uint &mplexid_restriction,
uint &chanid_restriction)
const
238 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"no m_inputId"));
244 mplexid_restriction = 0;
245 chanid_restriction = 0;
248 for (
uint inputid : inputids)
252 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
253 QString(
"Input %1 is busy on %2/%3")
255 .arg(
info.m_chanId).arg(
info.m_mplexId));
258 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Input is busy"));
261 mplexid_restriction =
info.m_mplexId;
262 chanid_restriction =
info.m_chanId;
266 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Input is free on %1/%2")
267 .arg(mplexid_restriction).arg(chanid_restriction));
306 if (freqid.isEmpty())
308 LOG(VB_GENERAL, LOG_WARNING,
LOC +
309 "A channel changer is set, but the freqid field is empty."
310 "\n\t\t\tWe will return success to ease setup pains, "
311 "but no script is will actually run.");
333 LOG(VB_GENERAL, LOG_ERR,
LOC +
334 "Can not execute channel changer, previous call to script "
335 "is still running.");
346 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can not execute internal channel "
362 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can not execute channel changer.");
372 [[maybe_unused]]
uint inputid)
const
380 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Internal channel change to %1 "
381 "on inputid %2, GUID %3 (%4)").arg(freqid).arg(inputid)
382 .arg(fwnode, fwmodel));
384#if CONFIG_FIREWIRE_LINUX
388#if CONFIG_FIREWIRE_OSX
398 if (!device->
SetChannel(fwmodel, 0, freqid.toUInt()))
417 const QString &freqid)
422 if (changer.isEmpty() || freqid.isEmpty())
425 QString command = QString(
"%1 %2").arg(changer, freqid);
426 LOG(VB_CHANNEL, LOG_INFO,
LOC +
427 QString(
"Running command: %1").arg(command));
453 LOG(VB_CHANNEL, LOG_DEBUG,
LOC + QString(
"GetScriptStatus() %1")
471 LOG(VB_CHANNEL, LOG_DEBUG,
LOC + QString(
"GetScriptStatus() %1 -> %2")
487 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Channel change script succeeded.");
496 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Channel change script failed.");
510 query.
prepare(
"SELECT chanid,visible FROM channel "
511 "WHERE deleted IS NULL AND "
512 " channum = :CHANNUM AND "
513 " sourceid = :SOURCEID");
525 if (query.
value(1).toInt() > 0)
528 visible = query.
value(0).toInt();
532 id = query.
value(0).toInt();
538 LOG(VB_GENERAL, LOG_INFO,
539 QString(
"No visible channel ids for %1 on sourceid %2")
545 LOG(VB_GENERAL, LOG_WARNING,
546 QString(
"Found multiple visible channel ids for %1 on sourceid %2")
550 return (visible >= 0 ? visible :
id);
568 LOG(VB_GENERAL, LOG_ERR,
569 "InitializeInput(): Programmer error, no parent.");
575 "SELECT sourceid, inputname, "
576 " startchan, externalcommand, "
579 "WHERE cardid = :INPUTID");
589 LOG(VB_GENERAL, LOG_ERR,
LOC +
590 QString(
"No capturecard record in database for input %1")
605 LOG(VB_GENERAL, LOG_ERR,
LOC +
606 QString(
"No video source defined for input %1")
618 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"External Channel changer is "
619 "set, but this device does not support it.");
624 LOG(VB_CHANNEL, LOG_INFO,
LOC +
625 QString(
"Input #%1: '%2' schan(%3) sourceid(%4)")
636 const QString &oldChanNum,
637 const QString &newChanNum)
639 bool skip = (
m_name.isEmpty() ||
663 "UPDATE capturecard "
664 "SET startchan = :STARTCHAN "
665 "WHERE cardid = :CARDINPUTID");
680 "SELECT channel.chanid "
681 "FROM channel, capturecard "
682 "WHERE channel.deleted IS NULL AND "
683 " channel.channum = :CHANNUM AND "
684 " channel.sourceid = capturecard.sourceid AND "
685 " capturecard.cardid = :INPUTID AND "
686 " capturecard.hostname = :HOSTNAME");
695 else if (query.
size() > 0)
700 LOG(VB_CHANNEL, LOG_ERR,
LOC +
701 QString(
"Failed to find channel(%1) on input (%2).")
711 const QString &startchannel,
712 bool enter_power_save_mode,
723 auto *dvbchannel =
dynamic_cast<DVBChannel*
>(channel);
724 if (dvbchannel !=
nullptr)
749 genOpt.
m_videoDev.startsWith(
"file:", Qt::CaseInsensitive)))
754#if CONFIG_IPTV || CONFIG_VBOX
801 QString msg = QString(
802 "%1 card configured on video device %2, \n"
803 "but MythTV was not compiled with %3 support. \n"
805 "Recompile MythTV with %4 support or remove the card \n"
806 "from the configuration and restart MythTV.")
809 LOG(VB_GENERAL, LOG_ERR,
"ChannelBase: CreateChannel() Error: \n" +
814 if (!channel->
Open())
816 LOG(VB_GENERAL, LOG_ERR,
"ChannelBase: CreateChannel() Error: " +
817 QString(
"Failed to open device %1").arg(genOpt.
m_videoDev));
822 QString channum = startchannel;
823 channel->
Init(channum, setchan);
825 if (enter_power_save_mode)
837 auto *dtvchannel =
dynamic_cast<DTVChannel*
>(channel);
853 LOG(VB_GENERAL, LOG_ERR,
LOC +
854 QString(
"IsExternalChannelChangeInUse: "
855 "non-existant input"));
static uint64_t string_to_guid(const QString &guid)
static QString GetFirewireChangerModel(uint inputid)
static uint GetFirstInputID(const QString &videodevice)
Convenience function for GetInputIDs()
static bool IsV4L(const QString &rawtype)
static QString GetFirewireChangerNode(uint inputid)
static std::vector< uint > GetConflictingInputs(uint inputid)
Abstract class providing a generic interface to tuning hardware.
void HandleScript(const QString &freqid)
virtual uint GetSourceID(void) const
ChannelBase(TVRec *parent)
bool ChangeInternalChannel(const QString &freqid, uint cardinputid) const
bool ChangeExternalChannel(const QString &changer, const QString &freqid)
virtual bool Open(void)=0
Opens the channel changing hardware for use.
virtual uint GetNextChannel(uint chanid, ChannelChangeDirection direction) const
virtual bool IsInputAvailable(uint &mplexid_restriction, uint &chanid_restriction) const
Switches to another input on hardware, and sets the channel is setstarting is true.
virtual void HandleScriptEnd(bool ok)
virtual bool IsTunable(const QString &channum) 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 ~ChannelBase(void)
ChannelInfoList m_channels
channels across all inputs
virtual void Renumber(uint sourceid, const QString &oldChanNum, const QString &newChanNum)
Changes a channum if we have it cached anywhere.
virtual bool IsExternalChannelChangeInUse(void)
bool CheckChannel(const QString &channum) const
uint m_systemStatus
These get mapped from the GENERIC_EXIT_* to these values for use with the signalmonitor code.
virtual int GetChanID(void) const
virtual bool IsExternalChannelChangeSupported(void)
virtual bool Init(QString &startchannel, bool setchan)
QString m_externalChanger
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 SetChannelByString(const QString &chan)=0
virtual bool InitializeInput(void)
Fills in input map from DB.
uint GetScriptStatus(bool holding_lock=false)
MythSystemLegacy * m_system
virtual QString GetDevice(void) const
Returns String representing device, useful for debugging.
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
static bool GetChannelData(uint sourceid, uint &chanid, const QString &channum, QString &name, QString &callsign, QString &tvformat, QString &modulation, QString &freqtable, QString &freqid, int &finetune, uint64_t &frequency, QString &dtv_si_std, int &mpeg_prog_num, uint &atsc_major, uint &atsc_minor, uint &dvb_transportid, uint &dvb_networkid, uint &mplexid, bool &commfree)
static uint GetNextChannel(const ChannelInfoList &sorted, uint old_chanid, uint mplexid_restriction, uint chanid_restriction, ChannelChangeDirection direction, bool skip_non_visible=true, bool skip_same_channum_and_callsign=false, bool skip_other_sources=false)
static ChannelInfoList GetChannels(uint sourceid, bool visible_only, const QString &group_by=QString(), uint channel_groupid=0)
Class providing a generic interface to digital tuning hardware.
virtual bool EnterPowerSavingMode(void)
Enters power saving mode if the card supports it.
Provides interface to the tuning hardware when using DVB drivers.
void SetSlowTuning(std::chrono::milliseconds how_slow)
std::chrono::milliseconds m_dvbTuningDelay
FirewireChannel Copyright (c) 2005 by Jim Westfall and Dave Abrahams Distributed as part of MythTV un...
virtual bool OpenPort(void)=0
virtual bool SetChannel(const QString &panel_model, uint alt_method, uint channel)
virtual bool ClosePort(void)=0
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.
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
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.
QString GetHostName(void)
QString GetSetting(const QString &key, const QString &defaultval="")
static void DBError(const QString &where, const MSqlQuery &query)
uint Wait(std::chrono::seconds timeout=0s)
void Term(bool force=false)
void Run(std::chrono::seconds timeout=0s)
Runs a command inside the /bin/sh shell. Returns immediately.
This is the coordinating class of the Recorder Subsystem.
uint GetInputId(void) const
Returns the inputid.
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
@ GENERIC_EXIT_START
MythSystemLegacy process starting.
@ GENERIC_EXIT_OK
Exited with no error.
@ GENERIC_EXIT_RUNNING
Process is running.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
@ kMSRunShell
run process through shell
@ kMSRunBackground
run child in the background
ChannelChangeDirection
ChannelChangeDirection is an enumeration of possible channel changing directions.
bool RemoteIsBusy(uint inputid, InputInfo &busy_input)