MythTV  master
videosource.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 // Standard UNIX C headers
4 #include <unistd.h>
5 #include <fcntl.h>
6 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(_WIN32)
7 #include <sys/types.h>
8 #else
9 #include <sys/sysmacros.h>
10 #endif
11 #include <sys/stat.h>
12 
13 // C++ headers
14 #include <algorithm>
15 using namespace std;
16 
17 // Qt headers
18 #include <QCoreApplication>
19 #include <QCursor>
20 #include <QDateTime>
21 #include <QDir>
22 #include <QFile>
23 #include <QLayout>
24 #include <QMap>
25 #include <QStringList>
26 #include <QTextStream>
27 #include <utility>
28 
29 // MythTV headers
30 #include "mythconfig.h"
31 #include "mythcorecontext.h"
32 #include "videosource.h"
33 #include "scanwizard.h"
34 #include "cardutil.h"
35 #include "sourceutil.h"
36 #include "channelinfo.h"
37 #include "channelutil.h"
38 #include "frequencies.h"
39 #include "diseqcsettings.h"
40 #include "firewiredevice.h"
41 #include "compat.h"
42 #include "mythdb.h"
43 #include "mythdirs.h"
44 #include "mythlogging.h"
45 #include "libmythupnp/httprequest.h" // for TestMimeType()
46 #include "mythsystemlegacy.h"
47 #include "exitcodes.h"
48 #include "v4l2util.h"
49 #include "mythnotification.h"
50 #include "mythterminal.h"
51 
52 #ifdef USING_DVB
53 #include "dvbtypes.h"
54 #endif
55 
56 #ifdef USING_VBOX
57 #include "vboxutils.h"
58 #endif
59 
60 #ifdef USING_HDHOMERUN
61 #include HDHOMERUN_HEADERFILE
62 #endif
63 
64 static const uint kDefaultMultirecCount = 2;
65 
67  const QString &_card_types,
68  bool _must_have_mplexid) :
69  m_initialSourceId(_initial_sourceid),
70  m_cardTypes(_card_types),
71  m_mustHaveMplexId(_must_have_mplexid)
72 {
73  setLabel(tr("Video Source"));
74 }
75 
77 {
79 
80  QString querystr =
81  "SELECT DISTINCT videosource.name, videosource.sourceid "
82  "FROM capturecard, videosource";
83 
84  querystr += (m_mustHaveMplexId) ? ", channel " : " ";
85 
86  querystr +=
87  "WHERE capturecard.sourceid = videosource.sourceid AND "
88  " capturecard.hostname = :HOSTNAME ";
89 
90  if (!m_cardTypes.isEmpty())
91  {
92  querystr += QString(" AND capturecard.cardtype in %1 ")
93  .arg(m_cardTypes);
94  }
95 
97  {
98  querystr +=
99  " AND channel.sourceid = videosource.sourceid "
100  " AND channel.mplexid != 32767 "
101  " AND channel.mplexid != 0 ";
102  }
103 
104  query.prepare(querystr);
105  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
106 
107  if (!query.exec() || !query.isActive() || query.size() <= 0)
108  return;
109 
110  uint sel = 0, cnt = 0;
111  for (; query.next(); cnt++)
112  {
113  addSelection(query.value(0).toString(),
114  query.value(1).toString());
115 
116  sel = (query.value(1).toUInt() == m_initialSourceId) ? cnt : sel;
117  }
118 
119  if (m_initialSourceId)
120  {
121  if (cnt)
122  setValue(sel);
123  setEnabled(false);
124  }
125 
127 }
128 
130 {
131  public:
132  InstanceCount(const CardInput &parent, int _initValue) :
133  MythUISpinBoxSetting(new CardInputDBStorage(this, parent, "reclimit"),
134  1, 10, 1)
135  {
136  setLabel(QObject::tr("Max recordings"));
137  setValue(_initValue);
138  setHelpText(
139  QObject::tr(
140  "Maximum number of simultaneous recordings MythTV will "
141  "attempt using this device. If set to a value other than "
142  "1, MythTV can sometimes record multiple programs on "
143  "the same multiplex or overlapping copies of the same "
144  "program on a single channel."
145  ));
146  };
147 };
148 
150 {
151  public:
152  explicit SchedGroup(const CardInput &parent) :
153  MythUICheckBoxSetting(new CardInputDBStorage(this, parent, "schedgroup"))
154  {
155  setLabel(QObject::tr("Schedule as group"));
156  setValue(true);
157  setHelpText(
158  QObject::tr(
159  "Schedule all virtual inputs on this device as a group. "
160  "This is more efficient than scheduling each input "
161  "individually. Additional, virtual inputs will be "
162  "automatically added as needed to fulfill the recording "
163  "load."
164  ));
165  };
166 };
167 
169 {
170  QString sourceidTag(":WHERESOURCEID");
171 
172  QString query("sourceid = " + sourceidTag);
173 
174  bindings.insert(sourceidTag, m_parent.getSourceID());
175 
176  return query;
177 }
178 
180 {
181  QString sourceidTag(":SETSOURCEID");
182  QString colTag(":SET" + GetColumnName().toUpper());
183 
184  QString query("sourceid = " + sourceidTag + ", " +
185  GetColumnName() + " = " + colTag);
186 
187  bindings.insert(sourceidTag, m_parent.getSourceID());
188  bindings.insert(colTag, m_user->GetDBValue());
189 
190  return query;
191 }
192 
194 {
195  QString cardidTag(":WHERECARDID");
196 
197  QString query("cardid = " + cardidTag);
198 
199  bindings.insert(cardidTag, m_parent.getCardID());
200 
201  return query;
202 }
203 
205 {
206  QString cardidTag(":SETCARDID");
207  QString colTag(":SET" + GetColumnName().toUpper());
208 
209  QString query("cardid = " + cardidTag + ", " +
210  GetColumnName() + " = " + colTag);
211 
212  bindings.insert(cardidTag, m_parent.getCardID());
213  bindings.insert(colTag, m_user->GetDBValue());
214 
215  return query;
216 }
217 
219 {
220  public:
221  explicit XMLTVGrabber(const VideoSource &parent) :
223  "xmltvgrabber")),
224  m_parent(parent)
225  {
226  setLabel(QObject::tr("Listings grabber"));
227  };
228 
229  void Load(void) override // StandardSetting
230  {
231  addTargetedChild("eitonly", new EITOnly_config(m_parent, this));
232  addTargetedChild("/bin/true", new NoGrabber_config(m_parent));
233 
234  addSelection(
235  QObject::tr("Transmitted guide only (EIT)"), "eitonly");
236 
237  addSelection(QObject::tr("No grabber"), "/bin/true");
238 
239  QString gname, d1, d2, d3;
241 
242 #ifdef _MSC_VER
243 #pragma message( "tv_find_grabbers is not supported yet on windows." )
244  //-=>TODO:Screen doesn't show up if the call to MythSysemLegacy is executed
245 #else
246 
247  QString loc = "XMLTVGrabber::Load: ";
248  QString loc_err = "XMLTVGrabber::Load, Error: ";
249 
250  QStringList name_list;
251  QStringList prog_list;
252 
253  QStringList args;
254  args += "baseline";
255 
256  MythSystemLegacy find_grabber_proc("tv_find_grabbers", args,
258  find_grabber_proc.Run(25);
259  LOG(VB_GENERAL, LOG_INFO,
260  loc + "Running 'tv_find_grabbers " + args.join(" ") + "'.");
261  uint status = find_grabber_proc.Wait();
262 
263  if (status == GENERIC_EXIT_OK)
264  {
265  QTextStream ostream(find_grabber_proc.ReadAll());
266  while (!ostream.atEnd())
267  {
268  QString grabber_list(ostream.readLine());
269  QStringList grabber_split =
270  grabber_list.split("|", QString::SkipEmptyParts);
271  QString grabber_name = grabber_split[1] + " (xmltv)";
272  QFileInfo grabber_file(grabber_split[0]);
273 
274  name_list.push_back(grabber_name);
275  prog_list.push_back(grabber_file.fileName());
276  LOG(VB_GENERAL, LOG_DEBUG, "Found " + grabber_split[0]);
277  }
278  LOG(VB_GENERAL, LOG_INFO, loc + "Finished running tv_find_grabbers");
279  }
280  else
281  LOG(VB_GENERAL, LOG_ERR, loc + "Failed to run tv_find_grabbers");
282 
283  LoadXMLTVGrabbers(name_list, prog_list);
284 
286 #endif
287  }
288 
289  void Save(void) override // StandardSetting
290  {
292 
293  MSqlQuery query(MSqlQuery::InitCon());
294  query.prepare(
295  "UPDATE videosource "
296  "SET userid=NULL, password=NULL "
297  "WHERE xmltvgrabber NOT IN ( 'technovera' )");
298  if (!query.exec())
299  MythDB::DBError("XMLTVGrabber::Save", query);
300  }
301 
302  void LoadXMLTVGrabbers(QStringList name_list, QStringList prog_list)
303  {
304  if (name_list.size() != prog_list.size())
305  return;
306 
307  QString selValue = getValue();
308  int selIndex = getValueIndex(selValue);
309  setValue(0);
310 
311  for (uint i = 0; i < (uint) name_list.size(); i++)
312  {
313  addTargetedChild(prog_list[i],
314  new XMLTV_generic_config(m_parent, prog_list[i],
315  this));
316  addSelection(name_list[i], prog_list[i]);
317  }
318 
319  if (!selValue.isEmpty())
320  selIndex = getValueIndex(selValue);
321  if (selIndex >= 0)
322  setValue(selIndex);
323  }
324 private:
326 };
327 
329 {
330  public:
332  uint min_val, uint max_val, uint step,
333  const QString &setting) :
334  MythUISpinBoxSetting(new CaptureCardDBStorage(this, parent, setting),
335  min_val, max_val, step)
336  {
337  }
338 };
339 
341 {
342  public:
344  const QString &setting) :
345  MythUITextEditSetting(new CaptureCardDBStorage(this, parent, setting))
346  {
347  }
348 };
349 
351 {
352  public:
353  DVBNetID(const VideoSource &parent, signed int value, signed int min_val) :
354  MythUISpinBoxSetting(new VideoSourceDBStorage(this, parent, "dvb_nit_id"),
355  min_val, 0xffff, 1)
356  {
357  setLabel(QObject::tr("Network ID"));
358  //: Network_ID is the name of an identifier in the DVB's Service
359  //: Information standard specification.
360  setHelpText(QObject::tr("If your provider has asked you to configure a "
361  "specific network identifier (Network_ID), "
362  "enter it here. Leave it at -1 otherwise."));
363  setValue(value);
364  };
365 };
366 
368  MythUIComboBoxSetting(new VideoSourceDBStorage(this, parent, "freqtable"))
369 {
370  setLabel(QObject::tr("Channel frequency table"));
371  addSelection("default");
372 
373  for (uint i = 0; chanlists[i].name; i++)
375 
376  setHelpText(QObject::tr("Use default unless this source uses a "
377  "different frequency table than the system wide table "
378  "defined in the General settings."));
379 }
380 
382  m_sourceId(_sourceid)
383 {
384  setLabel(QObject::tr("Channel frequency table"));
385 
386  for (uint i = 0; chanlists[i].name; i++)
388 }
389 
391 {
392  int idx1 = getValueIndex(gCoreContext->GetSetting("FreqTable"));
393  if (idx1 >= 0)
394  setValue(idx1);
395 
396  if (!m_sourceId)
397  return;
398 
399  MSqlQuery query(MSqlQuery::InitCon());
400  query.prepare(
401  "SELECT freqtable "
402  "FROM videosource "
403  "WHERE sourceid = :SOURCEID");
404  query.bindValue(":SOURCEID", m_sourceId);
405 
406  if (!query.exec() || !query.isActive())
407  {
408  MythDB::DBError("TransFreqTableSelector::load", query);
409  return;
410  }
411 
412  m_LoadedFreqTable.clear();
413 
414  if (query.next())
415  {
416  m_LoadedFreqTable = query.value(0).toString();
417  if (!m_LoadedFreqTable.isEmpty() &&
418  (m_LoadedFreqTable.toLower() != "default"))
419  {
420  int idx2 = getValueIndex(m_LoadedFreqTable);
421  if (idx2 >= 0)
422  setValue(idx2);
423  }
424  }
425 }
426 
428 {
429  LOG(VB_GENERAL, LOG_INFO, "TransFreqTableSelector::Save(void)");
430 
431  if ((m_LoadedFreqTable == getValue()) ||
432  ((m_LoadedFreqTable.toLower() == "default") &&
433  (getValue() == gCoreContext->GetSetting("FreqTable"))))
434  {
435  return;
436  }
437 
438  MSqlQuery query(MSqlQuery::InitCon());
439  query.prepare(
440  "UPDATE videosource "
441  "SET freqtable = :FREQTABLE "
442  "WHERE sourceid = :SOURCEID");
443 
444  query.bindValue(":FREQTABLE", getValue());
445  query.bindValue(":SOURCEID", m_sourceId);
446 
447  if (!query.exec() || !query.isActive())
448  {
449  MythDB::DBError("TransFreqTableSelector::load", query);
450  return;
451  }
452 }
453 
455 {
456  m_sourceId = _sourceid;
457  Load();
458 }
459 
461 {
462  public:
463  explicit UseEIT(const VideoSource &parent) :
464  MythUICheckBoxSetting(new VideoSourceDBStorage(this, parent, "useeit"))
465  {
466  setLabel(QObject::tr("Perform EIT scan"));
467  setHelpText(QObject::tr(
468  "If enabled, program guide data for channels on this "
469  "source will be updated with data provided by the "
470  "channels themselves 'Over-the-Air'."));
471  }
472 };
473 
475  const QString& _grabber,
476  StandardSetting *_setting) :
477  m_parent(_parent), m_grabber(_grabber)
478 {
479  setVisible(false);
480 
481  QString filename = QString("%1/%2.xmltv")
482  .arg(GetConfDir()).arg(m_parent.getSourceName());
483 
484  m_grabberArgs.push_back("--config-file");
485  m_grabberArgs.push_back(filename);
486  m_grabberArgs.push_back("--configure");
487 
488  _setting->addTargetedChild(_grabber, new UseEIT(m_parent));
489 
490  ButtonStandardSetting *config = new ButtonStandardSetting(tr("Configure"));
491  config->setHelpText(tr("Run XMLTV configure command."));
492 
493  _setting->addTargetedChild(_grabber, config);
494 
495  connect(config, SIGNAL(clicked()), SLOT(RunConfig()));
496 }
497 
499 {
501 #if 0
502  QString err_msg = QObject::tr(
503  "You MUST run 'mythfilldatabase --manual' the first time,\n"
504  "instead of just 'mythfilldatabase'.\nYour grabber does not provide "
505  "channel numbers, so you have to set them manually.");
506 
508  {
509  LOG(VB_GENERAL, LOG_ERR, err_msg);
510  ShowOkPopup(err_msg);
511  }
512 #endif
513 }
514 
516 {
518  MythScreenType *ssd =
519  new MythTerminal(mainStack, m_grabber, m_grabberArgs);
520 
521  if (ssd->Create())
522  mainStack->AddScreen(ssd);
523  else
524  delete ssd;
525 }
526 
528 {
529  setVisible(false);
530 
531  m_useeit = new UseEIT(_parent);
532  m_useeit->setValue(true);
533  m_useeit->setVisible(false);
535 
536  TransTextEditSetting *label;
537  label=new TransTextEditSetting();
538  label->setValue(QObject::tr("Use only the transmitted guide data."));
539  label->setHelpText(
540  QObject::tr("This will usually only work with ATSC or DVB channels, "
541  "and generally provides data only for the next few days."));
542  _setting->addTargetedChild("eitonly", label);
543 }
544 
546 {
547  // Force this value on
548  m_useeit->setValue(true);
549  m_useeit->Save();
550 }
551 
553 {
554  m_useeit = new UseEIT(_parent);
555  m_useeit->setValue(false);
556  m_useeit->setVisible(false);
558 
560  label->setValue(QObject::tr("Do not configure a grabber"));
561  addTargetedChild("/bin/true", label);
562 }
563 
565 {
566  m_useeit->setValue(false);
567  m_useeit->Save();
568 }
569 
571 {
572  // must be first
573  m_id = new ID();
574  addChild(m_id = new ID());
575 
576  setLabel(QObject::tr("Video Source Setup"));
577  addChild(m_name = new Name(*this));
578  addChild(new XMLTVGrabber(*this));
579  addChild(new FreqTableSelector(*this));
580  addChild(new DVBNetID(*this, -1, -1));
581 }
582 
584 {
585  return true;
586 }
587 
589 {
591 }
592 
593 bool VideoSourceEditor::cardTypesInclude(const int &sourceID,
594  const QString &thecardtype)
595 {
596  MSqlQuery query(MSqlQuery::InitCon());
597  query.prepare("SELECT count(cardtype)"
598  " FROM capturecard "
599  " WHERE capturecard.sourceid = :SOURCEID "
600  " AND capturecard.cardtype = :CARDTYPE ;");
601  query.bindValue(":SOURCEID", sourceID);
602  query.bindValue(":CARDTYPE", thecardtype);
603 
604  if (query.exec() && query.next())
605  {
606  int count = query.value(0).toInt();
607 
608  if (count > 0)
609  return true;
610  }
611 
612  return false;
613 }
614 
616 {
617  MSqlQuery result(MSqlQuery::InitCon());
618  result.prepare("SELECT name, sourceid FROM videosource;");
619 
620  if (result.exec() && result.isActive() && result.size() > 0)
621  {
622  while (result.next())
623  {
624  VideoSource* source = new VideoSource();
625  source->setLabel(result.value(0).toString());
626  source->loadByID(result.value(1).toInt());
627  setting->addChild(source);
628  }
629  }
630 }
631 
633 {
634  MSqlQuery result(MSqlQuery::InitCon());
635  result.prepare("SELECT name, sourceid FROM videosource;");
636 
637  if (result.exec() && result.isActive() && result.size() > 0)
638  {
639  while (result.next())
640  {
641  setting->addSelection(result.value(0).toString(),
642  result.value(1).toString());
643  }
644  }
645 }
646 
647 void VideoSource::loadByID(int sourceid)
648 {
649  m_id->setValue(sourceid);
650 }
651 
653 {
654  public:
655  VideoDevice(const CaptureCard &parent,
656  uint minor_min = 0,
657  uint minor_max = UINT_MAX,
658  const QString& card = QString(),
659  const QString& driver = QString()) :
660  CaptureCardComboBoxSetting(parent, true, "videodevice")
661  {
662  setLabel(QObject::tr("Video device"));
663 
664  // /dev/v4l/video*
665  QDir dev("/dev/v4l", "video*", QDir::Name, QDir::System);
666  fillSelectionsFromDir(dev, minor_min, minor_max,
667  card, driver, false);
668 
669  // /dev/video*
670  dev.setPath("/dev");
671  fillSelectionsFromDir(dev, minor_min, minor_max,
672  card, driver, false);
673 
674  // /dev/dtv/video*
675  dev.setPath("/dev/dtv");
676  fillSelectionsFromDir(dev, minor_min, minor_max,
677  card, driver, false);
678 
679  // /dev/dtv*
680  dev.setPath("/dev");
681  dev.setNameFilters(QStringList("dtv*"));
682  fillSelectionsFromDir(dev, minor_min, minor_max,
683  card, driver, false);
684  };
685 
690  void fillSelectionsFromDir(const QDir &dir, bool absPath = true)
691  {
692  // Needed to make both compiler and doxygen happy.
693  (void) absPath;
694 
695  fillSelectionsFromDir(dir, 0, 255, QString(), QString(), false);
696  }
697 
698  uint fillSelectionsFromDir(const QDir& dir,
699  uint minor_min, uint minor_max,
700  const QString& card, const QString& driver,
701  bool allow_duplicates)
702  {
703  uint cnt = 0;
704 
705  QFileInfoList il = dir.entryInfoList();
706  QRegExp *driverExp = nullptr;
707  if (!driver.isEmpty())
708  driverExp = new QRegExp(driver);
709 
710  for( QFileInfoList::iterator it = il.begin();
711  it != il.end();
712  ++it )
713  {
714  QFileInfo &fi = *it;
715 
716  struct stat st;
717  QString filepath = fi.absoluteFilePath();
718  int err = lstat(filepath.toLocal8Bit().constData(), &st);
719 
720  if (err)
721  {
722  LOG(VB_GENERAL, LOG_ERR,
723  QString("Could not stat file: %1").arg(filepath));
724  continue;
725  }
726 
727  // is this is a character device?
728  if (!S_ISCHR(st.st_mode))
729  continue;
730 
731  // is this device is in our minor range?
732  uint minor_num = minor(st.st_rdev);
733  if (minor_min > minor_num || minor_max < minor_num)
734  continue;
735 
736  // ignore duplicates if allow_duplicates not set
737  if (!allow_duplicates && m_minorList[minor_num])
738  continue;
739 
740  // if the driver returns any info add this device to our list
741  QByteArray tmp = filepath.toLatin1();
742  int videofd = open(tmp.constData(), O_RDWR);
743  if (videofd >= 0)
744  {
745  QString card_name, driver_name;
746  if (CardUtil::GetV4LInfo(videofd, card_name, driver_name) &&
747  (!driverExp || (driverExp->exactMatch(driver_name))) &&
748  (card.isEmpty() || (card_name == card)))
749  {
750  addSelection(filepath);
751  cnt++;
752  }
753  close(videofd);
754  }
755 
756  // add to list of minors discovered to avoid duplicates
757  m_minorList[minor_num] = 1;
758  }
759  delete driverExp;
760 
761  return cnt;
762  }
763 
764  QString Driver(void) const { return m_driverName; }
765  QString Card(void) const { return m_cardName; }
766 
767  private:
768  QMap<uint, uint> m_minorList;
769  QString m_cardName;
770  QString m_driverName;
771 };
772 
774 {
775  public:
776  explicit VBIDevice(const CaptureCard &parent) :
777  CaptureCardComboBoxSetting(parent, true /*, mustexist true */,
778  "vbidevice")
779  {
780  setLabel(QObject::tr("VBI device"));
781  setFilter(QString(), QString());
782  setHelpText(QObject::tr("Device to read VBI (captions) from."));
783  };
784 
785  uint setFilter(const QString &card, const QString &driver)
786  {
787  uint count = 0;
788  clearSelections();
789  QDir dev("/dev/v4l", "vbi*", QDir::Name, QDir::System);
790  if (!(count = fillSelectionsFromDir(dev, card, driver)))
791  {
792  dev.setPath("/dev");
793  if (!(count = fillSelectionsFromDir(dev, card, driver)) &&
794  !getValue().isEmpty())
795  {
796  addSelection(getValue(),getValue(),true);
797  }
798  }
799 
800  return count;
801  }
802 
807  void fillSelectionsFromDir(const QDir &dir, bool absPath = true)
808  {
809  // Needed to make both compiler and doxygen happy.
810  (void) absPath;
811 
812  fillSelectionsFromDir(dir, QString(), QString());
813  }
814 
815  uint fillSelectionsFromDir(const QDir &dir, const QString &card,
816  const QString &driver)
817  {
818  QStringList devices;
819  QFileInfoList il = dir.entryInfoList();
820  for( QFileInfoList::iterator it = il.begin();
821  it != il.end();
822  ++it )
823  {
824  QFileInfo &fi = *it;
825 
826  QString device = fi.absoluteFilePath();
827  QByteArray adevice = device.toLatin1();
828  int vbifd = open(adevice.constData(), O_RDWR);
829  if (vbifd < 0)
830  continue;
831 
832  QString cn, dn;
833  if (CardUtil::GetV4LInfo(vbifd, cn, dn) &&
834  (driver.isEmpty() || (dn == driver)) &&
835  (card.isEmpty() || (cn == card)))
836  {
837  devices.push_back(device);
838  }
839 
840  close(vbifd);
841  }
842 
843  QString sel = getValue();
844  for (uint i = 0; i < (uint) devices.size(); i++)
845  addSelection(devices[i], devices[i], devices[i] == sel);
846 
847  return (uint) devices.size();
848  }
849 };
850 
852 {
853  public:
854  explicit CommandPath(const CaptureCard &parent) :
856  "videodevice"))
857  {
858  setLabel(QObject::tr(""));
859  setValue("");
860  setHelpText(QObject::tr("Specify the command to run, with any "
861  "needed arguments."));
862  };
863 };
864 
866 {
867  public:
868  explicit FileDevice(const CaptureCard &parent) :
870  new CaptureCardDBStorage(this, parent, "videodevice")
871  /* mustexist, false */)
872  {
873  setLabel(QObject::tr("File path"));
874  };
875 };
876 
878 {
879  public:
880  explicit AudioDevice(const CaptureCard &parent) :
881  CaptureCardComboBoxSetting(parent, true /* mustexist false */,
882  "audiodevice")
883  {
884  setLabel(QObject::tr("Audio device"));
885 #if USING_OSS
886  QDir dev("/dev", "dsp*", QDir::Name, QDir::System);
888  dev.setPath("/dev/sound");
890 #endif
891 #if USING_ALSA
892  addSelection("ALSA:default", "ALSA:default");
893 #endif
894  addSelection(QObject::tr("(None)"), "NULL");
895  setHelpText(QObject::tr("Device to read audio from, "
896  "if audio is separate from the video."));
897  };
898 };
899 
901 {
902  public:
903  SignalTimeout(const CaptureCard &parent, uint value, uint min_val) :
904  CaptureCardSpinBoxSetting(parent, min_val, 60000, 250, "signal_timeout")
905  {
906  setLabel(QObject::tr("Signal timeout (ms)"));
907  setValue(QString::number(value));
908  setHelpText(QObject::tr(
909  "Maximum time (in milliseconds) MythTV waits for "
910  "a signal when scanning for channels."));
911  };
912 };
913 
915 {
916  public:
917  ChannelTimeout(const CaptureCard &parent, uint value, uint min_val) :
918  CaptureCardSpinBoxSetting(parent, min_val, 65000, 250,
919  "channel_timeout")
920  {
921  setLabel(QObject::tr("Tuning timeout (ms)"));
922  setValue(value);
923  setHelpText(QObject::tr(
924  "Maximum time (in milliseconds) MythTV waits for "
925  "a channel lock. For recordings, if this time is "
926  "exceeded, the recording will be marked as failed."));
927  };
928 };
929 
931 {
932  public:
933  explicit AudioRateLimit(const CaptureCard &parent) :
934  CaptureCardComboBoxSetting(parent, false, "audioratelimit")
935  {
936  setLabel(QObject::tr("Force audio sampling rate"));
937  setHelpText(
938  QObject::tr("If non-zero, override the audio sampling "
939  "rate in the recording profile when this card is "
940  "used. Use this if your capture card does not "
941  "support all of the standard rates."));
942  addSelection(QObject::tr("(None)"), "0");
943  addSelection("32000");
944  addSelection("44100");
945  addSelection("48000");
946  };
947 };
948 
950 {
951  public:
952  explicit SkipBtAudio(const CaptureCard &parent) :
954  "skipbtaudio"))
955  {
956  setLabel(QObject::tr("Do not adjust volume"));
957  setHelpText(
958  QObject::tr("Enable this option for budget BT878 based "
959  "DVB-T cards such as the AverTV DVB-T which "
960  "require the audio volume to be left alone."));
961  };
962 };
963 
965 {
966  public:
967  explicit DVBCardNum(const CaptureCard &parent) :
968  CaptureCardComboBoxSetting(parent, true, "videodevice")
969  {
970  setLabel(QObject::tr("DVB device"));
971  setHelpText(
972  QObject::tr("When you change this setting, the text below "
973  "should change to the name and type of your card. "
974  "If the card cannot be opened, an error message "
975  "will be displayed."));
976  fillSelections(QString());
977  };
978 
982  void fillSelections(const QString &current)
983  {
984  clearSelections();
985 
986  // Get devices from filesystem
987  QStringList sdevs = CardUtil::ProbeVideoDevices("DVB");
988 
989  // Add current if needed
990  if (!current.isEmpty() &&
991  (find(sdevs.begin(), sdevs.end(), current) == sdevs.end()))
992  {
993  stable_sort(sdevs.begin(), sdevs.end());
994  }
995 
996  QStringList db = CardUtil::GetVideoDevices("DVB");
997 
998  QMap<QString,bool> in_use;
999  QString sel = current;
1000  for (uint i = 0; i < (uint)sdevs.size(); i++)
1001  {
1002  const QString dev = sdevs[i];
1003  in_use[sdevs[i]] = find(db.begin(), db.end(), dev) != db.end();
1004  if (sel.isEmpty() && !in_use[sdevs[i]])
1005  sel = dev;
1006  }
1007 
1008  if (sel.isEmpty() && !sdevs.empty())
1009  sel = sdevs[0];
1010 
1011  QString usestr = QString(" -- ");
1012  usestr += QObject::tr("Warning: already in use");
1013 
1014  for (uint i = 0; i < (uint)sdevs.size(); i++)
1015  {
1016  const QString dev = sdevs[i];
1017  QString desc = dev + (in_use[sdevs[i]] ? usestr : "");
1018  desc = (current == sdevs[i]) ? dev : desc;
1019  addSelection(desc, dev, dev == sel);
1020  }
1021  }
1022 
1023  void Load(void) override // StandardSetting
1024  {
1025  clearSelections();
1026  addSelection(QString());
1027 
1029 
1031  fillSelections(dev);
1032  }
1033 };
1034 
1035 // Use capturecard/inputname to store the delivery system selection of the card
1037 {
1038  public:
1039  explicit DVBCardType(const CaptureCard &parent) :
1040  CaptureCardComboBoxSetting(parent, false, "inputname")
1041  {
1042  setLabel(QObject::tr("Delivery system"));
1043  setHelpText(
1044  QObject::tr("If your card supports more than one delivery system "
1045  "then you can select here the one that you want to use."));
1046  };
1047 };
1048 
1050 {
1051  public:
1053  {
1054  setLabel(QObject::tr("Frontend ID"));
1055  setEnabled(false);
1056  };
1057 };
1058 
1060 {
1061  public:
1062  explicit DVBNoSeqStart(const CaptureCard &parent) :
1064  new CaptureCardDBStorage(this, parent, "dvb_wait_for_seqstart"))
1065  {
1066  setLabel(QObject::tr("Wait for SEQ start header"));
1067  setValue(true);
1068  setHelpText(
1069  QObject::tr("If enabled, drop packets from the start of a DVB "
1070  "recording until a sequence start header is seen."));
1071  };
1072 };
1073 
1075 {
1076  public:
1077  explicit DVBOnDemand(const CaptureCard &parent) :
1079  new CaptureCardDBStorage(this, parent, "dvb_on_demand"))
1080  {
1081  setLabel(QObject::tr("Open DVB card on demand"));
1082  setValue(true);
1083  setHelpText(
1084  QObject::tr("If enabled, only open the DVB card when required, "
1085  "leaving it free for other programs at other times."));
1086  };
1087 };
1088 
1090 {
1091  public:
1092  explicit DVBEITScan(const CaptureCard &parent) :
1094  new CaptureCardDBStorage(this, parent, "dvb_eitscan"))
1095  {
1096  setLabel(QObject::tr("Use DVB card for active EIT scan"));
1097  setValue(true);
1098  setHelpText(
1099  QObject::tr("If enabled, activate active scanning for "
1100  "program data (EIT). When this option is enabled "
1101  "the DVB card is constantly in-use."));
1102  };
1103 };
1104 
1106 {
1107  public:
1108  explicit DVBTuningDelay(const CaptureCard &parent) :
1109  CaptureCardSpinBoxSetting(parent, 0, 2000, 25, "dvb_tuning_delay")
1110  {
1111  setValue("0");
1112  setLabel(QObject::tr("DVB tuning delay (ms)"));
1113  setValue(true);
1114  setHelpText(
1115  QObject::tr("Some Linux DVB drivers, in particular for the "
1116  "Hauppauge Nova-T, require that we slow down "
1117  "the tuning process by specifying a delay "
1118  "(in milliseconds)."));
1119  };
1120 };
1121 
1123 {
1124  public:
1125  explicit FirewireGUID(const CaptureCard &parent) :
1126  CaptureCardComboBoxSetting(parent, false, "videodevice")
1127  {
1128  setLabel(QObject::tr("GUID"));
1129 #ifdef USING_FIREWIRE
1130  vector<AVCInfo> list = FirewireDevice::GetSTBList();
1131  for (size_t i = 0; i < list.size(); i++)
1132  {
1133  QString guid = list[i].GetGUIDString();
1134  guid_to_avcinfo[guid] = list[i];
1135  addSelection(guid);
1136  }
1137 #endif // USING_FIREWIRE
1138  }
1139 
1140  AVCInfo GetAVCInfo(const QString &guid) const
1141  { return guid_to_avcinfo[guid]; }
1142 
1143  private:
1144  QMap<QString,AVCInfo> guid_to_avcinfo;
1145 };
1146 
1148  const FirewireGUID *_guid) :
1149  CaptureCardComboBoxSetting(parent, false, "firewire_model"),
1150  m_guid(_guid)
1151 {
1152  setLabel(QObject::tr("Cable box model"));
1153  addSelection(QObject::tr("Motorola Generic"), "MOTO GENERIC");
1154  addSelection(QObject::tr("SA/Cisco Generic"), "SA GENERIC");
1155  addSelection("DCH-3200");
1156  addSelection("DCX-3200");
1157  addSelection("DCT-3412");
1158  addSelection("DCT-3416");
1159  addSelection("DCT-6200");
1160  addSelection("DCT-6212");
1161  addSelection("DCT-6216");
1162  addSelection("QIP-6200");
1163  addSelection("QIP-7100");
1164  addSelection("PACE-550");
1165  addSelection("PACE-779");
1166  addSelection("SA3250HD");
1167  addSelection("SA4200HD");
1168  addSelection("SA4250HDC");
1169  addSelection("SA8300HD");
1170  QString help = QObject::tr(
1171  "Choose the model that most closely resembles your set top box. "
1172  "Depending on firmware revision SA4200HD may work better for a "
1173  "SA3250HD box.");
1174  setHelpText(help);
1175 }
1176 
1177 void FirewireModel::SetGUID(const QString &_guid)
1178 {
1179  (void) _guid;
1180 
1181 #ifdef USING_FIREWIRE
1182  AVCInfo info = m_guid->GetAVCInfo(_guid);
1183  QString model = FirewireDevice::GetModelName(info.m_vendorid, info.m_modelid);
1184  setValue(max(getValueIndex(model), 0));
1185 #endif // USING_FIREWIRE
1186 }
1187 
1188 void FirewireDesc::SetGUID(const QString &_guid)
1189 {
1190  (void) _guid;
1191 
1192  setLabel(tr("Description"));
1193 
1194 #ifdef USING_FIREWIRE
1195  QString name = m_guid->GetAVCInfo(_guid).m_product_name;
1196  name.replace("Scientific-Atlanta", "SA");
1197  name.replace(", Inc.", "");
1198  name.replace("Explorer(R)", "");
1199  name = name.simplified();
1200  setValue((name.isEmpty()) ? "" : name);
1201 #endif // USING_FIREWIRE
1202 }
1203 
1205 {
1206  public:
1207  explicit FirewireConnection(const CaptureCard &parent) :
1209  "firewire_connection"))
1210  {
1211  setLabel(QObject::tr("Connection Type"));
1212  addSelection(QObject::tr("Point to Point"),"0");
1213  addSelection(QObject::tr("Broadcast"),"1");
1214  }
1215 };
1216 
1218 {
1219  public:
1220  explicit FirewireSpeed(const CaptureCard &parent) :
1222  "firewire_speed"))
1223  {
1224  setLabel(QObject::tr("Speed"));
1225  addSelection(QObject::tr("100Mbps"),"0");
1226  addSelection(QObject::tr("200Mbps"),"1");
1227  addSelection(QObject::tr("400Mbps"),"2");
1228  addSelection(QObject::tr("800Mbps"),"3");
1229  }
1230 };
1231 
1232 #ifdef USING_FIREWIRE
1233 static void FirewireConfigurationGroup(CaptureCard& parent, CardType& cardtype)
1234 {
1235  FirewireGUID *dev(new FirewireGUID(parent));
1236  FirewireDesc *desc(new FirewireDesc(dev));
1237  FirewireModel *model(new FirewireModel(parent, dev));
1238  cardtype.addTargetedChild("FIREWIRE", dev);
1239  cardtype.addTargetedChild("FIREWIRE", new EmptyAudioDevice(parent));
1240  cardtype.addTargetedChild("FIREWIRE", new EmptyVBIDevice(parent));
1241  cardtype.addTargetedChild("FIREWIRE", desc);
1242  cardtype.addTargetedChild("FIREWIRE", model);
1243 
1244 #ifdef USING_LINUX_FIREWIRE
1245  cardtype.addTargetedChild("FIREWIRE", new FirewireConnection(parent));
1246  cardtype.addTargetedChild("FIREWIRE", new FirewireSpeed(parent));
1247 #endif // USING_LINUX_FIREWIRE
1248 
1249  cardtype.addTargetedChild("FIREWIRE", new SignalTimeout(parent, 2000, 1000));
1250  cardtype.addTargetedChild("FIREWIRE", new ChannelTimeout(parent, 9000, 1750));
1251 
1252  model->SetGUID(dev->getValue());
1253  desc->SetGUID(dev->getValue());
1254  QObject::connect(dev, SIGNAL(valueChanged(const QString&)),
1255  model, SLOT( SetGUID( const QString&)));
1256  QObject::connect(dev, SIGNAL(valueChanged(const QString&)),
1257  desc, SLOT( SetGUID( const QString&)));
1258 }
1259 #endif
1260 
1261 #if USING_HDHOMERUN
1262 
1263 // -----------------------
1264 // HDHomeRun Configuration
1265 // -----------------------
1266 
1268  HDHomeRunConfigurationGroup &_group) :
1270  new CaptureCardDBStorage(this, parent, "videodevice")),
1271  group(_group)
1272 {
1273  setVisible(false);
1274 };
1275 
1277 {
1280 }
1281 
1283 {
1286 }
1287 
1289 {
1290  public:
1291  explicit HDHomeRunEITScan(const CaptureCard &parent) :
1293  new CaptureCardDBStorage(this, parent, "dvb_eitscan"))
1294  {
1295  setLabel(QObject::tr("Use HD HomeRun for active EIT scan"));
1296  setValue(true);
1297  setHelpText(
1298  QObject::tr("If enabled, activate active scanning for "
1299  "program data (EIT). When this option is enabled "
1300  "the HD HomeRun is constantly in-use."));
1301  };
1302 };
1303 
1304 
1306 {
1307  public:
1308  explicit UseHDHomeRunDevice(QString &deviceid, QString &model,
1309  QString &ipaddr)
1310  {
1311  setLabel(QObject::tr("Use HDHomeRun %1 (%2 %3)")
1312  .arg(deviceid).arg(model).arg(ipaddr));
1313  setValue(false);
1314  setHelpText(
1315  QObject::tr("If enabled, use tuners from this HDHomeRun "
1316  "device."));
1317  };
1318 };
1319 
1321  (CaptureCard& a_parent, CardType &a_cardtype) :
1322  m_parent(a_parent)
1323 {
1324  setVisible(false);
1325 
1326  // Fill Device list
1327  FillDeviceList();
1328 
1329  m_deviceId = new HDHomeRunDeviceID(m_parent, *this);
1330 
1331  QMap<QString, HDHomeRunDevice>::iterator dit;
1332  for (dit = m_deviceList.begin(); dit != m_deviceList.end(); ++dit)
1333  {
1334  HDHomeRunDevice &dev = *dit;
1335  dev.checkbox = new UseHDHomeRunDevice(
1336  dev.deviceid, dev.model, dev.cardip);
1337  a_cardtype.addTargetedChild("HDHOMERUN", dev.checkbox);
1338  }
1339  a_cardtype.addTargetedChild("HDHOMERUN", new EmptyAudioDevice(m_parent));
1340  a_cardtype.addTargetedChild("HDHOMERUN", new EmptyVBIDevice(m_parent));
1341  a_cardtype.addTargetedChild("HDHOMERUN", m_deviceId);
1342 
1343  GroupSetting *buttonRecOpt = new GroupSetting();
1344  buttonRecOpt->setLabel(tr("Recording Options"));
1345  buttonRecOpt->addChild(new SignalTimeout(m_parent, 1000, 250));
1346  buttonRecOpt->addChild(new ChannelTimeout(m_parent, 3000, 1750));
1347  buttonRecOpt->addChild(new HDHomeRunEITScan(m_parent));
1348  a_cardtype.addTargetedChild("HDHOMERUN", buttonRecOpt);
1349 };
1350 
1352 {
1353  m_deviceList.clear();
1354 
1355  // Find physical devices first
1356  // ProbeVideoDevices returns "deviceid ip" pairs
1357  QStringList devs = CardUtil::ProbeVideoDevices("HDHOMERUN");
1358 
1359  QStringList::const_iterator it;
1360 
1361  for (it = devs.begin(); it != devs.end(); ++it)
1362  {
1363  QString dev = *it;
1364  QStringList devinfo = dev.split(" ");
1365  const QString& devid = devinfo.at(0);
1366  const QString& devip = devinfo.at(1);
1367  const QString& model = devinfo.at(2);
1368 
1369  HDHomeRunDevice tmpdevice;
1370  tmpdevice.model = model;
1371  tmpdevice.cardip = devip;
1372  tmpdevice.deviceid = devid;
1373  // Fully specify object. Checkboxes will be added later when
1374  // the configuration group is created.
1375  tmpdevice.checkbox = nullptr;
1376  m_deviceList[tmpdevice.deviceid] = tmpdevice;
1377  }
1378 
1379 #if 0
1380  // Debug dump of cards
1381  QMap<QString, HDHomeRunDevice>::iterator debugit;
1382  for (debugit = m_deviceList.begin(); debugit != m_deviceList.end(); ++debugit)
1383  {
1384  LOG(VB_GENERAL, LOG_DEBUG, QString("%1: %2 %3")
1385  .arg(debugit.key()).arg((*debugit).model)
1386  .arg((*debugit).cardip));
1387  }
1388 #endif
1389 }
1390 
1392 {
1393  QStringList devstrs = devices.split(",");
1394  for (int i = 0; i < devstrs.size(); ++i)
1395  {
1396  // Get the HDHomeRun device ID using libhdhomerun. We need to
1397  // do it this way because legacy configurations could use an
1398  // IP address and a tuner nubmer.
1399  QByteArray ba = devstrs[i].toUtf8();
1400  hdhomerun_device_t *device = hdhomerun_device_create_from_str(
1401  ba.data(), nullptr);
1402  if (!device)
1403  continue;
1404  QString devid = QString("%1").arg(
1405  hdhomerun_device_get_device_id(device), 8, 16).toUpper();
1406  hdhomerun_device_destroy(device);
1407 
1408  // If we know about this device, set its checkbox to on.
1409  QMap<QString, HDHomeRunDevice>::iterator dit;
1410  dit = m_deviceList.find(devid);
1411  if (dit != m_deviceList.end())
1412  (*dit).checkbox->setValue(true);
1413  }
1414 }
1415 
1417 {
1418  // Return a string listing each HDHomeRun device with its checbox
1419  // turned on.
1420  QStringList devstrs;
1421  QMap<QString, HDHomeRunDevice>::iterator dit;
1422  for (dit = m_deviceList.begin(); dit != m_deviceList.end(); ++dit)
1423  {
1424  if ((*dit).checkbox->boolValue())
1425  devstrs << (*dit).deviceid;
1426  }
1427  QString devices = devstrs.join(",");
1428  return devices;
1429 }
1430 
1431 #endif
1432 
1433 // -----------------------
1434 // VBOX Configuration
1435 // -----------------------
1436 
1438 {
1439  setLabel(QObject::tr("IP Address"));
1440  setHelpText(QObject::tr("Device IP or ID of a VBox device. eg. '192.168.1.100' or 'vbox_3718'"));
1441  VBoxIP::setEnabled(false);
1442  connect(this, SIGNAL(valueChanged(const QString&)),
1443  this, SLOT(UpdateDevices(const QString&)));
1444 };
1445 
1447 {
1449  if (e)
1450  {
1451  if (!m_oldValue.isEmpty())
1453  emit NewIP(getValue());
1454  }
1455  else
1456  {
1457  m_oldValue = getValue();
1458  }
1459 }
1460 
1461 void VBoxIP::UpdateDevices(const QString &v)
1462 {
1463  if (isEnabled())
1464  emit NewIP(v);
1465 }
1466 
1468 {
1469  setLabel(QObject::tr("Tuner"));
1470  setHelpText(QObject::tr("Number and type of the tuner to use. eg '1-DVBT/T2'."));
1472  connect(this, SIGNAL(valueChanged(const QString&)),
1473  this, SLOT(UpdateDevices(const QString&)));
1474 };
1475 
1477 {
1479  if (e) {
1480  if (!m_oldValue.isEmpty())
1482  emit NewTuner(getValue());
1483  }
1484  else
1485  {
1486  m_oldValue = getValue();
1487  }
1488 }
1489 
1490 void VBoxTunerIndex::UpdateDevices(const QString &v)
1491 {
1492  if (isEnabled())
1493  emit NewTuner(v);
1494 }
1495 
1497  MythUITextEditSetting(new CaptureCardDBStorage(this, parent, "videodevice"))
1498 {
1499  setLabel(tr("Device ID"));
1500  setHelpText(tr("Device ID of VBox device"));
1501  setEnabled(false);
1502 }
1503 
1504 void VBoxDeviceID::SetIP(const QString &ip)
1505 {
1506  m_ip = ip;
1507  setValue(QString("%1-%2").arg(m_ip).arg(m_tuner));
1508 }
1509 
1510 void VBoxDeviceID::SetTuner(const QString &tuner)
1511 {
1512  m_tuner = tuner;
1513  setValue(QString("%1-%2").arg(m_ip).arg(m_tuner));
1514 }
1515 
1516 void VBoxDeviceID::SetOverrideDeviceID(const QString &deviceid)
1517 {
1518  m_overrideDeviceId = deviceid;
1519  setValue(deviceid);
1520 }
1521 
1523 {
1524  GetStorage()->Load();
1525  if (!m_overrideDeviceId.isEmpty())
1526  {
1528  m_overrideDeviceId.clear();
1529  }
1530 }
1531 
1533  VBoxDeviceID *deviceid,
1534  StandardSetting *desc,
1535  VBoxIP *cardip,
1536  VBoxTunerIndex *cardtuner,
1537  VBoxDeviceList *devicelist,
1538  const CaptureCard &parent) :
1539  m_deviceId(deviceid),
1540  m_desc(desc),
1541  m_cardIp(cardip),
1542  m_cardTuner(cardtuner),
1543  m_deviceList(devicelist),
1544  m_parent(parent)
1545 {
1546  setLabel(QObject::tr("Available devices"));
1547  setHelpText(
1548  QObject::tr(
1549  "Device IP or ID, tuner number and tuner type of available VBox devices."));
1550 
1551  connect(this, SIGNAL(valueChanged(const QString&)),
1552  this, SLOT(UpdateDevices(const QString&)));
1553 };
1554 
1556 void VBoxDeviceIDList::fillSelections(const QString &cur)
1557 {
1558  clearSelections();
1559 
1560  vector<QString> devs;
1561  QMap<QString, bool> in_use;
1562 
1563  const QString& current = cur;
1564 
1565  VBoxDeviceList::iterator it = m_deviceList->begin();
1566  for (; it != m_deviceList->end(); ++it)
1567  {
1568  devs.push_back(it.key());
1569  in_use[it.key()] = (*it).inuse;
1570  }
1571 
1572  QString man_addr = VBoxDeviceIDList::tr("Manually Enter IP Address");
1573  QString sel = man_addr;
1574  devs.push_back(sel);
1575 
1576  vector<QString>::const_iterator it2 = devs.begin();
1577  for (; it2 != devs.end(); ++it2)
1578  sel = (current == *it2) ? *it2 : sel;
1579 
1580  QString usestr = QString(" -- ");
1581  usestr += QObject::tr("Warning: already in use");
1582 
1583  for (size_t i = 0; i < devs.size(); i++)
1584  {
1585  const QString dev = devs[i];
1586  QString desc = dev + (in_use[devs[i]] ? usestr : "");
1587  addSelection(desc, dev, dev == sel);
1588  }
1589 
1590  if (current != cur)
1591  {
1593  }
1594  else if (sel == man_addr && !current.isEmpty())
1595  {
1596  // Populate the proper values for IP address and tuner
1597  QStringList selection = current.split("-");
1598 
1599  m_cardIp->SetOldValue(selection.first());
1600  m_cardTuner->SetOldValue(selection.last());
1601 
1602  m_cardIp->setValue(selection.first());
1603  m_cardTuner->setValue(selection.last());
1604  }
1605 }
1606 
1608 {
1609  clearSelections();
1610 
1611  int cardid = m_parent.getCardID();
1612  QString device = CardUtil::GetVideoDevice(cardid);
1613  fillSelections(device);
1614 }
1615 
1616 void VBoxDeviceIDList::UpdateDevices(const QString &v)
1617 {
1618  if (v == VBoxDeviceIDList::tr("Manually Enter IP Address"))
1619  {
1620  m_cardIp->setEnabled(true);
1621  m_cardTuner->setEnabled(true);
1622  }
1623  else if (!v.isEmpty())
1624  {
1625  if (m_oldValue == VBoxDeviceIDList::tr("Manually Enter IP Address"))
1626  {
1627  m_cardIp->setEnabled(false);
1628  m_cardTuner->setEnabled(false);
1629  }
1630  m_deviceId->setValue(v);
1631 
1632  // Update _cardip and _cardtuner
1633  m_cardIp->setValue((*m_deviceList)[v].cardip);
1634  m_cardTuner->setValue(QString("%1").arg((*m_deviceList)[v].tunerno));
1635  m_desc->setValue((*m_deviceList)[v].desc);
1636  }
1637  m_oldValue = v;
1638 };
1639 
1640 // -----------------------
1641 // IPTV Configuration
1642 // -----------------------
1643 
1645 {
1646  public:
1647  explicit IPTVHost(const CaptureCard &parent) :
1648  CaptureCardTextEditSetting(parent, "videodevice")
1649  {
1650  setValue("http://mafreebox.freebox.fr/freeboxtv/playlist.m3u");
1651  setLabel(QObject::tr("M3U URL"));
1652  setHelpText(
1653  QObject::tr("URL of M3U containing RTSP/RTP/UDP channel URLs."));
1654  }
1655 };
1656 
1657 static void IPTVConfigurationGroup(CaptureCard& parent, CardType& cardType)
1658 {
1659  cardType.addTargetedChild("FREEBOX", new IPTVHost(parent));
1660  cardType.addTargetedChild("FREEBOX", new ChannelTimeout(parent, 30000, 1750));
1661  cardType.addTargetedChild("FREEBOX", new EmptyAudioDevice(parent));
1662  cardType.addTargetedChild("FREEBOX", new EmptyVBIDevice(parent));
1663 }
1664 
1666 {
1667  public:
1668  explicit ASIDevice(const CaptureCard &parent) :
1669  CaptureCardComboBoxSetting(parent, true, "videodevice")
1670  {
1671  setLabel(QObject::tr("ASI device"));
1672  fillSelections(QString());
1673  };
1674 
1678  void fillSelections(const QString &current)
1679  {
1680  clearSelections();
1681 
1682  // Get devices from filesystem
1683  QStringList sdevs = CardUtil::ProbeVideoDevices("ASI");
1684 
1685  // Add current if needed
1686  if (!current.isEmpty() &&
1687  (find(sdevs.begin(), sdevs.end(), current) == sdevs.end()))
1688  {
1689  stable_sort(sdevs.begin(), sdevs.end());
1690  }
1691 
1692  // Get devices from DB
1693  QStringList db = CardUtil::GetVideoDevices("ASI");
1694 
1695  // Figure out which physical devices are already in use
1696  // by another card defined in the DB, and select a device
1697  // for new configs (preferring non-conflicing devices).
1698  QMap<QString,bool> in_use;
1699  QString sel = current;
1700  for (uint i = 0; i < (uint)sdevs.size(); ++i)
1701  {
1702  const QString dev = sdevs[i];
1703  in_use[sdevs[i]] = find(db.begin(), db.end(), dev) != db.end();
1704  if (sel.isEmpty() && !in_use[sdevs[i]])
1705  sel = dev;
1706  }
1707 
1708  // Unfortunately all devices are conflicted, select first device.
1709  if (sel.isEmpty() && !sdevs.empty())
1710  sel = sdevs[0];
1711 
1712  QString usestr = QString(" -- ");
1713  usestr += QObject::tr("Warning: already in use");
1714 
1715  // Add the devices to the UI
1716  bool found = false;
1717  for (uint i = 0; i < (uint)sdevs.size(); ++i)
1718  {
1719  const QString dev = sdevs[i];
1720  QString desc = dev + (in_use[sdevs[i]] ? usestr : "");
1721  desc = (current == sdevs[i]) ? dev : desc;
1722  addSelection(desc, dev, dev == sel);
1723  found |= (dev == sel);
1724  }
1725 
1726  // If a configured device isn't on the list, add it with warning
1727  if (!found && !current.isEmpty())
1728  {
1729  QString desc = current + " -- " +
1730  QObject::tr("Warning: unable to open");
1731  addSelection(desc, current, true);
1732  }
1733  }
1734 
1735  void Load(void) override // StandardSetting
1736  {
1737  clearSelections();
1738  addSelection(QString());
1739  GetStorage()->Load();
1741  }
1742 };
1743 
1745  CardType &cardType):
1746  m_parent(a_parent),
1747  m_device(new ASIDevice(m_parent)),
1748  m_cardInfo(new TransTextEditSetting())
1749 {
1750  setVisible(false);
1751  m_cardInfo->setLabel(tr("Status"));
1752  m_cardInfo->setEnabled(false);
1753 
1754  cardType.addTargetedChild("ASI", m_device);
1755  cardType.addTargetedChild("ASI", new EmptyAudioDevice(m_parent));
1756  cardType.addTargetedChild("ASI", new EmptyVBIDevice(m_parent));
1757  cardType.addTargetedChild("ASI", m_cardInfo);
1758 
1759  connect(m_device, SIGNAL(valueChanged(const QString&)),
1760  this, SLOT( probeCard( const QString&)));
1761 
1763 };
1764 
1765 void ASIConfigurationGroup::probeCard(const QString &device)
1766 {
1767 #ifdef USING_ASI
1768  if (device.isEmpty())
1769  {
1770  m_cardInfo->setValue("");
1771  return;
1772  }
1773 
1774  if (m_parent.getCardID() && m_parent.GetRawCardType() != "ASI")
1775  {
1776  m_cardInfo->setValue("");
1777  return;
1778  }
1779 
1780  QString error;
1781  int device_num = CardUtil::GetASIDeviceNumber(device, &error);
1782  if (device_num < 0)
1783  {
1784  m_cardInfo->setValue(tr("Not a valid DVEO ASI card"));
1785  LOG(VB_GENERAL, LOG_WARNING,
1786  "ASIConfigurationGroup::probeCard(), Warning: " + error);
1787  return;
1788  }
1789  m_cardInfo->setValue(tr("Valid DVEO ASI card"));
1790 #else
1791  Q_UNUSED(device);
1792  m_cardInfo->setValue(QString("Not compiled with ASI support"));
1793 #endif
1794 }
1795 
1797  CardType& a_cardtype):
1798  m_parent(a_parent),
1799  m_info(new TransTextEditSetting()), m_size(new TransTextEditSetting())
1800 {
1801  setVisible(false);
1802  FileDevice *device = new FileDevice(m_parent);
1803  device->setHelpText(tr("A local file used to simulate a recording."
1804  " Leave empty to use MythEvents to trigger an"
1805  " external program to import recording files."));
1806  a_cardtype.addTargetedChild("IMPORT", device);
1807 
1808  a_cardtype.addTargetedChild("IMPORT", new EmptyAudioDevice(m_parent));
1809  a_cardtype.addTargetedChild("IMPORT", new EmptyVBIDevice(m_parent));
1810 
1811  m_info->setLabel(tr("File info"));
1812  m_info->setEnabled(false);
1813  a_cardtype.addTargetedChild("IMPORT", m_info);
1814 
1815  m_size->setLabel(tr("File size"));
1816  m_size->setEnabled(false);
1817  a_cardtype.addTargetedChild("IMPORT", m_size);
1818 
1819  connect(device, SIGNAL(valueChanged(const QString&)),
1820  this, SLOT( probeCard( const QString&)));
1821 
1822  probeCard(device->getValue());
1823 };
1824 
1825 void ImportConfigurationGroup::probeCard(const QString &device)
1826 {
1827  QString ci, cs;
1828  QFileInfo fileInfo(device);
1829 
1830  // For convenience, ImportRecorder allows both formats:
1831  if (device.toLower().startsWith("file:"))
1832  fileInfo.setFile(device.mid(5));
1833 
1834  if (fileInfo.exists())
1835  {
1836  if (fileInfo.isReadable() && (fileInfo.isFile()))
1837  {
1838  ci = HTTPRequest::TestMimeType(fileInfo.absoluteFilePath());
1839  cs = tr("%1 MB").arg(fileInfo.size() / 1024 / 1024);
1840  }
1841  else
1842  ci = tr("File not readable");
1843  }
1844  else
1845  {
1846  ci = tr("File %1 does not exist").arg(device);
1847  }
1848 
1849  m_info->setValue(ci);
1850  m_size->setValue(cs);
1851 }
1852 
1853 // -----------------------
1854 // VBox Configuration
1855 // -----------------------
1856 
1858  (CaptureCard& a_parent, CardType& a_cardtype) :
1859  m_parent(a_parent)
1860 {
1861  setVisible(false);
1862 
1863  // Fill Device list
1864  FillDeviceList();
1865 
1866  m_deviceId = new VBoxDeviceID(m_parent);
1867  m_desc = new GroupSetting();
1868  m_desc->setLabel(tr("Description"));
1869  m_cardIp = new VBoxIP();
1870  m_cardTuner = new VBoxTunerIndex();
1871  m_deviceIdList = new VBoxDeviceIDList(
1872  m_deviceId, m_desc, m_cardIp, m_cardTuner, &m_deviceList, m_parent);
1873 
1874  a_cardtype.addTargetedChild("VBOX", m_deviceIdList);
1875  a_cardtype.addTargetedChild("VBOX", new EmptyAudioDevice(m_parent));
1876  a_cardtype.addTargetedChild("VBOX", new EmptyVBIDevice(m_parent));
1877  a_cardtype.addTargetedChild("VBOX", m_deviceId);
1878  a_cardtype.addTargetedChild("VBOX", m_desc);
1879  a_cardtype.addTargetedChild("VBOX", m_cardIp);
1880  a_cardtype.addTargetedChild("VBOX", m_cardTuner);
1881  a_cardtype.addTargetedChild("VBOX", new SignalTimeout(m_parent, 7000, 1000));
1882  a_cardtype.addTargetedChild("VBOX", new ChannelTimeout(m_parent, 10000, 1750));
1883 // TransButtonSetting *buttonRecOpt = new TransButtonSetting();
1884 // buttonRecOpt->setLabel(tr("Recording Options"));
1885 // addChild(buttonRecOpt);
1886 
1887 // connect(buttonRecOpt, SIGNAL(pressed()),
1888 // this, SLOT( VBoxExtraPanel()));
1889 
1890  connect(m_cardIp, SIGNAL(NewIP(const QString&)),
1891  m_deviceId, SLOT( SetIP(const QString&)));
1892  connect(m_cardTuner, SIGNAL(NewTuner(const QString&)),
1893  m_deviceId, SLOT( SetTuner(const QString&)));
1894 };
1895 
1897 {
1898  m_deviceList.clear();
1899 
1900  // Find physical devices first
1901  // ProbeVideoDevices returns "deviceid ip tunerno tunertype"
1902  QStringList devs = CardUtil::ProbeVideoDevices("VBOX");
1903 
1904  QStringList::const_iterator it;
1905 
1906  for (it = devs.begin(); it != devs.end(); ++it)
1907  {
1908  QString dev = *it;
1909  QStringList devinfo = dev.split(" ");
1910  const QString& id = devinfo.at(0);
1911  const QString& ip = devinfo.at(1);
1912  const QString& tunerNo = devinfo.at(2);
1913  const QString& tunerType = devinfo.at(3);
1914 
1915  VBoxDevice tmpdevice;
1916  tmpdevice.deviceid = id;
1917  tmpdevice.desc = CardUtil::GetVBoxdesc(id, ip, tunerNo, tunerType);
1918  tmpdevice.cardip = ip;
1919  tmpdevice.inuse = false;
1920  tmpdevice.discovered = true;
1921  tmpdevice.tunerno = tunerNo;
1922  tmpdevice.tunertype = tunerType;
1923  tmpdevice.mythdeviceid = id + "-" + tunerNo + "-" + tunerType;
1924  m_deviceList[tmpdevice.mythdeviceid] = tmpdevice;
1925  }
1926 
1927  // Now find configured devices
1928 
1929  // returns "ip.ip.ip.ip-n-type" or deviceid-n-type values
1930  QStringList db = CardUtil::GetVideoDevices("VBOX");
1931 
1932  for (it = db.begin(); it != db.end(); ++it)
1933  {
1934  QMap<QString, VBoxDevice>::iterator dit;
1935  dit = m_deviceList.find(*it);
1936 
1937  if (dit != m_deviceList.end())
1938  (*dit).inuse = true;
1939  }
1940 }
1941 
1942 // -----------------------
1943 // Ceton Configuration
1944 // -----------------------
1945 
1946 CetonSetting::CetonSetting(const char* label, const char* helptext)
1947 {
1948  setLabel(QObject::tr(label));
1949  setHelpText(tr(helptext));
1950  connect(this, SIGNAL(valueChanged( const QString&)),
1951  this, SLOT( UpdateDevices(const QString&)));
1952 }
1953 
1954 void CetonSetting::UpdateDevices(const QString &v)
1955 {
1956  if (isEnabled())
1957  emit NewValue(v);
1958 }
1959 
1960 void CetonSetting::LoadValue(const QString &value)
1961 {
1962  setValue(value);
1963 }
1964 
1966  MythUITextEditSetting(new CaptureCardDBStorage(this, parent, "videodevice")),
1967  m_parent(parent)
1968 {
1969  setLabel(tr("Device ID"));
1970  setHelpText(tr("Device ID of Ceton device"));
1971 }
1972 
1973 void CetonDeviceID::SetIP(const QString &ip)
1974 {
1975  QString regexp = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){4}$";
1976  if (QRegExp(regexp).exactMatch(ip + "."))
1977  {
1978  m_ip = ip;
1979  setValue(QString("%1-RTP.%3").arg(m_ip).arg(m_tuner));
1980  }
1981 }
1982 
1983 void CetonDeviceID::SetTuner(const QString &tuner)
1984 {
1985  if (QRegExp("^\\d$").exactMatch(tuner))
1986  {
1987  m_tuner = tuner;
1988  setValue(QString("%1-RTP.%2").arg(m_ip).arg(m_tuner));
1989  }
1990 }
1991 
1993 {
1994  GetStorage()->Load();
1995  UpdateValues();
1996 }
1997 
1999 {
2000  QRegExp newstyle("^([0-9.]+)-(\\d|RTP)\\.(\\d)$");
2001  if (newstyle.exactMatch(getValue()))
2002  {
2003  emit LoadedIP(newstyle.cap(1));
2004  emit LoadedTuner(newstyle.cap(3));
2005  }
2006 }
2007 
2008 #ifdef USING_CETON
2009 static void CetonConfigurationGroup(CaptureCard& parent, CardType& cardtype)
2010 {
2011  CetonDeviceID *deviceid = new CetonDeviceID(parent);
2012  GroupSetting *desc = new GroupSetting();
2013  desc->setLabel(QCoreApplication::translate("CetonConfigurationGroup",
2014  "Description"));
2015  CetonSetting *ip = new CetonSetting(
2016  "IP Address",
2017  "IP Address of the Ceton device (192.168.200.1 by default)");
2018  CetonSetting *tuner = new CetonSetting(
2019  "Tuner",
2020  "Number of the tuner on the Ceton device (first tuner is number 0)");
2021 
2022  cardtype.addTargetedChild("CETON", ip);
2023  cardtype.addTargetedChild("CETON", tuner);
2024  cardtype.addTargetedChild("CETON", deviceid);
2025  cardtype.addTargetedChild("CETON", desc);
2026  cardtype.addTargetedChild("CETON", new SignalTimeout(parent, 1000, 250));
2027  cardtype.addTargetedChild("CETON", new ChannelTimeout(parent, 3000, 1750));
2028 
2029  QObject::connect(ip, SIGNAL(NewValue(const QString&)),
2030  deviceid, SLOT( SetIP(const QString&)));
2031  QObject::connect(tuner, SIGNAL(NewValue(const QString&)),
2032  deviceid, SLOT( SetTuner(const QString&)));
2033 
2034  QObject::connect(deviceid, SIGNAL(LoadedIP(const QString&)),
2035  ip, SLOT( LoadValue(const QString&)));
2036  QObject::connect(deviceid, SIGNAL(LoadedTuner(const QString&)),
2037  tuner, SLOT( LoadValue(const QString&)));
2038 }
2039 #endif
2040 
2042  CardType& a_cardtype) :
2043  m_parent(a_parent),
2044  m_cardInfo(new TransTextEditSetting()), m_vbiDev(new VBIDevice(m_parent))
2045 {
2046  setVisible(false);
2047  QString drv = "(?!ivtv|hdpvr|(saa7164(.*))).*";
2048  VideoDevice *device = new VideoDevice(m_parent, 0, 15, QString(), drv);
2049 
2050  m_cardInfo->setLabel(tr("Probed info"));
2051  m_cardInfo->setEnabled(false);
2052 
2053  a_cardtype.addTargetedChild("V4L", device);
2054  a_cardtype.addTargetedChild("V4L", m_cardInfo);
2055  a_cardtype.addTargetedChild("V4L", m_vbiDev);
2056  a_cardtype.addTargetedChild("V4L", new AudioDevice(m_parent));
2057  a_cardtype.addTargetedChild("V4L", new AudioRateLimit(m_parent));
2058  a_cardtype.addTargetedChild("V4L", new SkipBtAudio(m_parent));
2059 
2060  connect(device, SIGNAL(valueChanged(const QString&)),
2061  this, SLOT( probeCard( const QString&)));
2062 
2063  probeCard(device->getValue());
2064 };
2065 
2066 void V4LConfigurationGroup::probeCard(const QString &device)
2067 {
2068  QString cn = tr("Failed to open"), ci = cn, dn;
2069 
2070  QByteArray adevice = device.toLatin1();
2071  int videofd = open(adevice.constData(), O_RDWR);
2072  if (videofd >= 0)
2073  {
2074  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2075  ci = cn = tr("Failed to probe");
2076  else if (!dn.isEmpty())
2077  ci = cn + " [" + dn + "]";
2078  close(videofd);
2079  }
2080 
2081  m_cardInfo->setValue(ci);
2082  m_vbiDev->setFilter(cn, dn);
2083 }
2084 
2086  CardType &a_cardtype) :
2087  m_parent(a_parent),
2088  m_cardInfo(new TransTextEditSetting())
2089 {
2090  setVisible(false);
2091  QString drv = "ivtv|(saa7164(.*))";
2092  m_device = new VideoDevice(m_parent, 0, 15, QString(), drv);
2094  m_vbiDevice->setVisible(false);
2095 
2096  m_cardInfo->setLabel(tr("Probed info"));
2097  m_cardInfo->setEnabled(false);
2098 
2099  a_cardtype.addTargetedChild("MPEG", m_device);
2100  a_cardtype.addTargetedChild("MPEG", m_vbiDevice);
2101  a_cardtype.addTargetedChild("MPEG", m_cardInfo);
2102  a_cardtype.addTargetedChild("MPEG", new ChannelTimeout(m_parent, 12000, 2000));
2103 
2104  connect(m_device, SIGNAL(valueChanged(const QString&)),
2105  this, SLOT( probeCard( const QString&)));
2106 
2108 }
2109 
2110 void MPEGConfigurationGroup::probeCard(const QString &device)
2111 {
2112  QString cn = tr("Failed to open"), ci = cn, dn;
2113 
2114  QByteArray adevice = device.toLatin1();
2115  int videofd = open(adevice.constData(), O_RDWR);
2116  if (videofd >= 0)
2117  {
2118  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2119  ci = cn = tr("Failed to probe");
2120  else if (!dn.isEmpty())
2121  ci = cn + " [" + dn + "]";
2122  close(videofd);
2123  }
2124 
2125  m_cardInfo->setValue(ci);
2126  m_vbiDevice->setVisible(dn!="ivtv");
2127  m_vbiDevice->setFilter(cn, dn);
2128 }
2129 
2131  CardType &a_cardtype) :
2132  m_parent(a_parent),
2133  m_info(new TransTextEditSetting()), m_size(new TransTextEditSetting())
2134 {
2135  setVisible(false);
2136  FileDevice *device = new FileDevice(m_parent);
2137  device->setHelpText(tr("A local MPEG file used to simulate a recording."));
2138 
2139  a_cardtype.addTargetedChild("DEMO", device);
2140 
2141  a_cardtype.addTargetedChild("DEMO", new EmptyAudioDevice(m_parent));
2142  a_cardtype.addTargetedChild("DEMO", new EmptyVBIDevice(m_parent));
2143 
2144  m_info->setLabel(tr("File info"));
2145  m_info->setEnabled(false);
2146  a_cardtype.addTargetedChild("DEMO", m_info);
2147 
2148  m_size->setLabel(tr("File size"));
2149  m_size->setEnabled(false);
2150  a_cardtype.addTargetedChild("DEMO", m_size);
2151 
2152  connect(device, SIGNAL(valueChanged(const QString&)),
2153  this, SLOT( probeCard( const QString&)));
2154 
2155  probeCard(device->getValue());
2156 }
2157 
2158 void DemoConfigurationGroup::probeCard(const QString &device)
2159 {
2160  QString ci, cs;
2161  QFileInfo fileInfo(device.mid(5));
2162  if (fileInfo.exists())
2163  {
2164  if (fileInfo.isReadable() && (fileInfo.isFile()))
2165  {
2166  ci = HTTPRequest::TestMimeType(fileInfo.absoluteFilePath());
2167  cs = tr("%1 MB").arg(fileInfo.size() / 1024 / 1024);
2168  }
2169  else
2170  ci = tr("File not readable");
2171  }
2172  else
2173  {
2174  ci = tr("File does not exist");
2175  }
2176 
2177  m_info->setValue(ci);
2178  m_size->setValue(cs);
2179 }
2180 
2181 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2182 ExternalConfigurationGroup::ExternalConfigurationGroup(CaptureCard &a_parent,
2183  CardType &a_cardtype) :
2184  m_parent(a_parent),
2185  m_info(new TransTextEditSetting())
2186 {
2187  setVisible(false);
2188  CommandPath *device = new CommandPath(m_parent);
2189  device->setLabel(tr("Command path"));
2190  device->setHelpText(tr("A 'black box' application controlled via "
2191  "stdin, status on stderr and TransportStream "
2192  "read from stdout"));
2193  a_cardtype.addTargetedChild("EXTERNAL", device);
2194 
2195  m_info->setLabel(tr("File info"));
2196  m_info->setEnabled(false);
2197  a_cardtype.addTargetedChild("EXTERNAL", m_info);
2198 
2199  a_cardtype.addTargetedChild("EXTERNAL",
2200  new ChannelTimeout(m_parent, 20000, 1750));
2201 
2202  connect(device, SIGNAL(valueChanged(const QString&)),
2203  this, SLOT( probeApp( const QString&)));
2204 
2205  probeApp(device->getValue());
2206 }
2207 
2208 void ExternalConfigurationGroup::probeApp(const QString & path)
2209 {
2210  int idx1 = path.toLower().startsWith("file:") ? 5 : 0;
2211  int idx2 = path.indexOf(' ', idx1);
2212 
2213  QString ci, cs;
2214  QFileInfo fileInfo(path.mid(idx1, idx2 - idx1));
2215 
2216  if (fileInfo.exists())
2217  {
2218  ci = tr("'%1' is valid.").arg(fileInfo.absoluteFilePath());
2219  if (!fileInfo.isReadable() || !fileInfo.isFile())
2220  ci = tr("WARNING: '%1' is not readable.")
2221  .arg(fileInfo.absoluteFilePath());
2222  if (!fileInfo.isExecutable())
2223  ci = tr("WARNING: '%1' is not executable.")
2224  .arg(fileInfo.absoluteFilePath());
2225  }
2226  else
2227  {
2228  ci = tr("WARNING: '%1' does not exist.")
2229  .arg(fileInfo.absoluteFilePath());
2230  }
2231 
2232  m_info->setValue(ci);
2233 }
2234 #endif // !defined( USING_MINGW ) && !defined( _MSC_VER )
2235 
2237  CardType &a_cardtype) :
2238  m_parent(a_parent), m_cardInfo(new GroupSetting()),
2239  m_audioInput(new TunerCardAudioInput(m_parent, QString(), "HDPVR"))
2240 {
2241  setVisible(false);
2242 
2243  VideoDevice *device =
2244  new VideoDevice(m_parent, 0, 15, QString(), "hdpvr");
2245 
2246  m_cardInfo->setLabel(tr("Probed info"));
2247  m_cardInfo->setEnabled(false);
2248 
2249  a_cardtype.addTargetedChild("HDPVR", device);
2250  a_cardtype.addTargetedChild("HDPVR", new EmptyAudioDevice(m_parent));
2251  a_cardtype.addTargetedChild("HDPVR", new EmptyVBIDevice(m_parent));
2252  a_cardtype.addTargetedChild("HDPVR", m_cardInfo);
2253  a_cardtype.addTargetedChild("HDPVR", m_audioInput);
2254  a_cardtype.addTargetedChild("HDPVR", new ChannelTimeout(m_parent, 15000, 2000));
2255 
2256  connect(device, SIGNAL(valueChanged(const QString&)),
2257  this, SLOT( probeCard( const QString&)));
2258 
2259  probeCard(device->getValue());
2260 }
2261 
2262 void HDPVRConfigurationGroup::probeCard(const QString &device)
2263 {
2264  QString cn = tr("Failed to open"), ci = cn, dn;
2265 
2266  int videofd = open(device.toLocal8Bit().constData(), O_RDWR);
2267  if (videofd >= 0)
2268  {
2269  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2270  ci = cn = tr("Failed to probe");
2271  else if (!dn.isEmpty())
2272  ci = cn + " [" + dn + "]";
2273  close(videofd);
2274  }
2275 
2276  m_cardInfo->setValue(ci);
2277  m_audioInput->fillSelections(device);
2278 }
2279 
2281  m_parent(parent),
2282  m_cardInfo(new TransTextEditSetting())
2283 {
2284  setLabel(QObject::tr("V4L2 encoder devices (multirec capable)"));
2285  m_device = new VideoDevice(m_parent, 0, 15);
2286 
2287  cardtype.addTargetedChild("V4L2ENC", m_device);
2288  m_cardInfo->setLabel(tr("Probed info"));
2289  cardtype.addTargetedChild("V4L2ENC", m_cardInfo);
2290 
2291  setVisible(false);
2292 
2293  connect(m_device, SIGNAL(valueChanged(const QString&)),
2294  this, SLOT( probeCard( const QString&)));
2295 
2296  const QString &device_name = m_device->getValue();
2297  if (!device_name.isEmpty())
2298  probeCard(device_name);
2299 }
2300 
2301 void V4L2encGroup::probeCard(const QString &device_name)
2302 {
2303 #ifdef USING_V4L2
2304  QString card_name = tr("Failed to open");
2305  QString card_info = card_name;
2306  V4L2util v4l2(device_name);
2307 
2308  if (!v4l2.IsOpen())
2309  {
2310  m_DriverName = tr("Failed to probe");
2311  return;
2312  }
2313  m_DriverName = v4l2.DriverName();
2314  card_name = v4l2.CardName();
2315 
2316  if (!m_DriverName.isEmpty())
2317  card_info = card_name + " [" + m_DriverName + "]";
2318 
2319  m_cardInfo->setValue(card_info);
2320 
2321  if (m_device->getSubSettings()->empty())
2322  {
2323  TunerCardAudioInput* audioinput =
2324  new TunerCardAudioInput(m_parent, QString(), "V4L2");
2325  if (audioinput->fillSelections(device_name) > 1)
2326  {
2327  audioinput->setName("AudioInput");
2328  m_device->addTargetedChild(m_DriverName, audioinput);
2329  }
2330  else
2331  delete audioinput;
2332 
2333  if (v4l2.HasSlicedVBI())
2334  {
2335  VBIDevice* vbidev = new VBIDevice(m_parent);
2336  if (vbidev->setFilter(card_name, m_DriverName) > 0)
2337  {
2338  vbidev->setName("VBIDevice");
2340  }
2341  else
2342  delete vbidev;
2343  }
2344 
2347  new ChannelTimeout(m_parent, 15000, 2000));
2348  }
2349 #else
2350  Q_UNUSED(device_name);
2351 #endif // USING_V4L2
2352 }
2353 
2355 {
2356  setLabel(QObject::tr("Capture Card Setup"));
2357 
2358  CardType* cardtype = new CardType(parent);
2359  parent.addChild(cardtype);
2360 
2361 #ifdef USING_DVB
2362  cardtype->addTargetedChild("DVB",
2363  new DVBConfigurationGroup(parent, *cardtype));
2364 #endif // USING_DVB
2365 
2366 #ifdef USING_V4L2
2367 # ifdef USING_HDPVR
2368  cardtype->addTargetedChild("HDPVR",
2369  new HDPVRConfigurationGroup(parent, *cardtype));
2370 # endif // USING_HDPVR
2371 #endif // USING_V4L2
2372 
2373 #ifdef USING_HDHOMERUN
2374  cardtype->addTargetedChild("HDHOMERUN",
2375  new HDHomeRunConfigurationGroup(parent, *cardtype));
2376 #endif // USING_HDHOMERUN
2377 
2378 #ifdef USING_VBOX
2379  cardtype->addTargetedChild("VBOX",
2380  new VBoxConfigurationGroup(parent, *cardtype));
2381 #endif // USING_VBOX
2382 
2383 #ifdef USING_FIREWIRE
2384  FirewireConfigurationGroup(parent, *cardtype);
2385 #endif // USING_FIREWIRE
2386 
2387 #ifdef USING_CETON
2388  CetonConfigurationGroup(parent, *cardtype);
2389 #endif // USING_CETON
2390 
2391 #ifdef USING_IPTV
2392  IPTVConfigurationGroup(parent, *cardtype);
2393 #endif // USING_IPTV
2394 
2395 #ifdef USING_V4L2
2396  cardtype->addTargetedChild("V4L2ENC", new V4L2encGroup(parent, *cardtype));
2397  cardtype->addTargetedChild("V4L",
2398  new V4LConfigurationGroup(parent, *cardtype));
2399  cardtype->addTargetedChild("MJPEG",
2400  new V4LConfigurationGroup(parent, *cardtype));
2401  cardtype->addTargetedChild("GO7007",
2402  new V4LConfigurationGroup(parent, *cardtype));
2403 # ifdef USING_IVTV
2404  cardtype->addTargetedChild("MPEG",
2405  new MPEGConfigurationGroup(parent, *cardtype));
2406 # endif // USING_IVTV
2407 #endif // USING_V4L2
2408 
2409 #ifdef USING_ASI
2410  cardtype->addTargetedChild("ASI",
2411  new ASIConfigurationGroup(parent, *cardtype));
2412 #endif // USING_ASI
2413 
2414  // for testing without any actual tuner hardware:
2415  cardtype->addTargetedChild("IMPORT",
2416  new ImportConfigurationGroup(parent, *cardtype));
2417  cardtype->addTargetedChild("DEMO",
2418  new DemoConfigurationGroup(parent, *cardtype));
2419 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2420  cardtype->addTargetedChild("EXTERNAL",
2421  new ExternalConfigurationGroup(parent,
2422  *cardtype));
2423 #endif
2424 }
2425 
2426 CaptureCard::CaptureCard(bool use_card_group)
2427  : m_id(new ID)
2428 {
2429  addChild(m_id);
2430  if (use_card_group)
2431  CaptureCardGroup(*this);
2432  addChild(new Hostname(*this));
2433 }
2434 
2435 QString CaptureCard::GetRawCardType(void) const
2436 {
2437  int cardid = getCardID();
2438  if (cardid <= 0)
2439  return QString();
2440  return CardUtil::GetRawInputType(cardid);
2441 }
2442 
2444 {
2445  MSqlQuery query(MSqlQuery::InitCon());
2446  QString qstr =
2447  "SELECT cardid, videodevice, cardtype "
2448  "FROM capturecard "
2449  "WHERE hostname = :HOSTNAME AND parentid = 0 "
2450  "ORDER BY cardid";
2451 
2452  query.prepare(qstr);
2453  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
2454 
2455  if (!query.exec())
2456  {
2457  MythDB::DBError("CaptureCard::fillSelections", query);
2458  return;
2459  }
2460 
2462 
2463  while (query.next())
2464  {
2465  uint cardid = query.value(0).toUInt();
2466  QString videodevice = query.value(1).toString();
2467  QString cardtype = query.value(2).toString();
2468 
2469  QString label = CardUtil::GetDeviceLabel(cardtype, videodevice);
2470  CaptureCard *card = new CaptureCard();
2471  card->loadByID(cardid);
2472  card->setLabel(label);
2473  setting->addChild(card);
2474  }
2475 }
2476 
2477 void CaptureCard::loadByID(int cardid)
2478 {
2479  m_id->setValue(cardid);
2480  Load();
2481 }
2482 
2484 {
2485  return true;
2486 }
2487 
2489 {
2491 }
2492 
2493 
2495 {
2496  uint init_cardid = getCardID();
2497  QString init_dev = CardUtil::GetVideoDevice(init_cardid);
2498 
2500 
2502 
2504 
2505  uint cardid = getCardID();
2506  QString type = CardUtil::GetRawInputType(cardid);
2507  QString dev = CardUtil::GetVideoDevice(cardid);
2508 
2509  if (dev != init_dev)
2510  {
2511  if (!init_dev.isEmpty())
2512  {
2513  uint init_groupid = CardUtil::GetDeviceInputGroup(init_cardid);
2514  CardUtil::UnlinkInputGroup(init_cardid, init_groupid);
2515  }
2516  if (!dev.isEmpty())
2517  {
2518  uint groupid =
2520  gCoreContext->GetHostName(), dev);
2521  CardUtil::LinkInputGroup(cardid, groupid);
2522  CardUtil::UnlinkInputGroup(0, groupid);
2523  }
2524  }
2525 
2526  // Handle any cloning we may need to do
2528  {
2529  vector<uint> clones = CardUtil::GetChildInputIDs(cardid);
2530  for (size_t i = 0; i < clones.size(); i++)
2531  CardUtil::CloneCard(cardid, clones[i]);
2532  }
2533 }
2534 
2536 {
2537  if (getCardID() == 0)
2538  {
2539  Save();
2540  Load();
2541  }
2542 }
2543 
2545  CaptureCardComboBoxSetting(parent, false, "cardtype")
2546 {
2547  setLabel(QObject::tr("Card type"));
2548  setHelpText(QObject::tr("Change the cardtype to the appropriate type for "
2549  "the capture card you are configuring."));
2550  fillSelections(this);
2551 }
2552 
2554 {
2555 #ifdef USING_DVB
2556  setting->addSelection(
2557  QObject::tr("DVB-T/S/C, ATSC or ISDB-T tuner card"), "DVB");
2558 #endif // USING_DVB
2559 
2560 #ifdef USING_V4L2
2561  setting->addSelection(
2562  QObject::tr("V4L2 encoder"), "V4L2ENC");
2563 #ifdef USING_HDPVR
2564  setting->addSelection(
2565  QObject::tr("HD-PVR H.264 encoder"), "HDPVR");
2566 # endif // USING_HDPVR
2567 #endif // USING_V4L2
2568 
2569 #ifdef USING_HDHOMERUN
2570  setting->addSelection(
2571  QObject::tr("HDHomeRun networked tuner"), "HDHOMERUN");
2572 #endif // USING_HDHOMERUN
2573 
2574 #ifdef USING_VBOX
2575  setting->addSelection(
2576  QObject::tr("V@Box TV Gateway networked tuner"), "VBOX");
2577 #endif // USING_VBOX
2578 
2579 #ifdef USING_FIREWIRE
2580  setting->addSelection(
2581  QObject::tr("FireWire cable box"), "FIREWIRE");
2582 #endif // USING_FIREWIRE
2583 
2584 #ifdef USING_CETON
2585  setting->addSelection(
2586  QObject::tr("Ceton Cablecard tuner"), "CETON");
2587 #endif // USING_CETON
2588 
2589 #ifdef USING_IPTV
2590  setting->addSelection(QObject::tr("IPTV recorder"), "FREEBOX");
2591 #endif // USING_IPTV
2592 
2593 #ifdef USING_V4L2
2594 # ifdef USING_IVTV
2595  setting->addSelection(
2596  QObject::tr("Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"), "MPEG");
2597 # endif // USING_IVTV
2598  setting->addSelection(
2599  QObject::tr("Analog to MJPEG encoder card (Matrox G200, DC10, etc)"), "MJPEG");
2600  setting->addSelection(
2601  QObject::tr("Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
2602  "GO7007");
2603  setting->addSelection(
2604  QObject::tr("Analog capture card"), "V4L");
2605 #endif // USING_V4L2
2606 
2607 #ifdef USING_ASI
2608  setting->addSelection(QObject::tr("DVEO ASI recorder"), "ASI");
2609 #endif
2610 
2611  setting->addSelection(QObject::tr("Import test recorder"), "IMPORT");
2612  setting->addSelection(QObject::tr("Demo test recorder"), "DEMO");
2613 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2614  setting->addSelection(QObject::tr("External (black box) recorder"),
2615  "EXTERNAL");
2616 #endif
2617 }
2618 
2620 {
2621  public:
2622  explicit InputName(const CardInput &parent) :
2623  MythUIComboBoxSetting(new CardInputDBStorage(this, parent, "inputname"))
2624  {
2625  setLabel(QObject::tr("Input name"));
2626  };
2627 
2628  void Load(void) override // StandardSetting
2629  {
2630  fillSelections();
2632  };
2633 
2635  clearSelections();
2636  addSelection(QObject::tr("(None)"), "None");
2637  uint cardid = static_cast<CardInputDBStorage*>(GetStorage())->getInputID();
2638  QString type = CardUtil::GetRawInputType(cardid);
2639  QString device = CardUtil::GetVideoDevice(cardid);
2640  QStringList inputs;
2641  CardUtil::GetDeviceInputNames(device, type, inputs);
2642  while (!inputs.isEmpty())
2643  {
2644  addSelection(inputs.front());
2645  inputs.pop_front();
2646  }
2647  };
2648 };
2649 
2651 {
2652  public:
2654  {
2655  setLabel(QObject::tr("Delivery system"));
2656  setHelpText(QObject::tr(
2657  "This shows the delivery system (modulation), for instance DVB-T2, "
2658  "that you have selected when you configured the capture card. "
2659  "This must be the same as the modulation used by the video source. "));
2660  };
2661 };
2662 
2664 {
2665  public:
2666  explicit InputDisplayName(const CardInput &parent) :
2667  MythUITextEditSetting(new CardInputDBStorage(this, parent, "displayname"))
2668  {
2669  setLabel(QObject::tr("Display name (optional)"));
2670  setHelpText(QObject::tr(
2671  "This name is displayed on screen when Live TV begins "
2672  "and when changing the selected input or card. If you "
2673  "use this, make sure the information is unique for "
2674  "each input."));
2675  };
2676 };
2677 
2679 {
2680  public:
2681  CardInputComboBoxSetting(const CardInput &parent, const QString &setting) :
2682  MythUIComboBoxSetting(new CardInputDBStorage(this, parent, setting))
2683  {
2684  }
2685 };
2686 
2688 {
2689  public:
2690  explicit SourceID(const CardInput &parent) :
2691  CardInputComboBoxSetting(parent, "sourceid")
2692  {
2693  setLabel(QObject::tr("Video source"));
2694  addSelection(QObject::tr("(None)"), "0");
2695  };
2696 
2697  void Load(void) override // StandardSetting
2698  {
2699  fillSelections();
2701  };
2702 
2704  clearSelections();
2705  addSelection(QObject::tr("(None)"), "0");
2707  };
2708 };
2709 
2711 {
2712  public:
2713  InputGroup(const CardInput &parent, uint group_num) :
2714  m_cardInput(parent),
2715  m_groupNum(group_num)
2716  {
2717  setLabel(QObject::tr("Input group") +
2718  QString(" %1").arg(m_groupNum + 1));
2719  setHelpText(QObject::tr(
2720  "Leave as 'Generic' unless this input is shared with "
2721  "another device. Only one of the inputs in an input "
2722  "group will be allowed to record at any given time."));
2723  }
2724 
2725  void Load(void) override; // StandardSetting
2726 
2727  void Save(void) override // StandardSetting
2728  {
2729  uint inputid = m_cardInput.getInputID();
2730  uint new_groupid = getValue().toUInt();
2731 
2732  if (m_groupId)
2734 
2735  if (new_groupid)
2736  {
2737  if (CardUtil::UnlinkInputGroup(inputid, new_groupid))
2738  CardUtil::LinkInputGroup(inputid, new_groupid);
2739  }
2740  }
2741 
2742  virtual void Save(QString /*destination*/) { Save(); }
2743 
2744  private:
2748 };
2749 
2751 {
2752 #if 0
2753  LOG(VB_GENERAL, LOG_DEBUG, QString("InputGroup::Load() %1 %2")
2754  .arg(m_groupNum).arg(m_cardInput.getInputID()));
2755 #endif
2756 
2757  uint inputid = m_cardInput.getInputID();
2758  QMap<uint, uint> grpcnt;
2759  vector<QString> names;
2760  vector<uint> grpid;
2761  vector<uint> selected_groupids;
2762 
2763  names.push_back(QObject::tr("Generic"));
2764  grpid.push_back(0);
2765  grpcnt[0]++;
2766 
2767  MSqlQuery query(MSqlQuery::InitCon());
2768  query.prepare(
2769  "SELECT cardinputid, inputgroupid, inputgroupname "
2770  "FROM inputgroup "
2771  "WHERE inputgroupname LIKE 'user:%' "
2772  "ORDER BY inputgroupid, cardinputid, inputgroupname");
2773 
2774  if (!query.exec())
2775  {
2776  MythDB::DBError("InputGroup::Load()", query);
2777  }
2778  else
2779  {
2780  while (query.next())
2781  {
2782  uint groupid = query.value(1).toUInt();
2783  if (inputid && (query.value(0).toUInt() == inputid))
2784  selected_groupids.push_back(groupid);
2785 
2786  grpcnt[groupid]++;
2787 
2788  if (grpcnt[groupid] == 1)
2789  {
2790  names.push_back(query.value(2).toString().mid(5, -1));
2791  grpid.push_back(groupid);
2792  }
2793  }
2794  }
2795 
2796  // makes sure we select something
2797  m_groupId = 0;
2798  if (m_groupNum < selected_groupids.size())
2799  m_groupId = selected_groupids[m_groupNum];
2800 
2801 #if 0
2802  LOG(VB_GENERAL, LOG_DEBUG, QString("Group num: %1 id: %2")
2803  .arg(m_groupNum).arg(m_groupId));
2804  {
2805  QString msg;
2806  for (uint i = 0; i < selected_groupids.size(); i++)
2807  msg += QString("%1 ").arg(selected_groupids[i]);
2808  LOG(VB_GENERAL, LOG_DEBUG, msg);
2809  }
2810 #endif
2811 
2812  // add selections to combobox
2813  clearSelections();
2814  uint index = 0;
2815  for (size_t i = 0; i < names.size(); i++)
2816  {
2817  bool sel = (m_groupId == grpid[i]);
2818  index = (sel) ? i : index;
2819 
2820 #if 0
2821  LOG(VB_GENERAL, LOG_DEBUG, QString("grpid %1, name '%2', i %3, s %4")
2822  .arg(grpid[i]).arg(names[i]) .arg(index).arg(sel ? "T" : "F"));
2823 #endif
2824 
2825  addSelection(names[i], QString::number(grpid[i]), sel);
2826  }
2827 
2828 #if 0
2829  LOG(VB_GENERAL, LOG_DEBUG, QString("Group index: %1").arg(index));
2830 #endif
2831 
2832  if (!names.empty())
2833  setValue(index);
2834 
2836 }
2837 
2839 {
2840  public:
2841  explicit QuickTune(const CardInput &parent) :
2842  CardInputComboBoxSetting(parent, "quicktune")
2843  {
2844  setLabel(QObject::tr("Use quick tuning"));
2845  addSelection(QObject::tr("Never"), "0", true);
2846  addSelection(QObject::tr("Live TV only"), "1", false);
2847  addSelection(QObject::tr("Always"), "2", false);
2848  setHelpText(QObject::tr(
2849  "If enabled, MythTV will tune using only the "
2850  "MPEG program number. The program numbers "
2851  "change more often than DVB or ATSC tuning "
2852  "parameters, so this is slightly less reliable. "
2853  "This will also inhibit EIT gathering during "
2854  "Live TV and recording."));
2855  };
2856 };
2857 
2859 {
2860  public:
2861  explicit ExternalChannelCommand(const CardInput &parent) :
2862  MythUITextEditSetting(new CardInputDBStorage(this, parent, "externalcommand"))
2863  {
2864  setLabel(QObject::tr("External channel change command"));
2865  setValue("");
2866  setHelpText(QObject::tr("If specified, this command will be run to "
2867  "change the channel for inputs which have an external "
2868  "tuner device such as a cable box. The first argument "
2869  "will be the channel number."));
2870  };
2871 };
2872 
2874 {
2875  public:
2876  explicit PresetTuner(const CardInput &parent) :
2877  MythUITextEditSetting(new CardInputDBStorage(this, parent, "tunechan"))
2878  {
2879  setLabel(QObject::tr("Preset tuner to channel"));
2880  setValue("");
2881  setHelpText(QObject::tr("Leave this blank unless you have an external "
2882  "tuner that is connected to the tuner input of your card. "
2883  "If so, you will need to specify the preset channel for "
2884  "the signal (normally 3 or 4)."));
2885  };
2886 };
2887 
2888 void StartingChannel::SetSourceID(const QString &sourceid)
2889 {
2890  clearSelections();
2891  if (sourceid.isEmpty() || !sourceid.toUInt())
2892  return;
2893 
2894  // Get the existing starting channel
2895  int inputId = static_cast<CardInputDBStorage*>(GetStorage())->getInputID();
2896  QString startChan = CardUtil::GetStartingChannel(inputId);
2897 
2898  ChannelInfoList channels = ChannelUtil::GetAllChannels(sourceid.toUInt());
2899 
2900  if (channels.empty())
2901  {
2902  addSelection(tr("Please add channels to this source"),
2903  startChan.isEmpty() ? "0" : startChan);
2904  return;
2905  }
2906 
2907  // If there are channels sort them, then add theme
2908  // (selecting the old start channel if it is there).
2909  QString order = gCoreContext->GetSetting("ChannelOrdering", "channum");
2910  ChannelUtil::SortChannels(channels, order);
2911  bool has_visible = false;
2912  for (size_t i = 0; i < channels.size() && !has_visible; i++)
2913  has_visible |= channels[i].m_visible;
2914 
2915  for (size_t i = 0; i < channels.size(); i++)
2916  {
2917  const QString channum = channels[i].m_channum;
2918  bool sel = channum == startChan;
2919  if (!has_visible || channels[i].m_visible || sel)
2920  {
2921  addSelection(channum, channum, sel);
2922  }
2923  }
2924 }
2925 
2927 {
2928  public:
2929  explicit InputPriority(const CardInput &parent) :
2930  MythUISpinBoxSetting(new CardInputDBStorage(this, parent, "recpriority"),
2931  -99, 99, 1)
2932  {
2933  setLabel(QObject::tr("Input priority"));
2934  setValue(0);
2935  setHelpText(QObject::tr("If the input priority is not equal for "
2936  "all inputs, the scheduler may choose to record a show "
2937  "at a later time so that it can record on an input with "
2938  "a higher value."));
2939  };
2940 };
2941 
2943 {
2944  public:
2945  ScheduleOrder(const CardInput &parent, int _value) :
2946  MythUISpinBoxSetting(new CardInputDBStorage(this, parent, "schedorder"),
2947  0, 99, 1)
2948  {
2949  setLabel(QObject::tr("Schedule order"));
2950  setValue(_value);
2951  setHelpText(QObject::tr("If priorities and other factors are equal "
2952  "the scheduler will choose the available "
2953  "input with the lowest, non-zero value. "
2954  "Setting this value to zero will make the "
2955  "input unavailable to the scheduler."));
2956  };
2957 };
2958 
2960 {
2961  public:
2962  LiveTVOrder(const CardInput &parent, int _value) :
2963  MythUISpinBoxSetting(new CardInputDBStorage(this, parent, "livetvorder"),
2964  0, 99, 1)
2965  {
2966  setLabel(QObject::tr("Live TV order"));
2967  setValue(_value);
2968  setHelpText(QObject::tr("When entering Live TV, the available, local "
2969  "input with the lowest, non-zero value will "
2970  "be used. If no local inputs are available, "
2971  "the available, remote input with the lowest, "
2972  "non-zero value will be used. "
2973  "Setting this value to zero will make the "
2974  "input unavailable to live TV."));
2975  };
2976 };
2977 
2979 {
2980  public:
2981  explicit DishNetEIT(const CardInput &parent) :
2982  MythUICheckBoxSetting(new CardInputDBStorage(this, parent,
2983  "dishnet_eit"))
2984  {
2985  setLabel(QObject::tr("Use DishNet long-term EIT data"));
2986  setValue(false);
2987  setHelpText(
2988  QObject::tr(
2989  "If you point your satellite dish toward DishNet's birds, "
2990  "you may wish to enable this feature. For best results, "
2991  "enable general EIT collection as well."));
2992  };
2993 };
2994 
2995 CardInput::CardInput(const QString & cardtype, const QString & device,
2996  int _cardid) :
2997  m_id(new ID()),
2998  m_inputName(new InputName(*this)),
2999  m_sourceId(new SourceID(*this)),
3000  m_startChan(new StartingChannel(*this)),
3001  m_scan(new ButtonStandardSetting(tr("Scan for channels"))),
3002  m_srcFetch(new ButtonStandardSetting(tr("Fetch channels from listings source"))),
3003  m_externalInputSettings(new DiSEqCDevSettings()),
3004  m_inputGrp0(new InputGroup(*this, 0)),
3005  m_inputGrp1(new InputGroup(*this, 1))
3006 {
3007  addChild(m_id);
3008 
3010  {
3012  _cardid, true));
3013  }
3014 
3015  // Delivery system for DVB, input name for other,
3016  // same field capturecard/inputname for both
3017  if ("DVB" == cardtype)
3018  {
3019  DeliverySystem *ds = new DeliverySystem();
3021  addChild(ds);
3022  }
3023  else
3024  {
3026  }
3027  addChild(new InputDisplayName(*this));
3029 
3030  if (CardUtil::IsEncoder(cardtype) || CardUtil::IsUnscanable(cardtype))
3031  {
3032  addChild(new ExternalChannelCommand(*this));
3033  if (CardUtil::HasTuner(cardtype, device))
3034  addChild(new PresetTuner(*this));
3035  }
3036  else
3037  {
3038  addChild(new QuickTune(*this));
3039  if ("DVB" == cardtype)
3040  addChild(new DishNetEIT(*this));
3041  }
3042 
3044  tr("Use channel scanner to find channels for this input."));
3045 
3047  tr("This uses the listings data source to "
3048  "provide the channels for this input.") + " " +
3049  tr("This can take a long time to run."));
3050 
3051  addChild(m_scan);
3053 
3055 
3056  GroupSetting *interact = new GroupSetting();
3057 
3058  interact->setLabel(QObject::tr("Interactions between inputs"));
3059  if (CardUtil::IsTunerSharingCapable(cardtype))
3060  {
3062  interact->addChild(m_instanceCount);
3063  m_schedGroup = new SchedGroup(*this);
3064  interact->addChild(m_schedGroup);
3065  }
3066  interact->addChild(new InputPriority(*this));
3067  interact->addChild(new ScheduleOrder(*this, _cardid));
3068  interact->addChild(new LiveTVOrder(*this, _cardid));
3069 
3070  ButtonStandardSetting *ingrpbtn =
3071  new ButtonStandardSetting(QObject::tr("Create a New Input Group"));
3072  ingrpbtn->setHelpText(
3073  QObject::tr("Input groups are only needed when two or more cards "
3074  "share the same resource such as a FireWire card and "
3075  "an analog card input controlling the same set top box."));
3076  interact->addChild(ingrpbtn);
3077  interact->addChild(m_inputGrp0);
3078  interact->addChild(m_inputGrp1);
3079 
3080  addChild(interact);
3081 
3082  setObjectName("CardInput");
3083  SetSourceID("-1");
3084 
3085  connect(m_scan, SIGNAL(clicked()), SLOT(channelScanner()));
3086  connect(m_srcFetch, SIGNAL(clicked()), SLOT(sourceFetch()));
3087  connect(m_sourceId, SIGNAL(valueChanged(const QString&)),
3088  m_startChan,SLOT( SetSourceID (const QString&)));
3089  connect(m_sourceId, SIGNAL(valueChanged(const QString&)),
3090  this, SLOT( SetSourceID (const QString&)));
3091  connect(ingrpbtn, SIGNAL(clicked()),
3092  this, SLOT( CreateNewInputGroup()));
3093 }
3094 
3096 {
3098  {
3099  delete m_externalInputSettings;
3100  m_externalInputSettings = nullptr;
3101  }
3102 }
3103 
3104 void CardInput::SetSourceID(const QString &sourceid)
3105 {
3106  uint cid = m_id->getValue().toUInt();
3107  QString raw_card_type = CardUtil::GetRawInputType(cid);
3108  bool enable = (sourceid.toInt() > 0);
3109  m_scan->setEnabled(enable && !raw_card_type.isEmpty() &&
3110  !CardUtil::IsUnscanable(raw_card_type));
3111  m_srcFetch->setEnabled(enable);
3112 }
3113 
3114 QString CardInput::getSourceName(void) const
3115 {
3116  return m_sourceId->getValueLabel();
3117 }
3118 
3120 {
3121  m_inputGrp0->Save();
3122  m_inputGrp1->Save();
3123 
3124  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
3125  MythTextInputDialog *settingdialog =
3126  new MythTextInputDialog(popupStack, tr("Enter new group name"));
3127 
3128  if (settingdialog->Create())
3129  {
3130  connect(settingdialog, SIGNAL(haveResult(QString)),
3131  SLOT(CreateNewInputGroupSlot(const QString&)));
3132  popupStack->AddScreen(settingdialog);
3133  }
3134  else
3135  delete settingdialog;
3136 }
3137 
3139 {
3140  if (name.isEmpty())
3141  {
3142  ShowOkPopup(tr("Sorry, this Input Group name cannot be blank."));
3143  return;
3144  }
3145 
3146  QString new_name = QString("user:") + name;
3147 
3148  MSqlQuery query(MSqlQuery::InitCon());
3149  query.prepare("SELECT inputgroupname "
3150  "FROM inputgroup "
3151  "WHERE inputgroupname = :GROUPNAME");
3152  query.bindValue(":GROUPNAME", new_name);
3153 
3154  if (!query.exec())
3155  {
3156  MythDB::DBError("CreateNewInputGroup 1", query);
3157  return;
3158  }
3159 
3160  if (query.next())
3161  {
3162  ShowOkPopup(tr("Sorry, this Input Group name is already in use."));
3163  return;
3164  }
3165 
3166  uint inputgroupid = CardUtil::CreateInputGroup(new_name);
3167 
3168  m_inputGrp0->Load();
3169  m_inputGrp1->Load();
3170 
3171  if (m_inputGrp0->getValue().toUInt() == 0U)
3172  {
3174  m_inputGrp0->getValueIndex(QString::number(inputgroupid)));
3175  }
3176  else
3177  {
3179  m_inputGrp1->getValueIndex(QString::number(inputgroupid)));
3180  }
3181 }
3182 
3184 {
3185  uint srcid = m_sourceId->getValue().toUInt();
3186  uint crdid = m_id->getValue().toUInt();
3187  QString in = m_inputName->getValue();
3188 
3189 #ifdef USING_BACKEND
3190  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3191 
3192  Save(); // save info for scanner.
3193 
3194  QString cardtype = CardUtil::GetRawInputType(crdid);
3195  if (CardUtil::IsUnscanable(cardtype))
3196  {
3197  LOG(VB_GENERAL, LOG_ERR,
3198  QString("Sorry, %1 cards do not yet support scanning.")
3199  .arg(cardtype));
3200  return;
3201  }
3202 
3204  StandardSettingDialog *ssd =
3205  new StandardSettingDialog(mainStack, "generalsettings",
3206  new ScanWizard(srcid, crdid, in));
3207 
3208  if (ssd->Create())
3209  {
3210  connect(ssd, &StandardSettingDialog::Exiting,
3211  [=]()
3212  {
3213  if (SourceUtil::GetChannelCount(srcid))
3214  m_startChan->SetSourceID(QString::number(srcid));
3215  if (num_channels_before)
3216  {
3217  m_startChan->Load();
3218  m_startChan->Save();
3219  }
3220  });
3221  mainStack->AddScreen(ssd);
3222  }
3223  else
3224  delete ssd;
3225 
3226 #else
3227  LOG(VB_GENERAL, LOG_ERR, "You must compile the backend "
3228  "to be able to scan for channels");
3229 #endif
3230 }
3231 
3233 {
3234  uint srcid = m_sourceId->getValue().toUInt();
3235  uint crdid = m_id->getValue().toUInt();
3236 
3237  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3238 
3239  if (crdid && srcid)
3240  {
3241  Save(); // save info for fetch..
3242 
3243  QString cardtype = CardUtil::GetRawInputType(crdid);
3244 
3245  if (!CardUtil::IsCableCardPresent(crdid, cardtype) &&
3246  !CardUtil::IsUnscanable(cardtype) &&
3247  !CardUtil::IsEncoder(cardtype) &&
3248  cardtype != "HDHOMERUN" &&
3249  !num_channels_before)
3250  {
3251  LOG(VB_GENERAL, LOG_ERR, "Skipping channel fetch, you need to "
3252  "scan for channels first.");
3253  return;
3254  }
3255 
3256  SourceUtil::UpdateChannelsFromListings(srcid, cardtype);
3257  }
3258 
3259  if (SourceUtil::GetChannelCount(srcid))
3260  m_startChan->SetSourceID(QString::number(srcid));
3261  if (num_channels_before)
3262  {
3263  m_startChan->Load();
3264  m_startChan->Save();
3265  }
3266 }
3267 
3269 {
3270  QString cardinputidTag(":WHERECARDID");
3271 
3272  QString query("cardid = " + cardinputidTag);
3273 
3274  bindings.insert(cardinputidTag, m_parent.getInputID());
3275 
3276  return query;
3277 }
3278 
3280 {
3281  QString cardinputidTag(":SETCARDID");
3282  QString colTag(":SET" + GetColumnName().toUpper());
3283 
3284  QString query("cardid = " + cardinputidTag + ", " +
3285  GetColumnName() + " = " + colTag);
3286 
3287  bindings.insert(cardinputidTag, m_parent.getInputID());
3288  bindings.insert(colTag, m_user->GetDBValue());
3289 
3290  return query;
3291 }
3292 
3293 void CardInput::loadByID(int inputid)
3294 {
3295  m_id->setValue(inputid);
3296  m_externalInputSettings->Load(inputid);
3298 }
3299 
3300 void CardInput::loadByInput(int _cardid, const QString& _inputname)
3301 {
3302  MSqlQuery query(MSqlQuery::InitCon());
3303  query.prepare("SELECT cardid FROM capturecard "
3304  "WHERE cardid = :CARDID AND inputname = :INPUTNAME");
3305  query.bindValue(":CARDID", _cardid);
3306  query.bindValue(":INPUTNAME", _inputname);
3307 
3308  if (query.exec() && query.isActive() && query.next())
3309  {
3310  loadByID(query.value(0).toInt());
3311  }
3312 }
3313 
3315 {
3316  uint cardid = m_id->getValue().toUInt();
3319 
3320  uint icount = 1;
3321  if (m_instanceCount)
3322  icount = m_instanceCount->getValue().toUInt();
3323  vector<uint> cardids = CardUtil::GetChildInputIDs(cardid);
3324 
3325  // Delete old clone cards as required.
3326  for (size_t i = cardids.size() + 1;
3327  (i > icount) && !cardids.empty(); --i)
3328  {
3329  CardUtil::DeleteInput(cardids.back());
3330  cardids.pop_back();
3331  }
3332 
3333  // Clone this config to existing clone cards.
3334  for (size_t i = 0; i < cardids.size(); ++i)
3335  {
3336  CardUtil::CloneCard(cardid, cardids[i]);
3337  }
3338 
3339  // Create new clone cards as required.
3340  for (size_t i = cardids.size() + 1; i < icount; i++)
3341  {
3342  CardUtil::CloneCard(cardid, 0);
3343  }
3344 
3345  // Delete any unused input groups
3347 }
3348 
3350 {
3351  return m_parent.getInputID();
3352 }
3353 
3355 {
3356  return m_parent.getCardID();
3357 }
3358 
3360 {
3361  emit Clicked(m_value);
3362 }
3363 
3364 void CaptureCardEditor::AddSelection(const QString &label, const char *slot)
3365 {
3366  ButtonStandardSetting *button = new ButtonStandardSetting(label);
3367  connect(button, SIGNAL(clicked()), slot);
3368  addChild(button);
3369 }
3370 
3372 {
3373  ShowOkPopup(
3374  tr("Are you sure you want to delete "
3375  "ALL capture cards on %1?").arg(gCoreContext->GetHostName()),
3376  this,
3377  SLOT(DeleteAllCaptureCardsOnHost(bool)),
3378  true);
3379 }
3380 
3382 {
3383  ShowOkPopup(
3384  tr("Are you sure you want to delete "
3385  "ALL capture cards?"),
3386  this,
3387  SLOT(DeleteAllCaptureCards(bool)),
3388  true);
3389 }
3390 
3392 {
3393  CaptureCard *card = new CaptureCard();
3394  card->setLabel(tr("New capture card"));
3395  card->Load();
3396  addChild(card);
3397  emit settingsChanged(this);
3398 }
3399 
3401 {
3402  if (!doDelete)
3403  return;
3404 
3406  Load();
3407  emit settingsChanged(this);
3408 }
3409 
3411 {
3412  if (!doDelete)
3413  return;
3414 
3415  MSqlQuery cards(MSqlQuery::InitCon());
3416 
3417  cards.prepare(
3418  "SELECT cardid "
3419  "FROM capturecard "
3420  "WHERE hostname = :HOSTNAME");
3421  cards.bindValue(":HOSTNAME", gCoreContext->GetHostName());
3422 
3423  if (!cards.exec() || !cards.isActive())
3424  {
3425  ShowOkPopup(
3426  tr("Error getting list of cards for this host. "
3427  "Unable to delete capturecards for %1")
3428  .arg(gCoreContext->GetHostName()));
3429 
3430  MythDB::DBError("Selecting cardids for deletion", cards);
3431  return;
3432  }
3433 
3434  while (cards.next())
3435  CardUtil::DeleteInput(cards.value(0).toUInt());
3436 
3437  Load();
3438  emit settingsChanged(this);
3439 }
3440 
3442 {
3443  setLabel(tr("Capture cards"));
3444 }
3445 
3447 {
3448  clearSettings();
3449  AddSelection(QObject::tr("(New capture card)"), SLOT(AddNewCard()));
3450  AddSelection(QObject::tr("(Delete all capture cards on %1)")
3451  .arg(gCoreContext->GetHostName()),
3453  AddSelection(QObject::tr("(Delete all capture cards)"),
3456 }
3457 
3459 {
3460  setLabel(tr("Video sources"));
3461 }
3462 
3464 {
3465  clearSettings();
3466  AddSelection(QObject::tr("(New video source)"), SLOT(NewSource()));
3467  AddSelection(QObject::tr("(Delete all video sources)"),
3468  SLOT(ShowDeleteAllSourcesDialog()));
3471 }
3472 
3473 void VideoSourceEditor::AddSelection(const QString &label, const char* slot)
3474 {
3475  ButtonStandardSetting *button = new ButtonStandardSetting(label);
3476  connect(button, SIGNAL(clicked()), slot);
3477  addChild(button);
3478 }
3479 
3481 {
3482  ShowOkPopup(
3483  tr("Are you sure you want to delete "
3484  "ALL video sources?"),
3485  this,
3486  SLOT(DeleteAllSources(bool)),
3487  true);
3488 }
3489 
3491 {
3492  if (!doDelete)
3493  return;
3494 
3496  Load();
3497  emit settingsChanged(this);
3498 }
3499 
3501 {
3502  VideoSource *source = new VideoSource();
3503  source->setLabel(tr("New video source"));
3504  source->Load();
3505  addChild(source);
3506  emit settingsChanged(this);
3507 }
3508 
3510 {
3511  setLabel(tr("Input connections"));
3512 }
3513 
3515 {
3516  m_cardInputs.clear();
3517  clearSettings();
3518 
3519  // We do this manually because we want custom labels. If
3520  // SelectSetting provided a facility to edit the labels, we
3521  // could use CaptureCard::fillSelections
3522 
3523  MSqlQuery query(MSqlQuery::InitCon());
3524  query.prepare(
3525  "SELECT cardid, videodevice, cardtype, inputname "
3526  "FROM capturecard "
3527  "WHERE hostname = :HOSTNAME "
3528  " AND parentid = 0 "
3529  "ORDER BY cardid");
3530  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
3531 
3532  if (!query.exec())
3533  {
3534  MythDB::DBError("CardInputEditor::load", query);
3535  return;
3536  }
3537 
3538  while (query.next())
3539  {
3540  uint cardid = query.value(0).toUInt();
3541  QString videodevice = query.value(1).toString();
3542  QString cardtype = query.value(2).toString();
3543  QString inputname = query.value(3).toString();
3544 
3545  CardInput *cardinput = new CardInput(cardtype, videodevice,
3546  cardid);
3547  cardinput->loadByID(cardid);
3548  QString inputlabel = QString("%1 (%2) -> %3")
3549  .arg(CardUtil::GetDeviceLabel(cardtype, videodevice))
3550  .arg(inputname).arg(cardinput->getSourceName());
3551  m_cardInputs.push_back(cardinput);
3552  cardinput->setLabel(inputlabel);
3553  addChild(cardinput);
3554  }
3555 
3557 }
3558 
3559 #ifdef USING_DVB
3560 static QString remove_chaff(const QString &name)
3561 {
3562  // Trim off some of the chaff.
3563  QString short_name = name;
3564  if (short_name.startsWith("LG Electronics"))
3565  short_name = short_name.right(short_name.length() - 15);
3566  if (short_name.startsWith("Oren"))
3567  short_name = short_name.right(short_name.length() - 5);
3568  if (short_name.startsWith("Nextwave"))
3569  short_name = short_name.right(short_name.length() - 9);
3570  if (short_name.startsWith("frontend", Qt::CaseInsensitive))
3571  short_name = short_name.left(short_name.length() - 9);
3572  if (short_name.endsWith("VSB/QAM"))
3573  short_name = short_name.left(short_name.length() - 8);
3574  if (short_name.endsWith("VSB"))
3575  short_name = short_name.left(short_name.length() - 4);
3576  if (short_name.endsWith("DVB-T"))
3577  short_name = short_name.left(short_name.length() - 6);
3578 
3579  // It would be infinitely better if DVB allowed us to query
3580  // the vendor ID. But instead we have to guess based on the
3581  // demodulator name. This means cards like the Air2PC HD5000
3582  // and DViCO Fusion HDTV cards are not identified correctly.
3583  short_name = short_name.simplified();
3584  if (short_name.startsWith("or51211", Qt::CaseInsensitive))
3585  short_name = "pcHDTV HD-2000";
3586  else if (short_name.startsWith("or51132", Qt::CaseInsensitive))
3587  short_name = "pcHDTV HD-3000";
3588  else if (short_name.startsWith("bcm3510", Qt::CaseInsensitive))
3589  short_name = "Air2PC v1";
3590  else if (short_name.startsWith("nxt2002", Qt::CaseInsensitive))
3591  short_name = "Air2PC v2";
3592  else if (short_name.startsWith("nxt200x", Qt::CaseInsensitive))
3593  short_name = "Air2PC v2";
3594  else if (short_name.startsWith("lgdt3302", Qt::CaseInsensitive))
3595  short_name = "DViCO HDTV3";
3596  else if (short_name.startsWith("lgdt3303", Qt::CaseInsensitive))
3597  short_name = "DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
3598 
3599  return short_name;
3600 }
3601 #endif // USING_DVB
3602 
3603 void DVBConfigurationGroup::reloadDiseqcTree(const QString &videodevice)
3604 {
3605  if (m_diseqcTree)
3606  m_diseqcTree->Load(videodevice);
3607 }
3608 
3609 void DVBConfigurationGroup::probeCard(const QString &videodevice)
3610 {
3611  if (videodevice.isEmpty())
3612  {
3613  m_cardName->setValue("");
3614  m_cardType->setValue("");
3615  return;
3616  }
3617 
3618  if (m_parent.getCardID() && m_parent.GetRawCardType() != "DVB")
3619  {
3620  m_cardName->setValue("");
3621  m_cardType->setValue("");
3622  return;
3623  }
3624 
3625 #ifdef USING_DVB
3626  QString frontend_name = CardUtil::ProbeDVBFrontendName(videodevice);
3627  QString subtype = CardUtil::ProbeDVBType(videodevice);
3628 
3629  QString err_open = tr("Could not open card %1").arg(videodevice);
3630  QString err_other = tr("Could not get card info for card %1").arg(videodevice);
3631 
3632  switch (CardUtil::toInputType(subtype))
3633  {
3634  case CardUtil::ERROR_OPEN:
3635  m_cardName->setValue(err_open);
3636  m_cardType->setValue(strerror(errno));
3637  break;
3639  m_cardName->setValue(err_other);
3640  m_cardType->setValue("Unknown error");
3641  break;
3642  case CardUtil::ERROR_PROBE:
3643  m_cardName->setValue(err_other);
3644  m_cardType->setValue(strerror(errno));
3645  break;
3646  case CardUtil::QPSK:
3647  m_cardType->setValue("DVB-S");
3648  m_cardName->setValue(frontend_name);
3649  m_signalTimeout->setValue(7000);
3650  m_channelTimeout->setValue(10000);
3651  break;
3652  case CardUtil::DVBS2:
3653  m_cardType->setValue("DVB-S2");
3654  m_cardName->setValue(frontend_name);
3655  m_signalTimeout->setValue(7000);
3656  m_channelTimeout->setValue(10000);
3657  break;
3658  case CardUtil::QAM:
3659  m_cardType->setValue("DVB-C");
3660  m_cardName->setValue(frontend_name);
3661  m_signalTimeout->setValue(1000);
3662  m_channelTimeout->setValue(3000);
3663  break;
3664  case CardUtil::DVBT2:
3665  m_cardType->setValue("DVB-T2");
3666  m_cardName->setValue(frontend_name);
3667  m_signalTimeout->setValue(1000);
3668  m_channelTimeout->setValue(3000);
3669  break;
3670  case CardUtil::OFDM:
3671  {
3672  m_cardType->setValue("DVB-T");
3673  m_cardName->setValue(frontend_name);
3674  m_signalTimeout->setValue(1000);
3675  m_channelTimeout->setValue(3000);
3676  if (frontend_name.toLower().indexOf("usb") >= 0)
3677  {
3678  m_signalTimeout->setValue(40000);
3679  m_channelTimeout->setValue(42500);
3680  }
3681 
3682  // slow down tuning for buggy drivers
3683  if ((frontend_name == "DiBcom 3000P/M-C DVB-T") ||
3684  (frontend_name ==
3685  "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
3686  {
3687  m_tuningDelay->setValue(200);
3688  }
3689 
3690 #if 0 // frontends on hybrid DVB-T/Analog cards
3691  QString short_name = remove_chaff(frontend_name);
3692  m_buttonAnalog->setVisible(
3693  short_name.startsWith("zarlink zl10353",
3694  Qt::CaseInsensitive) ||
3695  short_name.startsWith("wintv hvr 900 m/r: 65008/a1c0",
3696  Qt::CaseInsensitive) ||
3697  short_name.startsWith("philips tda10046h",
3698  Qt::CaseInsensitive));
3699 #endif
3700  }
3701  break;
3702  case CardUtil::ATSC:
3703  {
3704  QString short_name = remove_chaff(frontend_name);
3705  m_cardType->setValue("ATSC");
3706  m_cardName->setValue(short_name);
3707  m_signalTimeout->setValue(500);
3708  m_channelTimeout->setValue(3000);
3709 
3710  // According to #1779 and #1935 the AverMedia 180 needs
3711  // a 3000 ms signal timeout, at least for QAM tuning.
3712  if (frontend_name == "Nextwave NXT200X VSB/QAM frontend")
3713  {
3714  m_signalTimeout->setValue(3000);
3715  m_channelTimeout->setValue(5500);
3716  }
3717 
3718 #if 0 // frontends on hybrid DVB-T/Analog cards
3719  if (frontend_name.toLower().indexOf("usb") < 0)
3720  {
3721  m_buttonAnalog->setVisible(
3722  short_name.startsWith("pchdtv", Qt::CaseInsensitive) ||
3723  short_name.startsWith("dvico", Qt::CaseInsensitive) ||
3724  short_name.startsWith("nextwave", Qt::CaseInsensitive));
3725  }
3726 #endif
3727  }
3728  break;
3729  default:
3730  break;
3731  }
3732 
3733  // Create selection list of all delivery systems of this card
3734  {
3736  QStringList delsyslist = CardUtil::ProbeDeliverySystems(videodevice);
3737  QStringList::iterator it = delsyslist.begin();
3738  for (; it != delsyslist.end(); it++)
3739  {
3740  LOG(VB_GENERAL, LOG_DEBUG, QString("DVBCardType: add deliverysystem:%1")
3741  .arg(*it));
3742 
3743  m_cardType->addSelection(*it, *it);
3744  }
3745 
3746  // Default value, used if not already defined in capturecard/inputname
3747  QString delsys = CardUtil::ProbeDefaultDeliverySystem(videodevice);
3748  if (!delsys.isEmpty())
3749  {
3750  m_cardType->setValue(delsys);
3751  }
3752  }
3753 #
3754 #else
3755  m_cardType->setValue(QString("Recompile with DVB-Support!"));
3756 #endif
3757 }
3758 
3760  QString dev, QString type) :
3761  CaptureCardComboBoxSetting(parent, false, "audiodevice"),
3762  m_lastDevice(std::move(dev)), m_lastCardType(std::move(type))
3763 {
3764  setLabel(QObject::tr("Audio input"));
3765  setHelpText(QObject::tr("If there is more than one audio input, "
3766  "select which one to use."));
3767  int cardid = parent.getCardID();
3768  if (cardid <= 0)
3769  return;
3770 
3773 }
3774 
3775 int TunerCardAudioInput::fillSelections(const QString &device)
3776 {
3777  clearSelections();
3778 
3779  if (device.isEmpty())
3780  return 0;
3781 
3782  m_lastDevice = device;
3783  QStringList inputs =
3785 
3786  for (uint i = 0; i < (uint)inputs.size(); i++)
3787  {
3788  addSelection(inputs[i], QString::number(i),
3789  m_lastDevice == QString::number(i));
3790  }
3791  return inputs.size();
3792 }
3793 
3795  CardType& cardType) :
3796  m_parent(a_parent),
3797  m_diseqcTree(new DiSEqCDevTree())
3798 {
3799  setVisible(false);
3800 
3801  m_cardNum = new DVBCardNum(m_parent);
3802  m_cardName = new DVBCardName();
3804 
3805  m_signalTimeout = new SignalTimeout(m_parent, 500, 250);
3806  m_channelTimeout = new ChannelTimeout(m_parent, 3000, 1750);
3807 
3808  cardType.addTargetedChild("DVB", m_cardNum);
3809 
3810  cardType.addTargetedChild("DVB", m_cardName);
3811  cardType.addTargetedChild("DVB", m_cardType);
3812 
3813  cardType.addTargetedChild("DVB", m_signalTimeout);
3814  cardType.addTargetedChild("DVB", m_channelTimeout);
3815 
3816  cardType.addTargetedChild("DVB", new EmptyAudioDevice(m_parent));
3817  cardType.addTargetedChild("DVB", new EmptyVBIDevice(m_parent));
3818 
3819  cardType.addTargetedChild("DVB", new DVBNoSeqStart(m_parent));
3820  cardType.addTargetedChild("DVB", new DVBOnDemand(m_parent));
3821  cardType.addTargetedChild("DVB", new DVBEITScan(m_parent));
3822 
3824  m_diseqcBtn->setLabel(tr("DiSEqC (Switch, LNB, and Rotor Configuration)"));
3825  m_diseqcBtn->setHelpText(tr("Input and satellite settings."));
3826  m_diseqcBtn->setVisible(false);
3827 
3829  cardType.addTargetedChild("DVB", m_tuningDelay);
3830  cardType.addTargetedChild("DVB", m_diseqcBtn);
3831  m_tuningDelay->setVisible(false);
3832 
3833  connect(m_cardNum, SIGNAL(valueChanged(const QString&)),
3834  this, SLOT( probeCard (const QString&)));
3835  connect(m_cardNum, SIGNAL(valueChanged(const QString&)),
3836  this, SLOT( reloadDiseqcTree(const QString&)));
3837 }
3838 
3840 {
3841  if (m_diseqcTree)
3842  {
3843  delete m_diseqcTree;
3844  m_diseqcTree = nullptr;
3845  }
3846 }
3847 
3849 {
3851  m_diseqcBtn->Load();
3853  if (m_cardType->getValue() == "DVB-S" ||
3854  m_cardType->getValue() == "DVB-S2" ||
3856  {
3857  m_diseqcBtn->setVisible(true);
3858  }
3859 }
3860 
3862 {
3865  DiSEqCDev trees;
3866  trees.InvalidateTrees();
3867 }
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:782
CommandPath(const CaptureCard &parent)
void NewIP(const QString &)
QString m_ip
Definition: videosource.h:915
void Load(void) override
QuickTune(const CardInput &parent)
void Run(time_t timeout=0)
Runs a command inside the /bin/sh shell. Returns immediately.
static bool IsTunerSharingCapable(const QString &rawtype)
Definition: cardutil.h:162
static QString remove_chaff(const QString &name)
void SetSourceID(uint _sourceid)
static QString GetModelName(uint vendor_id, uint model_id)
SignalTimeout * m_signalTimeout
Definition: videosource.h:574
TransTextEditSetting * m_size
Definition: videosource.h:509
QString getValueLabel(void) const
CaptureCard & m_parent
Definition: videosource.h:418
static QStringList ProbeVideoDevices(const QString &rawtype)
Definition: cardutil.cpp:458
XMLTV_generic_config(const VideoSource &_parent, const QString &_grabber, StandardSetting *_setting)
DiSEqCDevTree * m_diseqcTree
Definition: videosource.h:580
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:863
QString getSourceName(void) const
Definition: videosource.h:174
static ChannelInfoList GetAllChannels(uint sourceid)
Returns channels that are not connected to an input and channels that are not marked as visible.
Definition: channelutil.h:246
SourceID * m_sourceId
Definition: videosource.h:813
DVB-S device settings class.
Definition: diseqc.h:35
void NewSource(void)
VideoDevice * m_device
Definition: videosource.h:438
void fillSelections()
QString Card(void) const
allow access to stdout
Definition: mythsystem.h:39
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
vector< CardInput * > m_cardInputs
Definition: videosource.h:758
QString GetColumnName(void) const
Definition: mythstorage.h:43
virtual void clearSettings()
HDHomeRunConfigurationGroup(CaptureCard &parent, CardType &cardtype)
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
QString cardip
Definition: videosource.h:374
void probeCard(const QString &device)
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
CardType(const CaptureCard &parent)
static uint CreateInputGroup(const QString &name)
Definition: cardutil.cpp:1810
void Load(void) override
void probeCard(const QString &device)
MythUISpinBoxSetting * m_instanceCount
Definition: videosource.h:820
UseHDHomeRunDevice * checkbox
Definition: videosource.h:326
void Load(void) override
VBoxDeviceID * m_deviceId
Definition: videosource.h:890
void NewTuner(const QString &)
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:678
QString m_oldValue
Definition: videosource.h:897
void SetSourceID(const QString &sourceid)
CaptureCardSpinBoxSetting(const CaptureCard &parent, uint min_val, uint max_val, uint step, const QString &setting)
static void ClearVideoDeviceCache()
Definition: cardutil.cpp:452
ASIDevice(const CaptureCard &parent)
AudioRateLimit(const CaptureCard &parent)
NoGrabber_config(const VideoSource &_parent)
static uint GetChannelCount(uint sourceid)
Definition: sourceutil.cpp:109
void Load(void) override
SignalTimeout(const CaptureCard &parent, uint value, uint min_val)
static void error(const char *str,...)
Definition: vbi.c:42
Storage * GetStorage(void) const
static bool DeleteSource(uint sourceid)
Definition: sourceutil.cpp:480
SchedGroup(const CardInput &parent)
CaptureCard & m_parent
Definition: videosource.h:523
void DeleteAllSources(bool)
void Save(void) override
static void FirewireConfigurationGroup(CaptureCard &parent, CardType &cardtype)
static enum INPUT_TYPES toInputType(const QString &name)
Definition: cardutil.h:72
void settingsChanged(StandardSetting *selectedSetting=nullptr)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
ScheduleOrder(const CardInput &parent, int _value)
InputGroup * m_inputGrp0
Definition: videosource.h:818
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)
virtual void Load(void)
virtual bool Create(void)
DVBCardType(const CaptureCard &parent)
void addSelection(const QString &label, QString value=QString(), bool select=false)
static QString ProbeDVBFrontendName(const QString &device)
Returns the input type from the video device.
Definition: cardutil.cpp:699
const CaptureCard & m_parent
Definition: videosource.h:895
LiveTVOrder(const CardInput &parent, int _value)
virtual void setHelpText(const QString &str)
TransTextEditSetting * m_cardInfo
Definition: videosource.h:471
V4L2encGroup(CaptureCard &parent, CardType &cardType)
static bool IsInNeedOfExternalInputConf(uint inputid)
Definition: cardutil.cpp:2076
int size(void) const
Definition: mythdbcon.h:203
QString deviceid
Definition: videosource.h:372
static bool IsUnscanable(const QString &rawtype)
Definition: cardutil.h:144
bool cardTypesInclude(const int &SourceID, const QString &thecardtype)
TransTextEditSetting * m_cardInfo
Definition: videosource.h:419
InputGroup(const CardInput &parent, uint group_num)
FirewireModel(const CaptureCard &parent, const FirewireGUID *)
DVBEITScan(const CaptureCard &parent)
HDHomeRunConfigurationGroup & group
Definition: videosource.h:363
bool IsOpen(void) const
Definition: v4l2util.h:29
void CreateNewInputGroup()
QString GetWhereClause(MSqlBindings &bindings) const override
InputDisplayName(const CardInput &parent)
MythScreenStack * GetStack(const QString &stackname)
void Save(void) override
unsigned int uint
Definition: compat.h:140
int getCardID(void) const
Definition: videosource.h:627
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString m_product_name
Definition: avcinfo.h:45
void AddSelection(const QString &label, const char *slot)
void Load(void) override
int getValueIndex(const QString &value) const
MythScreenStack * GetMainStack()
GroupSetting * m_cardInfo
Definition: videosource.h:455
IPTVHost(const CaptureCard &parent)
VBoxConfigurationGroup(CaptureCard &parent, CardType &cardtype)
QString getSourceName(void) const
CetonDeviceID(const CaptureCard &parent)
void Load(void) override
void Load(void) override
Definition: videosource.cpp:76
QStringList m_grabberArgs
Definition: videosource.h:119
virtual QString GetDBValue(void) const =0
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
QMap< QString, VBoxDevice > VBoxDeviceList
Definition: videosource.h:381
VideoSourceSelector(uint _initial_sourceid, const QString &_card_types, bool _must_have_mplexid)
Definition: videosource.cpp:66
DVBCardType * m_cardType
Definition: videosource.h:573
UseEIT * m_useeit
Definition: videosource.h:143
static guint32 * tmp
Definition: goom_core.c:35
static QString GetDeviceName(dvb_dev_type_t, const QString &device)
void Load(void) override
void DeleteAllCaptureCardsOnHost(bool)
MythUICheckBoxSetting * m_schedGroup
Definition: videosource.h:821
static bool HasTuner(const QString &rawtype, const QString &device)
Definition: cardutil.cpp:228
void Clicked(const QString &choice)
DVBTuningDelay(const CaptureCard &parent)
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:130
#define lstat
Definition: compat.h:194
static uint CloneCard(uint src_inputid, uint dst_inputid)
Definition: cardutil.cpp:1495
bool Store(uint cardid, const QString &device="")
Stores the device tree to the database.
Definition: diseqc.cpp:419
void probeCard(const QString &device)
void fillSelections(const QString &current)
Adds all available cards to list If current is >= 0 it will be considered available even if no device...
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:2123
DVBCardNum * m_cardNum
Definition: videosource.h:571
void LoadedTuner(const QString &)
void UpdateDevices(const QString &)
DVBTuningDelay * m_tuningDelay
Definition: videosource.h:579
void Load(void) override
void NewValue(const QString &)
const char * name
Definition: frequencies.h:102
virtual QString getValue(void) const
static bool IsEncoder(const QString &rawtype)
Definition: cardutil.h:121
VBIDevice * m_vbiDev
Definition: videosource.h:420
QString deviceid
Definition: videosource.h:323
void fillSelections(const QString &current)
Adds all available cards to list If current is >= 0 it will be considered available even if no device...
uint fillSelectionsFromDir(const QDir &dir, uint minor_min, uint minor_max, const QString &card, const QString &driver, bool allow_duplicates)
virtual void setName(const QString &name)
QString GetConfDir(void)
Definition: mythdirs.cpp:224
const CaptureCard & m_parent
Definition: videosource.h:229
void AddSelection(const QString &label, const char *slot)
QVariant value(int i) const
Definition: mythdbcon.h:198
void loadByID(int id)
void probeCard(const QString &device)
void sourceFetch()
CaptureCard(bool use_card_group=true)
static bool DeleteInput(uint inputid)
bool Create(void) override
void SetTuner(const QString &)
void ShowDeleteAllSourcesDialog(void)
static vector< AVCInfo > GetSTBList(void)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
SourceID(const CardInput &parent)
struct CHANLISTS chanlists[]
QString GetWhereClause(MSqlBindings &bindings) const override
uint m_vendorid
Definition: avcinfo.h:42
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
static QString TestMimeType(const QString &sFileName)
void Save(void) override
void fillSelections()
ChannelTimeout * m_channelTimeout
Definition: videosource.h:575
void SetIP(const QString &)
TunerCardAudioInput * m_audioInput
Definition: videosource.h:456
void Load(void) override
void probeCard(const QString &device)
#define close
Definition: compat.h:16
void setValue(int value) override
FileDevice(const CaptureCard &parent)
int getCardID(void) const
TransTextEditSetting * m_size
Definition: videosource.h:525
void fillSelections(const QString &current)
Adds all available device-tuner combinations to list.
void LoadedIP(const QString &)
InputName(const CardInput &parent)
static bool DeleteAllInputs(void)
VideoDevice(const CaptureCard &parent, uint minor_min=0, uint minor_max=UINT_MAX, const QString &card=QString(), const QString &driver=QString())
virtual void setLabel(QString str)
void SetOldValue(const QString &s)
Definition: videosource.h:836
MPEGConfigurationGroup(CaptureCard &parent, CardType &cardtype)
UseHDHomeRunDevice(QString &deviceid, QString &model, QString &ipaddr)
void SetDeviceCheckBoxes(const QString &devices)
AudioDevice(const CaptureCard &parent)
run process through shell
Definition: mythsystem.h:41
void setEnabled(bool e) override
HDHomeRunDeviceList m_deviceList
Definition: videosource.h:349
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
TransTextEditSetting * m_cardInfo
Definition: videosource.h:440
QString GetSetting(const QString &key, const QString &defaultval="")
static QString GetDeliverySystemFromDB(uint inputid)
Definition: cardutil.h:279
VBoxDeviceList m_deviceList
Definition: videosource.h:404
DemoConfigurationGroup(CaptureCard &parent, CardType &cardtype)
QByteArray & ReadAll()
void LoadXMLTVGrabbers(QStringList name_list, QStringList prog_list)
static bool IsCableCardPresent(uint inputid, const QString &inputType)
Definition: cardutil.cpp:117
StorageUser * m_user
Definition: mythstorage.h:46
void Save(void) override
static uint GetDeviceInputGroup(uint inputid)
Definition: cardutil.cpp:1865
TransFreqTableSelector(uint _sourceid)
#define minor(X)
Definition: compat.h:138
V4LConfigurationGroup(CaptureCard &parent, CardType &cardtype)
DishNetEIT(const CardInput &parent)
static bool UpdateChannelsFromListings(uint sourceid, const QString &inputtype=QString(), bool wait=false)
Definition: sourceutil.cpp:363
bool isActive(void) const
Definition: mythdbcon.h:204
QString Driver(void) const
InputName * m_inputName
Definition: videosource.h:812
QString tunertype
Definition: videosource.h:376
VBoxIP * m_cardIp
Definition: videosource.h:892
void SetGUID(const QString &)
static void IPTVConfigurationGroup(CaptureCard &parent, CardType &cardType)
void ShowDeleteAllCaptureCardsDialog(void)
bool Store(uint card_input_id) const
Stores configuration chain to DB for specified card input id.
Definition: diseqc.cpp:164
void Load(void) override
Definition: videosource.h:176
bool discovered
Definition: videosource.h:378
void SetTuner(const QString &)
virtual void setEnabled(bool enabled)
void Load(void) override
VBoxDeviceID(const CaptureCard &parent)
static void fillSelections(GroupSetting *setting)
void SetGUID(const QString &)
void fillSelectionsFromDir(const QDir &dir, bool absPath=true)
static vector< uint > GetChildInputIDs(uint inputid)
Definition: cardutil.cpp:1318
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1929
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
CardInput(const QString &cardtype, const QString &device, int cardid)
void LoadValue(const QString &)
AVCInfo GetAVCInfo(const QString &guid) const
QString m_tuner
Definition: videosource.h:957
const char * name
Definition: ParseText.cpp:328
void edit(MythScreenType *screen) override
HDHomeRunDeviceID(const CaptureCard &parent, HDHomeRunConfigurationGroup &_group)
static void fillSelections(GroupSetting *setting)
virtual void Load(void)=0
const FirewireGUID * m_guid
Definition: videosource.h:596
bool isEnabled() const
FirewireConnection(const CaptureCard &parent)
void probeCard(const QString &videodevice)
void Load(void) override
virtual QList< StandardSetting * > * getSubSettings()
CaptureCard & m_parent
Definition: videosource.h:437
CardInputComboBoxSetting(const CardInput &parent, const QString &setting)
CaptureCard & m_parent
Definition: videosource.h:470
static void GetDeviceInputNames(const QString &device, const QString &inputtype, QStringList &inputs)
void Save(void) override
void deleteEntry(void) override
CetonSetting(const char *label, const char *helptext)
virtual void addChild(StandardSetting *child)
void Save(void) override
bool Load(const QString &device)
Loads the device tree from the database.
Definition: diseqc.cpp:315
DVBOnDemand(const CaptureCard &parent)
InputPriority(const CardInput &parent)
MythMainWindow * GetMythMainWindow(void)
void Load(void) override
HDHomeRunEITScan(const CaptureCard &parent)
static void CetonConfigurationGroup(CaptureCard &parent, CardType &cardtype)
const VideoSource & m_parent
Definition: videosource.h:53
uint Wait(time_t timeout=0)
void Load(void) override
void Load(void) override
virtual void Save(void)
static QString GetDeviceLabel(const QString &inputtype, const QString &videodevice)
VBIDevice * m_vbiDevice
Definition: videosource.h:439
vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:120
void SetIP(const QString &)
static const uint kDefaultMultirecCount
Definition: videosource.cpp:64
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:273
virtual void Save(QString)
void setEnabled(bool e) override
TunerCardAudioInput(const CaptureCard &parent, QString dev=QString(), QString type=QString())
void UpdateDevices(const QString &)
Dialog prompting the user to enter a text string.
void setVisible(bool visible)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:807
QString tunerno
Definition: videosource.h:375
SkipBtAudio(const CaptureCard &parent)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
bool Create(void) override
QString m_overrideDeviceId
Definition: videosource.h:917
static int GetASIDeviceNumber(const QString &device, QString *error=nullptr)
UseEIT(const VideoSource &parent)
CaptureCardGroup(CaptureCard &parent)
QMap< uint, uint > m_minorList
static QString GetVBoxdesc(const QString &id, const QString &ip, const QString &tunerNo, const QString &tunerType)
UseEIT * m_useeit
Definition: videosource.h:131
Name * m_name
Definition: videosource.h:210
ButtonStandardSetting * m_scan
Definition: videosource.h:815
static QString GetAudioDevice(uint inputid)
Definition: cardutil.h:275
QMap< QString, AVCInfo > guid_to_avcinfo
void SetOldValue(const QString &s)
Definition: videosource.h:857
InstanceCount(const CardInput &parent, int _initValue)
const VideoSource & m_parent
Definition: videosource.h:117
const FirewireGUID * m_guid
Definition: videosource.h:611
GroupSetting()=default
CaptureCard & m_parent
Definition: videosource.h:491
QString m_DriverName
Definition: videosource.h:474
uint m_modelid
Definition: avcinfo.h:43
EITOnly_config(const VideoSource &_parent, StandardSetting *_setting)
void Load(void) override
void setValue(int value) override
Definition: videosource.h:155
DVBNetID(const VideoSource &parent, signed int value, signed int min_val)
void probeCard(const QString &device)
static bool DeleteAllSources(void)
Definition: sourceutil.cpp:532
void channelScanner()
static QStringList ProbeAudioInputs(const QString &device, const QString &inputtype=QString())
QString GetSetClause(MSqlBindings &bindings) const override
static QStringList GetVideoDevices(const QString &rawtype, QString hostname=QString())
Returns the videodevices of the matching inputs, duplicates removed.
Definition: cardutil.cpp:407
uint setFilter(const QString &card, const QString &driver)
QString GetSetClause(MSqlBindings &bindings) const override
int fillSelections(const QString &device)
DiSEqCDevSettings * m_externalInputSettings
Definition: videosource.h:817
void ShowDeleteAllCaptureCardsDialogOnHost(void)
VideoDevice * m_device
Definition: videosource.h:472
DVBNoSeqStart(const CaptureCard &parent)
void loadByID(int id)
void UpdateDevices(const QString &)
void InvalidateTrees(void)
Invalidate cached trees.
Definition: diseqc.cpp:248
ChannelTimeout(const CaptureCard &parent, uint value, uint min_val)
XMLTVGrabber(const VideoSource &parent)
void deleteEntry(void) override
VBoxTunerIndex * m_cardTuner
Definition: videosource.h:893
QString m_driverName
static bool Exists(int cardid)
Check if a Diseqc device tree exists.
Definition: diseqc.cpp:390
void probeCard(const QString &device)
bool canDelete(void) override
void DeleteAllCaptureCards(bool)
void setValue(const QString &) override
VBIDevice(const CaptureCard &parent)
ASIConfigurationGroup(CaptureCard &parent, CardType &cardType)
void reload(void)
ButtonStandardSetting * m_srcFetch
Definition: videosource.h:816
QString m_cardName
static QString GetRawInputType(uint inputid)
Definition: cardutil.h:271
CaptureCard & m_parent
Definition: videosource.h:507
CaptureCardTextEditSetting(const CaptureCard &parent, const QString &setting)
void Save(void) override
void fillSelectionsFromDir(const QDir &dir, bool absPath=true)
TransTextEditSetting * m_info
Definition: videosource.h:508
void UpdateDevices(const QString &)
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:98
ExternalChannelCommand(const CardInput &parent)
QString m_ip
Definition: videosource.h:955
int getSourceID(void) const
Definition: videosource.h:166
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
static bool GetListingsLoginData(uint sourceid, QString &grabber, QString &userid, QString &passwd, QString &lineupid)
Definition: sourceutil.cpp:144
HDPVRConfigurationGroup(CaptureCard &parent, CardType &cardtype)
ASIDevice * m_device
Definition: videosource.h:492
QString m_oldValue
Definition: videosource.h:846
void Save(void) override
int getInputID(void) const
QString m_tuner
Definition: videosource.h:916
static bool LinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1889
FirewireGUID(const CaptureCard &parent)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
Screen in which all other widgets are contained and rendered.
void reloadDiseqcTree(const QString &device)
StartingChannel * m_startChan
Definition: videosource.h:814
void loadByInput(int cardid, const QString &inputname)
TransTextEditSetting * m_cardInfo
Definition: videosource.h:493
bool canDelete(void) override
void Load(void) override
DeviceTree * m_diseqcBtn
Definition: videosource.h:581
FirewireSpeed(const CaptureCard &parent)
static QString ProbeDefaultDeliverySystem(const QString &device)
Definition: cardutil.cpp:660
DVBConfigurationGroup(CaptureCard &a_parent, CardType &cardType)
CaptureCard & m_parent
Definition: videosource.h:569
QString desc
Definition: videosource.h:373
void fillSelectionsFromDir(const QDir &dir, bool absPath=true)
InputGroup * m_inputGrp1
Definition: videosource.h:819
StandardSetting * m_desc
Definition: videosource.h:891
QString GetRawCardType(void) const
static QStringList ProbeDeliverySystems(const QString &device)
Definition: cardutil.cpp:577
QString GetHostName(void)
void Save(void) override
void Save(void) override
const VideoSource & m_parent
DVBCardNum(const CaptureCard &parent)
const CardInput & m_parent
Definition: videosource.h:687
void CreateNewInputGroupSlot(const QString &name)
TransTextEditSetting * m_info
Definition: videosource.h:524
bool HasSlicedVBI(void) const
VBoxDeviceIDList(VBoxDeviceID *deviceid, StandardSetting *desc, VBoxIP *cardip, VBoxTunerIndex *cardtuner, VBoxDeviceList *devicelist, const CaptureCard &parent)
void addTargetedChild(const QString &value, StandardSetting *setting)
DVB-S device tree class.
Definition: diseqc.h:73
uint fillSelectionsFromDir(const QDir &dir, const QString &card, const QString &driver)
QString DriverName(void) const
Definition: v4l2util.h:45
static void fillSelections(MythUIComboBoxSetting *setting)
virtual void setValue(const QString &newValue)
const CardInput & m_cardInput
VBoxDeviceList * m_deviceList
Definition: videosource.h:894
QString CardName(void) const
Definition: v4l2util.h:46
ImportConfigurationGroup(CaptureCard &parent, CardType &cardtype)
void AddNewCard(void)
void SetSourceID(const QString &sourceid)
PresetTuner(const CardInput &parent)
QString GetWhereClause(MSqlBindings &bindings) const override
DVBCardName * m_cardName
Definition: videosource.h:572
void SetOverrideDeviceID(const QString &)
QString GetSetClause(MSqlBindings &bindings) const override
static bool is_grabber_external(const QString &grabber)
Definition: videosource.h:27
CaptureCard & m_parent
Definition: videosource.h:454
static uint CreateDeviceInputGroup(uint inputid, const QString &type, const QString &host, const QString &device)
Definition: cardutil.cpp:1852
static QString GetStartingChannel(uint inputid)
Definition: cardutil.cpp:1690
QString mythdeviceid
Definition: videosource.h:371
int getInputID(void) const
Definition: videosource.h:787
Main DVB-S device interface.
Definition: diseqc.h:50
FreqTableSelector(const VideoSource &parent)
QString m_oldValue
Definition: videosource.h:867
void valueChanged(const QString &)
void loadByID(int id)