6 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(_WIN32)
9 #include <sys/sysmacros.h>
17 #include <QCoreApplication>
24 #include <QStringList>
25 #include <QTextStream>
32 #include "libmythbase/mythconfig.h"
60 #ifdef USING_HDHOMERUN
61 #include HDHOMERUN_HEADERFILE
66 bool _must_have_mplexid) :
67 m_initialSourceId(_initial_sourceid),
68 m_cardTypes(
std::move(_card_types)),
69 m_mustHaveMplexId(_must_have_mplexid)
74 "Select a video source that is connected to one "
75 "or more capture cards. Default is the video source "
76 "selected in the Channel Editor page."
85 "SELECT DISTINCT videosource.name, videosource.sourceid "
86 "FROM capturecard, videosource";
91 "WHERE capturecard.sourceid = videosource.sourceid AND "
92 " capturecard.hostname = :HOSTNAME ";
96 querystr += QString(
" AND capturecard.cardtype in %1 ")
103 " AND channel.sourceid = videosource.sourceid "
104 " AND channel.mplexid != 32767 "
105 " AND channel.mplexid != 0 ";
116 for (; query.
next(); cnt++)
119 query.
value(1).toString());
134 m_initialSourceId(_initial_sourceid)
139 "The video source that is "
140 "selected in the Channel Editor page."
149 "SELECT DISTINCT videosource.name, videosource.sourceid "
150 "FROM capturecard, videosource "
151 "WHERE capturecard.sourceid = videosource.sourceid AND "
152 " capturecard.hostname = :HOSTNAME AND "
153 " videosource.sourceid = :SOURCEID ";
178 setLabel(QObject::tr(
"Max recordings"));
182 "Maximum number of simultaneous recordings MythTV will "
183 "attempt using this device. If set to a value other than "
184 "1, MythTV can sometimes record multiple programs on "
185 "the same multiplex or overlapping copies of the same "
186 "program on a single channel."
197 setLabel(QObject::tr(
"Schedule as group"));
201 "Schedule all virtual inputs on this device as a group. "
202 "This is more efficient than scheduling each input "
203 "individually. Additional, virtual inputs will be "
204 "automatically added as needed to fulfill the recording "
212 QString sourceidTag(
":WHERESOURCEID");
214 QString query(
"sourceid = " + sourceidTag);
223 QString sourceidTag(
":SETSOURCEID");
226 QString query(
"sourceid = " + sourceidTag +
", " +
237 QString cardidTag(
":WHERECARDID");
239 QString query(
"cardid = " + cardidTag);
248 QString cardidTag(
":SETCARDID");
251 QString query(
"cardid = " + cardidTag +
", " +
268 setLabel(QObject::tr(
"Listings grabber"));
277 QObject::tr(
"Transmitted guide only (EIT)"),
"eitonly");
288 #pragma message( "tv_find_grabbers is not supported yet on windows." )
294 QMutexLocker lock(&
m_lock);
302 find_grabber_proc.
Run(25s);
303 LOG(VB_GENERAL, LOG_INFO,
304 loc +
"Running 'tv_find_grabbers " +
args.join(
" ") +
"'.");
305 uint status = find_grabber_proc.
Wait();
309 QTextStream ostream(find_grabber_proc.
ReadAll());
310 while (!ostream.atEnd())
312 QString grabber_list(ostream.readLine());
313 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
314 QStringList grabber_split =
315 grabber_list.split(
"|", QString::SkipEmptyParts);
317 QStringList grabber_split =
318 grabber_list.split(
"|", Qt::SkipEmptyParts);
320 QString grabber_name = grabber_split[1] +
" (xmltv)";
321 QFileInfo grabber_file(grabber_split[0]);
324 m_progList.push_back(grabber_file.fileName());
325 LOG(VB_GENERAL, LOG_DEBUG,
"Found " + grabber_split[0]);
327 LOG(VB_GENERAL, LOG_INFO, loc +
"Finished running tv_find_grabbers");
331 LOG(VB_GENERAL, LOG_ERR, loc +
"Failed to run tv_find_grabbers");
336 LOG(VB_GENERAL, LOG_INFO, loc +
"Loading results of tv_find_grabbers");
350 "UPDATE videosource "
351 "SET userid=NULL, password=NULL "
352 "WHERE xmltvgrabber NOT IN ( 'technovera' )");
359 if (name_list.size() != prog_list.size())
366 for (
uint i = 0; i < (
uint) name_list.size(); i++)
374 if (!selValue.isEmpty())
397 std::chrono::milliseconds min_val,
398 std::chrono::milliseconds max_val,
399 std::chrono::milliseconds step,
400 const QString &setting) :
402 min_val.count(), max_val.count(), step.count())
409 template<typename T, typename = typename std::enable_if<!std::is_integral<T>()>>
411 {
setValueMs(duration_cast<std::chrono::milliseconds>(newSecs)); }
418 const QString &setting) :
430 setLabel(QObject::tr(
"Scan Frequency"));
431 setHelpText(QObject::tr(
"The frequency to start scanning this video source. "
432 "This is then default for 'Full Scan (Tuned)' channel scanning. "
433 "Frequency value in Hz for DVB-T/T2/C, in kHz for DVB-S/S2. "
434 "Leave at 0 if not known. "));
445 setLabel(QObject::tr(
"Network ID"));
448 setHelpText(QObject::tr(
"If your provider has asked you to configure a "
449 "specific network identifier (Network_ID), "
450 "enter it here. Leave it at -1 otherwise."));
462 setLabel(QObject::tr(
"Bouquet ID"));
463 setHelpText(QObject::tr(
"Bouquet ID for Freesat or Sky on satellite Astra-2 28.2E. "
464 "Leave this at 0 if you do not receive this satellite. "
465 "This is needed to get the Freesat and Sky channel numbers. "
466 "Value 272 selects Freesat bouquet 'England HD'. "
467 "See the MythTV Wiki https://www.mythtv.org/wiki/DVB_UK."));
480 setHelpText(QObject::tr(
"Region ID for Freesat or Sky on satellite Astra-2 28.2E. "
481 "Leave this at 0 you do not receive this satellite. "
482 "This is needed to get the Freesat and Sky channel numbers. "
483 "Value 1 selects region London. "
484 "See the MythTV Wiki https://www.mythtv.org/wiki/DVB_UK."));
496 setLabel(QObject::tr(
"Logical Channel Number Offset"));
497 setHelpText(QObject::tr(
"The offset is added to each logical channel number found "
498 "during a scan of a DVB video source. This makes it possible "
499 "to give different video sources a non-overlapping range "
500 "of channel numbers. Leave at 0 if you have only one video source "
501 "or if the video sources do not have DVB logical channel numbers."));
509 setLabel(QObject::tr(
"Channel frequency table"));
515 setHelpText(QObject::tr(
"Use default unless this source uses a "
516 "different frequency table than the system wide table "
517 "defined in the General settings."));
521 m_sourceId(_sourceid)
523 setLabel(QObject::tr(
"Channel frequency table"));
542 "WHERE sourceid = :SOURCEID");
568 LOG(VB_GENERAL, LOG_INFO,
"TransFreqTableSelector::Save(void)");
579 "UPDATE videosource "
580 "SET freqtable = :FREQTABLE "
581 "WHERE sourceid = :SOURCEID");
605 setLabel(QObject::tr(
"Perform EIT scan"));
607 "If enabled, program guide data for channels on this "
608 "source will be updated with data provided by the "
609 "channels themselves 'Over-the-Air'."));
614 const QString& _grabber,
616 m_parent(_parent), m_grabber(_grabber)
620 QString
filename = QString(
"%1/%2.xmltv")
630 config->setHelpText(tr(
"Run XMLTV configure command."));
641 QString err_msg = QObject::tr(
642 "You MUST run 'mythfilldatabase --manual' the first time,\n"
643 "instead of just 'mythfilldatabase'.\nYour grabber does not provide "
644 "channel numbers, so you have to set them manually.");
648 LOG(VB_GENERAL, LOG_ERR, err_msg);
676 label->setValue(QObject::tr(
"Use only the transmitted guide data."));
678 QObject::tr(
"This will usually only work with ATSC or DVB channels, "
679 "and generally provides data only for the next few days."));
698 label->setValue(QObject::tr(
"Do not configure a grabber"));
714 setLabel(QObject::tr(
"Video Source Setup"));
736 const QString &thecardtype)
739 query.
prepare(
"SELECT count(cardtype)"
741 " WHERE capturecard.sourceid = :SOURCEID "
742 " AND capturecard.cardtype = :CARDTYPE ;");
744 query.
bindValue(
":CARDTYPE", thecardtype);
748 int count = query.
value(0).toInt();
760 result.
prepare(
"SELECT name, sourceid FROM videosource;");
764 while (result.
next())
767 source->setLabel(result.
value(0).toString());
768 source->loadByID(result.
value(1).toInt());
777 result.
prepare(
"SELECT name, sourceid FROM videosource;");
781 while (result.
next())
784 result.
value(1).toString());
799 uint minor_max = UINT_MAX,
800 const QString& card = QString(),
801 const QRegularExpression& driver = QRegularExpression()) :
804 setLabel(QObject::tr(
"Video device"));
807 QDir dev(
"/dev/v4l",
"video*", QDir::Name, QDir::System);
809 card, driver,
false);
814 card, driver,
false);
817 dev.setPath(
"/dev/dtv");
819 card, driver,
false);
823 dev.setNameFilters(QStringList(
"dtv*"));
825 card, driver,
false);
833 [[maybe_unused]]
bool absPath =
true)
840 const QString& card,
const QRegularExpression& driver,
841 bool allow_duplicates)
844 QFileInfoList entries = dir.entryInfoList();
845 for (
const auto & fi : qAsConst(entries))
848 QString filepath = fi.absoluteFilePath();
849 int err =
lstat(filepath.toLocal8Bit().constData(), &st);
853 LOG(VB_GENERAL, LOG_ERR,
854 QString(
"Could not stat file: %1").arg(filepath));
859 if (!S_ISCHR(st.st_mode))
864 if (minor_min > minor_num || minor_max < minor_num)
872 QByteArray
tmp = filepath.toLatin1();
873 int videofd = open(
tmp.constData(), O_RDWR);
880 auto match = driver.match(driver_name);
881 if ((!driver.pattern().isEmpty() || match.hasMatch()) &&
882 (card.isEmpty() || (card_name == card)))
914 setLabel(QObject::tr(
"VBI device"));
916 setHelpText(QObject::tr(
"Device to read VBI (captions) from."));
923 QDir dev(
"/dev/v4l",
"vbi*", QDir::Name, QDir::System);
942 [[maybe_unused]]
bool absPath =
true)
948 const QString &driver)
951 QFileInfoList entries = dir.entryInfoList();
952 for (
const auto & fi : qAsConst(entries))
954 QString device = fi.absoluteFilePath();
955 QByteArray adevice = device.toLatin1();
956 int vbifd = open(adevice.constData(), O_RDWR);
963 (driver.isEmpty() || (dn == driver)) &&
964 (card.isEmpty() || (cn == card)))
966 devices.push_back(device);
973 for (
const QString& device : qAsConst(devices))
976 return (
uint) devices.size();
989 setHelpText(QObject::tr(
"Specify the command to run, with any "
990 "needed arguments."));
1002 setLabel(QObject::tr(
"File path"));
1013 setLabel(QObject::tr(
"Audio device"));
1015 QDir dev(
"/dev",
"dsp*", QDir::Name, QDir::System);
1017 dev.setPath(
"/dev/sound");
1024 setHelpText(QObject::tr(
"Device to read audio from, "
1025 "if audio is separate from the video."));
1034 std::chrono::milliseconds min_val) :
1037 setLabel(QObject::tr(
"Signal timeout (ms)"));
1040 "Maximum time (in milliseconds) MythTV waits for "
1041 "a signal when scanning for channels."));
1044 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>
::type >
1046 SignalTimeout(parent, value, duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1047 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>
::type >
1050 duration_cast<
std::chrono::milliseconds>(value),
1051 duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1059 std::chrono::milliseconds min_val) :
1062 setLabel(QObject::tr(
"Tuning timeout (ms)"));
1065 "Maximum time (in milliseconds) MythTV waits for "
1066 "a channel lock. For recordings, if this time is "
1067 "exceeded, the recording will be marked as failed."));
1070 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>
::type >
1072 ChannelTimeout(parent, value, duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1073 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>
::type >
1075 ChannelTimeout(parent, value, duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1084 setLabel(QObject::tr(
"Force audio sampling rate"));
1086 QObject::tr(
"If non-zero, override the audio sampling "
1087 "rate in the recording profile when this card is "
1088 "used. Use this if your capture card does not "
1089 "support all of the standard rates."));
1104 setLabel(QObject::tr(
"Do not adjust volume"));
1106 QObject::tr(
"Enable this option for budget BT878 based "
1107 "DVB-T cards such as the AverTV DVB-T which "
1108 "require the audio volume to be left alone."));
1118 setLabel(QObject::tr(
"DVB device"));
1120 QObject::tr(
"When you change this setting, the text below "
1121 "should change to the name and type of your card. "
1122 "If the card cannot be opened, an error message "
1123 "will be displayed."));
1141 std::stable_sort(sdevs.begin(), sdevs.end());
1146 QMap<QString,bool> in_use;
1148 for (
const QString& dev : qAsConst(sdevs))
1150 in_use[dev] =
std::find(db.begin(), db.end(), dev) != db.end();
1151 if (sel.isEmpty() && !in_use[dev])
1155 if (sel.isEmpty() && !sdevs.empty())
1158 QString usestr = QString(
" -- ");
1159 usestr += QObject::tr(
"Warning: already in use");
1161 for (
const QString& dev : qAsConst(sdevs))
1163 QString desc = dev + (in_use[dev] ? usestr :
"");
1164 desc = (
current == dev) ? dev : desc;
1188 setLabel(QObject::tr(
"Delivery system"));
1190 QObject::tr(
"If your card supports more than one delivery system "
1191 "then you can select here the one that you want to use."));
1200 setLabel(QObject::tr(
"Frontend ID"));
1202 QObject::tr(
"Identification string reported by the card. "
1203 "If the message \"Could not get card info...\" appears "
1204 "the card can be in use by another program."));
1215 setLabel(QObject::tr(
"Wait for SEQ start header"));
1218 QObject::tr(
"If enabled, drop packets from the start of a DVB "
1219 "recording until a sequence start header is seen."));
1230 setLabel(QObject::tr(
"Open DVB card on demand"));
1233 QObject::tr(
"If enabled, only open the DVB card when required, "
1234 "leaving it free for other programs at other times."));
1245 setLabel(QObject::tr(
"Use DVB card for active EIT scan"));
1248 QObject::tr(
"If enabled, activate active scanning for "
1249 "program data (EIT). When this option is enabled "
1250 "the DVB card is constantly in use."));
1260 setLabel(QObject::tr(
"DVB tuning delay (ms)"));
1263 QObject::tr(
"Some Linux DVB drivers, in particular for the "
1264 "Hauppauge Nova-T, require that we slow down "
1265 "the tuning process by specifying a delay "
1266 "(in milliseconds)."));
1277 #ifdef USING_FIREWIRE
1279 for (
auto & i : list)
1281 QString guid = i.GetGUIDString();
1285 #endif // USING_FIREWIRE
1300 setLabel(QObject::tr(
"Cable box model"));
1301 addSelection(QObject::tr(
"Motorola Generic"),
"MOTO GENERIC");
1302 addSelection(QObject::tr(
"SA/Cisco Generic"),
"SA GENERIC");
1318 QString
help = QObject::tr(
1319 "Choose the model that most closely resembles your set top box. "
1320 "Depending on firmware revision SA4200HD may work better for a "
1327 #ifdef USING_FIREWIRE
1331 #endif // USING_FIREWIRE
1338 #ifdef USING_FIREWIRE
1340 name.replace(
"Scientific-Atlanta",
"SA");
1341 name.replace(
", Inc.",
"");
1342 name.replace(
"Explorer(R)",
"");
1343 name = name.simplified();
1344 setValue((name.isEmpty()) ?
"" : name);
1345 #endif // USING_FIREWIRE
1353 "firewire_connection"))
1355 setLabel(QObject::tr(
"Connection Type"));
1376 #ifdef USING_FIREWIRE
1388 #ifdef USING_LINUX_FIREWIRE
1391 #endif // USING_LINUX_FIREWIRE
1396 model->SetGUID(dev->getValue());
1397 desc->SetGUID(dev->getValue());
1405 #ifdef USING_HDHOMERUN
1439 setLabel(QObject::tr(
"Use HDHomeRun for active EIT scan"));
1442 QObject::tr(
"If enabled, activate active scanning for "
1443 "program data (EIT). When this option is enabled "
1444 "the HDHomeRun is constantly in use."));
1455 setLabel(QObject::tr(
"Use HDHomeRun %1 (%2 %3)")
1456 .arg(deviceid, model, ipaddr));
1459 QObject::tr(
"If enabled, use tuners from this HDHomeRun "
1475 QMap<QString, HDHomeRunDevice>::iterator dit;
1476 for (dit = m_deviceList.begin(); dit != m_deviceList.end(); ++dit)
1488 buttonRecOpt->setLabel(tr(
"Recording Options"));
1489 buttonRecOpt->addChild(
new SignalTimeout(m_parent, 3s, 0.25s));
1503 for (
const auto & dev : qAsConst(devs))
1505 QStringList devinfo = dev.split(
" ");
1506 const QString& devid = devinfo.at(0);
1507 const QString& devip = devinfo.at(1);
1508 const QString& model = devinfo.at(2);
1522 QMap<QString, HDHomeRunDevice>::iterator debugit;
1525 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1: %2 %3")
1526 .arg(debugit.key()).arg((*debugit).model)
1527 .arg((*debugit).cardip));
1534 QStringList devstrs = devices.split(
",");
1535 for (
const QString& devstr : qAsConst(devstrs))
1540 QByteArray ba = devstr.toUtf8();
1541 hdhomerun_device_t *device = hdhomerun_device_create_from_str(
1542 ba.data(),
nullptr);
1545 QString devid = QString(
"%1").arg(
1546 hdhomerun_device_get_device_id(device), 8, 16).toUpper();
1547 hdhomerun_device_destroy(device);
1550 QMap<QString, HDHomeRunDevice>::iterator dit;
1553 (*dit).m_checkbox->setValue(
true);
1561 QStringList devstrs;
1562 QMap<QString, HDHomeRunDevice>::iterator dit;
1565 if ((*dit).m_checkbox->boolValue())
1566 devstrs << (*dit).m_deviceId;
1568 QString devices = devstrs.join(
",");
1580 setLabel(QObject::tr(
"IP Address"));
1581 setHelpText(QObject::tr(
"Device IP or ID of a VBox device. eg. '192.168.1.100' or 'vbox_3718'"));
1611 setHelpText(QObject::tr(
"Number and type of the tuner to use. eg '1-DVBT/T2'."));
1680 m_deviceId(deviceid),
1683 m_cardTuner(cardtuner),
1684 m_deviceList(devicelist),
1687 setLabel(QObject::tr(
"Available devices"));
1690 "Device IP or ID, tuner number and tuner type of available VBox devices."));
1701 std::vector<QString> devs;
1702 QMap<QString, bool> in_use;
1708 devs.push_back(it.key());
1709 in_use[it.key()] = (*it).m_inUse;
1712 QString man_addr = VBoxDeviceIDList::tr(
"Manually Enter IP Address");
1713 QString sel = man_addr;
1714 devs.push_back(sel);
1716 for (
const auto & dev : devs)
1717 sel = (
current == dev) ? dev : sel;
1719 QString usestr = QString(
" -- ");
1720 usestr += QObject::tr(
"Warning: already in use");
1722 for (
const auto & dev : devs)
1724 QString desc = dev + (in_use[dev] ? usestr :
"");
1732 else if (sel == man_addr && !
current.isEmpty())
1735 QStringList selection =
current.split(
"-");
1756 if (v == VBoxDeviceIDList::tr(
"Manually Enter IP Address"))
1761 else if (!v.isEmpty())
1763 if (
m_oldValue == VBoxDeviceIDList::tr(
"Manually Enter IP Address"))
1788 setValue(
"http://mafreebox.freebox.fr/freeboxtv/playlist.m3u");
1791 QObject::tr(
"URL of M3U file containing RTSP/RTP/UDP/HTTP channel URLs,"
1792 " example for HDHomeRun: http://<ipv4>/lineup.m3u and for Freebox:"
1793 " http://mafreebox.freebox.fr/freeboxtv/playlist.m3u."
1812 setLabel(QObject::tr(
"ASI device"));
1830 std::stable_sort(sdevs.begin(), sdevs.end());
1839 QMap<QString,bool> in_use;
1841 for (
const QString& dev : qAsConst(sdevs))
1843 in_use[dev] =
std::find(db.begin(), db.end(), dev) != db.end();
1844 if (sel.isEmpty() && !in_use[dev])
1849 if (sel.isEmpty() && !sdevs.empty())
1852 QString usestr = QString(
" -- ");
1853 usestr += QObject::tr(
"Warning: already in use");
1857 for (
const QString& dev : qAsConst(sdevs))
1859 QString desc = dev + (in_use[dev] ? usestr :
"");
1860 desc = (
current == dev) ? dev : desc;
1862 found |= (dev == sel);
1866 if (!found && !
current.isEmpty())
1868 QString desc =
current +
" -- " +
1869 QObject::tr(
"Warning: unable to open");
1907 if (device.isEmpty())
1924 LOG(VB_GENERAL, LOG_WARNING,
1925 "ASIConfigurationGroup::probeCard(), Warning: " +
error);
1941 device->setHelpText(tr(
"A local file used to simulate a recording."
1942 " Leave empty to use MythEvents to trigger an"
1943 " external program to import recording files."));
1965 QFileInfo fileInfo(device);
1968 if (device.startsWith(
"file:", Qt::CaseInsensitive))
1969 fileInfo.setFile(device.mid(5));
1971 if (fileInfo.exists())
1973 if (fileInfo.isReadable() && (fileInfo.isFile()))
1976 cs = tr(
"%1 MB").arg(fileInfo.size() / 1024 / 1024);
1979 ci = tr(
"File not readable");
1983 ci = tr(
"File %1 does not exist").arg(device);
2005 m_desc->setLabel(tr(
"Description"));
2009 m_deviceId, m_desc, m_cardIp, m_cardTuner, &m_deviceList, m_parent);
2035 for (
const auto & dev : qAsConst(devs))
2037 QStringList devinfo = dev.split(
" ");
2038 const QString&
id = devinfo.at(0);
2039 const QString& ip = devinfo.at(1);
2040 const QString& tunerNo = devinfo.at(2);
2041 const QString& tunerType = devinfo.at(3);
2060 for (
const auto & dev : qAsConst(db))
2062 QMap<QString, VBoxDevice>::iterator dit;
2066 (*dit).m_inUse =
true;
2103 static const QRegularExpression ipV4Regex
2104 {
"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){4}$" };
2105 auto match = ipV4Regex.match(ip +
".");
2106 if (match.hasMatch())
2115 static const QRegularExpression oneDigit {
"^\\d$" };
2116 auto match = oneDigit.match(tuner);
2117 if (match.hasMatch())
2132 static const QRegularExpression newstyle { R
"(^([0-9.]+)-(\d|RTP)\.(\d)$)" };
2133 auto match = newstyle.match(
getValue());
2134 if (match.hasMatch())
2145 desc->setLabel(tr(
"CetonConfigurationGroup",
"Description"));
2147 tr(
"IP Address of the Ceton device (192.168.200.1 by default)"));
2149 tr(
"Number of the tuner on the Ceton device (first tuner is number 0)"));
2185 const QString &inputtype) :
2191 QRegularExpression drv {
"^(?!ivtv|hdpvr|(saa7164(.*))).*$" };
2215 QString cn = tr(
"Failed to open");
2219 QByteArray adevice = device.toLatin1();
2220 int videofd = open(adevice.constData(), O_RDWR);
2224 ci = cn = tr(
"Failed to probe");
2225 else if (!dn.isEmpty())
2226 ci = cn +
" [" + dn +
"]";
2240 QRegularExpression drv {
"^(ivtv|(saa7164(.*)))$" };
2264 QString cn = tr(
"Failed to open");
2268 QByteArray adevice = device.toLatin1();
2269 int videofd = open(adevice.constData(), O_RDWR);
2273 ci = cn = tr(
"Failed to probe");
2274 else if (!dn.isEmpty())
2275 ci = cn +
" [" + dn +
"]";
2291 device->setHelpText(tr(
"A local MPEG file used to simulate a recording."));
2314 QFileInfo fileInfo(device);
2315 if (fileInfo.exists())
2317 if (fileInfo.isReadable() && (fileInfo.isFile()))
2320 cs = tr(
"%1 MB").arg(fileInfo.size() / 1024 / 1024);
2323 ci = tr(
"File not readable");
2327 ci = tr(
"File does not exist");
2334 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2335 ExternalConfigurationGroup::ExternalConfigurationGroup(
CaptureCard &a_parent,
2342 device->setLabel(tr(
"Command path"));
2343 device->setHelpText(tr(
"A 'black box' application controlled via stdin, status on "
2344 "stderr and TransportStream read from stdout.\n"
2345 "Use absolute path or path relative to the current directory."));
2355 this, &ExternalConfigurationGroup::probeApp);
2357 probeApp(device->getValue());
2360 void ExternalConfigurationGroup::probeApp(
const QString & path)
2362 int idx1 = path.startsWith(
"file:", Qt::CaseInsensitive) ? 5 : 0;
2363 int idx2 = path.indexOf(
' ', idx1);
2366 QFileInfo fileInfo(path.mid(idx1, idx2 - idx1));
2368 if (fileInfo.exists())
2370 ci = tr(
"File '%1' is valid.").arg(fileInfo.absoluteFilePath());
2371 if (!fileInfo.isReadable() || !fileInfo.isFile())
2372 ci = tr(
"WARNING: File '%1' is not readable.")
2373 .arg(fileInfo.absoluteFilePath());
2374 if (!fileInfo.isExecutable())
2375 ci = tr(
"WARNING: File '%1' is not executable.")
2376 .arg(fileInfo.absoluteFilePath());
2380 ci = tr(
"WARNING: File '%1' does not exist.")
2381 .arg(fileInfo.absoluteFilePath());
2384 m_info->setValue(ci);
2385 m_info->setHelpText(ci);
2387 #endif // !defined( USING_MINGW ) && !defined( _MSC_VER )
2397 QRegularExpression(
"^hdpvr$"));
2420 QString cn = tr(
"Failed to open");
2424 int videofd = open(device.toLocal8Bit().constData(), O_RDWR);
2428 ci = cn = tr(
"Failed to probe");
2429 else if (!dn.isEmpty())
2430 ci = cn +
" [" + dn +
"]";
2446 setLabel(QObject::tr(
"V4L2 encoder devices (multirec capable)"));
2461 if (!device_name.isEmpty())
2468 QString card_name = tr(
"Failed to open");
2469 QString card_info = card_name;
2488 if (audioinput->fillSelections(device_name) > 1)
2490 audioinput->setName(
"AudioInput");
2501 vbidev->setName(
"VBIDevice");
2512 #endif // USING_V4L2
2517 setLabel(QObject::tr(
"Capture Card Setup"));
2519 auto* cardtype =
new CardType(parent);
2523 cardtype->addTargetedChild(
"DVB",
2528 cardtype->addTargetedChild(
"HDPVR",
2530 #endif // USING_V4L2
2532 #ifdef USING_HDHOMERUN
2533 cardtype->addTargetedChild(
"HDHOMERUN",
2535 #endif // USING_HDHOMERUN
2538 cardtype->addTargetedChild(
"VBOX",
2540 #endif // USING_VBOX
2543 cardtype->addTargetedChild(
"SATIP",
2544 new SatIPConfigurationGroup(parent, *cardtype));
2545 #endif // USING_SATIP
2547 #ifdef USING_FIREWIRE
2549 #endif // USING_FIREWIRE
2553 #endif // USING_CETON
2557 #endif // USING_IPTV
2560 cardtype->addTargetedChild(
"V4L2ENC",
new V4L2encGroup(parent, *cardtype));
2561 cardtype->addTargetedChild(
"V4L",
2563 cardtype->addTargetedChild(
"MJPEG",
2565 cardtype->addTargetedChild(
"GO7007",
2567 cardtype->addTargetedChild(
"MPEG",
2569 #endif // USING_V4L2
2572 cardtype->addTargetedChild(
"ASI",
2577 cardtype->addTargetedChild(
"IMPORT",
2579 cardtype->addTargetedChild(
"DEMO",
2581 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2582 cardtype->addTargetedChild(
"EXTERNAL",
2583 new ExternalConfigurationGroup(parent,
2609 "SELECT cardid, videodevice, cardtype, displayname "
2611 "WHERE hostname = :HOSTNAME AND parentid = 0 "
2625 while (query.
next())
2628 QString videodevice = query.
value(1).toString();
2629 QString cardtype = query.
value(2).toString();
2630 QString displayname = query.
value(3).toString();
2632 QString label = QString(
"%1 (%2)")
2636 card->loadByID(cardid);
2637 card->setLabel(label);
2674 if (dev != init_dev)
2676 if (!init_dev.isEmpty())
2695 for (
uint clone : clones)
2712 setLabel(QObject::tr(
"Card type"));
2713 setHelpText(QObject::tr(
"Change the cardtype to the appropriate type for "
2714 "the capture card you are configuring."));
2722 QObject::tr(
"DVB-T/S/C, ATSC or ISDB-T tuner card"),
"DVB");
2727 QObject::tr(
"V4L2 encoder"),
"V4L2ENC");
2729 QObject::tr(
"HD-PVR H.264 encoder"),
"HDPVR");
2730 #endif // USING_V4L2
2732 #ifdef USING_HDHOMERUN
2734 QObject::tr(
"HDHomeRun networked tuner"),
"HDHOMERUN");
2735 #endif // USING_HDHOMERUN
2739 QObject::tr(
"Sat>IP networked tuner"),
"SATIP");
2740 #endif // USING_SATIP
2744 QObject::tr(
"V@Box TV Gateway networked tuner"),
"VBOX");
2745 #endif // USING_VBOX
2747 #ifdef USING_FIREWIRE
2749 QObject::tr(
"FireWire cable box"),
"FIREWIRE");
2750 #endif // USING_FIREWIRE
2754 QObject::tr(
"Ceton Cablecard tuner"),
"CETON");
2755 #endif // USING_CETON
2758 setting->
addSelection(QObject::tr(
"IPTV recorder"),
"FREEBOX");
2759 #endif // USING_IPTV
2763 QObject::tr(
"Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"),
"MPEG");
2765 QObject::tr(
"Analog to MJPEG encoder card (Matrox G200, DC10, etc)"),
"MJPEG");
2767 QObject::tr(
"Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
2770 QObject::tr(
"Analog capture card"),
"V4L");
2771 #endif // USING_V4L2
2774 setting->
addSelection(QObject::tr(
"DVEO ASI recorder"),
"ASI");
2777 setting->
addSelection(QObject::tr(
"Import test recorder"),
"IMPORT");
2778 setting->
addSelection(QObject::tr(
"Demo test recorder"),
"DEMO");
2779 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2780 setting->
addSelection(QObject::tr(
"External (black box) recorder"),
2791 setLabel(QObject::tr(
"Input name"));
2804 if (storage ==
nullptr)
2811 while (!inputs.isEmpty())
2824 setLabel(QObject::tr(
"Delivery system"));
2826 "This shows the delivery system (modulation), for instance DVB-T2, "
2827 "that you have selected when you configured the capture card. "
2828 "This must be the same as the modulation used by the video source. "));
2840 setLabel(QObject::tr(
"Display name"));
2842 "This name is displayed on screen when Live TV begins "
2843 "and in various other places. Make sure the last two "
2844 "characters are unique for each input or use a "
2845 "slash ('/') to designate the unique portion."));
2871 setLabel(QObject::tr(
"Video source"));
2895 setLabel(QObject::tr(
"Input group") +
2898 "Leave as 'Generic' unless this input is shared with "
2899 "another device. Only one of the inputs in an input "
2900 "group will be allowed to record at any given time."));
2903 void Load(
void)
override;
2928 LOG(VB_GENERAL, LOG_DEBUG, QString(
"InputGroup::Load() %1 %2")
2933 QMap<uint, uint> grpcnt;
2934 std::vector<QString> names;
2935 std::vector<uint> grpid;
2936 std::vector<uint> selected_groupids;
2938 names.push_back(QObject::tr(
"Generic"));
2944 "SELECT cardinputid, inputgroupid, inputgroupname "
2946 "WHERE inputgroupname LIKE 'user:%' "
2947 "ORDER BY inputgroupid, cardinputid, inputgroupname");
2955 while (query.
next())
2958 if ((inputid != 0U) && (query.
value(0).toUInt() == inputid))
2959 selected_groupids.push_back(groupid);
2963 if (grpcnt[groupid] == 1)
2965 names.push_back(query.
value(2).toString().mid(5, -1));
2966 grpid.push_back(groupid);
2977 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Group num: %1 id: %2")
2981 for (
uint i = 0; i < selected_groupids.size(); i++)
2982 msg += QString(
"%1 ").arg(selected_groupids[i]);
2983 LOG(VB_GENERAL, LOG_DEBUG, msg);
2990 for (
size_t i = 0; i < names.size(); i++)
2993 index = (sel) ? i : index;
2996 LOG(VB_GENERAL, LOG_DEBUG, QString(
"grpid %1, name '%2', i %3, s %4")
2997 .arg(grpid[i]).arg(names[i]) .arg(index).arg(sel ?
"T" :
"F"));
3000 addSelection(names[i], QString::number(grpid[i]), sel);
3004 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Group index: %1").arg(index));
3019 setLabel(QObject::tr(
"Use quick tuning"));
3024 "If enabled, MythTV will tune using only the "
3025 "MPEG program number. The program numbers "
3026 "change more often than DVB or ATSC tuning "
3027 "parameters, so this is slightly less reliable. "
3028 "This will also inhibit EIT gathering during "
3029 "Live TV and recording."));
3039 setLabel(QObject::tr(
"External channel change command"));
3041 setHelpText(QObject::tr(
"If specified, this command will be run to "
3042 "change the channel for inputs which have an external "
3043 "tuner device such as a cable box. The first argument "
3044 "will be the channel number."));
3054 setLabel(QObject::tr(
"Preset tuner to channel"));
3056 setHelpText(QObject::tr(
"Leave this blank unless you have an external "
3057 "tuner that is connected to the tuner input of your card. "
3058 "If so, you will need to specify the preset channel for "
3059 "the signal (normally 3 or 4)."));
3066 if (sourceid.isEmpty() || !sourceid.toUInt())
3071 if (storage ==
nullptr)
3078 if (channels.empty())
3081 startChan.isEmpty() ?
"0" : startChan);
3089 bool has_visible =
false;
3090 for (
size_t i = 0; i < channels.size() && !has_visible; i++)
3093 for (
auto & channel : channels)
3095 const QString channum = channel.m_chanNum;
3096 bool sel = channum == startChan;
3097 if (!has_visible || channel.m_visible || sel)
3111 setLabel(QObject::tr(
"Input priority"));
3113 setHelpText(QObject::tr(
"If the input priority is not equal for "
3114 "all inputs, the scheduler may choose to record a show "
3115 "at a later time so that it can record on an input with "
3116 "a higher value."));
3127 setLabel(QObject::tr(
"Schedule order"));
3129 setHelpText(QObject::tr(
"If priorities and other factors are equal "
3130 "the scheduler will choose the available "
3131 "input with the lowest, non-zero value. "
3132 "Setting this value to zero will make the "
3133 "input unavailable to the scheduler."));
3144 setLabel(QObject::tr(
"Live TV order"));
3146 setHelpText(QObject::tr(
"When entering Live TV, the available, local "
3147 "input with the lowest, non-zero value will "
3148 "be used. If no local inputs are available, "
3149 "the available, remote input with the lowest, "
3150 "non-zero value will be used. "
3151 "Setting this value to zero will make the "
3152 "input unavailable to live TV."));
3163 setLabel(QObject::tr(
"Use DishNet long-term EIT data"));
3167 "If you point your satellite dish toward DishNet's birds, "
3168 "you may wish to enable this feature. For best results, "
3169 "enable general EIT collection as well."));
3195 if (
"DVB" == cardtype)
3217 if (
"DVB" == cardtype)
3222 tr(
"Use channel scanner to find channels for this input."));
3225 tr(
"This uses the listings data source to "
3226 "provide the channels for this input.") +
" " +
3227 tr(
"This can take a long time to run."));
3236 interact->setLabel(QObject::tr(
"Interactions between inputs"));
3246 interact->addChild(
new LiveTVOrder(*
this, _cardid));
3250 ingrpbtn->setHelpText(
3251 QObject::tr(
"Input groups are only needed when two or more cards "
3252 "share the same resource such as a FireWire card and "
3253 "an analog card input controlling the same set top box."));
3254 interact->addChild(ingrpbtn);
3260 setObjectName(
"CardInput");
3286 bool enable = (sourceid.toInt() > 0);
3303 auto *settingdialog =
3306 if (settingdialog->Create())
3313 delete settingdialog;
3320 ShowOkPopup(tr(
"Sorry, this Input Group name cannot be blank."));
3324 QString new_name = QString(
"user:") + name;
3327 query.
prepare(
"SELECT inputgroupname "
3329 "WHERE inputgroupname = :GROUPNAME");
3330 query.
bindValue(
":GROUPNAME", new_name);
3340 ShowOkPopup(tr(
"Sorry, this Input Group name is already in use."));
3367 #ifdef USING_BACKEND
3375 LOG(VB_GENERAL, LOG_ERR,
3376 QString(
"Sorry, %1 cards do not yet support scanning.")
3392 if (num_channels_before)
3404 LOG(VB_GENERAL, LOG_ERR,
"You must compile the backend "
3405 "to be able to scan for channels");
3425 cardtype !=
"HDHOMERUN" &&
3426 !num_channels_before)
3428 LOG(VB_GENERAL, LOG_ERR,
"Skipping channel fetch, you need to "
3429 "scan for channels first.");
3438 if (num_channels_before)
3447 QString cardinputidTag(
":WHERECARDID");
3449 QString query(
"cardid = " + cardinputidTag);
3458 QString cardinputidTag(
":SETCARDID");
3461 QString query(
"cardid = " + cardinputidTag +
", " +
3480 query.
prepare(
"SELECT cardid FROM capturecard "
3481 "WHERE cardid = :CARDID AND inputname = :INPUTNAME");
3483 query.
bindValue(
":INPUTNAME", _inputname);
3536 tr(
"Are you sure you want to delete "
3545 tr(
"Are you sure you want to delete "
3546 "ALL capture cards?"),
3554 card->setLabel(tr(
"New capture card"));
3580 "WHERE hostname = :HOSTNAME");
3586 tr(
"Error getting list of cards for this host. "
3587 "Unable to delete capturecards for %1")
3594 while (cards.
next())
3610 AddSelection(QObject::tr(
"(Delete all capture cards on %1)")
3613 AddSelection(QObject::tr(
"(Delete all capture cards)"),
3627 AddSelection(QObject::tr(
"(Delete all video sources)"),
3650 tr(
"Are you sure you want to delete "
3651 "ALL video sources?"),
3669 source->setLabel(tr(
"New video source"));
3691 "SELECT cardid, videodevice, cardtype, displayname "
3693 "WHERE hostname = :HOSTNAME "
3694 " AND parentid = 0 "
3704 while (query.
next())
3707 QString videodevice = query.
value(1).toString();
3708 QString cardtype = query.
value(2).toString();
3709 QString displayname = query.
value(3).toString();
3711 auto *cardinput =
new CardInput(cardtype, videodevice, cardid);
3712 cardinput->loadByID(cardid);
3713 QString inputlabel = QString(
"%1 (%2) -> %3")
3715 displayname, cardinput->getSourceName());
3717 cardinput->setLabel(inputlabel);
3728 QString short_name = name;
3729 if (short_name.startsWith(
"LG Electronics"))
3730 short_name = short_name.right(short_name.length() - 15);
3731 if (short_name.startsWith(
"Oren"))
3732 short_name = short_name.right(short_name.length() - 5);
3733 if (short_name.startsWith(
"Nextwave"))
3734 short_name = short_name.right(short_name.length() - 9);
3735 if (short_name.startsWith(
"frontend", Qt::CaseInsensitive))
3736 short_name = short_name.left(short_name.length() - 9);
3737 if (short_name.endsWith(
"VSB/QAM"))
3738 short_name = short_name.left(short_name.length() - 8);
3739 if (short_name.endsWith(
"VSB"))
3740 short_name = short_name.left(short_name.length() - 4);
3741 if (short_name.endsWith(
"DVB-T"))
3742 short_name = short_name.left(short_name.length() - 6);
3748 short_name = short_name.simplified();
3749 if (short_name.startsWith(
"or51211", Qt::CaseInsensitive))
3750 short_name =
"pcHDTV HD-2000";
3751 else if (short_name.startsWith(
"or51132", Qt::CaseInsensitive))
3752 short_name =
"pcHDTV HD-3000";
3753 else if (short_name.startsWith(
"bcm3510", Qt::CaseInsensitive))
3754 short_name =
"Air2PC v1";
3755 else if (short_name.startsWith(
"nxt2002", Qt::CaseInsensitive) ||
3756 short_name.startsWith(
"nxt200x", Qt::CaseInsensitive))
3757 short_name =
"Air2PC v2";
3758 else if (short_name.startsWith(
"lgdt3302", Qt::CaseInsensitive))
3759 short_name =
"DViCO HDTV3";
3760 else if (short_name.startsWith(
"lgdt3303", Qt::CaseInsensitive))
3761 short_name =
"DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
3786 if (videodevice.isEmpty())
3804 QString err_open = tr(
"Could not open card %1").arg(videodevice);
3805 QString err_other = tr(
"Could not get card info for card %1").arg(videodevice);
3851 if (frontend_name.toLower().indexOf(
"usb") >= 0)
3858 if ((frontend_name ==
"DiBcom 3000P/M-C DVB-T") ||
3860 "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
3865 #if 0 // frontends on hybrid DVB-T/Analog cards
3867 m_buttonAnalog->setVisible(
3868 short_name.startsWith(
"zarlink zl10353",
3869 Qt::CaseInsensitive) ||
3870 short_name.startsWith(
"wintv hvr 900 m/r: 65008/a1c0",
3871 Qt::CaseInsensitive) ||
3872 short_name.startsWith(
"philips tda10046h",
3873 Qt::CaseInsensitive));
3887 if (frontend_name ==
"Nextwave NXT200X VSB/QAM frontend")
3893 #if 0 // frontends on hybrid DVB-T/Analog cards
3894 if (frontend_name.toLower().indexOf(
"usb") < 0)
3896 m_buttonAnalog->setVisible(
3897 short_name.startsWith(
"pchdtv", Qt::CaseInsensitive) ||
3898 short_name.startsWith(
"dvico", Qt::CaseInsensitive) ||
3899 short_name.startsWith(
"nextwave", Qt::CaseInsensitive));
3912 for (
const auto & item : qAsConst(delsyslist))
3914 LOG(VB_GENERAL, LOG_DEBUG, QString(
"DVBCardType: add deliverysystem:%1")
3922 if (!delsys.isEmpty())
3934 QString dev, QString
type) :
3936 m_lastDevice(
std::move(dev)), m_lastCardType(
std::move(
type))
3938 setLabel(QObject::tr(
"Audio input"));
3939 setHelpText(QObject::tr(
"If there is more than one audio input, "
3940 "select which one to use."));
3953 if (device.isEmpty())
3957 QStringList inputs =
3960 for (
uint i = 0; i < (
uint)inputs.size(); i++)
3965 return inputs.size();
4049 explicit DiSEqCPosition(
const CaptureCard &parent,
int value,
int min_val) :
4053 setLabel(QObject::tr(
"DiSEqC position"));
4054 setHelpText(QObject::tr(
"Position of the LNB on the DiSEqC switch. "
4055 "Leave at 1 if there is no DiSEqC switch "
4056 "and the LNB is directly connected to the SatIP server. "
4057 "This value is used as signal source (attribute src) in "
4058 "the SatIP tune command."));
4063 SatIPConfigurationGroup::SatIPConfigurationGroup
4071 m_friendlyName =
new SatIPDeviceAttribute(tr(
"Friendly name"), tr(
"Friendly name of the Sat>IP server"));
4072 m_tunerType =
new SatIPDeviceAttribute(tr(
"Tuner type"), tr(
"Type of the selected tuner"));
4073 m_tunerIndex =
new SatIPDeviceAttribute(tr(
"Tuner index"), tr(
"Index of the tuner on the Sat>IP server"));
4074 m_deviceId =
new SatIPDeviceID(
m_parent);
4076 m_deviceIdList =
new SatIPDeviceIDList(
4077 m_deviceId, m_friendlyName, m_tunerType, m_tunerIndex, &m_deviceList,
m_parent);
4089 connect(m_deviceIdList, &SatIPDeviceIDList::NewTuner,
4090 m_deviceId, &SatIPDeviceID::SetTuner);
4093 void SatIPConfigurationGroup::FillDeviceList(
void)
4095 m_deviceList.clear();
4101 for (
const auto & dev : qAsConst(devs))
4103 QStringList devparts = dev.split(
" ");
4104 const QString&
id = devparts.value(0);
4105 const QString& name = devparts.value(1);
4106 const QString& ip = devparts.value(2);
4107 const QString& tunerno = devparts.value(3);
4108 const QString& tunertype = devparts.value(4);
4111 device.m_deviceId = id;
4112 device.m_cardIP = ip;
4113 device.m_inUse =
false;
4114 device.m_friendlyName = name;
4115 device.m_tunerNo = tunerno;
4116 device.m_tunerType = tunertype;
4117 device.m_mythDeviceId = QString(
"%1:%2:%3").arg(
id, tunertype, tunerno);
4119 QString friendlyIdentifier = QString(
"%1, %2, Tuner #%3").arg(name, tunertype, tunerno);
4121 m_deviceList[device.m_mythDeviceId] = device;
4123 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"SatIP: Add %1 '%2' '%3'")
4124 .arg(device.m_mythDeviceId, device.m_friendlyName, friendlyIdentifier));
4130 for (
const auto& dev : db)
4132 auto dit = m_deviceList.find(dev);
4133 if (dit != m_deviceList.end())
4135 (*dit).m_inUse =
true;
4140 SatIPDeviceIDList::SatIPDeviceIDList(
4141 SatIPDeviceID *deviceId,
4142 SatIPDeviceAttribute *friendlyName,
4143 SatIPDeviceAttribute *tunerType,
4144 SatIPDeviceAttribute *tunerIndex,
4145 SatIPDeviceList *deviceList,
4147 m_deviceId(deviceId),
4148 m_friendlyName(friendlyName),
4149 m_tunerType(tunerType),
4150 m_tunerIndex(tunerIndex),
4151 m_deviceList(deviceList),
4155 setHelpText(tr(
"Device IP or ID, tuner number and tuner type of available Sat>IP device"));
4158 this, &SatIPDeviceIDList::UpdateDevices);
4161 void SatIPDeviceIDList::Load(
void)
4165 int cardid = m_parent.getCardID();
4168 fillSelections(device);
4171 void SatIPDeviceIDList::UpdateDevices(
const QString &v)
4173 SatIPDevice dev = (*m_deviceList)[v];
4174 m_deviceId->setValue(dev.m_mythDeviceId);
4175 m_friendlyName->setValue(dev.m_friendlyName);
4176 m_tunerType->setValue(dev.m_tunerType);
4177 m_tunerIndex->setValue(dev.m_tunerNo);
4180 void SatIPDeviceIDList::fillSelections(
const QString &cur)
4184 std::vector<QString> names;
4185 std::vector<QString> devs;
4186 QMap<QString, bool> in_use;
4191 SatIPDeviceList::iterator it = m_deviceList->begin();
4192 for(; it != m_deviceList->end(); ++it)
4194 QString friendlyIdentifier = QString(
"%1, %2, Tuner #%3")
4195 .arg((*it).m_friendlyName, (*it).m_tunerType, (*it).m_tunerNo);
4196 names.push_back(friendlyIdentifier);
4198 devs.push_back(it.key());
4199 in_use[it.key()] = (*it).m_inUse;
4202 for (
const auto& it2s : devs)
4204 sel = (
current == it2s) ? it2s : sel;
4207 QString usestr = QString(
" -- ");
4208 usestr += tr(
"Warning: already in use");
4210 for (
uint i = 0; i < devs.size(); ++i)
4212 const QString dev = devs[i];
4213 const QString name = names[i];
4214 bool dev_in_use = (dev == sel) ?
false : in_use[devs[i]];
4215 QString desc = name + (dev_in_use ? usestr :
"");
4216 addSelection(desc, dev, dev == sel);
4220 SatIPDeviceID::SatIPDeviceID(
const CaptureCard &parent) :
4230 void SatIPDeviceID::Load(
void)
4235 void SatIPDeviceID::SetTuner(
const QString &tuner)
4240 SatIPDeviceAttribute::SatIPDeviceAttribute(
const QString& label,
const QString& helptext)
4243 setHelpText(helptext);
4245 #endif // USING_SATIP