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