7 #include <QDomDocument> 17 #define LOC QString("VBox: ") 19 #define QUERY_BOARDINFO "http://{URL}/cgi-bin/HttpControl/HttpControlApp?OPTION=1&Method=QueryBoardInfo" 20 #define QUERY_CHANNELS "http://{URL}/cgi-bin/HttpControl/HttpControlApp?OPTION=1&Method=GetXmltvChannelsList"\ 21 "&FromChIndex=FirstChannel&ToChIndex=LastChannel&FilterBy=All" 23 #define SEARCH_TIME 3000 24 #define VBOX_URI "urn:schemas-upnp-org:device:MediaServer:1" 43 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Using UPNP to search for Vboxes (%1 secs)")
44 .arg(milliSeconds / 1000));
52 while (totalTime.
elapsed() < milliSeconds)
54 std::this_thread::sleep_for(std::chrono::milliseconds(25));
55 int ttl = milliSeconds - totalTime.
elapsed();
56 if ((searchTime.
elapsed() > 249) && (ttl > 1000))
58 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"UPNP Search %1 secs")
76 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"No UPnP VBoxes found");
80 int count = vboxes->
Count();
83 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
84 QString(
"Found %1 possible VBoxes").arg(count));
88 LOG(VB_GENERAL, LOG_ERR,
LOC +
89 "No UPnP VBoxes found, but SSDP::Find() not NULL");
95 EntryMap::const_iterator it = map.begin();
96 for (; it != map.end(); ++it)
101 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"GetDeviceDesc() failed for %1").arg(BE->
GetFriendlyName()));
109 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Found possible VBox at %1 (%2:%3)").arg(friendlyName).arg(ip).arg(port));
111 if (friendlyName.startsWith(
"VBox"))
115 int startPos = friendlyName.indexOf(
'(');
116 int endPos = friendlyName.indexOf(
')');
118 if (startPos != -1 && endPos != -1)
119 id = friendlyName.mid(startPos + 1, endPos - startPos - 1);
130 for (
int x = 0; x < tuners.count(); x++)
134 const QString& tuner = tuners.at(x);
135 QString device = QString(
"%1 %2 %3").arg(
id).arg(ip).arg(tuner);
137 LOG(VB_GENERAL, LOG_INFO, QString(
"Found VBox - %1").arg(device));
156 QStringList devItems = dev.split(
"-");
158 if (devItems.size() != 3)
160 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Got malformed videodev %1").arg(dev));
164 QString
id = devItems.at(0).trimmed();
167 QRegExp ipRegExp(
"[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}");
168 if (
id.indexOf(ipRegExp) == 0)
174 for (
int x = 0; x < vboxes.count(); x++)
176 QStringList vboxItems = vboxes.at(x).split(
" ");
177 if (vboxItems.size() != 4)
179 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Got malformed probed device %1").arg(vboxes.at(x)));
183 const QString& vboxID = vboxItems.at(0);
184 QString vboxIP = vboxItems.at(1);
196 auto *xmlDoc =
new QDomDocument();
199 query.replace(
"{URL}",
m_url);
219 QStringList sList = requiredVersion.split(
'.');
222 if (sList.count() < 3 || !requiredVersion.startsWith(
"V"))
224 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Failed to parse required version from %1").arg(requiredVersion));
229 int requiredMajor = sList[1].toInt();
230 int requiredMinor = sList[2].toInt();
236 QDomElement elem = xmlDoc->documentElement();
245 if (sList.count() < 3 || !(
version.startsWith(
"VB.") ||
version.startsWith(
"VJ.")))
247 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Failed to parse version from %1").arg(
version));
252 major = sList[1].toInt();
253 minor = sList[2].toInt();
260 if (major < requiredMajor)
263 if (major == requiredMajor &&
minor < requiredMinor)
275 QDomElement elem = xmlDoc->documentElement();
281 for (
int x = 1; x <= noTuners; x++)
283 QString tuner =
getStrValue(elem, QString(
"Tuner%1").arg(x));
284 QString s = QString(
"%1 %2").arg(x).arg(tuner);
298 auto *xmlDoc =
new QDomDocument();
301 query.replace(
"{URL}",
m_url);
310 QDomNodeList chanNodes = xmlDoc->elementsByTagName(
"channel");
312 for (
int x = 0; x < chanNodes.count(); x++)
314 QDomElement chanElem = chanNodes.at(x).toElement();
315 QString xmltvid = chanElem.attribute(
"id",
"UNKNOWN_ID");
316 QString name =
getStrValue(chanElem,
"display-name", 0);
317 QString chanType =
getStrValue(chanElem,
"display-name", 1);
318 QString triplet =
getStrValue(chanElem,
"display-name", 2);
319 bool fta = (
getStrValue(chanElem,
"display-name", 3) ==
"Free");
320 QString lcn =
getStrValue(chanElem,
"display-name", 4);
321 uint serviceID = triplet.right(4).toUInt(
nullptr, 16);
323 QString transType =
"UNKNOWN";
324 QStringList slist = triplet.split(
'-');
325 uint networkID = slist[2].left(4).toUInt(
nullptr, 16);
326 uint transportID = slist[2].mid(4, 4).toUInt(
nullptr, 16);
327 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"NIT/TID/SID %1 %2 %3)").arg(networkID).arg(transportID).arg(serviceID));
331 if (slist.count() == 3)
332 transType = slist[0];
335 QDomNodeList iconNodes = chanElem.elementsByTagName(
"icon");
336 if (iconNodes.count())
338 QDomElement iconElem = iconNodes.at(0).toElement();
339 icon = iconElem.attribute(
"src",
"");
343 QDomNodeList urlNodes = chanElem.elementsByTagName(
"url");
344 if (urlNodes.count())
346 QDomElement urlElem = urlNodes.at(0).toElement();
347 url = urlElem.attribute(
"src",
"");
350 VBoxChannelInfo chanInfo(name, xmltvid, url, fta, chanType, transType, serviceID, networkID, transportID);
351 result->insert(lcn, chanInfo);
368 if (!xmlDoc->setContent(result,
false, &errorMsg, &errorLine, &errorColumn))
370 LOG(VB_GENERAL, LOG_ERR,
LOC +
371 QString(
"Error parsing: %1\nat line: %2 column: %3 msg: %4").
372 arg(query).arg(errorLine).arg(errorColumn).arg(errorMsg));
377 QDomNodeList statusNodes = xmlDoc->elementsByTagName(
"Status");
379 if (!statusNodes.count())
380 statusNodes = xmlDoc->elementsByTagName(
"Error");
382 if (statusNodes.count())
384 QDomElement elem = statusNodes.at(0).toElement();
388 QString errorDesc =
getStrValue(elem,
"ErrorDescription");
393 LOG(VB_GENERAL, LOG_ERR,
LOC +
394 QString(
"API Error: %1 - %2, Query was: %3").arg(errorCode).arg(errorDesc).arg(query));
406 QDomNodeList nodes = element.elementsByTagName(name);
407 if (!nodes.isEmpty())
409 if (index >= nodes.count())
411 QDomElement e = nodes.at(index).toElement();
422 return value.toInt();
427 for (QDomNode dname = element.firstChild(); !dname.isNull();
428 dname = dname.nextSibling())
430 QDomText
t = dname.toText();
static QString getFirstText(QDomElement &element)
A QElapsedTimer based timer to replace use of QTime as a timer.
#define VBOX_MIN_API_VERSION
bool checkVersion(QString &version)
static QString getIPFromVideoDevice(const QString &dev)
QString GetFriendlyName(void)
void GetEntryMap(EntryMap &)
Returns a copy of the EntryMap.
void PerformSearch(const QString &sST, uint timeout_secs=2)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
UPnpDeviceDesc * GetDeviceDesc(void)
QMap< QString, VBoxChannelInfo > vbox_chan_map_t
QMap< QString, DeviceLocation * > EntryMap
Key == Unique Service Name (USN)
static QString getStrValue(QDomElement &element, const QString &name, int index=0)
static QStringList probeDevices(void)
#define LOG(_MASK_, _LEVEL_, _STRING_)
static int getIntValue(QDomElement &element, const QString &name, int index=0)
int elapsed(void)
Returns milliseconds elapsed since last start() or restart()
vbox_chan_map_t * getChannels(void)
bool checkConnection(void)
static QStringList doUPNPSearch(void)
static SSDPCacheEntries * Find(const QString &sURI)
QDomDocument * getBoardInfo(void)
void start(void)
starts measuring elapsed time.
QStringList getTuners(void)
returns a list of tuners in the format 'TUNERNO TUNERTYPE' eg '1 DVBT/T2'
static bool sendQuery(const QString &query, QDomDocument *xmlDoc)