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 
809  void fillSelectionsFromDir(const QDir &dir, bool absPath = true)
810  {
811  fillSelectionsFromDir(dir, 0, 255, QString::null, QString::null, false);
812  }
813 
814  uint fillSelectionsFromDir(const QDir& dir,
815  uint minor_min, uint minor_max,
816  QString card, QString driver,
817  bool allow_duplicates)
818  {
819  uint cnt = 0;
820 
821  QFileInfoList il = dir.entryInfoList();
822  QRegExp *driverExp = NULL;
823  if (!driver.isEmpty())
824  driverExp = new QRegExp(driver);
825 
826  for( QFileInfoList::iterator it = il.begin();
827  it != il.end();
828  ++it )
829  {
830  QFileInfo &fi = *it;
831 
832  struct stat st;
833  QString filepath = fi.absoluteFilePath();
834  int err = lstat(filepath.toLocal8Bit().constData(), &st);
835 
836  if (err)
837  {
838  LOG(VB_GENERAL, LOG_ERR,
839  QString("Could not stat file: %1").arg(filepath));
840  continue;
841  }
842 
843  // is this is a character device?
844  if (!S_ISCHR(st.st_mode))
845  continue;
846 
847  // is this device is in our minor range?
848  uint minor_num = minor(st.st_rdev);
849  if (minor_min > minor_num || minor_max < minor_num)
850  continue;
851 
852  // ignore duplicates if allow_duplicates not set
853  if (!allow_duplicates && minor_list[minor_num])
854  continue;
855 
856  // if the driver returns any info add this device to our list
857  QByteArray tmp = filepath.toLatin1();
858  int videofd = open(tmp.constData(), O_RDWR);
859  if (videofd >= 0)
860  {
861  QString card_name, driver_name;
862  if (CardUtil::GetV4LInfo(videofd, card_name, driver_name) &&
863  (!driverExp || (driverExp->exactMatch(driver_name))) &&
864  (card.isEmpty() || (card_name == card)))
865  {
866  addSelection(filepath);
867  cnt++;
868  }
869  close(videofd);
870  }
871 
872  // add to list of minors discovered to avoid duplicates
873  minor_list[minor_num] = 1;
874  }
875  delete driverExp;
876 
877  return cnt;
878  }
879 
880  QString Driver(void) const { return driver_name; }
881  QString Card(void) const { return card_name; }
882 
883  private:
884  QMap<uint, uint> minor_list;
885  QString card_name;
886  QString driver_name;
887 };
888 
890 {
891  public:
892  explicit VBIDevice(const CaptureCard &parent) :
893  CaptureCardComboBoxSetting(parent, true /*, mustexist true */,
894  "vbidevice")
895  {
896  setLabel(QObject::tr("VBI device"));
897  setFilter(QString::null, QString::null);
898  setHelpText(QObject::tr("Device to read VBI (captions) from."));
899  };
900 
901  uint setFilter(const QString &card, const QString &driver)
902  {
903  uint count = 0;
904  clearSelections();
905  QDir dev("/dev/v4l", "vbi*", QDir::Name, QDir::System);
906  if (!(count = fillSelectionsFromDir(dev, card, driver)))
907  {
908  dev.setPath("/dev");
909  if (!(count = fillSelectionsFromDir(dev, card, driver)) &&
910  !getValue().isEmpty())
911  {
912  addSelection(getValue(),getValue(),true);
913  }
914  }
915 
916  return count;
917  }
918 
919  void fillSelectionsFromDir(const QDir &dir, bool absPath = true)
920  {
921  fillSelectionsFromDir(dir, QString::null, QString::null);
922  }
923 
924  uint fillSelectionsFromDir(const QDir &dir, const QString &card,
925  const QString &driver)
926  {
927  QStringList devices;
928  QFileInfoList il = dir.entryInfoList();
929  for( QFileInfoList::iterator it = il.begin();
930  it != il.end();
931  ++it )
932  {
933  QFileInfo &fi = *it;
934 
935  QString device = fi.absoluteFilePath();
936  QByteArray adevice = device.toLatin1();
937  int vbifd = open(adevice.constData(), O_RDWR);
938  if (vbifd < 0)
939  continue;
940 
941  QString cn, dn;
942  if (CardUtil::GetV4LInfo(vbifd, cn, dn) &&
943  (driver.isEmpty() || (dn == driver)) &&
944  (card.isEmpty() || (cn == card)))
945  {
946  devices.push_back(device);
947  }
948 
949  close(vbifd);
950  }
951 
952  QString sel = getValue();
953  for (uint i = 0; i < (uint) devices.size(); i++)
954  addSelection(devices[i], devices[i], devices[i] == sel);
955 
956  return (uint) devices.size();
957  }
958 };
959 
961 {
962  public:
963  explicit ArgumentString(const CaptureCard &parent) :
964  LineEditSetting(this, true),
965  CaptureCardDBStorage(this, parent, "audiodevice") // change to arguments
966  {
967  setLabel(QObject::tr("Arguments"));
968  }
969 };
970 
972 {
973  public:
974  explicit FileDevice(const CaptureCard &parent) :
976  new CaptureCardDBStorage(this, parent, "videodevice")
977  /* mustexist, false */)
978  {
979  setLabel(QObject::tr("File path"));
980  };
981 };
982 
984 {
985  public:
986  explicit AudioDevice(const CaptureCard &parent) :
987  CaptureCardComboBoxSetting(parent, true /* mustexist false */,
988  "audiodevice")
989  {
990  setLabel(QObject::tr("Audio device"));
991 #if USING_OSS
992  QDir dev("/dev", "dsp*", QDir::Name, QDir::System);
994  dev.setPath("/dev/sound");
996 #endif
997 #if USING_ALSA
998  addSelection("ALSA:default", "ALSA:default");
999 #endif
1000  addSelection(QObject::tr("(None)"), "NULL");
1001  setHelpText(QObject::tr("Device to read audio from, "
1002  "if audio is separate from the video."));
1003  };
1004 };
1005 
1007 {
1008  public:
1010  CaptureCardSpinBoxSetting(parent, min_val, 60000, 250, "signal_timeout")
1011  {
1012  setLabel(QObject::tr("Signal timeout (ms)"));
1013  setValue(QString::number(value));
1014  setHelpText(QObject::tr(
1015  "Maximum time (in milliseconds) MythTV waits for "
1016  "a signal when scanning for channels."));
1017  };
1018 };
1019 
1021 {
1022  public:
1024  CaptureCardSpinBoxSetting(parent, min_val, 65000, 250,
1025  "channel_timeout")
1026  {
1027  setLabel(QObject::tr("Tuning timeout (ms)"));
1028  setValue(value);
1029  setHelpText(QObject::tr(
1030  "Maximum time (in milliseconds) MythTV waits for "
1031  "a channel lock. For recordings, if this time is "
1032  "exceeded, the recording will be marked as failed."));
1033  };
1034 };
1035 
1037 {
1038  public:
1039  explicit AudioRateLimit(const CaptureCard &parent) :
1040  CaptureCardComboBoxSetting(parent, false, "audioratelimit")
1041  {
1042  setLabel(QObject::tr("Force audio sampling rate"));
1043  setHelpText(
1044  QObject::tr("If non-zero, override the audio sampling "
1045  "rate in the recording profile when this card is "
1046  "used. Use this if your capture card does not "
1047  "support all of the standard rates."));
1048  addSelection(QObject::tr("(None)"), "0");
1049  addSelection("32000");
1050  addSelection("44100");
1051  addSelection("48000");
1052  };
1053 };
1054 
1056 {
1057  public:
1058  explicit SkipBtAudio(const CaptureCard &parent) :
1060  "skipbtaudio"))
1061  {
1062  setLabel(QObject::tr("Do not adjust volume"));
1063  setHelpText(
1064  QObject::tr("Enable this option for budget BT878 based "
1065  "DVB-T cards such as the AverTV DVB-T which "
1066  "require the audio volume to be left alone."));
1067  };
1068 };
1069 
1071 {
1072  public:
1073  explicit DVBCardNum(const CaptureCard &parent) :
1074  CaptureCardComboBoxSetting(parent, true, "videodevice")
1075  {
1076  setLabel(QObject::tr("DVB device"));
1077  setHelpText(
1078  QObject::tr("When you change this setting, the text below "
1079  "should change to the name and type of your card. "
1080  "If the card cannot be opened, an error message "
1081  "will be displayed."));
1082  fillSelections(QString::null);
1083  };
1084 
1088  void fillSelections(const QString &current)
1089  {
1090  clearSelections();
1091 
1092  // Get devices from filesystem
1093  QStringList sdevs = CardUtil::ProbeVideoDevices("DVB");
1094 
1095  // Add current if needed
1096  if (!current.isEmpty() &&
1097  (find(sdevs.begin(), sdevs.end(), current) == sdevs.end()))
1098  {
1099  stable_sort(sdevs.begin(), sdevs.end());
1100  }
1101 
1102  QStringList db = CardUtil::GetVideoDevices("DVB");
1103 
1104  QMap<QString,bool> in_use;
1105  QString sel = current;
1106  for (uint i = 0; i < (uint)sdevs.size(); i++)
1107  {
1108  const QString dev = sdevs[i];
1109  in_use[sdevs[i]] = find(db.begin(), db.end(), dev) != db.end();
1110  if (sel.isEmpty() && !in_use[sdevs[i]])
1111  sel = dev;
1112  }
1113 
1114  if (sel.isEmpty() && sdevs.size())
1115  sel = sdevs[0];
1116 
1117  QString usestr = QString(" -- ");
1118  usestr += QObject::tr("Warning: already in use");
1119 
1120  for (uint i = 0; i < (uint)sdevs.size(); i++)
1121  {
1122  const QString dev = sdevs[i];
1123  QString desc = dev + (in_use[sdevs[i]] ? usestr : "");
1124  desc = (current == sdevs[i]) ? dev : desc;
1125  addSelection(desc, dev, dev == sel);
1126  }
1127  }
1128 
1129  virtual void Load(void)
1130  {
1131  clearSelections();
1132  addSelection(QString::null);
1133 
1135 
1137  fillSelections(dev);
1138  }
1139 };
1140 
1142 {
1143  public:
1145  {
1146  setLabel(QObject::tr("Subtype"));
1147  setEnabled(false);
1148  };
1149 };
1150 
1152 {
1153  public:
1155  {
1156  setLabel(QObject::tr("Frontend ID"));
1157  setEnabled(false);
1158  };
1159 };
1160 
1162 {
1163  public:
1164  explicit DVBNoSeqStart(const CaptureCard &parent) :
1166  new CaptureCardDBStorage(this, parent, "dvb_wait_for_seqstart"))
1167  {
1168  setLabel(QObject::tr("Wait for SEQ start header."));
1169  setValue(true);
1170  setHelpText(
1171  QObject::tr("If enabled, drop packets from the start of a DVB "
1172  "recording until a sequence start header is seen."));
1173  };
1174 };
1175 
1177 {
1178  public:
1179  explicit DVBOnDemand(const CaptureCard &parent) :
1181  new CaptureCardDBStorage(this, parent, "dvb_on_demand"))
1182  {
1183  setLabel(QObject::tr("Open DVB card on demand"));
1184  setValue(true);
1185  setHelpText(
1186  QObject::tr("If enabled, only open the DVB card when required, "
1187  "leaving it free for other programs at other times."));
1188  };
1189 };
1190 
1192 {
1193  public:
1194  explicit DVBEITScan(const CaptureCard &parent) :
1196  new CaptureCardDBStorage(this, parent, "dvb_eitscan"))
1197  {
1198  setLabel(QObject::tr("Use DVB card for active EIT scan"));
1199  setValue(true);
1200  setHelpText(
1201  QObject::tr("If enabled, activate active scanning for "
1202  "program data (EIT). When this option is enabled "
1203  "the DVB card is constantly in-use."));
1204  };
1205 };
1206 
1208 {
1209  public:
1210  explicit DVBTuningDelay(const CaptureCard &parent) :
1211  CaptureCardSpinBoxSetting(parent, 0, 2000, 25, "dvb_tuning_delay")
1212  {
1213  setValue("0");
1214  setLabel(QObject::tr("DVB tuning delay (ms)"));
1215  setValue(true);
1216  setHelpText(
1217  QObject::tr("Some Linux DVB drivers, in particular for the "
1218  "Hauppauge Nova-T, require that we slow down "
1219  "the tuning process by specifying a delay "
1220  "(in milliseconds)."));
1221  };
1222 };
1223 
1225 {
1226  public:
1227  explicit FirewireGUID(const CaptureCard &parent) :
1228  CaptureCardComboBoxSetting(parent, false, "videodevice")
1229  {
1230  setLabel(QObject::tr("GUID"));
1231 #ifdef USING_FIREWIRE
1232  vector<AVCInfo> list = FirewireDevice::GetSTBList();
1233  for (uint i = 0; i < list.size(); i++)
1234  {
1235  QString guid = list[i].GetGUIDString();
1236  guid_to_avcinfo[guid] = list[i];
1237  addSelection(guid);
1238  }
1239 #endif // USING_FIREWIRE
1240  }
1241 
1242  AVCInfo GetAVCInfo(const QString &guid) const
1243  { return guid_to_avcinfo[guid]; }
1244 
1245  private:
1246  QMap<QString,AVCInfo> guid_to_avcinfo;
1247 };
1248 
1250  const FirewireGUID *_guid) :
1251  CaptureCardComboBoxSetting(parent, false, "firewire_model"),
1252  guid(_guid)
1253 {
1254  setLabel(QObject::tr("Cable box model"));
1255  addSelection(QObject::tr("Motorola Generic"), "MOTO GENERIC");
1256  addSelection(QObject::tr("SA/Cisco Generic"), "SA GENERIC");
1257  addSelection("DCH-3200");
1258  addSelection("DCX-3200");
1259  addSelection("DCT-3412");
1260  addSelection("DCT-3416");
1261  addSelection("DCT-6200");
1262  addSelection("DCT-6212");
1263  addSelection("DCT-6216");
1264  addSelection("QIP-6200");
1265  addSelection("QIP-7100");
1266  addSelection("PACE-550");
1267  addSelection("PACE-779");
1268  addSelection("SA3250HD");
1269  addSelection("SA4200HD");
1270  addSelection("SA4250HDC");
1271  addSelection("SA8300HD");
1272  QString help = QObject::tr(
1273  "Choose the model that most closely resembles your set top box. "
1274  "Depending on firmware revision SA4200HD may work better for a "
1275  "SA3250HD box.");
1276  setHelpText(help);
1277 }
1278 
1279 void FirewireModel::SetGUID(const QString &_guid)
1280 {
1281  (void) _guid;
1282 
1283 #ifdef USING_FIREWIRE
1284  AVCInfo info = guid->GetAVCInfo(_guid);
1285  QString model = FirewireDevice::GetModelName(info.vendorid, info.modelid);
1286  setValue(max(getValueIndex(model), 0));
1287 #endif // USING_FIREWIRE
1288 }
1289 
1290 void FirewireDesc::SetGUID(const QString &_guid)
1291 {
1292  (void) _guid;
1293 
1294  setLabel(tr("Description"));
1295 
1296 #ifdef USING_FIREWIRE
1297  QString name = guid->GetAVCInfo(_guid).product_name;
1298  name.replace("Scientific-Atlanta", "SA");
1299  name.replace(", Inc.", "");
1300  name.replace("Explorer(R)", "");
1301  name = name.simplified();
1302  setValue((name.isEmpty()) ? "" : name);
1303 #endif // USING_FIREWIRE
1304 }
1305 
1307 {
1308  public:
1309  explicit FirewireConnection(const CaptureCard &parent) :
1311  "firewire_connection"))
1312  {
1313  setLabel(QObject::tr("Connection Type"));
1314  addSelection(QObject::tr("Point to Point"),"0");
1315  addSelection(QObject::tr("Broadcast"),"1");
1316  }
1317 };
1318 
1320 {
1321  public:
1322  explicit FirewireSpeed(const CaptureCard &parent) :
1324  "firewire_speed"))
1325  {
1326  setLabel(QObject::tr("Speed"));
1327  addSelection(QObject::tr("100Mbps"),"0");
1328  addSelection(QObject::tr("200Mbps"),"1");
1329  addSelection(QObject::tr("400Mbps"),"2");
1330  addSelection(QObject::tr("800Mbps"),"3");
1331  }
1332 };
1333 
1334 static void FirewireConfigurationGroup(CaptureCard& parent, CardType& cardtype)
1335 {
1336  FirewireGUID *dev(new FirewireGUID(parent));
1337  FirewireDesc *desc(new FirewireDesc(dev));
1338  FirewireModel *model(new FirewireModel(parent, dev));
1339  cardtype.addTargetedChild("FIREWIRE", dev);
1340  cardtype.addTargetedChild("FIREWIRE", new EmptyAudioDevice(parent));
1341  cardtype.addTargetedChild("FIREWIRE", new EmptyVBIDevice(parent));
1342  cardtype.addTargetedChild("FIREWIRE", desc);
1343  cardtype.addTargetedChild("FIREWIRE", model);
1344 
1345 #ifdef USING_LINUX_FIREWIRE
1346  cardtype.addTargetedChild("FIREWIRE", new FirewireConnection(parent));
1347  cardtype.addTargetedChild("FIREWIRE", new FirewireSpeed(parent));
1348 #endif // USING_LINUX_FIREWIRE
1349 
1350  cardtype.addTargetedChild("FIREWIRE", new SignalTimeout(parent, 2000, 1000));
1351  cardtype.addTargetedChild("FIREWIRE", new ChannelTimeout(parent, 9000, 1750));
1352 
1353  model->SetGUID(dev->getValue());
1354  desc->SetGUID(dev->getValue());
1355  QObject::connect(dev, SIGNAL(valueChanged(const QString&)),
1356  model, SLOT( SetGUID( const QString&)));
1357  QObject::connect(dev, SIGNAL(valueChanged(const QString&)),
1358  desc, SLOT( SetGUID( const QString&)));
1359 }
1360 
1361 // -----------------------
1362 // HDHomeRun Configuration
1363 // -----------------------
1364 
1366 {
1367  setLabel(QObject::tr("IP Address"));
1368  setEnabled(false);
1369  connect(this, SIGNAL(valueChanged( const QString&)),
1370  this, SLOT( UpdateDevices(const QString&)));
1371  _oldValue="";
1372 };
1373 
1375 {
1377  if (e)
1378  {
1379  if (!_oldValue.isEmpty())
1380  setValue(_oldValue);
1381  emit NewIP(getValue());
1382  }
1383  else
1384  {
1385  _oldValue = getValue();
1386  _oldValue.detach();
1387  }
1388 }
1389 
1390 void HDHomeRunIP::UpdateDevices(const QString &v)
1391 {
1392  if (isEnabled())
1393  {
1394 #if 0
1395  LOG(VB_GENERAL, LOG_DEBUG, QString("Emitting NewIP(%1)").arg(v));
1396 #endif
1397  emit NewIP(v);
1398  }
1399 }
1400 
1402 {
1403  setLabel(QObject::tr("Tuner"));
1404  setEnabled(false);
1405  connect(this, SIGNAL(valueChanged( const QString&)),
1406  this, SLOT( UpdateDevices(const QString&)));
1407  _oldValue = "";
1408 };
1409 
1411 {
1413  if (e) {
1414  if (!_oldValue.isEmpty())
1415  setValue(_oldValue);
1416  emit NewTuner(getValue());
1417  }
1418  else
1419  {
1420  _oldValue = getValue();
1421  }
1422 }
1423 
1425 {
1426  if (isEnabled())
1427  {
1428 #if 0
1429  LOG(VB_GENERAL, LOG_DEBUG, QString("Emitting NewTuner(%1)").arg(v));
1430 #endif
1431  emit NewTuner(v);
1432  }
1433 }
1434 
1436  MythUITextEditSetting(new CaptureCardDBStorage(this, parent, "videodevice")),
1437  _ip(QString::null),
1438  _tuner(QString::null),
1439  _overridedeviceid(QString::null)
1440 {
1441  setLabel(tr("Device ID"));
1442  setHelpText(tr("Device ID of HDHomeRun device"));
1443 }
1444 
1445 void HDHomeRunDeviceID::SetIP(const QString &ip)
1446 {
1447 #if 0
1448  LOG(VB_GENERAL, LOG_DEBUG, QString("Setting IP to %1").arg(ip));
1449 #endif
1450  _ip = ip;
1451  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1452 #if 0
1453  LOG(VB_GENERAL, LOG_DEBUG, QString("Done Setting IP to %1").arg(ip));
1454 #endif
1455 }
1456 
1457 void HDHomeRunDeviceID::SetTuner(const QString &tuner)
1458 {
1459 #if 0
1460  LOG(VB_GENERAL, LOG_DEBUG, QString("Setting Tuner to %1").arg(tuner));
1461 #endif
1462  _tuner = tuner;
1463  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1464 #if 0
1465  LOG(VB_GENERAL, LOG_DEBUG, QString("Done Setting Tuner to %1").arg(tuner));
1466 #endif
1467 }
1468 
1469 void HDHomeRunDeviceID::SetOverrideDeviceID(const QString &deviceid)
1470 {
1471  _overridedeviceid = deviceid;
1472  setValue(deviceid);
1473 }
1474 
1476 {
1477  GetStorage()->Load();
1478  if (!_overridedeviceid.isEmpty())
1479  {
1481  _overridedeviceid = QString::null;
1482  }
1483 }
1484 
1486  HDHomeRunDeviceID *deviceid,
1487  StandardSetting *desc,
1488  HDHomeRunIP *cardip,
1489  HDHomeRunTunerIndex *cardtuner,
1490  HDHomeRunDeviceList *devicelist) :
1491  _deviceid(deviceid),
1492  _desc(desc),
1493  _cardip(cardip),
1494  _cardtuner(cardtuner),
1495  _devicelist(devicelist)
1496 {
1497  setLabel(QObject::tr("Available devices"));
1498  setHelpText(
1499  QObject::tr(
1500  "Device ID and Tuner Number of available HDHomeRun devices."));
1501 
1502  connect(this, SIGNAL(valueChanged( const QString&)),
1503  this, SLOT( UpdateDevices(const QString&)));
1504 
1505  _oldValue = "";
1506 };
1507 
1512 {
1513  clearSelections();
1514 
1515  vector<QString> devs;
1516  QMap<QString, bool> in_use;
1517 
1518  QString current = cur;
1519 
1520 #if 0
1521  LOG(VB_GENERAL, LOG_DEBUG, QString("Filling List, current = '%1'")
1522  .arg(current));
1523 #endif
1524 
1525  HDHomeRunDeviceList::iterator it = _devicelist->begin();
1526  for (; it != _devicelist->end(); ++it)
1527  {
1528  if ((*it).discovered)
1529  {
1530  devs.push_back(it.key());
1531  in_use[it.key()] = (*it).inuse;
1532  }
1533  }
1534 
1535  QString man_addr = HDHomeRunDeviceIDList::tr("Manually Enter IP Address");
1536  QString sel = man_addr;
1537  devs.push_back(sel);
1538 
1539  if (3 == devs.size() && current.startsWith("FFFFFFFF", Qt::CaseInsensitive))
1540  {
1541  current = sel = (current.endsWith("0")) ?
1542  *(devs.begin()) : *(++devs.begin());
1543  }
1544  else
1545  {
1546  vector<QString>::const_iterator it = devs.begin();
1547  for (; it != devs.end(); ++it)
1548  sel = (current == *it) ? *it : sel;
1549  }
1550 
1551  QString usestr = QString(" -- ");
1552  usestr += QObject::tr("Warning: already in use");
1553 
1554  for (uint i = 0; i < devs.size(); i++)
1555  {
1556  const QString dev = devs[i];
1557  QString desc = dev + (in_use[devs[i]] ? usestr : "");
1558  desc = (current == devs[i]) ? dev : desc;
1559  addSelection(desc, dev, dev == sel);
1560  }
1561 
1562  if (current != cur)
1563  {
1564  _deviceid->SetOverrideDeviceID(current);
1565  }
1566  else if (sel == man_addr && !current.isEmpty())
1567  {
1568  // Populate the proper values for IP address and tuner
1569  QStringList selection = current.split("-");
1570 
1571  _cardip->SetOldValue(selection.first());
1572  _cardtuner->SetOldValue(selection.last());
1573 
1574  _cardip->setValue(selection.first());
1575  _cardtuner->setValue(selection.last());
1576  }
1577 }
1578 
1580 {
1581  clearSelections();
1582 
1584 }
1585 
1587 {
1588 #if 0
1589  LOG(VB_GENERAL, LOG_DEBUG, QString("Got signal with %1").arg(v));
1590 #endif
1591  if (v == HDHomeRunDeviceIDList::tr("Manually Enter IP Address"))
1592  {
1593  _cardip->setEnabled(true);
1594  _cardtuner->setEnabled(true);
1595 #if 0
1596  LOG(VB_GENERAL, LOG_DEBUG, "Done");
1597 #endif
1598  }
1599  else if (!v.isEmpty())
1600  {
1601  if (_oldValue == HDHomeRunDeviceIDList::tr("Manually Enter IP Address"))
1602  {
1603  _cardip->setEnabled(false);
1604  _cardtuner->setEnabled(false);
1605  }
1606  _deviceid->setValue(v);
1607 
1608  // Update _cardip and cardtuner
1609  _cardip->setValue((*_devicelist)[v].cardip);
1610  _cardtuner->setValue(QString("%1").arg((*_devicelist)[v].cardtuner));
1611  _desc->setValue((*_devicelist)[v].desc);
1612  }
1613  _oldValue = v;
1614 };
1615 
1616 // -----------------------
1617 // VBOX Configuration
1618 // -----------------------
1619 
1621 {
1622  setLabel(QObject::tr("IP Address"));
1623  setHelpText(QObject::tr("Device IP or ID of a VBox device. eg. '192.168.1.100' or 'vbox_3718'"));
1624  setEnabled(false);
1625  connect(this, SIGNAL(valueChanged(const QString&)),
1626  this, SLOT(UpdateDevices(const QString&)));
1627  _oldValue="";
1628 };
1629 
1631 {
1633  if (e)
1634  {
1635  if (!_oldValue.isEmpty())
1637  emit NewIP(getValue());
1638  }
1639  else
1640  {
1641  _oldValue = getValue();
1642  _oldValue.detach();
1643  }
1644 }
1645 
1646 void VBoxIP::UpdateDevices(const QString &v)
1647 {
1648  if (isEnabled())
1649  emit NewIP(v);
1650 }
1651 
1653 {
1654  setLabel(QObject::tr("Tuner"));
1655  setHelpText(QObject::tr("Number and type of the tuner to use. eg '1-DVBT/T2'."));
1656  setEnabled(false);
1657  connect(this, SIGNAL(valueChanged(const QString&)),
1658  this, SLOT(UpdateDevices(const QString&)));
1659  _oldValue = "";
1660 };
1661 
1663 {
1665  if (e) {
1666  if (!_oldValue.isEmpty())
1668  emit NewTuner(getValue());
1669  }
1670  else
1671  {
1672  _oldValue = getValue();
1673  }
1674 }
1675 
1676 void VBoxTunerIndex::UpdateDevices(const QString &v)
1677 {
1678  if (isEnabled())
1679  emit NewTuner(v);
1680 }
1681 
1683  MythUITextEditSetting(new CaptureCardDBStorage(this, parent, "videodevice")),
1684  _ip(QString::null),
1685  _tuner(QString::null),
1686  _overridedeviceid(QString::null)
1687 {
1688  setLabel(tr("Device ID"));
1689  setHelpText(tr("Device ID of VBox device"));
1690 }
1691 
1692 void VBoxDeviceID::SetIP(const QString &ip)
1693 {
1694  _ip = ip;
1695  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1696 }
1697 
1698 void VBoxDeviceID::SetTuner(const QString &tuner)
1699 {
1700  _tuner = tuner;
1701  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1702 }
1703 
1704 void VBoxDeviceID::SetOverrideDeviceID(const QString &deviceid)
1705 {
1706  _overridedeviceid = deviceid;
1707  setValue(deviceid);
1708 }
1709 
1711 {
1712  GetStorage()->Load();
1713  if (!_overridedeviceid.isEmpty())
1714  {
1716  _overridedeviceid = QString::null;
1717  }
1718 }
1719 
1721  VBoxDeviceID *deviceid,
1722  StandardSetting *desc,
1723  VBoxIP *cardip,
1724  VBoxTunerIndex *cardtuner,
1725  VBoxDeviceList *devicelist) :
1726  _deviceid(deviceid),
1727  _desc(desc),
1728  _cardip(cardip),
1729  _cardtuner(cardtuner),
1730  _devicelist(devicelist)
1731 {
1732  setLabel(QObject::tr("Available devices"));
1733  setHelpText(
1734  QObject::tr(
1735  "Device IP or ID, tuner number and tuner type of available VBox devices."));
1736 
1737  connect(this, SIGNAL(valueChanged(const QString&)),
1738  this, SLOT(UpdateDevices(const QString&)));
1739 
1740  _oldValue = "";
1741 };
1742 
1744 void VBoxDeviceIDList::fillSelections(const QString &cur)
1745 {
1746  clearSelections();
1747 
1748  vector<QString> devs;
1749  QMap<QString, bool> in_use;
1750 
1751  QString current = cur;
1752 
1753  VBoxDeviceList::iterator it = _devicelist->begin();
1754  for (; it != _devicelist->end(); ++it)
1755  {
1756  devs.push_back(it.key());
1757  in_use[it.key()] = (*it).inuse;
1758  }
1759 
1760  QString man_addr = VBoxDeviceIDList::tr("Manually Enter IP Address");
1761  QString sel = man_addr;
1762  devs.push_back(sel);
1763 
1764  vector<QString>::const_iterator it2 = devs.begin();
1765  for (; it2 != devs.end(); ++it2)
1766  sel = (current == *it2) ? *it2 : sel;
1767 
1768  QString usestr = QString(" -- ");
1769  usestr += QObject::tr("Warning: already in use");
1770 
1771  for (uint i = 0; i < devs.size(); i++)
1772  {
1773  const QString dev = devs[i];
1774  QString desc = dev + (in_use[devs[i]] ? usestr : "");
1775  addSelection(desc, dev, dev == sel);
1776  }
1777 
1778  if (current != cur)
1779  {
1780  _deviceid->SetOverrideDeviceID(current);
1781  }
1782  else if (sel == man_addr && !current.isEmpty())
1783  {
1784  // Populate the proper values for IP address and tuner
1785  QStringList selection = current.split("-");
1786 
1787  _cardip->SetOldValue(selection.first());
1788  _cardtuner->SetOldValue(selection.last());
1789 
1790  _cardip->setValue(selection.first());
1791  _cardtuner->setValue(selection.last());
1792  }
1793 }
1794 
1796 {
1797  clearSelections();
1798 
1800 }
1801 
1802 void VBoxDeviceIDList::UpdateDevices(const QString &v)
1803 {
1804  if (v == VBoxDeviceIDList::tr("Manually Enter IP Address"))
1805  {
1806  _cardip->setEnabled(true);
1807  _cardtuner->setEnabled(true);
1808  }
1809  else if (!v.isEmpty())
1810  {
1811  if (_oldValue == VBoxDeviceIDList::tr("Manually Enter IP Address"))
1812  {
1813  _cardip->setEnabled(false);
1814  _cardtuner->setEnabled(false);
1815  }
1816  _deviceid->setValue(v);
1817 
1818  // Update _cardip and _cardtuner
1819  _cardip->setValue((*_devicelist)[v].cardip);
1820  _cardtuner->setValue(QString("%1").arg((*_devicelist)[v].tunerno));
1821  _desc->setValue((*_devicelist)[v].desc);
1822  }
1823  _oldValue = v;
1824 };
1825 
1826 // -----------------------
1827 // IPTV Configuration
1828 // -----------------------
1829 
1831 {
1832  public:
1833  explicit IPTVHost(const CaptureCard &parent) :
1834  CaptureCardTextEditSetting(parent, "videodevice")
1835  {
1836  setValue("http://mafreebox.freebox.fr/freeboxtv/playlist.m3u");
1837  setLabel(QObject::tr("M3U URL"));
1838  setHelpText(
1839  QObject::tr("URL of M3U containing RTSP/RTP/UDP channel URLs."));
1840  }
1841 };
1842 
1843 static void IPTVConfigurationGroup(CaptureCard& parent, CardType& cardType)
1844 {
1845  cardType.addTargetedChild("FREEBOX", new IPTVHost(parent));
1846  cardType.addTargetedChild("FREEBOX", new ChannelTimeout(parent, 30000, 1750));
1847  cardType.addTargetedChild("FREEBOX", new EmptyAudioDevice(parent));
1848  cardType.addTargetedChild("FREEBOX", new EmptyVBIDevice(parent));
1849 }
1850 
1852 {
1853  public:
1854  explicit ASIDevice(const CaptureCard &parent) :
1855  CaptureCardComboBoxSetting(parent, true, "videodevice")
1856  {
1857  setLabel(QObject::tr("ASI device"));
1858  fillSelections(QString::null);
1859  };
1860 
1864  void fillSelections(const QString &current)
1865  {
1866  clearSelections();
1867 
1868  // Get devices from filesystem
1869  QStringList sdevs = CardUtil::ProbeVideoDevices("ASI");
1870 
1871  // Add current if needed
1872  if (!current.isEmpty() &&
1873  (find(sdevs.begin(), sdevs.end(), current) == sdevs.end()))
1874  {
1875  stable_sort(sdevs.begin(), sdevs.end());
1876  }
1877 
1878  // Get devices from DB
1879  QStringList db = CardUtil::GetVideoDevices("ASI");
1880 
1881  // Figure out which physical devices are already in use
1882  // by another card defined in the DB, and select a device
1883  // for new configs (preferring non-conflicing devices).
1884  QMap<QString,bool> in_use;
1885  QString sel = current;
1886  for (uint i = 0; i < (uint)sdevs.size(); i++)
1887  {
1888  const QString dev = sdevs[i];
1889  in_use[sdevs[i]] = find(db.begin(), db.end(), dev) != db.end();
1890  if (sel.isEmpty() && !in_use[sdevs[i]])
1891  sel = dev;
1892  }
1893 
1894  // Unfortunately all devices are conflicted, select first device.
1895  if (sel.isEmpty() && sdevs.size())
1896  sel = sdevs[0];
1897 
1898  QString usestr = QString(" -- ");
1899  usestr += QObject::tr("Warning: already in use");
1900 
1901  // Add the devices to the UI
1902  bool found = false;
1903  for (uint i = 0; i < (uint)sdevs.size(); i++)
1904  {
1905  const QString dev = sdevs[i];
1906  QString desc = dev + (in_use[sdevs[i]] ? usestr : "");
1907  desc = (current == sdevs[i]) ? dev : desc;
1908  addSelection(desc, dev, dev == sel);
1909  found |= (dev == sel);
1910  }
1911 
1912  // If a configured device isn't on the list, add it with warning
1913  if (!found && !current.isEmpty())
1914  {
1915  QString desc = current + " -- " +
1916  QObject::tr("Warning: unable to open");
1917  addSelection(desc, current, true);
1918  }
1919  }
1920 
1921  virtual void Load(void)
1922  {
1923  clearSelections();
1924  addSelection(QString::null);
1925  GetStorage()->Load();
1927  }
1928 };
1929 
1931  CardType &cardType):
1932  parent(a_parent),
1933  device(new ASIDevice(parent)),
1934  cardinfo(new TransTextEditSetting())
1935 {
1936  setVisible(false);
1937  cardinfo->setEnabled(false);
1938  cardType.addChild(device);
1939  cardType.addChild(new EmptyAudioDevice(parent));
1940  cardType.addChild(new EmptyVBIDevice(parent));
1941  cardType.addChild(cardinfo);
1942 
1943  connect(device, SIGNAL(valueChanged(const QString&)),
1944  this, SLOT( probeCard( const QString&)));
1945 
1947 };
1948 
1950 {
1951 #ifdef USING_ASI
1952  if (device.isEmpty())
1953  {
1954  cardinfo->setValue("");
1955  return;
1956  }
1957 
1958  if (parent.getCardID() && parent.GetRawCardType() != "ASI")
1959  {
1960  cardinfo->setValue("");
1961  return;
1962  }
1963 
1964  QString error;
1965  int device_num = CardUtil::GetASIDeviceNumber(device, &error);
1966  if (device_num < 0)
1967  {
1968  cardinfo->setValue(tr("Not a valid DVEO ASI card"));
1969  LOG(VB_GENERAL, LOG_WARNING,
1970  "ASIConfigurationGroup::probeCard(), Warning: " + error);
1971  return;
1972  }
1973  cardinfo->setValue(tr("Valid DVEO ASI card"));
1974 #else
1975  cardinfo->setValue(QString("Not compiled with ASI support"));
1976 #endif
1977 }
1978 
1980  CardType& a_cardtype):
1981  parent(a_parent),
1982  info(new TransTextEditSetting()), size(new TransTextEditSetting())
1983 {
1984  setVisible(false);
1985  FileDevice *device = new FileDevice(parent);
1986  device->setHelpText(tr("A local file used to simulate a recording."
1987  " Leave empty to use MythEvents to trigger an"
1988  " external program to import recording files."));
1989  a_cardtype.addTargetedChild("IMPORT", device);
1990 
1991  a_cardtype.addTargetedChild("IMPORT", new EmptyAudioDevice(parent));
1992  a_cardtype.addTargetedChild("IMPORT", new EmptyVBIDevice(parent));
1993 
1994  info->setLabel(tr("File info"));
1995  info->setEnabled(false);
1996  a_cardtype.addTargetedChild("IMPORT", info);
1997 
1998  size->setLabel(tr("File size"));
1999  size->setEnabled(false);
2000  a_cardtype.addTargetedChild("IMPORT", size);
2001 
2002  connect(device, SIGNAL(valueChanged(const QString&)),
2003  this, SLOT( probeCard( const QString&)));
2004 
2005  probeCard(device->getValue());
2006 };
2007 
2008 void ImportConfigurationGroup::probeCard(const QString &device)
2009 {
2010  QString ci, cs;
2011  QFileInfo fileInfo(device);
2012 
2013  // For convenience, ImportRecorder allows both formats:
2014  if (device.toLower().startsWith("file:"))
2015  fileInfo.setFile(device.mid(5));
2016 
2017  if (fileInfo.exists())
2018  {
2019  if (fileInfo.isReadable() && (fileInfo.isFile()))
2020  {
2021  ci = HTTPRequest::TestMimeType(fileInfo.absoluteFilePath());
2022  cs = tr("%1 MB").arg(fileInfo.size() / 1024 / 1024);
2023  }
2024  else
2025  ci = tr("File not readable");
2026  }
2027  else
2028  {
2029  ci = tr("File %1 does not exist").arg(device);
2030  }
2031 
2032  info->setValue(ci);
2033  size->setValue(cs);
2034 }
2035 
2037 {
2038  public:
2041  new CaptureCardDBStorage(this, parent, "dvb_eitscan"))
2042  {
2043  setLabel(QObject::tr("Use HD HomeRun for active EIT scan"));
2044  setValue(true);
2045  setHelpText(
2046  QObject::tr("If enabled, activate active scanning for "
2047  "program data (EIT). When this option is enabled "
2048  "the HD HomeRun is constantly in-use."));
2049  };
2050 };
2051 
2052 
2054  (CaptureCard& a_parent, CardType &a_cardtype) :
2055  parent(a_parent)
2056 {
2057  setVisible(false);
2058 
2059  // Fill Device list
2060  FillDeviceList();
2061 
2062  deviceid = new HDHomeRunDeviceID(parent);
2063  desc = new GroupSetting();
2064  desc->setLabel(tr("Description"));
2065  cardip = new HDHomeRunIP();
2066  cardtuner = new HDHomeRunTunerIndex();
2067  deviceidlist = new HDHomeRunDeviceIDList(
2068  deviceid, desc, cardip, cardtuner, &devicelist);
2069 
2070  a_cardtype.addTargetedChild("HDHOMERUN", deviceidlist);
2071  a_cardtype.addTargetedChild("HDHOMERUN", new EmptyAudioDevice(parent));
2072  a_cardtype.addTargetedChild("HDHOMERUN", new EmptyVBIDevice(parent));
2073  a_cardtype.addTargetedChild("HDHOMERUN", deviceid);
2074  a_cardtype.addTargetedChild("HDHOMERUN", desc);
2075  a_cardtype.addTargetedChild("HDHOMERUN", cardip);
2076  a_cardtype.addTargetedChild("HDHOMERUN", cardtuner);
2077 
2078  GroupSetting *buttonRecOpt = new GroupSetting();
2079  buttonRecOpt->setLabel(tr("Recording Options"));
2080  buttonRecOpt->addChild(new SignalTimeout(parent, 1000, 250));
2081  buttonRecOpt->addChild(new ChannelTimeout(parent, 3000, 1750));
2082  buttonRecOpt->addChild(new HDHomeRunEITScan(parent));
2083  a_cardtype.addTargetedChild("HDHOMERUN", buttonRecOpt);
2084 
2085  connect(cardip, SIGNAL(NewIP(const QString&)),
2086  deviceid, SLOT( SetIP(const QString&)));
2087  connect(cardtuner, SIGNAL(NewTuner(const QString&)),
2088  deviceid, SLOT( SetTuner(const QString&)));
2089 };
2090 
2092 {
2093  devicelist.clear();
2094 
2095  // Find physical devices first
2096  // ProbeVideoDevices returns "deviceid ip" pairs
2097  QStringList devs = CardUtil::ProbeVideoDevices("HDHOMERUN");
2098 
2099  QStringList::const_iterator it;
2100 
2101  for (it = devs.begin(); it != devs.end(); ++it)
2102  {
2103  QString dev = *it;
2104  QStringList devinfo = dev.split(" ");
2105  QString devid = devinfo.at(0);
2106  QString devip = devinfo.at(1);
2107  QString devtuner = devinfo.at(2);
2108 
2109  HDHomeRunDevice tmpdevice;
2110  tmpdevice.deviceid = devid;
2111  tmpdevice.desc = CardUtil::GetHDHRdesc(devid);
2112  tmpdevice.cardip = devip;
2113  tmpdevice.inuse = false;
2114  tmpdevice.discovered = true;
2115  tmpdevice.cardtuner = devtuner;
2116  tmpdevice.mythdeviceid =
2117  tmpdevice.deviceid + "-" + tmpdevice.cardtuner;
2118  devicelist[tmpdevice.mythdeviceid] = tmpdevice;
2119  }
2120  uint found_device_count = devicelist.size();
2121 
2122  // Now find configured devices
2123 
2124  // returns "xxxxxxxx-n" or "ip.ip.ip.ip-n" values
2125  QStringList db = CardUtil::GetVideoDevices("HDHOMERUN");
2126 
2127  for (it = db.begin(); it != db.end(); ++it)
2128  {
2129  QMap<QString, HDHomeRunDevice>::iterator dit;
2130 
2131  dit = devicelist.find(*it);
2132 
2133  if (dit == devicelist.end())
2134  {
2135  if ((*it).toUpper() == "FFFFFFFF-0" && 2 == found_device_count)
2136  dit = devicelist.begin();
2137 
2138  if ((*it).toUpper() == "FFFFFFFF-1" && 2 == found_device_count)
2139  {
2140  dit = devicelist.begin();
2141  ++dit;
2142  }
2143  }
2144 
2145  if (dit != devicelist.end())
2146  {
2147  (*dit).inuse = true;
2148  continue;
2149  }
2150 
2151  HDHomeRunDevice tmpdevice;
2152  tmpdevice.mythdeviceid = *it;
2153  tmpdevice.inuse = true;
2154  tmpdevice.discovered = false;
2155 
2156  if (ProbeCard(tmpdevice))
2157  devicelist[tmpdevice.mythdeviceid] = tmpdevice;
2158  }
2159 
2160 #if 0
2161  // Debug dump of cards
2162  QMap<QString, HDHomeRunDevice>::iterator debugit;
2163  for (debugit = devicelist.begin(); debugit != devicelist.end(); ++debugit)
2164  {
2165  LOG(VB_GENERAL, LOG_DEBUG, QString("%1: %2 %3 %4 %5 %6 %7")
2166  .arg(debugit.key())
2167  .arg((*debugit).mythdeviceid)
2168  .arg((*debugit).deviceid)
2169  .arg((*debugit).cardip)
2170  .arg((*debugit).cardtuner)
2171  .arg((*debugit).inuse)
2172  .arg((*debugit).discovered));
2173  }
2174 #endif
2175 }
2176 
2178 {
2179 #ifdef USING_HDHOMERUN
2180  hdhomerun_device_t *thisdevice =
2181  hdhomerun_device_create_from_str(
2182  tmpdevice.mythdeviceid.toLocal8Bit().constData(), NULL);
2183 
2184  if (thisdevice)
2185  {
2186  uint device_id = hdhomerun_device_get_device_id(thisdevice);
2187  uint device_ip = hdhomerun_device_get_device_ip(thisdevice);
2188  uint tuner = hdhomerun_device_get_tuner(thisdevice);
2189  hdhomerun_device_destroy(thisdevice);
2190 
2191  if (device_id == 0)
2192  tmpdevice.deviceid = "NOTFOUND";
2193  else
2194  {
2195  tmpdevice.deviceid = QString("%1").arg(device_id, 8, 16);
2196  tmpdevice.desc = CardUtil::GetHDHRdesc(tmpdevice.deviceid);
2197  }
2198 
2199  tmpdevice.deviceid = tmpdevice.deviceid.toUpper();
2200 
2201  tmpdevice.cardip = QString("%1.%2.%3.%4")
2202  .arg((device_ip>>24) & 0xFF).arg((device_ip>>16) & 0xFF)
2203  .arg((device_ip>> 8) & 0xFF).arg((device_ip>> 0) & 0xFF);
2204 
2205  tmpdevice.cardtuner = QString("%1").arg(tuner);
2206  return true;
2207  }
2208 #endif // USING_HDHOMERUN
2209  return false;
2210 }
2211 
2212 // -----------------------
2213 // VBox Configuration
2214 // -----------------------
2215 
2217  (CaptureCard& a_parent, CardType& a_cardtype) :
2218  parent(a_parent)
2219 {
2220  setVisible(false);
2221 
2222  // Fill Device list
2223  FillDeviceList();
2224 
2225  deviceid = new VBoxDeviceID(parent);
2226  desc = new GroupSetting();
2227  desc->setLabel(tr("Description"));
2228  cardip = new VBoxIP();
2229  cardtuner = new VBoxTunerIndex();
2230  deviceidlist = new VBoxDeviceIDList(
2231  deviceid, desc, cardip, cardtuner, &devicelist);
2232 
2233  a_cardtype.addTargetedChild("VBOX", deviceidlist);
2234  a_cardtype.addTargetedChild("VBOX", new EmptyAudioDevice(parent));
2235  a_cardtype.addTargetedChild("VBOX", new EmptyVBIDevice(parent));
2236  a_cardtype.addTargetedChild("VBOX", deviceid);
2237  a_cardtype.addTargetedChild("VBOX", desc);
2238  a_cardtype.addTargetedChild("VBOX", cardip);
2239  a_cardtype.addTargetedChild("VBOX", cardtuner);
2240  a_cardtype.addTargetedChild("VBOX", new SignalTimeout(parent, 7000, 1000));
2241  a_cardtype.addTargetedChild("VBOX", new ChannelTimeout(parent, 10000, 1750));
2242 // TransButtonSetting *buttonRecOpt = new TransButtonSetting();
2243 // buttonRecOpt->setLabel(tr("Recording Options"));
2244 // addChild(buttonRecOpt);
2245 
2246 // connect(buttonRecOpt, SIGNAL(pressed()),
2247 // this, SLOT( VBoxExtraPanel()));
2248 
2249  connect(cardip, SIGNAL(NewIP(const QString&)),
2250  deviceid, SLOT( SetIP(const QString&)));
2251  connect(cardtuner, SIGNAL(NewTuner(const QString&)),
2252  deviceid, SLOT( SetTuner(const QString&)));
2253 };
2254 
2256 {
2257  devicelist.clear();
2258 
2259  // Find physical devices first
2260  // ProbeVideoDevices returns "deviceid ip tunerno tunertype"
2261  QStringList devs = CardUtil::ProbeVideoDevices("VBOX");
2262 
2263  QStringList::const_iterator it;
2264 
2265  for (it = devs.begin(); it != devs.end(); ++it)
2266  {
2267  QString dev = *it;
2268  QStringList devinfo = dev.split(" ");
2269  QString id = devinfo.at(0);
2270  QString ip = devinfo.at(1);
2271  QString tunerNo = devinfo.at(2);
2272  QString tunerType = devinfo.at(3);
2273 
2274  VBoxDevice tmpdevice;
2275  tmpdevice.deviceid = id;
2276  tmpdevice.desc = CardUtil::GetVBoxdesc(id, ip, tunerNo, tunerType);
2277  tmpdevice.cardip = ip;
2278  tmpdevice.inuse = false;
2279  tmpdevice.discovered = true;
2280  tmpdevice.tunerno = tunerNo;
2281  tmpdevice.tunertype = tunerType;
2282  tmpdevice.mythdeviceid = id + "-" + tunerNo + "-" + tunerType;
2283  devicelist[tmpdevice.mythdeviceid] = tmpdevice;
2284  }
2285 
2286  // Now find configured devices
2287 
2288  // returns "ip.ip.ip.ip-n-type" or deviceid-n-type values
2289  QStringList db = CardUtil::GetVideoDevices("VBOX");
2290 
2291  for (it = db.begin(); it != db.end(); ++it)
2292  {
2293  QMap<QString, VBoxDevice>::iterator dit;
2294  dit = devicelist.find(*it);
2295 
2296  if (dit != devicelist.end())
2297  (*dit).inuse = true;
2298  }
2299 }
2300 
2301 // -----------------------
2302 // Ceton Configuration
2303 // -----------------------
2304 
2305 CetonSetting::CetonSetting(const char* label, const char* helptext)
2306 {
2307  setLabel(QObject::tr(label));
2308  setHelpText(tr(helptext));
2309  connect(this, SIGNAL(valueChanged( const QString&)),
2310  this, SLOT( UpdateDevices(const QString&)));
2311 }
2312 
2313 void CetonSetting::UpdateDevices(const QString &v)
2314 {
2315  if (isEnabled())
2316  emit NewValue(v);
2317 }
2318 
2319 void CetonSetting::LoadValue(const QString &value)
2320 {
2321  setValue(value);
2322 }
2323 
2325  MythUITextEditSetting(new CaptureCardDBStorage(this, parent, "videodevice")),
2326  _ip(), _card(), _tuner(), _parent(parent)
2327 {
2328  setLabel(tr("Device ID"));
2329  setHelpText(tr("Device ID of Ceton device"));
2330 }
2331 
2332 void CetonDeviceID::SetIP(const QString &ip)
2333 {
2334  QString regexp = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){4}$";
2335  if (QRegExp(regexp).exactMatch(ip + "."))
2336  {
2337  _ip = ip;
2338  setValue(QString("%1-RTP.%3").arg(_ip).arg(_tuner));
2339  }
2340 }
2341 
2342 void CetonDeviceID::SetTuner(const QString &tuner)
2343 {
2344  if (QRegExp("^\\d$").exactMatch(tuner))
2345  {
2346  _tuner = tuner;
2347  setValue(QString("%1-RTP.%2").arg(_ip).arg(_tuner));
2348  }
2349 }
2350 
2352 {
2353  GetStorage()->Load();
2354  UpdateValues();
2355 }
2356 
2358 {
2359  QRegExp newstyle("^([0-9.]+)-(\\d|RTP)\\.(\\d)$");
2360  if (newstyle.exactMatch(getValue()))
2361  {
2362  emit LoadedIP(newstyle.cap(1));
2363  emit LoadedTuner(newstyle.cap(3));
2364  }
2365 }
2366 
2367 static void CetonConfigurationGroup(CaptureCard& parent, CardType& cardtype)
2368 {
2369  CetonDeviceID *deviceid = new CetonDeviceID(parent);
2370  GroupSetting *desc = new GroupSetting();
2371  desc->setLabel(QCoreApplication::translate("CetonConfigurationGroup",
2372  "Description"));
2373  CetonSetting *ip = new CetonSetting(
2374  "IP Address",
2375  "IP Address of the Ceton device (192.168.200.1 by default)");
2376  CetonSetting *tuner = new CetonSetting(
2377  "Tuner",
2378  "Number of the tuner on the Ceton device (first tuner is number 0)");
2379 
2380  cardtype.addTargetedChild("CETON", ip);
2381  cardtype.addTargetedChild("CETON", tuner);
2382  cardtype.addTargetedChild("CETON", deviceid);
2383  cardtype.addTargetedChild("CETON", desc);
2384  cardtype.addTargetedChild("CETON", new SignalTimeout(parent, 1000, 250));
2385  cardtype.addTargetedChild("CETON", new ChannelTimeout(parent, 3000, 1750));
2386 
2387  QObject::connect(ip, SIGNAL(NewValue(const QString&)),
2388  deviceid, SLOT( SetIP(const QString&)));
2389  QObject::connect(tuner, SIGNAL(NewValue(const QString&)),
2390  deviceid, SLOT( SetTuner(const QString&)));
2391 
2392  QObject::connect(deviceid, SIGNAL(LoadedIP(const QString&)),
2393  ip, SLOT( LoadValue(const QString&)));
2394  QObject::connect(deviceid, SIGNAL(LoadedTuner(const QString&)),
2395  tuner, SLOT( LoadValue(const QString&)));
2396 }
2397 
2399  CardType& a_cardtype) :
2400  parent(a_parent),
2401  cardinfo(new TransTextEditSetting()), vbidev(new VBIDevice(parent))
2402 {
2403  setVisible(false);
2404  QString drv = "(?!ivtv|hdpvr|(saa7164(.*))).*";
2405  VideoDevice *device = new VideoDevice(parent, 0, 15, QString::null, drv);
2406 
2407  cardinfo->setLabel(tr("Probed info"));
2408  cardinfo->setEnabled(false);
2409 
2410  a_cardtype.addTargetedChild("V4L", device);
2411  a_cardtype.addTargetedChild("V4L", cardinfo);
2412  a_cardtype.addTargetedChild("V4L", vbidev);
2413  a_cardtype.addTargetedChild("V4L", new AudioDevice(parent));
2414  a_cardtype.addTargetedChild("V4L", new AudioRateLimit(parent));
2415  a_cardtype.addTargetedChild("V4L", new SkipBtAudio(parent));
2416 
2417  connect(device, SIGNAL(valueChanged(const QString&)),
2418  this, SLOT( probeCard( const QString&)));
2419 
2420  probeCard(device->getValue());
2421 };
2422 
2423 void V4LConfigurationGroup::probeCard(const QString &device)
2424 {
2425  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2426 
2427  QByteArray adevice = device.toLatin1();
2428  int videofd = open(adevice.constData(), O_RDWR);
2429  if (videofd >= 0)
2430  {
2431  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2432  ci = cn = tr("Failed to probe");
2433  else if (!dn.isEmpty())
2434  ci = cn + " [" + dn + "]";
2435  close(videofd);
2436  }
2437 
2438  cardinfo->setValue(ci);
2439  vbidev->setFilter(cn, dn);
2440 }
2441 
2443  CardType &a_cardtype) :
2444  parent(a_parent),
2445  device(NULL), vbidevice(NULL),
2447 {
2448  setVisible(false);
2449  QString drv = "ivtv|(saa7164(.*))";
2450  device = new VideoDevice(parent, 0, 15, QString::null, drv);
2451  vbidevice = new VBIDevice(parent);
2452  vbidevice->setVisible(false);
2453 
2454  cardinfo->setLabel(tr("Probed info"));
2455  cardinfo->setEnabled(false);
2456 
2457  a_cardtype.addTargetedChild("MPEG", device);
2458  a_cardtype.addTargetedChild("MPEG", vbidevice);
2459  a_cardtype.addTargetedChild("MPEG", cardinfo);
2460  a_cardtype.addTargetedChild("MPEG", new ChannelTimeout(parent, 12000, 2000));
2461 
2462  connect(device, SIGNAL(valueChanged(const QString&)),
2463  this, SLOT( probeCard( const QString&)));
2464 
2466 }
2467 
2469 {
2470  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2471 
2472  QByteArray adevice = device.toLatin1();
2473  int videofd = open(adevice.constData(), O_RDWR);
2474  if (videofd >= 0)
2475  {
2476  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2477  ci = cn = tr("Failed to probe");
2478  else if (!dn.isEmpty())
2479  ci = cn + " [" + dn + "]";
2480  close(videofd);
2481  }
2482 
2483  cardinfo->setValue(ci);
2484  vbidevice->setVisible(dn!="ivtv");
2485  vbidevice->setFilter(cn, dn);
2486 }
2487 
2489  CardType &a_cardtype) :
2490  parent(a_parent),
2491  info(new TransTextEditSetting()), size(new TransTextEditSetting())
2492 {
2493  setVisible(false);
2494  FileDevice *device = new FileDevice(parent);
2495  device->setHelpText(tr("A local MPEG file used to simulate a recording."));
2496 
2497  a_cardtype.addTargetedChild("DEMO", device);
2498 
2499  a_cardtype.addTargetedChild("DEMO", new EmptyAudioDevice(parent));
2500  a_cardtype.addTargetedChild("DEMO", new EmptyVBIDevice(parent));
2501 
2502  info->setLabel(tr("File info"));
2503  info->setEnabled(false);
2504  a_cardtype.addTargetedChild("DEMO", info);
2505 
2506  size->setLabel(tr("File size"));
2507  size->setEnabled(false);
2508  a_cardtype.addTargetedChild("DEMO", size);
2509 
2510  connect(device, SIGNAL(valueChanged(const QString&)),
2511  this, SLOT( probeCard( const QString&)));
2512 
2513  probeCard(device->getValue());
2514 }
2515 
2516 void DemoConfigurationGroup::probeCard(const QString &device)
2517 {
2518  QString ci, cs;
2519  QFileInfo fileInfo(device.mid(5));
2520  if (fileInfo.exists())
2521  {
2522  if (fileInfo.isReadable() && (fileInfo.isFile()))
2523  {
2524  ci = HTTPRequest::TestMimeType(fileInfo.absoluteFilePath());
2525  cs = tr("%1 MB").arg(fileInfo.size() / 1024 / 1024);
2526  }
2527  else
2528  ci = tr("File not readable");
2529  }
2530  else
2531  {
2532  ci = tr("File does not exist");
2533  }
2534 
2535  info->setValue(ci);
2536  size->setValue(cs);
2537 }
2538 
2539 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2541  CardType &a_cardtype) :
2542  parent(a_parent),
2543  info(new TransTextEditSetting())
2544 {
2545  setVisible(false);
2546  FileDevice *device = new FileDevice(parent);
2547  device->setHelpText(tr("A 'black box' application controlled via "
2548  "stdin, status on stderr and TransportStream "
2549  "read from stdout"));
2550  a_cardtype.addTargetedChild("EXTERNAL", device);
2551 
2552  info->setLabel(tr("File info"));
2553  info->setEnabled(false);
2554  a_cardtype.addTargetedChild("EXTERNAL", info);
2555 
2556  connect(device, SIGNAL(valueChanged(const QString&)),
2557  this, SLOT( probeApp( const QString&)));
2558 
2559  probeApp(device->getValue());
2560 }
2561 
2562 void ExternalConfigurationGroup::probeApp(const QString & path)
2563 {
2564  int idx1 = path.toLower().startsWith("file:") ? 5 : 0;
2565  int idx2 = path.indexOf(' ', idx1);
2566 
2567  QString ci, cs;
2568  QFileInfo fileInfo(path.mid(idx1, idx2 - idx1));
2569 
2570  if (fileInfo.exists())
2571  {
2572  ci = tr("'%1' is valid.").arg(fileInfo.absoluteFilePath());
2573  if (!fileInfo.isReadable() || !fileInfo.isFile())
2574  ci = tr("'%1' is not readable.").arg(fileInfo.absoluteFilePath());
2575  if (!fileInfo.isExecutable())
2576  ci = tr("'%1' is not executable.").arg(fileInfo.absoluteFilePath());
2577  }
2578  else
2579  {
2580  ci = tr("'%1' does not exist.").arg(fileInfo.absoluteFilePath());
2581  }
2582 
2583  info->setValue(ci);
2584 }
2585 #endif // !defined( USING_MINGW ) && !defined( _MSC_VER )
2586 
2588  CardType &a_cardtype) :
2589  parent(a_parent), cardinfo(new GroupSetting()),
2590  audioinput(new TunerCardAudioInput(parent, QString::null, "HDPVR")),
2591  vbidevice(NULL)
2592 {
2593  setVisible(false);
2594 
2595  VideoDevice *device =
2596  new VideoDevice(parent, 0, 15, QString::null, "hdpvr");
2597 
2598  cardinfo->setLabel(tr("Probed info"));
2599  cardinfo->setEnabled(false);
2600 
2601  a_cardtype.addTargetedChild("HDPVR", device);
2602  a_cardtype.addTargetedChild("HDPVR", new EmptyAudioDevice(parent));
2603  a_cardtype.addTargetedChild("HDPVR", new EmptyVBIDevice(parent));
2604  a_cardtype.addTargetedChild("HDPVR", cardinfo);
2605  a_cardtype.addTargetedChild("HDPVR", audioinput);
2606  a_cardtype.addTargetedChild("HDPVR", new ChannelTimeout(parent, 15000, 2000));
2607 
2608  connect(device, SIGNAL(valueChanged(const QString&)),
2609  this, SLOT( probeCard( const QString&)));
2610 
2611  probeCard(device->getValue());
2612 }
2613 
2614 void HDPVRConfigurationGroup::probeCard(const QString &device)
2615 {
2616  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2617 
2618  int videofd = open(device.toLocal8Bit().constData(), O_RDWR);
2619  if (videofd >= 0)
2620  {
2621  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2622  ci = cn = tr("Failed to probe");
2623  else if (!dn.isEmpty())
2624  ci = cn + " [" + dn + "]";
2625  close(videofd);
2626  }
2627 
2628  cardinfo->setValue(ci);
2629  audioinput->fillSelections(device);
2630 }
2631 
2633  m_parent(parent),
2634  m_cardinfo(new TransTextEditSetting())
2635 {
2636  setLabel(QObject::tr("V4L2 encoder devices (multirec capable)"));
2637  m_device = new VideoDevice(m_parent, 0, 15);
2638 
2639  cardtype.addTargetedChild("V4L2ENC", m_device);
2640  m_cardinfo->setLabel(tr("Probed info"));
2641  cardtype.addTargetedChild("V4L2ENC", m_cardinfo);
2642 
2643  setVisible(false);
2644 
2645  connect(m_device, SIGNAL(valueChanged(const QString&)),
2646  this, SLOT( probeCard( const QString&)));
2647 
2649 }
2650 
2651 void V4L2encGroup::probeCard(const QString &device_name)
2652 {
2653 #ifdef USING_V4L2
2654  QString card_name = tr("Failed to open");
2655  QString card_info = card_name;
2656  V4L2util v4l2(device_name);
2657 
2658  if (!v4l2.IsOpen())
2659  {
2660  m_DriverName = tr("Failed to probe");
2661  return;
2662  }
2663  m_DriverName = v4l2.DriverName();
2664  card_name = v4l2.CardName();
2665 
2666  if (!m_DriverName.isEmpty())
2667  card_info = card_name + " [" + m_DriverName + "]";
2668 
2669  m_cardinfo->setValue(card_info);
2670 
2671  if (m_device->getSubSettings()->size() == 0)
2672  {
2673  TunerCardAudioInput* audioinput =
2674  new TunerCardAudioInput(m_parent, QString::null, "V4L2");
2675  if (audioinput->fillSelections(device_name) > 1)
2676  {
2677  audioinput->setName("AudioInput");
2678  m_device->addTargetedChild(m_DriverName, audioinput);
2679  }
2680  else
2681  delete audioinput;
2682 
2683  if (v4l2.HasSlicedVBI())
2684  {
2685  VBIDevice* vbidev = new VBIDevice(m_parent);
2686  if (vbidev->setFilter(card_name, m_DriverName) > 0)
2687  {
2688  vbidev->setName("VBIDevice");
2690  }
2691  else
2692  delete vbidev;
2693  }
2694 
2697  new ChannelTimeout(m_parent, 15000, 2000));
2698  }
2699 #endif // USING_V4L2
2700 }
2701 
2703 {
2704  setLabel(QObject::tr("Capture Card Setup"));
2705 
2706  CardType* cardtype = new CardType(parent);
2707  parent.addChild(cardtype);
2708 
2709 #ifdef USING_DVB
2710  cardtype->addTargetedChild("DVB",
2711  new DVBConfigurationGroup(parent, *cardtype));
2712 #endif // USING_DVB
2713 
2714 #ifdef USING_V4L2
2715 # ifdef USING_HDPVR
2716  cardtype->addTargetedChild("HDPVR",
2717  new HDPVRConfigurationGroup(parent, *cardtype));
2718 # endif // USING_HDPVR
2719 #endif // USING_V4L2
2720 
2721 #ifdef USING_HDHOMERUN
2722  cardtype->addTargetedChild("HDHOMERUN",
2723  new HDHomeRunConfigurationGroup(parent, *cardtype));
2724 #endif // USING_HDHOMERUN
2725 
2726 #ifdef USING_VBOX
2727  cardtype->addTargetedChild("VBOX",
2728  new VBoxConfigurationGroup(parent, *cardtype));
2729 #endif // USING_VBOX
2730 
2731 #ifdef USING_FIREWIRE
2732  FirewireConfigurationGroup(parent, *cardtype);
2733 #endif // USING_FIREWIRE
2734 
2735 #ifdef USING_CETON
2736  CetonConfigurationGroup(parent, *cardtype);
2737 #endif // USING_CETON
2738 
2739 #ifdef USING_IPTV
2740  IPTVConfigurationGroup(parent, *cardtype);
2741 #endif // USING_IPTV
2742 
2743 #ifdef USING_V4L2
2744  cardtype->addTargetedChild("V4L2ENC", new V4L2encGroup(parent, *cardtype));
2745  cardtype->addTargetedChild("V4L",
2746  new V4LConfigurationGroup(parent, *cardtype));
2747  cardtype->addTargetedChild("MJPEG",
2748  new V4LConfigurationGroup(parent, *cardtype));
2749  cardtype->addTargetedChild("GO7007",
2750  new V4LConfigurationGroup(parent, *cardtype));
2751 # ifdef USING_IVTV
2752  cardtype->addTargetedChild("MPEG",
2753  new MPEGConfigurationGroup(parent, *cardtype));
2754 # endif // USING_IVTV
2755 #endif // USING_V4L2
2756 
2757 #ifdef USING_ASI
2758  cardtype->addTargetedChild("ASI",
2759  new ASIConfigurationGroup(parent, *cardtype));
2760 #endif // USING_ASI
2761 
2762  // for testing without any actual tuner hardware:
2763  cardtype->addTargetedChild("IMPORT",
2764  new ImportConfigurationGroup(parent, *cardtype));
2765  cardtype->addTargetedChild("DEMO",
2766  new DemoConfigurationGroup(parent, *cardtype));
2767 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2768  cardtype->addTargetedChild("EXTERNAL",
2769  new ExternalConfigurationGroup(parent,
2770  *cardtype));
2771 #endif
2772 }
2773 
2774 CaptureCard::CaptureCard(bool use_card_group)
2775  : id(new ID)
2776 {
2777  addChild(id);
2778  if (use_card_group)
2779  CaptureCardGroup(*this);
2780  addChild(new Hostname(*this));
2781 }
2782 
2783 QString CaptureCard::GetRawCardType(void) const
2784 {
2785  int cardid = getCardID();
2786  if (cardid <= 0)
2787  return QString::null;
2788  return CardUtil::GetRawInputType(cardid);
2789 }
2790 
2792 {
2793  MSqlQuery query(MSqlQuery::InitCon());
2794  QString qstr =
2795  "SELECT cardid, videodevice, cardtype "
2796  "FROM capturecard "
2797  "WHERE hostname = :HOSTNAME AND parentid = 0 "
2798  "ORDER BY cardid";
2799 
2800  query.prepare(qstr);
2801  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
2802 
2803  if (!query.exec())
2804  {
2805  MythDB::DBError("CaptureCard::fillSelections", query);
2806  return;
2807  }
2808 
2809  while (query.next())
2810  {
2811  uint cardid = query.value(0).toUInt();
2812  QString videodevice = query.value(1).toString();
2813  QString cardtype = query.value(2).toString();
2814 
2815  QString label = CardUtil::GetDeviceLabel(cardtype, videodevice);
2816  CaptureCard *card = new CaptureCard();
2817  card->loadByID(cardid);
2818  card->setLabel(label);
2819  setting->addChild(card);
2820  }
2821 }
2822 
2823 void CaptureCard::loadByID(int cardid)
2824 {
2825  id->setValue(cardid);
2826  Load();
2827 }
2828 
2830 {
2831  return true;
2832 }
2833 
2835 {
2837 }
2838 
2839 
2841 {
2842  uint init_cardid = getCardID();
2843  QString init_type = CardUtil::GetRawInputType(init_cardid);
2844  QString init_dev = CardUtil::GetVideoDevice(init_cardid);
2845  QString init_input = CardUtil::GetInputName(init_cardid);
2846 
2848 
2850 
2852 
2853  uint cardid = getCardID();
2854  QString type = CardUtil::GetRawInputType(cardid);
2855  QString dev = CardUtil::GetVideoDevice(cardid);
2856 
2857  if (dev != init_dev)
2858  {
2859  if (!init_dev.isEmpty())
2860  {
2861  uint init_groupid = CardUtil::GetDeviceInputGroup(init_cardid);
2862  CardUtil::UnlinkInputGroup(init_cardid, init_groupid);
2863  }
2864  if (!dev.isEmpty())
2865  {
2866  uint groupid =
2867  CardUtil::CreateDeviceInputGroup(cardid, type,
2868  gCoreContext->GetHostName(), dev);
2869  CardUtil::LinkInputGroup(cardid, groupid);
2870  CardUtil::UnlinkInputGroup(0, groupid);
2871  }
2872  }
2873 
2874  // Handle any cloning we may need to do
2876  {
2877  vector<uint> clones = CardUtil::GetChildInputIDs(cardid);
2878  for (uint i = 0; i < clones.size(); i++)
2879  CardUtil::CloneCard(cardid, clones[i]);
2880  }
2881 }
2882 
2884 {
2885  if (getCardID() == 0)
2886  {
2887  Save();
2888  Load();
2889  }
2890 }
2891 
2893  CaptureCardComboBoxSetting(parent, false, "cardtype")
2894 {
2895  setLabel(QObject::tr("Card type"));
2896  setHelpText(QObject::tr("Change the cardtype to the appropriate type for "
2897  "the capture card you are configuring."));
2898  fillSelections(this);
2899 }
2900 
2902 {
2903 #ifdef USING_DVB
2904  setting->addSelection(
2905  QObject::tr("DVB-T/S/C, ATSC or ISDB-T tuner card"), "DVB");
2906 #endif // USING_DVB
2907 
2908 #ifdef USING_V4L2
2909  setting->addSelection(
2910  QObject::tr("V4L2 encoder"), "V4L2ENC");
2911 #ifdef USING_HDPVR
2912  setting->addSelection(
2913  QObject::tr("HD-PVR H.264 encoder"), "HDPVR");
2914 # endif // USING_HDPVR
2915 #endif // USING_V4L2
2916 
2917 #ifdef USING_HDHOMERUN
2918  setting->addSelection(
2919  QObject::tr("HDHomeRun networked tuner"), "HDHOMERUN");
2920 #endif // USING_HDHOMERUN
2921 
2922 #ifdef USING_VBOX
2923  setting->addSelection(
2924  QObject::tr("V@Box TV Gateway networked tuner"), "VBOX");
2925 #endif // USING_VBOX
2926 
2927 #ifdef USING_FIREWIRE
2928  setting->addSelection(
2929  QObject::tr("FireWire cable box"), "FIREWIRE");
2930 #endif // USING_FIREWIRE
2931 
2932 #ifdef USING_CETON
2933  setting->addSelection(
2934  QObject::tr("Ceton Cablecard tuner"), "CETON");
2935 #endif // USING_CETON
2936 
2937 #ifdef USING_IPTV
2938  setting->addSelection(QObject::tr("IPTV recorder"), "FREEBOX");
2939 #endif // USING_IPTV
2940 
2941 #ifdef USING_V4L2
2942 # ifdef USING_IVTV
2943  setting->addSelection(
2944  QObject::tr("Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"), "MPEG");
2945 # endif // USING_IVTV
2946  setting->addSelection(
2947  QObject::tr("Analog to MJPEG encoder card (Matrox G200, DC10, etc)"), "MJPEG");
2948  setting->addSelection(
2949  QObject::tr("Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
2950  "GO7007");
2951  setting->addSelection(
2952  QObject::tr("Analog capture card"), "V4L");
2953 #endif // USING_V4L2
2954 
2955 #ifdef USING_ASI
2956  setting->addSelection(QObject::tr("DVEO ASI recorder"), "ASI");
2957 #endif
2958 
2959  setting->addSelection(QObject::tr("Import test recorder"), "IMPORT");
2960  setting->addSelection(QObject::tr("Demo test recorder"), "DEMO");
2961 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2962  setting->addSelection(QObject::tr("External (black box) recorder"),
2963  "EXTERNAL");
2964 #endif
2965 }
2966 
2968 {
2969  public:
2970  explicit InputName(const CardInput &parent) :
2971  MythUIComboBoxSetting(new CardInputDBStorage(this, parent, "inputname"))
2972  {
2973  setLabel(QObject::tr("Input name"));
2974  };
2975 
2976  virtual void Load(void)
2977  {
2978  fillSelections();
2980  };
2981 
2983  clearSelections();
2984  addSelection(QObject::tr("(None)"), "None");
2985  uint cardid = static_cast<CardInputDBStorage*>(GetStorage())->getInputID();
2986  QString type = CardUtil::GetRawInputType(cardid);
2987  QString device = CardUtil::GetVideoDevice(cardid);
2988  QStringList inputs;
2989  CardUtil::GetDeviceInputNames(cardid, device, type, inputs);
2990  while (!inputs.isEmpty())
2991  {
2992  addSelection(inputs.front());
2993  inputs.pop_front();
2994  }
2995  };
2996 };
2997 
2999 {
3000  public:
3001  explicit InputDisplayName(const CardInput &parent) :
3002  MythUITextEditSetting(new CardInputDBStorage(this, parent, "displayname"))
3003  {
3004  setLabel(QObject::tr("Display name (optional)"));
3005  setHelpText(QObject::tr(
3006  "This name is displayed on screen when Live TV begins "
3007  "and when changing the selected input or card. If you "
3008  "use this, make sure the information is unique for "
3009  "each input."));
3010  };
3011 };
3012 
3014 {
3015  public:
3016  CardInputComboBoxSetting(const CardInput &parent, const QString &setting) :
3017  MythUIComboBoxSetting(new CardInputDBStorage(this, parent, setting))
3018  {
3019  }
3020 };
3021 
3023 {
3024  public:
3025  explicit SourceID(const CardInput &parent) :
3026  CardInputComboBoxSetting(parent, "sourceid")
3027  {
3028  setLabel(QObject::tr("Video source"));
3029  addSelection(QObject::tr("(None)"), "0");
3030  };
3031 
3032  virtual void Load(void)
3033  {
3034  fillSelections();
3036  };
3037 
3039  clearSelections();
3040  addSelection(QObject::tr("(None)"), "0");
3042  };
3043 };
3044 
3046 {
3047  public:
3048  InputGroup(const CardInput &parent, uint group_num) :
3049  TransMythUIComboBoxSetting(), cardinput(parent),
3050  groupnum(group_num), groupid(0)
3051  {
3052  setLabel(QObject::tr("Input group") +
3053  QString(" %1").arg(groupnum + 1));
3054  setHelpText(QObject::tr(
3055  "Leave as 'Generic' unless this input is shared with "
3056  "another device. Only one of the inputs in an input "
3057  "group will be allowed to record at any given time."));
3058  }
3059 
3060  virtual void Load(void);
3061 
3062  virtual void Save(void)
3063  {
3064  uint inputid = cardinput.getInputID();
3065  uint new_groupid = getValue().toUInt();
3066 
3067  if (groupid)
3068  CardUtil::UnlinkInputGroup(inputid, groupid);
3069 
3070  if (new_groupid)
3071  {
3072  if (CardUtil::UnlinkInputGroup(inputid, new_groupid))
3073  CardUtil::LinkInputGroup(inputid, new_groupid);
3074  }
3075  }
3076 
3077  virtual void Save(QString /*destination*/) { Save(); }
3078 
3079  private:
3083 };
3084 
3086 {
3087 #if 0
3088  LOG(VB_GENERAL, LOG_DEBUG, QString("InputGroup::Load() %1 %2")
3089  .arg(groupnum).arg(cardinput.getInputID()));
3090 #endif
3091 
3092  uint inputid = cardinput.getInputID();
3093  QMap<uint, uint> grpcnt;
3094  vector<QString> names;
3095  vector<uint> grpid;
3096  vector<uint> selected_groupids;
3097 
3098  names.push_back(QObject::tr("Generic"));
3099  grpid.push_back(0);
3100  grpcnt[0]++;
3101 
3102  MSqlQuery query(MSqlQuery::InitCon());
3103  query.prepare(
3104  "SELECT cardinputid, inputgroupid, inputgroupname "
3105  "FROM inputgroup "
3106  "WHERE inputgroupname LIKE 'user:%' "
3107  "ORDER BY inputgroupid, cardinputid, inputgroupname");
3108 
3109  if (!query.exec())
3110  {
3111  MythDB::DBError("InputGroup::Load()", query);
3112  }
3113  else
3114  {
3115  while (query.next())
3116  {
3117  uint groupid = query.value(1).toUInt();
3118  if (inputid && (query.value(0).toUInt() == inputid))
3119  selected_groupids.push_back(groupid);
3120 
3121  grpcnt[groupid]++;
3122 
3123  if (grpcnt[groupid] == 1)
3124  {
3125  names.push_back(query.value(2).toString().mid(5, -1));
3126  grpid.push_back(groupid);
3127  }
3128  }
3129  }
3130 
3131  // makes sure we select something
3132  groupid = 0;
3133  if (groupnum < selected_groupids.size())
3134  groupid = selected_groupids[groupnum];
3135 
3136 #if 0
3137  LOG(VB_GENERAL, LOG_DEBUG, QString("Group num: %1 id: %2")
3138  .arg(groupnum).arg(groupid));
3139  {
3140  QString msg;
3141  for (uint i = 0; i < selected_groupids.size(); i++)
3142  msg += QString("%1 ").arg(selected_groupids[i]);
3143  LOG(VB_GENERAL, LOG_DEBUG, msg);
3144  }
3145 #endif
3146 
3147  // add selections to combobox
3148  clearSelections();
3149  uint index = 0;
3150  for (uint i = 0; i < names.size(); i++)
3151  {
3152  bool sel = (groupid == grpid[i]);
3153  index = (sel) ? i : index;
3154 
3155 #if 0
3156  LOG(VB_GENERAL, LOG_DEBUG, QString("grpid %1, name '%2', i %3, s %4")
3157  .arg(grpid[i]).arg(names[i]) .arg(index).arg(sel ? "T" : "F"));
3158 #endif
3159 
3160  addSelection(names[i], QString::number(grpid[i]), sel);
3161  }
3162 
3163 #if 0
3164  LOG(VB_GENERAL, LOG_DEBUG, QString("Group index: %1").arg(index));
3165 #endif
3166 
3167  if (!names.empty())
3168  setValue(index);
3169 
3171 }
3172 
3174 {
3175  public:
3176  explicit QuickTune(const CardInput &parent) :
3177  CardInputComboBoxSetting(parent, "quicktune")
3178  {
3179  setLabel(QObject::tr("Use quick tuning"));
3180  addSelection(QObject::tr("Never"), "0", true);
3181  addSelection(QObject::tr("Live TV only"), "1", false);
3182  addSelection(QObject::tr("Always"), "2", false);
3183  setHelpText(QObject::tr(
3184  "If enabled, MythTV will tune using only the "
3185  "MPEG program number. The program numbers "
3186  "change more often than DVB or ATSC tuning "
3187  "parameters, so this is slightly less reliable. "
3188  "This will also inhibit EIT gathering during "
3189  "Live TV and recording."));
3190  };
3191 };
3192 
3194 {
3195  public:
3196  explicit ExternalChannelCommand(const CardInput &parent) :
3197  CardInputComboBoxSetting(parent, "externalcommand")
3198  {
3199  setLabel(QObject::tr("External channel change command"));
3200  setValue("");
3201  setHelpText(QObject::tr("If specified, this command will be run to "
3202  "change the channel for inputs which have an external "
3203  "tuner device such as a cable box. The first argument "
3204  "will be the channel number."));
3205  };
3206 };
3207 
3209 {
3210  public:
3211  explicit PresetTuner(const CardInput &parent) :
3212  CardInputComboBoxSetting(parent, "tunechan")
3213  {
3214  setLabel(QObject::tr("Preset tuner to channel"));
3215  setValue("");
3216  setHelpText(QObject::tr("Leave this blank unless you have an external "
3217  "tuner that is connected to the tuner input of your card. "
3218  "If so, you will need to specify the preset channel for "
3219  "the signal (normally 3 or 4)."));
3220  };
3221 };
3222 
3223 void StartingChannel::SetSourceID(const QString &sourceid)
3224 {
3225  clearSelections();
3226  if (sourceid.isEmpty() || !sourceid.toUInt())
3227  return;
3228 
3229  // Get the existing starting channel
3230  int inputId = static_cast<CardInputDBStorage*>(GetStorage())->getInputID();
3231  QString startChan = CardUtil::GetStartingChannel(inputId);
3232 
3233  ChannelInfoList channels = ChannelUtil::GetAllChannels(sourceid.toUInt());
3234 
3235  if (channels.empty())
3236  {
3237  addSelection(tr("Please add channels to this source"),
3238  startChan.isEmpty() ? "0" : startChan);
3239  return;
3240  }
3241 
3242  // If there are channels sort them, then add theme
3243  // (selecting the old start channel if it is there).
3244  QString order = gCoreContext->GetSetting("ChannelOrdering", "channum");
3245  ChannelUtil::SortChannels(channels, order);
3246  bool has_visible = false;
3247  for (uint i = 0; i < channels.size() && !has_visible; i++)
3248  has_visible |= channels[i].visible;
3249 
3250  for (uint i = 0; i < channels.size(); i++)
3251  {
3252  const QString channum = channels[i].channum;
3253  bool sel = channum == startChan;
3254  if (!has_visible || channels[i].visible || sel)
3255  {
3256  addSelection(channum, channum, sel);
3257  }
3258  }
3259 }
3260 
3262 {
3263  public:
3264  explicit InputPriority(const CardInput &parent) :
3265  MythUISpinBoxSetting(new CardInputDBStorage(this, parent, "recpriority"),
3266  -99, 99, 1)
3267  {
3268  setLabel(QObject::tr("Input priority"));
3269  setValue(0);
3270  setHelpText(QObject::tr("If the input priority is not equal for "
3271  "all inputs, the scheduler may choose to record a show "
3272  "at a later time so that it can record on an input with "
3273  "a higher value."));
3274  };
3275 };
3276 
3278 {
3279  public:
3280  ScheduleOrder(const CardInput &parent, int _value) :
3281  MythUISpinBoxSetting(new CardInputDBStorage(this, parent, "schedorder"),
3282  0, 99, 1)
3283  {
3284  setLabel(QObject::tr("Schedule order"));
3285  setValue(_value);
3286  setHelpText(QObject::tr("If priorities and other factors are equal "
3287  "the scheduler will choose the available "
3288  "input with the lowest, non-zero value. "
3289  "Setting this value to zero will make the "
3290  "input unavailable to the scheduler."));
3291  };
3292 };
3293 
3295 {
3296  public:
3297  LiveTVOrder(const CardInput &parent, int _value) :
3298  MythUISpinBoxSetting(new CardInputDBStorage(this, parent, "livetvorder"),
3299  0, 99, 1)
3300  {
3301  setLabel(QObject::tr("Live TV order"));
3302  setValue(_value);
3303  setHelpText(QObject::tr("When entering Live TV, the available, local "
3304  "input with the lowest, non-zero value will "
3305  "be used. If no local inputs are available, "
3306  "the available, remote input with the lowest, "
3307  "non-zero value will be used. "
3308  "Setting this value to zero will make the "
3309  "input unavailable to live TV."));
3310  };
3311 };
3312 
3314 {
3315  public:
3316  explicit DishNetEIT(const CardInput &parent) :
3317  MythUICheckBoxSetting(new CardInputDBStorage(this, parent,
3318  "dishnet_eit"))
3319  {
3320  setLabel(QObject::tr("Use DishNet long-term EIT data"));
3321  setValue(false);
3322  setHelpText(
3323  QObject::tr(
3324  "If you point your satellite dish toward DishNet's birds, "
3325  "you may wish to enable this feature. For best results, "
3326  "enable general EIT collection as well."));
3327  };
3328 };
3329 
3330 CardInput::CardInput(const QString & cardtype, const QString & device,
3331  bool isNewInput, int _cardid) :
3332  id(new ID()),
3333  inputname(new InputName(*this)),
3334  sourceid(new SourceID(*this)),
3335  startchan(new StartingChannel(*this)),
3336  scan(new ButtonStandardSetting(tr("Scan for channels"))),
3337  srcfetch(new ButtonStandardSetting(tr("Fetch channels from listings source"))),
3338  externalInputSettings(new DiSEqCDevSettings()),
3339  inputgrp0(new InputGroup(*this, 0)),
3340  inputgrp1(new InputGroup(*this, 1)),
3341  instancecount(NULL),
3342  schedgroup(NULL)
3343 {
3344  addChild(id);
3345 
3347  {
3349  _cardid, true /*isNewInput*/));
3350  }
3351 
3353  addChild(new InputDisplayName(*this));
3354  addChild(sourceid);
3355 
3356  if (CardUtil::IsEncoder(cardtype) || CardUtil::IsUnscanable(cardtype))
3357  {
3358  addChild(new ExternalChannelCommand(*this));
3359  if (CardUtil::HasTuner(cardtype, device))
3360  addChild(new PresetTuner(*this));
3361  }
3362  else
3363  {
3364  addChild(new QuickTune(*this));
3365  if ("DVB" == cardtype)
3366  addChild(new DishNetEIT(*this));
3367  }
3368 
3369  scan->setHelpText(
3370  tr("Use channel scanner to find channels for this input."));
3371 
3373  tr("This uses the listings data source to "
3374  "provide the channels for this input.") + " " +
3375  tr("This can take a long time to run."));
3376 
3377  addChild(scan);
3378  addChild(srcfetch);
3379 
3381 
3382  GroupSetting *interact = new GroupSetting();
3383 
3384  interact->setLabel(QObject::tr("Interactions between inputs"));
3385  if (CardUtil::IsTunerSharingCapable(cardtype))
3386  {
3388  interact->addChild(instancecount);
3389  schedgroup = new SchedGroup(*this);
3390  interact->addChild(schedgroup);
3391  }
3392  interact->addChild(new InputPriority(*this));
3393  interact->addChild(new ScheduleOrder(*this, _cardid));
3394  interact->addChild(new LiveTVOrder(*this, _cardid));
3395 
3396  ButtonStandardSetting *ingrpbtn =
3397  new ButtonStandardSetting(QObject::tr("Create a New Input Group"));
3398  ingrpbtn->setHelpText(
3399  QObject::tr("Input groups are only needed when two or more cards "
3400  "share the same resource such as a FireWire card and "
3401  "an analog card input controlling the same set top box."));
3402  interact->addChild(ingrpbtn);
3403  interact->addChild(inputgrp0);
3404  interact->addChild(inputgrp1);
3405 
3406  addChild(interact);
3407 
3408  setObjectName("CardInput");
3409  SetSourceID("-1");
3410 
3411  connect(scan, SIGNAL(clicked()), SLOT(channelScanner()));
3412  connect(srcfetch, SIGNAL(clicked()), SLOT(sourceFetch()));
3413  connect(sourceid, SIGNAL(valueChanged(const QString&)),
3414  startchan,SLOT( SetSourceID (const QString&)));
3415  connect(sourceid, SIGNAL(valueChanged(const QString&)),
3416  this, SLOT( SetSourceID (const QString&)));
3417  connect(ingrpbtn, SIGNAL(clicked()),
3418  this, SLOT( CreateNewInputGroup()));
3419  if (schedgroup)
3420  connect(instancecount, SIGNAL(valueChanged(const QString &)),
3421  this, SLOT(UpdateSchedGroup(const QString &)));
3422 }
3423 
3425 {
3427  {
3428  delete externalInputSettings;
3429  externalInputSettings = NULL;
3430  }
3431 }
3432 
3433 void CardInput::SetSourceID(const QString &sourceid)
3434 {
3435  uint cid = id->getValue().toUInt();
3436  QString raw_card_type = CardUtil::GetRawInputType(cid);
3437  bool enable = (sourceid.toInt() > 0);
3438  scan->setEnabled(enable && !raw_card_type.isEmpty() &&
3439  !CardUtil::IsUnscanable(raw_card_type));
3440  srcfetch->setEnabled(enable);
3441 }
3442 
3443 void CardInput::UpdateSchedGroup(const QString &val)
3444 {
3445  int value = val.toInt();
3446  if (value <= 1)
3447  schedgroup->setValue(false);
3448  schedgroup->setEnabled(value > 1);
3449 }
3450 
3451 QString CardInput::getSourceName(void) const
3452 {
3453  return sourceid->getValueLabel();
3454 }
3455 
3457 {
3458  inputgrp0->Save();
3459  inputgrp1->Save();
3460 
3461  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
3462  MythTextInputDialog *settingdialog =
3463  new MythTextInputDialog(popupStack, tr("Enter new group name"));
3464 
3465  if (settingdialog->Create())
3466  {
3467  connect(settingdialog, SIGNAL(haveResult(QString)),
3468  SLOT(CreateNewInputGroupSlot(const QString&)));
3469  popupStack->AddScreen(settingdialog);
3470  }
3471  else
3472  delete settingdialog;
3473 }
3474 
3476 {
3477  if (name.isEmpty())
3478  {
3479  ShowOkPopup(tr("Sorry, this Input Group name cannot be blank."));
3480  return;
3481  }
3482 
3483  QString new_name = QString("user:") + name;
3484 
3485  MSqlQuery query(MSqlQuery::InitCon());
3486  query.prepare("SELECT inputgroupname "
3487  "FROM inputgroup "
3488  "WHERE inputgroupname = :GROUPNAME");
3489  query.bindValue(":GROUPNAME", new_name);
3490 
3491  if (!query.exec())
3492  {
3493  MythDB::DBError("CreateNewInputGroup 1", query);
3494  return;
3495  }
3496 
3497  if (query.next())
3498  {
3499  ShowOkPopup(tr("Sorry, this Input Group name is already in use."));
3500  return;
3501  }
3502 
3503  uint inputgroupid = CardUtil::CreateInputGroup(new_name);
3504 
3505  inputgrp0->Load();
3506  inputgrp1->Load();
3507 
3508  if (!inputgrp0->getValue().toUInt())
3509  {
3511  inputgrp0->getValueIndex(QString::number(inputgroupid)));
3512  }
3513  else
3514  {
3516  inputgrp1->getValueIndex(QString::number(inputgroupid)));
3517  }
3518 }
3519 
3521 {
3522  uint srcid = sourceid->getValue().toUInt();
3523  uint crdid = id->getValue().toUInt();
3524  QString in = inputname->getValue();
3525 
3526 #ifdef USING_BACKEND
3527  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3528 
3529  Save(); // save info for scanner.
3530 
3531  QString cardtype = CardUtil::GetRawInputType(crdid);
3532  if (CardUtil::IsUnscanable(cardtype))
3533  {
3534  LOG(VB_GENERAL, LOG_ERR,
3535  QString("Sorry, %1 cards do not yet support scanning.")
3536  .arg(cardtype));
3537  return;
3538  }
3539 
3541  StandardSettingDialog *ssd =
3542  new StandardSettingDialog(mainStack, "generalsettings",
3543  new ScanWizard(srcid, crdid, in));
3544 
3545  if (ssd->Create())
3546  {
3547  connect(ssd, &StandardSettingDialog::Exiting,
3548  [=]()
3549  {
3550  if (SourceUtil::GetChannelCount(srcid))
3551  startchan->SetSourceID(QString::number(srcid));
3552  if (num_channels_before)
3553  {
3554  startchan->Load();
3555  startchan->Save();
3556  }
3557  });
3558  mainStack->AddScreen(ssd);
3559  }
3560  else
3561  delete ssd;
3562 
3563 #else
3564  LOG(VB_GENERAL, LOG_ERR, "You must compile the backend "
3565  "to be able to scan for channels");
3566 #endif
3567 }
3568 
3570 {
3571  uint srcid = sourceid->getValue().toUInt();
3572  uint crdid = id->getValue().toUInt();
3573 
3574  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3575 
3576  if (crdid && srcid)
3577  {
3578  Save(); // save info for fetch..
3579 
3580  QString cardtype = CardUtil::GetRawInputType(crdid);
3581 
3582  if (!CardUtil::IsCableCardPresent(crdid, cardtype) &&
3583  !CardUtil::IsUnscanable(cardtype) &&
3584  !CardUtil::IsEncoder(cardtype) &&
3585  !num_channels_before)
3586  {
3587  LOG(VB_GENERAL, LOG_ERR, "Skipping channel fetch, you need to "
3588  "scan for channels first.");
3589  return;
3590  }
3591 
3592  SourceUtil::UpdateChannelsFromListings(srcid, cardtype);
3593  }
3594 
3595  if (SourceUtil::GetChannelCount(srcid))
3596  startchan->SetSourceID(QString::number(srcid));
3597  if (num_channels_before)
3598  {
3599  startchan->Load();
3600  startchan->Save();
3601  }
3602 }
3603 
3605 {
3606  QString cardinputidTag(":WHERECARDID");
3607 
3608  QString query("cardid = " + cardinputidTag);
3609 
3610  bindings.insert(cardinputidTag, m_parent.getInputID());
3611 
3612  return query;
3613 }
3614 
3616 {
3617  QString cardinputidTag(":SETCARDID");
3618  QString colTag(":SET" + GetColumnName().toUpper());
3619 
3620  QString query("cardid = " + cardinputidTag + ", " +
3621  GetColumnName() + " = " + colTag);
3622 
3623  bindings.insert(cardinputidTag, m_parent.getInputID());
3624  bindings.insert(colTag, user->GetDBValue());
3625 
3626  return query;
3627 }
3628 
3629 void CardInput::loadByID(int inputid)
3630 {
3631  id->setValue(inputid);
3632  externalInputSettings->Load(inputid);
3634 }
3635 
3636 void CardInput::loadByInput(int _cardid, QString _inputname)
3637 {
3638  MSqlQuery query(MSqlQuery::InitCon());
3639  query.prepare("SELECT cardid FROM capturecard "
3640  "WHERE cardid = :CARDID AND inputname = :INPUTNAME");
3641  query.bindValue(":CARDID", _cardid);
3642  query.bindValue(":INPUTNAME", _inputname);
3643 
3644  if (query.exec() && query.isActive() && query.next())
3645  {
3646  loadByID(query.value(0).toInt());
3647  }
3648 }
3649 
3651 {
3652  uint cardid = id->getValue().toUInt();
3653  QString init_input = CardUtil::GetInputName(cardid);
3656 
3657  uint icount = 1;
3658  if (instancecount)
3659  icount = instancecount->getValue().toUInt();
3660  vector<uint> cardids = CardUtil::GetChildInputIDs(cardid);
3661 
3662  // Delete old clone cards as required.
3663  for (uint i = cardids.size() + 1;
3664  (i > icount) && !cardids.empty(); --i)
3665  {
3666  CardUtil::DeleteCard(cardids.back());
3667  cardids.pop_back();
3668  }
3669 
3670  // Clone this config to existing clone cards.
3671  for (uint i = 0; i < cardids.size(); ++i)
3672  {
3673  CardUtil::CloneCard(cardid, cardids[i]);
3674  }
3675 
3676  // Create new clone cards as required.
3677  for (uint i = cardids.size() + 1; i < icount; i++)
3678  {
3679  CardUtil::CloneCard(cardid, 0);
3680  }
3681 
3682  // Delete any unused input groups
3684 }
3685 
3687 {
3688  return m_parent.getInputID();
3689 }
3690 
3692 {
3693  return m_parent.getCardID();
3694 }
3695 
3697 {
3698  emit Clicked(m_value);
3699 }
3700 
3701 void CaptureCardEditor::AddSelection(const QString &label, const char *slot)
3702 {
3703  ButtonStandardSetting *button = new ButtonStandardSetting(label);
3704  connect(button, SIGNAL(clicked()), slot);
3705  addChild(button);
3706 }
3707 
3709 {
3710  ShowOkPopup(
3711  tr("Are you sure you want to delete "
3712  "ALL capture cards on %1?").arg(gCoreContext->GetHostName()),
3713  this,
3714  SLOT(DeleteAllCaptureCardsOnHost(bool)),
3715  true);
3716 }
3717 
3719 {
3720  ShowOkPopup(
3721  tr("Are you sure you want to delete "
3722  "ALL capture cards?"),
3723  this,
3724  SLOT(DeleteAllCaptureCards(bool)),
3725  true);
3726 }
3727 
3729 {
3730  CaptureCard *card = new CaptureCard();
3731  card->setLabel(tr("New capture card"));
3732  addChild(card);
3733  emit settingsChanged(this);
3734 }
3735 
3737 {
3738  if (!doDelete)
3739  return;
3740 
3742  Load();
3743  emit settingsChanged(this);
3744 }
3745 
3747 {
3748  if (!doDelete)
3749  return;
3750 
3751  MSqlQuery cards(MSqlQuery::InitCon());
3752 
3753  cards.prepare(
3754  "SELECT cardid "
3755  "FROM capturecard "
3756  "WHERE hostname = :HOSTNAME");
3757  cards.bindValue(":HOSTNAME", gCoreContext->GetHostName());
3758 
3759  if (!cards.exec() || !cards.isActive())
3760  {
3761  ShowOkPopup(
3762  tr("Error getting list of cards for this host. "
3763  "Unable to delete capturecards for %1")
3764  .arg(gCoreContext->GetHostName()));
3765 
3766  MythDB::DBError("Selecting cardids for deletion", cards);
3767  return;
3768  }
3769 
3770  while (cards.next())
3771  CardUtil::DeleteCard(cards.value(0).toUInt());
3772 
3773  Load();
3774  emit settingsChanged(this);
3775 }
3776 
3778 {
3779  setLabel(tr("Capture cards"));
3780 }
3781 
3783 {
3784  clearSettings();
3785  AddSelection(QObject::tr("(New capture card)"), SLOT(AddNewCard()));
3786  AddSelection(QObject::tr("(Delete all capture cards on %1)")
3787  .arg(gCoreContext->GetHostName()),
3788  SLOT(ShowDeleteAllCaptureCardsDialogOnHost()));
3789  AddSelection(QObject::tr("(Delete all capture cards)"),
3790  SLOT(ShowDeleteAllCaptureCardsDialog()));
3792 }
3793 
3795 {
3796  setLabel(tr("Video sources"));
3797 }
3798 
3800 {
3801  clearSettings();
3802  AddSelection(QObject::tr("(New video source)"), SLOT(NewSource()));
3803  AddSelection(QObject::tr("(Delete all video sources)"),
3804  SLOT(ShowDeleteAllSourcesDialog()));
3807 }
3808 
3809 void VideoSourceEditor::AddSelection(const QString &label, const char* slot)
3810 {
3811  ButtonStandardSetting *button = new ButtonStandardSetting(label);
3812  connect(button, SIGNAL(clicked()), slot);
3813  addChild(button);
3814 }
3815 
3817 {
3818  ShowOkPopup(
3819  tr("Are you sure you want to delete "
3820  "ALL video sources?"),
3821  this,
3822  SLOT(DeleteAllSources(bool)),
3823  true);
3824 }
3825 
3827 {
3828  if (!doDelete)
3829  return;
3830 
3832  Load();
3833  emit settingsChanged(this);
3834 }
3835 
3837 {
3838  VideoSource *source = new VideoSource();
3839  source->setLabel(tr("New video source"));
3840  source->Load();
3841  addChild(source);
3842  emit settingsChanged(this);
3843 }
3844 
3846 {
3847  setLabel(tr("Input connections"));
3848 }
3849 
3851 {
3852  cardinputs.clear();
3853  clearSettings();
3854 
3855  // We do this manually because we want custom labels. If
3856  // SelectSetting provided a facility to edit the labels, we
3857  // could use CaptureCard::fillSelections
3858 
3859  MSqlQuery query(MSqlQuery::InitCon());
3860  query.prepare(
3861  "SELECT cardid, videodevice, cardtype, inputname "
3862  "FROM capturecard "
3863  "WHERE hostname = :HOSTNAME "
3864  " AND parentid = 0 "
3865  "ORDER BY cardid");
3866  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
3867 
3868  if (!query.exec())
3869  {
3870  MythDB::DBError("CardInputEditor::load", query);
3871  return;
3872  }
3873 
3874  while (query.next())
3875  {
3876  uint cardid = query.value(0).toUInt();
3877  QString videodevice = query.value(1).toString();
3878  QString cardtype = query.value(2).toString();
3879  QString inputname = query.value(3).toString();
3880 
3881  CardInput *cardinput = new CardInput(cardtype, videodevice,
3882  true, cardid);
3883  cardinput->loadByID(cardid);
3884  QString inputlabel = QString("%1 (%2) -> %3")
3885  .arg(CardUtil::GetDeviceLabel(cardtype, videodevice))
3886  .arg(inputname).arg(cardinput->getSourceName());
3887  cardinputs.push_back(cardinput);
3888  cardinput->setLabel(inputlabel);
3889  addChild(cardinput);
3890  }
3891 
3893 }
3894 
3895 #ifdef USING_DVB
3896 static QString remove_chaff(const QString &name)
3897 {
3898  // Trim off some of the chaff.
3899  QString short_name = name;
3900  if (short_name.startsWith("LG Electronics"))
3901  short_name = short_name.right(short_name.length() - 15);
3902  if (short_name.startsWith("Oren"))
3903  short_name = short_name.right(short_name.length() - 5);
3904  if (short_name.startsWith("Nextwave"))
3905  short_name = short_name.right(short_name.length() - 9);
3906  if (short_name.startsWith("frontend", Qt::CaseInsensitive))
3907  short_name = short_name.left(short_name.length() - 9);
3908  if (short_name.endsWith("VSB/QAM"))
3909  short_name = short_name.left(short_name.length() - 8);
3910  if (short_name.endsWith("VSB"))
3911  short_name = short_name.left(short_name.length() - 4);
3912  if (short_name.endsWith("DVB-T"))
3913  short_name = short_name.left(short_name.length() - 6);
3914 
3915  // It would be infinitely better if DVB allowed us to query
3916  // the vendor ID. But instead we have to guess based on the
3917  // demodulator name. This means cards like the Air2PC HD5000
3918  // and DViCO Fusion HDTV cards are not identified correctly.
3919  short_name = short_name.simplified();
3920  if (short_name.startsWith("or51211", Qt::CaseInsensitive))
3921  short_name = "pcHDTV HD-2000";
3922  else if (short_name.startsWith("or51132", Qt::CaseInsensitive))
3923  short_name = "pcHDTV HD-3000";
3924  else if (short_name.startsWith("bcm3510", Qt::CaseInsensitive))
3925  short_name = "Air2PC v1";
3926  else if (short_name.startsWith("nxt2002", Qt::CaseInsensitive))
3927  short_name = "Air2PC v2";
3928  else if (short_name.startsWith("nxt200x", Qt::CaseInsensitive))
3929  short_name = "Air2PC v2";
3930  else if (short_name.startsWith("lgdt3302", Qt::CaseInsensitive))
3931  short_name = "DViCO HDTV3";
3932  else if (short_name.startsWith("lgdt3303", Qt::CaseInsensitive))
3933  short_name = "DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
3934 
3935  return short_name;
3936 }
3937 #endif // USING_DVB
3938 
3939 void DVBConfigurationGroup::reloadDiseqcTree(const QString &videodevice)
3940 {
3941  if (diseqc_tree)
3942  diseqc_tree->Load(videodevice);
3943 }
3944 
3945 void DVBConfigurationGroup::probeCard(const QString &videodevice)
3946 {
3947  if (videodevice.isEmpty())
3948  {
3949  cardname->setValue("");
3950  cardtype->setValue("");
3951  return;
3952  }
3953 
3954  if (parent.getCardID() && parent.GetRawCardType() != "DVB")
3955  {
3956  cardname->setValue("");
3957  cardtype->setValue("");
3958  return;
3959  }
3960 
3961 #ifdef USING_DVB
3962  QString frontend_name = CardUtil::ProbeDVBFrontendName(videodevice);
3963  QString subtype = CardUtil::ProbeDVBType(videodevice);
3964 
3965  QString err_open = tr("Could not open card %1").arg(videodevice);
3966  QString err_other = tr("Could not get card info for card %1").arg(videodevice);
3967 
3968  switch (CardUtil::toInputType(subtype))
3969  {
3970  case CardUtil::ERROR_OPEN:
3971  cardname->setValue(err_open);
3972  cardtype->setValue(strerror(errno));
3973  break;
3975  cardname->setValue(err_other);
3976  cardtype->setValue("Unknown error");
3977  break;
3978  case CardUtil::ERROR_PROBE:
3979  cardname->setValue(err_other);
3980  cardtype->setValue(strerror(errno));
3981  break;
3982  case CardUtil::QPSK:
3983  cardtype->setValue("DVB-S");
3984  cardname->setValue(frontend_name);
3985  signal_timeout->setValue(7000);
3986  channel_timeout->setValue(10000);
3987  break;
3988  case CardUtil::DVBS2:
3989  cardtype->setValue("DVB-S2");
3990  cardname->setValue(frontend_name);
3991  signal_timeout->setValue(7000);
3992  channel_timeout->setValue(10000);
3993  break;
3994  case CardUtil::QAM:
3995  cardtype->setValue("DVB-C");
3996  cardname->setValue(frontend_name);
3997  signal_timeout->setValue(1000);
3998  channel_timeout->setValue(3000);
3999  break;
4000  case CardUtil::DVBT2:
4001  cardtype->setValue("DVB-T2");
4002  cardname->setValue(frontend_name);
4003  signal_timeout->setValue(1000);
4004  channel_timeout->setValue(3000);
4005  break;
4006  case CardUtil::OFDM:
4007  {
4008  cardtype->setValue("DVB-T");
4009  cardname->setValue(frontend_name);
4010  signal_timeout->setValue(1000);
4011  channel_timeout->setValue(3000);
4012  if (frontend_name.toLower().indexOf("usb") >= 0)
4013  {
4014  signal_timeout->setValue(40000);
4015  channel_timeout->setValue(42500);
4016  }
4017 
4018  // slow down tuning for buggy drivers
4019  if ((frontend_name == "DiBcom 3000P/M-C DVB-T") ||
4020  (frontend_name ==
4021  "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
4022  {
4023  tuning_delay->setValue(200);
4024  }
4025 
4026 #if 0 // frontends on hybrid DVB-T/Analog cards
4027  QString short_name = remove_chaff(frontend_name);
4028  buttonAnalog->setVisible(
4029  short_name.startsWith("zarlink zl10353",
4030  Qt::CaseInsensitive) ||
4031  short_name.startsWith("wintv hvr 900 m/r: 65008/a1c0",
4032  Qt::CaseInsensitive) ||
4033  short_name.startsWith("philips tda10046h",
4034  Qt::CaseInsensitive));
4035 #endif
4036  }
4037  break;
4038  case CardUtil::ATSC:
4039  {
4040  QString short_name = remove_chaff(frontend_name);
4041  cardtype->setValue("ATSC");
4042  cardname->setValue(short_name);
4043  signal_timeout->setValue(500);
4044  channel_timeout->setValue(3000);
4045 
4046  // According to #1779 and #1935 the AverMedia 180 needs
4047  // a 3000 ms signal timeout, at least for QAM tuning.
4048  if (frontend_name == "Nextwave NXT200X VSB/QAM frontend")
4049  {
4050  signal_timeout->setValue(3000);
4051  channel_timeout->setValue(5500);
4052  }
4053 
4054 #if 0 // frontends on hybrid DVB-T/Analog cards
4055  if (frontend_name.toLower().indexOf("usb") < 0)
4056  {
4057  buttonAnalog->setVisible(
4058  short_name.startsWith("pchdtv", Qt::CaseInsensitive) ||
4059  short_name.startsWith("dvico", Qt::CaseInsensitive) ||
4060  short_name.startsWith("nextwave", Qt::CaseInsensitive));
4061  }
4062 #endif
4063  }
4064  break;
4065  default:
4066  break;
4067  }
4068 #else
4069  cardtype->setValue(QString("Recompile with DVB-Support!"));
4070 #endif
4071 }
4072 
4074  QString dev, QString type) :
4075  CaptureCardComboBoxSetting(parent, false, "audiodevice"),
4076  last_device(dev), last_cardtype(type)
4077 {
4078  setLabel(QObject::tr("Audio input"));
4079  setHelpText(QObject::tr("If there is more than one audio input, "
4080  "select which one to use."));
4081  int cardid = parent.getCardID();
4082  if (cardid <= 0)
4083  return;
4084 
4087 }
4088 
4089 int TunerCardAudioInput::fillSelections(const QString &device)
4090 {
4091  clearSelections();
4092 
4093  if (device.isEmpty())
4094  return 0;
4095 
4096  last_device = device;
4097  QStringList inputs =
4099 
4100  for (uint i = 0; i < (uint)inputs.size(); i++)
4101  {
4102  addSelection(inputs[i], QString::number(i),
4103  last_device == QString::number(i));
4104  }
4105  return inputs.size();
4106 }
4107 
4109  CardType& cardType) :
4110  parent(a_parent),
4111  diseqc_tree(new DiSEqCDevTree())
4112 {
4113  setVisible(false);
4114 
4115  cardnum = new DVBCardNum(parent);
4116  cardname = new DVBCardName();
4117  cardtype = new DVBCardType();
4118 
4119  signal_timeout = new SignalTimeout(parent, 500, 250);
4120  channel_timeout = new ChannelTimeout(parent, 3000, 1750);
4121 
4122  cardType.addTargetedChild("DVB", cardnum);
4123 
4124  cardType.addTargetedChild("DVB", cardname);
4125  cardType.addTargetedChild("DVB", cardtype);
4126 
4127  cardType.addTargetedChild("DVB", signal_timeout);
4128  cardType.addTargetedChild("DVB", channel_timeout);
4129 
4130  cardType.addTargetedChild("DVB", new EmptyAudioDevice(parent));
4131  cardType.addTargetedChild("DVB", new EmptyVBIDevice(parent));
4132 
4133  cardType.addTargetedChild("DVB", new DVBNoSeqStart(parent));
4134  cardType.addTargetedChild("DVB", new DVBOnDemand(parent));
4135  cardType.addTargetedChild("DVB", new DVBEITScan(parent));
4136 
4138  diseqc_btn->setLabel(tr("DiSEqC (Switch, LNB, and Rotor Configuration)"));
4139  diseqc_btn->setHelpText(tr("Input and satellite settings."));
4140  diseqc_btn->setVisible(false);
4141 
4143  cardType.addTargetedChild("DVB", tuning_delay);
4144  cardType.addTargetedChild("DVB", diseqc_btn);
4145  tuning_delay->setVisible(false);
4146 
4147  connect(cardnum, SIGNAL(valueChanged(const QString&)),
4148  this, SLOT( probeCard (const QString&)));
4149  connect(cardnum, SIGNAL(valueChanged(const QString&)),
4150  this, SLOT( reloadDiseqcTree(const QString&)));
4151 }
4152 
4154 {
4155  if (diseqc_tree)
4156  {
4157  delete diseqc_tree;
4158  diseqc_tree = NULL;
4159  }
4160 }
4161 
4163 {
4165  diseqc_btn->Load();
4167  if (cardtype->getValue() == "DVB-S" ||
4168  cardtype->getValue() == "DVB-S2" ||
4170  {
4171  diseqc_btn->setVisible(true);
4172  }
4173 }
4174 
4176 {
4179  DiSEqCDev trees;
4180  trees.InvalidateTrees();
4181 }
4182 
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:794
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:380
virtual void setEnabled(bool e)
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:893
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:1078
void fillSelections()
virtual void Load(void)
QString Card(void) const
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:83
allow access to stdout
Definition: mythsystem.h:39
virtual void Save(void)
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)
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:1243
void probeCard(const QString &device)
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:489
void SetSourceID(const QString &sourceid)
CaptureCardSpinBoxSetting(const CaptureCard &parent, uint min_val, uint max_val, uint step, const QString &setting)
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:1827
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:539
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:1507
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)
__u32 index
Definition: videodev2.h:1039
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
void probeApp(const QString &path)
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
bool Store(uint cardid, const QString &device="")
Stores the device tree to the database.
Definition: diseqc.cpp:434
virtual void Save(void)
__u32 type
Definition: videodev2.h:1038
virtual void Load(void)
void SetOldValue(const QString &s)
Definition: videosource.h: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:1554
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:212
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:2224
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:1730
struct CHANLISTS chanlists[]
const char * name
Definition: ParseText.cpp:338
void loadByInput(int cardid, QString input)
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)
int errno
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:2110
static bool IsCableCardPresent(uint inputid, const QString &inputType)
Definition: cardutil.cpp:116
static uint GetDeviceInputGroup(uint inputid)
Definition: cardutil.cpp:1297
TransFreqTableSelector(uint _sourceid)
void UpdateDevices(const QString &)
V4LConfigurationGroup(CaptureCard &parent, CardType &cardtype)
__u64 val
Definition: videodev2.h:1041
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:738
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1361
virtual void Load(void)
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
static QString GetModelName(uint vendorid, uint modelid)
void LoadValue(const QString &)
uint vendorid
Definition: avcinfo.h:43
QString _overridedeviceid
Definition: videosource.h:1065
virtual void Load(void)
AVCInfo GetAVCInfo(const QString &guid) const
SignalTimeout * signal_timeout
Definition: videosource.h:629
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:2296
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:915
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
VERBOSE_PREAMBLE Most Errors or other very important messages true
Definition: verbosedefs.h:91
void UpdateDevices(const QString &)
DiSEqCDevTree * diseqc_tree
Definition: videosource.h:635
Dialog prompting the user to enter a text string.
__u32 id
Definition: videodev2.h:1038
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:819
QString tunerno
Definition: videosource.h:430
struct v4l2_dbg_match match
Definition: videodev2.h:1038
DataDirectPassword(const VideoSource &parent)
SkipBtAudio(const CaptureCard &parent)
CardInput(const QString &cardtype, const QString &device, bool is_new_input, int cardid)
VideoDevice * device
Definition: videosource.h: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
static bool Exists(int id)
Check if a Diseqc device tree exists.
Definition: diseqc.cpp:406
QString GetListingsProviderName(void) const
Definition: datadirect.h:351
TransTextEditSetting * info
Definition: videosource.h:596
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:256
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
void probeCard(const QString &device)
void DeleteAllCaptureCards(bool)
virtual void Load(void)
VBIDevice(const CaptureCard &parent)
static bool DeleteCard(uint inputid)
Definition: cardutil.cpp:1959
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:619
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:1321
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)
ExternalConfigurationGroup(CaptureCard &parent, CardType &cardtype)
virtual void Save()
static bool DeleteAllCards(void)
Definition: cardutil.cpp:2035
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)
__s32 value
Definition: videodev2.h:1042
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:2167
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:1285
static QString GetStartingChannel(uint inputid)
Definition: cardutil.cpp:1085
QString mythdeviceid
Definition: videosource.h:426
int getInputID(void) const
Definition: videosource.h:842
Main DVB-S device interface.
Definition: diseqc.h:52
static void GetDeviceInputNames(uint inputid, const QString &device, const QString &inputtype, QStringList &inputs)
Definition: cardutil.cpp:1850
virtual void Load(void)
FreqTableSelector(const VideoSource &parent)
void valueChanged(const QString &)
virtual void Load(void)
virtual bool canDelete(void)
void loadByID(int id)