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