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