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 QStringList grabber_split =
314 grabber_list.split(
"|", Qt::SkipEmptyParts);
315 QString grabber_name = grabber_split[1] +
" (xmltv)";
316 QFileInfo grabber_file(grabber_split[0]);
319 m_progList.push_back(grabber_file.fileName());
320 LOG(VB_GENERAL, LOG_DEBUG,
"Found " + grabber_split[0]);
322 LOG(VB_GENERAL, LOG_INFO, loc +
"Finished running tv_find_grabbers");
326 LOG(VB_GENERAL, LOG_ERR, loc +
"Failed to run tv_find_grabbers");
331 LOG(VB_GENERAL, LOG_INFO, loc +
"Loading results of tv_find_grabbers");
345 "UPDATE videosource "
346 "SET userid=NULL, password=NULL "
347 "WHERE xmltvgrabber NOT IN ( 'technovera' )");
354 if (name_list.size() != prog_list.size())
361 for (
uint i = 0; i < (
uint) name_list.size(); i++)
369 if (!selValue.isEmpty())
392 std::chrono::milliseconds min_val,
393 std::chrono::milliseconds max_val,
394 std::chrono::milliseconds step,
395 const QString &setting) :
397 min_val.count(), max_val.count(), step.count())
404 template<typename T, typename = typename std::enable_if<!std::is_integral<T>()>>
406 {
setValueMs(duration_cast<std::chrono::milliseconds>(newSecs)); }
413 const QString &setting) :
425 setLabel(QObject::tr(
"Scan Frequency"));
426 setHelpText(QObject::tr(
"The frequency to start scanning this video source. "
427 "This is then default for 'Full Scan (Tuned)' channel scanning. "
428 "Frequency value in Hz for DVB-T/T2/C, in kHz for DVB-S/S2. "
429 "Leave at 0 if not known. "));
440 setLabel(QObject::tr(
"Network ID"));
443 setHelpText(QObject::tr(
"If your provider has asked you to configure a "
444 "specific network identifier (Network_ID), "
445 "enter it here. Leave it at -1 otherwise."));
457 setLabel(QObject::tr(
"Bouquet ID"));
458 setHelpText(QObject::tr(
"Bouquet ID for Freesat or Sky on satellite Astra-2 28.2E. "
459 "Leave this at 0 if you do not receive this satellite. "
460 "This is needed to get the Freesat and Sky channel numbers. "
461 "Value 272 selects Freesat bouquet 'England HD'. "
462 "See the MythTV Wiki https://www.mythtv.org/wiki/DVB_UK."));
475 setHelpText(QObject::tr(
"Region ID for Freesat or Sky on satellite Astra-2 28.2E. "
476 "Leave this at 0 you do not receive this satellite. "
477 "This is needed to get the Freesat and Sky channel numbers. "
478 "Value 1 selects region London. "
479 "See the MythTV Wiki https://www.mythtv.org/wiki/DVB_UK."));
491 setLabel(QObject::tr(
"Logical Channel Number Offset"));
492 setHelpText(QObject::tr(
"The offset is added to each logical channel number found "
493 "during a scan of a DVB video source. This makes it possible "
494 "to give different video sources a non-overlapping range "
495 "of channel numbers. Leave at 0 if you have only one video source "
496 "or if the video sources do not have DVB logical channel numbers."));
504 setLabel(QObject::tr(
"Channel frequency table"));
510 setHelpText(QObject::tr(
"Use default unless this source uses a "
511 "different frequency table than the system wide table "
512 "defined in the General settings."));
516 m_sourceId(_sourceid)
518 setLabel(QObject::tr(
"Channel frequency table"));
537 "WHERE sourceid = :SOURCEID");
563 LOG(VB_GENERAL, LOG_INFO,
"TransFreqTableSelector::Save(void)");
574 "UPDATE videosource "
575 "SET freqtable = :FREQTABLE "
576 "WHERE sourceid = :SOURCEID");
600 setLabel(QObject::tr(
"Perform EIT scan"));
602 "If enabled, program guide data for channels on this "
603 "source will be updated with data provided by the "
604 "channels themselves 'Over-the-Air'."));
609 const QString& _grabber,
611 m_parent(_parent), m_grabber(_grabber)
615 QString
filename = QString(
"%1/%2.xmltv")
625 config->setHelpText(tr(
"Run XMLTV configure command."));
636 QString err_msg = QObject::tr(
637 "You MUST run 'mythfilldatabase --manual' the first time,\n"
638 "instead of just 'mythfilldatabase'.\nYour grabber does not provide "
639 "channel numbers, so you have to set them manually.");
643 LOG(VB_GENERAL, LOG_ERR, err_msg);
671 label->setValue(QObject::tr(
"Use only the transmitted guide data."));
673 QObject::tr(
"This will usually only work with ATSC or DVB channels, "
674 "and generally provides data only for the next few days."));
693 label->setValue(QObject::tr(
"Do not configure a grabber"));
709 setLabel(QObject::tr(
"Video Source Setup"));
731 const QString &thecardtype)
734 query.
prepare(
"SELECT count(cardtype)"
736 " WHERE capturecard.sourceid = :SOURCEID "
737 " AND capturecard.cardtype = :CARDTYPE ;");
739 query.
bindValue(
":CARDTYPE", thecardtype);
743 int count = query.
value(0).toInt();
755 result.
prepare(
"SELECT name, sourceid FROM videosource;");
759 while (result.
next())
762 source->setLabel(result.
value(0).toString());
763 source->loadByID(result.
value(1).toInt());
772 result.
prepare(
"SELECT name, sourceid FROM videosource;");
776 while (result.
next())
779 result.
value(1).toString());
794 uint minor_max = UINT_MAX,
795 const QString& card = QString(),
796 const QRegularExpression& driver = QRegularExpression()) :
799 setLabel(QObject::tr(
"Video device"));
802 QDir dev(
"/dev/v4l",
"video*", QDir::Name, QDir::System);
804 card, driver,
false);
809 card, driver,
false);
812 dev.setPath(
"/dev/dtv");
814 card, driver,
false);
818 dev.setNameFilters(QStringList(
"dtv*"));
820 card, driver,
false);
828 [[maybe_unused]]
bool absPath =
true)
835 const QString& card,
const QRegularExpression& driver,
836 bool allow_duplicates)
839 QFileInfoList entries = dir.entryInfoList();
840 for (
const auto & fi : std::as_const(entries))
843 QString filepath = fi.absoluteFilePath();
844 int err =
lstat(filepath.toLocal8Bit().constData(), &st);
848 LOG(VB_GENERAL, LOG_ERR,
849 QString(
"Could not stat file: %1").arg(filepath));
854 if (!S_ISCHR(st.st_mode))
859 if (minor_min > minor_num || minor_max < minor_num)
867 QByteArray
tmp = filepath.toLatin1();
868 int videofd = open(
tmp.constData(), O_RDWR);
875 auto match = driver.match(driver_name);
876 if ((!driver.pattern().isEmpty() || match.hasMatch()) &&
877 (card.isEmpty() || (card_name == card)))
909 setLabel(QObject::tr(
"VBI device"));
911 setHelpText(QObject::tr(
"Device to read VBI (captions) from."));
918 QDir dev(
"/dev/v4l",
"vbi*", QDir::Name, QDir::System);
937 [[maybe_unused]]
bool absPath =
true)
943 const QString &driver)
946 QFileInfoList entries = dir.entryInfoList();
947 for (
const auto & fi : std::as_const(entries))
949 QString device = fi.absoluteFilePath();
950 QByteArray adevice = device.toLatin1();
951 int vbifd = open(adevice.constData(), O_RDWR);
958 (driver.isEmpty() || (dn == driver)) &&
959 (card.isEmpty() || (cn == card)))
961 devices.push_back(device);
968 for (
const QString& device : std::as_const(devices))
971 return (
uint) devices.size();
984 setHelpText(QObject::tr(
"Specify the command to run, with any "
985 "needed arguments."));
1008 setLabel(QObject::tr(
"Audio device"));
1010 QDir dev(
"/dev",
"dsp*", QDir::Name, QDir::System);
1012 dev.setPath(
"/dev/sound");
1019 setHelpText(QObject::tr(
"Device to read audio from, "
1020 "if audio is separate from the video."));
1029 std::chrono::milliseconds min_val) :
1032 setLabel(QObject::tr(
"Signal timeout (ms)"));
1035 "Maximum time (in milliseconds) MythTV waits for "
1036 "a signal when scanning for channels."));
1039 template<
typename T,
typename = std::enable_if_t<std::is_
floating_po
int_v<T>> >
1041 SignalTimeout(parent, value, duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1042 template<
typename T,
typename = std::enable_if_t<std::is_
floating_po
int_v<T>> >
1045 duration_cast<
std::chrono::milliseconds>(value),
1046 duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1054 std::chrono::milliseconds min_val) :
1057 setLabel(QObject::tr(
"Tuning timeout (ms)"));
1060 "Maximum time (in milliseconds) MythTV waits for "
1061 "a channel lock. For recordings, if this time is "
1062 "exceeded, the recording will be marked as failed."));
1065 template<
typename T,
typename = std::enable_if_t<std::is_
floating_po
int_v<T>> >
1067 ChannelTimeout(parent, value, duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1068 template<
typename T,
typename = std::enable_if_t<std::is_
floating_po
int_v<T>> >
1070 ChannelTimeout(parent, value, duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1079 setLabel(QObject::tr(
"Force audio sampling rate"));
1081 QObject::tr(
"If non-zero, override the audio sampling "
1082 "rate in the recording profile when this card is "
1083 "used. Use this if your capture card does not "
1084 "support all of the standard rates."));
1099 setLabel(QObject::tr(
"Do not adjust volume"));
1101 QObject::tr(
"Enable this option for budget BT878 based "
1102 "DVB-T cards such as the AverTV DVB-T which "
1103 "require the audio volume to be left alone."));
1113 setLabel(QObject::tr(
"DVB device"));
1115 QObject::tr(
"When you change this setting, the text below "
1116 "should change to the name and type of your card. "
1117 "If the card cannot be opened, an error message "
1118 "will be displayed."));
1136 std::stable_sort(sdevs.begin(), sdevs.end());
1141 QMap<QString,bool> in_use;
1143 for (
const QString& dev : std::as_const(sdevs))
1145 in_use[dev] =
std::find(db.begin(), db.end(), dev) != db.end();
1146 if (sel.isEmpty() && !in_use[dev])
1150 if (sel.isEmpty() && !sdevs.empty())
1153 QString usestr = QString(
" -- ");
1154 usestr += QObject::tr(
"Warning: already in use");
1156 for (
const QString& dev : std::as_const(sdevs))
1158 QString desc = dev + (in_use[dev] ? usestr :
"");
1159 desc = (
current == dev) ? dev : desc;
1183 setLabel(QObject::tr(
"Delivery system"));
1185 QObject::tr(
"If your card supports more than one delivery system "
1186 "then you can select here the one that you want to use."));
1195 setLabel(QObject::tr(
"Frontend ID"));
1197 QObject::tr(
"Identification string reported by the card. "
1198 "If the message \"Could not get card info...\" appears "
1199 "the card can be in use by another program."));
1210 setLabel(QObject::tr(
"Wait for SEQ start header"));
1213 QObject::tr(
"If enabled, drop packets from the start of a DVB "
1214 "recording until a sequence start header is seen."));
1225 setLabel(QObject::tr(
"Open DVB card on demand"));
1228 QObject::tr(
"If enabled, only open the DVB card when required, "
1229 "leaving it free for other programs at other times."));
1240 setLabel(QObject::tr(
"Use DVB card for active EIT scan"));
1243 QObject::tr(
"If enabled, activate active scanning for "
1244 "program data (EIT). When this option is enabled "
1245 "the DVB card is constantly in use."));
1255 setLabel(QObject::tr(
"DVB tuning delay (ms)"));
1258 QObject::tr(
"Some Linux DVB drivers, in particular for the "
1259 "Hauppauge Nova-T, require that we slow down "
1260 "the tuning process by specifying a delay "
1261 "(in milliseconds)."));
1272 #ifdef USING_FIREWIRE
1274 for (
auto & i : list)
1276 QString guid = i.GetGUIDString();
1280 #endif // USING_FIREWIRE
1295 setLabel(QObject::tr(
"Cable box model"));
1296 addSelection(QObject::tr(
"Motorola Generic"),
"MOTO GENERIC");
1297 addSelection(QObject::tr(
"SA/Cisco Generic"),
"SA GENERIC");
1313 QString
help = QObject::tr(
1314 "Choose the model that most closely resembles your set top box. "
1315 "Depending on firmware revision SA4200HD may work better for a "
1322 #ifdef USING_FIREWIRE
1326 #endif // USING_FIREWIRE
1333 #ifdef USING_FIREWIRE
1335 name.replace(
"Scientific-Atlanta",
"SA");
1336 name.replace(
", Inc.",
"");
1337 name.replace(
"Explorer(R)",
"");
1338 name = name.simplified();
1339 setValue((name.isEmpty()) ?
"" : name);
1340 #endif // USING_FIREWIRE
1348 "firewire_connection"))
1350 setLabel(QObject::tr(
"Connection Type"));
1371 #ifdef USING_FIREWIRE
1383 #ifdef USING_LINUX_FIREWIRE
1386 #endif // USING_LINUX_FIREWIRE
1391 model->SetGUID(dev->getValue());
1392 desc->SetGUID(dev->getValue());
1400 #ifdef USING_HDHOMERUN
1434 setLabel(QObject::tr(
"Use HDHomeRun for active EIT scan"));
1437 QObject::tr(
"If enabled, activate active scanning for "
1438 "program data (EIT). When this option is enabled "
1439 "the HDHomeRun is constantly in use."));
1450 setLabel(QObject::tr(
"Use HDHomeRun %1 (%2 %3)")
1451 .arg(deviceid, model, ipaddr));
1454 QObject::tr(
"If enabled, use tuners from this HDHomeRun "
1470 QMap<QString, HDHomeRunDevice>::iterator dit;
1471 for (dit = m_deviceList.begin(); dit != m_deviceList.end(); ++dit)
1483 buttonRecOpt->setLabel(tr(
"Recording Options"));
1484 buttonRecOpt->addChild(
new SignalTimeout(m_parent, 3s, 0.25s));
1498 for (
const auto & dev : std::as_const(devs))
1500 QStringList devinfo = dev.split(
" ");
1501 const QString& devid = devinfo.at(0);
1502 const QString& devip = devinfo.at(1);
1503 const QString& model = devinfo.at(2);
1517 QMap<QString, HDHomeRunDevice>::iterator debugit;
1520 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1: %2 %3")
1521 .arg(debugit.key()).arg((*debugit).model)
1522 .arg((*debugit).cardip));
1529 QStringList devstrs = devices.split(
",");
1530 for (
const QString& devstr : std::as_const(devstrs))
1535 QByteArray ba = devstr.toUtf8();
1536 hdhomerun_device_t *device = hdhomerun_device_create_from_str(
1537 ba.data(),
nullptr);
1540 QString devid = QString(
"%1").arg(
1541 hdhomerun_device_get_device_id(device), 8, 16).toUpper();
1542 hdhomerun_device_destroy(device);
1545 QMap<QString, HDHomeRunDevice>::iterator dit;
1548 (*dit).m_checkbox->setValue(
true);
1556 QStringList devstrs;
1557 QMap<QString, HDHomeRunDevice>::iterator dit;
1560 if ((*dit).m_checkbox->boolValue())
1561 devstrs << (*dit).m_deviceId;
1563 QString devices = devstrs.join(
",");
1575 setLabel(QObject::tr(
"IP Address"));
1576 setHelpText(QObject::tr(
"Device IP or ID of a VBox device. eg. '192.168.1.100' or 'vbox_3718'"));
1606 setHelpText(QObject::tr(
"Number and type of the tuner to use. eg '1-DVBT/T2'."));
1675 m_deviceId(deviceid),
1678 m_cardTuner(cardtuner),
1679 m_deviceList(devicelist),
1682 setLabel(QObject::tr(
"Available devices"));
1685 "Device IP or ID, tuner number and tuner type of available VBox devices."));
1696 std::vector<QString> devs;
1697 QMap<QString, bool> in_use;
1703 devs.push_back(it.key());
1704 in_use[it.key()] = (*it).m_inUse;
1707 QString man_addr = VBoxDeviceIDList::tr(
"Manually Enter IP Address");
1708 QString sel = man_addr;
1709 devs.push_back(sel);
1711 for (
const auto & dev : devs)
1712 sel = (
current == dev) ? dev : sel;
1714 QString usestr = QString(
" -- ");
1715 usestr += QObject::tr(
"Warning: already in use");
1717 for (
const auto & dev : devs)
1719 QString desc = dev + (in_use[dev] ? usestr :
"");
1727 else if (sel == man_addr && !
current.isEmpty())
1730 QStringList selection =
current.split(
"-");
1751 if (v == VBoxDeviceIDList::tr(
"Manually Enter IP Address"))
1756 else if (!v.isEmpty())
1758 if (
m_oldValue == VBoxDeviceIDList::tr(
"Manually Enter IP Address"))
1783 setValue(
"http://mafreebox.freebox.fr/freeboxtv/playlist.m3u");
1786 QObject::tr(
"URL of M3U file containing RTSP/RTP/UDP/HTTP channel URLs,"
1787 " example for HDHomeRun: http://<ipv4>/lineup.m3u and for Freebox:"
1788 " http://mafreebox.freebox.fr/freeboxtv/playlist.m3u."
1807 setLabel(QObject::tr(
"ASI device"));
1825 std::stable_sort(sdevs.begin(), sdevs.end());
1834 QMap<QString,bool> in_use;
1836 for (
const QString& dev : std::as_const(sdevs))
1838 in_use[dev] =
std::find(db.begin(), db.end(), dev) != db.end();
1839 if (sel.isEmpty() && !in_use[dev])
1844 if (sel.isEmpty() && !sdevs.empty())
1847 QString usestr = QString(
" -- ");
1848 usestr += QObject::tr(
"Warning: already in use");
1852 for (
const QString& dev : std::as_const(sdevs))
1854 QString desc = dev + (in_use[dev] ? usestr :
"");
1855 desc = (
current == dev) ? dev : desc;
1857 found |= (dev == sel);
1861 if (!found && !
current.isEmpty())
1863 QString desc =
current +
" -- " +
1864 QObject::tr(
"Warning: unable to open");
1902 if (device.isEmpty())
1919 LOG(VB_GENERAL, LOG_WARNING,
1920 "ASIConfigurationGroup::probeCard(), Warning: " +
error);
1936 device->setHelpText(tr(
"A local file used to simulate a recording."
1937 " Leave empty to use MythEvents to trigger an"
1938 " external program to import recording files."));
1960 QFileInfo fileInfo(device);
1963 if (device.startsWith(
"file:", Qt::CaseInsensitive))
1964 fileInfo.setFile(device.mid(5));
1966 if (fileInfo.exists())
1968 if (fileInfo.isReadable() && (fileInfo.isFile()))
1971 cs = tr(
"%1 MB").arg(fileInfo.size() / 1024 / 1024);
1974 ci = tr(
"File not readable");
1978 ci = tr(
"File %1 does not exist").arg(device);
2000 m_desc->setLabel(tr(
"Description"));
2004 m_deviceId, m_desc, m_cardIp, m_cardTuner, &m_deviceList, m_parent);
2030 for (
const auto & dev : std::as_const(devs))
2032 QStringList devinfo = dev.split(
" ");
2033 const QString&
id = devinfo.at(0);
2034 const QString& ip = devinfo.at(1);
2035 const QString& tunerNo = devinfo.at(2);
2036 const QString& tunerType = devinfo.at(3);
2055 for (
const auto & dev : std::as_const(db))
2057 QMap<QString, VBoxDevice>::iterator dit;
2061 (*dit).m_inUse =
true;
2098 static const QRegularExpression ipV4Regex
2099 {
"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){4}$" };
2100 auto match = ipV4Regex.match(ip +
".");
2101 if (match.hasMatch())
2110 static const QRegularExpression oneDigit {
"^\\d$" };
2111 auto match = oneDigit.match(tuner);
2112 if (match.hasMatch())
2127 static const QRegularExpression newstyle { R
"(^([0-9.]+)-(\d|RTP)\.(\d)$)" };
2128 auto match = newstyle.match(
getValue());
2129 if (match.hasMatch())
2140 desc->setLabel(tr(
"CetonConfigurationGroup",
"Description"));
2142 tr(
"IP Address of the Ceton device (192.168.200.1 by default)"));
2144 tr(
"Number of the tuner on the Ceton device (first tuner is number 0)"));
2180 const QString &inputtype) :
2186 QRegularExpression drv {
"^(?!ivtv|hdpvr|(saa7164(.*))).*$" };
2210 QString cn = tr(
"Failed to open");
2214 QByteArray adevice = device.toLatin1();
2215 int videofd = open(adevice.constData(), O_RDWR);
2219 ci = cn = tr(
"Failed to probe");
2220 else if (!dn.isEmpty())
2221 ci = cn +
" [" + dn +
"]";
2235 QRegularExpression drv {
"^(ivtv|(saa7164(.*)))$" };
2259 QString cn = tr(
"Failed to open");
2263 QByteArray adevice = device.toLatin1();
2264 int videofd = open(adevice.constData(), O_RDWR);
2268 ci = cn = tr(
"Failed to probe");
2269 else if (!dn.isEmpty())
2270 ci = cn +
" [" + dn +
"]";
2286 device->setHelpText(tr(
"A local MPEG file used to simulate a recording."));
2309 QFileInfo fileInfo(device);
2310 if (fileInfo.exists())
2312 if (fileInfo.isReadable() && (fileInfo.isFile()))
2315 cs = tr(
"%1 MB").arg(fileInfo.size() / 1024 / 1024);
2318 ci = tr(
"File not readable");
2322 ci = tr(
"File does not exist");
2329 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2330 ExternalConfigurationGroup::ExternalConfigurationGroup(
CaptureCard &a_parent,
2337 device->setLabel(tr(
"Command path"));
2338 device->setHelpText(tr(
"A 'black box' application controlled via stdin, status on "
2339 "stderr and TransportStream read from stdout.\n"
2340 "Use absolute path or path relative to the current directory."));
2350 this, &ExternalConfigurationGroup::probeApp);
2352 probeApp(device->getValue());
2355 void ExternalConfigurationGroup::probeApp(
const QString & path)
2357 int idx1 = path.startsWith(
"file:", Qt::CaseInsensitive) ? 5 : 0;
2358 int idx2 = path.indexOf(
' ', idx1);
2361 QFileInfo fileInfo(path.mid(idx1, idx2 - idx1));
2363 if (fileInfo.exists())
2365 ci = tr(
"File '%1' is valid.").arg(fileInfo.absoluteFilePath());
2366 if (!fileInfo.isReadable() || !fileInfo.isFile())
2367 ci = tr(
"WARNING: File '%1' is not readable.")
2368 .arg(fileInfo.absoluteFilePath());
2369 if (!fileInfo.isExecutable())
2370 ci = tr(
"WARNING: File '%1' is not executable.")
2371 .arg(fileInfo.absoluteFilePath());
2375 ci = tr(
"WARNING: File '%1' does not exist.")
2376 .arg(fileInfo.absoluteFilePath());
2379 m_info->setValue(ci);
2380 m_info->setHelpText(ci);
2382 #endif // !defined( USING_MINGW ) && !defined( _MSC_VER )
2392 QRegularExpression(
"^hdpvr$"));
2415 QString cn = tr(
"Failed to open");
2419 int videofd = open(device.toLocal8Bit().constData(), O_RDWR);
2423 ci = cn = tr(
"Failed to probe");
2424 else if (!dn.isEmpty())
2425 ci = cn +
" [" + dn +
"]";
2441 setLabel(QObject::tr(
"V4L2 encoder devices (multirec capable)"));
2456 if (!device_name.isEmpty())
2463 QString card_name = tr(
"Failed to open");
2464 QString card_info = card_name;
2483 if (audioinput->fillSelections(device_name) > 1)
2485 audioinput->setName(
"AudioInput");
2496 vbidev->setName(
"VBIDevice");
2507 #endif // USING_V4L2
2512 setLabel(QObject::tr(
"Capture Card Setup"));
2514 auto* cardtype =
new CardType(parent);
2518 cardtype->addTargetedChild(
"DVB",
2523 cardtype->addTargetedChild(
"HDPVR",
2525 #endif // USING_V4L2
2527 #ifdef USING_HDHOMERUN
2528 cardtype->addTargetedChild(
"HDHOMERUN",
2530 #endif // USING_HDHOMERUN
2533 cardtype->addTargetedChild(
"VBOX",
2535 #endif // USING_VBOX
2538 cardtype->addTargetedChild(
"SATIP",
2539 new SatIPConfigurationGroup(parent, *cardtype));
2540 #endif // USING_SATIP
2542 #ifdef USING_FIREWIRE
2544 #endif // USING_FIREWIRE
2548 #endif // USING_CETON
2552 #endif // USING_IPTV
2555 cardtype->addTargetedChild(
"V4L2ENC",
new V4L2encGroup(parent, *cardtype));
2556 cardtype->addTargetedChild(
"V4L",
2558 cardtype->addTargetedChild(
"MJPEG",
2560 cardtype->addTargetedChild(
"GO7007",
2562 cardtype->addTargetedChild(
"MPEG",
2564 #endif // USING_V4L2
2567 cardtype->addTargetedChild(
"ASI",
2572 cardtype->addTargetedChild(
"IMPORT",
2574 cardtype->addTargetedChild(
"DEMO",
2576 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2577 cardtype->addTargetedChild(
"EXTERNAL",
2578 new ExternalConfigurationGroup(parent,
2604 "SELECT cardid, videodevice, cardtype, displayname "
2606 "WHERE hostname = :HOSTNAME AND parentid = 0 "
2620 while (query.
next())
2623 QString videodevice = query.
value(1).toString();
2624 QString cardtype = query.
value(2).toString();
2625 QString displayname = query.
value(3).toString();
2627 QString label = QString(
"%1 (%2)")
2631 card->loadByID(cardid);
2632 card->setLabel(label);
2669 if (dev != init_dev)
2671 if (!init_dev.isEmpty())
2690 for (
uint clone : clones)
2707 setLabel(QObject::tr(
"Card type"));
2708 setHelpText(QObject::tr(
"Change the cardtype to the appropriate type for "
2709 "the capture card you are configuring."));
2717 QObject::tr(
"DVB-T/S/C, ATSC or ISDB-T tuner card"),
"DVB");
2722 QObject::tr(
"V4L2 encoder"),
"V4L2ENC");
2724 QObject::tr(
"HD-PVR H.264 encoder"),
"HDPVR");
2725 #endif // USING_V4L2
2727 #ifdef USING_HDHOMERUN
2729 QObject::tr(
"HDHomeRun networked tuner"),
"HDHOMERUN");
2730 #endif // USING_HDHOMERUN
2734 QObject::tr(
"Sat>IP networked tuner"),
"SATIP");
2735 #endif // USING_SATIP
2739 QObject::tr(
"V@Box TV Gateway networked tuner"),
"VBOX");
2740 #endif // USING_VBOX
2742 #ifdef USING_FIREWIRE
2744 QObject::tr(
"FireWire cable box"),
"FIREWIRE");
2745 #endif // USING_FIREWIRE
2749 QObject::tr(
"Ceton Cablecard tuner"),
"CETON");
2750 #endif // USING_CETON
2753 setting->
addSelection(QObject::tr(
"IPTV recorder"),
"FREEBOX");
2754 #endif // USING_IPTV
2758 QObject::tr(
"Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"),
"MPEG");
2760 QObject::tr(
"Analog to MJPEG encoder card (Matrox G200, DC10, etc)"),
"MJPEG");
2762 QObject::tr(
"Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
2765 QObject::tr(
"Analog capture card"),
"V4L");
2766 #endif // USING_V4L2
2769 setting->
addSelection(QObject::tr(
"DVEO ASI recorder"),
"ASI");
2772 setting->
addSelection(QObject::tr(
"Import test recorder"),
"IMPORT");
2773 setting->
addSelection(QObject::tr(
"Demo test recorder"),
"DEMO");
2774 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2775 setting->
addSelection(QObject::tr(
"External (black box) recorder"),
2786 setLabel(QObject::tr(
"Input name"));
2799 if (storage ==
nullptr)
2806 while (!inputs.isEmpty())
2819 setLabel(QObject::tr(
"Delivery system"));
2821 "This shows the delivery system (modulation), for instance DVB-T2, "
2822 "that you have selected when you configured the capture card. "
2823 "This must be the same as the modulation used by the video source. "));
2835 setLabel(QObject::tr(
"Display name"));
2837 "This name is displayed on screen when Live TV begins "
2838 "and in various other places. Make sure the last two "
2839 "characters are unique for each input or use a "
2840 "slash ('/') to designate the unique portion."));
2866 setLabel(QObject::tr(
"Video source"));
2890 setLabel(QObject::tr(
"Input group") +
2893 "Leave as 'Generic' unless this input is shared with "
2894 "another device. Only one of the inputs in an input "
2895 "group will be allowed to record at any given time."));
2898 void Load(
void)
override;
2923 LOG(VB_GENERAL, LOG_DEBUG, QString(
"InputGroup::Load() %1 %2")
2928 QMap<uint, uint> grpcnt;
2929 std::vector<QString> names;
2930 std::vector<uint> grpid;
2931 std::vector<uint> selected_groupids;
2933 names.push_back(QObject::tr(
"Generic"));
2939 "SELECT cardinputid, inputgroupid, inputgroupname "
2941 "WHERE inputgroupname LIKE 'user:%' "
2942 "ORDER BY inputgroupid, cardinputid, inputgroupname");
2950 while (query.
next())
2953 if ((inputid != 0U) && (query.
value(0).toUInt() == inputid))
2954 selected_groupids.push_back(groupid);
2958 if (grpcnt[groupid] == 1)
2960 names.push_back(query.
value(2).toString().mid(5, -1));
2961 grpid.push_back(groupid);
2972 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Group num: %1 id: %2")
2976 for (
uint i = 0; i < selected_groupids.size(); i++)
2977 msg += QString(
"%1 ").arg(selected_groupids[i]);
2978 LOG(VB_GENERAL, LOG_DEBUG, msg);
2985 for (
size_t i = 0; i < names.size(); i++)
2988 index = (sel) ? i : index;
2991 LOG(VB_GENERAL, LOG_DEBUG, QString(
"grpid %1, name '%2', i %3, s %4")
2992 .arg(grpid[i]).arg(names[i]) .arg(index).arg(sel ?
"T" :
"F"));
2995 addSelection(names[i], QString::number(grpid[i]), sel);
2999 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Group index: %1").arg(index));
3014 setLabel(QObject::tr(
"Use quick tuning"));
3019 "If enabled, MythTV will tune using only the "
3020 "MPEG program number. The program numbers "
3021 "change more often than DVB or ATSC tuning "
3022 "parameters, so this is slightly less reliable. "
3023 "This will also inhibit EIT gathering during "
3024 "Live TV and recording."));
3034 setLabel(QObject::tr(
"External channel change command"));
3036 setHelpText(QObject::tr(
"If specified, this command will be run to "
3037 "change the channel for inputs which have an external "
3038 "tuner device such as a cable box. The first argument "
3039 "will be the channel number."));
3049 setLabel(QObject::tr(
"Preset tuner to channel"));
3051 setHelpText(QObject::tr(
"Leave this blank unless you have an external "
3052 "tuner that is connected to the tuner input of your card. "
3053 "If so, you will need to specify the preset channel for "
3054 "the signal (normally 3 or 4)."));
3061 if (sourceid.isEmpty() || !sourceid.toUInt())
3066 if (storage ==
nullptr)
3073 if (channels.empty())
3076 startChan.isEmpty() ?
"0" : startChan);
3084 bool has_visible =
false;
3085 for (
size_t i = 0; i < channels.size() && !has_visible; i++)
3088 for (
auto & channel : channels)
3090 const QString channum = channel.m_chanNum;
3091 bool sel = channum == startChan;
3092 if (!has_visible || channel.m_visible || sel)
3106 setLabel(QObject::tr(
"Input priority"));
3108 setHelpText(QObject::tr(
"If the input priority is not equal for "
3109 "all inputs, the scheduler may choose to record a show "
3110 "at a later time so that it can record on an input with "
3111 "a higher value."));
3122 setLabel(QObject::tr(
"Schedule order"));
3124 setHelpText(QObject::tr(
"If priorities and other factors are equal "
3125 "the scheduler will choose the available "
3126 "input with the lowest, non-zero value. "
3127 "Setting this value to zero will make the "
3128 "input unavailable to the scheduler."));
3139 setLabel(QObject::tr(
"Live TV order"));
3141 setHelpText(QObject::tr(
"When entering Live TV, the available, local "
3142 "input with the lowest, non-zero value will "
3143 "be used. If no local inputs are available, "
3144 "the available, remote input with the lowest, "
3145 "non-zero value will be used. "
3146 "Setting this value to zero will make the "
3147 "input unavailable to live TV."));
3158 setLabel(QObject::tr(
"Use DishNet long-term EIT data"));
3162 "If you point your satellite dish toward DishNet's birds, "
3163 "you may wish to enable this feature. For best results, "
3164 "enable general EIT collection as well."));
3190 if (
"DVB" == cardtype)
3212 if (
"DVB" == cardtype)
3217 tr(
"Use channel scanner to find channels for this input."));
3220 tr(
"This uses the listings data source to "
3221 "provide the channels for this input.") +
" " +
3222 tr(
"This can take a long time to run."));
3231 interact->setLabel(QObject::tr(
"Interactions between inputs"));
3241 interact->addChild(
new LiveTVOrder(*
this, _cardid));
3245 ingrpbtn->setHelpText(
3246 QObject::tr(
"Input groups are only needed when two or more cards "
3247 "share the same resource such as a FireWire card and "
3248 "an analog card input controlling the same set top box."));
3249 interact->addChild(ingrpbtn);
3255 setObjectName(
"CardInput");
3281 bool enable = (sourceid.toInt() > 0);
3298 auto *settingdialog =
3301 if (settingdialog->Create())
3308 delete settingdialog;
3315 ShowOkPopup(tr(
"Sorry, this Input Group name cannot be blank."));
3319 QString new_name = QString(
"user:") + name;
3322 query.
prepare(
"SELECT inputgroupname "
3324 "WHERE inputgroupname = :GROUPNAME");
3325 query.
bindValue(
":GROUPNAME", new_name);
3335 ShowOkPopup(tr(
"Sorry, this Input Group name is already in use."));
3362 #ifdef USING_BACKEND
3370 LOG(VB_GENERAL, LOG_ERR,
3371 QString(
"Sorry, %1 cards do not yet support scanning.")
3387 if (num_channels_before)
3399 LOG(VB_GENERAL, LOG_ERR,
"You must compile the backend "
3400 "to be able to scan for channels");
3420 cardtype !=
"HDHOMERUN" &&
3421 !num_channels_before)
3423 LOG(VB_GENERAL, LOG_ERR,
"Skipping channel fetch, you need to "
3424 "scan for channels first.");
3433 if (num_channels_before)
3442 QString cardinputidTag(
":WHERECARDID");
3444 QString query(
"cardid = " + cardinputidTag);
3453 QString cardinputidTag(
":SETCARDID");
3456 QString query(
"cardid = " + cardinputidTag +
", " +
3475 query.
prepare(
"SELECT cardid FROM capturecard "
3476 "WHERE cardid = :CARDID AND inputname = :INPUTNAME");
3478 query.
bindValue(
":INPUTNAME", _inputname);
3531 tr(
"Are you sure you want to delete "
3540 tr(
"Are you sure you want to delete "
3541 "ALL capture cards?"),
3549 card->setLabel(tr(
"New capture card"));
3575 "WHERE hostname = :HOSTNAME");
3581 tr(
"Error getting list of cards for this host. "
3582 "Unable to delete capturecards for %1")
3589 while (cards.
next())
3605 AddSelection(QObject::tr(
"(Delete all capture cards on %1)")
3608 AddSelection(QObject::tr(
"(Delete all capture cards)"),
3622 AddSelection(QObject::tr(
"(Delete all video sources)"),
3645 tr(
"Are you sure you want to delete "
3646 "ALL video sources?"),
3664 source->setLabel(tr(
"New video source"));
3686 "SELECT cardid, videodevice, cardtype, displayname "
3688 "WHERE hostname = :HOSTNAME "
3689 " AND parentid = 0 "
3699 while (query.
next())
3702 QString videodevice = query.
value(1).toString();
3703 QString cardtype = query.
value(2).toString();
3704 QString displayname = query.
value(3).toString();
3706 auto *cardinput =
new CardInput(cardtype, videodevice, cardid);
3707 cardinput->loadByID(cardid);
3708 QString inputlabel = QString(
"%1 (%2) -> %3")
3710 displayname, cardinput->getSourceName());
3712 cardinput->setLabel(inputlabel);
3723 QString short_name = name;
3724 if (short_name.startsWith(
"LG Electronics"))
3725 short_name = short_name.right(short_name.length() - 15);
3726 if (short_name.startsWith(
"Oren"))
3727 short_name = short_name.right(short_name.length() - 5);
3728 if (short_name.startsWith(
"Nextwave"))
3729 short_name = short_name.right(short_name.length() - 9);
3730 if (short_name.startsWith(
"frontend", Qt::CaseInsensitive))
3731 short_name = short_name.left(short_name.length() - 9);
3732 if (short_name.endsWith(
"VSB/QAM"))
3733 short_name = short_name.left(short_name.length() - 8);
3734 if (short_name.endsWith(
"VSB"))
3735 short_name = short_name.left(short_name.length() - 4);
3736 if (short_name.endsWith(
"DVB-T"))
3737 short_name = short_name.left(short_name.length() - 6);
3743 short_name = short_name.simplified();
3744 if (short_name.startsWith(
"or51211", Qt::CaseInsensitive))
3745 short_name =
"pcHDTV HD-2000";
3746 else if (short_name.startsWith(
"or51132", Qt::CaseInsensitive))
3747 short_name =
"pcHDTV HD-3000";
3748 else if (short_name.startsWith(
"bcm3510", Qt::CaseInsensitive))
3749 short_name =
"Air2PC v1";
3750 else if (short_name.startsWith(
"nxt2002", Qt::CaseInsensitive) ||
3751 short_name.startsWith(
"nxt200x", Qt::CaseInsensitive))
3752 short_name =
"Air2PC v2";
3753 else if (short_name.startsWith(
"lgdt3302", Qt::CaseInsensitive))
3754 short_name =
"DViCO HDTV3";
3755 else if (short_name.startsWith(
"lgdt3303", Qt::CaseInsensitive))
3756 short_name =
"DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
3781 if (videodevice.isEmpty())
3799 QString err_open = tr(
"Could not open card %1").arg(videodevice);
3800 QString err_other = tr(
"Could not get card info for card %1").arg(videodevice);
3846 if (frontend_name.toLower().indexOf(
"usb") >= 0)
3853 if ((frontend_name ==
"DiBcom 3000P/M-C DVB-T") ||
3855 "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
3860 #if 0 // frontends on hybrid DVB-T/Analog cards
3862 m_buttonAnalog->setVisible(
3863 short_name.startsWith(
"zarlink zl10353",
3864 Qt::CaseInsensitive) ||
3865 short_name.startsWith(
"wintv hvr 900 m/r: 65008/a1c0",
3866 Qt::CaseInsensitive) ||
3867 short_name.startsWith(
"philips tda10046h",
3868 Qt::CaseInsensitive));
3882 if (frontend_name ==
"Nextwave NXT200X VSB/QAM frontend")
3888 #if 0 // frontends on hybrid DVB-T/Analog cards
3889 if (frontend_name.toLower().indexOf(
"usb") < 0)
3891 m_buttonAnalog->setVisible(
3892 short_name.startsWith(
"pchdtv", Qt::CaseInsensitive) ||
3893 short_name.startsWith(
"dvico", Qt::CaseInsensitive) ||
3894 short_name.startsWith(
"nextwave", Qt::CaseInsensitive));
3907 for (
const auto & item : std::as_const(delsyslist))
3909 LOG(VB_GENERAL, LOG_DEBUG, QString(
"DVBCardType: add deliverysystem:%1")
3917 if (!delsys.isEmpty())
3929 QString dev, QString
type) :
3931 m_lastDevice(
std::move(dev)), m_lastCardType(
std::move(
type))
3933 setLabel(QObject::tr(
"Audio input"));
3934 setHelpText(QObject::tr(
"If there is more than one audio input, "
3935 "select which one to use."));
3948 if (device.isEmpty())
3952 QStringList inputs =
3955 for (
uint i = 0; i < (
uint)inputs.size(); i++)
3960 return inputs.size();
4044 explicit DiSEqCPosition(
const CaptureCard &parent,
int value,
int min_val) :
4048 setLabel(QObject::tr(
"DiSEqC position"));
4049 setHelpText(QObject::tr(
"Position of the LNB on the DiSEqC switch. "
4050 "Leave at 1 if there is no DiSEqC switch "
4051 "and the LNB is directly connected to the SatIP server. "
4052 "This value is used as signal source (attribute src) in "
4053 "the SatIP tune command."));
4058 SatIPConfigurationGroup::SatIPConfigurationGroup
4066 m_friendlyName =
new SatIPDeviceAttribute(tr(
"Friendly name"), tr(
"Friendly name of the Sat>IP server"));
4067 m_tunerType =
new SatIPDeviceAttribute(tr(
"Tuner type"), tr(
"Type of the selected tuner"));
4068 m_tunerIndex =
new SatIPDeviceAttribute(tr(
"Tuner index"), tr(
"Index of the tuner on the Sat>IP server"));
4069 m_deviceId =
new SatIPDeviceID(
m_parent);
4071 m_deviceIdList =
new SatIPDeviceIDList(
4072 m_deviceId, m_friendlyName, m_tunerType, m_tunerIndex, &m_deviceList,
m_parent);
4084 connect(m_deviceIdList, &SatIPDeviceIDList::NewTuner,
4085 m_deviceId, &SatIPDeviceID::SetTuner);
4088 void SatIPConfigurationGroup::FillDeviceList(
void)
4090 m_deviceList.clear();
4096 for (
const auto & dev : std::as_const(devs))
4098 QStringList devparts = dev.split(
" ");
4099 const QString&
id = devparts.value(0);
4100 const QString& name = devparts.value(1);
4101 const QString& ip = devparts.value(2);
4102 const QString& tunerno = devparts.value(3);
4103 const QString& tunertype = devparts.value(4);
4106 device.m_deviceId = id;
4107 device.m_cardIP = ip;
4108 device.m_inUse =
false;
4109 device.m_friendlyName = name;
4110 device.m_tunerNo = tunerno;
4111 device.m_tunerType = tunertype;
4112 device.m_mythDeviceId = QString(
"%1:%2:%3").arg(
id, tunertype, tunerno);
4114 QString friendlyIdentifier = QString(
"%1, %2, Tuner #%3").arg(name, tunertype, tunerno);
4116 m_deviceList[device.m_mythDeviceId] = device;
4118 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"SatIP: Add %1 '%2' '%3'")
4119 .arg(device.m_mythDeviceId, device.m_friendlyName, friendlyIdentifier));
4125 for (
const auto& dev : std::as_const(db))
4127 auto dit = m_deviceList.find(dev);
4128 if (dit != m_deviceList.end())
4130 (*dit).m_inUse =
true;
4135 SatIPDeviceIDList::SatIPDeviceIDList(
4136 SatIPDeviceID *deviceId,
4137 SatIPDeviceAttribute *friendlyName,
4138 SatIPDeviceAttribute *tunerType,
4139 SatIPDeviceAttribute *tunerIndex,
4140 SatIPDeviceList *deviceList,
4142 m_deviceId(deviceId),
4143 m_friendlyName(friendlyName),
4144 m_tunerType(tunerType),
4145 m_tunerIndex(tunerIndex),
4146 m_deviceList(deviceList),
4150 setHelpText(tr(
"Device IP or ID, tuner number and tuner type of available Sat>IP device"));
4153 this, &SatIPDeviceIDList::UpdateDevices);
4156 void SatIPDeviceIDList::Load(
void)
4160 int cardid = m_parent.getCardID();
4163 fillSelections(device);
4166 void SatIPDeviceIDList::UpdateDevices(
const QString &v)
4168 SatIPDevice dev = (*m_deviceList)[v];
4169 m_deviceId->setValue(dev.m_mythDeviceId);
4170 m_friendlyName->setValue(dev.m_friendlyName);
4171 m_tunerType->setValue(dev.m_tunerType);
4172 m_tunerIndex->setValue(dev.m_tunerNo);
4175 void SatIPDeviceIDList::fillSelections(
const QString &cur)
4179 std::vector<QString> names;
4180 std::vector<QString> devs;
4181 QMap<QString, bool> in_use;
4186 SatIPDeviceList::iterator it = m_deviceList->begin();
4187 for(; it != m_deviceList->end(); ++it)
4189 QString friendlyIdentifier = QString(
"%1, %2, Tuner #%3")
4190 .arg((*it).m_friendlyName, (*it).m_tunerType, (*it).m_tunerNo);
4191 names.push_back(friendlyIdentifier);
4193 devs.push_back(it.key());
4194 in_use[it.key()] = (*it).m_inUse;
4197 for (
const auto& it2s : devs)
4199 sel = (
current == it2s) ? it2s : sel;
4202 QString usestr = QString(
" -- ");
4203 usestr += tr(
"Warning: already in use");
4205 for (
uint i = 0; i < devs.size(); ++i)
4207 const QString dev = devs[i];
4208 const QString name = names[i];
4209 bool dev_in_use = (dev == sel) ?
false : in_use[devs[i]];
4210 QString desc = name + (dev_in_use ? usestr :
"");
4211 addSelection(desc, dev, dev == sel);
4215 SatIPDeviceID::SatIPDeviceID(
const CaptureCard &parent) :
4225 void SatIPDeviceID::Load(
void)
4230 void SatIPDeviceID::SetTuner(
const QString &tuner)
4235 SatIPDeviceAttribute::SatIPDeviceAttribute(
const QString& label,
const QString& helptext)
4238 setHelpText(helptext);
4240 #endif // USING_SATIP