MythTV  master
channelbase.cpp
Go to the documentation of this file.
1 // Std C headers
2 #include <cstdlib>
3 #include <cerrno>
4 
5 // POSIX headers
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 
11 // C++ headers
12 #include <iostream>
13 #include <algorithm>
14 
15 // Qt headers
16 #include <QCoreApplication>
17 
18 // MythTV headers
19 #ifdef USING_OSX_FIREWIRE
20 #include "darwinfirewiredevice.h"
21 #endif
22 #ifdef USING_LINUX_FIREWIRE
23 #include "linuxfirewiredevice.h"
24 #endif
25 #include "firewirechannel.h"
26 #include "mythcorecontext.h"
27 #include "cetonchannel.h"
28 #include "dummychannel.h"
29 #include "tvremoteutil.h"
30 #include "channelbase.h"
31 #include "channelutil.h"
32 #include "frequencies.h"
33 #include "hdhrchannel.h"
34 #include "iptvchannel.h"
35 #include "mythlogging.h"
36 #include "asichannel.h"
37 #include "dtvchannel.h"
38 #include "dvbchannel.h"
39 #include "v4lchannel.h"
40 #include "ExternalChannel.h"
41 #include "sourceutil.h"
42 #include "exitcodes.h"
43 #include "cardutil.h"
44 #include "compat.h"
45 #include "inputinfo.h"
46 #include "satipchannel.h"
47 
48 #define LOC QString("ChannelBase[%1]: ").arg(m_inputId)
49 
51 {
52  QMutexLocker locker(&m_systemLock);
53  if (m_system)
54  KillScript();
55 }
56 
57 bool ChannelBase::Init(QString &startchannel, bool setchan)
58 {
59  bool ok = false;
60 
61  if (!setchan)
62  ok = IsTunable(startchannel);
63  else
64  ok = SetChannelByString(startchannel);
65 
66  if (ok)
67  return true;
68 
69  // Try to find a valid channel if given start channel fails.
70  QString msg1 = QString("Setting start channel '%1' failed ").arg(startchannel);
71  QString msg2 = "and no suitable channel found.";
72  bool msg_error = true;
73 
74  // Attempt to find the requested startchannel
75  for (auto & channel : m_channels)
76  {
77  if (channel.m_chanNum == startchannel &&
78  IsTunable(startchannel))
79  {
80  LOG(VB_CHANNEL, LOG_INFO, LOC +
81  QString("Found startchannel '%1'").arg(startchannel));
82  return true;
83  }
84  }
85 
86  uint mplexid_restriction = 0;
87  uint chanid_restriction = 0;
88 
89  if (!m_channels.empty() &&
90  IsInputAvailable(mplexid_restriction, chanid_restriction))
91  {
93  m_channels, m_channels[0].m_chanId,
94  mplexid_restriction, chanid_restriction, CHANNEL_DIRECTION_UP);
95 
96  auto cit = find(m_channels.begin(), m_channels.end(), chanid);
97 
98  if ((chanid != 0U) && (cit != m_channels.end()))
99  {
100  if (!setchan)
101  {
102  ok = IsTunable((mplexid_restriction || chanid_restriction)
103  ? (*cit).m_chanNum : startchannel);
104  }
105  else
106  ok = SetChannelByString((*cit).m_chanNum);
107 
108  if (ok)
109  {
110  startchannel = (*cit).m_chanNum;
111  msg2 = QString("selected '%1' instead.").arg(startchannel);
112  msg_error = false;
113  }
114  }
115  }
116 
117  LOG(VB_GENERAL, ((msg_error) ? LOG_ERR : LOG_WARNING), LOC + msg1 + msg2);
118 
119  return ok;
120 }
121 
122 bool ChannelBase::IsTunable(const QString &channum) const
123 {
124  QString loc = LOC + QString("IsTunable(%1)").arg(channum);
125 
126  if (!m_inputId)
127  {
128  LOG(VB_GENERAL, LOG_ERR, loc + " " +
129  QString("Requested non-existant input"));
130 
131  return false;
132  }
133 
134  uint mplexid_restriction = 0;
135  uint chanid_restriction = 0;
136  if (!IsInputAvailable(mplexid_restriction, chanid_restriction))
137  {
138  LOG(VB_GENERAL, LOG_ERR, loc + " " +
139  QString("Requested channel is on input '%1' "
140  "which is in a busy input group")
141  .arg(m_inputId));
142 
143  return false;
144  }
145 
146  // Fetch tuning data from the database.
147  QString tvformat;
148  QString modulation;
149  QString freqtable;
150  QString freqid;
151  QString dtv_si_std;
152  int finetune = 0;
153  uint64_t frequency = 0;
154  int mpeg_prog_num = 0;
155  uint atsc_major = 0;
156  uint atsc_minor = 0;
157  uint mplexid = 0;
158  uint chanid = 0;
159  uint tsid = 0;
160  uint netid = 0;
161  bool commfree = false;
162 
163  if (!ChannelUtil::GetChannelData(m_sourceId, chanid, channum,
164  tvformat, modulation, freqtable, freqid,
165  finetune, frequency, dtv_si_std,
166  mpeg_prog_num, atsc_major, atsc_minor,
167  tsid, netid, mplexid, commfree))
168  {
169  LOG(VB_GENERAL, LOG_ERR, loc + " " +
170  QString("Failed to find channel in DB on input '%1' ")
171  .arg(m_inputId));
172 
173  return false;
174  }
175 
176  if ((mplexid_restriction && (mplexid != mplexid_restriction)) ||
177  (!mplexid_restriction &&
178  chanid_restriction && (chanid != chanid_restriction)))
179  {
180  LOG(VB_GENERAL, LOG_ERR, loc + " " +
181  QString("Channel is valid, but tuner is busy "
182  "on different multiplex/channel (%1 != %2) / (%3 != %4)")
183  .arg(mplexid).arg(mplexid_restriction)
184  .arg(chanid).arg(chanid_restriction));
185 
186  return false;
187  }
188 
189  return true;
190 }
191 
193 {
194  if (!chanid)
195  {
196  if (!m_inputId)
197  return 0;
198 
200  }
201 
202  uint mplexid_restriction = 0;
203  uint chanid_restriction = 0;
204  (void)IsInputAvailable(mplexid_restriction, chanid_restriction);
205 
207  m_channels, chanid, mplexid_restriction, chanid_restriction,
208  direction);
209 }
210 
211 uint ChannelBase::GetNextChannel(const QString &channum, ChannelChangeDirection direction) const
212 {
213  if (!m_inputId)
214  return 0;
215 
216  uint chanid = ChannelUtil::GetChanID(m_sourceId, channum);
217  return GetNextChannel(chanid, direction);
218 }
219 
221  uint &mplexid_restriction, uint &chanid_restriction) const
222 {
223  if (!m_inputId)
224  {
225  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("no m_inputId"));
226  return false;
227  }
228 
229  InputInfo info;
230 
231  mplexid_restriction = 0;
232  chanid_restriction = 0;
233 
234  std::vector<uint> inputids = CardUtil::GetConflictingInputs(m_inputId);
235  for (uint inputid : inputids)
236  {
237  if (RemoteIsBusy(inputid, info))
238  {
239  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
240  QString("Input %1 is busy on %2/%3")
241  .arg(info.m_inputId)
242  .arg(info.m_chanId).arg(info.m_mplexId));
243  if (info.m_sourceId != m_sourceId)
244  {
245  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Input is busy"));
246  return false;
247  }
248  mplexid_restriction = info.m_mplexId;
249  chanid_restriction = info.m_chanId;
250  }
251  }
252 
253  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Input is free on %1/%2")
254  .arg(mplexid_restriction).arg(chanid_restriction));
255  return true;
256 }
257 
260 {
261  if (!m_system)
262  return true;
263 
264  m_system->Term(true);
265 
266  delete m_system;
267  m_system = nullptr;
268  return true;
269 }
270 
272 void ChannelBase::HandleScript(const QString &freqid)
273 {
274  QMutexLocker locker(&m_systemLock);
275 
276  bool ok = true;
277  m_systemStatus = 0; // unknown
278 
279  if (!m_inputId)
280  {
281  m_systemStatus = 2; // failed
282  HandleScriptEnd(true);
283  return;
284  }
285 
286  if (m_externalChanger.isEmpty())
287  {
288  m_systemStatus = 3; // success
289  HandleScriptEnd(true);
290  return;
291  }
292 
293  if (freqid.isEmpty())
294  {
295  LOG(VB_GENERAL, LOG_WARNING, LOC +
296  "A channel changer is set, but the freqid field is empty."
297  "\n\t\t\tWe will return success to ease setup pains, "
298  "but no script is will actually run.");
299  m_systemStatus = 3; // success
300  HandleScriptEnd(true);
301  return;
302  }
303 
304  // It's possible we simply never reaped the process, check status first.
305  if (m_system)
306  GetScriptStatus(true);
307 
308  // If it's still running, try killing it. GetScriptStatus() may
309  // update m_system. (cppcheck-suppress duplicateCondition)
310  if (m_system)
311  ok = KillScript();
312 
313  // The GetScriptStatus() call above can reset m_systemStatus with
314  // the exit status of the last channel change script invocation, so
315  // we must set it to pending here.
316  m_systemStatus = 1; // pending
317 
318  if (!ok)
319  {
320  LOG(VB_GENERAL, LOG_ERR, LOC +
321  "Can not execute channel changer, previous call to script "
322  "is still running.");
323  m_systemStatus = 2; // failed
324  HandleScriptEnd(ok);
325  }
326  else
327  {
328  if (m_externalChanger.toLower() == "internal")
329  {
330  ok = ChangeInternalChannel(freqid, m_inputId);
331  if (!ok)
332  {
333  LOG(VB_GENERAL, LOG_ERR, LOC + "Can not execute internal channel "
334  "changer.");
335  m_systemStatus = 2; // failed
336  }
337  else
338  m_systemStatus = 3; // success
339 
340  HandleScriptEnd(ok);
341  }
342  else
343  {
345  if (!ok)
346  {
347  LOG(VB_GENERAL, LOG_ERR, LOC + "Can not execute channel changer.");
348  m_systemStatus = 2; // failed
349  HandleScriptEnd(ok);
350  }
351  }
352  }
353 }
354 
355 bool ChannelBase::ChangeInternalChannel(const QString &freqid,
356  uint inputid) const
357 {
358 #ifdef USING_FIREWIRE
359  FirewireDevice *device = nullptr;
360  QString fwnode = CardUtil::GetFirewireChangerNode(inputid);
361  uint64_t guid = string_to_guid(fwnode);
362  QString fwmodel = CardUtil::GetFirewireChangerModel(inputid);
363 
364  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Internal channel change to %1 "
365  "on inputid %2, GUID %3 (%4)").arg(freqid).arg(inputid)
366  .arg(fwnode, fwmodel));
367 
368 #ifdef USING_LINUX_FIREWIRE
369  device = new LinuxFirewireDevice(
370  guid, 0, 100, true);
371 #endif // USING_LINUX_FIREWIRE
372 
373 #ifdef USING_OSX_FIREWIRE
374  device = new DarwinFirewireDevice(guid, 0, 100);
375 #endif // USING_OSX_FIREWIRE
376 
377  if (!device)
378  return false;
379 
380  if (!device->OpenPort())
381  return false;
382 
383  if (!device->SetChannel(fwmodel, 0, freqid.toUInt()))
384  {
385  device->ClosePort();
386  delete device;
387  device = nullptr;
388  return false;
389  }
390 
391  device->ClosePort();
392  delete device;
393  device = nullptr;
394  return true;
395 #else
396  Q_UNUSED(freqid);
397  Q_UNUSED(inputid);
398  return false;
399 #endif
400 }
401 
403 bool ChannelBase::ChangeExternalChannel(const QString &changer,
404  const QString &freqid)
405 {
406  if (m_system)
407  return false;
408 
409  if (changer.isEmpty() || freqid.isEmpty())
410  return false;
411 
412  QString command = QString("%1 %2").arg(changer, freqid);
413  LOG(VB_CHANNEL, LOG_INFO, LOC +
414  QString("Running command: %1").arg(command));
415 
417  m_system->Run();
418 
419  return true;
420 }
421 
423 {
424  if (!m_system)
425  return m_systemStatus;
426 
427  if (!holding_lock)
428  m_systemLock.lock();
429 
433  {
434  delete m_system;
435  m_system = nullptr;
436 
438  }
439 
440  LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("GetScriptStatus() %1")
441  .arg(m_systemStatus));
442 
443  uint ret = 0;
444  switch(m_systemStatus)
445  {
446  case GENERIC_EXIT_OK:
447  ret = 3; // success
448  break;
450  case GENERIC_EXIT_START:
451  ret = 1; // pending
452  break;
453  default:
454  ret = 2; // fail
455  break;
456  }
457 
458  LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("GetScriptStatus() %1 -> %2")
459  .arg(m_systemStatus). arg(ret));
460 
461  m_systemStatus = ret;
462 
463  if (!holding_lock)
464  m_systemLock.unlock();
465 
466  return ret;
467 }
468 
471 {
472  if (ok)
473  {
474  LOG(VB_CHANNEL, LOG_INFO, LOC + "Channel change script succeeded.");
475  if (m_inputId)
476  {
477  // Set this as the future start channel for this source
479  }
480  }
481  else
482  {
483  LOG(VB_GENERAL, LOG_ERR, LOC + "Channel change script failed.");
484  }
485 }
486 
487 int ChannelBase::GetChanID(void) const
488 {
489  if (!m_inputId)
490  return -1;
491 
492  int found = 0;
493  int visible = -1;
494  int id = -1;
495  MSqlQuery query(MSqlQuery::InitCon());
496 
497  query.prepare("SELECT chanid,visible FROM channel "
498  "WHERE deleted IS NULL AND "
499  " channum = :CHANNUM AND "
500  " sourceid = :SOURCEID");
501  query.bindValueNoNull(":CHANNUM", m_curChannelName);
502  query.bindValue(":SOURCEID", m_sourceId);
503 
504  if (!query.exec() || !query.isActive())
505  {
506  MythDB::DBError("fetching chanid", query);
507  return -1;
508  }
509 
510  while (query.next())
511  {
512  if (query.value(1).toInt() > 0)
513  {
514  ++found;
515  visible = query.value(0).toInt();
516  }
517  else
518  id = query.value(0).toInt();
519  }
520 
521  if (!found)
522  {
523  LOG(VB_GENERAL, LOG_INFO,
524  QString("No visible channel ids for %1 on sourceid %2")
525  .arg(m_curChannelName).arg(m_sourceId));
526  }
527 
528  if (found > 1)
529  {
530  LOG(VB_GENERAL, LOG_WARNING,
531  QString("Found multiple visible channel ids for %1 on sourceid %2")
532  .arg(m_curChannelName).arg(m_sourceId));
533  }
534 
535  return (visible >= 0 ? visible : id);
536 }
537 
542 {
543  if (!m_inputId)
544  {
545  if (m_pParent)
547  else
549  }
550 
551  if (!m_inputId)
552  {
553  LOG(VB_GENERAL, LOG_ERR,
554  "InitializeInput(): Programmer error, no parent.");
555  return false;
556  }
557 
558  MSqlQuery query(MSqlQuery::InitCon());
559  query.prepare(
560  "SELECT sourceid, inputname, "
561  " startchan, externalcommand, "
562  " tunechan "
563  "FROM capturecard "
564  "WHERE cardid = :INPUTID");
565  query.bindValue(":INPUTID", m_inputId);
566 
567  if (!query.exec() || !query.isActive())
568  {
569  MythDB::DBError("ChannelBase::InitializeInput", query);
570  return false;
571  }
572  if (!query.size())
573  {
574  LOG(VB_GENERAL, LOG_ERR, LOC +
575  QString("No capturecard record in database for input %1")
576  .arg(m_inputId));
577  return false;
578  }
579 
580  query.next();
581 
582  m_sourceId = query.value(0).toUInt();
583  m_name = query.value(1).toString();
584  m_startChanNum = query.value(2).toString();
585  m_externalChanger = query.value(3).toString();
586  m_tuneToChannel = query.value(4).toString();
587 
588  if (0 == m_sourceId)
589  {
590  LOG(VB_GENERAL, LOG_ERR, LOC +
591  QString("No video source defined for input %1")
592  .arg(m_inputId));
593  return false;
594  }
595 
597  QString order = gCoreContext->GetSetting("ChannelOrdering", "channum");
599 
601  !m_externalChanger.isEmpty())
602  {
603  LOG(VB_GENERAL, LOG_WARNING, LOC + "External Channel changer is "
604  "set, but this device does not support it.");
605  m_externalChanger.clear();
606  }
607 
608  // print it
609  LOG(VB_CHANNEL, LOG_INFO, LOC +
610  QString("Input #%1: '%2' schan(%3) sourceid(%4)")
611  .arg(m_inputId).arg(m_name, m_startChanNum)
612  .arg(m_sourceId));
613 
614  return true;
615 }
616 
621  const QString &oldChanNum,
622  const QString &newChanNum)
623 {
624  bool skip = (m_name.isEmpty() ||
625  m_startChanNum.isEmpty() ||
626  m_startChanNum != oldChanNum ||
627  m_sourceId != sourceid);
628  if (!skip)
629  m_startChanNum = newChanNum;
630 
631  if (GetSourceID() == sourceid && oldChanNum == m_curChannelName)
632  m_curChannelName = newChanNum;
633 
635 }
636 
641 {
642  MSqlQuery query(MSqlQuery::InitCon());
643 
644  if (m_name.isEmpty() || m_startChanNum.isEmpty())
645  return;
646 
647  query.prepare(
648  "UPDATE capturecard "
649  "SET startchan = :STARTCHAN "
650  "WHERE cardid = :CARDINPUTID");
651  query.bindValue(":STARTCHAN", m_startChanNum);
652  query.bindValue(":CARDINPUTID", m_inputId);
653 
654  if (!query.exec() || !query.isActive())
655  MythDB::DBError("StoreInputChannels", query);
656 }
657 
658 bool ChannelBase::CheckChannel(const QString &channum) const
659 {
660  MSqlQuery query(MSqlQuery::InitCon());
661  if (!query.isConnected())
662  return false;
663 
664  query.prepare(
665  "SELECT channel.chanid "
666  "FROM channel, capturecard "
667  "WHERE channel.deleted IS NULL AND "
668  " channel.channum = :CHANNUM AND "
669  " channel.sourceid = capturecard.sourceid AND "
670  " capturecard.cardid = :INPUTID AND "
671  " capturecard.hostname = :HOSTNAME");
672  query.bindValue(":CHANNUM", channum);
673  query.bindValue(":INPUTID", m_inputId);
674  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
675 
676  if (!query.exec() || !query.isActive())
677  {
678  MythDB::DBError("checkchannel", query);
679  }
680  else if (query.size() > 0)
681  return true;
682 
683  LOG(VB_CHANNEL, LOG_ERR, LOC +
684  QString("Failed to find channel(%1) on input (%2).")
685  .arg(channum).arg(m_inputId));
686  return false;
687 }
688 
690  TVRec *tvrec,
691  const GeneralDBOptions &genOpt,
692  const DVBDBOptions &dvbOpt,
693  const FireWireDBOptions &fwOpt,
694  const QString &startchannel,
695  bool enter_power_save_mode,
696  QString &rbFileExt,
697  bool setchan)
698 {
699  rbFileExt = "ts";
700 
701  ChannelBase *channel = nullptr;
702  if (genOpt.m_inputType == "DVB")
703  {
704 #ifdef USING_DVB
705  channel = new DVBChannel(genOpt.m_videoDev, tvrec);
706  auto *dvbchannel = dynamic_cast<DVBChannel*>(channel);
707  if (dvbchannel != nullptr)
708  dvbchannel->SetSlowTuning(dvbOpt.m_dvbTuningDelay);
709 #endif
710  }
711  else if (genOpt.m_inputType == "FIREWIRE")
712  {
713 #ifdef USING_FIREWIRE
714  channel = new FirewireChannel(tvrec, genOpt.m_videoDev, fwOpt);
715 #else
716  Q_UNUSED(fwOpt);
717 #endif
718  }
719 #ifdef USING_HDHOMERUN
720  else if (genOpt.m_inputType == "HDHOMERUN")
721  {
722  channel = new HDHRChannel(tvrec, genOpt.m_videoDev);
723  }
724 #endif
725 #ifdef USING_SATIP
726  else if (genOpt.m_inputType == "SATIP")
727  {
728  channel = new SatIPChannel(tvrec, genOpt.m_videoDev);
729  }
730 #endif
731  else if ((genOpt.m_inputType == "IMPORT") ||
732  (genOpt.m_inputType == "DEMO") ||
733  (genOpt.m_inputType == "MPEG" &&
734  genOpt.m_videoDev.startsWith("file:", Qt::CaseInsensitive)))
735  {
736  channel = new DummyChannel(tvrec);
737  rbFileExt = "mpg";
738  }
739 #ifdef USING_IPTV
740  else if (genOpt.m_inputType == "FREEBOX") // IPTV
741  { // NOLINTNEXTLINE(bugprone-branch-clone)
742  channel = new IPTVChannel(tvrec, genOpt.m_videoDev);
743  }
744 #endif
745 #ifdef USING_VBOX
746  else if (genOpt.m_inputType == "VBOX")
747  {
748  channel = new IPTVChannel(tvrec, genOpt.m_videoDev);
749  }
750 #endif
751 #ifdef USING_ASI
752  else if (genOpt.m_inputType == "ASI")
753  {
754  channel = new ASIChannel(tvrec, genOpt.m_videoDev);
755  }
756 #endif
757 #ifdef USING_CETON
758  else if (genOpt.m_inputType == "CETON")
759  {
760  channel = new CetonChannel(tvrec, genOpt.m_videoDev);
761  }
762 #endif
763  else if (genOpt.m_inputType == "V4L2ENC")
764  {
765 #ifdef USING_V4L2
766  channel = new V4LChannel(tvrec, genOpt.m_videoDev);
767 #endif
768  if (genOpt.m_inputType == "MPEG")
769  rbFileExt = "mpg";
770  }
771  else if (CardUtil::IsV4L(genOpt.m_inputType))
772  {
773 #ifdef USING_V4L2
774  channel = new V4LChannel(tvrec, genOpt.m_videoDev);
775 #endif
776  if (genOpt.m_inputType != "HDPVR")
777  {
778  if (genOpt.m_inputType != "MPEG")
779  rbFileExt = "nuv";
780  else
781  rbFileExt = "mpg";
782  }
783  }
784  else if (genOpt.m_inputType == "EXTERNAL")
785  {
786  channel = new ExternalChannel(tvrec, genOpt.m_videoDev);
787  }
788 
789  if (!channel)
790  {
791  QString msg = QString(
792  "%1 card configured on video device %2, \n"
793  "but MythTV was not compiled with %3 support. \n"
794  "\n"
795  "Recompile MythTV with %4 support or remove the card \n"
796  "from the configuration and restart MythTV.")
797  .arg(genOpt.m_inputType, genOpt.m_videoDev,
798  genOpt.m_inputType, genOpt.m_inputType);
799  LOG(VB_GENERAL, LOG_ERR, "ChannelBase: CreateChannel() Error: \n" +
800  msg + "\n");
801  return nullptr;
802  }
803 
804  if (!channel->Open())
805  {
806  LOG(VB_GENERAL, LOG_ERR, "ChannelBase: CreateChannel() Error: " +
807  QString("Failed to open device %1").arg(genOpt.m_videoDev));
808  delete channel;
809  return nullptr;
810  }
811 
812  QString channum = startchannel;
813  channel->Init(channum, setchan);
814 
815  if (enter_power_save_mode)
816  {
817  if (channel &&
818  ((genOpt.m_inputType == "DVB" && dvbOpt.m_dvbOnDemand) ||
819  genOpt.m_inputType == "HDHOMERUN" ||
820  genOpt.m_inputType == "EXTERNAL" ||
821  CardUtil::IsV4L(genOpt.m_inputType)))
822  {
823  channel->Close();
824  }
825  else if (setchan)
826  {
827  auto *dtvchannel = dynamic_cast<DTVChannel*>(channel);
828  if (dtvchannel)
829  dtvchannel->EnterPowerSavingMode();
830  }
831  }
832 
833  return channel;
834 }
835 
837 {
839  return false;
840 
841  if (!m_inputId)
842  {
843  LOG(VB_GENERAL, LOG_ERR, LOC +
844  QString("IsExternalChannelChangeInUse: "
845  "non-existant input"));
846  return false;
847  }
848 
849  return !m_externalChanger.isEmpty();
850 }
851 
853 {
854  return m_pParent ? m_pParent->GetMajorId() : m_inputId;
855 }
GeneralDBOptions
Definition: tv_rec.h:68
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:212
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:802
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:124
ChannelBase::Close
virtual void Close(void)=0
Closes the channel changing hardware to use.
linuxfirewiredevice.h
dtvchannel.h
ChannelBase::Init
virtual bool Init(QString &startchannel, bool setchan)
Definition: channelbase.cpp:57
MSqlQuery::size
int size(void) const
Definition: mythdbcon.h:211
MSqlQuery::bindValueNoNull
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
Definition: mythdbcon.cpp:883
GENERIC_EXIT_OK
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
InputInfo::m_chanId
uint m_chanId
chanid restriction if applicable
Definition: inputinfo.h:51
MythSystemLegacy::Term
void Term(bool force=false)
Definition: mythsystemlegacy.cpp:284
TVRec::GetMajorId
uint GetMajorId(void)
Definition: tv_rec.h:239
ChannelChangeDirection
ChannelChangeDirection
ChannelChangeDirection is an enumeration of possible channel changing directions.
Definition: tv.h:28
MythSystemLegacy
Definition: mythsystemlegacy.h:67
ChannelBase::m_name
QString m_name
Definition: channelbase.h:139
CHANNEL_DIRECTION_UP
@ CHANNEL_DIRECTION_UP
Definition: tv.h:30
ChannelBase::HandleScriptEnd
virtual void HandleScriptEnd(bool ok)
Definition: channelbase.cpp:470
ChannelBase::Open
virtual bool Open(void)=0
Opens the channel changing hardware for use.
darwinfirewiredevice.h
CardUtil::GetFirstInputID
static uint GetFirstInputID(const QString &videodevice)
Convenience function for GetInputIDs()
Definition: cardutil.h:258
firewirechannel.h
GeneralDBOptions::m_inputType
QString m_inputType
Definition: tv_rec.h:76
frequencies.h
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:201
DarwinFirewireDevice
Definition: darwinfirewiredevice.h:10
ChannelBase::CreateChannel
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)
Definition: channelbase.cpp:689
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
ChannelBase::m_inputId
uint m_inputId
Definition: channelbase.h:137
ChannelBase::IsTunable
virtual bool IsTunable(const QString &channum) const
Definition: channelbase.cpp:122
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
CetonChannel
Definition: cetonchannel.h:22
string_to_guid
static uint64_t string_to_guid(const QString &guid)
Definition: avcinfo.h:17
channelbase.h
ChannelBase::m_startChanNum
QString m_startChanNum
Definition: channelbase.h:140
ChannelBase::m_systemLock
QMutex m_systemLock
Definition: channelbase.h:145
ChannelUtil::GetNextChannel
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)
Definition: channelutil.cpp:2334
ChannelBase::m_tuneToChannel
QString m_tuneToChannel
Definition: channelbase.h:142
satipchannel.h
ChannelBase::IsExternalChannelChangeSupported
virtual bool IsExternalChannelChangeSupported(void)
Definition: channelbase.h:121
dvbchannel.h
HDHRChannel
Definition: hdhrchannel.h:20
CardUtil::GetFirewireChangerModel
static QString GetFirewireChangerModel(uint inputid)
Definition: cardutil.cpp:1572
ChannelBase::Renumber
virtual void Renumber(uint sourceid, const QString &oldChanNum, const QString &newChanNum)
Changes a channum if we have it cached anywhere.
Definition: channelbase.cpp:620
LinuxFirewireDevice
Definition: linuxfirewiredevice.h:19
ChannelBase::m_channels
ChannelInfoList m_channels
channels across all inputs
Definition: channelbase.h:143
ChannelUtil::SortChannels
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
Definition: channelutil.cpp:2277
ChannelBase::IsInputAvailable
virtual bool IsInputAvailable(uint &mplexid_restriction, uint &chanid_restriction) const
Switches to another input on hardware, and sets the channel is setstarting is true.
Definition: channelbase.cpp:220
SatIPChannel
Definition: satipchannel.h:12
ChannelBase::HandleScript
void HandleScript(const QString &freqid)
Definition: channelbase.cpp:272
TVRec::GetInputId
uint GetInputId(void) const
Returns the inputid.
Definition: tv_rec.h:237
sourceutil.h
cetonchannel.h
ChannelUtil::GetChanID
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
Definition: channelutil.cpp:1308
mythlogging.h
DVBChannel::SetSlowTuning
void SetSlowTuning(std::chrono::milliseconds how_slow)
Definition: dvbchannel.h:46
ChannelBase
Abstract class providing a generic interface to tuning hardware.
Definition: channelbase.h:31
RemoteIsBusy
bool RemoteIsBusy(uint inputid, InputInfo &busy_input)
Definition: tvremoteutil.cpp:361
ChannelBase::StoreInputChannels
virtual void StoreInputChannels(void)
Saves current channel as the default channel for the current input.
Definition: channelbase.cpp:640
ChannelBase::m_curChannelName
QString m_curChannelName
Definition: channelbase.h:135
FirewireChannel
FirewireChannel Copyright (c) 2005 by Jim Westfall and Dave Abrahams Distributed as part of MythTV un...
Definition: firewirechannel.h:14
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
compat.h
v4lchannel.h
DVBDBOptions::m_dvbOnDemand
bool m_dvbOnDemand
Definition: tv_rec.h:89
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:200
ChannelBase::IsExternalChannelChangeInUse
virtual bool IsExternalChannelChangeInUse(void)
Definition: channelbase.cpp:836
MythSystemLegacy::Wait
uint Wait(std::chrono::seconds timeout=0s)
Definition: mythsystemlegacy.cpp:242
IPTVChannel
Definition: iptvchannel.h:24
ChannelUtil::GetChannels
static ChannelInfoList GetChannels(uint sourceid, bool visible_only, const QString &group_by=QString(), uint channel_groupid=0)
Definition: channelutil.h:243
MSqlQuery::isConnected
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:134
uint
unsigned int uint
Definition: compat.h:144
ExternalChannel
-*- Mode: c++ -*-
Definition: ExternalChannel.h:17
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
DTVChannel::EnterPowerSavingMode
virtual bool EnterPowerSavingMode(void)
Enters power saving mode if the card supports it.
Definition: dtvchannel.h:65
CardUtil::IsV4L
static bool IsV4L(const QString &rawtype)
Definition: cardutil.h:140
asichannel.h
CardUtil::GetFirewireChangerNode
static QString GetFirewireChangerNode(uint inputid)
Definition: cardutil.cpp:1555
kMSRunShell
@ kMSRunShell
run process through shell
Definition: mythsystem.h:43
channelutil.h
tvremoteutil.h
InputInfo::m_inputId
uint m_inputId
unique key in DB for this input
Definition: inputinfo.h:49
kMSRunBackground
@ kMSRunBackground
run child in the background
Definition: mythsystem.h:38
iptvchannel.h
LOC
#define LOC
Definition: channelbase.cpp:48
ChannelBase::GetScriptStatus
uint GetScriptStatus(bool holding_lock=false)
Definition: channelbase.cpp:422
ChannelUtil::GetChannelData
static bool GetChannelData(uint sourceid, uint &chanid, const QString &channum, 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)
Definition: channelutil.cpp:1881
InputInfo::m_sourceId
uint m_sourceId
associated channel listings source
Definition: inputinfo.h:48
DVBChannel
Provides interface to the tuning hardware when using DVB drivers.
Definition: dvbchannel.h:30
ChannelBase::ChangeInternalChannel
bool ChangeInternalChannel(const QString &freqid, uint cardinputid) const
Definition: channelbase.cpp:355
ChannelBase::SetChannelByString
virtual bool SetChannelByString(const QString &chan)=0
ASIChannel
-*- Mode: c++ -*-
Definition: asichannel.h:14
ChannelBase::m_systemStatus
uint m_systemStatus
These get mapped from the GENERIC_EXIT_* to these values for use with the signalmonitor code.
Definition: channelbase.h:150
ChannelBase::KillScript
bool KillScript(void)
Definition: channelbase.cpp:259
mythcorecontext.h
ChannelBase::m_sourceId
uint m_sourceId
Definition: channelbase.h:138
cardutil.h
ChannelBase::CheckChannel
bool CheckChannel(const QString &channum) const
Definition: channelbase.cpp:658
ExternalChannel.h
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:878
DVBDBOptions
Definition: tv_rec.h:84
GeneralDBOptions::m_videoDev
QString m_videoDev
Definition: tv_rec.h:73
TVRec
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:145
FireWireDBOptions
Definition: tv_rec.h:94
GENERIC_EXIT_START
#define GENERIC_EXIT_START
MythSystemLegacy process starting.
Definition: exitcodes.h:35
DVBDBOptions::m_dvbTuningDelay
std::chrono::milliseconds m_dvbTuningDelay
Definition: tv_rec.h:90
inputinfo.h
InputInfo
Definition: inputinfo.h:14
ChannelBase::GetDevice
virtual QString GetDevice(void) const
Returns String representing device, useful for debugging.
Definition: channelbase.h:78
dummychannel.h
ChannelBase::ChangeExternalChannel
bool ChangeExternalChannel(const QString &changer, const QString &freqid)
Definition: channelbase.cpp:403
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:862
ChannelBase::GetSourceID
virtual uint GetSourceID(void) const
Definition: channelbase.h:71
MythSystemLegacy::Run
void Run(std::chrono::seconds timeout=0s)
Runs a command inside the /bin/sh shell. Returns immediately.
Definition: mythsystemlegacy.cpp:212
DTVChannel
Class providing a generic interface to digital tuning hardware.
Definition: dtvchannel.h:33
ChannelBase::GetNextChannel
virtual uint GetNextChannel(uint chanid, ChannelChangeDirection direction) const
Definition: channelbase.cpp:192
DummyChannel
DummyChannel.
Definition: dummychannel.h:14
GENERIC_EXIT_RUNNING
#define GENERIC_EXIT_RUNNING
Process is running.
Definition: exitcodes.h:25
FirewireDevice::SetChannel
virtual bool SetChannel(const QString &panel_model, uint alt_method, uint channel)
Definition: firewiredevice.cpp:145
ChannelBase::m_system
MythSystemLegacy * m_system
Definition: channelbase.h:146
exitcodes.h
hdhrchannel.h
CardUtil::GetConflictingInputs
static std::vector< uint > GetConflictingInputs(uint inputid)
Definition: cardutil.cpp:2132
ChannelBase::GetMajorID
int GetMajorID(void)
Definition: channelbase.cpp:852
ChannelBase::InitializeInput
virtual bool InitializeInput(void)
Fills in input map from DB.
Definition: channelbase.cpp:541
V4LChannel
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
Definition: v4lchannel.h:30
ChannelBase::~ChannelBase
virtual ~ChannelBase(void)
Definition: channelbase.cpp:50
FirewireDevice::ClosePort
virtual bool ClosePort(void)=0
ChannelBase::m_pParent
TVRec * m_pParent
Definition: channelbase.h:134
InputInfo::m_mplexId
uint m_mplexId
mplexid restriction if applicable
Definition: inputinfo.h:50
find
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)
Definition: dvbstreamhandler.cpp:356
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:922
FirewireDevice
Definition: firewiredevice.h:23
ChannelBase::m_externalChanger
QString m_externalChanger
Definition: channelbase.h:141
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:827
FirewireDevice::OpenPort
virtual bool OpenPort(void)=0
ChannelBase::GetChanID
virtual int GetChanID(void) const
Definition: channelbase.cpp:487