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