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 #include <sys/types.h>
7 #include <sys/stat.h>
8 
9 // C++ headers
10 #include <algorithm>
11 using namespace std;
12 
13 // Qt headers
14 #include <QCoreApplication>
15 #include <QTextStream>
16 #include <QStringList>
17 #include <QCursor>
18 #include <QLayout>
19 #include <QFile>
20 #include <QMap>
21 #include <QDir>
22 #include <QDateTime>
23 
24 // MythTV headers
25 #include "mythconfig.h"
26 #include "mythwidgets.h"
27 #include "mythdialogs.h"
28 #include "mythcorecontext.h"
29 #include "videosource.h"
30 #include "datadirect.h"
31 #include "scanwizard.h"
32 #include "cardutil.h"
33 #include "sourceutil.h"
34 #include "channelinfo.h"
35 #include "channelutil.h"
36 #include "frequencies.h"
37 #include "diseqcsettings.h"
38 #include "firewiredevice.h"
39 #include "compat.h"
40 #include "mythdb.h"
41 #include "mythdirs.h"
42 #include "mythlogging.h"
43 #include "libmythupnp/httprequest.h" // for TestMimeType()
44 #include "mythsystemlegacy.h"
45 #include "exitcodes.h"
46 #include "v4l2util.h"
47 
48 #ifdef USING_DVB
49 #include "dvbtypes.h"
50 #endif
51 
52 #ifdef USING_VBOX
53 #include "vboxutils.h"
54 #endif
55 
56 #ifdef USING_HDHOMERUN
57 #include "hdhomerun.h"
58 #endif
59 
60 static const uint kDefaultMultirecCount = 2;
61 
63  const QString &_card_types,
64  bool _must_have_mplexid) :
65  ComboBoxSetting(this),
66  initial_sourceid(_initial_sourceid),
67  card_types(_card_types),
68  must_have_mplexid(_must_have_mplexid)
69 {
70  card_types.detach();
71  setLabel(tr("Video Source"));
72 }
73 
75 {
77 
78  QString querystr =
79  "SELECT DISTINCT videosource.name, videosource.sourceid "
80  "FROM capturecard, videosource";
81 
82  querystr += (must_have_mplexid) ? ", channel " : " ";
83 
84  querystr +=
85  "WHERE capturecard.sourceid = videosource.sourceid AND "
86  " capturecard.hostname = :HOSTNAME ";
87 
88  if (!card_types.isEmpty())
89  {
90  querystr += QString(" AND capturecard.cardtype in %1 ")
91  .arg(card_types);
92  }
93 
95  {
96  querystr +=
97  " AND channel.sourceid = videosource.sourceid "
98  " AND channel.mplexid != 32767 "
99  " AND channel.mplexid != 0 ";
100  }
101 
102  query.prepare(querystr);
103  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
104 
105  if (!query.exec() || !query.isActive() || query.size() <= 0)
106  return;
107 
108  uint sel = 0, cnt = 0;
109  for (; query.next(); cnt++)
110  {
111  addSelection(query.value(0).toString(),
112  query.value(1).toString());
113 
114  sel = (query.value(1).toUInt() == initial_sourceid) ? cnt : sel;
115  }
116 
117  if (initial_sourceid)
118  {
119  if (cnt)
120  setValue(sel);
121  setEnabled(false);
122  }
123 }
124 
126 {
127  public:
128  InstanceCount(const CardInput &parent, int _initValue) :
129  SpinBoxSetting(this, 1, 10, _initValue),
130  CardInputDBStorage(this, parent, "reclimit")
131  {
132  setLabel(QObject::tr("Max recordings"));
133  setValue(_initValue);
134  setHelpText(
135  QObject::tr(
136  "Maximum number of simultaneous recordings MythTV will "
137  "attempt using this device. If set to a value other than "
138  "1, MythTV can sometimes record multiple programs on "
139  "the same multiplex or overlapping copies of the same "
140  "program on a single channel."
141  ));
142  };
143 };
144 
146 {
147  public:
148  explicit SchedGroup(const CardInput &parent) :
149  CheckBoxSetting(this),
150  CardInputDBStorage(this, parent, "schedgroup")
151  {
152  setLabel(QObject::tr("Schedule as group"));
153  setValue(false);
154  setHelpText(
155  QObject::tr(
156  "Schedule all virtual inputs on this device as a group. "
157  "This is more efficient than scheduling each input "
158  "individually, but can result in scheduling more "
159  "simultaneous recordings than is allowed. Be sure to set "
160  "the maximum number of simultaneous recordings above "
161  "high enough to handle all expected cases."
162  ));
163  };
164 };
165 
167 {
168  QString sourceidTag(":WHERESOURCEID");
169 
170  QString query("sourceid = " + sourceidTag);
171 
172  bindings.insert(sourceidTag, m_parent.getSourceID());
173 
174  return query;
175 }
176 
178 {
179  QString sourceidTag(":SETSOURCEID");
180  QString colTag(":SET" + GetColumnName().toUpper());
181 
182  QString query("sourceid = " + sourceidTag + ", " +
183  GetColumnName() + " = " + colTag);
184 
185  bindings.insert(sourceidTag, m_parent.getSourceID());
186  bindings.insert(colTag, user->GetDBValue());
187 
188  return query;
189 }
190 
192 {
193  QString cardidTag(":WHERECARDID");
194 
195  QString query("cardid = " + cardidTag);
196 
197  bindings.insert(cardidTag, m_parent.getCardID());
198 
199  return query;
200 }
201 
203 {
204  QString cardidTag(":SETCARDID");
205  QString colTag(":SET" + GetColumnName().toUpper());
206 
207  QString query("cardid = " + cardidTag + ", " +
208  GetColumnName() + " = " + colTag);
209 
210  bindings.insert(cardidTag, m_parent.getCardID());
211  bindings.insert(colTag, user->GetDBValue());
212 
213  return query;
214 }
215 
217 {
218  public:
219  explicit XMLTVGrabber(const VideoSource &parent) :
220  ComboBoxSetting(this),
221  VideoSourceDBStorage(this, parent, "xmltvgrabber")
222  {
223  setLabel(QObject::tr("Listings grabber"));
224  };
225 };
226 
228 {
229  public:
230  DVBNetID(const VideoSource &parent, signed int value, signed int min_val) :
231  SpinBoxSetting(this, min_val, 0xffff, 1),
232  VideoSourceDBStorage(this, parent, "dvb_nit_id")
233  {
234  setLabel(QObject::tr("Network ID"));
235  //: Network_ID is the name of an identifier in the DVB's Service
236  //: Information standard specification.
237  setHelpText(QObject::tr("If your provider has asked you to configure a "
238  "specific network identifier (Network_ID), "
239  "enter it here. Leave it at -1 otherwise."));
240  setValue(value);
241  };
242 };
243 
245  ComboBoxSetting(this), VideoSourceDBStorage(this, parent, "freqtable")
246 {
247  setLabel(QObject::tr("Channel frequency table"));
248  addSelection("default");
249 
250  for (uint i = 0; chanlists[i].name; i++)
252 
253  setHelpText(QObject::tr("Use default unless this source uses a "
254  "different frequency table than the system wide table "
255  "defined in the General settings."));
256 }
257 
259  ComboBoxSetting(this), sourceid(_sourceid),
260  loaded_freq_table(QString::null)
261 {
262  setLabel(QObject::tr("Channel frequency table"));
263 
264  for (uint i = 0; chanlists[i].name; i++)
266 }
267 
269 {
270  int idx = getValueIndex(gCoreContext->GetSetting("FreqTable"));
271  if (idx >= 0)
272  setValue(idx);
273 
274  if (!sourceid)
275  return;
276 
277  MSqlQuery query(MSqlQuery::InitCon());
278  query.prepare(
279  "SELECT freqtable "
280  "FROM videosource "
281  "WHERE sourceid = :SOURCEID");
282  query.bindValue(":SOURCEID", sourceid);
283 
284  if (!query.exec() || !query.isActive())
285  {
286  MythDB::DBError("TransFreqTableSelector::load", query);
287  return;
288  }
289 
290  loaded_freq_table = QString::null;
291 
292  if (query.next())
293  {
294  loaded_freq_table = query.value(0).toString();
295  if (!loaded_freq_table.isEmpty() &&
296  (loaded_freq_table.toLower() != "default"))
297  {
298  int idx = getValueIndex(loaded_freq_table);
299  if (idx >= 0)
300  setValue(idx);
301  }
302  }
303 }
304 
306 {
307  LOG(VB_GENERAL, LOG_INFO, "TransFreqTableSelector::Save(void)");
308 
309  if ((loaded_freq_table == getValue()) ||
310  ((loaded_freq_table.toLower() == "default") &&
311  (getValue() == gCoreContext->GetSetting("FreqTable"))))
312  {
313  return;
314  }
315 
316  MSqlQuery query(MSqlQuery::InitCon());
317  query.prepare(
318  "UPDATE videosource "
319  "SET freqtable = :FREQTABLE "
320  "WHERE sourceid = :SOURCEID");
321 
322  query.bindValue(":FREQTABLE", getValue());
323  query.bindValue(":SOURCEID", sourceid);
324 
325  if (!query.exec() || !query.isActive())
326  {
327  MythDB::DBError("TransFreqTableSelector::load", query);
328  return;
329  }
330 }
331 
333 {
334  sourceid = _sourceid;
335  Load();
336 }
337 
339 {
340  public:
341  explicit UseEIT(const VideoSource &parent) :
342  CheckBoxSetting(this), VideoSourceDBStorage(this, parent, "useeit")
343  {
344  setLabel(QObject::tr("Perform EIT scan"));
345  setHelpText(QObject::tr(
346  "If enabled, program guide data for channels on this "
347  "source will be updated with data provided by the "
348  "channels themselves 'Over-the-Air'."));
349  }
350 };
351 
353 {
354  public:
355  explicit DataDirectUserID(const VideoSource &parent) :
356  LineEditSetting(this), VideoSourceDBStorage(this, parent, "userid")
357  {
358  setLabel(QObject::tr("User ID"));
359  }
360 };
361 
363 {
364  public:
365  explicit DataDirectPassword(const VideoSource &parent) :
366  LineEditSetting(this, true),
367  VideoSourceDBStorage(this, parent, "password")
368  {
369  SetPasswordEcho(true);
370  setLabel(QObject::tr("Password"));
371  }
372 };
373 
375  const QString &pwd,
376  int _source)
377 {
378  (void) uid;
379  (void) pwd;
380 #ifdef USING_BACKEND
381  if (uid.isEmpty() || pwd.isEmpty())
382  return;
383 
384  qApp->processEvents();
385 
386  DataDirectProcessor ddp(_source, uid, pwd);
387  QString waitMsg = tr("Fetching lineups from %1...")
388  .arg(ddp.GetListingsProviderName());
389 
390  LOG(VB_GENERAL, LOG_INFO, waitMsg);
391  MythProgressDialog *pdlg = new MythProgressDialog(waitMsg, 2);
392 
393  clearSelections();
394 
395  pdlg->setProgress(1);
396 
397  if (!ddp.GrabLineupsOnly())
398  {
399  LOG(VB_GENERAL, LOG_ERR,
400  "DDLS: fillSelections did not successfully load selections");
401  pdlg->deleteLater();
402  return;
403  }
404  const DDLineupList lineups = ddp.GetLineups();
405 
406  DDLineupList::const_iterator it;
407  for (it = lineups.begin(); it != lineups.end(); ++it)
408  addSelection((*it).displayname, (*it).lineupid);
409 
410  pdlg->setProgress(2);
411  pdlg->Close();
412  pdlg->deleteLater();
413 #else // USING_BACKEND
414  LOG(VB_GENERAL, LOG_ERR,
415  "You must compile the backend to set up a DataDirect line-up");
416 #endif // USING_BACKEND
417 }
418 
420 {
422  bool is_sd_userid = userid->getValue().contains('@') > 0;
423  bool match = ((is_sd_userid && (source == DD_SCHEDULES_DIRECT)) ||
424  (!is_sd_userid && (source == DD_ZAP2IT)));
425  if (((userid->getValue() != lastloadeduserid) ||
426  (password->getValue() != lastloadedpassword)) && match)
427  {
428  lineupselector->fillSelections(userid->getValue(),
429  password->getValue(),
430  source);
431  lastloadeduserid = userid->getValue();
432  lastloadedpassword = password->getValue();
433  }
434 }
435 
436 DataDirect_config::DataDirect_config(const VideoSource& _parent, int _source) :
438  parent(_parent)
439 {
440  source = _source;
441 
443  new HorizontalConfigurationGroup(false, false, true, true);
444 
446  addChild(up);
447 
449  new HorizontalConfigurationGroup(false, false, true, true);
450 
452  lp->addChild(button = new DataDirectButton());
453  addChild(lp);
454 
456  addChild(new UseEIT(parent));
457 
458  connect(button, SIGNAL(pressed()),
459  this, SLOT(fillDataDirectLineupSelector()));
460 }
461 
463 {
466 }
467 
469  QString _grabber) :
471  parent(_parent), grabber(_grabber)
472 {
473  QString filename = QString("%1/%2.xmltv")
474  .arg(GetConfDir()).arg(parent.getSourceName());
475 
476  grabberArgs.push_back("--config-file");
477  grabberArgs.push_back(filename);
478  grabberArgs.push_back("--configure");
479 
480  addChild(new UseEIT(parent));
481 
482  TransButtonSetting *config = new TransButtonSetting();
483  config->setLabel(tr("Configure"));
484  config->setHelpText(tr("Run XMLTV configure command."));
485 
486  addChild(config);
487 
488  connect(config, SIGNAL(pressed()), SLOT(RunConfig()));
489 }
490 
492 {
494 #if 0
495  QString err_msg = QObject::tr(
496  "You MUST run 'mythfilldatabase --manual' the first time,\n"
497  "instead of just 'mythfilldatabase'.\nYour grabber does not provide "
498  "channel numbers, so you have to set them manually.");
499 
501  {
502  LOG(VB_GENERAL, LOG_ERR, err_msg);
504  GetMythMainWindow(), QObject::tr("Warning."), err_msg);
505  }
506 #endif
507 }
508 
510 {
512  tw->exec(false, true);
513  delete tw;
514 }
515 
518 {
519  useeit = new UseEIT(_parent);
520  useeit->setValue(true);
521  useeit->setVisible(false);
522  addChild(useeit);
523 
525  label=new TransLabelSetting();
526  label->setValue(QObject::tr("Use only the transmitted guide data."));
527  addChild(label);
528  label=new TransLabelSetting();
529  label->setValue(
530  QObject::tr("This will usually only work with ATSC or DVB channels,"));
531  addChild(label);
532  label=new TransLabelSetting();
533  label->setValue(
534  QObject::tr("and generally provides data only for the next few days."));
535  addChild(label);
536 }
537 
539 {
540  // Force this value on
541  useeit->setValue(true);
542  useeit->Save();
543 }
544 
547 {
548  useeit = new UseEIT(_parent);
549  useeit->setValue(false);
550  useeit->setVisible(false);
551  addChild(useeit);
552 
554  label->setValue(QObject::tr("Do not configure a grabber"));
555  addChild(label);
556 }
557 
559 {
560  useeit->setValue(false);
561  useeit->Save();
562 }
563 
564 
567  parent(aparent), grabber(new XMLTVGrabber(parent))
568 {
569  addChild(grabber);
571 
572  // only save settings for the selected grabber
573  setSaveAll(false);
574 
575 }
576 
578 {
579  addTarget("schedulesdirect1",
581  addTarget("eitonly", new EITOnly_config(parent));
582  addTarget("/bin/true", new NoGrabber_config(parent));
583 
585  QObject::tr("North America (SchedulesDirect.org) (Internal)"),
586  "schedulesdirect1");
587 
589  QObject::tr("Transmitted guide only (EIT)"), "eitonly");
590 
591  grabber->addSelection(QObject::tr("No grabber"), "/bin/true");
592 
593 
594  QString validValues;
595  validValues += "schedulesdirect1";
596  validValues += "eitonly";
597  validValues += "/bin/true";
598 
599  QString gname, d1, d2, d3;
601 
602 #ifdef _MSC_VER
603  #pragma message( "tv_find_grabbers is not supported yet on windows." )
604  //-=>TODO:Screen doesn't show up if the call to MythSysemLegacy is executed
605 #else
606 
607  QString loc = "XMLTVConfig::Load: ";
608  QString loc_err = "XMLTVConfig::Load, Error: ";
609 
610  QStringList name_list;
611  QStringList prog_list;
612 
613  QStringList args;
614  args += "baseline";
615 
616  MythSystemLegacy find_grabber_proc("tv_find_grabbers", args,
618  find_grabber_proc.Run(25);
619  LOG(VB_GENERAL, LOG_INFO,
620  loc + "Running 'tv_find_grabbers " + args.join(" ") + "'.");
621  uint status = find_grabber_proc.Wait();
622 
623  if (status == GENERIC_EXIT_OK)
624  {
625  QTextStream ostream(find_grabber_proc.ReadAll());
626  while (!ostream.atEnd())
627  {
628  QString grabber_list(ostream.readLine());
629  QStringList grabber_split =
630  grabber_list.split("|", QString::SkipEmptyParts);
631  QString grabber_name = grabber_split[1] + " (xmltv)";
632  QFileInfo grabber_file(grabber_split[0]);
633 
634  name_list.push_back(grabber_name);
635  prog_list.push_back(grabber_file.fileName());
636  LOG(VB_GENERAL, LOG_DEBUG, "Found " + grabber_split[0]);
637  }
638  LOG(VB_GENERAL, LOG_INFO, loc + "Finished running tv_find_grabbers");
639  }
640  else
641  LOG(VB_GENERAL, LOG_ERR, loc + "Failed to run tv_find_grabbers");
642 
643  LoadXMLTVGrabbers(name_list, prog_list);
644 #endif
645 
647 
648 }
649 
651  QStringList name_list, QStringList prog_list)
652 {
653  if (name_list.size() != prog_list.size())
654  return;
655 
656  QString selValue = grabber->getValue();
657  int selIndex = grabber->getValueIndex(selValue);
658  grabber->setValue(0);
659 
660  QString validValues;
661  validValues += "schedulesdirect1";
662  validValues += "eitonly";
663  validValues += "/bin/true";
664 
665  for (uint i = 0; i < grabber->size(); i++)
666  {
667  if (!validValues.contains(grabber->GetValue(i)))
668  {
670  i--;
671  }
672  }
673 
674  for (uint i = 0; i < (uint) name_list.size(); i++)
675  {
676  addTarget(prog_list[i],
677  new XMLTV_generic_config(parent, prog_list[i]));
678  grabber->addSelection(name_list[i], prog_list[i]);
679  }
680 
681  if (!selValue.isEmpty())
682  selIndex = grabber->getValueIndex(selValue);
683  if (selIndex >= 0)
684  grabber->setValue(selIndex);
685 
686 }
687 
689 {
691  MSqlQuery query(MSqlQuery::InitCon());
692  query.prepare(
693  "UPDATE videosource "
694  "SET userid=NULL, password=NULL "
695  "WHERE xmltvgrabber NOT IN ( 'datadirect', 'technovera', "
696  " 'schedulesdirect1' )");
697  if (!query.exec())
698  MythDB::DBError("XMLTVConfig::Save", query);
699 }
700 
702 {
703  // must be first
704  addChild(id = new ID());
705 
706  ConfigurationGroup *group = new VerticalConfigurationGroup(false, false);
707  group->setLabel(QObject::tr("Video Source Setup"));
708  group->addChild(name = new Name(*this));
709  group->addChild(xmltv = new XMLTVConfig(*this));
710  group->addChild(new FreqTableSelector(*this));
711  group->addChild(new DVBNetID(*this, -1, -1));
712  addChild(group);
713 }
714 
715 bool VideoSourceEditor::cardTypesInclude(const int &sourceID,
716  const QString &thecardtype)
717 {
718  MSqlQuery query(MSqlQuery::InitCon());
719  query.prepare("SELECT count(cardtype)"
720  " FROM capturecard "
721  " WHERE capturecard.sourceid = :SOURCEID "
722  " AND capturecard.cardtype = :CARDTYPE ;");
723  query.bindValue(":SOURCEID", sourceID);
724  query.bindValue(":CARDTYPE", thecardtype);
725 
726  if (query.exec() && query.next())
727  {
728  int count = query.value(0).toInt();
729 
730  if (count > 0)
731  return true;
732  }
733 
734  return false;
735 }
736 
738 {
739  MSqlQuery result(MSqlQuery::InitCon());
740  result.prepare("SELECT name, sourceid FROM videosource;");
741 
742  if (result.exec() && result.isActive() && result.size() > 0)
743  {
744  while (result.next())
745  {
746  setting->addSelection(result.value(0).toString(),
747  result.value(1).toString());
748  }
749  }
750 }
751 
752 void VideoSource::loadByID(int sourceid)
753 {
754  id->setValue(sourceid);
755 }
756 
758 {
759  public:
761  uint minor_min = 0,
762  uint minor_max = UINT_MAX,
763  QString card = QString::null,
764  QString driver = QString::null) :
765  PathSetting(this, true),
766  CaptureCardDBStorage(this, parent, "videodevice")
767  {
768  setLabel(QObject::tr("Video device"));
769 
770  // /dev/v4l/video*
771  QDir dev("/dev/v4l", "video*", QDir::Name, QDir::System);
772  fillSelectionsFromDir(dev, minor_min, minor_max,
773  card, driver, false);
774 
775  // /dev/video*
776  dev.setPath("/dev");
777  fillSelectionsFromDir(dev, minor_min, minor_max,
778  card, driver, false);
779 
780  // /dev/dtv/video*
781  dev.setPath("/dev/dtv");
782  fillSelectionsFromDir(dev, minor_min, minor_max,
783  card, driver, false);
784 
785  // /dev/dtv*
786  dev.setPath("/dev");
787  dev.setNameFilters(QStringList("dtv*"));
788  fillSelectionsFromDir(dev, minor_min, minor_max,
789  card, driver, false);
790  };
791 
792  void fillSelectionsFromDir(const QDir &dir, bool absPath = true)
793  {
794  fillSelectionsFromDir(dir, 0, 255, QString::null, QString::null, false);
795  }
796 
797  uint fillSelectionsFromDir(const QDir& dir,
798  uint minor_min, uint minor_max,
799  QString card, QString driver,
800  bool allow_duplicates)
801  {
802  uint cnt = 0;
803 
804  QFileInfoList il = dir.entryInfoList();
805  QRegExp *driverExp = NULL;
806  if (!driver.isEmpty())
807  driverExp = new QRegExp(driver);
808 
809  for( QFileInfoList::iterator it = il.begin();
810  it != il.end();
811  ++it )
812  {
813  QFileInfo &fi = *it;
814 
815  struct stat st;
816  QString filepath = fi.absoluteFilePath();
817  int err = lstat(filepath.toLocal8Bit().constData(), &st);
818 
819  if (err)
820  {
821  LOG(VB_GENERAL, LOG_ERR,
822  QString("Could not stat file: %1").arg(filepath));
823  continue;
824  }
825 
826  // is this is a character device?
827  if (!S_ISCHR(st.st_mode))
828  continue;
829 
830  // is this device is in our minor range?
831  uint minor_num = minor(st.st_rdev);
832  if (minor_min > minor_num || minor_max < minor_num)
833  continue;
834 
835  // ignore duplicates if allow_duplicates not set
836  if (!allow_duplicates && minor_list[minor_num])
837  continue;
838 
839  // if the driver returns any info add this device to our list
840  QByteArray tmp = filepath.toLatin1();
841  int videofd = open(tmp.constData(), O_RDWR);
842  if (videofd >= 0)
843  {
844  QString card_name, driver_name;
845  if (CardUtil::GetV4LInfo(videofd, card_name, driver_name) &&
846  (!driverExp || (driverExp->exactMatch(driver_name))) &&
847  (card.isEmpty() || (card_name == card)))
848  {
849  addSelection(filepath);
850  cnt++;
851  }
852  close(videofd);
853  }
854 
855  // add to list of minors discovered to avoid duplicates
856  minor_list[minor_num] = 1;
857  }
858  delete driverExp;
859 
860  return cnt;
861  }
862 
863  QString Driver(void) const { return driver_name; }
864  QString Card(void) const { return card_name; }
865 
866  private:
867  QMap<uint, uint> minor_list;
868  QString card_name;
869  QString driver_name;
870 };
871 
873 {
874  public:
875  explicit VBIDevice(const CaptureCard &parent) :
876  PathSetting(this, true),
877  CaptureCardDBStorage(this, parent, "vbidevice")
878  {
879  setLabel(QObject::tr("VBI device"));
880  setFilter(QString::null, QString::null);
881  setHelpText(QObject::tr("Device to read VBI (captions) from."));
882  };
883 
884  void setFilter(const QString &card, const QString &driver)
885  {
886  clearSelections();
887  QDir dev("/dev/v4l", "vbi*", QDir::Name, QDir::System);
888  if (!fillSelectionsFromDir(dev, card, driver))
889  {
890  dev.setPath("/dev");
891  if (!fillSelectionsFromDir(dev, card, driver) &&
892  !getValue().isEmpty())
893  {
894  addSelection(getValue(),getValue(),true);
895  }
896  }
897  }
898 
899  void fillSelectionsFromDir(const QDir &dir, bool absPath = true)
900  {
901  fillSelectionsFromDir(dir, QString::null, QString::null);
902  }
903 
904  uint fillSelectionsFromDir(const QDir &dir, const QString &card,
905  const QString &driver)
906  {
907  QStringList devices;
908  QFileInfoList il = dir.entryInfoList();
909  for( QFileInfoList::iterator it = il.begin();
910  it != il.end();
911  ++it )
912  {
913  QFileInfo &fi = *it;
914 
915  QString device = fi.absoluteFilePath();
916  QByteArray adevice = device.toLatin1();
917  int vbifd = open(adevice.constData(), O_RDWR);
918  if (vbifd < 0)
919  continue;
920 
921  QString cn, dn;
922  if (CardUtil::GetV4LInfo(vbifd, cn, dn) &&
923  (driver.isEmpty() || (dn == driver)) &&
924  (card.isEmpty() || (cn == card)))
925  {
926  devices.push_back(device);
927  }
928 
929  close(vbifd);
930  }
931 
932  QString sel = getValue();
933  for (uint i = 0; i < (uint) devices.size(); i++)
934  addSelection(devices[i], devices[i], devices[i] == sel);
935 
936  return (uint) devices.size();
937  }
938 };
939 
941 {
942  public:
943  explicit ArgumentString(const CaptureCard &parent) :
944  LineEditSetting(this, true),
945  CaptureCardDBStorage(this, parent, "audiodevice") // change to arguments
946  {
947  setLabel(QObject::tr("Arguments"));
948  }
949 };
950 
952 {
953  public:
954  explicit FileDevice(const CaptureCard &parent) :
955  PathSetting(this, false),
956  CaptureCardDBStorage(this, parent, "videodevice")
957  {
958  setLabel(QObject::tr("File path"));
959  };
960 };
961 
963 {
964  public:
965  explicit AudioDevice(const CaptureCard &parent) :
966  PathSetting(this, false),
967  CaptureCardDBStorage(this, parent, "audiodevice")
968  {
969  setLabel(QObject::tr("Audio device"));
970 #if USING_OSS
971  QDir dev("/dev", "dsp*", QDir::Name, QDir::System);
973  dev.setPath("/dev/sound");
975 #endif
976 #if USING_ALSA
977  addSelection("ALSA:default", "ALSA:default");
978 #endif
979  addSelection(QObject::tr("(None)"), "NULL");
980  setHelpText(QObject::tr("Device to read audio from, "
981  "if audio is separate from the video."));
982  };
983 };
984 
986 {
987  public:
989  SpinBoxSetting(this, min_val, 60000, 250),
990  CaptureCardDBStorage(this, parent, "signal_timeout")
991  {
992  setLabel(QObject::tr("Signal timeout (ms)"));
993  setValue(value);
994  setHelpText(QObject::tr(
995  "Maximum time (in milliseconds) MythTV waits for "
996  "a signal when scanning for channels."));
997  };
998 };
999 
1001 {
1002  public:
1004  SpinBoxSetting(this, min_val, 65000, 250),
1005  CaptureCardDBStorage(this, parent, "channel_timeout")
1006  {
1007  setLabel(QObject::tr("Tuning timeout (ms)"));
1008  setValue(value);
1009  setHelpText(QObject::tr(
1010  "Maximum time (in milliseconds) MythTV waits for "
1011  "a channel lock. For recordings, if this time is "
1012  "exceeded, the recording will be marked as failed."));
1013  };
1014 };
1015 
1017 {
1018  public:
1019  explicit AudioRateLimit(const CaptureCard &parent) :
1020  ComboBoxSetting(this),
1021  CaptureCardDBStorage(this, parent, "audioratelimit")
1022  {
1023  setLabel(QObject::tr("Force audio sampling rate"));
1024  setHelpText(
1025  QObject::tr("If non-zero, override the audio sampling "
1026  "rate in the recording profile when this card is "
1027  "used. Use this if your capture card does not "
1028  "support all of the standard rates."));
1029  addSelection(QObject::tr("(None)"), "0");
1030  addSelection("32000");
1031  addSelection("44100");
1032  addSelection("48000");
1033  };
1034 };
1035 
1037 {
1038  public:
1039  explicit SkipBtAudio(const CaptureCard &parent) :
1040  CheckBoxSetting(this),
1041  CaptureCardDBStorage(this, parent, "skipbtaudio")
1042  {
1043  setLabel(QObject::tr("Do not adjust volume"));
1044  setHelpText(
1045  QObject::tr("Enable this option for budget BT878 based "
1046  "DVB-T cards such as the AverTV DVB-T which "
1047  "require the audio volume to be left alone."));
1048  };
1049 };
1050 
1052 {
1053  public:
1054  explicit DVBCardNum(const CaptureCard &parent) :
1055  PathSetting(this, true),
1056  CaptureCardDBStorage(this, parent, "videodevice")
1057  {
1058  setLabel(QObject::tr("DVB device"));
1059  setHelpText(
1060  QObject::tr("When you change this setting, the text below "
1061  "should change to the name and type of your card. "
1062  "If the card cannot be opened, an error message "
1063  "will be displayed."));
1064  fillSelections(QString::null);
1065  };
1066 
1070  void fillSelections(const QString &current)
1071  {
1072  clearSelections();
1073 
1074  // Get devices from filesystem
1075  QStringList sdevs = CardUtil::ProbeVideoDevices("DVB");
1076 
1077  // Add current if needed
1078  if (!current.isEmpty() &&
1079  (find(sdevs.begin(), sdevs.end(), current) == sdevs.end()))
1080  {
1081  stable_sort(sdevs.begin(), sdevs.end());
1082  }
1083 
1084  QStringList db = CardUtil::GetVideoDevices("DVB");
1085 
1086  QMap<QString,bool> in_use;
1087  QString sel = current;
1088  for (uint i = 0; i < (uint)sdevs.size(); i++)
1089  {
1090  const QString dev = sdevs[i];
1091  in_use[sdevs[i]] = find(db.begin(), db.end(), dev) != db.end();
1092  if (sel.isEmpty() && !in_use[sdevs[i]])
1093  sel = dev;
1094  }
1095 
1096  if (sel.isEmpty() && sdevs.size())
1097  sel = sdevs[0];
1098 
1099  QString usestr = QString(" -- ");
1100  usestr += QObject::tr("Warning: already in use");
1101 
1102  for (uint i = 0; i < (uint)sdevs.size(); i++)
1103  {
1104  const QString dev = sdevs[i];
1105  QString desc = dev + (in_use[sdevs[i]] ? usestr : "");
1106  desc = (current == sdevs[i]) ? dev : desc;
1107  addSelection(desc, dev, dev == sel);
1108  }
1109  }
1110 
1111  virtual void Load(void)
1112  {
1113  clearSelections();
1114  addSelection(QString::null);
1115 
1117 
1119  fillSelections(dev);
1120  }
1121 };
1122 
1124 {
1125  public:
1127  {
1128  setLabel(QObject::tr("Subtype"));
1129  };
1130 };
1131 
1133 {
1134  public:
1136  {
1137  setLabel(QObject::tr("Frontend ID"));
1138  };
1139 };
1140 
1142 {
1143  public:
1144  explicit DVBNoSeqStart(const CaptureCard &parent) :
1145  CheckBoxSetting(this),
1146  CaptureCardDBStorage(this, parent, "dvb_wait_for_seqstart")
1147  {
1148  setLabel(QObject::tr("Wait for SEQ start header."));
1149  setValue(true);
1150  setHelpText(
1151  QObject::tr("If enabled, drop packets from the start of a DVB "
1152  "recording until a sequence start header is seen."));
1153  };
1154 };
1155 
1157 {
1158  public:
1159  explicit DVBOnDemand(const CaptureCard &parent) :
1160  CheckBoxSetting(this),
1161  CaptureCardDBStorage(this, parent, "dvb_on_demand")
1162  {
1163  setLabel(QObject::tr("Open DVB card on demand"));
1164  setValue(true);
1165  setHelpText(
1166  QObject::tr("If enabled, only open the DVB card when required, "
1167  "leaving it free for other programs at other times."));
1168  };
1169 };
1170 
1172 {
1173  public:
1174  explicit DVBEITScan(const CaptureCard &parent) :
1175  CheckBoxSetting(this),
1176  CaptureCardDBStorage(this, parent, "dvb_eitscan")
1177  {
1178  setLabel(QObject::tr("Use DVB card for active EIT scan"));
1179  setValue(true);
1180  setHelpText(
1181  QObject::tr("If enabled, activate active scanning for "
1182  "program data (EIT). When this option is enabled "
1183  "the DVB card is constantly in-use."));
1184  };
1185 };
1186 
1188 {
1189  public:
1190  explicit DVBTuningDelay(const CaptureCard &parent) :
1191  SpinBoxSetting(this, 0, 2000, 25),
1192  CaptureCardDBStorage(this, parent, "dvb_tuning_delay")
1193  {
1194  setLabel(QObject::tr("DVB tuning delay (ms)"));
1195  setValue(true);
1196  setHelpText(
1197  QObject::tr("Some Linux DVB drivers, in particular for the "
1198  "Hauppauge Nova-T, require that we slow down "
1199  "the tuning process by specifying a delay "
1200  "(in milliseconds)."));
1201  };
1202 };
1203 
1205 {
1206  public:
1207  explicit FirewireGUID(const CaptureCard &parent) :
1208  ComboBoxSetting(this),
1209  CaptureCardDBStorage(this, parent, "videodevice")
1210  {
1211  setLabel(QObject::tr("GUID"));
1212 #ifdef USING_FIREWIRE
1213  vector<AVCInfo> list = FirewireDevice::GetSTBList();
1214  for (uint i = 0; i < list.size(); i++)
1215  {
1216  QString guid = list[i].GetGUIDString();
1217  guid_to_avcinfo[guid] = list[i];
1218  addSelection(guid);
1219  }
1220 #endif // USING_FIREWIRE
1221  }
1222 
1223  AVCInfo GetAVCInfo(const QString &guid) const
1224  { return guid_to_avcinfo[guid]; }
1225 
1226  private:
1227  QMap<QString,AVCInfo> guid_to_avcinfo;
1228 };
1229 
1231  const FirewireGUID *_guid) :
1232  ComboBoxSetting(this),
1233  CaptureCardDBStorage(this, parent, "firewire_model"),
1234  guid(_guid)
1235 {
1236  setLabel(QObject::tr("Cable box model"));
1237  addSelection(QObject::tr("Motorola Generic"), "MOTO GENERIC");
1238  addSelection(QObject::tr("SA/Cisco Generic"), "SA GENERIC");
1239  addSelection("DCH-3200");
1240  addSelection("DCX-3200");
1241  addSelection("DCT-3412");
1242  addSelection("DCT-3416");
1243  addSelection("DCT-6200");
1244  addSelection("DCT-6212");
1245  addSelection("DCT-6216");
1246  addSelection("QIP-6200");
1247  addSelection("QIP-7100");
1248  addSelection("PACE-550");
1249  addSelection("PACE-779");
1250  addSelection("SA3250HD");
1251  addSelection("SA4200HD");
1252  addSelection("SA4250HDC");
1253  addSelection("SA8300HD");
1254  QString help = QObject::tr(
1255  "Choose the model that most closely resembles your set top box. "
1256  "Depending on firmware revision SA4200HD may work better for a "
1257  "SA3250HD box.");
1258  setHelpText(help);
1259 }
1260 
1261 void FirewireModel::SetGUID(const QString &_guid)
1262 {
1263  (void) _guid;
1264 
1265 #ifdef USING_FIREWIRE
1266  AVCInfo info = guid->GetAVCInfo(_guid);
1267  QString model = FirewireDevice::GetModelName(info.vendorid, info.modelid);
1268  setValue(max(getValueIndex(model), 0));
1269 #endif // USING_FIREWIRE
1270 }
1271 
1272 void FirewireDesc::SetGUID(const QString &_guid)
1273 {
1274  (void) _guid;
1275 
1276  setLabel(tr("Description"));
1277 
1278 #ifdef USING_FIREWIRE
1279  QString name = guid->GetAVCInfo(_guid).product_name;
1280  name.replace("Scientific-Atlanta", "SA");
1281  name.replace(", Inc.", "");
1282  name.replace("Explorer(R)", "");
1283  name = name.simplified();
1284  setValue((name.isEmpty()) ? "" : name);
1285 #endif // USING_FIREWIRE
1286 }
1287 
1289 {
1290  public:
1291  explicit FirewireConnection(const CaptureCard &parent) :
1292  ComboBoxSetting(this),
1293  CaptureCardDBStorage(this, parent, "firewire_connection")
1294  {
1295  setLabel(QObject::tr("Connection Type"));
1296  addSelection(QObject::tr("Point to Point"),"0");
1297  addSelection(QObject::tr("Broadcast"),"1");
1298  }
1299 };
1300 
1302 {
1303  public:
1304  explicit FirewireSpeed(const CaptureCard &parent) :
1305  ComboBoxSetting(this),
1306  CaptureCardDBStorage(this, parent, "firewire_speed")
1307  {
1308  setLabel(QObject::tr("Speed"));
1309  addSelection(QObject::tr("100Mbps"),"0");
1310  addSelection(QObject::tr("200Mbps"),"1");
1311  addSelection(QObject::tr("400Mbps"),"2");
1312  addSelection(QObject::tr("800Mbps"),"3");
1313  }
1314 };
1315 
1317 {
1318  public:
1321  parent(a_parent),
1322  dev(new FirewireGUID(parent)),
1323  desc(new FirewireDesc(dev)),
1324  model(new FirewireModel(parent, dev))
1325  {
1326  addChild(dev);
1327  addChild(new EmptyAudioDevice(parent));
1328  addChild(new EmptyVBIDevice(parent));
1329  addChild(desc);
1330  addChild(model);
1331 
1332 #ifdef USING_LINUX_FIREWIRE
1333  addChild(new FirewireConnection(parent));
1334  addChild(new FirewireSpeed(parent));
1335 #endif // USING_LINUX_FIREWIRE
1336 
1337  addChild(new SignalTimeout(parent, 2000, 1000));
1338  addChild(new ChannelTimeout(parent, 9000, 1750));
1339 
1340  model->SetGUID(dev->getValue());
1341  desc->SetGUID(dev->getValue());
1342  connect(dev, SIGNAL(valueChanged(const QString&)),
1343  model, SLOT( SetGUID( const QString&)));
1344  connect(dev, SIGNAL(valueChanged(const QString&)),
1345  desc, SLOT( SetGUID( const QString&)));
1346  };
1347 
1348  private:
1353 };
1354 
1355 // -----------------------
1356 // HDHomeRun Configuration
1357 // -----------------------
1358 
1360 {
1361  setLabel(QObject::tr("IP Address"));
1362  setEnabled(false);
1363  connect(this, SIGNAL(valueChanged( const QString&)),
1364  this, SLOT( UpdateDevices(const QString&)));
1365  _oldValue="";
1366 };
1367 
1369 {
1371  if (e)
1372  {
1373  if (!_oldValue.isEmpty())
1374  setValue(_oldValue);
1375  emit NewIP(getValue());
1376  }
1377  else
1378  {
1379  _oldValue = getValue();
1380  _oldValue.detach();
1381  }
1382 }
1383 
1384 void HDHomeRunIP::UpdateDevices(const QString &v)
1385 {
1386  if (isEnabled())
1387  {
1388 #if 0
1389  LOG(VB_GENERAL, LOG_DEBUG, QString("Emitting NewIP(%1)").arg(v));
1390 #endif
1391  emit NewIP(v);
1392  }
1393 }
1394 
1396 {
1397  setLabel(QObject::tr("Tuner"));
1398  setEnabled(false);
1399  connect(this, SIGNAL(valueChanged( const QString&)),
1400  this, SLOT( UpdateDevices(const QString&)));
1401  _oldValue = "";
1402 };
1403 
1405 {
1407  if (e) {
1408  if (!_oldValue.isEmpty())
1409  setValue(_oldValue);
1410  emit NewTuner(getValue());
1411  }
1412  else
1413  {
1414  _oldValue = getValue();
1415  }
1416 }
1417 
1419 {
1420  if (isEnabled())
1421  {
1422 #if 0
1423  LOG(VB_GENERAL, LOG_DEBUG, QString("Emitting NewTuner(%1)").arg(v));
1424 #endif
1425  emit NewTuner(v);
1426  }
1427 }
1428 
1430  LabelSetting(this),
1431  CaptureCardDBStorage(this, parent, "videodevice"),
1432  _ip(QString::null),
1433  _tuner(QString::null),
1434  _overridedeviceid(QString::null)
1435 {
1436  setLabel(tr("Device ID"));
1437  setHelpText(tr("Device ID of HDHomeRun device"));
1438 }
1439 
1440 void HDHomeRunDeviceID::SetIP(const QString &ip)
1441 {
1442 #if 0
1443  LOG(VB_GENERAL, LOG_DEBUG, QString("Setting IP to %1").arg(ip));
1444 #endif
1445  _ip = ip;
1446  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1447 #if 0
1448  LOG(VB_GENERAL, LOG_DEBUG, QString("Done Setting IP to %1").arg(ip));
1449 #endif
1450 }
1451 
1452 void HDHomeRunDeviceID::SetTuner(const QString &tuner)
1453 {
1454 #if 0
1455  LOG(VB_GENERAL, LOG_DEBUG, QString("Setting Tuner to %1").arg(tuner));
1456 #endif
1457  _tuner = tuner;
1458  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1459 #if 0
1460  LOG(VB_GENERAL, LOG_DEBUG, QString("Done Setting Tuner to %1").arg(tuner));
1461 #endif
1462 }
1463 
1464 void HDHomeRunDeviceID::SetOverrideDeviceID(const QString &deviceid)
1465 {
1466  _overridedeviceid = deviceid;
1467  setValue(deviceid);
1468 }
1469 
1471 {
1473  if (!_overridedeviceid.isEmpty())
1474  {
1476  _overridedeviceid = QString::null;
1477  }
1478 }
1479 
1481  HDHomeRunDeviceID *deviceid,
1482  TransLabelSetting *desc,
1483  HDHomeRunIP *cardip,
1484  HDHomeRunTunerIndex *cardtuner,
1485  HDHomeRunDeviceList *devicelist) :
1486  _deviceid(deviceid),
1487  _desc(desc),
1488  _cardip(cardip),
1489  _cardtuner(cardtuner),
1490  _devicelist(devicelist)
1491 {
1492  setLabel(QObject::tr("Available devices"));
1493  setHelpText(
1494  QObject::tr(
1495  "Device ID and Tuner Number of available HDHomeRun devices."));
1496 
1497  connect(this, SIGNAL(valueChanged( const QString&)),
1498  this, SLOT( UpdateDevices(const QString&)));
1499 
1500  _oldValue = "";
1501 };
1502 
1507 {
1508  clearSelections();
1509 
1510  vector<QString> devs;
1511  QMap<QString, bool> in_use;
1512 
1513  QString current = cur;
1514 
1515 #if 0
1516  LOG(VB_GENERAL, LOG_DEBUG, QString("Filling List, current = '%1'")
1517  .arg(current));
1518 #endif
1519 
1520  HDHomeRunDeviceList::iterator it = _devicelist->begin();
1521  for (; it != _devicelist->end(); ++it)
1522  {
1523  if ((*it).discovered)
1524  {
1525  devs.push_back(it.key());
1526  in_use[it.key()] = (*it).inuse;
1527  }
1528  }
1529 
1530  QString man_addr = HDHomeRunDeviceIDList::tr("Manually Enter IP Address");
1531  QString sel = man_addr;
1532  devs.push_back(sel);
1533 
1534  if (3 == devs.size() && current.startsWith("FFFFFFFF", Qt::CaseInsensitive))
1535  {
1536  current = sel = (current.endsWith("0")) ?
1537  *(devs.begin()) : *(++devs.begin());
1538  }
1539  else
1540  {
1541  vector<QString>::const_iterator it = devs.begin();
1542  for (; it != devs.end(); ++it)
1543  sel = (current == *it) ? *it : sel;
1544  }
1545 
1546  QString usestr = QString(" -- ");
1547  usestr += QObject::tr("Warning: already in use");
1548 
1549  for (uint i = 0; i < devs.size(); i++)
1550  {
1551  const QString dev = devs[i];
1552  QString desc = dev + (in_use[devs[i]] ? usestr : "");
1553  desc = (current == devs[i]) ? dev : desc;
1554  addSelection(desc, dev, dev == sel);
1555  }
1556 
1557  if (current != cur)
1558  {
1559  _deviceid->SetOverrideDeviceID(current);
1560  }
1561  else if (sel == man_addr && !current.isEmpty())
1562  {
1563  // Populate the proper values for IP address and tuner
1564  QStringList selection = current.split("-");
1565 
1566  _cardip->SetOldValue(selection.first());
1567  _cardtuner->SetOldValue(selection.last());
1568 
1569  _cardip->setValue(selection.first());
1570  _cardtuner->setValue(selection.last());
1571  }
1572 }
1573 
1575 {
1576  clearSelections();
1577 
1579 }
1580 
1582 {
1583 #if 0
1584  LOG(VB_GENERAL, LOG_DEBUG, QString("Got signal with %1").arg(v));
1585 #endif
1586  if (v == HDHomeRunDeviceIDList::tr("Manually Enter IP Address"))
1587  {
1588  _cardip->setEnabled(true);
1589  _cardtuner->setEnabled(true);
1590 #if 0
1591  LOG(VB_GENERAL, LOG_DEBUG, "Done");
1592 #endif
1593  }
1594  else if (!v.isEmpty())
1595  {
1596  if (_oldValue == HDHomeRunDeviceIDList::tr("Manually Enter IP Address"))
1597  {
1598  _cardip->setEnabled(false);
1599  _cardtuner->setEnabled(false);
1600  }
1601  _deviceid->setValue(v);
1602 
1603  // Update _cardip and cardtuner
1604  _cardip->setValue((*_devicelist)[v].cardip);
1605  _cardtuner->setValue(QString("%1").arg((*_devicelist)[v].cardtuner));
1606  _desc->setValue((*_devicelist)[v].desc);
1607  }
1608  _oldValue = v;
1609 };
1610 
1611 // -----------------------
1612 // VBOX Configuration
1613 // -----------------------
1614 
1616 {
1617  setLabel(QObject::tr("IP Address"));
1618  setHelpText(QObject::tr("Device IP or ID of a VBox device. eg. '192.168.1.100' or 'vbox_3718'"));
1619  setEnabled(false);
1620  connect(this, SIGNAL(valueChanged(const QString&)),
1621  this, SLOT(UpdateDevices(const QString&)));
1622  _oldValue="";
1623 };
1624 
1626 {
1628  if (e)
1629  {
1630  if (!_oldValue.isEmpty())
1632  emit NewIP(getValue());
1633  }
1634  else
1635  {
1636  _oldValue = getValue();
1637  _oldValue.detach();
1638  }
1639 }
1640 
1641 void VBoxIP::UpdateDevices(const QString &v)
1642 {
1643  if (isEnabled())
1644  emit NewIP(v);
1645 }
1646 
1648 {
1649  setLabel(QObject::tr("Tuner"));
1650  setHelpText(QObject::tr("Number and type of the tuner to use. eg '1-DVBT/T2'."));
1651  setEnabled(false);
1652  connect(this, SIGNAL(valueChanged(const QString&)),
1653  this, SLOT(UpdateDevices(const QString&)));
1654  _oldValue = "";
1655 };
1656 
1658 {
1660  if (e) {
1661  if (!_oldValue.isEmpty())
1663  emit NewTuner(getValue());
1664  }
1665  else
1666  {
1667  _oldValue = getValue();
1668  }
1669 }
1670 
1671 void VBoxTunerIndex::UpdateDevices(const QString &v)
1672 {
1673  if (isEnabled())
1674  emit NewTuner(v);
1675 }
1676 
1678  LabelSetting(this),
1679  CaptureCardDBStorage(this, parent, "videodevice"),
1680  _ip(QString::null),
1681  _tuner(QString::null),
1682  _overridedeviceid(QString::null)
1683 {
1684  setLabel(tr("Device ID"));
1685  setHelpText(tr("Device ID of VBox device"));
1686 }
1687 
1688 void VBoxDeviceID::SetIP(const QString &ip)
1689 {
1690  _ip = ip;
1691  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1692 }
1693 
1694 void VBoxDeviceID::SetTuner(const QString &tuner)
1695 {
1696  _tuner = tuner;
1697  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1698 }
1699 
1700 void VBoxDeviceID::SetOverrideDeviceID(const QString &deviceid)
1701 {
1702  _overridedeviceid = deviceid;
1703  setValue(deviceid);
1704 }
1705 
1707 {
1709  if (!_overridedeviceid.isEmpty())
1710  {
1712  _overridedeviceid = QString::null;
1713  }
1714 }
1715 
1717  VBoxDeviceID *deviceid,
1718  TransLabelSetting *desc,
1719  VBoxIP *cardip,
1720  VBoxTunerIndex *cardtuner,
1721  VBoxDeviceList *devicelist) :
1722  _deviceid(deviceid),
1723  _desc(desc),
1724  _cardip(cardip),
1725  _cardtuner(cardtuner),
1726  _devicelist(devicelist)
1727 {
1728  setLabel(QObject::tr("Available devices"));
1729  setHelpText(
1730  QObject::tr(
1731  "Device IP or ID, tuner number and tuner type of available VBox devices."));
1732 
1733  connect(this, SIGNAL(valueChanged(const QString&)),
1734  this, SLOT(UpdateDevices(const QString&)));
1735 
1736  _oldValue = "";
1737 };
1738 
1740 void VBoxDeviceIDList::fillSelections(const QString &cur)
1741 {
1742  clearSelections();
1743 
1744  vector<QString> devs;
1745  QMap<QString, bool> in_use;
1746 
1747  QString current = cur;
1748 
1749  VBoxDeviceList::iterator it = _devicelist->begin();
1750  for (; it != _devicelist->end(); ++it)
1751  {
1752  devs.push_back(it.key());
1753  in_use[it.key()] = (*it).inuse;
1754  }
1755 
1756  QString man_addr = VBoxDeviceIDList::tr("Manually Enter IP Address");
1757  QString sel = man_addr;
1758  devs.push_back(sel);
1759 
1760  vector<QString>::const_iterator it2 = devs.begin();
1761  for (; it2 != devs.end(); ++it2)
1762  sel = (current == *it2) ? *it2 : sel;
1763 
1764  QString usestr = QString(" -- ");
1765  usestr += QObject::tr("Warning: already in use");
1766 
1767  for (uint i = 0; i < devs.size(); i++)
1768  {
1769  const QString dev = devs[i];
1770  QString desc = dev + (in_use[devs[i]] ? usestr : "");
1771  addSelection(desc, dev, dev == sel);
1772  }
1773 
1774  if (current != cur)
1775  {
1776  _deviceid->SetOverrideDeviceID(current);
1777  }
1778  else if (sel == man_addr && !current.isEmpty())
1779  {
1780  // Populate the proper values for IP address and tuner
1781  QStringList selection = current.split("-");
1782 
1783  _cardip->SetOldValue(selection.first());
1784  _cardtuner->SetOldValue(selection.last());
1785 
1786  _cardip->setValue(selection.first());
1787  _cardtuner->setValue(selection.last());
1788  }
1789 }
1790 
1792 {
1793  clearSelections();
1794 
1796 }
1797 
1798 void VBoxDeviceIDList::UpdateDevices(const QString &v)
1799 {
1800  if (v == VBoxDeviceIDList::tr("Manually Enter IP Address"))
1801  {
1802  _cardip->setEnabled(true);
1803  _cardtuner->setEnabled(true);
1804  }
1805  else if (!v.isEmpty())
1806  {
1807  if (_oldValue == VBoxDeviceIDList::tr("Manually Enter IP Address"))
1808  {
1809  _cardip->setEnabled(false);
1810  _cardtuner->setEnabled(false);
1811  }
1812  _deviceid->setValue(v);
1813 
1814  // Update _cardip and _cardtuner
1815  _cardip->setValue((*_devicelist)[v].cardip);
1816  _cardtuner->setValue(QString("%1").arg((*_devicelist)[v].tunerno));
1817  _desc->setValue((*_devicelist)[v].desc);
1818  }
1819  _oldValue = v;
1820 };
1821 
1822 // -----------------------
1823 // IPTV Configuration
1824 // -----------------------
1825 
1827 {
1828  public:
1829  explicit IPTVHost(const CaptureCard &parent) :
1830  LineEditSetting(this),
1831  CaptureCardDBStorage(this, parent, "videodevice")
1832  {
1833  setValue("http://mafreebox.freebox.fr/freeboxtv/playlist.m3u");
1834  setLabel(QObject::tr("M3U URL"));
1835  setHelpText(
1836  QObject::tr("URL of M3U containing RTSP/RTP/UDP channel URLs."));
1837  }
1838 };
1839 
1841 {
1842  public:
1843  explicit IPTVConfigurationGroup(CaptureCard& a_parent) :
1845  parent(a_parent)
1846  {
1847  setUseLabel(false);
1848  addChild(new IPTVHost(parent));
1849  addChild(new ChannelTimeout(parent, 30000, 1750));
1850  addChild(new EmptyAudioDevice(parent));
1851  addChild(new EmptyVBIDevice(parent));
1852  };
1853 
1854  private:
1856 };
1857 
1859 {
1860  public:
1861  explicit ASIDevice(const CaptureCard &parent) :
1862  ComboBoxSetting(this, true),
1863  CaptureCardDBStorage(this, parent, "videodevice")
1864  {
1865  setLabel(QObject::tr("ASI device"));
1866  fillSelections(QString::null);
1867  };
1868 
1872  void fillSelections(const QString &current)
1873  {
1874  clearSelections();
1875 
1876  // Get devices from filesystem
1877  QStringList sdevs = CardUtil::ProbeVideoDevices("ASI");
1878 
1879  // Add current if needed
1880  if (!current.isEmpty() &&
1881  (find(sdevs.begin(), sdevs.end(), current) == sdevs.end()))
1882  {
1883  stable_sort(sdevs.begin(), sdevs.end());
1884  }
1885 
1886  // Get devices from DB
1887  QStringList db = CardUtil::GetVideoDevices("ASI");
1888 
1889  // Figure out which physical devices are already in use
1890  // by another card defined in the DB, and select a device
1891  // for new configs (preferring non-conflicing devices).
1892  QMap<QString,bool> in_use;
1893  QString sel = current;
1894  for (uint i = 0; i < (uint)sdevs.size(); i++)
1895  {
1896  const QString dev = sdevs[i];
1897  in_use[sdevs[i]] = find(db.begin(), db.end(), dev) != db.end();
1898  if (sel.isEmpty() && !in_use[sdevs[i]])
1899  sel = dev;
1900  }
1901 
1902  // Unfortunately all devices are conflicted, select first device.
1903  if (sel.isEmpty() && sdevs.size())
1904  sel = sdevs[0];
1905 
1906  QString usestr = QString(" -- ");
1907  usestr += QObject::tr("Warning: already in use");
1908 
1909  // Add the devices to the UI
1910  bool found = false;
1911  for (uint i = 0; i < (uint)sdevs.size(); i++)
1912  {
1913  const QString dev = sdevs[i];
1914  QString desc = dev + (in_use[sdevs[i]] ? usestr : "");
1915  desc = (current == sdevs[i]) ? dev : desc;
1916  addSelection(desc, dev, dev == sel);
1917  found |= (dev == sel);
1918  }
1919 
1920  // If a configured device isn't on the list, add it with warning
1921  if (!found && !current.isEmpty())
1922  {
1923  QString desc = current + " -- " +
1924  QObject::tr("Warning: unable to open");
1925  addSelection(desc, current, true);
1926  }
1927  }
1928 
1929  virtual void Load(void)
1930  {
1931  clearSelections();
1932  addSelection(QString::null);
1935  }
1936 };
1937 
1940  parent(a_parent),
1941  device(new ASIDevice(parent)),
1942  cardinfo(new TransLabelSetting())
1943 {
1944  addChild(device);
1947  addChild(cardinfo);
1948 
1949  connect(device, SIGNAL(valueChanged(const QString&)),
1950  this, SLOT( probeCard( const QString&)));
1951 
1953 };
1954 
1956 {
1957 #ifdef USING_ASI
1958  if (device.isEmpty())
1959  {
1960  cardinfo->setValue("");
1961  return;
1962  }
1963 
1964  if (parent.getCardID() && parent.GetRawCardType() != "ASI")
1965  {
1966  cardinfo->setValue("");
1967  return;
1968  }
1969 
1970  QString error;
1971  int device_num = CardUtil::GetASIDeviceNumber(device, &error);
1972  if (device_num < 0)
1973  {
1974  cardinfo->setValue(tr("Not a valid DVEO ASI card"));
1975  LOG(VB_GENERAL, LOG_WARNING,
1976  "ASIConfigurationGroup::probeCard(), Warning: " + error);
1977  return;
1978  }
1979  cardinfo->setValue(tr("Valid DVEO ASI card"));
1980 #else
1981  cardinfo->setValue(QString("Not compiled with ASI support"));
1982 #endif
1983 }
1984 
1987  parent(a_parent),
1988  info(new TransLabelSetting()), size(new TransLabelSetting())
1989 {
1990  FileDevice *device = new FileDevice(parent);
1991  device->setHelpText(tr("A local file used to simulate a recording."
1992  " Leave empty to use MythEvents to trigger an"
1993  " external program to import recording files."));
1994  addChild(device);
1995 
1998 
1999  info->setLabel(tr("File info"));
2000  addChild(info);
2001 
2002  size->setLabel(tr("File size"));
2003  addChild(size);
2004 
2005  connect(device, SIGNAL(valueChanged(const QString&)),
2006  this, SLOT( probeCard( const QString&)));
2007 
2008  probeCard(device->getValue());
2009 };
2010 
2011 void ImportConfigurationGroup::probeCard(const QString &device)
2012 {
2013  QString ci, cs;
2014  QFileInfo fileInfo(device);
2015 
2016  // For convenience, ImportRecorder allows both formats:
2017  if (device.toLower().startsWith("file:"))
2018  fileInfo.setFile(device.mid(5));
2019 
2020  if (fileInfo.exists())
2021  {
2022  if (fileInfo.isReadable() && (fileInfo.isFile()))
2023  {
2024  ci = HTTPRequest::TestMimeType(fileInfo.absoluteFilePath());
2025  cs = tr("%1 MB").arg(fileInfo.size() / 1024 / 1024);
2026  }
2027  else
2028  ci = tr("File not readable");
2029  }
2030  else
2031  {
2032  ci = tr("File %1 does not exist").arg(device);
2033  }
2034 
2035  info->setValue(ci);
2036  size->setValue(cs);
2037 }
2038 
2040 {
2041  public:
2043  CheckBoxSetting(this),
2044  CaptureCardDBStorage(this, parent, "dvb_eitscan")
2045  {
2046  setLabel(QObject::tr("Use HD HomeRun for active EIT scan"));
2047  setValue(true);
2048  setHelpText(
2049  QObject::tr("If enabled, activate active scanning for "
2050  "program data (EIT). When this option is enabled "
2051  "the HD HomeRun is constantly in-use."));
2052  };
2053 };
2054 
2056 {
2057  public:
2059 };
2060 
2062 {
2064  rec->setLabel(QObject::tr("Recorder Options"));
2065  rec->setUseLabel(false);
2066 
2067  rec->addChild(new SignalTimeout(parent.parent, 1000, 250));
2068  rec->addChild(new ChannelTimeout(parent.parent, 3000, 1750));
2069  rec->addChild(new HDHomeRunEITScan(parent.parent));
2070 
2071  addChild(rec);
2072 }
2073 
2075  (CaptureCard& a_parent) :
2076  VerticalConfigurationGroup(false, true, false, false),
2077  parent(a_parent)
2078 {
2079  setUseLabel(false);
2080 
2081  // Fill Device list
2082  FillDeviceList();
2083 
2084  deviceid = new HDHomeRunDeviceID(parent);
2085  desc = new TransLabelSetting();
2086  desc->setLabel(tr("Description"));
2087  cardip = new HDHomeRunIP();
2088  cardtuner = new HDHomeRunTunerIndex();
2089  deviceidlist = new HDHomeRunDeviceIDList(
2090  deviceid, desc, cardip, cardtuner, &devicelist);
2091 
2092  addChild(deviceidlist);
2095  addChild(deviceid);
2096  addChild(desc);
2097  addChild(cardip);
2098  addChild(cardtuner);
2099 
2100  TransButtonSetting *buttonRecOpt = new TransButtonSetting();
2101  buttonRecOpt->setLabel(tr("Recording Options"));
2102  addChild(buttonRecOpt);
2103 
2104  connect(buttonRecOpt, SIGNAL(pressed()),
2105  this, SLOT( HDHomeRunExtraPanel()));
2106 
2107  connect(cardip, SIGNAL(NewIP(const QString&)),
2108  deviceid, SLOT( SetIP(const QString&)));
2109  connect(cardtuner, SIGNAL(NewTuner(const QString&)),
2110  deviceid, SLOT( SetTuner(const QString&)));
2111 };
2112 
2114 {
2115  devicelist.clear();
2116 
2117  // Find physical devices first
2118  // ProbeVideoDevices returns "deviceid ip" pairs
2119  QStringList devs = CardUtil::ProbeVideoDevices("HDHOMERUN");
2120 
2121  QStringList::const_iterator it;
2122 
2123  for (it = devs.begin(); it != devs.end(); ++it)
2124  {
2125  QString dev = *it;
2126  QStringList devinfo = dev.split(" ");
2127  QString devid = devinfo.at(0);
2128  QString devip = devinfo.at(1);
2129  QString devtuner = devinfo.at(2);
2130 
2131  HDHomeRunDevice tmpdevice;
2132  tmpdevice.deviceid = devid;
2133  tmpdevice.desc = CardUtil::GetHDHRdesc(devid);
2134  tmpdevice.cardip = devip;
2135  tmpdevice.inuse = false;
2136  tmpdevice.discovered = true;
2137  tmpdevice.cardtuner = devtuner;
2138  tmpdevice.mythdeviceid =
2139  tmpdevice.deviceid + "-" + tmpdevice.cardtuner;
2140  devicelist[tmpdevice.mythdeviceid] = tmpdevice;
2141  }
2142  uint found_device_count = devicelist.size();
2143 
2144  // Now find configured devices
2145 
2146  // returns "xxxxxxxx-n" or "ip.ip.ip.ip-n" values
2147  QStringList db = CardUtil::GetVideoDevices("HDHOMERUN");
2148 
2149  for (it = db.begin(); it != db.end(); ++it)
2150  {
2151  QMap<QString, HDHomeRunDevice>::iterator dit;
2152 
2153  dit = devicelist.find(*it);
2154 
2155  if (dit == devicelist.end())
2156  {
2157  if ((*it).toUpper() == "FFFFFFFF-0" && 2 == found_device_count)
2158  dit = devicelist.begin();
2159 
2160  if ((*it).toUpper() == "FFFFFFFF-1" && 2 == found_device_count)
2161  {
2162  dit = devicelist.begin();
2163  ++dit;
2164  }
2165  }
2166 
2167  if (dit != devicelist.end())
2168  {
2169  (*dit).inuse = true;
2170  continue;
2171  }
2172 
2173  HDHomeRunDevice tmpdevice;
2174  tmpdevice.mythdeviceid = *it;
2175  tmpdevice.inuse = true;
2176  tmpdevice.discovered = false;
2177 
2178  if (ProbeCard(tmpdevice))
2179  devicelist[tmpdevice.mythdeviceid] = tmpdevice;
2180  }
2181 
2182 #if 0
2183  // Debug dump of cards
2184  QMap<QString, HDHomeRunDevice>::iterator debugit;
2185  for (debugit = devicelist.begin(); debugit != devicelist.end(); ++debugit)
2186  {
2187  LOG(VB_GENERAL, LOG_DEBUG, QString("%1: %2 %3 %4 %5 %6 %7")
2188  .arg(debugit.key())
2189  .arg((*debugit).mythdeviceid)
2190  .arg((*debugit).deviceid)
2191  .arg((*debugit).cardip)
2192  .arg((*debugit).cardtuner)
2193  .arg((*debugit).inuse)
2194  .arg((*debugit).discovered));
2195  }
2196 #endif
2197 }
2198 
2200 {
2201 #ifdef USING_HDHOMERUN
2202  hdhomerun_device_t *thisdevice =
2203  hdhomerun_device_create_from_str(
2204  tmpdevice.mythdeviceid.toLocal8Bit().constData(), NULL);
2205 
2206  if (thisdevice)
2207  {
2208  uint device_id = hdhomerun_device_get_device_id(thisdevice);
2209  uint device_ip = hdhomerun_device_get_device_ip(thisdevice);
2210  uint tuner = hdhomerun_device_get_tuner(thisdevice);
2211  hdhomerun_device_destroy(thisdevice);
2212 
2213  if (device_id == 0)
2214  tmpdevice.deviceid = "NOTFOUND";
2215  else
2216  {
2217  tmpdevice.deviceid = QString("%1").arg(device_id, 8, 16);
2218  tmpdevice.desc = CardUtil::GetHDHRdesc(tmpdevice.deviceid);
2219  }
2220 
2221  tmpdevice.deviceid = tmpdevice.deviceid.toUpper();
2222 
2223  tmpdevice.cardip = QString("%1.%2.%3.%4")
2224  .arg((device_ip>>24) & 0xFF).arg((device_ip>>16) & 0xFF)
2225  .arg((device_ip>> 8) & 0xFF).arg((device_ip>> 0) & 0xFF);
2226 
2227  tmpdevice.cardtuner = QString("%1").arg(tuner);
2228  return true;
2229  }
2230 #endif // USING_HDHOMERUN
2231  return false;
2232 }
2233 
2235 {
2236  parent.reload(); // ensure card id is valid
2237 
2238  HDHomeRunExtra acw(*this);
2239  acw.exec();
2240 }
2241 
2242 // -----------------------
2243 // VBox Configuration
2244 // -----------------------
2245 
2247 {
2248  public:
2250 };
2251 
2253 {
2255  rec->setLabel(QObject::tr("Recorder Options"));
2256  rec->setUseLabel(false);
2257 
2258  rec->addChild(new SignalTimeout(parent.parent, 7000, 250));
2259  rec->addChild(new ChannelTimeout(parent.parent, 10000, 1750));
2260 
2261  addChild(rec);
2262 }
2263 
2265  (CaptureCard& a_parent) :
2266  VerticalConfigurationGroup(false, true, false, false),
2267  parent(a_parent)
2268 {
2269  setUseLabel(false);
2270 
2271  // Fill Device list
2272  FillDeviceList();
2273 
2274  deviceid = new VBoxDeviceID(parent);
2275  desc = new TransLabelSetting();
2276  desc->setLabel(tr("Description"));
2277  cardip = new VBoxIP();
2278  cardtuner = new VBoxTunerIndex();
2279  deviceidlist = new VBoxDeviceIDList(
2280  deviceid, desc, cardip, cardtuner, &devicelist);
2281 
2282  addChild(deviceidlist);
2285  addChild(deviceid);
2286  addChild(desc);
2287  addChild(cardip);
2288  addChild(cardtuner);
2289  addChild(new SignalTimeout(parent, 7000, 1000));
2290  addChild(new ChannelTimeout(parent, 10000, 1750));
2291 // TransButtonSetting *buttonRecOpt = new TransButtonSetting();
2292 // buttonRecOpt->setLabel(tr("Recording Options"));
2293 // addChild(buttonRecOpt);
2294 
2295 // connect(buttonRecOpt, SIGNAL(pressed()),
2296 // this, SLOT( VBoxExtraPanel()));
2297 
2298  connect(cardip, SIGNAL(NewIP(const QString&)),
2299  deviceid, SLOT( SetIP(const QString&)));
2300  connect(cardtuner, SIGNAL(NewTuner(const QString&)),
2301  deviceid, SLOT( SetTuner(const QString&)));
2302 };
2303 
2305 {
2306  devicelist.clear();
2307 
2308  // Find physical devices first
2309  // ProbeVideoDevices returns "deviceid ip tunerno tunertype"
2310  QStringList devs = CardUtil::ProbeVideoDevices("VBOX");
2311 
2312  QStringList::const_iterator it;
2313 
2314  for (it = devs.begin(); it != devs.end(); ++it)
2315  {
2316  QString dev = *it;
2317  QStringList devinfo = dev.split(" ");
2318  QString id = devinfo.at(0);
2319  QString ip = devinfo.at(1);
2320  QString tunerNo = devinfo.at(2);
2321  QString tunerType = devinfo.at(3);
2322 
2323  VBoxDevice tmpdevice;
2324  tmpdevice.deviceid = id;
2325  tmpdevice.desc = CardUtil::GetVBoxdesc(id, ip, tunerNo, tunerType);
2326  tmpdevice.cardip = ip;
2327  tmpdevice.inuse = false;
2328  tmpdevice.discovered = true;
2329  tmpdevice.tunerno = tunerNo;
2330  tmpdevice.tunertype = tunerType;
2331  tmpdevice.mythdeviceid = id + "-" + tunerNo + "-" + tunerType;
2332  devicelist[tmpdevice.mythdeviceid] = tmpdevice;
2333  }
2334 
2335  // Now find configured devices
2336 
2337  // returns "ip.ip.ip.ip-n-type" or deviceid-n-type values
2338  QStringList db = CardUtil::GetVideoDevices("VBOX");
2339 
2340  for (it = db.begin(); it != db.end(); ++it)
2341  {
2342  QMap<QString, VBoxDevice>::iterator dit;
2343  dit = devicelist.find(*it);
2344 
2345  if (dit != devicelist.end())
2346  (*dit).inuse = true;
2347  }
2348 }
2349 
2351 {
2352  parent.reload(); // ensure card id is valid
2353 
2354  VBoxExtra acw(*this);
2355  acw.exec();
2356 }
2357 
2358 // -----------------------
2359 // Ceton Configuration
2360 // -----------------------
2361 
2362 CetonSetting::CetonSetting(const char* label, const char* helptext)
2363 {
2364  setLabel(QObject::tr(label));
2365  setHelpText(tr(helptext));
2366  connect(this, SIGNAL(valueChanged( const QString&)),
2367  this, SLOT( UpdateDevices(const QString&)));
2368 }
2369 
2370 void CetonSetting::UpdateDevices(const QString &v)
2371 {
2372  if (isEnabled())
2373  emit NewValue(v);
2374 }
2375 
2376 void CetonSetting::LoadValue(const QString &value)
2377 {
2378  setValue(value);
2379 }
2380 
2382  LabelSetting(this),
2383  CaptureCardDBStorage(this, parent, "videodevice"),
2384  _ip(), _card(), _tuner(), _parent(parent)
2385 {
2386  setLabel(tr("Device ID"));
2387  setHelpText(tr("Device ID of Ceton device"));
2388 }
2389 
2390 void CetonDeviceID::SetIP(const QString &ip)
2391 {
2392  QString regexp = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){4}$";
2393  if (QRegExp(regexp).exactMatch(ip + "."))
2394  {
2395  _ip = ip;
2396  setValue(QString("%1-RTP.%3").arg(_ip).arg(_tuner));
2397  }
2398 }
2399 
2400 void CetonDeviceID::SetTuner(const QString &tuner)
2401 {
2402  if (QRegExp("^\\d$").exactMatch(tuner))
2403  {
2404  _tuner = tuner;
2405  setValue(QString("%1-RTP.%2").arg(_ip).arg(_tuner));
2406  }
2407 }
2408 
2410 {
2412  UpdateValues();
2413 }
2414 
2416 {
2417  QRegExp newstyle("^([0-9.]+)-(\\d|RTP)\\.(\\d)$");
2418  if (newstyle.exactMatch(getValue()))
2419  {
2420  emit LoadedIP(newstyle.cap(1));
2421  emit LoadedTuner(newstyle.cap(3));
2422  }
2423 }
2424 
2426 {
2427  public:
2428  explicit CetonExtra(CetonConfigurationGroup &parent);
2429 };
2430 
2432 {
2434  rec->setLabel(QObject::tr("Recorder Options"));
2435  rec->setUseLabel(false);
2436 
2437  rec->addChild(new SignalTimeout(parent.parent, 1000, 250));
2438  rec->addChild(new ChannelTimeout(parent.parent, 3000, 1750));
2439 
2440  addChild(rec);
2441 }
2442 
2443 
2446  parent(a_parent)
2447 {
2448  setUseLabel(false);
2449 
2450  deviceid = new CetonDeviceID(parent);
2451  desc = new TransLabelSetting();
2452  desc->setLabel(tr("Description"));
2453  ip = new CetonSetting(
2454  "IP Address",
2455  "IP Address of the Ceton device (192.168.200.1 by default)");
2456  tuner = new CetonSetting(
2457  "Tuner",
2458  "Number of the tuner on the Ceton device (first tuner is number 0)");
2459 
2460  addChild(ip);
2461  addChild(tuner);
2462  addChild(deviceid);
2463  addChild(desc);
2464 
2465  TransButtonSetting *buttonRecOpt = new TransButtonSetting();
2466  buttonRecOpt->setLabel(tr("Recording Options"));
2467  addChild(buttonRecOpt);
2468 
2469  connect(ip, SIGNAL(NewValue(const QString&)),
2470  deviceid, SLOT( SetIP(const QString&)));
2471  connect(tuner, SIGNAL(NewValue(const QString&)),
2472  deviceid, SLOT( SetTuner(const QString&)));
2473 
2474  connect(deviceid, SIGNAL(LoadedIP(const QString&)),
2475  ip, SLOT( LoadValue(const QString&)));
2476  connect(deviceid, SIGNAL(LoadedTuner(const QString&)),
2477  tuner, SLOT( LoadValue(const QString&)));
2478 
2479  connect(buttonRecOpt, SIGNAL(pressed()),
2480  this, SLOT( CetonExtraPanel()));
2481 
2482 };
2483 
2485 {
2486  parent.reload(); // ensure card id is valid
2487 
2488  CetonExtra acw(*this);
2489  acw.exec();
2490 }
2491 
2492 
2495  parent(a_parent),
2496  cardinfo(new TransLabelSetting()), vbidev(new VBIDevice(parent))
2497 {
2498  QString drv = "(?!ivtv|hdpvr|(saa7164(.*))).*";
2499  VideoDevice *device = new VideoDevice(parent, 0, 15, QString::null, drv);
2501  new HorizontalConfigurationGroup(false, false, true, true);
2502 
2503  audgrp->addChild(new AudioRateLimit(parent));
2504  audgrp->addChild(new SkipBtAudio(parent));
2505 
2506  addChild(device);
2507  cardinfo->setLabel(tr("Probed info"));
2508  addChild(cardinfo);
2509 
2510  addChild(vbidev);
2511  addChild(new AudioDevice(parent));
2512  addChild(audgrp);
2513 
2514  connect(device, SIGNAL(valueChanged(const QString&)),
2515  this, SLOT( probeCard( const QString&)));
2516 
2517  probeCard(device->getValue());
2518 };
2519 
2520 void V4LConfigurationGroup::probeCard(const QString &device)
2521 {
2522  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2523 
2524  QByteArray adevice = device.toLatin1();
2525  int videofd = open(adevice.constData(), O_RDWR);
2526  if (videofd >= 0)
2527  {
2528  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2529  ci = cn = tr("Failed to probe");
2530  else if (!dn.isEmpty())
2531  ci = cn + " [" + dn + "]";
2532  close(videofd);
2533  }
2534 
2535  cardinfo->setValue(ci);
2536  vbidev->setFilter(cn, dn);
2537 }
2538 
2541  parent(a_parent),
2542  device(NULL), vbidevice(NULL),
2544 {
2545  QString drv = "ivtv|(saa7164(.*))";
2546  device = new VideoDevice(parent, 0, 15, QString::null, drv);
2547  vbidevice = new VBIDevice(parent);
2548  vbidevice->setVisible(false);
2549 
2550  cardinfo->setLabel(tr("Probed info"));
2551 
2552  addChild(device);
2554  addChild(cardinfo);
2555  addChild(new ChannelTimeout(parent, 12000, 2000));
2556 
2557  connect(device, SIGNAL(valueChanged(const QString&)),
2558  this, SLOT( probeCard( const QString&)));
2559 
2561 }
2562 
2564 {
2565  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2566 
2567  QByteArray adevice = device.toLatin1();
2568  int videofd = open(adevice.constData(), O_RDWR);
2569  if (videofd >= 0)
2570  {
2571  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2572  ci = cn = tr("Failed to probe");
2573  else if (!dn.isEmpty())
2574  ci = cn + " [" + dn + "]";
2575  close(videofd);
2576  }
2577 
2578  cardinfo->setValue(ci);
2579  vbidevice->setVisible(dn!="ivtv");
2580  vbidevice->setFilter(cn, dn);
2581 }
2582 
2585  parent(a_parent),
2586  info(new TransLabelSetting()), size(new TransLabelSetting())
2587 {
2588  FileDevice *device = new FileDevice(parent);
2589  device->setHelpText(tr("A local MPEG file used to simulate a recording."
2590  " Must be entered as file:/path/movie.mpg"));
2591  device->addSelection("file:/");
2592  addChild(device);
2593 
2596 
2597  info->setLabel(tr("File info"));
2598  addChild(info);
2599 
2600  size->setLabel(tr("File size"));
2601  addChild(size);
2602 
2603  connect(device, SIGNAL(valueChanged(const QString&)),
2604  this, SLOT( probeCard( const QString&)));
2605 
2606  probeCard(device->getValue());
2607 }
2608 
2609 void DemoConfigurationGroup::probeCard(const QString &device)
2610 {
2611  if (!device.startsWith("file:", Qt::CaseInsensitive))
2612  {
2613  info->setValue("");
2614  size->setValue("");
2615  return;
2616  }
2617 
2618 
2619  QString ci, cs;
2620  QFileInfo fileInfo(device.mid(5));
2621  if (fileInfo.exists())
2622  {
2623  if (fileInfo.isReadable() && (fileInfo.isFile()))
2624  {
2625  ci = HTTPRequest::TestMimeType(fileInfo.absoluteFilePath());
2626  cs = tr("%1 MB").arg(fileInfo.size() / 1024 / 1024);
2627  }
2628  else
2629  ci = tr("File not readable");
2630  }
2631  else
2632  {
2633  ci = tr("File does not exist");
2634  }
2635 
2636  info->setValue(ci);
2637  size->setValue(cs);
2638 }
2639 
2640 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2643  parent(a_parent),
2644  info(new TransLabelSetting())
2645 {
2646  FileDevice *device = new FileDevice(parent);
2647  device->setHelpText(tr("A 'black box' application controlled via "
2648  "stdin, status on stderr and TransportStream "
2649  "read from stdout"));
2650  addChild(device);
2651 
2652  info->setLabel(tr("File info"));
2653  addChild(info);
2654 
2655  connect(device, SIGNAL(valueChanged(const QString&)),
2656  this, SLOT( probeApp( const QString&)));
2657 
2658  probeApp(device->getValue());
2659 }
2660 
2661 void ExternalConfigurationGroup::probeApp(const QString & path)
2662 {
2663  int idx1 = path.toLower().startsWith("file:") ? 5 : 0;
2664  int idx2 = path.indexOf(' ', idx1);
2665 
2666  QString ci, cs;
2667  QFileInfo fileInfo(path.mid(idx1, idx2 - idx1));
2668 
2669  if (fileInfo.exists())
2670  {
2671  ci = tr("'%1' is valid.").arg(fileInfo.absoluteFilePath());
2672  if (!fileInfo.isReadable() || !fileInfo.isFile())
2673  ci = tr("'%1' is not readable.").arg(fileInfo.absoluteFilePath());
2674  if (!fileInfo.isExecutable())
2675  ci = tr("'%1' is not executable.").arg(fileInfo.absoluteFilePath());
2676  }
2677  else
2678  {
2679  ci = tr("'%1' does not exist.").arg(fileInfo.absoluteFilePath());
2680  }
2681 
2682  info->setValue(ci);
2683 }
2684 #endif // !defined( USING_MINGW ) && !defined( _MSC_VER )
2685 
2688  parent(a_parent), cardinfo(new TransLabelSetting()),
2689  audioinput(new TunerCardAudioInput(parent, QString::null, "HDPVR")),
2690  vbidevice(NULL)
2691 {
2692  VideoDevice *device =
2693  new VideoDevice(parent, 0, 15, QString::null, "hdpvr");
2694 
2695  cardinfo->setLabel(tr("Probed info"));
2696 
2697  addChild(device);
2700  addChild(cardinfo);
2702  addChild(new ChannelTimeout(parent, 15000, 2000));
2703 
2704  connect(device, SIGNAL(valueChanged(const QString&)),
2705  this, SLOT( probeCard( const QString&)));
2706 
2707  probeCard(device->getValue());
2708 }
2709 
2710 void HDPVRConfigurationGroup::probeCard(const QString &device)
2711 {
2712  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2713 
2714  int videofd = open(device.toLocal8Bit().constData(), O_RDWR);
2715  if (videofd >= 0)
2716  {
2717  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2718  ci = cn = tr("Failed to probe");
2719  else if (!dn.isEmpty())
2720  ci = cn + " [" + dn + "]";
2721  close(videofd);
2722  }
2723 
2724  cardinfo->setValue(ci);
2725  audioinput->fillSelections(device);
2726 }
2727 
2730  m_parent(parent),
2731  m_cardinfo(new TransLabelSetting())
2732 {
2733  setLabel(QObject::tr("V4L2 encoder devices (multirec capable)"));
2734  VideoDevice *device = new VideoDevice(m_parent, 0, 15);
2735 
2736  addChild(device);
2737  m_cardinfo->setLabel(tr("Probed info"));
2739 
2740  // Choose children to show based on which device is active
2741  setTrigger(device);
2742  // Only save settings for 'this' device.
2743  setSaveAll(false);
2744 
2745  connect(device, SIGNAL(valueChanged(const QString&)),
2746  this, SLOT( probeCard( const QString&)));
2747 
2748  probeCard(device->getValue());
2749 }
2750 
2751 void V4L2encGroup::triggerChanged(const QString& dev_path)
2752 {
2753  probeCard(dev_path);
2755 }
2756 
2757 void V4L2encGroup::probeCard(const QString &device_name)
2758 {
2759 #ifdef USING_V4L2
2760  QString card_name = tr("Failed to open");
2761  QString card_info = card_name;
2762  V4L2util v4l2(device_name);
2763 
2764  if (!v4l2.IsOpen())
2765  {
2766  m_DriverName = tr("Failed to probe");
2767  return;
2768  }
2769  m_DriverName = v4l2.DriverName();
2770  card_name = v4l2.CardName();
2771 
2772  if (!m_DriverName.isEmpty())
2773  card_info = card_name + " [" + m_DriverName + "]";
2774 
2775  m_cardinfo->setValue(card_info);
2776 
2778  QMap<QString,Configurable*>::iterator it = triggerMap.find(m_DriverName);
2779  if (it == triggerMap.end())
2780  {
2781  grp = new VerticalConfigurationGroup(false);
2782 
2783  TunerCardAudioInput* audioinput =
2784  new TunerCardAudioInput(m_parent, QString::null, "V4L2");
2785  audioinput->fillSelections(device_name);
2786  if (audioinput->size() > 1)
2787  {
2788  audioinput->setName("AudioInput");
2789  grp->addChild(audioinput);
2790  }
2791  else
2792  delete audioinput;
2793 
2794  if (v4l2.HasSlicedVBI())
2795  {
2796  VBIDevice* vbidev = new VBIDevice(m_parent);
2797  vbidev->setFilter(card_name, m_DriverName);
2798  if (vbidev->size() > 0)
2799  {
2800  vbidev->setName("VBIDevice");
2801  grp->addChild(vbidev);
2802  }
2803  else
2804  delete vbidev;
2805  }
2806 
2807  grp->addChild(new EmptyVBIDevice(m_parent));
2808  grp->addChild(new ChannelTimeout(m_parent, 15000, 2000));
2809 
2810  addTarget(m_DriverName, grp);
2811  }
2812 #endif // USING_V4L2
2813 }
2814 
2817 {
2818  setLabel(QObject::tr("Capture Card Setup"));
2819 
2820  CardType* cardtype = new CardType(parent);
2821  addChild(cardtype);
2822 
2823  setTrigger(cardtype);
2824  setSaveAll(false);
2825 
2826 #ifdef USING_DVB
2827  addTarget("DVB", new DVBConfigurationGroup(parent));
2828 #endif // USING_DVB
2829 
2830 #ifdef USING_V4L2
2831 # ifdef USING_HDPVR
2832  addTarget("HDPVR", new HDPVRConfigurationGroup(parent));
2833 # endif // USING_HDPVR
2834 #endif // USING_V4L2
2835 
2836 #ifdef USING_HDHOMERUN
2837  addTarget("HDHOMERUN", new HDHomeRunConfigurationGroup(parent));
2838 #endif // USING_HDHOMERUN
2839 
2840 #ifdef USING_VBOX
2841  addTarget("VBOX", new VBoxConfigurationGroup(parent));
2842 #endif // USING_VBOX
2843 
2844 #ifdef USING_FIREWIRE
2845  addTarget("FIREWIRE", new FirewireConfigurationGroup(parent));
2846 #endif // USING_FIREWIRE
2847 
2848 #ifdef USING_CETON
2849  addTarget("CETON", new CetonConfigurationGroup(parent));
2850 #endif // USING_CETON
2851 
2852 #ifdef USING_IPTV
2853  addTarget("FREEBOX", new IPTVConfigurationGroup(parent));
2854 #endif // USING_IPTV
2855 
2856 #ifdef USING_V4L2
2857  addTarget("V4L2ENC", new V4L2encGroup(parent));
2858  addTarget("V4L", new V4LConfigurationGroup(parent));
2859 # ifdef USING_IVTV
2860  addTarget("MPEG", new MPEGConfigurationGroup(parent));
2861 # endif // USING_IVTV
2862 #endif // USING_V4L2
2863 
2864 #ifdef USING_ASI
2865  addTarget("ASI", new ASIConfigurationGroup(parent));
2866 #endif // USING_ASI
2867 
2868  // for testing without any actual tuner hardware:
2869  addTarget("IMPORT", new ImportConfigurationGroup(parent));
2870  addTarget("DEMO", new DemoConfigurationGroup(parent));
2871 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2872  addTarget("EXTERNAL", new ExternalConfigurationGroup(parent));
2873 #endif
2874 }
2875 
2877 {
2878  QString own = (value == "MJPEG" || value == "GO7007") ? "V4L" : value;
2880 }
2881 
2882 CaptureCard::CaptureCard(bool use_card_group)
2883  : id(new ID)
2884 {
2885  addChild(id);
2886  if (use_card_group)
2887  addChild(new CaptureCardGroup(*this));
2888  addChild(new Hostname(*this));
2889 }
2890 
2891 QString CaptureCard::GetRawCardType(void) const
2892 {
2893  int cardid = getCardID();
2894  if (cardid <= 0)
2895  return QString::null;
2896  return CardUtil::GetRawInputType(cardid);
2897 }
2898 
2900 {
2901  MSqlQuery query(MSqlQuery::InitCon());
2902  QString qstr =
2903  "SELECT cardid, videodevice, cardtype "
2904  "FROM capturecard "
2905  "WHERE hostname = :HOSTNAME AND parentid = 0 "
2906  "ORDER BY cardid";
2907 
2908  query.prepare(qstr);
2909  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
2910 
2911  if (!query.exec())
2912  {
2913  MythDB::DBError("CaptureCard::fillSelections", query);
2914  return;
2915  }
2916 
2917  while (query.next())
2918  {
2919  uint cardid = query.value(0).toUInt();
2920  QString videodevice = query.value(1).toString();
2921  QString cardtype = query.value(2).toString();
2922  QString label = CardUtil::GetDeviceLabel(cardtype, videodevice);
2923  setting->addSelection(label, QString::number(cardid));
2924  }
2925 }
2926 
2927 void CaptureCard::loadByID(int cardid)
2928 {
2929  id->setValue(cardid);
2930  Load();
2931 }
2932 
2934 {
2935  uint init_cardid = getCardID();
2936  QString init_type = CardUtil::GetRawInputType(init_cardid);
2937  QString init_dev = CardUtil::GetVideoDevice(init_cardid);
2938  QString init_input = CardUtil::GetInputName(init_cardid);
2939 
2941 
2943 
2945 
2946  uint cardid = getCardID();
2947  QString type = CardUtil::GetRawInputType(cardid);
2948  QString dev = CardUtil::GetVideoDevice(cardid);
2949 
2950  if (dev != init_dev)
2951  {
2952  if (!init_dev.isEmpty())
2953  {
2954  uint init_groupid = CardUtil::GetDeviceInputGroup(init_cardid);
2955  CardUtil::UnlinkInputGroup(init_cardid, init_groupid);
2956  }
2957  if (!dev.isEmpty())
2958  {
2959  uint groupid =
2960  CardUtil::CreateDeviceInputGroup(cardid, type,
2961  gCoreContext->GetHostName(), dev);
2962  CardUtil::LinkInputGroup(cardid, groupid);
2963  CardUtil::UnlinkInputGroup(0, groupid);
2964  }
2965  }
2966 
2967  // Handle any cloning we may need to do
2969  {
2970  vector<uint> clones = CardUtil::GetChildInputIDs(cardid);
2971  for (uint i = 0; i < clones.size(); i++)
2972  CardUtil::CloneCard(cardid, clones[i]);
2973  }
2974 }
2975 
2977 {
2978  if (getCardID() == 0)
2979  {
2980  Save();
2981  Load();
2982  }
2983 }
2984 
2986  ComboBoxSetting(this),
2987  CaptureCardDBStorage(this, parent, "cardtype")
2988 {
2989  setLabel(QObject::tr("Card type"));
2990  setHelpText(QObject::tr("Change the cardtype to the appropriate type for "
2991  "the capture card you are configuring."));
2992  fillSelections(this);
2993 }
2994 
2996 {
2997 #ifdef USING_DVB
2998  setting->addSelection(
2999  QObject::tr("DVB-T/S/C, ATSC or ISDB-T tuner card"), "DVB");
3000 #endif // USING_DVB
3001 
3002 #ifdef USING_V4L2
3003  setting->addSelection(
3004  QObject::tr("V4L2 encoder"), "V4L2ENC");
3005 #ifdef USING_HDPVR
3006  setting->addSelection(
3007  QObject::tr("HD-PVR H.264 encoder"), "HDPVR");
3008 # endif // USING_HDPVR
3009 #endif // USING_V4L2
3010 
3011 #ifdef USING_HDHOMERUN
3012  setting->addSelection(
3013  QObject::tr("HDHomeRun networked tuner"), "HDHOMERUN");
3014 #endif // USING_HDHOMERUN
3015 
3016 #ifdef USING_VBOX
3017  setting->addSelection(
3018  QObject::tr("V@Box TV Gateway networked tuner"), "VBOX");
3019 #endif // USING_VBOX
3020 
3021 #ifdef USING_FIREWIRE
3022  setting->addSelection(
3023  QObject::tr("FireWire cable box"), "FIREWIRE");
3024 #endif // USING_FIREWIRE
3025 
3026 #ifdef USING_CETON
3027  setting->addSelection(
3028  QObject::tr("Ceton Cablecard tuner"), "CETON");
3029 #endif // USING_CETON
3030 
3031 #ifdef USING_IPTV
3032  setting->addSelection(QObject::tr("IPTV recorder"), "FREEBOX");
3033 #endif // USING_IPTV
3034 
3035 #ifdef USING_V4L2
3036 # ifdef USING_IVTV
3037  setting->addSelection(
3038  QObject::tr("Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"), "MPEG");
3039 # endif // USING_IVTV
3040  setting->addSelection(
3041  QObject::tr("Analog to MJPEG encoder card (Matrox G200, DC10, etc)"), "MJPEG");
3042  setting->addSelection(
3043  QObject::tr("Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
3044  "GO7007");
3045  setting->addSelection(
3046  QObject::tr("Analog capture card"), "V4L");
3047 #endif // USING_V4L2
3048 
3049 #ifdef USING_ASI
3050  setting->addSelection(QObject::tr("DVEO ASI recorder"), "ASI");
3051 #endif
3052 
3053  setting->addSelection(QObject::tr("Import test recorder"), "IMPORT");
3054  setting->addSelection(QObject::tr("Demo test recorder"), "DEMO");
3055 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
3056  setting->addSelection(QObject::tr("External (black box) recorder"),
3057  "EXTERNAL");
3058 #endif
3059 }
3060 
3062 {
3063  public:
3064  explicit InputName(const CardInput &parent) :
3065  ComboBoxSetting(this), CardInputDBStorage(this, parent, "inputname")
3066  {
3067  setLabel(QObject::tr("Input name"));
3068  };
3069 
3070  virtual void Load(void)
3071  {
3072  fillSelections();
3074  };
3075 
3077  clearSelections();
3078  addSelection(QObject::tr("(None)"), "None");
3079  uint cardid = getInputID();
3080  QString type = CardUtil::GetRawInputType(cardid);
3081  QString device = CardUtil::GetVideoDevice(cardid);
3082  QStringList inputs;
3083  CardUtil::GetDeviceInputNames(cardid, device, type, inputs);
3084  while (!inputs.isEmpty())
3085  {
3086  addSelection(inputs.front());
3087  inputs.pop_front();
3088  }
3089  };
3090 };
3091 
3093 {
3094  public:
3095  explicit InputDisplayName(const CardInput &parent) :
3096  LineEditSetting(this),
3097  CardInputDBStorage(this, parent, "displayname")
3098  {
3099  setLabel(QObject::tr("Display name (optional)"));
3100  setHelpText(QObject::tr(
3101  "This name is displayed on screen when Live TV begins "
3102  "and when changing the selected input or card. If you "
3103  "use this, make sure the information is unique for "
3104  "each input."));
3105  };
3106 };
3107 
3109 {
3110  public:
3111  explicit SourceID(const CardInput &parent) :
3112  ComboBoxSetting(this), CardInputDBStorage(this, parent, "sourceid")
3113  {
3114  setLabel(QObject::tr("Video source"));
3115  addSelection(QObject::tr("(None)"), "0");
3116  };
3117 
3118  virtual void Load(void)
3119  {
3120  fillSelections();
3122  };
3123 
3125  clearSelections();
3126  addSelection(QObject::tr("(None)"), "0");
3128  };
3129 };
3130 
3132 {
3133  public:
3134  InputGroup(const CardInput &parent, uint group_num) :
3135  TransComboBoxSetting(false), cardinput(parent),
3136  groupnum(group_num), groupid(0)
3137  {
3138  setLabel(QObject::tr("Input group") +
3139  QString(" %1").arg(groupnum + 1));
3140  setHelpText(QObject::tr(
3141  "Leave as 'Generic' unless this input is shared with "
3142  "another device. Only one of the inputs in an input "
3143  "group will be allowed to record at any given time."));
3144  }
3145 
3146  virtual void Load(void);
3147 
3148  virtual void Save(void)
3149  {
3150  uint inputid = cardinput.getInputID();
3151  uint new_groupid = getValue().toUInt();
3152 
3153  if (groupid)
3154  CardUtil::UnlinkInputGroup(inputid, groupid);
3155 
3156  if (new_groupid)
3157  {
3158  if (CardUtil::UnlinkInputGroup(inputid, new_groupid))
3159  CardUtil::LinkInputGroup(inputid, new_groupid);
3160  }
3161  }
3162 
3163  virtual void Save(QString /*destination*/) { Save(); }
3164 
3165  private:
3169 };
3170 
3172 {
3173 #if 0
3174  LOG(VB_GENERAL, LOG_DEBUG, QString("InputGroup::Load() %1 %2")
3175  .arg(groupnum).arg(cardinput.getInputID()));
3176 #endif
3177 
3178  uint inputid = cardinput.getInputID();
3179  QMap<uint, uint> grpcnt;
3180  vector<QString> names;
3181  vector<uint> grpid;
3182  vector<uint> selected_groupids;
3183 
3184  names.push_back(QObject::tr("Generic"));
3185  grpid.push_back(0);
3186  grpcnt[0]++;
3187 
3188  MSqlQuery query(MSqlQuery::InitCon());
3189  query.prepare(
3190  "SELECT cardinputid, inputgroupid, inputgroupname "
3191  "FROM inputgroup "
3192  "WHERE inputgroupname LIKE 'user:%' "
3193  "ORDER BY inputgroupid, cardinputid, inputgroupname");
3194 
3195  if (!query.exec())
3196  {
3197  MythDB::DBError("InputGroup::Load()", query);
3198  }
3199  else
3200  {
3201  while (query.next())
3202  {
3203  uint groupid = query.value(1).toUInt();
3204  if (inputid && (query.value(0).toUInt() == inputid))
3205  selected_groupids.push_back(groupid);
3206 
3207  grpcnt[groupid]++;
3208 
3209  if (grpcnt[groupid] == 1)
3210  {
3211  names.push_back(query.value(2).toString().mid(5, -1));
3212  grpid.push_back(groupid);
3213  }
3214  }
3215  }
3216 
3217  // makes sure we select something
3218  groupid = 0;
3219  if (groupnum < selected_groupids.size())
3220  groupid = selected_groupids[groupnum];
3221 
3222 #if 0
3223  LOG(VB_GENERAL, LOG_DEBUG, QString("Group num: %1 id: %2")
3224  .arg(groupnum).arg(groupid));
3225  {
3226  QString msg;
3227  for (uint i = 0; i < selected_groupids.size(); i++)
3228  msg += QString("%1 ").arg(selected_groupids[i]);
3229  LOG(VB_GENERAL, LOG_DEBUG, msg);
3230  }
3231 #endif
3232 
3233  // add selections to combobox
3234  clearSelections();
3235  uint index = 0;
3236  for (uint i = 0; i < names.size(); i++)
3237  {
3238  bool sel = (groupid == grpid[i]);
3239  index = (sel) ? i : index;
3240 
3241 #if 0
3242  LOG(VB_GENERAL, LOG_DEBUG, QString("grpid %1, name '%2', i %3, s %4")
3243  .arg(grpid[i]).arg(names[i]) .arg(index).arg(sel ? "T" : "F"));
3244 #endif
3245 
3246  addSelection(names[i], QString::number(grpid[i]), sel);
3247  }
3248 
3249 #if 0
3250  LOG(VB_GENERAL, LOG_DEBUG, QString("Group index: %1").arg(index));
3251 #endif
3252 
3253  if (!names.empty())
3254  setValue(index);
3255 }
3256 
3258 {
3259  public:
3260  explicit QuickTune(const CardInput &parent) :
3261  ComboBoxSetting(this), CardInputDBStorage(this, parent, "quicktune")
3262  {
3263  setLabel(QObject::tr("Use quick tuning"));
3264  addSelection(QObject::tr("Never"), "0", true);
3265  addSelection(QObject::tr("Live TV only"), "1", false);
3266  addSelection(QObject::tr("Always"), "2", false);
3267  setHelpText(QObject::tr(
3268  "If enabled, MythTV will tune using only the "
3269  "MPEG program number. The program numbers "
3270  "change more often than DVB or ATSC tuning "
3271  "parameters, so this is slightly less reliable. "
3272  "This will also inhibit EIT gathering during "
3273  "Live TV and recording."));
3274  };
3275 };
3276 
3278  public LineEditSetting, public CardInputDBStorage
3279 {
3280  public:
3281  explicit ExternalChannelCommand(const CardInput &parent) :
3282  LineEditSetting(this),
3283  CardInputDBStorage(this, parent, "externalcommand")
3284  {
3285  setLabel(QObject::tr("External channel change command"));
3286  setValue("");
3287  setHelpText(QObject::tr("If specified, this command will be run to "
3288  "change the channel for inputs which have an external "
3289  "tuner device such as a cable box. The first argument "
3290  "will be the channel number."));
3291  };
3292 };
3293 
3295 {
3296  public:
3297  explicit PresetTuner(const CardInput &parent) :
3298  LineEditSetting(this),
3299  CardInputDBStorage(this, parent, "tunechan")
3300  {
3301  setLabel(QObject::tr("Preset tuner to channel"));
3302  setValue("");
3303  setHelpText(QObject::tr("Leave this blank unless you have an external "
3304  "tuner that is connected to the tuner input of your card. "
3305  "If so, you will need to specify the preset channel for "
3306  "the signal (normally 3 or 4)."));
3307  };
3308 };
3309 
3310 void StartingChannel::SetSourceID(const QString &sourceid)
3311 {
3312  clearSelections();
3313  if (sourceid.isEmpty() || !sourceid.toUInt())
3314  return;
3315 
3316  // Get the existing starting channel
3317  QString startChan = CardUtil::GetStartingChannel(getInputID());
3318 
3319  ChannelInfoList channels = ChannelUtil::GetAllChannels(sourceid.toUInt());
3320 
3321  if (channels.empty())
3322  {
3323  addSelection(tr("Please add channels to this source"),
3324  startChan.isEmpty() ? "0" : startChan);
3325  return;
3326  }
3327 
3328  // If there are channels sort them, then add theme
3329  // (selecting the old start channel if it is there).
3330  QString order = gCoreContext->GetSetting("ChannelOrdering", "channum");
3331  ChannelUtil::SortChannels(channels, order);
3332  bool has_visible = false;
3333  for (uint i = 0; i < channels.size() && !has_visible; i++)
3334  has_visible |= channels[i].visible;
3335 
3336  for (uint i = 0; i < channels.size(); i++)
3337  {
3338  const QString channum = channels[i].channum;
3339  bool sel = channum == startChan;
3340  if (!has_visible || channels[i].visible || sel)
3341  {
3342  addSelection(channum, channum, sel);
3343  }
3344  }
3345 }
3346 
3348 {
3349  public:
3350  explicit InputPriority(const CardInput &parent) :
3351  SpinBoxSetting(this, -99, 99, 1),
3352  CardInputDBStorage(this, parent, "recpriority")
3353  {
3354  setLabel(QObject::tr("Input priority"));
3355  setValue(0);
3356  setHelpText(QObject::tr("If the input priority is not equal for "
3357  "all inputs, the scheduler may choose to record a show "
3358  "at a later time so that it can record on an input with "
3359  "a higher value."));
3360  };
3361 };
3362 
3364 {
3365  public:
3366  ScheduleOrder(const CardInput &parent, int _value) :
3367  SpinBoxSetting(this, 0, 99, 1),
3368  CardInputDBStorage(this, parent, "schedorder")
3369  {
3370  setLabel(QObject::tr("Schedule order"));
3371  setValue(_value);
3372  setHelpText(QObject::tr("If priorities and other factors are equal "
3373  "the scheduler will choose the available "
3374  "input with the lowest, non-zero value. "
3375  "Setting this value to zero will make the "
3376  "input unavailable to the scheduler."));
3377  };
3378 };
3379 
3381 {
3382  public:
3383  LiveTVOrder(const CardInput &parent, int _value) :
3384  SpinBoxSetting(this, 0, 99, 1),
3385  CardInputDBStorage(this, parent, "livetvorder")
3386  {
3387  setLabel(QObject::tr("Live TV order"));
3388  setValue(_value);
3389  setHelpText(QObject::tr("When entering Live TV, the available, local "
3390  "input with the lowest, non-zero value will "
3391  "be used. If no local inputs are available, "
3392  "the available, remote input with the lowest, "
3393  "non-zero value will be used. "
3394  "Setting this value to zero will make the "
3395  "input unavailable to live TV."));
3396  };
3397 };
3398 
3400 {
3401  public:
3402  explicit DishNetEIT(const CardInput &parent) :
3403  CheckBoxSetting(this),
3404  CardInputDBStorage(this, parent, "dishnet_eit")
3405  {
3406  setLabel(QObject::tr("Use DishNet long-term EIT data"));
3407  setValue(false);
3408  setHelpText(
3409  QObject::tr(
3410  "If you point your satellite dish toward DishNet's birds, "
3411  "you may wish to enable this feature. For best results, "
3412  "enable general EIT collection as well."));
3413  };
3414 };
3415 
3416 CardInput::CardInput(const QString & cardtype, const QString & device,
3417  bool isNewInput, int _cardid) :
3418  id(new ID()),
3419  inputname(new InputName(*this)),
3420  sourceid(new SourceID(*this)),
3421  startchan(new StartingChannel(*this)),
3422  scan(new TransButtonSetting()),
3423  srcfetch(new TransButtonSetting()),
3424  externalInputSettings(new DiSEqCDevSettings()),
3425  inputgrp0(new InputGroup(*this, 0)),
3426  inputgrp1(new InputGroup(*this, 1)),
3427  instancecount(NULL),
3428  schedgroup(NULL)
3429 {
3430  addChild(id);
3431 
3433  {
3435  _cardid, isNewInput));
3436  }
3437 
3438  ConfigurationGroup *basic =
3439  new VerticalConfigurationGroup(false, false, true, true);
3440 
3441  basic->setLabel(QObject::tr("Connect source to input"));
3442 
3443  basic->addChild(inputname);
3444  basic->addChild(new InputDisplayName(*this));
3445  basic->addChild(sourceid);
3446 
3447  if (CardUtil::IsEncoder(cardtype) || CardUtil::IsUnscanable(cardtype))
3448  {
3449  basic->addChild(new ExternalChannelCommand(*this));
3450  if (CardUtil::HasTuner(cardtype, device))
3451  basic->addChild(new PresetTuner(*this));
3452  }
3453  else
3454  {
3455  ConfigurationGroup *chgroup =
3456  new HorizontalConfigurationGroup(false, false, true, true);
3457  chgroup->addChild(new QuickTune(*this));
3458  if ("DVB" == cardtype)
3459  chgroup->addChild(new DishNetEIT(*this));
3460  basic->addChild(chgroup);
3461  }
3462 
3463  scan->setLabel(tr("Scan for channels"));
3464  scan->setHelpText(
3465  tr("Use channel scanner to find channels for this input."));
3466 
3467  srcfetch->setLabel(tr("Fetch channels from listings source"));
3469  tr("This uses the listings data source to "
3470  "provide the channels for this input.") + " " +
3471  tr("This can take a long time to run."));
3472 
3473  ConfigurationGroup *sgrp =
3474  new HorizontalConfigurationGroup(false, false, true, true);
3475  sgrp->addChild(scan);
3476  sgrp->addChild(srcfetch);
3477  basic->addChild(sgrp);
3478 
3479  basic->addChild(startchan);
3480 
3481  addChild(basic);
3482 
3483  ConfigurationGroup *interact =
3484  new VerticalConfigurationGroup(false, false, true, true);
3485 
3486  interact->setLabel(QObject::tr("Interactions between inputs"));
3487  if (CardUtil::IsTunerSharingCapable(cardtype))
3488  {
3490  interact->addChild(instancecount);
3491  schedgroup = new SchedGroup(*this);
3492  interact->addChild(schedgroup);
3493  }
3494  interact->addChild(new InputPriority(*this));
3495  interact->addChild(new ScheduleOrder(*this, _cardid));
3496  interact->addChild(new LiveTVOrder(*this, _cardid));
3497 
3498  TransButtonSetting *ingrpbtn = new TransButtonSetting("newgroup");
3499  ingrpbtn->setLabel(QObject::tr("Create a New Input Group"));
3500  ingrpbtn->setHelpText(
3501  QObject::tr("Input groups are only needed when two or more cards "
3502  "share the same resource such as a FireWire card and "
3503  "an analog card input controlling the same set top box."));
3504  interact->addChild(ingrpbtn);
3505  interact->addChild(inputgrp0);
3506  interact->addChild(inputgrp1);
3507 
3508  addChild(interact);
3509 
3510  setObjectName("CardInput");
3511  SetSourceID("-1");
3512 
3513  connect(scan, SIGNAL(pressed()), SLOT(channelScanner()));
3514  connect(srcfetch, SIGNAL(pressed()), SLOT(sourceFetch()));
3515  connect(sourceid, SIGNAL(valueChanged(const QString&)),
3516  startchan,SLOT( SetSourceID (const QString&)));
3517  connect(sourceid, SIGNAL(valueChanged(const QString&)),
3518  this, SLOT( SetSourceID (const QString&)));
3519  connect(ingrpbtn, SIGNAL(pressed(QString)),
3520  this, SLOT( CreateNewInputGroup()));
3521  if (schedgroup)
3522  connect(instancecount, SIGNAL(valueChanged(int)),
3523  this, SLOT(UpdateSchedGroup(int)));
3524 }
3525 
3527 {
3529  {
3530  delete externalInputSettings;
3531  externalInputSettings = NULL;
3532  }
3533 }
3534 
3535 void CardInput::SetSourceID(const QString &sourceid)
3536 {
3537  uint cid = id->getValue().toUInt();
3538  QString raw_card_type = CardUtil::GetRawInputType(cid);
3539  bool enable = (sourceid.toInt() > 0);
3540  scan->setEnabled(enable && !raw_card_type.isEmpty() &&
3541  !CardUtil::IsUnscanable(raw_card_type));
3542  srcfetch->setEnabled(enable);
3543 }
3544 
3546 {
3547  if (value <= 1)
3548  schedgroup->setValue(false);
3549  schedgroup->setEnabled(value > 1);
3550 }
3551 
3552 QString CardInput::getSourceName(void) const
3553 {
3554  return sourceid->getSelectionLabel();
3555 }
3556 
3558 {
3559  QString new_name = QString::null;
3560  QString tmp_name = QString::null;
3561 
3562  inputgrp0->Save();
3563  inputgrp1->Save();
3564 
3565  while (true)
3566  {
3567  tmp_name = "";
3569  GetMythMainWindow(), tr("Create Input Group"),
3570  tr("Enter new group name"), tmp_name);
3571 
3572  if (!ok)
3573  return;
3574 
3575  if (tmp_name.isEmpty())
3576  {
3578  GetMythMainWindow(), tr("Error"),
3579  tr("Sorry, this Input Group name cannot be blank."));
3580  continue;
3581  }
3582 
3583  new_name = QString("user:") + tmp_name;
3584 
3585  MSqlQuery query(MSqlQuery::InitCon());
3586  query.prepare(
3587  "SELECT inputgroupname "
3588  "FROM inputgroup "
3589  "WHERE inputgroupname = :GROUPNAME");
3590  query.bindValue(":GROUPNAME", new_name);
3591 
3592  if (!query.exec())
3593  {
3594  MythDB::DBError("CreateNewInputGroup 1", query);
3595  return;
3596  }
3597 
3598  if (query.next())
3599  {
3601  GetMythMainWindow(), tr("Error"),
3602  tr("Sorry, this Input Group name is already in use."));
3603  continue;
3604  }
3605 
3606  break;
3607  }
3608 
3609  uint inputgroupid = CardUtil::CreateInputGroup(new_name);
3610 
3611  inputgrp0->Load();
3612  inputgrp1->Load();
3613 
3614  if (!inputgrp0->getValue().toUInt())
3615  {
3617  inputgrp0->getValueIndex(QString::number(inputgroupid)));
3618  }
3619  else
3620  {
3622  inputgrp1->getValueIndex(QString::number(inputgroupid)));
3623  }
3624 }
3625 
3627 {
3628  uint srcid = sourceid->getValue().toUInt();
3629  uint crdid = id->getValue().toUInt();
3630  QString in = inputname->getValue();
3631 
3632 #ifdef USING_BACKEND
3633  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3634 
3635  Save(); // save info for scanner.
3636 
3637  QString cardtype = CardUtil::GetRawInputType(crdid);
3638  if (CardUtil::IsUnscanable(cardtype))
3639  {
3640  LOG(VB_GENERAL, LOG_ERR,
3641  QString("Sorry, %1 cards do not yet support scanning.")
3642  .arg(cardtype));
3643  return;
3644  }
3645 
3646  ScanWizard *scanwizard = new ScanWizard(srcid, crdid, in);
3647  scanwizard->exec(false, true);
3648  scanwizard->deleteLater();
3649 
3650  if (SourceUtil::GetChannelCount(srcid))
3651  startchan->SetSourceID(QString::number(srcid));
3652  if (num_channels_before)
3653  {
3654  startchan->Load();
3655  startchan->Save();
3656  }
3657 #else
3658  LOG(VB_GENERAL, LOG_ERR, "You must compile the backend "
3659  "to be able to scan for channels");
3660 #endif
3661 }
3662 
3664 {
3665  uint srcid = sourceid->getValue().toUInt();
3666  uint crdid = id->getValue().toUInt();
3667 
3668  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3669 
3670  if (crdid && srcid)
3671  {
3672  Save(); // save info for fetch..
3673 
3674  QString cardtype = CardUtil::GetRawInputType(crdid);
3675 
3676  if (!CardUtil::IsCableCardPresent(crdid, cardtype) &&
3677  !CardUtil::IsUnscanable(cardtype) &&
3678  !CardUtil::IsEncoder(cardtype) &&
3679  !num_channels_before)
3680  {
3681  LOG(VB_GENERAL, LOG_ERR, "Skipping channel fetch, you need to "
3682  "scan for channels first.");
3683  return;
3684  }
3685 
3686  SourceUtil::UpdateChannelsFromListings(srcid, cardtype);
3687  }
3688 
3689  if (SourceUtil::GetChannelCount(srcid))
3690  startchan->SetSourceID(QString::number(srcid));
3691  if (num_channels_before)
3692  {
3693  startchan->Load();
3694  startchan->Save();
3695  }
3696 }
3697 
3699 {
3700  QString cardinputidTag(":WHERECARDID");
3701 
3702  QString query("cardid = " + cardinputidTag);
3703 
3704  bindings.insert(cardinputidTag, m_parent.getInputID());
3705 
3706  return query;
3707 }
3708 
3710 {
3711  QString cardinputidTag(":SETCARDID");
3712  QString colTag(":SET" + GetColumnName().toUpper());
3713 
3714  QString query("cardid = " + cardinputidTag + ", " +
3715  GetColumnName() + " = " + colTag);
3716 
3717  bindings.insert(cardinputidTag, m_parent.getInputID());
3718  bindings.insert(colTag, user->GetDBValue());
3719 
3720  return query;
3721 }
3722 
3723 void CardInput::loadByID(int inputid)
3724 {
3725  id->setValue(inputid);
3726  externalInputSettings->Load(inputid);
3728 }
3729 
3730 void CardInput::loadByInput(int _cardid, QString _inputname)
3731 {
3732  MSqlQuery query(MSqlQuery::InitCon());
3733  query.prepare("SELECT cardid FROM capturecard "
3734  "WHERE cardid = :CARDID AND inputname = :INPUTNAME");
3735  query.bindValue(":CARDID", _cardid);
3736  query.bindValue(":INPUTNAME", _inputname);
3737 
3738  if (query.exec() && query.isActive() && query.next())
3739  {
3740  loadByID(query.value(0).toInt());
3741  }
3742 }
3743 
3745 {
3746  uint cardid = id->getValue().toUInt();
3747  QString init_input = CardUtil::GetInputName(cardid);
3750 
3751  uint icount = 1;
3752  if (instancecount)
3753  icount = instancecount->getValue().toUInt();
3754  vector<uint> cardids = CardUtil::GetChildInputIDs(cardid);
3755 
3756  // Delete old clone cards as required.
3757  for (uint i = cardids.size() + 1;
3758  (i > icount) && !cardids.empty(); --i)
3759  {
3760  CardUtil::DeleteCard(cardids.back());
3761  cardids.pop_back();
3762  }
3763 
3764  // Clone this config to existing clone cards.
3765  for (uint i = 0; i < cardids.size(); ++i)
3766  {
3767  CardUtil::CloneCard(cardid, cardids[i]);
3768  }
3769 
3770  // Create new clone cards as required.
3771  for (uint i = cardids.size() + 1; i < icount; i++)
3772  {
3773  CardUtil::CloneCard(cardid, 0);
3774  }
3775 
3776  // Delete any unused input groups
3778 }
3779 
3781 {
3782  return m_parent.getInputID();
3783 }
3784 
3786 {
3787  return m_parent.getCardID();
3788 }
3789 
3791 {
3792  listbox->setLabel(tr("Capture cards"));
3793  addChild(listbox);
3794 }
3795 
3797 {
3799  edit();
3800 
3801  return kDialogCodeRejected;
3802 }
3803 
3805 {
3807  listbox->addSelection(QObject::tr("(New capture card)"), "0");
3808  listbox->addSelection(QObject::tr("(Delete all capture cards on %1)")
3809  .arg(gCoreContext->GetHostName()), "-1");
3810  listbox->addSelection(QObject::tr("(Delete all capture cards)"), "-2");
3812 }
3813 
3815  const char* widgetName)
3816 {
3817  dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
3818  connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(menu()));
3819  connect(dialog, SIGNAL(editButtonPressed()), this, SLOT(edit()));
3820  connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(del()));
3821  return dialog;
3822 }
3823 
3825 {
3826  if (!listbox->getValue().toInt())
3827  {
3828  CaptureCard cc;
3829  cc.exec();
3830  }
3831  else
3832  {
3835  "",
3836  tr("Capture Card Menu"),
3837  tr("Edit..."),
3838  tr("Delete..."),
3840 
3841  if (kDialogCodeButton0 == val)
3842  edit();
3843  else if (kDialogCodeButton1 == val)
3844  del();
3845  }
3846 }
3847 
3849 {
3850  const int cardid = listbox->getValue().toInt();
3851  if (-1 == cardid)
3852  {
3854  GetMythMainWindow(), "",
3855  tr("Are you sure you want to delete "
3856  "ALL capture cards on %1?").arg(gCoreContext->GetHostName()),
3857  tr("Yes, delete capture cards"),
3858  tr("No, don't"), kDialogCodeButton1);
3859 
3860  if (kDialogCodeButton0 == val)
3861  {
3862  MSqlQuery cards(MSqlQuery::InitCon());
3863 
3864  cards.prepare(
3865  "SELECT cardid "
3866  "FROM capturecard "
3867  "WHERE hostname = :HOSTNAME");
3868  cards.bindValue(":HOSTNAME", gCoreContext->GetHostName());
3869 
3870  if (!cards.exec() || !cards.isActive())
3871  {
3874  tr("Error getting list of cards for this host"),
3875  tr("Unable to delete capturecards for %1")
3876  .arg(gCoreContext->GetHostName()));
3877 
3878  MythDB::DBError("Selecting cardids for deletion", cards);
3879  return;
3880  }
3881 
3882  while (cards.next())
3883  CardUtil::DeleteCard(cards.value(0).toUInt());
3884  }
3885  }
3886  else if (-2 == cardid)
3887  {
3889  GetMythMainWindow(), "",
3890  tr("Are you sure you want to delete "
3891  "ALL capture cards?"),
3892  tr("Yes, delete capture cards"),
3893  tr("No, don't"), kDialogCodeButton1);
3894 
3895  if (kDialogCodeButton0 == val)
3896  {
3898  Load();
3899  }
3900  }
3901  else
3902  {
3903  CaptureCard cc;
3904  if (cardid)
3905  cc.loadByID(cardid);
3906  cc.exec();
3907  }
3908 }
3909 
3911 {
3913  GetMythMainWindow(), "",
3914  tr("Are you sure you want to delete this capture card?"),
3915  tr("Yes, delete capture card"),
3916  tr("No, don't"), kDialogCodeButton1);
3917 
3918  if (kDialogCodeButton0 == val)
3919  {
3920  CardUtil::DeleteCard(listbox->getValue().toUInt());
3921  Load();
3922  }
3923 }
3924 
3926 {
3927  listbox->setLabel(tr("Video sources"));
3928  addChild(listbox);
3929 }
3930 
3932  const char* widgetName)
3933 {
3934  dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
3935  connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(menu()));
3936  connect(dialog, SIGNAL(editButtonPressed()), this, SLOT(edit()));
3937  connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(del()));
3938  return dialog;
3939 }
3940 
3942 {
3944  edit();
3945 
3946  return kDialogCodeRejected;
3947 }
3948 
3950 {
3952  listbox->addSelection(QObject::tr("(New video source)"), "0");
3953  listbox->addSelection(QObject::tr("(Delete all video sources)"), "-1");
3955 }
3956 
3958 {
3959  if (!listbox->getValue().toInt())
3960  {
3961  VideoSource vs;
3962  vs.exec();
3963  }
3964  else
3965  {
3968  "",
3969  tr("Video Source Menu"),
3970  tr("Edit..."),
3971  tr("Delete..."),
3973 
3974  if (kDialogCodeButton0 == val)
3975  edit();
3976  else if (kDialogCodeButton1 == val)
3977  del();
3978  }
3979 }
3980 
3982 {
3983  const int sourceid = listbox->getValue().toInt();
3984  if (-1 == sourceid)
3985  {
3987  GetMythMainWindow(), "",
3988  tr("Are you sure you want to delete "
3989  "ALL video sources?"),
3990  tr("Yes, delete video sources"),
3991  tr("No, don't"), kDialogCodeButton1);
3992 
3993  if (kDialogCodeButton0 == val)
3994  {
3996  Load();
3997  }
3998  }
3999  else
4000  {
4001  VideoSource vs;
4002  if (sourceid)
4003  vs.loadByID(sourceid);
4004  vs.exec();
4005  }
4006 }
4007 
4009 {
4011  GetMythMainWindow(), "",
4012  tr("Are you sure you want to delete "
4013  "this video source?"),
4014  tr("Yes, delete video source"),
4015  tr("No, don't"),
4017 
4018  if (kDialogCodeButton0 == val)
4019  {
4021  Load();
4022  }
4023 }
4024 
4026 {
4027  listbox->setLabel(tr("Input connections"));
4028  addChild(listbox);
4029 }
4030 
4032 {
4034  {
4035  if (!listbox)
4036  return kDialogCodeRejected;
4037 
4038  if (cardinputs.empty())
4039  return kDialogCodeRejected;
4040 
4041  int val = listbox->getValue().toInt();
4042 
4043  if (cardinputs[val])
4044  cardinputs[val]->exec();
4045  }
4046 
4047  return kDialogCodeRejected;
4048 }
4049 
4051 {
4052  cardinputs.clear();
4054 
4055  // We do this manually because we want custom labels. If
4056  // SelectSetting provided a facility to edit the labels, we
4057  // could use CaptureCard::fillSelections
4058 
4059  MSqlQuery query(MSqlQuery::InitCon());
4060  query.prepare(
4061  "SELECT cardid, videodevice, cardtype, inputname "
4062  "FROM capturecard "
4063  "WHERE hostname = :HOSTNAME "
4064  " AND parentid = 0 "
4065  "ORDER BY cardid");
4066  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
4067 
4068  if (!query.exec())
4069  {
4070  MythDB::DBError("CardInputEditor::load", query);
4071  return;
4072  }
4073 
4074  uint j = 0;
4075  QMap<QString, uint> device_refs;
4076  while (query.next())
4077  {
4078  uint cardid = query.value(0).toUInt();
4079  QString videodevice = query.value(1).toString();
4080  QString cardtype = query.value(2).toString();
4081  QString inputname = query.value(3).toString();
4082 
4083  CardInput *cardinput = new CardInput(cardtype, videodevice,
4084  true, cardid);
4085  cardinput->loadByID(cardid);
4086  QString inputlabel = QString("%1 (%2) -> %3")
4087  .arg(CardUtil::GetDeviceLabel(cardtype, videodevice))
4088  .arg(inputname).arg(cardinput->getSourceName());
4089  cardinputs.push_back(cardinput);
4090  listbox->addSelection(inputlabel, QString::number(j++));
4091  }
4092 }
4093 
4094 #ifdef USING_DVB
4095 static QString remove_chaff(const QString &name)
4096 {
4097  // Trim off some of the chaff.
4098  QString short_name = name;
4099  if (short_name.startsWith("LG Electronics"))
4100  short_name = short_name.right(short_name.length() - 15);
4101  if (short_name.startsWith("Oren"))
4102  short_name = short_name.right(short_name.length() - 5);
4103  if (short_name.startsWith("Nextwave"))
4104  short_name = short_name.right(short_name.length() - 9);
4105  if (short_name.startsWith("frontend", Qt::CaseInsensitive))
4106  short_name = short_name.left(short_name.length() - 9);
4107  if (short_name.endsWith("VSB/QAM"))
4108  short_name = short_name.left(short_name.length() - 8);
4109  if (short_name.endsWith("VSB"))
4110  short_name = short_name.left(short_name.length() - 4);
4111  if (short_name.endsWith("DVB-T"))
4112  short_name = short_name.left(short_name.length() - 6);
4113 
4114  // It would be infinitely better if DVB allowed us to query
4115  // the vendor ID. But instead we have to guess based on the
4116  // demodulator name. This means cards like the Air2PC HD5000
4117  // and DViCO Fusion HDTV cards are not identified correctly.
4118  short_name = short_name.simplified();
4119  if (short_name.startsWith("or51211", Qt::CaseInsensitive))
4120  short_name = "pcHDTV HD-2000";
4121  else if (short_name.startsWith("or51132", Qt::CaseInsensitive))
4122  short_name = "pcHDTV HD-3000";
4123  else if (short_name.startsWith("bcm3510", Qt::CaseInsensitive))
4124  short_name = "Air2PC v1";
4125  else if (short_name.startsWith("nxt2002", Qt::CaseInsensitive))
4126  short_name = "Air2PC v2";
4127  else if (short_name.startsWith("nxt200x", Qt::CaseInsensitive))
4128  short_name = "Air2PC v2";
4129  else if (short_name.startsWith("lgdt3302", Qt::CaseInsensitive))
4130  short_name = "DViCO HDTV3";
4131  else if (short_name.startsWith("lgdt3303", Qt::CaseInsensitive))
4132  short_name = "DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
4133 
4134  return short_name;
4135 }
4136 #endif // USING_DVB
4137 
4138 void DVBConfigurationGroup::reloadDiseqcTree(const QString &videodevice)
4139 {
4140  if (diseqc_tree)
4141  diseqc_tree->Load(videodevice);
4142 }
4143 
4144 void DVBConfigurationGroup::probeCard(const QString &videodevice)
4145 {
4146  if (videodevice.isEmpty())
4147  {
4148  cardname->setValue("");
4149  cardtype->setValue("");
4150  return;
4151  }
4152 
4153  if (parent.getCardID() && parent.GetRawCardType() != "DVB")
4154  {
4155  cardname->setValue("");
4156  cardtype->setValue("");
4157  return;
4158  }
4159 
4160 #ifdef USING_DVB
4161  QString frontend_name = CardUtil::ProbeDVBFrontendName(videodevice);
4162  QString subtype = CardUtil::ProbeDVBType(videodevice);
4163 
4164  QString err_open = tr("Could not open card %1").arg(videodevice);
4165  QString err_other = tr("Could not get card info for card %1").arg(videodevice);
4166 
4167  switch (CardUtil::toInputType(subtype))
4168  {
4169  case CardUtil::ERROR_OPEN:
4170  cardname->setValue(err_open);
4171  cardtype->setValue(strerror(errno));
4172  break;
4174  cardname->setValue(err_other);
4175  cardtype->setValue("Unknown error");
4176  break;
4177  case CardUtil::ERROR_PROBE:
4178  cardname->setValue(err_other);
4179  cardtype->setValue(strerror(errno));
4180  break;
4181  case CardUtil::QPSK:
4182  cardtype->setValue("DVB-S");
4183  cardname->setValue(frontend_name);
4184  signal_timeout->setValue(7000);
4185  channel_timeout->setValue(10000);
4186  break;
4187  case CardUtil::DVBS2:
4188  cardtype->setValue("DVB-S2");
4189  cardname->setValue(frontend_name);
4190  signal_timeout->setValue(7000);
4191  channel_timeout->setValue(10000);
4192  break;
4193  case CardUtil::QAM:
4194  cardtype->setValue("DVB-C");
4195  cardname->setValue(frontend_name);
4196  signal_timeout->setValue(1000);
4197  channel_timeout->setValue(3000);
4198  break;
4199  case CardUtil::DVBT2:
4200  cardtype->setValue("DVB-T2");
4201  cardname->setValue(frontend_name);
4202  signal_timeout->setValue(1000);
4203  channel_timeout->setValue(3000);
4204  break;
4205  case CardUtil::OFDM:
4206  {
4207  cardtype->setValue("DVB-T");
4208  cardname->setValue(frontend_name);
4209  signal_timeout->setValue(1000);
4210  channel_timeout->setValue(3000);
4211  if (frontend_name.toLower().indexOf("usb") >= 0)
4212  {
4213  signal_timeout->setValue(40000);
4214  channel_timeout->setValue(42500);
4215  }
4216 
4217  // slow down tuning for buggy drivers
4218  if ((frontend_name == "DiBcom 3000P/M-C DVB-T") ||
4219  (frontend_name ==
4220  "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
4221  {
4222  tuning_delay->setValue(200);
4223  }
4224 
4225 #if 0 // frontends on hybrid DVB-T/Analog cards
4226  QString short_name = remove_chaff(frontend_name);
4227  buttonAnalog->setVisible(
4228  short_name.startsWith("zarlink zl10353",
4229  Qt::CaseInsensitive) ||
4230  short_name.startsWith("wintv hvr 900 m/r: 65008/a1c0",
4231  Qt::CaseInsensitive) ||
4232  short_name.startsWith("philips tda10046h",
4233  Qt::CaseInsensitive));
4234 #endif
4235  }
4236  break;
4237  case CardUtil::ATSC:
4238  {
4239  QString short_name = remove_chaff(frontend_name);
4240  cardtype->setValue("ATSC");
4241  cardname->setValue(short_name);
4242  signal_timeout->setValue(500);
4243  channel_timeout->setValue(3000);
4244 
4245  // According to #1779 and #1935 the AverMedia 180 needs
4246  // a 3000 ms signal timeout, at least for QAM tuning.
4247  if (frontend_name == "Nextwave NXT200X VSB/QAM frontend")
4248  {
4249  signal_timeout->setValue(3000);
4250  channel_timeout->setValue(5500);
4251  }
4252 
4253 #if 0 // frontends on hybrid DVB-T/Analog cards
4254  if (frontend_name.toLower().indexOf("usb") < 0)
4255  {
4256  buttonAnalog->setVisible(
4257  short_name.startsWith("pchdtv", Qt::CaseInsensitive) ||
4258  short_name.startsWith("dvico", Qt::CaseInsensitive) ||
4259  short_name.startsWith("nextwave", Qt::CaseInsensitive));
4260  }
4261 #endif
4262  }
4263  break;
4264  default:
4265  break;
4266  }
4267 #else
4268  cardtype->setValue(QString("Recompile with DVB-Support!"));
4269 #endif
4270 }
4271 
4273  QString dev, QString type) :
4274  ComboBoxSetting(this), CaptureCardDBStorage(this, parent, "audiodevice"),
4275  last_device(dev), last_cardtype(type)
4276 {
4277  setLabel(QObject::tr("Audio input"));
4278  setHelpText(QObject::tr("If there is more than one audio input, "
4279  "select which one to use."));
4280  int cardid = parent.getCardID();
4281  if (cardid <= 0)
4282  return;
4283 
4286 }
4287 
4288 void TunerCardAudioInput::fillSelections(const QString &device)
4289 {
4290  clearSelections();
4291 
4292  if (device.isEmpty())
4293  return;
4294 
4295  last_device = device;
4296  QStringList inputs =
4298 
4299  for (uint i = 0; i < (uint)inputs.size(); i++)
4300  {
4301  addSelection(inputs[i], QString::number(i),
4302  last_device == QString::number(i));
4303  }
4304 }
4305 
4307 {
4308  public:
4309  explicit DVBExtra(DVBConfigurationGroup &parent);
4310 };
4311 
4313 {
4315  rec->setLabel(QObject::tr("Recorder Options"));
4316  rec->setUseLabel(false);
4317 
4318  rec->addChild(new DVBNoSeqStart(parent.parent));
4319  rec->addChild(new DVBOnDemand(parent.parent));
4320  rec->addChild(new DVBEITScan(parent.parent));
4321  rec->addChild(new DVBTuningDelay(parent.parent));
4322 
4323  addChild(rec);
4324 }
4325 
4328  parent(a_parent),
4329  diseqc_tree(new DiSEqCDevTree())
4330 {
4331  cardnum = new DVBCardNum(parent);
4332  cardname = new DVBCardName();
4333  cardtype = new DVBCardType();
4334 
4335  signal_timeout = new SignalTimeout(parent, 500, 250);
4336  channel_timeout = new ChannelTimeout(parent, 3000, 1750);
4337 
4338  addChild(cardnum);
4339 
4341  new HorizontalConfigurationGroup(false, false, true, true);
4342  hg0->addChild(cardname);
4343  hg0->addChild(cardtype);
4344  addChild(hg0);
4345 
4348 
4351 
4352  TransButtonSetting *buttonRecOpt = new TransButtonSetting();
4353  buttonRecOpt->setLabel(tr("Recording Options"));
4354 
4356  new HorizontalConfigurationGroup(false, false, true, true);
4357  advcfg->addChild(buttonRecOpt);
4358  addChild(advcfg);
4359 
4361  diseqc_btn->setLabel(tr("DiSEqC (Switch, LNB, and Rotor Configuration)"));
4362  diseqc_btn->setHelpText(tr("Input and satellite settings."));
4363 
4364  HorizontalConfigurationGroup *diseqc_cfg =
4365  new HorizontalConfigurationGroup(false, false, true, true);
4366  diseqc_cfg->addChild(diseqc_btn);
4367  diseqc_btn->setVisible(false);
4368  addChild(diseqc_cfg);
4369 
4372  tuning_delay->setVisible(false);
4373 
4374  connect(cardnum, SIGNAL(valueChanged(const QString&)),
4375  this, SLOT( probeCard (const QString&)));
4376  connect(cardnum, SIGNAL(valueChanged(const QString&)),
4377  this, SLOT( reloadDiseqcTree(const QString&)));
4378  connect(diseqc_btn, SIGNAL(pressed()),
4379  this, SLOT( DiSEqCPanel()));
4380  connect(buttonRecOpt, SIGNAL(pressed()),
4381  this, SLOT( DVBExtraPanel()));
4382 }
4383 
4385 {
4386  if (diseqc_tree)
4387  {
4388  delete diseqc_tree;
4389  diseqc_tree = NULL;
4390  }
4391 }
4392 
4394 {
4395  parent.reload(); // ensure card id is valid
4396 
4397  DTVDeviceTreeWizard diseqcWiz(*diseqc_tree);
4398  diseqcWiz.exec();
4399 }
4400 
4402 {
4405  if (cardtype->getValue() == "DVB-S" ||
4406  cardtype->getValue() == "DVB-S2" ||
4408  {
4409  diseqc_btn->setVisible(true);
4410  }
4411 }
4412 
4414 {
4417  DiSEqCDev trees;
4418  trees.InvalidateTrees();
4419 }
4420 
4422 {
4423  parent.reload(); // ensure card id is valid
4424 
4425  DVBExtra acw(*this);
4426  acw.exec();
4427 }
void SetOldValue(const QString &s)
Definition: videosource.h:937
V4L2encGroup(CaptureCard &parent)
virtual void setValue(const QString &newValue)
Definition: settings.cpp:96
QStringList grabberArgs
Definition: videosource.h:179
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:794
TransButtonSetting * scan
Definition: videosource.h:896
HDHomeRunIP * _cardip
Definition: videosource.h:972
DataDirectUserID(const VideoSource &parent)
VBoxExtra(VBoxConfigurationGroup &parent)
QuickTune(const CardInput &parent)
void UpdateDevices(const QString &)
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:163
virtual void Load(void)
static QString remove_chaff(const QString &name)
void SetSourceID(uint _sourceid)
virtual void Load(void)
virtual void clearSelections(void)
Definition: settings.cpp:175
void setVisible(bool b)
Definition: settings.h:65
static QStringList ProbeVideoDevices(const QString &rawtype)
Definition: cardutil.cpp:350
virtual void setEnabled(bool e)
TransLabelSetting * cardinfo
Definition: videosource.h:495
virtual void setValue(bool check)
Definition: settings.h:434
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:893
DiSEqCDevSettings * externalInputSettings
Definition: videosource.h:898
vector< CardInput * > cardinputs
Definition: videosource.h:835
Definition: cc.h:13
QString getSourceName(void) const
Definition: videosource.h:237
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:244
DVB-S device settings class.
Definition: diseqc.h:37
TransButtonSetting * srcfetch
Definition: videosource.h:897
QString _tuner
Definition: videosource.h:1130
def scan(profile, smoonURL, gate)
Definition: scan.py:43
static QString GetInputName(uint inputid)
Definition: cardutil.cpp:1048
void fillSelections()
CaptureCard & parent
Definition: videosource.h:474
void valueChanged(const QString &)
virtual DialogCode exec(void)
virtual void Load(void)
QString Card(void) const
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:83
allow access to stdout
Definition: mythsystem.h:39
virtual void Save(void)
static QStringList GetVideoDevices(const QString &rawtype, QString hostname=QString::null)
Returns the videodevices of the matching inputs, duplicates removed.
Definition: cardutil.cpp:307
virtual MythDialog * dialogWidget(MythMainWindow *parent, const char *widgetName=0)
VideoDevice(const CaptureCard &parent, uint minor_min=0, uint minor_max=UINT_MAX, QString card=QString::null, QString driver=QString::null)
virtual void Load(void)
virtual void Load(void)
virtual void Save(void)
QString cardip
Definition: videosource.h:421
void probeCard(const QString &device)
HDHomeRunDeviceIDList(HDHomeRunDeviceID *deviceid, TransLabelSetting *desc, HDHomeRunIP *cardip, HDHomeRunTunerIndex *cardtuner, HDHomeRunDeviceList *devicelist)
virtual void Save(void)
void setProgress(int curprogress)
virtual void setEnabled(bool b)
Definition: settings.cpp:688
CardType(const CaptureCard &parent)
static uint CreateInputGroup(const QString &name)
Definition: cardutil.cpp:1213
void probeCard(const QString &device)
virtual void deleteLater(void)
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:459
static DialogCode Show2ButtonPopup(MythMainWindow *parent, const QString &title, const QString &message, const QString &button1msg, const QString &button2msg, DialogCode default_button)
void SetSourceID(const QString &sourceid)
virtual QString getSelectionLabel(void) const
Definition: settings.cpp:213
TunerCardAudioInput(const CaptureCard &parent, QString dev=QString::null, QString type=QString::null)
EITOnly_config(const VideoSource &_parent)
ASIDevice(const CaptureCard &parent)
AudioRateLimit(const CaptureCard &parent)
virtual void Load(void)
NoGrabber_config(const VideoSource &_parent)
static uint GetChannelCount(uint sourceid)
Definition: sourceutil.cpp:109
bool visible
Definition: settings.h:91
uint modelid
Definition: avcinfo.h:44
SignalTimeout(const CaptureCard &parent, uint value, uint min_val)
static QString GetDeviceLabel(const QString &inputtype, const QString &videodevice)
Definition: cardutil.cpp:1797
static void error(const char *str,...)
Definition: vbi.c:41
static bool DeleteSource(uint sourceid)
Definition: sourceutil.cpp:479
SpinBoxSetting * instancecount
Definition: videosource.h:901
SchedGroup(const CardInput &parent)
virtual int getValueIndex(QString value)
Returns index of value in SelectSetting, or -1 if not found.
Definition: settings.cpp:224
virtual void setVisible(bool b)
Definition: settings.cpp:695
CetonDeviceID * deviceid
Definition: videosource.h:476
static enum INPUT_TYPES toInputType(const QString &name)
Definition: cardutil.h:74
TransLabelSetting * desc
Definition: videosource.h:475
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
ScheduleOrder(const CardInput &parent, int _value)
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 QString GetWhereClause(MSqlBindings &bindings) const
static QString ProbeDVBFrontendName(const QString &device)
Returns the input type from the video device.
Definition: cardutil.cpp:509
LiveTVOrder(const CardInput &parent, int _value)
void setName(const QString &str)
Definition: settings.h:47
CetonExtra(CetonConfigurationGroup &parent)
virtual void Load(void)
DVBExtra(DVBConfigurationGroup &parent)
QString _overridedeviceid
Definition: videosource.h:996
static bool IsInNeedOfExternalInputConf(uint inputid)
Definition: cardutil.cpp:1477
QString label
Definition: settings.h:89
CheckBoxSetting * schedgroup
Definition: videosource.h:902
int size(void) const
Definition: mythdbcon.h:187
QString deviceid
Definition: videosource.h:419
static bool IsUnscanable(const QString &rawtype)
Definition: cardutil.h:145
bool cardTypesInclude(const int &SourceID, const QString &thecardtype)
InputGroup(const CardInput &parent, uint group_num)
FirewireModel(const CaptureCard &parent, const FirewireGUID *)
DVBEITScan(const CaptureCard &parent)
CaptureCard & parent
Definition: videosource.h:450
virtual void addChild(Configurable *child)
virtual DialogCode exec(void)
voidpf void uLong size
Definition: ioapi.h:136
bool IsOpen(void) const
Definition: v4l2util.h:29
void CreateNewInputGroup()
virtual void setEnabled(bool e)
HDHomeRunDeviceList * _devicelist
Definition: videosource.h:974
InputDisplayName(const CardInput &parent)
ChannelTimeout * channel_timeout
Definition: videosource.h:654
const char * filename
Definition: ioapi.h:135
virtual void setValue(const QString &newValue)
Definition: settings.cpp:707
unsigned int uint
Definition: compat.h:136
int getCardID(void) const
Definition: videosource.h:709
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
TransLabelSetting * cardinfo
Definition: videosource.h:569
unsigned current
Definition: settings.h:311
SourceID * sourceid
Definition: videosource.h:894
V4LConfigurationGroup(CaptureCard &parent)
QString product_name
Definition: avcinfo.h:46
TransLabelSetting * info
Definition: videosource.h:600
DataDirectPassword * password
Definition: videosource.h:155
IPTVHost(const CaptureCard &parent)
QString getSourceName(void) const
CetonDeviceID(const CaptureCard &parent)
virtual DialogCode exec(void)
VBoxConfigurationGroup(CaptureCard &parent)
__u32 index
Definition: videodev2.h:1039
HDHomeRunDeviceID * _deviceid
Definition: videosource.h:970
ListBoxSetting * listbox
Definition: videosource.h:836
TransLabelSetting * cardinfo
Definition: videosource.h:516
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
QMap< QString, VBoxDevice > VBoxDeviceList
Definition: videosource.h:428
VideoSourceSelector(uint _initial_sourceid, const QString &_card_types, bool _must_have_mplexid)
Definition: videosource.cpp:62
void UpdateDevices(const QString &)
virtual void setEnabled(bool e)
CaptureCard & parent
Definition: videosource.h:494
bool ProbeCard(HDHomeRunDevice &)
InputGroup * inputgrp0
Definition: videosource.h:899
void probeApp(const QString &path)
QMap< QString, HDHomeRunDevice > HDHomeRunDeviceList
Definition: videosource.h:383
static bool HasTuner(const QString &rawtype, const QString &device)
Definition: cardutil.cpp:160
DVBTuningDelay(const CaptureCard &parent)
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:137
virtual MythDialog * dialogWidget(MythMainWindow *parent, const char *widgetName=0)
bool Store(uint cardid, const QString &device="")
Stores the device tree to the database.
Definition: diseqc.cpp:434
virtual void Save(void)
__u32 type
Definition: videodev2.h:1038
virtual void Load(void)
void SetOldValue(const QString &s)
Definition: videosource.h:916
void probeCard(const QString &device)
virtual void Load(void)
Definition: videosource.cpp:74
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:1524
virtual void addChild(Configurable *child)
CaptureCard & parent
Definition: videosource.h:648
void LoadedTuner(const QString &)
void UpdateDevices(const QString &)
virtual void setHelpText(const QString &str)
Definition: settings.h:61
virtual void addSelection(const QString &label, QString value=QString::null, bool select=false)
Definition: settings.cpp:843
void SetTuner(const QString &)
const char * name
Definition: frequencies.h:102
static bool IsEncoder(const QString &rawtype)
Definition: cardutil.h:123
DVBConfigurationGroup(CaptureCard &a_parent)
virtual void setLabel(QString)
Definition: settings.cpp:1194
ExternalConfigurationGroup(CaptureCard &parent)
QString deviceid
Definition: videosource.h:375
void fillSelections(const QString &current)
Adds all available cards to list If current is >= 0 it will be considered available even if no device...
virtual void Load(void)
static void fillSelections(SelectSetting *setting)
QString GetConfDir(void)
Definition: mythdirs.cpp:212
void addSelection(const QString &label, QString value=QString::null, bool select=false)
Definition: settings.cpp:1018
QVariant value(int i) const
Definition: mythdbcon.h:182
void loadByID(int id)
void probeCard(const QString &device)
FirewireConfigurationGroup(CaptureCard &a_parent)
void removeTarget(QString triggerValue)
VBoxTunerIndex * _cardtuner
Definition: videosource.h:1067
void sourceFetch()
static QString GetVBoxdesc(const QString &id, const QString &ip, const QString &tunerNo, const QString &tunerType)
Get a nicely formatted string describing the device.
Definition: cardutil.cpp:2194
CaptureCard(bool use_card_group=true)
DDLineupList GetLineups(void) const
Definition: datadirect.h:343
static bool showGetTextPopup(MythMainWindow *parent, QString title, QString message, QString &text)
virtual void Load(void)
Definition: mythstorage.cpp:7
QString cardtuner
Definition: videosource.h:378
void SetTuner(const QString &)
DataDirectLineupSelector * lineupselector
Definition: videosource.h:157
static vector< AVCInfo > GetSTBList(void)
void UpdateSchedGroup(int value)
DataDirect_config(const VideoSource &_parent, int _ddsource)
const FirewireGUID * guid
Definition: videosource.h:675
QMap< QString, Configurable * > triggerMap
SourceID(const CardInput &parent)
static QStringList ProbeAudioInputs(QString device, QString inputtype=QString::null)
Definition: cardutil.cpp:1700
struct CHANLISTS chanlists[]
const char * name
Definition: ParseText.cpp:338
void loadByInput(int cardid, QString input)
virtual void setEnabled(bool b)
Definition: settings.cpp:1187
static QString TestMimeType(const QString &sFileName)
void fillSelections()
virtual QString GetValue(uint i) const
Definition: settings.h:289
void SetIP(const QString &)
DialogCode
Definition: mythdialogs.h:21
virtual void addSelection(const QString &label, QString value=QString::null, bool select=false)
Definition: settings.cpp:115
void probeCard(const QString &device)
int errno
TunerCardAudioInput * audioinput
Definition: videosource.h:532
FileDevice(const CaptureCard &parent)
int getCardID(void) const
void fillSelections(const QString &current)
Adds all available device-tuner combinations to list.
void LoadedIP(const QString &)
InputName(const CardInput &parent)
void SetOldValue(const QString &s)
Definition: videosource.h:1011
virtual void Load(void)
QMap< uint, uint > minor_list
AudioDevice(const CaptureCard &parent)
run process through shell
Definition: mythsystem.h:41
TransLabelSetting * m_cardinfo
Definition: videosource.h:547
bool isEnabled()
Definition: settings.h:69
virtual void setEnabled(bool e)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString GetSetting(const QString &key, const QString &defaultval="")
CaptureCard & parent
Definition: videosource.h:513
QByteArray & ReadAll()
static QString GetDeviceName(dvb_dev_type_t, const QString &device)
Definition: cardutil.cpp:2080
static bool IsCableCardPresent(uint inputid, const QString &inputType)
Definition: cardutil.cpp:116
static uint GetDeviceInputGroup(uint inputid)
Definition: cardutil.cpp:1267
TransFreqTableSelector(uint _sourceid)
XMLTVGrabber * grabber
Definition: videosource.h:221
void UpdateDevices(const QString &)
__u64 val
Definition: videodev2.h:1041
TransButtonSetting * diseqc_btn
Definition: videosource.h:660
static void fillSelections(SelectSetting *setting)
DishNetEIT(const CardInput &parent)
bool isActive(void) const
Definition: mythdbcon.h:188
virtual void Save(void)
QString Driver(void) const
virtual void Load(void)
QString tunertype
Definition: videosource.h:423
CetonSetting * tuner
Definition: videosource.h:478
DataDirectButton * button
Definition: videosource.h:156
void SetGUID(const QString &)
VBoxDeviceID * _deviceid
Definition: videosource.h:1064
TransLabelSetting * cardinfo
Definition: videosource.h:531
bool Store(uint card_input_id) const
Stores configuration chain to DB for specified card input id.
Definition: diseqc.cpp:171
ASIConfigurationGroup(CaptureCard &parent)
bool discovered
Definition: videosource.h:425
void SetTuner(const QString &)
CaptureCard & parent
Definition: videosource.h:530
virtual void Save(void)
VBoxDeviceID(const CaptureCard &parent)
TransLabelSetting * _desc
Definition: videosource.h:971
void SetGUID(const QString &)
virtual QString GetWhereClause(MSqlBindings &bindings) const
QString mythdeviceid
Definition: videosource.h:374
static vector< uint > GetChildInputIDs(uint inputid)
Definition: cardutil.cpp:708
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1331
virtual void Load(void)
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
static QString GetModelName(uint vendorid, uint modelid)
void LoadValue(const QString &)
uint vendorid
Definition: avcinfo.h:43
XMLTVConfig(const VideoSource &aparent)
QString _overridedeviceid
Definition: videosource.h:1090
virtual void Load(void)
AVCInfo GetAVCInfo(const QString &guid) const
SignalTimeout * signal_timeout
Definition: videosource.h:653
virtual void Save(void)
TransLabelSetting * info
Definition: videosource.h:584
virtual void triggerChanged(const QString &value)
FirewireConnection(const CaptureCard &parent)
CetonConfigurationGroup(CaptureCard &parent)
virtual DialogCode exec(void)
DVBCardName * cardname
Definition: videosource.h:651
void addSelection(const QString &label, QString value=QString::null, bool select=false)
Definition: settings.cpp:733
IPTVConfigurationGroup(CaptureCard &a_parent)
const CardInput & cardinput
static int GetASIDeviceNumber(const QString &device, QString *error=NULL)
Definition: cardutil.cpp:2266
CaptureCard & m_parent
Definition: videosource.h:546
static bool CloneCard(uint src_inputid, uint dst_inputid)
Definition: cardutil.cpp:885
ListBoxSetting * listbox
Definition: videosource.h:788
CetonSetting(const char *label, const char *helptext)
A ConfigurationDialog that uses a ConfigurationGroup with one child per page.
Base dialog for most dialogs in MythTV using the old UI.
Definition: mythdialogs.h:50
virtual void Load(void)
void fillDataDirectLineupSelector(void)
MPEGConfigurationGroup(CaptureCard &parent)
DVBOnDemand(const CaptureCard &parent)
InputPriority(const CardInput &parent)
MythMainWindow * GetMythMainWindow(void)
HDHomeRunEITScan(const CaptureCard &parent)
virtual void Save(void)
Definition: mythstorage.cpp:83
uint Wait(time_t timeout=0)
virtual void setEnabled(bool b)
Definition: settings.cpp:342
void SetIP(const QString &)
virtual void triggerChanged(const QString &value)
static bool showOkPopup(MythMainWindow *parent, const QString &title, const QString &message, QString button_msg=QString())
XMLTV_generic_config(const VideoSource &_parent, QString _grabber)
vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:121
void SetIP(const QString &)
static const uint kDefaultMultirecCount
Definition: videosource.cpp:60
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:273
void LoadXMLTVGrabbers(QStringList name_list, QStringList prog_list)
ImportConfigurationGroup(CaptureCard &parent)
virtual void Save(void)
virtual void Save(QString)
virtual void Load(void)
DataDirectUserID * userid
Definition: videosource.h:154
InputGroup * inputgrp1
Definition: videosource.h:900
VERBOSE_PREAMBLE Most Errors or other very important messages true
Definition: verbosedefs.h:91
void UpdateDevices(const QString &)
DiSEqCDevTree * diseqc_tree
Definition: videosource.h:659
__u32 id
Definition: videodev2.h:1038
virtual void clearSelections(void)
Definition: settings.cpp:1011
virtual void Save(void)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:819
QString tunerno
Definition: videosource.h:422
struct v4l2_dbg_match match
Definition: videodev2.h:1038
static void fillSelections(SelectSetting *setting)
DataDirectPassword(const VideoSource &parent)
SkipBtAudio(const CaptureCard &parent)
CardInput(const QString &cardtype, const QString &device, bool is_new_input, int cardid)
VideoDevice * device
Definition: videosource.h:514
CaptureCard & parent
Definition: videosource.h:599
const VideoSource & parent
Definition: videosource.h:220
HDHomeRunDeviceID(const CaptureCard &parent)
virtual void triggerChanged(const QString &value)
UseEIT(const VideoSource &parent)
VerticalConfigurationGroup(bool luselabel=true, bool luseframe=true, bool lzeroMargin=false, bool lzeroSpace=false)
CaptureCardGroup(CaptureCard &parent)
void probeCard(const QString &cardNumber)
vector< DataDirectLineup > DDLineupList
Definition: datadirect.h:299
QString card_name
static QString GetAudioDevice(uint inputid)
Definition: cardutil.h:275
static bool Exists(int id)
Check if a Diseqc device tree exists.
Definition: diseqc.cpp:406
QString GetListingsProviderName(void) const
Definition: datadirect.h:351
HDHomeRunExtra(HDHomeRunConfigurationGroup &parent)
QMap< QString, AVCInfo > guid_to_avcinfo
void SetOldValue(const QString &s)
Definition: videosource.h:1032
void fillSelections(const QString &device)
InstanceCount(const CardInput &parent, int _initValue)
virtual uint size(void) const
Definition: settings.h:285
QString m_DriverName
Definition: videosource.h:549
virtual DialogCode exec(bool saveOnExec=false, bool doLoad=false)
virtual void setHelpText(const QString &str)
Definition: settings.cpp:793
DVBNetID(const VideoSource &parent, signed int value, signed int min_val)
void probeCard(const QString &device)
static bool DeleteAllSources(void)
Definition: sourceutil.cpp:531
HDPVRConfigurationGroup(CaptureCard &parent)
TransLabelSetting * _desc
Definition: videosource.h:1065
StartingChannel * startchan
Definition: videosource.h:895
void channelScanner()
virtual void setLabel(QString str)
Definition: settings.h:57
virtual DialogCode exec(bool saveOnExec=true, bool doLoad=true)
ListBoxSetting * listbox
Definition: videosource.h:817
static bool UpdateChannelsFromListings(uint sourceid, QString inputtype=QString::null, bool wait=false)
Definition: sourceutil.cpp:362
void SetOverrideDeviceID(const QString &)
virtual QString getValue(void) const
Definition: settings.cpp:91
DVBCardNum * cardnum
Definition: videosource.h:650
virtual QString GetSetClause(MSqlBindings &bindings) const
DVBNoSeqStart(const CaptureCard &parent)
void loadByID(int id)
void UpdateDevices(const QString &)
void InvalidateTrees(void)
Invalidate cached trees.
Definition: diseqc.cpp:256
ChannelTimeout(const CaptureCard &parent, uint value, uint min_val)
VBoxDeviceList * _devicelist
Definition: videosource.h:1068
XMLTVGrabber(const VideoSource &parent)
void setUseLabel(bool useit)
DVBCardType * cardtype
Definition: videosource.h:652
void probeCard(const QString &device)
DemoConfigurationGroup(CaptureCard &parent)
virtual void Load(void)
VBIDevice(const CaptureCard &parent)
static bool DeleteCard(uint inputid)
Definition: cardutil.cpp:1929
void reload(void)
HDHomeRunTunerIndex * _cardtuner
Definition: videosource.h:973
virtual void setVisible(bool b)
Definition: settings.cpp:918
static QString GetRawInputType(uint inputid)
Definition: cardutil.h:271
void setTrigger(Configurable *_trigger)
void fillSelections(const QString &current)
Adds all available device-tuner combinations to list If current is >= 0 it will be considered availab...
void fillSelectionsFromDir(const QDir &dir, bool absPath=true)
bool GrabLineupsOnly(void)
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)
int getSourceID(void) const
Definition: videosource.h:230
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
virtual QString GetSetClause(MSqlBindings &bindings) const
VBoxDeviceIDList(VBoxDeviceID *deviceid, TransLabelSetting *desc, VBoxIP *cardip, VBoxTunerIndex *cardtuner, VBoxDeviceList *devicelist)
virtual void setSaveAll(bool b)
static bool GetListingsLoginData(uint sourceid, QString &grabber, QString &userid, QString &passwd, QString &lineupid)
Definition: sourceutil.cpp:144
QString helptext
Definition: settings.h:90
int getInputID(void) const
static bool LinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1291
FirewireGUID(const CaptureCard &parent)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:181
void reloadDiseqcTree(const QString &device)
virtual void Load(void)
FirewireSpeed(const CaptureCard &parent)
uint fillSelectionsFromDir(const QDir &dir, uint minor_min, uint minor_max, QString card, QString driver, bool allow_duplicates)
DVBTuningDelay * tuning_delay
Definition: videosource.h:658
virtual QString GetWhereClause(MSqlBindings &bindings) const
QString desc
Definition: videosource.h:420
void fillSelectionsFromDir(const QDir &dir, bool absPath=true)
ArgumentString(const CaptureCard &parent)
virtual void setHelpText(const QString &)
Definition: settings.cpp:1201
virtual void Save()
static bool DeleteAllCards(void)
Definition: cardutil.cpp:2005
QString GetRawCardType(void) const
QString GetHostName(void)
QString driver_name
virtual QString GetSetClause(MSqlBindings &bindings) const
QString _tuner
Definition: videosource.h:1089
DVBCardNum(const CaptureCard &parent)
__s32 value
Definition: videodev2.h:1042
bool HasSlicedVBI(void) const
Definition: v4l2util.cpp:131
const VideoSource & parent
Definition: videosource.h:153
DVB-S device tree class.
Definition: diseqc.h:75
uint fillSelectionsFromDir(const QDir &dir, const QString &card, const QString &driver)
QString DriverName(void) const
Definition: v4l2util.h:45
InputName * inputname
Definition: videosource.h:893
void setFilter(const QString &card, const QString &driver)
TransLabelSetting * info
Definition: videosource.h:617
QString CardName(void) const
Definition: v4l2util.h:46
const VideoSource & parent
Definition: videosource.h:177
UseEIT * useeit
Definition: videosource.h:191
void SetSourceID(const QString &sourceid)
HDHomeRunConfigurationGroup(CaptureCard &parent)
PresetTuner(const CardInput &parent)