MythTV  master
cardutil.cpp
Go to the documentation of this file.
1 // Standard UNIX C headers
2 #include <fcntl.h>
3 #include <unistd.h>
4 
5 #include <algorithm>
6 
7 #if defined(USING_V4L2) || defined(USING_DVB)
8 #include <sys/ioctl.h>
9 #endif
10 
11 // Qt headers
12 #include <QMap>
13 #include <QDir>
14 
15 // MythTV headers
16 #include "mythconfig.h"
17 #include "cardutil.h"
18 #include "videosource.h"
19 #include "dvbchannel.h"
20 #include "diseqcsettings.h"
21 #include "sourceutil.h"
22 #include "mythdb.h"
23 #include "mythlogging.h"
24 #include "inputinfo.h"
25 #include "mythmiscutil.h" // for ping()
26 #include "mythdownloadmanager.h"
27 
28 #ifdef USING_DVB
29 #include "dvbtypes.h"
30 #endif
31 
32 #ifdef USING_V4L1
33 #include <linux/videodev.h>
34 #endif
35 
36 #ifdef USING_V4L2
37 #include "v4l2util.h"
38 #endif
39 
40 #ifdef USING_HDHOMERUN
41 #include HDHOMERUN_HEADERFILE
42 #endif
43 
44 #ifdef USING_VBOX
45 #include "vboxutils.h"
46 #include "mythmiscutil.h"
47 #endif
48 
49 #ifdef USING_SATIP
50 #include "satiputils.h"
51 #endif
52 
53 #ifdef USING_ASI
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 #include <dveo/asi.h>
57 #include <dveo/master.h>
58 #endif
59 
60 #define LOC QString("CardUtil: ")
61 
63 {
64  QString inputTypes = "";
65 
66 #ifdef USING_DVB
67  inputTypes += "'DVB'";
68 #endif // USING_DVB
69 
70 #ifdef USING_V4L2
71  if (!inputTypes.isEmpty())
72  inputTypes += ",";
73  inputTypes += "'V4L'";
74 # ifdef USING_IVTV
75  inputTypes += ",'MPEG'";
76 # endif // USING_IVTV
77 #endif // USING_V4L2
78 
79 #ifdef USING_IPTV
80  if (!inputTypes.isEmpty())
81  inputTypes += ",";
82  inputTypes += "'FREEBOX'";
83 #endif // USING_IPTV
84 
85 #ifdef USING_VBOX
86  if (!inputTypes.isEmpty())
87  inputTypes += ",";
88  inputTypes += "'VBOX'";
89 #endif // USING_VBOX
90 
91 #ifdef USING_HDHOMERUN
92  if (!inputTypes.isEmpty())
93  inputTypes += ",";
94  inputTypes += "'HDHOMERUN'";
95 #endif // USING_HDHOMERUN
96 
97 #ifdef USING_SATIP
98  if (!inputTypes.isEmpty())
99  inputTypes += ",";
100  inputTypes += "'SATIP'";
101 #endif // USING_SATIP
102 
103 #ifdef USING_ASI
104  if (!inputTypes.isEmpty())
105  inputTypes += ",";
106  inputTypes += "'ASI'";
107 #endif
108 
109 #ifdef USING_CETON
110  if (!inputTypes.isEmpty())
111  inputTypes += ",";
112  inputTypes += "'CETON'";
113 #endif // USING_CETON
114 
115 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
116  if (!inputTypes.isEmpty())
117  inputTypes += ",";
118  inputTypes += "'EXTERNAL'";
119 #endif
120 
121  if (inputTypes.isEmpty())
122  inputTypes = "'DUMMY'";
123 
124  return QString("(%1)").arg(inputTypes);
125 }
126 
128  const QString &inputType)
129 {
130 #if (!USING_HDHOMERUN && !USING_CETON)
131  Q_UNUSED(inputid);
132 #endif
133 
134  if (inputType == "HDHOMERUN")
135  {
136 #ifdef USING_HDHOMERUN
137  hdhomerun_tuner_status_t status {};
138  QString device = GetVideoDevice(inputid);
139  hdhomerun_device_t *hdhr =
140  hdhomerun_device_create_from_str(device.toLatin1(), nullptr);
141  if (!hdhr)
142  return false;
143 
144  int oob = hdhomerun_device_get_oob_status(hdhr, nullptr, &status);
145 
146  // if no OOB tuner, oob will be < 1. If no CC present, OOB
147  // status will be "none."
148  if (oob > 0 && (strncmp(status.channel, "none", 4) != 0))
149  {
150  LOG(VB_GENERAL, LOG_INFO, "Cardutil: HDHomeRun Cablecard Present.");
151  hdhomerun_device_destroy(hdhr);
152  return true;
153  }
154 
155  hdhomerun_device_destroy(hdhr);
156 
157 #endif
158  return false;
159  }
160  if (inputType == "CETON")
161  {
162 #ifdef USING_CETON
163  QString device = GetVideoDevice(inputid);
164 
165  QStringList parts = device.split("-");
166  if (parts.size() != 2)
167  {
168  LOG(VB_GENERAL, LOG_ERR,
169  QString("CardUtil: Ceton invalid device id %1").arg(device));
170  return false;
171  }
172 
173  const QString& ip_address = parts.at(0);
174 
175  QStringList tuner_parts = parts.at(1).split(".");
176  if (tuner_parts.size() != 2)
177  {
178  LOG(VB_GENERAL, LOG_ERR, LOC +
179  QString("CardUtil: Ceton invalid device id %1").arg(device));
180  return false;
181  }
182 
183  uint tuner = tuner_parts.at(1).toUInt();
184 
185  QUrlQuery params;
186  params.addQueryItem("i", QString::number(tuner));
187  params.addQueryItem("s", "cas");
188  params.addQueryItem("v", "CardStatus");
189 
190  QUrl url;
191  url.setScheme("http");
192  url.setHost(ip_address);
193  url.setPath("/get_var.json");
194  url.setQuery(params);
195 
196  auto *request = new QNetworkRequest();
197  request->setAttribute(QNetworkRequest::CacheLoadControlAttribute,
198  QNetworkRequest::AlwaysNetwork);
199  request->setUrl(url);
200 
201  QByteArray data;
203 
204  if (!manager->download(request, &data))
205  {
206  LOG(VB_GENERAL, LOG_ERR,
207  QString("CardUtil: Ceton http request failed %1").arg(device));
208  return false;
209  }
210 
211  QString response = QString(data);
212 
213  QRegExp regex("^\\{ \"?result\"?: \"(.*)\" \\}$");
214  if (regex.indexIn(response) == -1)
215  {
216  LOG(VB_GENERAL, LOG_ERR,
217  QString("CardUtil: Ceton unexpected http response: %1").arg(response));
218  return false;
219  }
220 
221  QString result = regex.cap(1);
222 
223  if (result == "Inserted")
224  {
225  LOG(VB_GENERAL, LOG_DEBUG, "Cardutil: Ceton CableCARD present.");
226  return true;
227  }
228 
229  LOG(VB_GENERAL, LOG_DEBUG, "Cardutil: Ceton CableCARD not present.");
230  return false;
231 #else
232  return false;
233 #endif
234  }
235  return false;
236 }
237 
238 bool CardUtil::HasTuner(const QString &rawtype, const QString & device)
239 {
240  if (rawtype == "DVB" || rawtype == "HDHOMERUN" ||
241  rawtype == "FREEBOX" || rawtype == "CETON" ||
242  rawtype == "VBOX" || rawtype == "SATIP")
243  return true;
244 
245 #ifdef USING_V4L2
246  if (rawtype == "V4L2ENC")
247  {
248  V4L2util v4l2(device);
249  return !v4l2 ? false : v4l2.HasTuner();
250  }
251 #else
252  Q_UNUSED(device);
253 #endif
254 
255  if (rawtype == "EXTERNAL")
256  {
257  // TODO: query EXTERNAL for capability
258  return true;
259  }
260 
261  return false;
262 }
263 
264 bool CardUtil::IsTunerShared(uint inputidA, uint inputidB)
265 {
266  LOG(VB_GENERAL, LOG_DEBUG, QString("IsTunerShared(%1,%2)")
267  .arg(inputidA).arg(inputidB));
268 
270  query.prepare("SELECT videodevice, hostname, cardtype "
271  "FROM capturecard "
272  "WHERE ( (cardid = :INPUTID_A) OR "
273  " (cardid = :INPUTID_B) )");
274  query.bindValue(":INPUTID_A", inputidA);
275  query.bindValue(":INPUTID_B", inputidB);
276 
277  if (!query.exec())
278  {
279  MythDB::DBError("CardUtil::is_tuner_shared()", query);
280  return false;
281  }
282 
283  if (!query.next())
284  return false;
285 
286  const QString vdevice = query.value(0).toString();
287  const QString hostname = query.value(1).toString();
288  const QString inputtype = query.value(2).toString();
289 
290  if (!IsTunerSharingCapable(inputtype.toUpper()))
291  return false;
292 
293  if (!query.next())
294  return false;
295 
296  bool ret = ((vdevice == query.value(0).toString()) &&
297  (hostname == query.value(1).toString()) &&
298  (inputtype == query.value(2).toString()));
299 
300  LOG(VB_RECORD, LOG_DEBUG, QString("IsTunerShared(%1,%2) -> %3")
301  .arg(inputidA).arg(inputidB).arg(ret));
302 
303  return ret;
304 }
305 
311 bool CardUtil::IsInputTypePresent(const QString &rawtype, QString hostname)
312 {
313  if (hostname.isEmpty())
315 
317  QString qstr =
318  "SELECT count(cardtype) "
319  "FROM capturecard "
320  "WHERE capturecard.hostname = :HOSTNAME ";
321 
322  if (!rawtype.isEmpty())
323  qstr += " AND capturecard.cardtype = :INPUTTYPE";
324 
325  query.prepare(qstr);
326 
327  if (!rawtype.isEmpty())
328  query.bindValue(":INPUTTYPE", rawtype.toUpper());
329 
330  query.bindValue(":HOSTNAME", hostname);
331 
332  if (!query.exec())
333  {
334  MythDB::DBError("CardUtil::IsInputTypePresent()", query);
335  return false;
336  }
337 
338  uint count = 0;
339  if (query.next())
340  count = query.value(0).toUInt();
341 
342  return count > 0;
343 }
344 
346 {
347  InputTypes inputtypes;
348 
350  query.prepare("SELECT DISTINCT cardtype, videodevice "
351  "FROM capturecard");
352 
353  if (!query.exec())
354  {
355  MythDB::DBError("CardUtil::GetInputTypes()", query);
356  }
357  else
358  {
359  QString cardtype;
360 
361  while (query.next())
362  {
363  cardtype = query.value(0).toString();
364  if (cardtype != "V4L2ENC")
365  {
366  inputtypes[cardtype] = "";
367  }
368 #ifdef USING_V4L2
369  else
370  {
371  V4L2util v4l2(query.value(1).toString());
372  if (v4l2.IsOpen())
373  {
374  QString driver_name = "V4L2:" + v4l2.DriverName();
375  inputtypes[driver_name] = v4l2.CardName();
376  }
377  }
378 #endif
379  }
380  }
381 
382  return inputtypes;
383 }
384 
392 QStringList CardUtil::GetInputTypeNames(uint sourceid)
393 {
395  query.prepare("SELECT cardtype "
396  "FROM capturecard "
397  "WHERE capturecard.sourceid = :SOURCEID "
398  "GROUP BY cardtype");
399  query.bindValue(":SOURCEID", sourceid);
400 
401  QStringList list;
402  if (!query.exec())
403  {
404  MythDB::DBError("CardUtil::GetInputTypes", query);
405  return list;
406  }
407  while (query.next())
408  list.push_back(query.value(0).toString());
409  return list;
410 }
411 
412 
413 
414 
420 QStringList CardUtil::GetVideoDevices(const QString &rawtype, QString hostname)
421 {
422  QStringList list;
423 
424  if (hostname.isEmpty())
426 
428  QString qstr =
429  "SELECT videodevice "
430  "FROM capturecard "
431  "WHERE hostname = :HOSTNAME";
432 
433  if (!rawtype.isEmpty())
434  qstr += " AND cardtype = :INPUTTYPE";
435 
436  query.prepare(qstr);
437 
438  if (!rawtype.isEmpty())
439  query.bindValue(":INPUTTYPE", rawtype.toUpper());
440 
441  query.bindValue(":HOSTNAME", hostname);
442 
443  if (!query.exec())
444  {
445  MythDB::DBError("CardUtil::GetVideoDevices", query);
446  return list;
447  }
448 
449  QMap<QString,bool> dup;
450  while (query.next())
451  {
452  QString videodevice = query.value(0).toString();
453  if (dup[videodevice])
454  continue;
455 
456  list.push_back(videodevice);
457  dup[videodevice] = true;
458  }
459 
460  return list;
461 }
462 
463 QMap <QString,QStringList> CardUtil::s_videoDeviceCache;
464 
466 {
467  s_videoDeviceCache.clear();
468 }
469 
470 
471 QStringList CardUtil::ProbeVideoDevices(const QString &rawtype)
472 {
473  if (s_videoDeviceCache.contains(rawtype))
474  return s_videoDeviceCache[rawtype];
475 
476  QStringList devs;
477 
478  if (rawtype.toUpper() == "DVB")
479  {
480  QDir dir("/dev/dvb", "adapter*", QDir::Name, QDir::Dirs);
481  for (const auto & it : dir.entryInfoList())
482  {
483  QDir subdir(it.filePath(), "frontend*", QDir::Name, QDir::Files | QDir::System);
484  const QFileInfoList subil = subdir.entryInfoList();
485  if (subil.isEmpty())
486  continue;
487 
488  for (const auto & subit : qAsConst(subil))
489  devs.push_back(subit.filePath());
490  }
491  }
492  else if (rawtype.toUpper() == "ASI")
493  {
494  QDir dir("/dev/", "asirx*", QDir::Name, QDir::System);
495  for (const auto & it : dir.entryInfoList())
496  {
497  if (GetASIDeviceNumber(it.filePath()) >= 0)
498  {
499  devs.push_back(it.filePath());
500  continue;
501  }
502  break;
503  }
504  }
505 #ifdef USING_HDHOMERUN
506  else if (rawtype.toUpper() == "HDHOMERUN")
507  {
508  uint32_t target_ip = 0;
509  uint32_t device_type = HDHOMERUN_DEVICE_TYPE_TUNER;
510  uint32_t device_id = HDHOMERUN_DEVICE_ID_WILDCARD;
511  const int max_count = 50;
512  hdhomerun_discover_device_t result_list[max_count];
513 
514 #ifdef HDHOMERUN_V2
515  int result = hdhomerun_discover_find_devices_custom_v2(
516  target_ip, device_type, device_id, result_list, max_count);
517 #else
518  int result = hdhomerun_discover_find_devices_custom(
519  target_ip, device_type, device_id, result_list, max_count);
520 #endif
521 
522  if (result == -1)
523  {
524  LOG(VB_GENERAL, LOG_ERR, "Error finding HDHomerun devices");
525  }
526 
527  if (result >= max_count)
528  {
529  LOG(VB_GENERAL, LOG_WARNING,
530  "Warning: may be > 50 HDHomerun devices");
531  }
532 
533  // Return "deviceid ipaddress" pairs
534  for (int i = 0; i < result; i++)
535  {
536  QString id = QString("%1").arg(result_list[i].device_id, 0, 16);
537  QString ip = QString("%1.%2.%3.%4")
538  .arg((result_list[i].ip_addr>>24) & 0xFF)
539  .arg((result_list[i].ip_addr>>16) & 0xFF)
540  .arg((result_list[i].ip_addr>> 8) & 0xFF)
541  .arg((result_list[i].ip_addr>> 0) & 0xFF);
542 
543  QString model = "";
544  hdhomerun_device_t *device = hdhomerun_device_create(
545  result_list[i].device_id, 0, 0, nullptr);
546  if (device)
547  {
548  model = hdhomerun_device_get_model_str(device);
549  hdhomerun_device_destroy(device);
550  }
551 
552  QString hdhrdev = id.toUpper() + " " + ip + " " + model;
553  devs.push_back(hdhrdev);
554  }
555  }
556 #endif // USING_HDHOMERUN
557 #ifdef USING_SATIP
558  else if (rawtype.toUpper() == "SATIP")
559  {
560  devs = SatIP::probeDevices();
561  }
562 #endif // USING_SATIP
563 #ifdef USING_VBOX
564  else if (rawtype.toUpper() == "VBOX")
565  {
566  devs = VBox::probeDevices();
567  }
568 #endif // USING_VBOX
569 #ifdef USING_CETON
570  else if (rawtype.toUpper() == "CETON")
571  {
572  // TODO implement CETON probing.
573  LOG(VB_GENERAL, LOG_INFO, "CardUtil::ProbeVideoDevices: "
574  "TODO Probe Ceton devices");
575  }
576 #endif // USING_CETON
577  else
578  {
579  LOG(VB_GENERAL, LOG_ERR, QString("Raw Type: '%1' is not supported")
580  .arg(rawtype));
581  }
582 
583  s_videoDeviceCache.insert(rawtype,devs);
584  return devs;
585 }
586 
587 // Get the list of delivery systems from the card
588 QStringList CardUtil::ProbeDeliverySystems(const QString &device)
589 {
590  QStringList delsyslist;
591 
592 #ifdef USING_DVB
593  int fd_frontend = OpenVideoDevice(device);
594  if (fd_frontend < 0)
595  {
596  return delsyslist;
597  }
598 
599  struct dtv_property prop = {};
600  struct dtv_properties cmd = {};
601 
602  prop.cmd = DTV_API_VERSION;
603  cmd.num = 1;
604  cmd.props = &prop;
605  if (ioctl(fd_frontend, FE_GET_PROPERTY, &cmd) == 0)
606  {
607  LOG(VB_GENERAL, LOG_INFO,
608  QString("CardUtil(%1): ").arg(device) +
609  QString("dvb api version %1.%2").arg((prop.u.data>>8)&0xff).arg((prop.u.data)&0xff));
610  }
611  else
612  {
613  LOG(VB_GENERAL, LOG_ERR,
614  QString("CardUtil(%1) FE_GET_PROPERTY ioctl failed").arg(device) + ENO);
615  close(fd_frontend);
616  return delsyslist;
617  }
618 
619  delsyslist = ProbeDeliverySystems(fd_frontend);
620 
621  QString msg = "Delivery systems:";
622  for (const auto & item : qAsConst(delsyslist))
623  {
624  msg += " ";
625  msg += item;
626  }
627  LOG(VB_GENERAL, LOG_INFO, QString("CardUtil(%1): ").arg(device) + msg);
628 
629  close(fd_frontend);
630 #else
631  Q_UNUSED(device);
632 #endif // USING_DVB
633 
634  return delsyslist;
635 }
636 
637 // Get the list of all supported delivery systems from the card
638 QStringList CardUtil::ProbeDeliverySystems(int fd_frontend)
639 {
640  QStringList delsyslist;
641 
642 #ifdef USING_DVB
643  struct dtv_property prop = {};
644  struct dtv_properties cmd = {};
645 
646  prop.cmd = DTV_ENUM_DELSYS;
647  cmd.num = 1;
648  cmd.props = &prop;
649  if (ioctl(fd_frontend, FE_GET_PROPERTY, &cmd) == 0)
650  {
651  for (unsigned int i = 0; i < prop.u.buffer.len; i++)
652  {
653  delsyslist.push_back(DTVModulationSystem::toString(prop.u.buffer.data[i]));
654  }
655  }
656  else
657  {
658  LOG(VB_GENERAL, LOG_ERR, LOC + "FE_GET_PROPERTY ioctl failed " + ENO);
659  }
660 #else
661  Q_UNUSED(fd_frontend);
662 #endif // USING_DVB
663 
664  return delsyslist;
665 }
666 
667 QString CardUtil::ProbeDefaultDeliverySystem(const QString &device)
668 {
669  DTVModulationSystem delsys;
670 
671 #ifdef USING_DVB
672  int fd = OpenVideoDevice(device);
673  if (fd >= 0)
674  {
675  delsys = ProbeBestDeliverySystem(fd);
676  close(fd);
677  }
678 #else
679  Q_UNUSED(device);
680 #endif // USING_DVB
681 
682  return delsys.toString();
683 }
684 
685 QString CardUtil::ProbeDVBType(const QString &device)
686 {
687  QString ret = "ERROR_UNKNOWN";
688 
689  if (device.isEmpty())
690  return ret;
691 
692 #ifdef USING_DVB
693  DTVTunerType type = ProbeTunerType(device);
694  ret = (type.toString() != "UNKNOWN") ? type.toString().toUpper() : ret;
695 
696  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("(%1) tuner type:%2 %3")
697  .arg(device).arg(type).arg(ret));
698 #endif // USING_DVB
699 
700  return ret;
701 }
702 
706 QString CardUtil::ProbeDVBFrontendName(const QString &device)
707 {
708  QString ret = "ERROR_UNKNOWN";
709 
710 #ifdef USING_DVB
711  QString dvbdev = CardUtil::GetDeviceName(DVB_DEV_FRONTEND, device);
712  QByteArray dev = dvbdev.toLatin1();
713  int fd_frontend = open(dev.constData(), O_RDWR | O_NONBLOCK);
714  if (fd_frontend < 0)
715  return "ERROR_OPEN";
716 
717  struct dvb_frontend_info info {};
718  int err = ioctl(fd_frontend, FE_GET_INFO, &info);
719  if (err < 0)
720  {
721  close(fd_frontend);
722  return "ERROR_PROBE";
723  }
724 
725  ret = info.name;
726 
727  close(fd_frontend);
728 #else
729  Q_UNUSED(device);
730 #endif // USING_DVB
731 
732  return ret;
733 }
734 
752 bool CardUtil::HasDVBCRCBug(const QString &device)
753 {
754  QString name = ProbeDVBFrontendName(device);
755  return ((name == "VLSI VES1x93 DVB-S") || // munges PMT
756  (name == "ST STV0299 DVB-S")); // munges PAT
757 }
758 
760 {
761  QString name = ProbeDVBFrontendName(device);
762  if (name.indexOf("DVB-S") >= 0)
763  return 300;
764  if (name == "DiBcom 3000P/M-C DVB-T")
765  return 100;
766  return 25;
767 }
768 
770 {
771  DTVTunerType tunertype;
772 
773  switch (delsys)
774  {
776  tunertype = DTVTunerType::kTunerTypeDVBS1;
777  break;
779  tunertype = DTVTunerType::kTunerTypeDVBS2;
780  break;
784  tunertype = DTVTunerType::kTunerTypeDVBC;
785  break;
787  tunertype = DTVTunerType::kTunerTypeDVBT;
788  break;
790  tunertype = DTVTunerType::kTunerTypeDVBT2;
791  break;
793  tunertype = DTVTunerType::kTunerTypeATSC;
794  break;
797  break;
798  default:
799  LOG(VB_GENERAL, LOG_ERR, LOC +
800  QString("TODO Add to switch case delivery system:%2 %3")
801  .arg(delsys).arg(delsys.toString()));
802  break;
803  }
804 
805  return tunertype;
806 }
807 
808 // Get the currently configured tuner type from the database
810 {
811  DTVModulationSystem delsys = GetDeliverySystem(inputid);
812  DTVTunerType tunertype = ConvertToTunerType(delsys);
813  return tunertype;
814 }
815 
816 // Get the currently configured tuner type from the device
818 {
819  DTVModulationSystem delsys = ProbeCurrentDeliverySystem(fd_frontend);
820  DTVTunerType tunertype = ConvertToTunerType(delsys);
821  return tunertype;
822 }
823 
824 // Get the currently configured tuner type from the device
826 {
828  DTVTunerType tunertype = ConvertToTunerType(delsys);
829  return tunertype;
830 }
831 
832 // Get the tuner type from the multiplex
834 {
835  DTVTunerType tuner_type;
836 
838  query.prepare(
839  "SELECT mod_sys "
840  "FROM dtv_multiplex "
841  "WHERE dtv_multiplex.mplexid = :MPLEXID");
842  query.bindValue(":MPLEXID", mplexid);
843 
844  if (!query.exec())
845  {
846  MythDB::DBError("CardUtil::GetTunerTypeFromMultiplex", query);
847  return tuner_type;
848  }
849 
850  if (!query.next())
851  {
852  LOG(VB_GENERAL, LOG_ERR, LOC +
853  QString("Could not find mod_sys in dtv_multiplex for mplexid %1")
854  .arg(mplexid));
855 
856  return tuner_type;
857  }
858 
859  DTVModulationSystem mod_sys;
860  mod_sys.Parse(query.value(0).toString());
861  tuner_type = CardUtil::ConvertToTunerType(mod_sys);
862 
863  return tuner_type;
864 }
865 
866 // Get the currently configured delivery system from the database
868 {
869  QString delsys_db = GetDeliverySystemFromDB(inputid);
870  DTVModulationSystem delsys;
871  delsys.Parse(delsys_db);
872  return delsys;
873 }
874 
875 // Get the currently configured delivery system from the device
877 {
878  DTVModulationSystem delsys;
879 
880  if (device.isEmpty())
881  {
882  return delsys;
883  }
884 
885 #ifdef USING_DVB
886  int fd_frontend = OpenVideoDevice(device);
887  if (fd_frontend < 0)
888  {
889  LOG(VB_GENERAL, LOG_ERR, LOC +
890  QString("open failed (%1)")
891  .arg(device) + ENO);
892  return delsys;
893  }
894 
895  delsys = ProbeCurrentDeliverySystem(fd_frontend);
896 
897  LOG(VB_GENERAL, LOG_DEBUG, QString("CardUtil(%1): delsys:%2 %3")
898  .arg(device).arg(delsys).arg(delsys.toString()));
899 
900  close(fd_frontend);
901 #else
902  Q_UNUSED(device);
903 #endif
904 
905  return delsys;
906 }
907 
908 // Get the currently configured delivery system from the device
910 {
911  DTVModulationSystem delsys;
912 
913 #ifdef USING_DVB
914  struct dtv_property prop = {};
915  struct dtv_properties cmd = {};
916 
917  prop.cmd = DTV_DELIVERY_SYSTEM;
918  // prop.u.data = delsys;
919  cmd.num = 1;
920  cmd.props = &prop;
921 
922  int ret = ioctl(fd_frontend, FE_GET_PROPERTY, &cmd);
923  if (ret < 0)
924  {
925  LOG(VB_GENERAL, LOG_ERR, LOC +
926  QString("FE_GET_PROPERTY ioctl failed (fd_frontend:%1)")
927  .arg(fd_frontend) + ENO);
928  return delsys;
929  }
930 
931  delsys.Parse(DTVModulationSystem::toString(prop.u.data));
932 
933 #else
934  Q_UNUSED(fd_frontend);
935 #endif // USING_DVB
936 
937  return delsys;
938 }
939 
940 // Get the delivery system from database table capturecard.
941 // If there is nothing in the database then get the currently
942 // configured delivery system, check for DVB-T/T2 and DVB-S/S2
943 // and update the database.
944 // Configure the tuner.
945 // Return the tuner type corresponding with the modulation system.
947 {
948  QString type = GetRawInputType(inputid);
949  if ("DVB" != type)
950  return type;
951 
952  QString device = GetVideoDevice(inputid);
953 
954  DTVTunerType tunertype;
955  int fd_frontend = OpenVideoDevice(inputid);
956  if (fd_frontend < 0)
957  return "ERROR_OPEN";
958 
959  DTVModulationSystem delsys = GetDeliverySystem(inputid);
961  {
962  delsys = ProbeBestDeliverySystem(fd_frontend);
964  {
965  // Update database
966  set_on_input("inputname", inputid, delsys.toString()); // Update DB capturecard
967  LOG(VB_GENERAL, LOG_INFO,
968  QString("CardUtil[%1]: ").arg(inputid) +
969  QString("Update capturecard delivery system: %1").arg(delsys.toString()));
970  }
971  else
972  {
973  LOG(VB_GENERAL, LOG_ERR,
974  QString("CardUtil[%1]: Error probing best delivery system").arg(inputid));
975  return "ERROR_UNKNOWN";
976  }
977  }
978  SetDeliverySystem(inputid, delsys, fd_frontend);
979  tunertype = ConvertToTunerType(delsys);
980  close(fd_frontend);
981 
982  QString subtype = "ERROR_UNKNOWN";
983  if (DTVTunerType::kTunerTypeUnknown != tunertype)
984  {
985  subtype = tunertype.toString();
986  }
987 
988  LOG(VB_GENERAL, LOG_DEBUG,
989  QString("CardUtil[%1]: subtype:%2").arg(inputid).arg(subtype));
990 
991  return subtype;
992 }
993 
995 bool CardUtil::IsDVBInputType(const QString &inputType)
996 {
997  QString t = inputType.toUpper();
998  return (t == "DVB") || (t == "QPSK") || (t == "QAM") || (t == "OFDM") ||
999  (t == "ATSC") || (t == "DVB_S2") || (t == "DVB_T2");
1000 }
1001 
1002 // Get the current delivery system from the card
1003 // Get all supported delivery systems from the card
1004 // If the current delivery system is DVB-T and DVB-T2 is supported then select DVB-T2
1005 // If the current delivery system is DVB-S and DVB-S2 is supported then select DVB-S2
1006 //
1008 {
1009  DTVModulationSystem delsys;
1010 
1011 #ifdef USING_DVB
1012  // Get the current delivery system from the card
1013  delsys = ProbeCurrentDeliverySystem(fd);
1014  LOG(VB_GENERAL, LOG_INFO, LOC +
1015  QString("Current delivery system: %1").arg(delsys.toString()));
1016 
1017  // Get all supported delivery systems from the card
1018  QString msg = "Supported delivery systems:";
1019  QStringList delsyslist = ProbeDeliverySystems(fd);
1020  for (const auto & it : qAsConst(delsyslist))
1021  {
1022  msg += " ";
1023  msg += it;
1024  }
1025  LOG(VB_GENERAL, LOG_INFO, LOC + msg);
1026 
1027  // If the current delivery system is DVB-T and DVB-T2 is supported then select DVB-T2
1029  {
1031  if (delsyslist.contains(newdelsys.toString()))
1032  {
1033  LOG(VB_GENERAL, LOG_INFO, LOC +
1034  QString("Changing delivery system from %1 to %2")
1035  .arg(delsys.toString()).arg(newdelsys.toString()));
1036  delsys = newdelsys;
1037  }
1038  }
1039 
1040  // If the current delivery system is DVB-S and DVB-S2 is supported then select DVB-S2
1042  {
1044  if (delsyslist.contains(newdelsys.toString()))
1045  {
1046  LOG(VB_GENERAL, LOG_INFO, LOC +
1047  QString("Changing delivery system from %1 to %2")
1048  .arg(delsys.toString()).arg(newdelsys.toString()));
1049  delsys = newdelsys;
1050  }
1051  }
1052 #else
1053  Q_UNUSED(fd);
1054 #endif
1055 
1056  return delsys;
1057 }
1058 
1059 // Get the delivery system from the database
1060 // If not found then get the best delivery system from the card
1061 //
1063 {
1064  DTVModulationSystem delsys;
1065 #ifdef USING_DVB
1066 
1067  // If there is a valid modulation system in the database
1068  // then we return that and do nothing more.
1069  delsys = GetDeliverySystem(inputid);
1071  {
1072  return delsys;
1073  }
1074 
1075  // Nothing in the database, get default and use that
1076  delsys = ProbeBestDeliverySystem(fd);
1077  LOG(VB_GENERAL, LOG_INFO,
1078  QString("CardUtil[%1]: ").arg(inputid) +
1079  QString("No capturecard delivery system in database, using: %1").arg(delsys.toString()));
1080 
1081 #else
1082  Q_UNUSED(inputid);
1083  Q_UNUSED(fd);
1084 #endif
1085 
1086  return delsys;
1087 }
1088 
1089 // Configure the tuner to use the delivery system from database
1090 // If not found then set to the best delivery system from the card
1091 //
1093 {
1094  int ret = -1;
1095 
1096 #ifdef USING_DVB
1097  DTVModulationSystem delsys = GetOrProbeDeliverySystem(inputid, fd);
1099  {
1100  ret = SetDeliverySystem(inputid, delsys, fd);
1101  }
1102 #else
1103  Q_UNUSED(inputid);
1104  Q_UNUSED(fd);
1105 #endif
1106 
1107  return ret;
1108 }
1109 
1110 // Set delivery system from database
1111 //
1113 {
1114  int ret = -1;
1115 
1116 #ifdef USING_DVB
1117  DTVModulationSystem delsys = GetDeliverySystem(inputid);
1119  {
1120  ret = SetDeliverySystem(inputid, delsys);
1121  }
1122 #else
1123  Q_UNUSED(inputid);
1124 #endif // USING_DVB
1125 
1126  return ret;
1127 }
1128 
1130 {
1131  int ret = -1;
1132 
1133 #ifdef USING_DVB
1134  QString device = GetVideoDevice(inputid);
1135 
1136  if (device.isEmpty())
1137  {
1138  LOG(VB_GENERAL, LOG_DEBUG,
1139  QString("CardUtil[%1]: ").arg(inputid) +
1140  QString("inputid:%1 ").arg(inputid) +
1141  QString("delsys:%1").arg(delsys.toString()));
1142  return ret;
1143  }
1144 
1145  int fd_frontend = OpenVideoDevice(device);
1146  if (fd_frontend < 0)
1147  {
1148  LOG(VB_GENERAL, LOG_ERR,
1149  QString("CardUtil[%1]: ").arg(inputid) +
1150  QString("open failed (%1)").arg(device) + ENO);
1151  return ret;
1152  }
1153  ret = SetDeliverySystem(inputid, delsys, fd_frontend);
1154 
1155  close(fd_frontend);
1156 #else
1157  Q_UNUSED(inputid);
1158  Q_UNUSED(delsys);
1159 #endif // USING_DVB
1160 
1161  return ret;
1162 }
1163 
1164 // Get delivery system from the database and write it to the card
1165 int CardUtil::SetDeliverySystem(uint inputid, int fd)
1166 {
1167  int ret = -1;
1168 
1169 #ifdef USING_DVB
1170  DTVModulationSystem delsys = GetDeliverySystem(inputid);
1172  {
1173  ret = SetDeliverySystem(inputid, delsys, fd);
1174  }
1175 #else
1176  Q_UNUSED(inputid);
1177  Q_UNUSED(fd);
1178 #endif // USING_DVB
1179 
1180  return ret;
1181 }
1182 
1183 // Write the delivery system to the card
1185 {
1186  int ret = -1;
1187 
1188 #ifdef USING_DVB
1189  LOG(VB_GENERAL, LOG_INFO,
1190  QString("CardUtil[%1]: ").arg(inputid) +
1191  QString("Set delivery system: %1").arg(delsys.toString()));
1192 
1193  struct dtv_property prop = {};
1194  struct dtv_properties cmd = {};
1195 
1196  prop.cmd = DTV_DELIVERY_SYSTEM;
1197  prop.u.data = delsys;
1198  cmd.num = 1;
1199  cmd.props = &prop;
1200 
1201  ret = ioctl(fd, FE_SET_PROPERTY, &cmd);
1202  if (ret < 0)
1203  {
1204  LOG(VB_GENERAL, LOG_ERR, LOC +
1205  QString("[%1] FE_SET_PROPERTY ioctl failed")
1206  .arg(inputid) + ENO);
1207  return ret;
1208  }
1209 #else
1210  Q_UNUSED(inputid);
1211  Q_UNUSED(delsys);
1212  Q_UNUSED(fd);
1213 #endif // USING_DVB
1214 
1215  return ret;
1216 }
1217 
1219 {
1220  QString device = GetVideoDevice(inputid);
1221  return OpenVideoDevice(device);
1222 }
1223 
1224 int CardUtil::OpenVideoDevice(const QString &device)
1225 {
1226  if (device.isEmpty())
1227  return -1;
1228 
1229  QString dvbdev = CardUtil::GetDeviceName(DVB_DEV_FRONTEND, device);
1230  QByteArray dev = dvbdev.toLatin1();
1231  int fd_frontend = open(dev.constData(), O_RDWR | O_NONBLOCK);
1232  if (fd_frontend < 0)
1233  {
1234  LOG(VB_GENERAL, LOG_ERR, LOC +
1235  QString("Can't open DVB frontend (%1) for %2.")
1236  .arg(dvbdev).arg(device) + ENO);
1237  }
1238  return fd_frontend;
1239 }
1240 
1241 QString get_on_input(const QString &to_get, uint inputid)
1242 {
1244  query.prepare(
1245  QString("SELECT %1 ").arg(to_get) +
1246  "FROM capturecard "
1247  "WHERE capturecard.cardid = :INPUTID");
1248  query.bindValue(":INPUTID", inputid);
1249 
1250  if (!query.exec())
1251  MythDB::DBError("CardUtil::get_on_input", query);
1252  else if (query.next())
1253  return query.value(0).toString();
1254 
1255  return QString();
1256 }
1257 
1258 bool set_on_input(const QString &to_set, uint inputid, const QString &value)
1259 {
1260  QString tmp = get_on_input("capturecard.cardid", inputid);
1261  if (tmp.isEmpty())
1262  return false;
1263 
1265  query.prepare(
1266  QString("UPDATE capturecard SET %1 = :VALUE ").arg(to_set) +
1267  "WHERE cardid = :INPUTID");
1268  query.bindValue(":INPUTID", inputid);
1269  query.bindValue(":VALUE", value);
1270 
1271  if (query.exec())
1272  return true;
1273 
1274  MythDB::DBError("CardUtil::set_on_input", query);
1275  return false;
1276 }
1277 
1288 vector<uint> CardUtil::GetInputIDs(const QString& videodevice,
1289  const QString& rawtype,
1290  const QString& inputname,
1291  QString hostname)
1292 {
1293  vector<uint> list;
1294 
1295  if (hostname.isEmpty())
1297 
1299  QString qstr =
1300  "SELECT cardid "
1301  "FROM capturecard "
1302  "WHERE hostname = :HOSTNAME ";
1303  if (!videodevice.isEmpty())
1304  qstr += "AND videodevice = :DEVICE ";
1305  if (!inputname.isEmpty())
1306  qstr += "AND inputname = :INPUTNAME ";
1307  if (!rawtype.isEmpty())
1308  qstr += "AND cardtype = :INPUTTYPE ";
1309  qstr += "ORDER BY cardid";
1310 
1311  query.prepare(qstr);
1312 
1313  query.bindValue(":HOSTNAME", hostname);
1314  if (!videodevice.isEmpty())
1315  query.bindValue(":DEVICE", videodevice);
1316  if (!inputname.isEmpty())
1317  query.bindValue(":INPUTNAME", inputname);
1318  if (!rawtype.isEmpty())
1319  query.bindValue(":INPUTTYPE", rawtype.toUpper());
1320 
1321  if (!query.exec())
1322  MythDB::DBError("CardUtil::GetInputIDs(videodevice...)", query);
1323  else
1324  {
1325  while (query.next())
1326  list.push_back(query.value(0).toUInt());
1327  }
1328 
1329  return list;
1330 }
1331 
1333 {
1334  if (!inputid)
1335  return 0;
1336 
1338  QString qstr =
1339  "SELECT COUNT(*) "
1340  "FROM capturecard "
1341  "WHERE parentid = :INPUTID";
1342 
1343  query.prepare(qstr);
1344  query.bindValue(":INPUTID", inputid);
1345 
1346  uint count = 0;
1347 
1348  if (!query.exec())
1349  MythDB::DBError("CardUtil::GetChildInputCount()", query);
1350  else if (query.next())
1351  count = query.value(0).toUInt();
1352 
1353  return count;
1354 }
1355 
1356 vector<uint> CardUtil::GetChildInputIDs(uint inputid)
1357 {
1358  vector<uint> list;
1359 
1360  if (!inputid)
1361  return list;
1362 
1364  QString qstr =
1365  "SELECT cardid "
1366  "FROM capturecard "
1367  "WHERE parentid = :INPUTID "
1368  "ORDER BY cardid";
1369 
1370  query.prepare(qstr);
1371  query.bindValue(":INPUTID", inputid);
1372 
1373  if (!query.exec())
1374  MythDB::DBError("CardUtil::GetChildInputIDs()", query);
1375  else
1376  {
1377  while (query.next())
1378  list.push_back(query.value(0).toUInt());
1379  }
1380 
1381  return list;
1382 }
1383 
1384 static uint clone_capturecard(uint src_inputid, uint orig_dst_inputid)
1385 {
1386  uint dst_inputid = orig_dst_inputid;
1387 
1389  if (!dst_inputid)
1390  {
1391  query.prepare(
1392  "DELETE FROM capturecard "
1393  "WHERE videodevice = 'temp_dummy'");
1394 
1395  if (!query.exec())
1396  {
1397  MythDB::DBError("clone_capturecard -- delete temp", query);
1398  return 0;
1399  }
1400 
1401  query.prepare(
1402  "INSERT INTO capturecard "
1403  "SET videodevice = 'temp_dummy'");
1404 
1405  if (!query.exec())
1406  {
1407  MythDB::DBError("clone_capturecard -- insert temp", query);
1408  return 0;
1409  }
1410 
1411  query.prepare(
1412  "SELECT cardid "
1413  "FROM capturecard "
1414  "WHERE videodevice = 'temp_dummy'");
1415 
1416  if (!query.exec())
1417  {
1418  MythDB::DBError("clone_capturecard -- get temp id", query);
1419  return 0;
1420  }
1421 
1422  if (!query.next())
1423  {
1424  LOG(VB_GENERAL, LOG_ERR, "clone_capturecard -- get temp id");
1425  return 0;
1426  }
1427 
1428  dst_inputid = query.value(0).toUInt();
1429  }
1430 
1431  query.prepare(
1432  "SELECT videodevice, audiodevice, vbidevice, "
1433  " cardtype, hostname, signal_timeout, "
1434  " channel_timeout, dvb_wait_for_seqstart, dvb_on_demand, "
1435  " dvb_tuning_delay, dvb_diseqc_type, diseqcid, "
1436  " dvb_eitscan, inputname, sourceid, "
1437  " externalcommand, changer_device, changer_model, "
1438  " tunechan, startchan, displayname, "
1439  " dishnet_eit, recpriority, quicktune, "
1440  " livetvorder, reclimit, "
1441  // See below for special handling of the following.
1442  " schedgroup, schedorder "
1443  "FROM capturecard "
1444  "WHERE cardid = :INPUTID");
1445  query.bindValue(":INPUTID", src_inputid);
1446 
1447  if (!query.exec())
1448  {
1449  MythDB::DBError("clone_capturecard -- get data", query);
1450  return 0;
1451  }
1452  if (!query.next())
1453  {
1454  LOG(VB_GENERAL, LOG_ERR, "clone_cardinput -- get data 2");
1455  return 0;
1456  }
1457 
1458  // Hangel schedgroup and schedorder specially. If schedgroup is
1459  // set, schedgroup and schedorder should be false and 0,
1460  // respectively, for all children.
1461  bool schedgroup = query.value(26).toBool();
1462  uint schedorder = query.value(27).toUInt();
1463  if (schedgroup)
1464  {
1465  schedgroup = false;
1466  schedorder = 0;
1467  }
1468 
1469  MSqlQuery query2(MSqlQuery::InitCon());
1470  query2.prepare(
1471  "UPDATE capturecard "
1472  "SET videodevice = :V0, "
1473  " audiodevice = :V1, "
1474  " vbidevice = :V2, "
1475  " cardtype = :V3, "
1476  " hostname = :V4, "
1477  " signal_timeout = :V5, "
1478  " channel_timeout = :V6, "
1479  " dvb_wait_for_seqstart = :V7, "
1480  " dvb_on_demand = :V8, "
1481  " dvb_tuning_delay = :V9, "
1482  " dvb_diseqc_type = :V10, "
1483  " diseqcid = :V11,"
1484  " dvb_eitscan = :V12, "
1485  " inputname = :V13, "
1486  " sourceid = :V14, "
1487  " externalcommand = :V15, "
1488  " changer_device = :V16, "
1489  " changer_model = :V17, "
1490  " tunechan = :V18, "
1491  " startchan = :V19, "
1492  " displayname = :V20, "
1493  " dishnet_eit = :V21, "
1494  " recpriority = :V22, "
1495  " quicktune = :V23, "
1496  " livetvorder = :V24, "
1497  " reclimit = :V25, "
1498  " schedgroup = :SCHEDGROUP, "
1499  " schedorder = :SCHEDORDER, "
1500  " parentid = :PARENTID "
1501  "WHERE cardid = :INPUTID");
1502  for (uint i = 0; i < 26; ++i)
1503  query2.bindValue(QString(":V%1").arg(i), query.value(i).toString());
1504  query2.bindValue(":INPUTID", dst_inputid);
1505  query2.bindValue(":PARENTID", src_inputid);
1506  query2.bindValue(":SCHEDGROUP", schedgroup);
1507  query2.bindValue(":SCHEDORDER", schedorder);
1508 
1509  if (!query2.exec())
1510  {
1511  MythDB::DBError("clone_capturecard -- save data", query2);
1512  if (!orig_dst_inputid)
1513  CardUtil::DeleteInput(dst_inputid);
1514  return 0;
1515  }
1516 
1517  // copy input group linkages
1518  vector<uint> src_grps = CardUtil::GetInputGroups(src_inputid);
1519  vector<uint> dst_grps = CardUtil::GetInputGroups(dst_inputid);
1520  for (uint dst_grp : dst_grps)
1521  CardUtil::UnlinkInputGroup(dst_inputid, dst_grp);
1522  for (uint src_grp : src_grps)
1523  CardUtil::LinkInputGroup(dst_inputid, src_grp);
1524 
1525  // clone diseqc_config (just points to the same diseqc_tree row)
1526  DiSEqCDevSettings diseqc;
1527  if (diseqc.Load(src_inputid))
1528  diseqc.Store(dst_inputid);
1529 
1530  return dst_inputid;
1531 }
1532 
1533 uint CardUtil::CloneCard(uint src_inputid, uint orig_dst_inputid)
1534 {
1535  QString type = CardUtil::GetRawInputType(src_inputid);
1537  return 0;
1538 
1539  uint dst_inputid = clone_capturecard(src_inputid, orig_dst_inputid);
1540  return dst_inputid;
1541 }
1542 
1544 {
1545  uint inputid = CloneCard(parentid, 0);
1546 
1547  // Update the reclimit for the parent and all children so the new
1548  // child doesn't get removed the next time mythtv-setup is run.
1549  if (inputid)
1550  {
1551  LOG(VB_GENERAL, LOG_INFO, LOC +
1552  QString("Added child input %1 to parent %2")
1553  .arg(inputid).arg(parentid));
1555  query.prepare("UPDATE capturecard "
1556  "SET reclimit = reclimit + 1 "
1557  "WHERE cardid = :PARENTID");
1558  query.bindValue(":PARENTID", parentid);
1559  if (!query.exec())
1560  MythDB::DBError("CardUtil::AddChildInput", query);
1561  }
1562  else
1563  {
1564  LOG(VB_GENERAL, LOG_ERR, LOC +
1565  QString("Failed to add child input to parent %1").arg(parentid));
1566  }
1567 
1568  return inputid;
1569 }
1570 
1572 {
1573  QString fwnode;
1574 
1576  query.prepare("SELECT changer_device "
1577  "FROM capturecard WHERE cardid = :INPUTID ");
1578  query.bindValue(":INPUTID", inputid);
1579 
1580  if (query.exec() && query.next())
1581  {
1582  fwnode = query.value(0).toString();
1583  }
1584 
1585  return fwnode;
1586 }
1587 
1589 {
1590  QString fwnode;
1591 
1593  query.prepare("SELECT changer_model "
1594  "FROM capturecard WHERE cardid = :INPUTID ");
1595  query.bindValue(":INPUTID", inputid);
1596 
1597  if (query.exec() && query.next())
1598  {
1599  fwnode = query.value(0).toString();
1600  }
1601 
1602  return fwnode;
1603 }
1604 
1605 vector<uint> CardUtil::GetInputIDs(uint sourceid)
1606 {
1608 
1609  query.prepare(
1610  "SELECT DISTINCT cardid "
1611  "FROM capturecard "
1612  "WHERE sourceid = :SOURCEID");
1613  query.bindValue(":SOURCEID", sourceid);
1614 
1615  vector<uint> list;
1616 
1617  if (!query.exec())
1618  {
1619  MythDB::DBError("CardUtil::GetInputIDs(sourceid)", query);
1620  return list;
1621  }
1622 
1623  while (query.next())
1624  list.push_back(query.value(0).toUInt());
1625 
1626  return list;
1627 }
1628 
1629 bool CardUtil::SetStartChannel(uint inputid, const QString &channum)
1630 {
1632  query.prepare("UPDATE capturecard "
1633  "SET startchan = :CHANNUM "
1634  "WHERE cardid = :INPUTID");
1635  query.bindValue(":CHANNUM", channum);
1636  query.bindValue(":INPUTID", inputid);
1637 
1638  if (!query.exec())
1639  {
1640  MythDB::DBError("CardUtil::SetStartChannel", query);
1641  return false;
1642  }
1643 
1644  return true;
1645 }
1646 
1647 bool CardUtil::GetInputInfo(InputInfo &input, vector<uint> *groupids)
1648 {
1649  if (!input.m_inputId)
1650  return false;
1651 
1653  query.prepare("SELECT "
1654  "inputname, sourceid, livetvorder, "
1655  "schedorder, displayname, recpriority, quicktune "
1656  "FROM capturecard "
1657  "WHERE cardid = :INPUTID");
1658  query.bindValue(":INPUTID", input.m_inputId);
1659 
1660  if (!query.exec())
1661  {
1662  MythDB::DBError("CardUtil::GetInputInfo()", query);
1663  return false;
1664  }
1665 
1666  if (!query.next())
1667  return false;
1668 
1669  input.m_name = query.value(0).toString();
1670  input.m_sourceId = query.value(1).toUInt();
1671  input.m_liveTvOrder = query.value(2).toUInt();
1672  input.m_scheduleOrder = query.value(3).toUInt();
1673  input.m_displayName = query.value(4).toString();
1674  input.m_recPriority = query.value(5).toInt();
1675  input.m_quickTune = query.value(6).toBool();
1676 
1677  if (groupids)
1678  *groupids = GetInputGroups(input.m_inputId);
1679 
1680  return true;
1681 }
1682 
1683 QList<InputInfo> CardUtil::GetAllInputInfo()
1684 {
1685  QList<InputInfo> infoInputList;
1686 
1688  query.prepare("SELECT cardid, "
1689  "inputname, sourceid, livetvorder, "
1690  "schedorder, displayname, recpriority, quicktune "
1691  "FROM capturecard");
1692 
1693  if (!query.exec())
1694  {
1695  MythDB::DBError("CardUtil::GetAllInputInfo()", query);
1696  return infoInputList;
1697  }
1698 
1699  while (query.next())
1700  {
1701  InputInfo input;
1702  input.m_inputId = query.value(0).toUInt();
1703  input.m_name = query.value(1).toString();
1704  input.m_sourceId = query.value(2).toUInt();
1705  input.m_liveTvOrder = query.value(3).toUInt();
1706  input.m_scheduleOrder = query.value(4).toUInt();
1707  input.m_displayName = query.value(5).toString();
1708  input.m_recPriority = query.value(6).toInt();
1709  input.m_quickTune = query.value(7).toBool();
1710 
1711  infoInputList.push_back(input);
1712  }
1713 
1714  return infoInputList;
1715 }
1716 
1718 {
1719  InputInfo info("None", 0, inputid, 0, 0, 0);
1720  GetInputInfo(info);
1721  return info.m_name;
1722 }
1723 
1725 {
1727  query.prepare("SELECT startchan "
1728  "FROM capturecard "
1729  "WHERE cardid = :INPUTID");
1730  query.bindValue(":INPUTID", inputid);
1731 
1732  if (!query.exec())
1733  MythDB::DBError("CardUtil::GetStartingChannel(uint)", query);
1734  else if (query.next())
1735  return query.value(0).toString();
1736 
1737  return QString();
1738 }
1739 
1741 {
1742  if (!inputid)
1743  return QString();
1744 
1746  query.prepare("SELECT displayname "
1747  "FROM capturecard "
1748  "WHERE cardid = :INPUTID");
1749  query.bindValue(":INPUTID", inputid);
1750 
1751  if (!query.exec())
1752  MythDB::DBError("CardUtil::GetDisplayName(uint)", query);
1753  else if (query.next())
1754  {
1755  QString result = query.value(0).toString();
1756  return result;
1757  }
1758 
1759  return QString();
1760 }
1761 
1762 bool CardUtil::IsUniqueDisplayName(const QString &name, uint exclude_inputid)
1763 {
1764  if (name.isEmpty())
1765  return false;
1766 
1768  query.prepare("SELECT cardid "
1769  "FROM capturecard "
1770  "WHERE parentid = 0 "
1771  " AND cardid <> :INPUTID "
1772  " AND right(displayname, 2) = :NAME");
1773  query.bindValue(":NAME", name.right(2));
1774  query.bindValue(":INPUTID", exclude_inputid);
1775 
1776  if (!query.exec())
1777  {
1778  MythDB::DBError("CardUtil::IsUniqueDisplayName()", query);
1779  return false;
1780  }
1781 
1782  // Any result means it's not unique.
1783  return !query.next();
1784 }
1785 
1787 {
1789  query.prepare(
1790  "SELECT sourceid "
1791  "FROM capturecard "
1792  "WHERE cardid = :INPUTID");
1793  query.bindValue(":INPUTID", inputid);
1794  if (!query.exec() || !query.isActive())
1795  MythDB::DBError("CardUtil::GetSourceID()", query);
1796  else if (query.next())
1797  return query.value(0).toUInt();
1798 
1799  return 0;
1800 }
1801 
1802 // Is this intentionally leaving out the hostname when updating the
1803 // capturecard table? The hostname value does get set when inserting
1804 // into the capturecard table. (Code written in 2011.)
1806  const uint sourceid,
1807  const QString &inputname,
1808  const QString &externalcommand,
1809  const QString &changer_device,
1810  const QString &changer_model,
1811  const QString &/*hostname*/,
1812  const QString &tunechan,
1813  const QString &startchan,
1814  const QString &displayname,
1815  bool dishnet_eit,
1816  const uint recpriority,
1817  const uint quicktune,
1818  const uint schedorder,
1819  const uint livetvorder)
1820 {
1822 
1823  query.prepare(
1824  "UPDATE capturecard "
1825  "SET sourceid = :SOURCEID, "
1826  " inputname = :INPUTNAME, "
1827  " externalcommand = :EXTERNALCOMMAND, "
1828  " changer_device = :CHANGERDEVICE, "
1829  " changer_model = :CHANGERMODEL, "
1830  " tunechan = :TUNECHAN, "
1831  " startchan = :STARTCHAN, "
1832  " displayname = :DISPLAYNAME, "
1833  " dishnet_eit = :DISHNETEIT, "
1834  " recpriority = :RECPRIORITY, "
1835  " quicktune = :QUICKTUNE, "
1836  " schedorder = :SCHEDORDER, "
1837  " livetvorder = :LIVETVORDER "
1838  "WHERE cardid = :INPUTID AND "
1839  " inputname = 'None'");
1840 
1841  query.bindValue(":INPUTID", inputid);
1842  query.bindValue(":SOURCEID", sourceid);
1843  query.bindValue(":INPUTNAME", inputname);
1844  query.bindValue(":EXTERNALCOMMAND", externalcommand);
1845  query.bindValue(":CHANGERDEVICE", changer_device);
1846  query.bindValue(":CHANGERMODEL", changer_model);
1847  query.bindValue(":TUNECHAN", tunechan);
1848  query.bindValue(":STARTCHAN", startchan);
1849  query.bindValue(":DISPLAYNAME", displayname.isNull() ? "" : displayname);
1850  query.bindValue(":DISHNETEIT", dishnet_eit);
1851  query.bindValue(":RECPRIORITY", recpriority);
1852  query.bindValue(":QUICKTUNE", quicktune);
1853  query.bindValue(":SCHEDORDER", schedorder);
1854  query.bindValue(":LIVETVORDER", livetvorder);
1855 
1856  if (!query.exec())
1857  {
1858  MythDB::DBError("CardUtil::CreateCardInput()", query);
1859  return -1;
1860  }
1861 
1862  return inputid;
1863 }
1864 
1865 uint CardUtil::CreateInputGroup(const QString &name)
1866 {
1868 
1869  query.prepare("SELECT inputgroupid FROM inputgroup "
1870  "WHERE inputgroupname = :GROUPNAME "
1871  "LIMIT 1");
1872  query.bindValue(":GROUPNAME", name);
1873  if (!query.exec())
1874  {
1875  MythDB::DBError("CardUtil::CreateNewInputGroup 0", query);
1876  return 0;
1877  }
1878 
1879  if (query.next())
1880  return query.value(0).toUInt();
1881 
1882  query.prepare("SELECT MAX(inputgroupid) FROM inputgroup");
1883  if (!query.exec())
1884  {
1885  MythDB::DBError("CardUtil::CreateNewInputGroup 1", query);
1886  return 0;
1887  }
1888 
1889  uint inputgroupid = (query.next()) ? query.value(0).toUInt() + 1 : 1;
1890 
1891  query.prepare(
1892  "INSERT INTO inputgroup "
1893  " (cardinputid, inputgroupid, inputgroupname) "
1894  "VALUES (:INPUTID, :GROUPID, :GROUPNAME ) ");
1895  query.bindValue(":INPUTID", 0);
1896  query.bindValue(":GROUPID", inputgroupid);
1897  query.bindValue(":GROUPNAME", name);
1898  if (!query.exec())
1899  {
1900  MythDB::DBError("CardUtil::CreateNewInputGroup 2", query);
1901  return 0;
1902  }
1903 
1904  return inputgroupid;
1905 }
1906 
1908  const QString &type,
1909  const QString &host,
1910  const QString &device)
1911 {
1912  QString name = host + '|' + device;
1913  if (type == "FREEBOX" || type == "IMPORT" ||
1914  type == "DEMO" || type == "EXTERNAL" ||
1915  type == "HDHOMERUN" || type == "SATIP")
1916  name += QString("|%1").arg(inputid);
1917  return CreateInputGroup(name);
1918 }
1919 
1921 {
1923  query.prepare(
1924  "SELECT inputgroupid "
1925  "FROM inputgroup "
1926  "WHERE cardinputid = :INPUTID "
1927  " AND inputgroupname REGEXP '^[a-z_-]*\\\\|'");
1928  query.bindValue(":INPUTID", inputid);
1929 
1930  if (!query.exec())
1931  {
1932  MythDB::DBError("CardUtil::GetDeviceInputGroup()", query);
1933  return 0;
1934  }
1935 
1936  if (query.next())
1937  {
1938  return query.value(0).toUInt();
1939  }
1940 
1941  return 0;
1942 }
1943 
1944 bool CardUtil::LinkInputGroup(uint inputid, uint inputgroupid)
1945 {
1947 
1948  query.prepare(
1949  "SELECT cardinputid, inputgroupid, inputgroupname "
1950  "FROM inputgroup "
1951  "WHERE inputgroupid = :GROUPID "
1952  "ORDER BY inputgroupid, cardinputid, inputgroupname");
1953  query.bindValue(":GROUPID", inputgroupid);
1954 
1955  if (!query.exec())
1956  {
1957  MythDB::DBError("CardUtil::CreateInputGroup() 1", query);
1958  return false;
1959  }
1960 
1961  if (!query.next())
1962  return false;
1963 
1964  const QString name = query.value(2).toString();
1965 
1966  query.prepare(
1967  "INSERT INTO inputgroup "
1968  " (cardinputid, inputgroupid, inputgroupname) "
1969  "VALUES (:INPUTID, :GROUPID, :GROUPNAME ) ");
1970 
1971  query.bindValue(":INPUTID", inputid);
1972  query.bindValue(":GROUPID", inputgroupid);
1973  query.bindValue(":GROUPNAME", name);
1974 
1975  if (!query.exec())
1976  {
1977  MythDB::DBError("CardUtil::CreateInputGroup() 2", query);
1978  return false;
1979  }
1980 
1981  return true;
1982 }
1983 
1984 bool CardUtil::UnlinkInputGroup(uint inputid, uint inputgroupid)
1985 {
1987 
1988  if (!inputid && !inputgroupid)
1989  {
1990  query.prepare(
1991  "DELETE FROM inputgroup "
1992  "WHERE cardinputid NOT IN "
1993  "( SELECT cardid FROM capturecard )");
1994  }
1995  else
1996  {
1997  query.prepare(
1998  "DELETE FROM inputgroup "
1999  "WHERE cardinputid = :INPUTID AND "
2000  " inputgroupid = :GROUPID ");
2001 
2002  query.bindValue(":INPUTID", inputid);
2003  query.bindValue(":GROUPID", inputgroupid);
2004  }
2005 
2006  if (!query.exec())
2007  {
2008  MythDB::DBError("CardUtil::DeleteInputGroup()", query);
2009  return false;
2010  }
2011 
2012  return true;
2013 }
2014 
2015 vector<uint> CardUtil::GetInputGroups(uint inputid)
2016 {
2017  vector<uint> list;
2018 
2020 
2021  query.prepare(
2022  "SELECT inputgroupid "
2023  "FROM inputgroup "
2024  "WHERE cardinputid = :INPUTID "
2025  "ORDER BY inputgroupid, cardinputid, inputgroupname");
2026 
2027  query.bindValue(":INPUTID", inputid);
2028 
2029  if (!query.exec())
2030  {
2031  MythDB::DBError("CardUtil::GetInputGroups()", query);
2032  return list;
2033  }
2034 
2035  while (query.next())
2036  list.push_back(query.value(0).toUInt());
2037 
2038  return list;
2039 }
2040 
2041 vector<uint> CardUtil::GetGroupInputIDs(uint inputgroupid)
2042 {
2043  vector<uint> list;
2044 
2046 
2047  query.prepare(
2048  "SELECT DISTINCT cardid "
2049  "FROM capturecard, inputgroup "
2050  "WHERE inputgroupid = :GROUPID AND "
2051  " capturecard.cardid = inputgroup.cardinputid "
2052  "ORDER BY cardid");
2053 
2054  query.bindValue(":GROUPID", inputgroupid);
2055 
2056  if (!query.exec())
2057  {
2058  MythDB::DBError("CardUtil::GetGroupInputIDs()", query);
2059  return list;
2060  }
2061 
2062  while (query.next())
2063  list.push_back(query.value(0).toUInt());
2064 
2065  return list;
2066 }
2067 
2069 {
2070  LOG(VB_RECORD, LOG_INFO,
2071  QString("CardUtil[%1]: GetConflictingInputs() input %1").arg(inputid));
2072 
2073  vector<uint> inputids;
2074 
2076 
2077  query.prepare(
2078  "SELECT DISTINCT c.cardid "
2079  "FROM ( "
2080  " SELECT inputgroupid "
2081  " FROM inputgroup "
2082  " WHERE cardinputid = :INPUTID1 "
2083  ") g "
2084  "JOIN inputgroup ig ON ig.inputgroupid = g.inputgroupid "
2085  "JOIN capturecard c ON c.cardid = ig.cardinputid "
2086  " AND c.cardid <> :INPUTID2 "
2087  "ORDER BY c.cardid");
2088 
2089  query.bindValue(":INPUTID1", inputid);
2090  query.bindValue(":INPUTID2", inputid);
2091 
2092  if (!query.exec())
2093  {
2094  MythDB::DBError("CardUtil::GetConflictingInputs()", query);
2095  return inputids;
2096  }
2097 
2098  while (query.next())
2099  {
2100  inputids.push_back(query.value(0).toUInt());
2101  LOG(VB_RECORD, LOG_INFO,
2102  QString("CardUtil[%1]: GetConflictingInputs() got input %2")
2103  .arg(inputid).arg(inputids.back()));
2104  }
2105 
2106  return inputids;
2107 }
2108 
2110  uint &signal_timeout, uint &channel_timeout)
2111 {
2113  query.prepare(
2114  "SELECT signal_timeout, channel_timeout "
2115  "FROM capturecard "
2116  "WHERE cardid = :INPUTID");
2117  query.bindValue(":INPUTID", inputid);
2118 
2119  if (!query.exec() || !query.isActive())
2120  MythDB::DBError("CardUtil::GetTimeouts()", query);
2121  else if (query.next())
2122  {
2123  signal_timeout = (uint) max(query.value(0).toInt(), 250);
2124  channel_timeout = (uint) max(query.value(1).toInt(), 500);
2125  return true;
2126  }
2127 
2128  return false;
2129 }
2130 
2132 {
2133  DiSEqCDevTree *diseqc_tree = DiSEqCDev::FindTree(inputid);
2134 
2135  bool needsConf = false;
2136  if (diseqc_tree)
2137  needsConf = diseqc_tree->IsInNeedOfConf();
2138 
2139  return needsConf;
2140 }
2141 
2142 uint CardUtil::GetQuickTuning(uint inputid, const QString &input_name)
2143 {
2144  uint quicktune = 0;
2145 
2147  query.prepare(
2148  "SELECT quicktune "
2149  "FROM capturecard "
2150  "WHERE cardid = :INPUTID AND "
2151  " inputname = :INPUTNAME");
2152  query.bindValue(":INPUTID", inputid);
2153  query.bindValue(":INPUTNAME", input_name);
2154 
2155  if (!query.exec() || !query.isActive())
2156  MythDB::DBError("CardUtil::GetQuickTuning()", query);
2157  else if (query.next())
2158  quicktune = query.value(0).toUInt();
2159 
2160  return quicktune;
2161 }
2162 
2163 bool CardUtil::hasV4L2(int videofd)
2164 {
2165  (void) videofd;
2166 #ifdef USING_V4L2
2167  struct v4l2_capability vcap {};
2168 
2169  return ((ioctl(videofd, VIDIOC_QUERYCAP, &vcap) >= 0) &&
2170  ((vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE) != 0U));
2171 #else // if !USING_V4L2
2172  return false;
2173 #endif // !USING_V4L2
2174 }
2175 
2177  int videofd, QString &input, QString &driver, uint32_t &version,
2178  uint32_t &capabilities)
2179 {
2180  input.clear();
2181  driver.clear();
2182  version = 0;
2183  capabilities = 0;
2184 
2185  if (videofd < 0)
2186  return false;
2187 
2188 #ifdef USING_V4L2
2189  // First try V4L2 query
2190  struct v4l2_capability capability {};
2191  if (ioctl(videofd, VIDIOC_QUERYCAP, &capability) >= 0)
2192  {
2193  input = QString::fromLatin1((const char*)capability.card);
2194  driver = QString::fromLatin1((const char*)capability.driver);
2195  version = capability.version;
2196  capabilities = capability.capabilities;
2197  }
2198 #ifdef USING_V4L1
2199  else // Fallback to V4L1 query
2200  {
2201  struct video_capability capability2;
2202  if (ioctl(videofd, VIDIOCGCAP, &capability2) >= 0)
2203  input = QString::fromLatin1((const char*)capability2.name);
2204  }
2205 #endif // USING_V4L1
2206 #endif // USING_V4L2
2207 
2208  if (!driver.isEmpty())
2209  driver.remove( QRegularExpression(R"(\[[0-9]\]$)") );
2210 
2211  return !input.isEmpty();
2212 }
2213 
2215 {
2216  (void) videofd;
2217 
2218  InputNames list;
2219  ok = false;
2220 
2221 #ifdef USING_V4L2
2222  bool usingv4l2 = hasV4L2(videofd);
2223 
2224  // V4L v2 query
2225  struct v4l2_input vin {};
2226  while (usingv4l2 && (ioctl(videofd, VIDIOC_ENUMINPUT, &vin) >= 0))
2227  {
2228  QString input((char *)vin.name);
2229  list[vin.index] = input;
2230  vin.index++;
2231  }
2232  if (vin.index)
2233  {
2234  ok = true;
2235  return list;
2236  }
2237 
2238 #ifdef USING_V4L1
2239  // V4L v1 query
2240  struct video_capability vidcap;
2241  memset(&vidcap, 0, sizeof(vidcap));
2242  if (ioctl(videofd, VIDIOCGCAP, &vidcap) != 0)
2243  {
2244  QString msg = QObject::tr("Could not query inputs.");
2245  LOG(VB_GENERAL, LOG_ERR, "ProbeV4LVideoInputs(): Error, " + msg + ENO);
2246  list[-1] = msg;
2247  vidcap.channels = 0;
2248  }
2249 
2250  for (int i = 0; i < vidcap.channels; i++)
2251  {
2252  struct video_channel test;
2253  memset(&test, 0, sizeof(test));
2254  test.channel = i;
2255 
2256  if (ioctl(videofd, VIDIOCGCHAN, &test) != 0)
2257  {
2258  LOG(VB_GENERAL, LOG_ERR, "ProbeV4LVideoInputs(): Error, " +
2259  QString("Could determine name of input #%1"
2260  "\n\t\t\tNot adding it to the list.")
2261  .arg(test.channel) + ENO);
2262  continue;
2263  }
2264 
2265  list[i] = test.name;
2266  }
2267 #endif // USING_V4L1
2268 
2269  // Create an input when none are advertised
2270  if (list.isEmpty())
2271  list[0] = "Television";
2272 
2273  ok = true;
2274 #else // if !USING_V4L2
2275  list[-1] += QObject::tr("ERROR, Compile with V4L support to query inputs");
2276 #endif // !USING_V4L2
2277  return list;
2278 }
2279 
2281 {
2282  (void) videofd;
2283 
2284  InputNames list;
2285  ok = false;
2286 
2287 #ifdef USING_V4L2
2288  bool usingv4l2 = hasV4L2(videofd);
2289 
2290  // V4L v2 query
2291  struct v4l2_audio ain {};
2292  while (usingv4l2 && (ioctl(videofd, VIDIOC_ENUMAUDIO, &ain) >= 0))
2293  {
2294  QString input((char *)ain.name);
2295  list[ain.index] = input;
2296  ain.index++;
2297  }
2298  if (ain.index)
2299  {
2300  ok = true;
2301  return list;
2302  }
2303 
2304  ok = true;
2305 #else // if !USING_V4L2
2306  list[-1] += QObject::tr(
2307  "ERROR, Compile with V4L support to query audio inputs");
2308 #endif // !USING_V4L2
2309  return list;
2310 }
2311 
2313 {
2314  InputNames list;
2316  query.prepare(
2317  "SELECT cardid, inputname "
2318  "FROM capturecard "
2319  "WHERE hostname = :HOSTNAME "
2320  " AND videodevice = :DEVICE "
2321  " AND parentid = 0 "
2322  " AND inputname <> 'None'");
2323  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
2324  query.bindValue(":DEVICE", device);
2325 
2326  if (!query.exec() || !query.isActive())
2327  MythDB::DBError("CardUtil::GetConfiguredDVBInputs", query);
2328  else
2329  {
2330  while (query.next())
2331  list[query.value(0).toUInt()] = query.value(1).toString();
2332  }
2333  return list;
2334 }
2335 
2336 QStringList CardUtil::ProbeVideoInputs(const QString& device, const QString& inputtype)
2337 {
2338  QStringList ret;
2339 
2340  if (IsSingleInputType(inputtype))
2341  ret += "MPEG2TS";
2342  else if ("DVB" == inputtype)
2343  ret += ProbeDVBInputs(device);
2344  else
2345  ret += ProbeV4LVideoInputs(device);
2346 
2347  return ret;
2348 }
2349 
2350 QStringList CardUtil::ProbeAudioInputs(const QString& device, const QString& inputtype)
2351 {
2352  LOG(VB_GENERAL, LOG_DEBUG, QString("ProbeAudioInputs(%1,%2)")
2353  .arg(device).arg(inputtype));
2354  QStringList ret;
2355 
2356  if ("HDPVR" == inputtype ||
2357  "V4L2" == inputtype)
2358  ret += ProbeV4LAudioInputs(device);
2359 
2360  return ret;
2361 }
2362 
2363 QStringList CardUtil::ProbeV4LVideoInputs(const QString& device)
2364 {
2365  bool ok = false;
2366  QStringList ret;
2367  QByteArray dev = device.toLatin1();
2368  int videofd = open(dev.constData(), O_RDWR);
2369  if (videofd < 0)
2370  {
2371  ret += QObject::tr("Could not open '%1' "
2372  "to probe its inputs.").arg(device);
2373  return ret;
2374  }
2375  InputNames list = CardUtil::ProbeV4LVideoInputs(videofd, ok);
2376  close(videofd);
2377 
2378  if (!ok)
2379  {
2380  ret += list[-1];
2381  return ret;
2382  }
2383 
2384  InputNames::iterator it;
2385  for (it = list.begin(); it != list.end(); ++it)
2386  {
2387  if (it.key() >= 0)
2388  ret += *it;
2389  }
2390 
2391  return ret;
2392 }
2393 
2394 QStringList CardUtil::ProbeV4LAudioInputs(const QString& device)
2395 {
2396  LOG(VB_GENERAL, LOG_DEBUG, QString("ProbeV4LAudioInputs(%1)").arg(device));
2397 
2398  bool ok = false;
2399  QStringList ret;
2400  int videofd = open(device.toLatin1().constData(), O_RDWR);
2401  if (videofd < 0)
2402  {
2403  LOG(VB_GENERAL, LOG_ERR, "ProbeAudioInputs() -> couldn't open device");
2404  ret += QObject::tr("Could not open '%1' to probe its inputs.")
2405  .arg(device);
2406  return ret;
2407  }
2408  InputNames list = CardUtil::ProbeV4LAudioInputs(videofd, ok);
2409  close(videofd);
2410 
2411  if (!ok)
2412  {
2413  ret += list[-1];
2414  return ret;
2415  }
2416 
2417  InputNames::iterator it;
2418  for (it = list.begin(); it != list.end(); ++it)
2419  {
2420  if (it.key() >= 0)
2421  ret += *it;
2422  }
2423 
2424  return ret;
2425 }
2426 
2427 QStringList CardUtil::ProbeDVBInputs(const QString& device)
2428 {
2429  QStringList ret;
2430 
2431 #ifdef USING_DVB
2432  InputNames list = GetConfiguredDVBInputs(device);
2433  InputNames::iterator it;
2434  for (it = list.begin(); it != list.end(); ++it)
2435  {
2436  if (it.key())
2437  ret += *it;
2438  }
2439 #else
2440  (void) device;
2441  ret += QObject::tr("ERROR, Compile with DVB support to query inputs");
2442 #endif
2443 
2444  return ret;
2445 }
2446 
2447 QString CardUtil::GetDeviceLabel(const QString &inputtype,
2448  const QString &videodevice)
2449 {
2450  return QString("[ %1 : %2 ]").arg(inputtype).arg(videodevice);
2451 }
2452 
2454 {
2455  QString devlabel;
2457  query.prepare("SELECT cardtype, videodevice "
2458  "FROM capturecard WHERE cardid = :INPUTID ");
2459  query.bindValue(":INPUTID", inputid);
2460 
2461  if (query.exec() && query.next())
2462  {
2463  return GetDeviceLabel(query.value(0).toString(),
2464  query.value(1).toString());
2465  }
2466 
2467  return "[ UNKNOWN ]";
2468 }
2469 
2471  const QString &device,
2472  const QString &inputtype,
2473  QStringList &inputs)
2474 {
2475  inputs.clear();
2476  if (IsSingleInputType(inputtype))
2477  inputs += "MPEG2TS";
2478  else if (inputtype == "DVB")
2479  inputs += "DVBInput";
2480  else
2481  inputs += ProbeV4LVideoInputs(device);
2482 }
2483 
2484 int CardUtil::CreateCaptureCard(const QString &videodevice,
2485  const QString &audiodevice,
2486  const QString &vbidevice,
2487  const QString &inputtype,
2488  const uint audioratelimit,
2489  const QString &hostname,
2490  const uint dvb_swfilter,
2491  const uint dvb_sat_type,
2492  bool dvb_wait_for_seqstart,
2493  bool skipbtaudio,
2494  bool dvb_on_demand,
2495  const uint dvb_diseqc_type,
2496  const uint firewire_speed,
2497  const QString &firewire_model,
2498  const uint firewire_connection,
2499  const uint signal_timeout,
2500  const uint channel_timeout,
2501  const uint dvb_tuning_delay,
2502  const uint contrast,
2503  const uint brightness,
2504  const uint colour,
2505  const uint hue,
2506  const uint diseqcid,
2507  bool dvb_eitscan)
2508 {
2510 
2511  query.prepare(
2512  "INSERT INTO capturecard "
2513  "(videodevice, audiodevice, vbidevice, cardtype, "
2514  "audioratelimit, hostname, dvb_swfilter, dvb_sat_type, "
2515  "dvb_wait_for_seqstart, skipbtaudio, dvb_on_demand, dvb_diseqc_type, "
2516  "firewire_speed, firewire_model, firewire_connection, signal_timeout, "
2517  "channel_timeout, dvb_tuning_delay, contrast, brightness, colour, "
2518  "hue, diseqcid, dvb_eitscan) "
2519  "VALUES (:VIDEODEVICE, :AUDIODEVICE, :VBIDEVICE, :INPUTTYPE, "
2520  ":AUDIORATELIMIT, :HOSTNAME, :DVBSWFILTER, :DVBSATTYPE, "
2521  ":DVBWAITFORSEQSTART, :SKIPBTAUDIO, :DVBONDEMAND, :DVBDISEQCTYPE, "
2522  ":FIREWIRESPEED, :FIREWIREMODEL, :FIREWIRECONNECTION, :SIGNALTIMEOUT, "
2523  ":CHANNELTIMEOUT, :DVBTUNINGDELAY, :CONTRAST, :BRIGHTNESS, :COLOUR, "
2524  ":HUE, :DISEQCID, :DVBEITSCAN ) ");
2525 
2526  query.bindValue(":VIDEODEVICE", videodevice);
2527  query.bindValue(":AUDIODEVICE", audiodevice);
2528  query.bindValue(":VBIDEVICE", vbidevice);
2529  query.bindValue(":INPUTTYPE", inputtype);
2530  query.bindValue(":AUDIORATELIMIT", audioratelimit);
2531  query.bindValue(":HOSTNAME", hostname);
2532  query.bindValue(":DVBSWFILTER", dvb_swfilter);
2533  query.bindValue(":DVBSATTYPE", dvb_sat_type);
2534  query.bindValue(":DVBWAITFORSEQSTART", dvb_wait_for_seqstart);
2535  query.bindValue(":SKIPBTAUDIO", skipbtaudio);
2536  query.bindValue(":DVBONDEMAND", dvb_on_demand);
2537  query.bindValue(":DVBDISEQCTYPE", dvb_diseqc_type);
2538  query.bindValue(":FIREWIRESPEED", firewire_speed);
2539  query.bindValue(":FIREWIREMODEL", firewire_model);
2540  query.bindValue(":FIREWIRECONNECTION", firewire_connection);
2541  query.bindValue(":SIGNALTIMEOUT", signal_timeout);
2542  query.bindValue(":CHANNELTIMEOUT", channel_timeout);
2543  query.bindValue(":DVBTUNINGDELAY", dvb_tuning_delay);
2544  query.bindValue(":CONTRAST", contrast);
2545  query.bindValue(":BRIGHTNESS", brightness);
2546  query.bindValue(":COLOUR", colour);
2547  query.bindValue(":HUE", hue);
2548  query.bindValue(":DISEQCID", diseqcid);
2549  query.bindValue(":DVBEITSCAN", dvb_eitscan);
2550 
2551  if (!query.exec())
2552  {
2553  MythDB::DBError("CreateCaptureCard", query);
2554  return -1;
2555  }
2556 
2557  query.prepare("SELECT MAX(cardid) FROM capturecard");
2558 
2559  if (!query.exec())
2560  {
2561  MythDB::DBError("CreateCaptureCard maxinput", query);
2562  return -1;
2563  }
2564 
2565  int inputid = -1; /* must be int not uint because of return type. */
2566 
2567  if (query.next())
2568  {
2569  inputid = query.value(0).toInt();
2570  uint groupid = CardUtil::CreateDeviceInputGroup(inputid, inputtype,
2571  hostname, videodevice);
2572  CardUtil::LinkInputGroup(inputid, groupid);
2573  }
2574 
2575  return inputid;
2576 }
2577 
2579 {
2580  vector<uint> childids = GetChildInputIDs(inputid);
2581  for (uint childid : childids)
2582  {
2583  if (!DeleteInput(childid))
2584  {
2585  LOG(VB_GENERAL, LOG_ERR, LOC +
2586  QString("CardUtil: Failed to delete child input %1")
2587  .arg(childid));
2588  return false;
2589  }
2590  }
2591 
2593 
2594  DiSEqCDevTree tree;
2595  tree.Load(inputid);
2596 
2597  // Delete the capturecard row for this input
2598  query.prepare("DELETE FROM capturecard WHERE cardid = :INPUTID");
2599  query.bindValue(":INPUTID", inputid);
2600  if (!query.exec())
2601  {
2602  MythDB::DBError("DeleteCard -- delete capturecard", query);
2603  return false;
2604  }
2605 
2606  // Update the reclimit of the parent input
2607  query.prepare("UPDATE capturecard SET reclimit=reclimit-1 "
2608  "WHERE cardid = :INPUTID");
2609  query.bindValue(":INPUTID", inputid);
2610  if (!query.exec())
2611  {
2612  MythDB::DBError("DeleteCard -- update capturecard", query);
2613  return false;
2614  }
2615 
2616  // Delete the inputgroup rows for this input
2617  query.prepare("DELETE FROM inputgroup WHERE cardinputid = :INPUTID");
2618  query.bindValue(":INPUTID", inputid);
2619  if (!query.exec())
2620  {
2621  MythDB::DBError("DeleteCard -- delete inputgroup", query);
2622  return false;
2623  }
2624 
2625  // Delete the diseqc tree if no more inputs reference it.
2626  if (tree.Root())
2627  {
2628  query.prepare("SELECT cardid FROM capturecard "
2629  "WHERE diseqcid = :DISEQCID LIMIT 1");
2630  query.bindValue(":DISEQCID", tree.Root()->GetDeviceID());
2631  if (!query.exec())
2632  {
2633  MythDB::DBError("DeleteCard -- find diseqc tree", query);
2634  }
2635  else if (!query.next())
2636  {
2637  tree.SetRoot(nullptr);
2638  tree.Store(inputid);
2639  }
2640  }
2641 
2642  // delete any unused input groups
2643  UnlinkInputGroup(0, 0);
2644 
2645  return true;
2646 }
2647 
2649 {
2651  return (query.exec("TRUNCATE TABLE inputgroup") &&
2652  query.exec("TRUNCATE TABLE diseqc_config") &&
2653  query.exec("TRUNCATE TABLE diseqc_tree") &&
2654  query.exec("TRUNCATE TABLE capturecard") &&
2655  query.exec("TRUNCATE TABLE iptv_channel"));
2656 }
2657 
2658 vector<uint> CardUtil::GetInputList(void)
2659 {
2660  vector<uint> list;
2661 
2663  query.prepare(
2664  "SELECT cardid "
2665  "FROM capturecard "
2666  "ORDER BY cardid");
2667 
2668  if (!query.exec())
2669  MythDB::DBError("CardUtil::GetInputList()", query);
2670  else
2671  {
2672  while (query.next())
2673  list.push_back(query.value(0).toUInt());
2674  }
2675 
2676  return list;
2677 }
2678 
2680 {
2681  vector<uint> list;
2682 
2684  query.prepare(
2685  "SELECT DISTINCT cardid "
2686  "FROM capturecard "
2687  "WHERE schedorder <> 0 "
2688  "ORDER BY schedorder, cardid");
2689 
2690  if (!query.exec())
2691  MythDB::DBError("CardUtil::GetSchedInputList()", query);
2692  else
2693  {
2694  while (query.next())
2695  list.push_back(query.value(0).toUInt());
2696  }
2697 
2698  return list;
2699 }
2700 
2702 {
2703  vector<uint> list;
2704 
2706  query.prepare(
2707  "SELECT DISTINCT cardid "
2708  "FROM capturecard "
2709  "WHERE livetvorder <> 0 "
2710  "ORDER BY livetvorder, cardid");
2711 
2712  if (!query.exec())
2713  MythDB::DBError("CardUtil::GetLiveTVInputList()", query);
2714  else
2715  {
2716  while (query.next())
2717  list.push_back(query.value(0).toUInt());
2718  }
2719 
2720  return list;
2721 }
2722 
2723 QString CardUtil::GetDeviceName(dvb_dev_type_t type, const QString &device)
2724 {
2725  QString devname = QString(device);
2726 #if 0
2727  LOG(VB_RECORD, LOG_DEBUG, LOC + QString("DVB Device (%1)").arg(devname));
2728 #endif
2729  QString tmp = devname;
2730 
2731  if (DVB_DEV_FRONTEND == type)
2732  return devname;
2733  if (DVB_DEV_DVR == type)
2734  {
2735  tmp = tmp.replace(devname.indexOf("frontend"), 8, "dvr");
2736  if (QFile::exists(tmp))
2737  {
2738  LOG(VB_RECORD, LOG_DEBUG, LOC +
2739  QString("Adapter Frontend dvr number matches (%1)").arg(tmp));
2740  return tmp;
2741  }
2742 
2743  // use dvr0, allows multi-standard frontends which only have one dvr
2744  devname = devname.replace(devname.indexOf("frontend"), 9, "dvr0");
2745  LOG(VB_RECORD, LOG_DEBUG, LOC +
2746  QString("Adapter Frontend dvr number not matching, using dvr0 instead (%1)").arg(devname));
2747  return devname;
2748  }
2749  if (DVB_DEV_DEMUX == type)
2750  {
2751  tmp = tmp.replace(devname.indexOf("frontend"), 8, "demux");
2752  if (QFile::exists(tmp))
2753  {
2754  LOG(VB_RECORD, LOG_DEBUG, LOC +
2755  QString("Adapter Frontend demux number matches (%1)").arg(tmp));
2756  return tmp;
2757  }
2758 
2759  // use demux0, allows multi-standard frontends, which only have one demux
2760  devname = devname.replace(devname.indexOf("frontend"), 9, "demux0");
2761  LOG(VB_RECORD, LOG_DEBUG, LOC +
2762  QString("Adapter Frontend demux number not matching, using demux0 instead (%1)").arg(devname));
2763  return devname;
2764  }
2765  if (DVB_DEV_CA == type)
2766  {
2767  tmp = tmp.replace(devname.indexOf("frontend"), 8, "ca");
2768  if (QFile::exists(tmp))
2769  {
2770  LOG(VB_RECORD, LOG_DEBUG, LOC +
2771  QString("Adapter Frontend ca number matches (%1)").arg(tmp));
2772  return tmp;
2773  }
2774 
2775  // use ca0, allows multi-standard frontends, which only have one ca
2776  devname = devname.replace(devname.indexOf("frontend"), 9, "ca0");
2777  LOG(VB_RECORD, LOG_DEBUG, LOC +
2778  QString("Adapter Frontend ca number not matching, using ca0 instead (%1)").arg(devname));
2779  return devname;
2780  }
2781  if (DVB_DEV_AUDIO == type)
2782  return devname.replace(devname.indexOf("frontend"), 8, "audio");
2783  if (DVB_DEV_VIDEO == type)
2784  return devname.replace(devname.indexOf("frontend"), 8, "video");
2785 
2786  return "";
2787 }
2788 
2789 
2799 bool CardUtil::HDHRdoesDVB(const QString &device)
2800 {
2801  (void) device;
2802 
2803 #ifdef USING_HDHOMERUN
2804  hdhomerun_device_t *hdhr =
2805  hdhomerun_device_create_from_str(device.toLatin1(), nullptr);
2806  if (!hdhr)
2807  return false;
2808 
2809  const char *model = hdhomerun_device_get_model_str(hdhr);
2810  if (model && strstr(model, "dvb"))
2811  {
2812  hdhomerun_device_destroy(hdhr);
2813  return true;
2814  }
2815 
2816  hdhomerun_device_destroy(hdhr);
2817 
2818 #endif
2819 
2820  return false;
2821 }
2822 
2827 bool CardUtil::HDHRdoesDVBC(const QString &device)
2828 {
2829  (void) device;
2830 
2831 #ifdef USING_HDHOMERUN
2832  hdhomerun_device_t *hdhr =
2833  hdhomerun_device_create_from_str(device.toLatin1(), nullptr);
2834  if (!hdhr)
2835  return false;
2836 
2837  const char *model = hdhomerun_device_get_model_str(hdhr);
2838  if (model && strstr(model, "dvbc"))
2839  {
2840  hdhomerun_device_destroy(hdhr);
2841  return true;
2842  }
2843 
2844  hdhomerun_device_destroy(hdhr);
2845 
2846 #endif
2847 
2848  return false;
2849 }
2850 
2855 QString CardUtil::GetHDHRdesc(const QString &device)
2856 {
2857  QString connectErr = QObject::tr("Unable to connect to device.");
2858 
2859 #ifdef USING_HDHOMERUN
2860  bool deviceIsIP = false;
2861 
2862  if (device.contains('.')) // Simplistic check, but also allows DNS names
2863  deviceIsIP = true;
2864  else
2865  {
2866  bool validID = false;
2867 
2868  uint32_t dev = device.toUInt(&validID, 16);
2869  if (!validID || !hdhomerun_discover_validate_device_id(dev))
2870  return QObject::tr("Invalid Device ID");
2871  }
2872  (void) deviceIsIP;
2873 
2874  LOG(VB_GENERAL, LOG_INFO, "CardUtil::GetHDHRdescription(" + device +
2875  ") - trying to locate device");
2876 
2877  hdhomerun_device_t *hdhr =
2878  hdhomerun_device_create_from_str(device.toLatin1(), nullptr);
2879  if (!hdhr)
2880  return QObject::tr("Invalid Device ID or address.");
2881 
2882  const char *model = hdhomerun_device_get_model_str(hdhr);
2883  if (!model)
2884  {
2885  hdhomerun_device_destroy(hdhr);
2886  return connectErr;
2887  }
2888 
2889 
2890  QString description = model;
2891  char *sVersion = nullptr;
2892  uint32_t iVersion = 0;
2893 
2894  if (hdhomerun_device_get_version(hdhr, &sVersion, &iVersion))
2895  description += QObject::tr(", firmware: %2").arg(sVersion);
2896 
2897  hdhomerun_device_destroy(hdhr);
2898 
2899  return description;
2900 #else
2901 
2902  (void) device;
2903  return connectErr;
2904 #endif
2905 }
2906 
2911 QString CardUtil::GetVBoxdesc(const QString &id, const QString &ip,
2912  const QString &tunerNo, const QString &tunerType)
2913 {
2914  QString connectErr = QObject::tr("Unable to connect to device.");
2915 
2916 #ifdef USING_VBOX
2917  VBox *vbox = new VBox(ip);
2918 
2919  if (!vbox->checkConnection())
2920  {
2921  delete vbox;
2922  return connectErr;
2923  }
2924 
2925  QString version;
2926 
2927  if (!vbox->checkVersion(version))
2928  {
2929  QString apiVersionErr = QObject::tr("The VBox software version is too old (%1), we require %2")
2930  .arg(version).arg(VBOX_MIN_API_VERSION);
2931  delete vbox;
2932  return apiVersionErr;
2933 
2934  }
2935 
2936  delete vbox;
2937 
2938  return QString("V@Box TV Gateway - ID: %1, IP: %2, Tuner: %3-%4").arg(id)
2939  .arg(ip).arg(tunerNo).arg(tunerType);
2940 
2941 #else
2942  (void) id;
2943  (void) ip;
2944  (void) tunerNo;
2945  (void) tunerType;
2946 
2947  return connectErr;
2948 #endif
2949 }
2950 
2951 #ifdef USING_ASI
2952 static QString sys_dev(uint device_num, const QString& dev)
2953 {
2954  return QString("/sys/class/asi/asirx%1/%2").arg(device_num).arg(dev);
2955 }
2956 
2957 static QString read_sys(const QString& sys_dev)
2958 {
2959  QFile f(sys_dev);
2960  f.open(QIODevice::ReadOnly);
2961  QByteArray sdba = f.readAll();
2962  f.close();
2963  return sdba;
2964 }
2965 
2966 static bool write_sys(const QString& sys_dev, const QString& str)
2967 {
2968  QFile f(sys_dev);
2969  f.open(QIODevice::WriteOnly);
2970  QByteArray ba = str.toLocal8Bit();
2971  qint64 offset = 0;
2972  for (uint tries = 0; (offset < ba.size()) && tries < 5; tries++)
2973  {
2974  qint64 written = f.write(ba.data()+offset, ba.size()-offset);
2975  if (written < 0)
2976  return false;
2977  offset += written;
2978  }
2979  return true;
2980 }
2981 #endif
2982 
2983 int CardUtil::GetASIDeviceNumber(const QString &device, QString *error)
2984 {
2985 #ifdef USING_ASI
2986  // basic confirmation
2987  struct stat statbuf {};
2988  if (stat(device.toLocal8Bit().constData(), &statbuf) < 0)
2989  {
2990  if (error)
2991  *error = QString("Unable to stat '%1'").arg(device) + ENO;
2992  return -1;
2993  }
2994 
2995  if (!S_ISCHR(statbuf.st_mode))
2996  {
2997  if (error)
2998  *error = QString("'%1' is not a character device").arg(device);
2999  return -1;
3000  }
3001 
3002  if (!(statbuf.st_rdev & 0x0080))
3003  {
3004  if (error)
3005  *error = QString("'%1' not a DVEO ASI receiver").arg(device);
3006  return -1;
3007  }
3008 
3009  int device_num = statbuf.st_rdev & 0x007f;
3010 
3011  // extra confirmation
3012  QString sys_dev_contents = read_sys(sys_dev(device_num, "dev"));
3013  QStringList sys_dev_clist = sys_dev_contents.split(":");
3014  if (2 != sys_dev_clist.size())
3015  {
3016  if (error)
3017  {
3018  *error = QString("Unable to read '%1'")
3019  .arg(sys_dev(device_num, "dev"));
3020  }
3021  return -1;
3022  }
3023  if (sys_dev_clist[0].toUInt() != (statbuf.st_rdev>>8))
3024  {
3025  if (error)
3026  *error = QString("'%1' not a DVEO ASI device").arg(device);
3027  return -1;
3028  }
3029 
3030  return device_num;
3031 #else
3032  (void) device;
3033  if (error)
3034  *error = "Not compiled with ASI support.";
3035  return -1;
3036 #endif
3037 }
3038 
3040 {
3041 #ifdef USING_ASI
3042  // get the buffer size
3043  QString sys_bufsize_contents = read_sys(sys_dev(device_num, "bufsize"));
3044  bool ok = false;
3045  uint buf_size = sys_bufsize_contents.toUInt(&ok);
3046  if (!ok)
3047  {
3048  if (error)
3049  {
3050  *error = QString("Failed to read buffer size from '%1'")
3051  .arg(sys_dev(device_num, "bufsize"));
3052  }
3053  return 0;
3054  }
3055  return buf_size;
3056 #else
3057  (void) device_num;
3058  if (error)
3059  *error = "Not compiled with ASI support.";
3060  return 0;
3061 #endif
3062 }
3063 
3065 {
3066 #ifdef USING_ASI
3067  // get the buffer size
3068  QString sys_numbuffers_contents = read_sys(sys_dev(device_num, "buffers"));
3069  bool ok = false;
3070  uint num_buffers = sys_numbuffers_contents.toUInt(&ok);
3071  if (!ok)
3072  {
3073  if (error)
3074  {
3075  *error = QString("Failed to read num buffers from '%1'")
3076  .arg(sys_dev(device_num, "buffers"));
3077  }
3078  return 0;
3079  }
3080  return num_buffers;
3081 #else
3082  (void) device_num;
3083  if (error)
3084  *error = "Not compiled with ASI support.";
3085  return 0;
3086 #endif
3087 }
3088 
3089 int CardUtil::GetASIMode(uint device_num, QString *error)
3090 {
3091 #ifdef USING_ASI
3092  QString sys_bufsize_contents = read_sys(sys_dev(device_num, "mode"));
3093  bool ok = false;
3094  uint mode = sys_bufsize_contents.toUInt(&ok);
3095  if (!ok)
3096  {
3097  if (error)
3098  {
3099  *error = QString("Failed to read mode from '%1'")
3100  .arg(sys_dev(device_num, "mode"));
3101  }
3102  return -1;
3103  }
3104  return mode;
3105 #else
3106  (void) device_num;
3107  if (error)
3108  *error = "Not compiled with ASI support.";
3109  return -1;
3110 #endif
3111 }
3112 
3113 bool CardUtil::SetASIMode(uint device_num, uint mode, QString *error)
3114 {
3115 #ifdef USING_ASI
3116  QString sys_bufsize_contents = read_sys(sys_dev(device_num, "mode"));
3117  bool ok = false;
3118  uint old_mode = sys_bufsize_contents.toUInt(&ok);
3119  if (ok && old_mode == mode)
3120  return true;
3121  ok = write_sys(sys_dev(device_num, "mode"), QString("%1\n").arg(mode));
3122  if (!ok && error)
3123  {
3124  *error = QString("Failed to set mode to %1 using '%2'")
3125  .arg(mode).arg(sys_dev(device_num, "mode"));
3126  }
3127  return ok;
3128 #else
3129  Q_UNUSED(device_num);
3130  Q_UNUSED(mode);
3131  if (error)
3132  *error = "Not compiled with ASI support.";
3133  return false;
3134 #endif
3135 }
3136 
3142 {
3143  // should only be called if inputtype == VBOX
3144  if (!inputid )
3145  {
3146  LOG(VB_GENERAL, LOG_ERR, QString("VBOX inputid (%1) not valid, redo mythtv-setup")
3147  .arg(inputid));
3148  return false;
3149  }
3150 
3151  // get sourceid and startchan from table capturecard for inputid
3152  uint chanid = 0;
3153  chanid = ChannelUtil::GetChannelValueInt("chanid",GetSourceID(inputid),GetStartingChannel(inputid));
3154  if (!chanid)
3155  {
3156  // no chanid, presume bad setup
3157  LOG(VB_GENERAL, LOG_ERR, QString("VBOX chanid (%1) not found for inputid (%2) , redo mythtv-setup")
3158  .arg(chanid).arg(inputid));
3159  return false;
3160  }
3161 
3162  // get timeouts for inputid
3163  uint signal_timeout = 0;
3164  uint tuning_timeout = 0;
3165  if (!GetTimeouts(inputid,signal_timeout,tuning_timeout))
3166  {
3167  LOG(VB_GENERAL, LOG_ERR, QString("Failed to get timeouts for inputid (%1)")
3168  .arg(inputid));
3169  return false;
3170  }
3171 
3172  signal_timeout = signal_timeout/1000; //convert to seconds
3173 
3174  // now get url from iptv_channel table
3175  QUrl url;
3177  query.prepare("SELECT url "
3178  "FROM iptv_channel "
3179  "WHERE chanid = :CHANID");
3180  query.bindValue(":CHANID", chanid);
3181 
3182  if (!query.exec())
3183  MythDB::DBError("CardUtil::IsVBoxPresent url", query);
3184  else if (query.next())
3185  url = query.value(0).toString();
3186 
3187  //now get just the IP address from the url
3188  QString ip = url.host();
3189  LOG(VB_GENERAL, LOG_INFO, QString("VBOX IP found (%1) for inputid (%2)")
3190  .arg(ip).arg(inputid));
3191 
3192  if (!ping(ip,signal_timeout))
3193  {
3194  LOG(VB_GENERAL, LOG_ERR, QString("VBOX at IP (%1) failed to respond to network ping for inputid (%2) timeout (%3)")
3195  .arg(ip).arg(inputid).arg(signal_timeout));
3196  return false;
3197  }
3198 
3199  return true;
3200 }
CardUtil::HDHRdoesDVBC
static bool HDHRdoesDVBC(const QString &device)
If the device is valid, check if the model does DVB-C.
Definition: cardutil.cpp:2827
VBox::checkVersion
bool checkVersion(QString &version)
Definition: vboxutils.cpp:215
manager
static MythSystemLegacyManager * manager
Definition: mythsystemunix.cpp:57
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:204
CardUtil::s_videoDeviceCache
static QMap< QString, QStringList > s_videoDeviceCache
Definition: cardutil.h:456
CardUtil::GetScanableInputTypes
static QString GetScanableInputTypes(void)
Definition: cardutil.cpp:62
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:126
CardUtil::IsTunerShared
static bool IsTunerShared(uint inputidA, uint inputidB)
Definition: cardutil.cpp:264
CardUtil::SetDeliverySystem
static int SetDeliverySystem(uint inputid)
Definition: cardutil.cpp:1112
CardUtil::GetVBoxdesc
static QString GetVBoxdesc(const QString &id, const QString &ip, const QString &tunerNo, const QString &tunerType)
Get a nicely formatted string describing the device.
Definition: cardutil.cpp:2911
CardUtil::IsInNeedOfExternalInputConf
static bool IsInNeedOfExternalInputConf(uint inputid)
Definition: cardutil.cpp:2131
DiSEqCDevTree::IsInNeedOfConf
bool IsInNeedOfConf(void) const
Definition: diseqc.cpp:840
CardUtil::CreateCardInput
static int CreateCardInput(uint inputid, uint sourceid, const QString &inputname, const QString &externalcommand, const QString &changer_device, const QString &changer_model, const QString &hostname, const QString &tunechan, const QString &startchan, const QString &displayname, bool dishnet_eit, uint recpriority, uint quicktune, uint schedorder, uint livetvorder)
Definition: cardutil.cpp:1805
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:72
CardUtil::GetDisplayName
static QString GetDisplayName(uint inputid)
Definition: cardutil.cpp:1740
DTVTunerType::kTunerTypeDVBC
static const int kTunerTypeDVBC
Definition: dtvconfparserhelpers.h:95
VBox::checkConnection
bool checkConnection(void)
Definition: vboxutils.cpp:209
CardUtil::GetDeviceLabel
static QString GetDeviceLabel(const QString &inputtype, const QString &videodevice)
Definition: cardutil.cpp:2447
error
static void error(const char *str,...)
Definition: vbi.cpp:42
CardUtil::ProbeDeliverySystems
static QStringList ProbeDeliverySystems(const QString &device)
Definition: cardutil.cpp:588
mythdb.h
CardUtil::GetOrProbeDeliverySystem
static DTVModulationSystem GetOrProbeDeliverySystem(uint inputid, int fd)
Definition: cardutil.cpp:1062
DTVModulationSystem::kModulationSystem_DVBS2
@ kModulationSystem_DVBS2
Definition: dtvconfparserhelpers.h:660
CardUtil::GetVideoDevices
static QStringList GetVideoDevices(const QString &rawtype, QString hostname=QString())
Returns the videodevices of the matching inputs, duplicates removed.
Definition: cardutil.cpp:420
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
CardUtil::ClearVideoDeviceCache
static void ClearVideoDeviceCache()
Definition: cardutil.cpp:465
CardUtil::GetInputName
static QString GetInputName(uint inputid)
Definition: cardutil.cpp:1717
CardUtil::ProbeCurrentDeliverySystem
static DTVModulationSystem ProbeCurrentDeliverySystem(const QString &device)
Definition: cardutil.cpp:876
CardUtil::GetASIDeviceNumber
static int GetASIDeviceNumber(const QString &device, QString *error=nullptr)
Definition: cardutil.cpp:2983
V4L2util::DriverName
QString DriverName(void) const
Definition: v4l2util.h:48
CardUtil::DeleteAllInputs
static bool DeleteAllInputs(void)
Definition: cardutil.cpp:2648
DTVTunerType::kTunerTypeDVBS1
static const int kTunerTypeDVBS1
Definition: dtvconfparserhelpers.h:93
DVB_DEV_VIDEO
@ DVB_DEV_VIDEO
Definition: cardutil.h:34
CardUtil::SetStartChannel
static bool SetStartChannel(uint inputid, const QString &channum)
Definition: cardutil.cpp:1629
CardUtil::ProbeVideoInputs
static QStringList ProbeVideoInputs(const QString &device, const QString &inputtype=QString())
Definition: cardutil.cpp:2336
CardUtil::ProbeBestDeliverySystem
static DTVModulationSystem ProbeBestDeliverySystem(int fd)
Definition: cardutil.cpp:1007
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
arg
arg(title).arg(filename).arg(doDelete))
CardUtil::HasDVBCRCBug
static bool HasDVBCRCBug(const QString &device)
Returns true if and only if the device munges PAT/PMT tables, and then doesn't fix the CRC.
Definition: cardutil.cpp:752
V4L2util::HasTuner
bool HasTuner(void) const
Definition: v4l2util.cpp:692
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
set_on_input
bool set_on_input(const QString &to_set, uint inputid, const QString &value)
Definition: cardutil.cpp:1258
VBOX_MIN_API_VERSION
#define VBOX_MIN_API_VERSION
Definition: vboxutils.h:11
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythDownloadManager
Definition: mythdownloadmanager.h:33
CardUtil::GetChildInputIDs
static vector< uint > GetChildInputIDs(uint inputid)
Definition: cardutil.cpp:1356
DVB_DEV_CA
@ DVB_DEV_CA
Definition: cardutil.h:32
DiSEqCDevSettings::Load
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:130
CardUtil::GetInputList
static vector< uint > GetInputList(void)
Definition: cardutil.cpp:2658
read_sys
static QString read_sys(const QString &sys_dev)
Definition: cardutil.cpp:2957
CardUtil::ProbeTunerType
static DTVTunerType ProbeTunerType(int fd_frontend)
Definition: cardutil.cpp:817
CardUtil::CloneCard
static uint CloneCard(uint src_inputid, uint dst_inputid)
Definition: cardutil.cpp:1533
CardUtil::IsUniqueDisplayName
static bool IsUniqueDisplayName(const QString &name, uint exclude_inputid)
Definition: cardutil.cpp:1762
dvbchannel.h
CardUtil::GetFirewireChangerModel
static QString GetFirewireChangerModel(uint inputid)
Definition: cardutil.cpp:1588
close
#define close
Definition: compat.h:16
tmp
static guint32 * tmp
Definition: goom_core.cpp:30
CardUtil::ProbeSubTypeName
static QString ProbeSubTypeName(uint inputid)
Definition: cardutil.cpp:946
DTVModulationSystem::kModulationSystem_UNDEFINED
@ kModulationSystem_UNDEFINED
Definition: dtvconfparserhelpers.h:654
CardUtil::GetMinSignalMonitoringDelay
static uint GetMinSignalMonitoringDelay(const QString &device)
Definition: cardutil.cpp:759
CardUtil::ProbeDefaultDeliverySystem
static QString ProbeDefaultDeliverySystem(const QString &device)
Definition: cardutil.cpp:667
DTVTunerType
Definition: dtvconfparserhelpers.h:77
CardUtil::GetASINumBuffers
static uint GetASINumBuffers(uint device_num, QString *error=nullptr)
Definition: cardutil.cpp:3064
CardUtil::ProbeDVBType
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:685
satiputils.h
CardUtil::ProbeVideoDevices
static QStringList ProbeVideoDevices(const QString &rawtype)
Definition: cardutil.cpp:471
DiSEqCDevSettings
DVB-S device settings class.
Definition: diseqc.h:37
CardUtil::SetDefaultDeliverySystem
static int SetDefaultDeliverySystem(uint inputid, int fd)
Definition: cardutil.cpp:1092
CardUtil::ProbeDVBFrontendName
static QString ProbeDVBFrontendName(const QString &device)
Returns the input type from the video device.
Definition: cardutil.cpp:706
CardUtil::GetASIBufferSize
static uint GetASIBufferSize(uint device_num, QString *error=nullptr)
Definition: cardutil.cpp:3039
sourceutil.h
CardUtil::UnlinkInputGroup
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1984
InputInfo::m_recPriority
int m_recPriority
Definition: inputinfo.h:53
CardUtil::GetTimeouts
static bool GetTimeouts(uint inputid, uint &signal_timeout, uint &channel_timeout)
Definition: cardutil.cpp:2109
CardUtil::GetAllInputInfo
static QList< InputInfo > GetAllInputInfo()
Definition: cardutil.cpp:1683
dvbtypes.h
mythlogging.h
SatIP::probeDevices
static QStringList probeDevices(void)
Definition: satiputils.cpp:21
InputInfo::m_liveTvOrder
uint m_liveTvOrder
order for live TV use
Definition: inputinfo.h:55
CardUtil::GetV4LInfo
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:2176
CardUtil::GetInputInfo
static bool GetInputInfo(InputInfo &input, vector< uint > *groupids=nullptr)
Definition: cardutil.cpp:1647
v4l2util.h
CardUtil::IsSingleInputType
static bool IsSingleInputType(const QString &rawtype)
Definition: cardutil.h:207
DTVModulationSystem::kModulationSystem_DVBC_ANNEX_B
@ kModulationSystem_DVBC_ANNEX_B
Definition: dtvconfparserhelpers.h:656
CardUtil::CreateDeviceInputGroup
static uint CreateDeviceInputGroup(uint inputid, const QString &type, const QString &host, const QString &device)
Definition: cardutil.cpp:1907
CardUtil::ProbeDVBInputs
static QStringList ProbeDVBInputs(const QString &device)
Definition: cardutil.cpp:2427
DTVTunerType::kTunerTypeUnknown
static const int kTunerTypeUnknown
Definition: dtvconfparserhelpers.h:103
hardwareprofile.i18n.t
t
Definition: i18n.py:36
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
CardUtil::GetConflictingInputs
static vector< uint > GetConflictingInputs(uint inputid)
Definition: cardutil.cpp:2068
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
O_NONBLOCK
#define O_NONBLOCK
Definition: mythmedia.cpp:25
CardUtil::hasV4L2
static bool hasV4L2(int videofd)
Definition: cardutil.cpp:2163
CardUtil::GetSchedInputList
static vector< uint > GetSchedInputList(void)
Definition: cardutil.cpp:2679
DTVTunerType::toString
QString toString() const
Definition: dtvconfparserhelpers.h:154
vboxutils.h
CardUtil::ProbeV4LAudioInputs
static InputNames ProbeV4LAudioInputs(int videofd, bool &ok)
Definition: cardutil.cpp:2280
DiSEqCDevTree::Load
bool Load(const QString &device)
Loads the device tree from the database.
Definition: diseqc.cpp:313
CardUtil::GetDeliverySystemFromDB
static QString GetDeliverySystemFromDB(uint inputid)
Definition: cardutil.h:290
DVB_DEV_AUDIO
@ DVB_DEV_AUDIO
Definition: cardutil.h:33
CardUtil::HasTuner
static bool HasTuner(const QString &rawtype, const QString &device)
Definition: cardutil.cpp:238
DiSEqCDevTree::SetRoot
void SetRoot(DiSEqCDevDevice *root)
Changes the root node of the tree.
Definition: diseqc.cpp:636
dvb_dev_type_t
dvb_dev_type_t
Definition: cardutil.h:28
CardUtil::GetDeviceInputGroup
static uint GetDeviceInputGroup(uint inputid)
Definition: cardutil.cpp:1920
f
QTextStream t & f
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:600
CardUtil::IsDVBInputType
static bool IsDVBInputType(const QString &inputType)
Returns true iff the input_type is one of the DVB types.
Definition: cardutil.cpp:995
CardUtil::GetTunerType
static DTVTunerType GetTunerType(uint inputid)
Definition: cardutil.cpp:809
uint
unsigned int uint
Definition: compat.h:140
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
DiSEqCDev::FindTree
static DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:239
DiSEqCDevTree::Root
DiSEqCDevDevice * Root(void)
Retrieves the root node in the tree.
Definition: diseqc.h:93
DTVModulationSystem::kModulationSystem_ATSC
@ kModulationSystem_ATSC
Definition: dtvconfparserhelpers.h:665
CardUtil::GetFirewireChangerNode
static QString GetFirewireChangerNode(uint inputid)
Definition: cardutil.cpp:1571
ChannelUtil::GetChannelValueInt
static int GetChannelValueInt(const QString &channel_field, uint sourceid, const QString &channum)
Definition: channelutil.cpp:977
CardUtil::IsVBoxPresent
static bool IsVBoxPresent(uint inputid)
Returns true if the VBox responds to a ping.
Definition: cardutil.cpp:3141
InputInfo::m_inputId
uint m_inputId
unique key in DB for this input
Definition: inputinfo.h:49
DTVTunerType::kTunerTypeDVBS2
static const int kTunerTypeDVBS2
Definition: dtvconfparserhelpers.h:94
CardUtil::GetGroupInputIDs
static vector< uint > GetGroupInputIDs(uint inputgroupid)
Definition: cardutil.cpp:2041
InputInfo::m_quickTune
bool m_quickTune
Definition: inputinfo.h:56
CardUtil::GetInputIDs
static vector< uint > GetInputIDs(const QString &videodevice=QString(), const QString &rawtype=QString(), const QString &inputname=QString(), QString hostname=QString())
Returns all inputids of inputs that uses the specified videodevice if specified, and optionally rawty...
Definition: cardutil.cpp:1288
sys_dev
static QString sys_dev(uint device_num, const QString &dev)
Definition: cardutil.cpp:2952
DTVModulationSystem::toString
QString toString() const
Definition: dtvconfparserhelpers.h:719
CardUtil::GetQuickTuning
static uint GetQuickTuning(uint inputid, const QString &input_name)
Definition: cardutil.cpp:2142
LOC
#define LOC
Definition: cardutil.cpp:60
CardUtil::GetDeviceName
static QString GetDeviceName(dvb_dev_type_t type, const QString &device)
Definition: cardutil.cpp:2723
CardUtil::GetConfiguredDVBInputs
static InputNames GetConfiguredDVBInputs(const QString &device)
Definition: cardutil.cpp:2312
CardUtil::GetRawInputType
static QString GetRawInputType(uint inputid)
Definition: cardutil.h:282
InputInfo::m_scheduleOrder
uint m_scheduleOrder
Definition: inputinfo.h:54
CardUtil::IsInputTypePresent
static bool IsInputTypePresent(const QString &rawtype, QString hostname=QString())
Returns true if the input type is present and connected to an input.
Definition: cardutil.cpp:311
CardUtil::OpenVideoDevice
static int OpenVideoDevice(int inputid)
Definition: cardutil.cpp:1218
InputInfo::m_sourceId
uint m_sourceId
associated channel listings source
Definition: inputinfo.h:48
CardUtil::GetTunerTypeFromMultiplex
static DTVTunerType GetTunerTypeFromMultiplex(uint mplexid)
Definition: cardutil.cpp:833
clone_capturecard
static uint clone_capturecard(uint src_inputid, uint orig_dst_inputid)
Definition: cardutil.cpp:1384
V4L2util::IsOpen
bool IsOpen(void) const
Definition: v4l2util.h:29
CardUtil::IsCableCardPresent
static bool IsCableCardPresent(uint inputid, const QString &inputType)
Definition: cardutil.cpp:127
DVB_DEV_DEMUX
@ DVB_DEV_DEMUX
Definition: cardutil.h:31
DiSEqCDevSettings::Store
bool Store(uint card_input_id) const
Stores configuration chain to DB for specified card input id.
Definition: diseqc.cpp:164
mythmiscutil.h
V4L2util
Definition: v4l2util.h:17
CardUtil::InputTypes
QMap< QString, QString > InputTypes
Definition: cardutil.h:43
DTVModulationSystem
Definition: dtvconfparserhelpers.h:643
cardutil.h
dir
QDir dir
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1171
CardUtil::CreateCaptureCard
static int CreateCaptureCard(const QString &videodevice, const QString &audiodevice, const QString &vbidevice, const QString &inputtype, uint audioratelimit, const QString &hostname, uint dvb_swfilter, uint dvb_sat_type, bool dvb_wait_for_seqstart, bool skipbtaudio, bool dvb_on_demand, uint dvb_diseqc_type, uint firewire_speed, const QString &firewire_model, uint firewire_connection, uint signal_timeout, uint channel_timeout, uint dvb_tuning_delay, uint contrast, uint brightness, uint colour, uint hue, uint diseqcid, bool dvb_eitscan)
Definition: cardutil.cpp:2484
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
VBox
Definition: vboxutils.h:14
CardUtil::GetInputTypes
static InputTypes GetInputTypes(void)
Definition: cardutil.cpp:345
CardUtil::AddChildInput
static uint AddChildInput(uint parentid)
Definition: cardutil.cpp:1543
CardUtil::GetChildInputCount
static uint GetChildInputCount(uint inputid)
Definition: cardutil.cpp:1332
CardUtil::HDHRdoesDVB
static bool HDHRdoesDVB(const QString &device)
If the device is valid, check if the model does DVB.
Definition: cardutil.cpp:2799
CardUtil::GetDeliverySystem
static DTVModulationSystem GetDeliverySystem(uint inputid)
Definition: cardutil.cpp:867
CardUtil::ProbeAudioInputs
static QStringList ProbeAudioInputs(const QString &device, const QString &inputtype=QString())
Definition: cardutil.cpp:2350
CardUtil::GetHDHRdesc
static QString GetHDHRdesc(const QString &device)
Get a nicely formatted string describing the device.
Definition: cardutil.cpp:2855
CardUtil::GetSourceID
static uint GetSourceID(uint inputid)
Definition: cardutil.cpp:1786
inputinfo.h
InputInfo
Definition: inputinfo.h:15
VBox::probeDevices
static QStringList probeDevices(void)
Definition: vboxutils.cpp:32
CardUtil::IsTunerSharingCapable
static bool IsTunerSharingCapable(const QString &rawtype)
Definition: cardutil.h:172
DiSEqCDevTree
DVB-S device tree class. Represents a tree of DVB-S devices.
Definition: diseqc.h:75
get_on_input
QString get_on_input(const QString &to_get, uint inputid)
Definition: cardutil.cpp:1241
CardUtil::GetInputTypeNames
static QStringList GetInputTypeNames(uint sourceid)
Get a list of card input types for a source id.
Definition: cardutil.cpp:392
CardUtil::ConvertToTunerType
static DTVTunerType ConvertToTunerType(DTVModulationSystem delsys)
Definition: cardutil.cpp:769
DTVTunerType::kTunerTypeATSC
static const int kTunerTypeATSC
Definition: dtvconfparserhelpers.h:98
InputNames
QMap< int, QString > InputNames
Definition: cardutil.h:21
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:856
DVB_DEV_FRONTEND
@ DVB_DEV_FRONTEND
Definition: cardutil.h:29
DiSEqCDevTree::Store
bool Store(uint cardid, const QString &device="")
Stores the device tree to the database.
Definition: diseqc.cpp:424
CardUtil::ProbeV4LVideoInputs
static InputNames ProbeV4LVideoInputs(int videofd, bool &ok)
Definition: cardutil.cpp:2214
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
DiSEqCDevDevice::GetDeviceID
uint GetDeviceID(void) const
Definition: diseqc.h:165
DTVModulationSystem::kModulationSystem_DVBT2
@ kModulationSystem_DVBT2
Definition: dtvconfparserhelpers.h:670
DTVTunerType::kTunerTypeDVBT
static const int kTunerTypeDVBT
Definition: dtvconfparserhelpers.h:96
DTVModulationSystem::kModulationSystem_DVBC_ANNEX_C
@ kModulationSystem_DVBC_ANNEX_C
Definition: dtvconfparserhelpers.h:672
mythdownloadmanager.h
CardUtil::GetDeviceInputNames
static void GetDeviceInputNames(const QString &device, const QString &inputtype, QStringList &inputs)
Definition: cardutil.cpp:2470
DVB_DEV_DVR
@ DVB_DEV_DVR
Definition: cardutil.h:30
V4L2util::CardName
QString CardName(void) const
Definition: v4l2util.h:49
DTVTunerType::kTunerTypeDVBT2
static const int kTunerTypeDVBT2
Definition: dtvconfparserhelpers.h:97
CardUtil::GetInputGroups
static vector< uint > GetInputGroups(uint inputid)
Definition: cardutil.cpp:2015
CardUtil::GetStartingChannel
static QString GetStartingChannel(uint inputid)
Definition: cardutil.cpp:1724
query
MSqlQuery query(MSqlQuery::InitCon())
nv_python_libs.bbciplayer.bbciplayer_api.version
string version
Definition: bbciplayer_api.py:81
InputInfo::m_displayName
QString m_displayName
Definition: inputinfo.h:52
CardUtil::CreateInputGroup
static uint CreateInputGroup(const QString &name)
Definition: cardutil.cpp:1865
CardUtil::LinkInputGroup
static bool LinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1944
DTVModulationSystem::kModulationSystem_DVBS
@ kModulationSystem_DVBS
Definition: dtvconfparserhelpers.h:659
videosource.h
DTVModulationSystem::kModulationSystem_DVBT
@ kModulationSystem_DVBT
Definition: dtvconfparserhelpers.h:657
diseqcsettings.h
CardUtil::SetASIMode
static bool SetASIMode(uint device_num, uint mode, QString *error=nullptr)
Definition: cardutil.cpp:3113
CardUtil::GetVideoDevice
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:284
ping
bool ping(const QString &host, int timeout)
Can we ping host within timeout seconds?
Definition: mythmiscutil.cpp:246
DTVModulationSystem::kModulationSystem_DVBC_ANNEX_A
@ kModulationSystem_DVBC_ANNEX_A
Definition: dtvconfparserhelpers.h:655
InputInfo::m_name
QString m_name
input name
Definition: inputinfo.h:47
GetMythDownloadManager
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
Definition: mythdownloadmanager.cpp:161
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808
write_sys
static bool write_sys(const QString &sys_dev, const QString &str)
Definition: cardutil.cpp:2966
DTVModulationSystem::Parse
bool Parse(const QString &_value)
Definition: dtvconfparserhelpers.h:716
CardUtil::GetASIMode
static int GetASIMode(uint device_num, QString *error=nullptr)
Definition: cardutil.cpp:3089
CardUtil::GetLiveTVInputList
static vector< uint > GetLiveTVInputList(void)
Definition: cardutil.cpp:2701
CardUtil::DeleteInput
static bool DeleteInput(uint inputid)
Definition: cardutil.cpp:2578