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