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