MythTV  0.28pre
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  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  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  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  DataDirectUserID(const VideoSource &parent) :
356  LineEditSetting(this), VideoSourceDBStorage(this, parent, "userid")
357  {
358  setLabel(QObject::tr("User ID"));
359  }
360 };
361 
363 {
364  public:
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:
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:
944  LineEditSetting(this, true),
945  CaptureCardDBStorage(this, parent, "audiodevice") // change to arguments
946  {
947  setLabel(QObject::tr("Arguments"));
948  }
949 };
950 
952 {
953  public:
955  PathSetting(this, false),
956  CaptureCardDBStorage(this, parent, "videodevice")
957  {
958  setLabel(QObject::tr("File path"));
959  };
960 };
961 
963 {
964  public:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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  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  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:
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  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, 1000, 250));
2259  rec->addChild(new ChannelTimeout(parent.parent, 3000, 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 
2290  TransButtonSetting *buttonRecOpt = new TransButtonSetting();
2291  buttonRecOpt->setLabel(tr("Recording Options"));
2292  addChild(buttonRecOpt);
2293 
2294  connect(buttonRecOpt, SIGNAL(pressed()),
2295  this, SLOT( VBoxExtraPanel()));
2296 
2297  connect(cardip, SIGNAL(NewIP(const QString&)),
2298  deviceid, SLOT( SetIP(const QString&)));
2299  connect(cardtuner, SIGNAL(NewTuner(const QString&)),
2300  deviceid, SLOT( SetTuner(const QString&)));
2301 };
2302 
2304 {
2305  devicelist.clear();
2306 
2307  // Find physical devices first
2308  // ProbeVideoDevices returns "deviceid ip tunerno tunertype"
2309  QStringList devs = CardUtil::ProbeVideoDevices("VBOX");
2310 
2311  QStringList::const_iterator it;
2312 
2313  for (it = devs.begin(); it != devs.end(); ++it)
2314  {
2315  QString dev = *it;
2316  QStringList devinfo = dev.split(" ");
2317  QString id = devinfo.at(0);
2318  QString ip = devinfo.at(1);
2319  QString tunerNo = devinfo.at(2);
2320  QString tunerType = devinfo.at(3);
2321 
2322  VBoxDevice tmpdevice;
2323  tmpdevice.deviceid = id;
2324  tmpdevice.desc = CardUtil::GetVBoxdesc(id, ip, tunerNo, tunerType);
2325  tmpdevice.cardip = ip;
2326  tmpdevice.inuse = false;
2327  tmpdevice.discovered = true;
2328  tmpdevice.tunerno = tunerNo;
2329  tmpdevice.tunertype = tunerType;
2330  tmpdevice.mythdeviceid = id + "-" + tunerNo + "-" + tunerType;
2331  devicelist[tmpdevice.mythdeviceid] = tmpdevice;
2332  }
2333 
2334  // Now find configured devices
2335 
2336  // returns "ip.ip.ip.ip-n-type" or deviceid-n-type values
2337  QStringList db = CardUtil::GetVideoDevices("VBOX");
2338 
2339  for (it = db.begin(); it != db.end(); ++it)
2340  {
2341  QMap<QString, VBoxDevice>::iterator dit;
2342  dit = devicelist.find(*it);
2343 
2344  if (dit != devicelist.end())
2345  (*dit).inuse = true;
2346  }
2347 }
2348 
2350 {
2351  parent.reload(); // ensure card id is valid
2352 
2353  VBoxExtra acw(*this);
2354  acw.exec();
2355 }
2356 
2357 // -----------------------
2358 // Ceton Configuration
2359 // -----------------------
2360 
2361 CetonSetting::CetonSetting(const char* label, const char* helptext)
2362 {
2363  setLabel(QObject::tr(label));
2364  setHelpText(tr(helptext));
2365  connect(this, SIGNAL(valueChanged( const QString&)),
2366  this, SLOT( UpdateDevices(const QString&)));
2367 }
2368 
2369 void CetonSetting::UpdateDevices(const QString &v)
2370 {
2371  if (isEnabled())
2372  emit NewValue(v);
2373 }
2374 
2375 void CetonSetting::LoadValue(const QString &value)
2376 {
2377  setValue(value);
2378 }
2379 
2381  LabelSetting(this),
2382  CaptureCardDBStorage(this, parent, "videodevice"),
2383  _ip(), _card(), _tuner(), _parent(parent)
2384 {
2385  setLabel(tr("Device ID"));
2386  setHelpText(tr("Device ID of Ceton device"));
2387 }
2388 
2389 void CetonDeviceID::SetIP(const QString &ip)
2390 {
2391  QString regexp = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){4}$";
2392  if (QRegExp(regexp).exactMatch(ip + "."))
2393  {
2394  _ip = ip;
2395  setValue(QString("%1-RTP.%3").arg(_ip).arg(_tuner));
2396  }
2397 }
2398 
2399 void CetonDeviceID::SetTuner(const QString &tuner)
2400 {
2401  if (QRegExp("^\\d$").exactMatch(tuner))
2402  {
2403  _tuner = tuner;
2404  setValue(QString("%1-RTP.%2").arg(_ip).arg(_tuner));
2405  }
2406 }
2407 
2409 {
2411  UpdateValues();
2412 }
2413 
2415 {
2416  QRegExp newstyle("^([0-9.]+)-(\\d|RTP)\\.(\\d)$");
2417  if (newstyle.exactMatch(getValue()))
2418  {
2419  emit LoadedIP(newstyle.cap(1));
2420  emit LoadedTuner(newstyle.cap(3));
2421  }
2422 }
2423 
2425 {
2426  public:
2428 };
2429 
2431 {
2433  rec->setLabel(QObject::tr("Recorder Options"));
2434  rec->setUseLabel(false);
2435 
2436  rec->addChild(new SignalTimeout(parent.parent, 1000, 250));
2437  rec->addChild(new ChannelTimeout(parent.parent, 3000, 1750));
2438 
2439  addChild(rec);
2440 }
2441 
2442 
2445  parent(a_parent)
2446 {
2447  setUseLabel(false);
2448 
2449  deviceid = new CetonDeviceID(parent);
2450  desc = new TransLabelSetting();
2451  desc->setLabel(tr("Description"));
2452  ip = new CetonSetting(
2453  "IP Address",
2454  "IP Address of the Ceton device (192.168.200.1 by default)");
2455  tuner = new CetonSetting(
2456  "Tuner",
2457  "Number of the tuner on the Ceton device (first tuner is number 0)");
2458 
2459  addChild(ip);
2460  addChild(tuner);
2461  addChild(deviceid);
2462  addChild(desc);
2463 
2464  TransButtonSetting *buttonRecOpt = new TransButtonSetting();
2465  buttonRecOpt->setLabel(tr("Recording Options"));
2466  addChild(buttonRecOpt);
2467 
2468  connect(ip, SIGNAL(NewValue(const QString&)),
2469  deviceid, SLOT( SetIP(const QString&)));
2470  connect(tuner, SIGNAL(NewValue(const QString&)),
2471  deviceid, SLOT( SetTuner(const QString&)));
2472 
2473  connect(deviceid, SIGNAL(LoadedIP(const QString&)),
2474  ip, SLOT( LoadValue(const QString&)));
2475  connect(deviceid, SIGNAL(LoadedTuner(const QString&)),
2476  tuner, SLOT( LoadValue(const QString&)));
2477 
2478  connect(buttonRecOpt, SIGNAL(pressed()),
2479  this, SLOT( CetonExtraPanel()));
2480 
2481 };
2482 
2484 {
2485  parent.reload(); // ensure card id is valid
2486 
2487  CetonExtra acw(*this);
2488  acw.exec();
2489 }
2490 
2491 
2494  parent(a_parent),
2495  cardinfo(new TransLabelSetting()), vbidev(new VBIDevice(parent))
2496 {
2497  QString drv = "(?!ivtv|hdpvr|(saa7164(.*))).*";
2498  VideoDevice *device = new VideoDevice(parent, 0, 15, QString::null, drv);
2500  new HorizontalConfigurationGroup(false, false, true, true);
2501 
2502  audgrp->addChild(new AudioRateLimit(parent));
2503  audgrp->addChild(new SkipBtAudio(parent));
2504 
2505  addChild(device);
2506  cardinfo->setLabel(tr("Probed info"));
2507  addChild(cardinfo);
2508 
2509  addChild(vbidev);
2510  addChild(new AudioDevice(parent));
2511  addChild(audgrp);
2512 
2513  connect(device, SIGNAL(valueChanged(const QString&)),
2514  this, SLOT( probeCard( const QString&)));
2515 
2516  probeCard(device->getValue());
2517 };
2518 
2519 void V4LConfigurationGroup::probeCard(const QString &device)
2520 {
2521  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2522 
2523  QByteArray adevice = device.toLatin1();
2524  int videofd = open(adevice.constData(), O_RDWR);
2525  if (videofd >= 0)
2526  {
2527  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2528  ci = cn = tr("Failed to probe");
2529  else if (!dn.isEmpty())
2530  ci = cn + " [" + dn + "]";
2531  close(videofd);
2532  }
2533 
2534  cardinfo->setValue(ci);
2535  vbidev->setFilter(cn, dn);
2536 }
2537 
2540  parent(a_parent),
2541  device(NULL), vbidevice(NULL),
2543 {
2544  QString drv = "ivtv|(saa7164(.*))";
2545  device = new VideoDevice(parent, 0, 15, QString::null, drv);
2546  vbidevice = new VBIDevice(parent);
2547  vbidevice->setVisible(false);
2548 
2549  cardinfo->setLabel(tr("Probed info"));
2550 
2551  addChild(device);
2553  addChild(cardinfo);
2554  addChild(new ChannelTimeout(parent, 12000, 2000));
2555 
2556  connect(device, SIGNAL(valueChanged(const QString&)),
2557  this, SLOT( probeCard( const QString&)));
2558 
2560 }
2561 
2563 {
2564  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2565 
2566  QByteArray adevice = device.toLatin1();
2567  int videofd = open(adevice.constData(), O_RDWR);
2568  if (videofd >= 0)
2569  {
2570  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2571  ci = cn = tr("Failed to probe");
2572  else if (!dn.isEmpty())
2573  ci = cn + " [" + dn + "]";
2574  close(videofd);
2575  }
2576 
2577  cardinfo->setValue(ci);
2578  vbidevice->setVisible(dn!="ivtv");
2579  vbidevice->setFilter(cn, dn);
2580 }
2581 
2584  parent(a_parent),
2585  info(new TransLabelSetting()), size(new TransLabelSetting())
2586 {
2587  FileDevice *device = new FileDevice(parent);
2588  device->setHelpText(tr("A local MPEG file used to simulate a recording."
2589  " Must be entered as file:/path/movie.mpg"));
2590  device->addSelection("file:/");
2591  addChild(device);
2592 
2595 
2596  info->setLabel(tr("File info"));
2597  addChild(info);
2598 
2599  size->setLabel(tr("File size"));
2600  addChild(size);
2601 
2602  connect(device, SIGNAL(valueChanged(const QString&)),
2603  this, SLOT( probeCard( const QString&)));
2604 
2605  probeCard(device->getValue());
2606 }
2607 
2608 void DemoConfigurationGroup::probeCard(const QString &device)
2609 {
2610  if (!device.startsWith("file:", Qt::CaseInsensitive))
2611  {
2612  info->setValue("");
2613  size->setValue("");
2614  return;
2615  }
2616 
2617 
2618  QString ci, cs;
2619  QFileInfo fileInfo(device.mid(5));
2620  if (fileInfo.exists())
2621  {
2622  if (fileInfo.isReadable() && (fileInfo.isFile()))
2623  {
2624  ci = HTTPRequest::TestMimeType(fileInfo.absoluteFilePath());
2625  cs = tr("%1 MB").arg(fileInfo.size() / 1024 / 1024);
2626  }
2627  else
2628  ci = tr("File not readable");
2629  }
2630  else
2631  {
2632  ci = tr("File does not exist");
2633  }
2634 
2635  info->setValue(ci);
2636  size->setValue(cs);
2637 }
2638 
2639 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2642  parent(a_parent),
2643  info(new TransLabelSetting())
2644 {
2645  FileDevice *device = new FileDevice(parent);
2646  device->setHelpText(tr("A 'black box' application controlled via "
2647  "stdin, status on stderr and TransportStream "
2648  "read from stdout"));
2649  addChild(device);
2650 
2651  info->setLabel(tr("File info"));
2652  addChild(info);
2653 
2654  connect(device, SIGNAL(valueChanged(const QString&)),
2655  this, SLOT( probeApp( const QString&)));
2656 
2657  probeApp(device->getValue());
2658 }
2659 
2660 void ExternalConfigurationGroup::probeApp(const QString & path)
2661 {
2662  int idx1 = path.toLower().startsWith("file:") ? 5 : 0;
2663  int idx2 = path.indexOf(' ', idx1);
2664 
2665  QString ci, cs;
2666  QFileInfo fileInfo(path.mid(idx1, idx2 - idx1));
2667 
2668  if (fileInfo.exists())
2669  {
2670  ci = tr("'%1' is valid.").arg(fileInfo.absoluteFilePath());
2671  if (!fileInfo.isReadable() || !fileInfo.isFile())
2672  ci = tr("'%1' is not readable.").arg(fileInfo.absoluteFilePath());
2673  if (!fileInfo.isExecutable())
2674  ci = tr("'%1' is not executable.").arg(fileInfo.absoluteFilePath());
2675  }
2676  else
2677  {
2678  ci = tr("'%1' does not exist.").arg(fileInfo.absoluteFilePath());
2679  }
2680 
2681  info->setValue(ci);
2682 }
2683 #endif // !defined( USING_MINGW ) && !defined( _MSC_VER )
2684 
2687  parent(a_parent), cardinfo(new TransLabelSetting()),
2688  audioinput(new TunerCardAudioInput(parent, QString::null, "HDPVR")),
2689  vbidevice(NULL)
2690 {
2691  VideoDevice *device =
2692  new VideoDevice(parent, 0, 15, QString::null, "hdpvr");
2693 
2694  cardinfo->setLabel(tr("Probed info"));
2695 
2696  addChild(device);
2699  addChild(cardinfo);
2701  addChild(new ChannelTimeout(parent, 15000, 2000));
2702 
2703  connect(device, SIGNAL(valueChanged(const QString&)),
2704  this, SLOT( probeCard( const QString&)));
2705 
2706  probeCard(device->getValue());
2707 }
2708 
2709 void HDPVRConfigurationGroup::probeCard(const QString &device)
2710 {
2711  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2712 
2713  int videofd = open(device.toLocal8Bit().constData(), O_RDWR);
2714  if (videofd >= 0)
2715  {
2716  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2717  ci = cn = tr("Failed to probe");
2718  else if (!dn.isEmpty())
2719  ci = cn + " [" + dn + "]";
2720  close(videofd);
2721  }
2722 
2723  cardinfo->setValue(ci);
2724  audioinput->fillSelections(device);
2725 }
2726 
2729  m_parent(parent),
2730  m_cardinfo(new TransLabelSetting())
2731 {
2732  setLabel(QObject::tr("V4L2 encoder devices (multirec capable)"));
2733  VideoDevice *device = new VideoDevice(m_parent, 0, 15);
2734 
2735  addChild(device);
2736  m_cardinfo->setLabel(tr("Probed info"));
2738 
2739  // Choose children to show based on which device is active
2740  setTrigger(device);
2741  // Only save settings for 'this' device.
2742  setSaveAll(false);
2743 
2744  connect(device, SIGNAL(valueChanged(const QString&)),
2745  this, SLOT( probeCard( const QString&)));
2746 
2747  probeCard(device->getValue());
2748 }
2749 
2750 void V4L2encGroup::triggerChanged(const QString& dev_path)
2751 {
2752  probeCard(dev_path);
2754 }
2755 
2756 void V4L2encGroup::probeCard(const QString &device_name)
2757 {
2758 #ifdef USING_V4L2
2759  QString card_name = tr("Failed to open");
2760  QString card_info = card_name;
2761  V4L2util v4l2(device_name);
2762 
2763  if (!v4l2.IsOpen())
2764  {
2765  m_DriverName = tr("Failed to probe");
2766  return;
2767  }
2768  m_DriverName = v4l2.DriverName();
2769  card_name = v4l2.CardName();
2770 
2771  if (!m_DriverName.isEmpty())
2772  card_info = card_name + " [" + m_DriverName + "]";
2773 
2774  m_cardinfo->setValue(card_info);
2775 
2777  QMap<QString,Configurable*>::iterator it = triggerMap.find(m_DriverName);
2778  if (it == triggerMap.end())
2779  {
2780  grp = new VerticalConfigurationGroup(false);
2781 
2782  TunerCardAudioInput* audioinput =
2783  new TunerCardAudioInput(m_parent, QString::null, "V4L2");
2784  audioinput->fillSelections(device_name);
2785  if (audioinput->size() > 1)
2786  {
2787  audioinput->setName("AudioInput");
2788  grp->addChild(audioinput);
2789  }
2790  else
2791  delete audioinput;
2792 
2793  if (v4l2.HasSlicedVBI())
2794  {
2795  VBIDevice* vbidev = new VBIDevice(m_parent);
2796  vbidev->setFilter(card_name, m_DriverName);
2797  if (vbidev->size() > 0)
2798  {
2799  vbidev->setName("VBIDevice");
2800  grp->addChild(vbidev);
2801  }
2802  else
2803  delete vbidev;
2804  }
2805 
2806  grp->addChild(new EmptyVBIDevice(m_parent));
2807  grp->addChild(new ChannelTimeout(m_parent, 15000, 2000));
2808 
2809  addTarget(m_DriverName, grp);
2810  }
2811 #endif // USING_V4L2
2812 }
2813 
2816 {
2817  setLabel(QObject::tr("Capture Card Setup"));
2818 
2819  CardType* cardtype = new CardType(parent);
2820  addChild(cardtype);
2821 
2822  setTrigger(cardtype);
2823  setSaveAll(false);
2824 
2825 #ifdef USING_DVB
2826  addTarget("DVB", new DVBConfigurationGroup(parent));
2827 #endif // USING_DVB
2828 
2829 #ifdef USING_V4L2
2830 # ifdef USING_HDPVR
2831  addTarget("HDPVR", new HDPVRConfigurationGroup(parent));
2832 # endif // USING_HDPVR
2833 #endif // USING_V4L2
2834 
2835 #ifdef USING_HDHOMERUN
2836  addTarget("HDHOMERUN", new HDHomeRunConfigurationGroup(parent));
2837 #endif // USING_HDHOMERUN
2838 
2839 #ifdef USING_VBOX
2840  addTarget("VBOX", new VBoxConfigurationGroup(parent));
2841 #endif // USING_VBOX
2842 
2843 #ifdef USING_FIREWIRE
2844  addTarget("FIREWIRE", new FirewireConfigurationGroup(parent));
2845 #endif // USING_FIREWIRE
2846 
2847 #ifdef USING_CETON
2848  addTarget("CETON", new CetonConfigurationGroup(parent));
2849 #endif // USING_CETON
2850 
2851 #ifdef USING_IPTV
2852  addTarget("FREEBOX", new IPTVConfigurationGroup(parent));
2853 #endif // USING_IPTV
2854 
2855 #ifdef USING_V4L2
2856  addTarget("V4L2ENC", new V4L2encGroup(parent));
2857  addTarget("V4L", new V4LConfigurationGroup(parent));
2858 # ifdef USING_IVTV
2859  addTarget("MPEG", new MPEGConfigurationGroup(parent));
2860 # endif // USING_IVTV
2861 #endif // USING_V4L2
2862 
2863 #ifdef USING_ASI
2864  addTarget("ASI", new ASIConfigurationGroup(parent));
2865 #endif // USING_ASI
2866 
2867  // for testing without any actual tuner hardware:
2868  addTarget("IMPORT", new ImportConfigurationGroup(parent));
2869  addTarget("DEMO", new DemoConfigurationGroup(parent));
2870 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2871  addTarget("EXTERNAL", new ExternalConfigurationGroup(parent));
2872 #endif
2873 }
2874 
2876 {
2877  QString own = (value == "MJPEG" || value == "GO7007") ? "V4L" : value;
2879 }
2880 
2881 CaptureCard::CaptureCard(bool use_card_group)
2882  : id(new ID)
2883 {
2884  addChild(id);
2885  if (use_card_group)
2886  addChild(new CaptureCardGroup(*this));
2887  addChild(new Hostname(*this));
2888 }
2889 
2890 QString CaptureCard::GetRawCardType(void) const
2891 {
2892  int cardid = getCardID();
2893  if (cardid <= 0)
2894  return QString::null;
2895  return CardUtil::GetRawInputType(cardid);
2896 }
2897 
2899 {
2900  MSqlQuery query(MSqlQuery::InitCon());
2901  QString qstr =
2902  "SELECT cardid, videodevice, cardtype "
2903  "FROM capturecard "
2904  "WHERE hostname = :HOSTNAME AND parentid = 0 "
2905  "ORDER BY cardid";
2906 
2907  query.prepare(qstr);
2908  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
2909 
2910  if (!query.exec())
2911  {
2912  MythDB::DBError("CaptureCard::fillSelections", query);
2913  return;
2914  }
2915 
2916  while (query.next())
2917  {
2918  uint cardid = query.value(0).toUInt();
2919  QString videodevice = query.value(1).toString();
2920  QString cardtype = query.value(2).toString();
2921  QString label = CardUtil::GetDeviceLabel(cardtype, videodevice);
2922  setting->addSelection(label, QString::number(cardid));
2923  }
2924 }
2925 
2926 void CaptureCard::loadByID(int cardid)
2927 {
2928  id->setValue(cardid);
2929  Load();
2930 }
2931 
2933 {
2934  uint init_cardid = getCardID();
2935  QString init_type = CardUtil::GetRawInputType(init_cardid);
2936  QString init_dev = CardUtil::GetVideoDevice(init_cardid);
2937  QString init_input = CardUtil::GetInputName(init_cardid);
2938 
2940 
2942 
2944 
2945  uint cardid = getCardID();
2946  QString type = CardUtil::GetRawInputType(cardid);
2947  QString dev = CardUtil::GetVideoDevice(cardid);
2948 
2949  if (dev != init_dev)
2950  {
2951  if (!init_dev.isEmpty())
2952  {
2953  uint init_groupid = CardUtil::GetDeviceInputGroup(init_cardid);
2954  CardUtil::UnlinkInputGroup(init_cardid, init_groupid);
2955  }
2956  if (!dev.isEmpty())
2957  {
2958  uint groupid =
2959  CardUtil::CreateDeviceInputGroup(cardid, type,
2960  gCoreContext->GetHostName(), dev);
2961  CardUtil::LinkInputGroup(cardid, groupid);
2962  CardUtil::UnlinkInputGroup(0, groupid);
2963  }
2964  }
2965 
2966  // Handle any cloning we may need to do
2968  {
2969  vector<uint> clones = CardUtil::GetChildInputIDs(cardid);
2970  for (uint i = 0; i < clones.size(); i++)
2971  CardUtil::CloneCard(cardid, clones[i]);
2972  }
2973 }
2974 
2976 {
2977  if (getCardID() == 0)
2978  {
2979  Save();
2980  Load();
2981  }
2982 }
2983 
2985  ComboBoxSetting(this),
2986  CaptureCardDBStorage(this, parent, "cardtype")
2987 {
2988  setLabel(QObject::tr("Card type"));
2989  setHelpText(QObject::tr("Change the cardtype to the appropriate type for "
2990  "the capture card you are configuring."));
2991  fillSelections(this);
2992 }
2993 
2995 {
2996 #ifdef USING_DVB
2997  setting->addSelection(
2998  QObject::tr("DVB-T/S/C, ATSC or ISDB-T tuner card"), "DVB");
2999 #endif // USING_DVB
3000 
3001 #ifdef USING_V4L2
3002  setting->addSelection(
3003  QObject::tr("V4L2 encoder"), "V4L2ENC");
3004 #ifdef USING_HDPVR
3005  setting->addSelection(
3006  QObject::tr("HD-PVR H.264 encoder"), "HDPVR");
3007 # endif // USING_HDPVR
3008 #endif // USING_V4L2
3009 
3010 #ifdef USING_HDHOMERUN
3011  setting->addSelection(
3012  QObject::tr("HDHomeRun networked tuner"), "HDHOMERUN");
3013 #endif // USING_HDHOMERUN
3014 
3015 #ifdef USING_VBOX
3016  setting->addSelection(
3017  QObject::tr("V@Box TV Gateway networked tuner"), "VBOX");
3018 #endif // USING_VBOX
3019 
3020 #ifdef USING_FIREWIRE
3021  setting->addSelection(
3022  QObject::tr("FireWire cable box"), "FIREWIRE");
3023 #endif // USING_FIREWIRE
3024 
3025 #ifdef USING_CETON
3026  setting->addSelection(
3027  QObject::tr("Ceton Cablecard tuner"), "CETON");
3028 #endif // USING_CETON
3029 
3030 #ifdef USING_IPTV
3031  setting->addSelection(QObject::tr("IPTV recorder"), "FREEBOX");
3032 #endif // USING_IPTV
3033 
3034 #ifdef USING_V4L2
3035 # ifdef USING_IVTV
3036  setting->addSelection(
3037  QObject::tr("Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"), "MPEG");
3038 # endif // USING_IVTV
3039  setting->addSelection(
3040  QObject::tr("Analog to MJPEG encoder card (Matrox G200, DC10, etc)"), "MJPEG");
3041  setting->addSelection(
3042  QObject::tr("Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
3043  "GO7007");
3044  setting->addSelection(
3045  QObject::tr("Analog capture card"), "V4L");
3046 #endif // USING_V4L2
3047 
3048 #ifdef USING_ASI
3049  setting->addSelection(QObject::tr("DVEO ASI recorder"), "ASI");
3050 #endif
3051 
3052  setting->addSelection(QObject::tr("Import test recorder"), "IMPORT");
3053  setting->addSelection(QObject::tr("Demo test recorder"), "DEMO");
3054 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
3055  setting->addSelection(QObject::tr("External (black box) recorder"),
3056  "EXTERNAL");
3057 #endif
3058 }
3059 
3061 {
3062  public:
3063  InputName(const CardInput &parent) :
3064  ComboBoxSetting(this), CardInputDBStorage(this, parent, "inputname")
3065  {
3066  setLabel(QObject::tr("Input name"));
3067  };
3068 
3069  virtual void Load(void)
3070  {
3071  fillSelections();
3073  };
3074 
3076  clearSelections();
3077  addSelection(QObject::tr("(None)"), "None");
3078  uint cardid = getInputID();
3079  QString type = CardUtil::GetRawInputType(cardid);
3080  QString device = CardUtil::GetVideoDevice(cardid);
3081  QStringList inputs;
3082  CardUtil::GetDeviceInputNames(cardid, device, type, inputs);
3083  while (!inputs.isEmpty())
3084  {
3085  addSelection(inputs.front());
3086  inputs.pop_front();
3087  }
3088  };
3089 };
3090 
3092 {
3093  public:
3094  InputDisplayName(const CardInput &parent) :
3095  LineEditSetting(this),
3096  CardInputDBStorage(this, parent, "displayname")
3097  {
3098  setLabel(QObject::tr("Display name (optional)"));
3099  setHelpText(QObject::tr(
3100  "This name is displayed on screen when Live TV begins "
3101  "and when changing the selected input or card. If you "
3102  "use this, make sure the information is unique for "
3103  "each input."));
3104  };
3105 };
3106 
3108 {
3109  public:
3110  SourceID(const CardInput &parent) :
3111  ComboBoxSetting(this), CardInputDBStorage(this, parent, "sourceid")
3112  {
3113  setLabel(QObject::tr("Video source"));
3114  addSelection(QObject::tr("(None)"), "0");
3115  };
3116 
3117  virtual void Load(void)
3118  {
3119  fillSelections();
3121  };
3122 
3124  clearSelections();
3125  addSelection(QObject::tr("(None)"), "0");
3127  };
3128 };
3129 
3131 {
3132  public:
3133  InputGroup(const CardInput &parent, uint group_num) :
3134  TransComboBoxSetting(false), cardinput(parent),
3135  groupnum(group_num), groupid(0)
3136  {
3137  setLabel(QObject::tr("Input group") +
3138  QString(" %1").arg(groupnum + 1));
3139  setHelpText(QObject::tr(
3140  "Leave as 'Generic' unless this input is shared with "
3141  "another device. Only one of the inputs in an input "
3142  "group will be allowed to record at any given time."));
3143  }
3144 
3145  virtual void Load(void);
3146 
3147  virtual void Save(void)
3148  {
3149  uint inputid = cardinput.getInputID();
3150  uint new_groupid = getValue().toUInt();
3151 
3152  if (groupid)
3153  CardUtil::UnlinkInputGroup(inputid, groupid);
3154 
3155  if (new_groupid)
3156  {
3157  if (CardUtil::UnlinkInputGroup(inputid, new_groupid))
3158  CardUtil::LinkInputGroup(inputid, new_groupid);
3159  }
3160  }
3161 
3162  virtual void Save(QString /*destination*/) { Save(); }
3163 
3164  private:
3168 };
3169 
3171 {
3172 #if 0
3173  LOG(VB_GENERAL, LOG_DEBUG, QString("InputGroup::Load() %1 %2")
3174  .arg(groupnum).arg(cardinput.getInputID()));
3175 #endif
3176 
3177  uint inputid = cardinput.getInputID();
3178  QMap<uint, uint> grpcnt;
3179  vector<QString> names;
3180  vector<uint> grpid;
3181  vector<uint> selected_groupids;
3182 
3183  names.push_back(QObject::tr("Generic"));
3184  grpid.push_back(0);
3185  grpcnt[0]++;
3186 
3187  MSqlQuery query(MSqlQuery::InitCon());
3188  query.prepare(
3189  "SELECT cardinputid, inputgroupid, inputgroupname "
3190  "FROM inputgroup "
3191  "WHERE inputgroupname LIKE 'user:%' "
3192  "ORDER BY inputgroupid, cardinputid, inputgroupname");
3193 
3194  if (!query.exec())
3195  {
3196  MythDB::DBError("InputGroup::Load()", query);
3197  }
3198  else
3199  {
3200  while (query.next())
3201  {
3202  uint groupid = query.value(1).toUInt();
3203  if (inputid && (query.value(0).toUInt() == inputid))
3204  selected_groupids.push_back(groupid);
3205 
3206  grpcnt[groupid]++;
3207 
3208  if (grpcnt[groupid] == 1)
3209  {
3210  names.push_back(query.value(2).toString().mid(5, -1));
3211  grpid.push_back(groupid);
3212  }
3213  }
3214  }
3215 
3216  // makes sure we select something
3217  groupid = 0;
3218  if (groupnum < selected_groupids.size())
3219  groupid = selected_groupids[groupnum];
3220 
3221 #if 0
3222  LOG(VB_GENERAL, LOG_DEBUG, QString("Group num: %1 id: %2")
3223  .arg(groupnum).arg(groupid));
3224  {
3225  QString msg;
3226  for (uint i = 0; i < selected_groupids.size(); i++)
3227  msg += QString("%1 ").arg(selected_groupids[i]);
3228  LOG(VB_GENERAL, LOG_DEBUG, msg);
3229  }
3230 #endif
3231 
3232  // add selections to combobox
3233  clearSelections();
3234  uint index = 0;
3235  for (uint i = 0; i < names.size(); i++)
3236  {
3237  bool sel = (groupid == grpid[i]);
3238  index = (sel) ? i : index;
3239 
3240 #if 0
3241  LOG(VB_GENERAL, LOG_DEBUG, QString("grpid %1, name '%2', i %3, s %4")
3242  .arg(grpid[i]).arg(names[i]) .arg(index).arg(sel ? "T" : "F"));
3243 #endif
3244 
3245  addSelection(names[i], QString::number(grpid[i]), sel);
3246  }
3247 
3248 #if 0
3249  LOG(VB_GENERAL, LOG_DEBUG, QString("Group index: %1").arg(index));
3250 #endif
3251 
3252  if (!names.empty())
3253  setValue(index);
3254 }
3255 
3257 {
3258  public:
3259  QuickTune(const CardInput &parent) :
3260  ComboBoxSetting(this), CardInputDBStorage(this, parent, "quicktune")
3261  {
3262  setLabel(QObject::tr("Use quick tuning"));
3263  addSelection(QObject::tr("Never"), "0", true);
3264  addSelection(QObject::tr("Live TV only"), "1", false);
3265  addSelection(QObject::tr("Always"), "2", false);
3266  setHelpText(QObject::tr(
3267  "If enabled, MythTV will tune using only the "
3268  "MPEG program number. The program numbers "
3269  "change more often than DVB or ATSC tuning "
3270  "parameters, so this is slightly less reliable. "
3271  "This will also inhibit EIT gathering during "
3272  "Live TV and recording."));
3273  };
3274 };
3275 
3277  public LineEditSetting, public CardInputDBStorage
3278 {
3279  public:
3281  LineEditSetting(this),
3282  CardInputDBStorage(this, parent, "externalcommand")
3283  {
3284  setLabel(QObject::tr("External channel change command"));
3285  setValue("");
3286  setHelpText(QObject::tr("If specified, this command will be run to "
3287  "change the channel for inputs which have an external "
3288  "tuner device such as a cable box. The first argument "
3289  "will be the channel number."));
3290  };
3291 };
3292 
3294 {
3295  public:
3296  PresetTuner(const CardInput &parent) :
3297  LineEditSetting(this),
3298  CardInputDBStorage(this, parent, "tunechan")
3299  {
3300  setLabel(QObject::tr("Preset tuner to channel"));
3301  setValue("");
3302  setHelpText(QObject::tr("Leave this blank unless you have an external "
3303  "tuner that is connected to the tuner input of your card. "
3304  "If so, you will need to specify the preset channel for "
3305  "the signal (normally 3 or 4)."));
3306  };
3307 };
3308 
3309 void StartingChannel::SetSourceID(const QString &sourceid)
3310 {
3311  clearSelections();
3312  if (sourceid.isEmpty() || !sourceid.toUInt())
3313  return;
3314 
3315  // Get the existing starting channel
3316  QString startChan = CardUtil::GetStartingChannel(getInputID());
3317 
3318  ChannelInfoList channels = ChannelUtil::GetAllChannels(sourceid.toUInt());
3319 
3320  if (channels.empty())
3321  {
3322  addSelection(tr("Please add channels to this source"),
3323  startChan.isEmpty() ? "0" : startChan);
3324  return;
3325  }
3326 
3327  // If there are channels sort them, then add theme
3328  // (selecting the old start channel if it is there).
3329  QString order = gCoreContext->GetSetting("ChannelOrdering", "channum");
3330  ChannelUtil::SortChannels(channels, order);
3331  bool has_visible = false;
3332  for (uint i = 0; i < channels.size() && !has_visible; i++)
3333  has_visible |= channels[i].visible;
3334 
3335  for (uint i = 0; i < channels.size(); i++)
3336  {
3337  const QString channum = channels[i].channum;
3338  bool sel = channum == startChan;
3339  if (!has_visible || channels[i].visible || sel)
3340  {
3341  addSelection(channum, channum, sel);
3342  }
3343  }
3344 }
3345 
3347 {
3348  public:
3349  InputPriority(const CardInput &parent) :
3350  SpinBoxSetting(this, -99, 99, 1),
3351  CardInputDBStorage(this, parent, "recpriority")
3352  {
3353  setLabel(QObject::tr("Input priority"));
3354  setValue(0);
3355  setHelpText(QObject::tr("If the input priority is not equal for "
3356  "all inputs, the scheduler may choose to record a show "
3357  "at a later time so that it can record on an input with "
3358  "a higher value."));
3359  };
3360 };
3361 
3363 {
3364  public:
3365  ScheduleOrder(const CardInput &parent, int _value) :
3366  SpinBoxSetting(this, 0, 99, 1),
3367  CardInputDBStorage(this, parent, "schedorder")
3368  {
3369  setLabel(QObject::tr("Schedule order"));
3370  setValue(_value);
3371  setHelpText(QObject::tr("If priorities and other factors are equal "
3372  "the scheduler will choose the available "
3373  "input with the lowest, non-zero value. "
3374  "Setting this value to zero will make the "
3375  "input unavailable to the scheduler."));
3376  };
3377 };
3378 
3380 {
3381  public:
3382  LiveTVOrder(const CardInput &parent, int _value) :
3383  SpinBoxSetting(this, 0, 99, 1),
3384  CardInputDBStorage(this, parent, "livetvorder")
3385  {
3386  setLabel(QObject::tr("Live TV order"));
3387  setValue(_value);
3388  setHelpText(QObject::tr("When entering Live TV, the available, local "
3389  "input with the lowest, non-zero value will "
3390  "be used. If no local inputs are available, "
3391  "the available, remote input with the lowest, "
3392  "non-zero value will be used. "
3393  "Setting this value to zero will make the "
3394  "input unavailable to live TV."));
3395  };
3396 };
3397 
3399 {
3400  public:
3401  DishNetEIT(const CardInput &parent) :
3402  CheckBoxSetting(this),
3403  CardInputDBStorage(this, parent, "dishnet_eit")
3404  {
3405  setLabel(QObject::tr("Use DishNet long-term EIT data"));
3406  setValue(false);
3407  setHelpText(
3408  QObject::tr(
3409  "If you point your satellite dish toward DishNet's birds, "
3410  "you may wish to enable this feature. For best results, "
3411  "enable general EIT collection as well."));
3412  };
3413 };
3414 
3415 CardInput::CardInput(const QString & cardtype, const QString & device,
3416  bool isNewInput, int _cardid) :
3417  id(new ID()),
3418  inputname(new InputName(*this)),
3419  sourceid(new SourceID(*this)),
3420  startchan(new StartingChannel(*this)),
3421  scan(new TransButtonSetting()),
3422  srcfetch(new TransButtonSetting()),
3423  externalInputSettings(new DiSEqCDevSettings()),
3424  inputgrp0(new InputGroup(*this, 0)),
3425  inputgrp1(new InputGroup(*this, 1)),
3426  instancecount(NULL),
3427  schedgroup(NULL)
3428 {
3429  addChild(id);
3430 
3432  {
3434  _cardid, isNewInput));
3435  }
3436 
3437  ConfigurationGroup *basic =
3438  new VerticalConfigurationGroup(false, false, true, true);
3439 
3440  basic->setLabel(QObject::tr("Connect source to input"));
3441 
3442  basic->addChild(inputname);
3443  basic->addChild(new InputDisplayName(*this));
3444  basic->addChild(sourceid);
3445 
3446  if (CardUtil::IsEncoder(cardtype) || CardUtil::IsUnscanable(cardtype))
3447  {
3448  basic->addChild(new ExternalChannelCommand(*this));
3449  if (CardUtil::HasTuner(cardtype, device))
3450  basic->addChild(new PresetTuner(*this));
3451  }
3452  else
3453  {
3454  ConfigurationGroup *chgroup =
3455  new HorizontalConfigurationGroup(false, false, true, true);
3456  chgroup->addChild(new QuickTune(*this));
3457  if ("DVB" == cardtype)
3458  chgroup->addChild(new DishNetEIT(*this));
3459  basic->addChild(chgroup);
3460  }
3461 
3462  scan->setLabel(tr("Scan for channels"));
3463  scan->setHelpText(
3464  tr("Use channel scanner to find channels for this input."));
3465 
3466  srcfetch->setLabel(tr("Fetch channels from listings source"));
3468  tr("This uses the listings data source to "
3469  "provide the channels for this input.") + " " +
3470  tr("This can take a long time to run."));
3471 
3472  ConfigurationGroup *sgrp =
3473  new HorizontalConfigurationGroup(false, false, true, true);
3474  sgrp->addChild(scan);
3475  sgrp->addChild(srcfetch);
3476  basic->addChild(sgrp);
3477 
3478  basic->addChild(startchan);
3479 
3480  addChild(basic);
3481 
3482  ConfigurationGroup *interact =
3483  new VerticalConfigurationGroup(false, false, true, true);
3484 
3485  interact->setLabel(QObject::tr("Interactions between inputs"));
3486  if (CardUtil::IsTunerSharingCapable(cardtype))
3487  {
3489  interact->addChild(instancecount);
3490  schedgroup = new SchedGroup(*this);
3491  interact->addChild(schedgroup);
3492  }
3493  interact->addChild(new InputPriority(*this));
3494  interact->addChild(new ScheduleOrder(*this, _cardid));
3495  interact->addChild(new LiveTVOrder(*this, _cardid));
3496 
3497  TransButtonSetting *ingrpbtn = new TransButtonSetting("newgroup");
3498  ingrpbtn->setLabel(QObject::tr("Create a New Input Group"));
3499  ingrpbtn->setHelpText(
3500  QObject::tr("Input groups are only needed when two or more cards "
3501  "share the same resource such as a FireWire card and "
3502  "an analog card input controlling the same set top box."));
3503  interact->addChild(ingrpbtn);
3504  interact->addChild(inputgrp0);
3505  interact->addChild(inputgrp1);
3506 
3507  addChild(interact);
3508 
3509  setObjectName("CardInput");
3510  SetSourceID("-1");
3511 
3512  connect(scan, SIGNAL(pressed()), SLOT(channelScanner()));
3513  connect(srcfetch, SIGNAL(pressed()), SLOT(sourceFetch()));
3514  connect(sourceid, SIGNAL(valueChanged(const QString&)),
3515  startchan,SLOT( SetSourceID (const QString&)));
3516  connect(sourceid, SIGNAL(valueChanged(const QString&)),
3517  this, SLOT( SetSourceID (const QString&)));
3518  connect(ingrpbtn, SIGNAL(pressed(QString)),
3519  this, SLOT( CreateNewInputGroup()));
3520  if (schedgroup)
3521  connect(instancecount, SIGNAL(valueChanged(int)),
3522  this, SLOT(UpdateSchedGroup(int)));
3523 }
3524 
3526 {
3528  {
3529  delete externalInputSettings;
3530  externalInputSettings = NULL;
3531  }
3532 }
3533 
3534 void CardInput::SetSourceID(const QString &sourceid)
3535 {
3536  uint cid = id->getValue().toUInt();
3537  QString raw_card_type = CardUtil::GetRawInputType(cid);
3538  bool enable = (sourceid.toInt() > 0);
3539  scan->setEnabled(enable && !raw_card_type.isEmpty() &&
3540  !CardUtil::IsUnscanable(raw_card_type));
3541  srcfetch->setEnabled(enable);
3542 }
3543 
3545 {
3546  if (value <= 1)
3547  schedgroup->setValue(false);
3548  schedgroup->setEnabled(value > 1);
3549 }
3550 
3551 QString CardInput::getSourceName(void) const
3552 {
3553  return sourceid->getSelectionLabel();
3554 }
3555 
3557 {
3558  QString new_name = QString::null;
3559  QString tmp_name = QString::null;
3560 
3561  inputgrp0->Save();
3562  inputgrp1->Save();
3563 
3564  while (true)
3565  {
3566  tmp_name = "";
3568  GetMythMainWindow(), tr("Create Input Group"),
3569  tr("Enter new group name"), tmp_name);
3570 
3571  if (!ok)
3572  return;
3573 
3574  if (tmp_name.isEmpty())
3575  {
3577  GetMythMainWindow(), tr("Error"),
3578  tr("Sorry, this Input Group name cannot be blank."));
3579  continue;
3580  }
3581 
3582  new_name = QString("user:") + tmp_name;
3583 
3584  MSqlQuery query(MSqlQuery::InitCon());
3585  query.prepare(
3586  "SELECT inputgroupname "
3587  "FROM inputgroup "
3588  "WHERE inputgroupname = :GROUPNAME");
3589  query.bindValue(":GROUPNAME", new_name);
3590 
3591  if (!query.exec())
3592  {
3593  MythDB::DBError("CreateNewInputGroup 1", query);
3594  return;
3595  }
3596 
3597  if (query.next())
3598  {
3600  GetMythMainWindow(), tr("Error"),
3601  tr("Sorry, this Input Group name is already in use."));
3602  continue;
3603  }
3604 
3605  break;
3606  }
3607 
3608  uint inputgroupid = CardUtil::CreateInputGroup(new_name);
3609 
3610  inputgrp0->Load();
3611  inputgrp1->Load();
3612 
3613  if (!inputgrp0->getValue().toUInt())
3614  {
3616  inputgrp0->getValueIndex(QString::number(inputgroupid)));
3617  }
3618  else
3619  {
3621  inputgrp1->getValueIndex(QString::number(inputgroupid)));
3622  }
3623 }
3624 
3626 {
3627  uint srcid = sourceid->getValue().toUInt();
3628  uint crdid = id->getValue().toUInt();
3629  QString in = inputname->getValue();
3630 
3631 #ifdef USING_BACKEND
3632  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3633 
3634  Save(); // save info for scanner.
3635 
3636  QString cardtype = CardUtil::GetRawInputType(crdid);
3637  if (CardUtil::IsUnscanable(cardtype))
3638  {
3639  LOG(VB_GENERAL, LOG_ERR,
3640  QString("Sorry, %1 cards do not yet support scanning.")
3641  .arg(cardtype));
3642  return;
3643  }
3644 
3645  ScanWizard *scanwizard = new ScanWizard(srcid, crdid, in);
3646  scanwizard->exec(false, true);
3647  scanwizard->deleteLater();
3648 
3649  if (SourceUtil::GetChannelCount(srcid))
3650  startchan->SetSourceID(QString::number(srcid));
3651  if (num_channels_before)
3652  {
3653  startchan->Load();
3654  startchan->Save();
3655  }
3656 #else
3657  LOG(VB_GENERAL, LOG_ERR, "You must compile the backend "
3658  "to be able to scan for channels");
3659 #endif
3660 }
3661 
3663 {
3664  uint srcid = sourceid->getValue().toUInt();
3665  uint crdid = id->getValue().toUInt();
3666 
3667  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3668 
3669  if (crdid && srcid)
3670  {
3671  Save(); // save info for fetch..
3672 
3673  QString cardtype = CardUtil::GetRawInputType(crdid);
3674 
3675  if (!CardUtil::IsCableCardPresent(crdid, cardtype) &&
3676  !CardUtil::IsUnscanable(cardtype) &&
3677  !CardUtil::IsEncoder(cardtype) &&
3678  !num_channels_before)
3679  {
3680  LOG(VB_GENERAL, LOG_ERR, "Skipping channel fetch, you need to "
3681  "scan for channels first.");
3682  return;
3683  }
3684 
3685  SourceUtil::UpdateChannelsFromListings(srcid, cardtype);
3686  }
3687 
3688  if (SourceUtil::GetChannelCount(srcid))
3689  startchan->SetSourceID(QString::number(srcid));
3690  if (num_channels_before)
3691  {
3692  startchan->Load();
3693  startchan->Save();
3694  }
3695 }
3696 
3698 {
3699  QString cardinputidTag(":WHERECARDID");
3700 
3701  QString query("cardid = " + cardinputidTag);
3702 
3703  bindings.insert(cardinputidTag, m_parent.getInputID());
3704 
3705  return query;
3706 }
3707 
3709 {
3710  QString cardinputidTag(":SETCARDID");
3711  QString colTag(":SET" + GetColumnName().toUpper());
3712 
3713  QString query("cardid = " + cardinputidTag + ", " +
3714  GetColumnName() + " = " + colTag);
3715 
3716  bindings.insert(cardinputidTag, m_parent.getInputID());
3717  bindings.insert(colTag, user->GetDBValue());
3718 
3719  return query;
3720 }
3721 
3722 void CardInput::loadByID(int inputid)
3723 {
3724  id->setValue(inputid);
3725  externalInputSettings->Load(inputid);
3727 }
3728 
3729 void CardInput::loadByInput(int _cardid, QString _inputname)
3730 {
3731  MSqlQuery query(MSqlQuery::InitCon());
3732  query.prepare("SELECT cardid FROM capturecard "
3733  "WHERE cardid = :CARDID AND inputname = :INPUTNAME");
3734  query.bindValue(":CARDID", _cardid);
3735  query.bindValue(":INPUTNAME", _inputname);
3736 
3737  if (query.exec() && query.isActive() && query.next())
3738  {
3739  loadByID(query.value(0).toInt());
3740  }
3741 }
3742 
3744 {
3745  uint cardid = id->getValue().toUInt();
3746  QString init_input = CardUtil::GetInputName(cardid);
3749 
3750  uint icount = 1;
3751  if (instancecount)
3752  icount = instancecount->getValue().toUInt();
3753  vector<uint> cardids = CardUtil::GetChildInputIDs(cardid);
3754 
3755  // Delete old clone cards as required.
3756  for (uint i = cardids.size() + 1;
3757  (i > icount) && !cardids.empty(); --i)
3758  {
3759  CardUtil::DeleteCard(cardids.back());
3760  cardids.pop_back();
3761  }
3762 
3763  // Clone this config to existing clone cards.
3764  for (uint i = 0; i < cardids.size(); ++i)
3765  {
3766  CardUtil::CloneCard(cardid, cardids[i]);
3767  }
3768 
3769  // Create new clone cards as required.
3770  for (uint i = cardids.size() + 1; i < icount; i++)
3771  {
3772  CardUtil::CloneCard(cardid, 0);
3773  }
3774 
3775  // Delete any unused input groups
3777 }
3778 
3780 {
3781  return m_parent.getInputID();
3782 }
3783 
3785 {
3786  return m_parent.getCardID();
3787 }
3788 
3790 {
3791  listbox->setLabel(tr("Capture cards"));
3792  addChild(listbox);
3793 }
3794 
3796 {
3798  edit();
3799 
3800  return kDialogCodeRejected;
3801 }
3802 
3804 {
3806  listbox->addSelection(QObject::tr("(New capture card)"), "0");
3807  listbox->addSelection(QObject::tr("(Delete all capture cards on %1)")
3808  .arg(gCoreContext->GetHostName()), "-1");
3809  listbox->addSelection(QObject::tr("(Delete all capture cards)"), "-2");
3811 }
3812 
3814  const char* widgetName)
3815 {
3816  dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
3817  connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(menu()));
3818  connect(dialog, SIGNAL(editButtonPressed()), this, SLOT(edit()));
3819  connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(del()));
3820  return dialog;
3821 }
3822 
3824 {
3825  if (!listbox->getValue().toInt())
3826  {
3827  CaptureCard cc;
3828  cc.exec();
3829  }
3830  else
3831  {
3834  "",
3835  tr("Capture Card Menu"),
3836  tr("Edit..."),
3837  tr("Delete..."),
3839 
3840  if (kDialogCodeButton0 == val)
3841  edit();
3842  else if (kDialogCodeButton1 == val)
3843  del();
3844  }
3845 }
3846 
3848 {
3849  const int cardid = listbox->getValue().toInt();
3850  if (-1 == cardid)
3851  {
3853  GetMythMainWindow(), "",
3854  tr("Are you sure you want to delete "
3855  "ALL capture cards on %1?").arg(gCoreContext->GetHostName()),
3856  tr("Yes, delete capture cards"),
3857  tr("No, don't"), kDialogCodeButton1);
3858 
3859  if (kDialogCodeButton0 == val)
3860  {
3861  MSqlQuery cards(MSqlQuery::InitCon());
3862 
3863  cards.prepare(
3864  "SELECT cardid "
3865  "FROM capturecard "
3866  "WHERE hostname = :HOSTNAME");
3867  cards.bindValue(":HOSTNAME", gCoreContext->GetHostName());
3868 
3869  if (!cards.exec() || !cards.isActive())
3870  {
3873  tr("Error getting list of cards for this host"),
3874  tr("Unable to delete capturecards for %1")
3875  .arg(gCoreContext->GetHostName()));
3876 
3877  MythDB::DBError("Selecting cardids for deletion", cards);
3878  return;
3879  }
3880 
3881  while (cards.next())
3882  CardUtil::DeleteCard(cards.value(0).toUInt());
3883  }
3884  }
3885  else if (-2 == cardid)
3886  {
3888  GetMythMainWindow(), "",
3889  tr("Are you sure you want to delete "
3890  "ALL capture cards?"),
3891  tr("Yes, delete capture cards"),
3892  tr("No, don't"), kDialogCodeButton1);
3893 
3894  if (kDialogCodeButton0 == val)
3895  {
3897  Load();
3898  }
3899  }
3900  else
3901  {
3902  CaptureCard cc;
3903  if (cardid)
3904  cc.loadByID(cardid);
3905  cc.exec();
3906  }
3907 }
3908 
3910 {
3912  GetMythMainWindow(), "",
3913  tr("Are you sure you want to delete this capture card?"),
3914  tr("Yes, delete capture card"),
3915  tr("No, don't"), kDialogCodeButton1);
3916 
3917  if (kDialogCodeButton0 == val)
3918  {
3919  CardUtil::DeleteCard(listbox->getValue().toUInt());
3920  Load();
3921  }
3922 }
3923 
3925 {
3926  listbox->setLabel(tr("Video sources"));
3927  addChild(listbox);
3928 }
3929 
3931  const char* widgetName)
3932 {
3933  dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
3934  connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(menu()));
3935  connect(dialog, SIGNAL(editButtonPressed()), this, SLOT(edit()));
3936  connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(del()));
3937  return dialog;
3938 }
3939 
3941 {
3943  edit();
3944 
3945  return kDialogCodeRejected;
3946 }
3947 
3949 {
3951  listbox->addSelection(QObject::tr("(New video source)"), "0");
3952  listbox->addSelection(QObject::tr("(Delete all video sources)"), "-1");
3954 }
3955 
3957 {
3958  if (!listbox->getValue().toInt())
3959  {
3960  VideoSource vs;
3961  vs.exec();
3962  }
3963  else
3964  {
3967  "",
3968  tr("Video Source Menu"),
3969  tr("Edit..."),
3970  tr("Delete..."),
3972 
3973  if (kDialogCodeButton0 == val)
3974  edit();
3975  else if (kDialogCodeButton1 == val)
3976  del();
3977  }
3978 }
3979 
3981 {
3982  const int sourceid = listbox->getValue().toInt();
3983  if (-1 == sourceid)
3984  {
3986  GetMythMainWindow(), "",
3987  tr("Are you sure you want to delete "
3988  "ALL video sources?"),
3989  tr("Yes, delete video sources"),
3990  tr("No, don't"), kDialogCodeButton1);
3991 
3992  if (kDialogCodeButton0 == val)
3993  {
3995  Load();
3996  }
3997  }
3998  else
3999  {
4000  VideoSource vs;
4001  if (sourceid)
4002  vs.loadByID(sourceid);
4003  vs.exec();
4004  }
4005 }
4006 
4008 {
4010  GetMythMainWindow(), "",
4011  tr("Are you sure you want to delete "
4012  "this video source?"),
4013  tr("Yes, delete video source"),
4014  tr("No, don't"),
4016 
4017  if (kDialogCodeButton0 == val)
4018  {
4020  Load();
4021  }
4022 }
4023 
4025 {
4026  listbox->setLabel(tr("Input connections"));
4027  addChild(listbox);
4028 }
4029 
4031 {
4033  {
4034  if (!listbox)
4035  return kDialogCodeRejected;
4036 
4037  if (cardinputs.empty())
4038  return kDialogCodeRejected;
4039 
4040  int val = listbox->getValue().toInt();
4041 
4042  if (cardinputs[val])
4043  cardinputs[val]->exec();
4044  }
4045 
4046  return kDialogCodeRejected;
4047 }
4048 
4050 {
4051  cardinputs.clear();
4053 
4054  // We do this manually because we want custom labels. If
4055  // SelectSetting provided a facility to edit the labels, we
4056  // could use CaptureCard::fillSelections
4057 
4058  MSqlQuery query(MSqlQuery::InitCon());
4059  query.prepare(
4060  "SELECT cardid, videodevice, cardtype, inputname "
4061  "FROM capturecard "
4062  "WHERE hostname = :HOSTNAME "
4063  " AND parentid = 0 "
4064  "ORDER BY cardid");
4065  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
4066 
4067  if (!query.exec())
4068  {
4069  MythDB::DBError("CardInputEditor::load", query);
4070  return;
4071  }
4072 
4073  uint j = 0;
4074  QMap<QString, uint> device_refs;
4075  while (query.next())
4076  {
4077  uint cardid = query.value(0).toUInt();
4078  QString videodevice = query.value(1).toString();
4079  QString cardtype = query.value(2).toString();
4080  QString inputname = query.value(3).toString();
4081 
4082  CardInput *cardinput = new CardInput(cardtype, videodevice,
4083  true, cardid);
4084  cardinput->loadByID(cardid);
4085  QString inputlabel = QString("%1 (%2) -> %3")
4086  .arg(CardUtil::GetDeviceLabel(cardtype, videodevice))
4087  .arg(inputname).arg(cardinput->getSourceName());
4088  cardinputs.push_back(cardinput);
4089  listbox->addSelection(inputlabel, QString::number(j++));
4090  }
4091 }
4092 
4093 #ifdef USING_DVB
4094 static QString remove_chaff(const QString &name)
4095 {
4096  // Trim off some of the chaff.
4097  QString short_name = name;
4098  if (short_name.startsWith("LG Electronics"))
4099  short_name = short_name.right(short_name.length() - 15);
4100  if (short_name.startsWith("Oren"))
4101  short_name = short_name.right(short_name.length() - 5);
4102  if (short_name.startsWith("Nextwave"))
4103  short_name = short_name.right(short_name.length() - 9);
4104  if (short_name.startsWith("frontend", Qt::CaseInsensitive))
4105  short_name = short_name.left(short_name.length() - 9);
4106  if (short_name.endsWith("VSB/QAM"))
4107  short_name = short_name.left(short_name.length() - 8);
4108  if (short_name.endsWith("VSB"))
4109  short_name = short_name.left(short_name.length() - 4);
4110  if (short_name.endsWith("DVB-T"))
4111  short_name = short_name.left(short_name.length() - 6);
4112 
4113  // It would be infinitely better if DVB allowed us to query
4114  // the vendor ID. But instead we have to guess based on the
4115  // demodulator name. This means cards like the Air2PC HD5000
4116  // and DViCO Fusion HDTV cards are not identified correctly.
4117  short_name = short_name.simplified();
4118  if (short_name.startsWith("or51211", Qt::CaseInsensitive))
4119  short_name = "pcHDTV HD-2000";
4120  else if (short_name.startsWith("or51132", Qt::CaseInsensitive))
4121  short_name = "pcHDTV HD-3000";
4122  else if (short_name.startsWith("bcm3510", Qt::CaseInsensitive))
4123  short_name = "Air2PC v1";
4124  else if (short_name.startsWith("nxt2002", Qt::CaseInsensitive))
4125  short_name = "Air2PC v2";
4126  else if (short_name.startsWith("nxt200x", Qt::CaseInsensitive))
4127  short_name = "Air2PC v2";
4128  else if (short_name.startsWith("lgdt3302", Qt::CaseInsensitive))
4129  short_name = "DViCO HDTV3";
4130  else if (short_name.startsWith("lgdt3303", Qt::CaseInsensitive))
4131  short_name = "DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
4132 
4133  return short_name;
4134 }
4135 #endif // USING_DVB
4136 
4137 void DVBConfigurationGroup::reloadDiseqcTree(const QString &videodevice)
4138 {
4139  if (diseqc_tree)
4140  diseqc_tree->Load(videodevice);
4141 }
4142 
4143 void DVBConfigurationGroup::probeCard(const QString &videodevice)
4144 {
4145  if (videodevice.isEmpty())
4146  {
4147  cardname->setValue("");
4148  cardtype->setValue("");
4149  return;
4150  }
4151 
4152  if (parent.getCardID() && parent.GetRawCardType() != "DVB")
4153  {
4154  cardname->setValue("");
4155  cardtype->setValue("");
4156  return;
4157  }
4158 
4159 #ifdef USING_DVB
4160  QString frontend_name = CardUtil::ProbeDVBFrontendName(videodevice);
4161  QString subtype = CardUtil::ProbeDVBType(videodevice);
4162 
4163  QString err_open = tr("Could not open card %1").arg(videodevice);
4164  QString err_other = tr("Could not get card info for card %1").arg(videodevice);
4165 
4166  switch (CardUtil::toInputType(subtype))
4167  {
4168  case CardUtil::ERROR_OPEN:
4169  cardname->setValue(err_open);
4170  cardtype->setValue(strerror(errno));
4171  break;
4173  cardname->setValue(err_other);
4174  cardtype->setValue("Unknown error");
4175  break;
4176  case CardUtil::ERROR_PROBE:
4177  cardname->setValue(err_other);
4178  cardtype->setValue(strerror(errno));
4179  break;
4180  case CardUtil::QPSK:
4181  cardtype->setValue("DVB-S");
4182  cardname->setValue(frontend_name);
4183  signal_timeout->setValue(7000);
4184  channel_timeout->setValue(10000);
4185  break;
4186  case CardUtil::DVBS2:
4187  cardtype->setValue("DVB-S2");
4188  cardname->setValue(frontend_name);
4189  signal_timeout->setValue(7000);
4190  channel_timeout->setValue(10000);
4191  break;
4192  case CardUtil::QAM:
4193  cardtype->setValue("DVB-C");
4194  cardname->setValue(frontend_name);
4195  signal_timeout->setValue(1000);
4196  channel_timeout->setValue(3000);
4197  break;
4198  case CardUtil::DVBT2:
4199  cardtype->setValue("DVB-T2");
4200  cardname->setValue(frontend_name);
4201  signal_timeout->setValue(1000);
4202  channel_timeout->setValue(3000);
4203  break;
4204  case CardUtil::OFDM:
4205  {
4206  cardtype->setValue("DVB-T");
4207  cardname->setValue(frontend_name);
4208  signal_timeout->setValue(1000);
4209  channel_timeout->setValue(3000);
4210  if (frontend_name.toLower().indexOf("usb") >= 0)
4211  {
4212  signal_timeout->setValue(40000);
4213  channel_timeout->setValue(42500);
4214  }
4215 
4216  // slow down tuning for buggy drivers
4217  if ((frontend_name == "DiBcom 3000P/M-C DVB-T") ||
4218  (frontend_name ==
4219  "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
4220  {
4221  tuning_delay->setValue(200);
4222  }
4223 
4224 #if 0 // frontends on hybrid DVB-T/Analog cards
4225  QString short_name = remove_chaff(frontend_name);
4226  buttonAnalog->setVisible(
4227  short_name.startsWith("zarlink zl10353",
4228  Qt::CaseInsensitive) ||
4229  short_name.startsWith("wintv hvr 900 m/r: 65008/a1c0",
4230  Qt::CaseInsensitive) ||
4231  short_name.startsWith("philips tda10046h",
4232  Qt::CaseInsensitive));
4233 #endif
4234  }
4235  break;
4236  case CardUtil::ATSC:
4237  {
4238  QString short_name = remove_chaff(frontend_name);
4239  cardtype->setValue("ATSC");
4240  cardname->setValue(short_name);
4241  signal_timeout->setValue(500);
4242  channel_timeout->setValue(3000);
4243 
4244  // According to #1779 and #1935 the AverMedia 180 needs
4245  // a 3000 ms signal timeout, at least for QAM tuning.
4246  if (frontend_name == "Nextwave NXT200X VSB/QAM frontend")
4247  {
4248  signal_timeout->setValue(3000);
4249  channel_timeout->setValue(5500);
4250  }
4251 
4252 #if 0 // frontends on hybrid DVB-T/Analog cards
4253  if (frontend_name.toLower().indexOf("usb") < 0)
4254  {
4255  buttonAnalog->setVisible(
4256  short_name.startsWith("pchdtv", Qt::CaseInsensitive) ||
4257  short_name.startsWith("dvico", Qt::CaseInsensitive) ||
4258  short_name.startsWith("nextwave", Qt::CaseInsensitive));
4259  }
4260 #endif
4261  }
4262  break;
4263  default:
4264  break;
4265  }
4266 #else
4267  cardtype->setValue(QString("Recompile with DVB-Support!"));
4268 #endif
4269 }
4270 
4272  QString dev, QString type) :
4273  ComboBoxSetting(this), CaptureCardDBStorage(this, parent, "audiodevice"),
4274  last_device(dev), last_cardtype(type)
4275 {
4276  setLabel(QObject::tr("Audio input"));
4277  setHelpText(QObject::tr("If there is more than one audio input, "
4278  "select which one to use."));
4279  int cardid = parent.getCardID();
4280  if (cardid <= 0)
4281  return;
4282 
4285 }
4286 
4287 void TunerCardAudioInput::fillSelections(const QString &device)
4288 {
4289  clearSelections();
4290 
4291  if (device.isEmpty())
4292  return;
4293 
4294  last_device = device;
4295  QStringList inputs =
4297 
4298  for (uint i = 0; i < (uint)inputs.size(); i++)
4299  {
4300  addSelection(inputs[i], QString::number(i),
4301  last_device == QString::number(i));
4302  }
4303 }
4304 
4306 {
4307  public:
4309 };
4310 
4312 {
4314  rec->setLabel(QObject::tr("Recorder Options"));
4315  rec->setUseLabel(false);
4316 
4317  rec->addChild(new DVBNoSeqStart(parent.parent));
4318  rec->addChild(new DVBOnDemand(parent.parent));
4319  rec->addChild(new DVBEITScan(parent.parent));
4320  rec->addChild(new DVBTuningDelay(parent.parent));
4321 
4322  addChild(rec);
4323 }
4324 
4327  parent(a_parent),
4328  diseqc_tree(new DiSEqCDevTree())
4329 {
4330  cardnum = new DVBCardNum(parent);
4331  cardname = new DVBCardName();
4332  cardtype = new DVBCardType();
4333 
4334  signal_timeout = new SignalTimeout(parent, 500, 250);
4335  channel_timeout = new ChannelTimeout(parent, 3000, 1750);
4336 
4337  addChild(cardnum);
4338 
4340  new HorizontalConfigurationGroup(false, false, true, true);
4341  hg0->addChild(cardname);
4342  hg0->addChild(cardtype);
4343  addChild(hg0);
4344 
4347 
4350 
4351  TransButtonSetting *buttonRecOpt = new TransButtonSetting();
4352  buttonRecOpt->setLabel(tr("Recording Options"));
4353 
4355  new HorizontalConfigurationGroup(false, false, true, true);
4356  advcfg->addChild(buttonRecOpt);
4357  addChild(advcfg);
4358 
4360  diseqc_btn->setLabel(tr("DiSEqC (Switch, LNB, and Rotor Configuration)"));
4361  diseqc_btn->setHelpText(tr("Input and satellite settings."));
4362 
4363  HorizontalConfigurationGroup *diseqc_cfg =
4364  new HorizontalConfigurationGroup(false, false, true, true);
4365  diseqc_cfg->addChild(diseqc_btn);
4366  diseqc_btn->setVisible(false);
4367  addChild(diseqc_cfg);
4368 
4371  tuning_delay->setVisible(false);
4372 
4373  connect(cardnum, SIGNAL(valueChanged(const QString&)),
4374  this, SLOT( probeCard (const QString&)));
4375  connect(cardnum, SIGNAL(valueChanged(const QString&)),
4376  this, SLOT( reloadDiseqcTree(const QString&)));
4377  connect(diseqc_btn, SIGNAL(pressed()),
4378  this, SLOT( DiSEqCPanel()));
4379  connect(buttonRecOpt, SIGNAL(pressed()),
4380  this, SLOT( DVBExtraPanel()));
4381 }
4382 
4384 {
4385  if (diseqc_tree)
4386  {
4387  delete diseqc_tree;
4388  diseqc_tree = NULL;
4389  }
4390 }
4391 
4393 {
4394  parent.reload(); // ensure card id is valid
4395 
4396  DTVDeviceTreeWizard diseqcWiz(*diseqc_tree);
4397  diseqcWiz.exec();
4398 }
4399 
4401 {
4404  if (cardtype->getValue() == "DVB-S" ||
4405  cardtype->getValue() == "DVB-S2" ||
4407  {
4408  diseqc_btn->setVisible(true);
4409  }
4410 }
4411 
4413 {
4416  DiSEqCDev trees;
4417  trees.InvalidateTrees();
4418 }
4419 
4421 {
4422  parent.reload(); // ensure card id is valid
4423 
4424  DVBExtra acw(*this);
4425  acw.exec();
4426 }
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:785
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:348
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:884
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:1046
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:305
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:1211
void probeCard(const QString &device)
virtual void deleteLater(void)
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:457
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:1795
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:507
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:1475
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:158
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:1522
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:2191
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:1698
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:2077
static bool IsCableCardPresent(uint inputid, const QString &inputType)
Definition: cardutil.cpp:114
static uint GetDeviceInputGroup(uint inputid)
Definition: cardutil.cpp:1265
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:706
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1329
virtual void Load(void)
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:542
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:2263
CaptureCard & m_parent
Definition: videosource.h:546
static bool CloneCard(uint src_inputid, uint dst_inputid)
Definition: cardutil.cpp:883
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:810
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:1927
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:610
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:1289
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:2003
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)
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)
__s32 value
Definition: videodev2.h:1042
static QString GetHDHRdesc(const QString &device)
Get a nicely formatted string describing the device.
Definition: cardutil.cpp:2134
CaptureCard & parent
Definition: videosource.h:567
void SetOverrideDeviceID(const QString &