MythTV  master
iptvchannelfetcher.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 // Std C headers
4 #include <cmath>
5 #include <unistd.h>
6 #include <utility>
7 
8 // Qt headers
9 #include <QFile>
10 #include <QRegularExpression>
11 #include <QTextStream>
12 
13 // MythTV headers
14 #include "libmyth/mythcontext.h"
17 
18 #include "cardutil.h"
19 #include "channelutil.h"
20 #include "iptvchannelfetcher.h"
21 #include "scanmonitor.h"
22 
23 #define LOC QString("IPTVChanFetch: ")
24 
25 static bool parse_chan_info(const QString &rawdata,
26  IPTVChannelInfo &info,
27  QString &channum,
28  int &nextChanNum,
29  uint &lineNum);
30 
31 static bool parse_extinf(const QString &line,
32  QString &channum,
33  QString &name,
34  int &nextChanNum);
35 
37  uint cardid, QString inputname, uint sourceid,
38  bool is_mpts, ScanMonitor *monitor) :
39  m_scanMonitor(monitor),
40  m_cardId(cardid), m_inputName(std::move(inputname)),
41  m_sourceId(sourceid), m_isMpts(is_mpts),
42  m_thread(new MThread("IPTVChannelFetcher", this))
43 {
44  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Has ScanMonitor %1")
45  .arg(monitor?"true":"false"));
46 }
47 
49 {
50  Stop();
51  delete m_thread;
52  m_thread = nullptr;
53 }
54 
59 {
60  m_lock.lock();
61 
62  while (m_threadRunning)
63  {
64  m_stopNow = true;
65  m_lock.unlock();
66  m_thread->wait(5ms);
67  m_lock.lock();
68  }
69 
70  m_lock.unlock();
71 
72  m_thread->wait();
73 }
74 
76 {
77  while (!m_thread->isFinished())
78  m_thread->wait(500ms);
79 
80  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Found %1 channels")
81  .arg(m_channels.size()));
82  return m_channels;
83 }
84 
87 {
88  Stop();
89  m_stopNow = false;
90  m_thread->start();
91 }
92 
94 {
95  m_lock.lock();
96  m_threadRunning = true;
97  m_lock.unlock();
98 
99  // Step 1/4 : Get info from DB
100  QString url = CardUtil::GetVideoDevice(m_cardId);
101 
102  if (m_stopNow || url.isEmpty())
103  {
104  LOG(VB_CHANNEL, LOG_INFO, LOC + "Playlist URL was empty");
105  QMutexLocker locker(&m_lock);
106  m_threadRunning = false;
107  m_stopNow = true;
108  return;
109  }
110 
111  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Playlist URL: %1").arg(url));
112 
113  // Step 2/4 : Download
114  if (m_scanMonitor)
115  {
117  m_scanMonitor->ScanAppendTextToLog(tr("Downloading Playlist"));
118  }
119 
120  QString playlist = DownloadPlaylist(url);
121 
122  if (m_stopNow || playlist.isEmpty())
123  {
124  if (playlist.isNull() && m_scanMonitor)
125  {
127  QCoreApplication::translate("(Common)", "Error"));
129  m_scanMonitor->ScanErrored(tr("Downloading Playlist Failed"));
130  }
131  QMutexLocker locker(&m_lock);
132  m_threadRunning = false;
133  m_stopNow = true;
134  return;
135  }
136 
137  // Step 3/4 : Process
138  if (m_scanMonitor)
139  {
141  m_scanMonitor->ScanAppendTextToLog(tr("Processing Playlist"));
142  }
143 
144  m_channels.clear();
145  m_channels = ParsePlaylist(playlist, this);
146 
147  // Step 4/4 : Finish up
148  if (m_scanMonitor)
149  m_scanMonitor->ScanAppendTextToLog(tr("Adding Channels"));
151 
152  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Found %1 channels")
153  .arg(m_channels.size()));
154 
155  if (!m_isMpts)
156  {
157  fbox_chan_map_t::const_iterator it = m_channels.cbegin();
158  for (uint i = 1; it != m_channels.cend(); ++it, ++i)
159  {
160  const QString& channum = it.key();
161  QString name = (*it).m_name;
162  QString xmltvid = (*it).m_xmltvid.isEmpty() ? "" : (*it).m_xmltvid;
163  uint programnumber = (*it).m_programNumber;
164  //: %1 is the channel number, %2 is the channel name
165  QString msg = tr("Channel #%1 : %2").arg(channum, name);
166 
167  LOG(VB_CHANNEL, LOG_INFO, QString("Handling channel %1 %2")
168  .arg(channum, name));
169 
170  int chanid = ChannelUtil::GetChanID(m_sourceId, channum);
171  if (chanid <= 0)
172  {
173  if (m_scanMonitor)
174  {
175  m_scanMonitor->ScanAppendTextToLog(tr("Adding %1").arg(msg));
176  }
177  chanid = ChannelUtil::CreateChanID(m_sourceId, channum);
178  ChannelUtil::CreateChannel(0, m_sourceId, chanid, name, name,
179  channum, programnumber, 0, 0,
180  false, kChannelVisible, QString(),
181  QString(), "Default", xmltvid);
182  ChannelUtil::CreateIPTVTuningData(chanid, (*it).m_tuning);
183  }
184  else
185  {
186  if (m_scanMonitor)
187  {
189  tr("Updating %1").arg(msg));
190  }
191  ChannelUtil::UpdateChannel(0, m_sourceId, chanid, name, name,
192  channum, programnumber, 0, 0,
193  false, kChannelVisible, QString(),
194  QString(), "Default", xmltvid);
195  ChannelUtil::UpdateIPTVTuningData(chanid, (*it).m_tuning);
196  }
197 
199  }
200 
201  if (m_scanMonitor)
202  {
203  m_scanMonitor->ScanAppendTextToLog(tr("Done"));
207  }
208  }
209 
210  QMutexLocker locker(&m_lock);
211  m_threadRunning = false;
212  m_stopNow = true;
213 }
214 
216 {
217  uint minval = 35;
218  uint range = 70 - minval;
219  uint pct = minval + (uint) truncf((((float)val) / m_chanCnt) * range);
220  if (m_scanMonitor)
222 }
223 
225 {
226  uint minval = 70;
227  uint range = 100 - minval;
228  uint pct = minval + (uint) truncf((((float)val) / m_chanCnt) * range);
229  if (m_scanMonitor)
231 }
232 
233 void IPTVChannelFetcher::SetMessage(const QString &status)
234 {
235  if (m_scanMonitor)
237 }
238 
239 // This function is always called from a thread context.
240 QString IPTVChannelFetcher::DownloadPlaylist(const QString &url)
241 {
242  if (url.startsWith("file", Qt::CaseInsensitive))
243  {
244  QString ret = "";
245  QUrl qurl(url);
246  QFile file(qurl.toLocalFile());
247  if (!file.open(QIODevice::ReadOnly))
248  {
249  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Opening '%1'")
250  .arg(qurl.toLocalFile()) + ENO);
251  return ret;
252  }
253 
254  QTextStream stream(&file);
255  while (!stream.atEnd())
256  ret += stream.readLine() + "\n";
257 
258  file.close();
259  return ret;
260  }
261 
262  // Use MythDownloadManager for http URLs
263  QByteArray data;
264  QString tmp;
265 
266  if (!GetMythDownloadManager()->download(url, &data))
267  {
268  LOG(VB_GENERAL, LOG_INFO, LOC +
269  QString("DownloadPlaylist failed to "
270  "download from %1").arg(url));
271  }
272  else
273  tmp = QString(data);
274 
275  return tmp.isNull() ? tmp : QString::fromUtf8(tmp.toLatin1().constData());
276 }
277 
278 static uint estimate_number_of_channels(const QString &rawdata)
279 {
280  uint result = 0;
281  uint numLine = 1;
282  while (true)
283  {
284  QString url = rawdata.section("\n", numLine, numLine, QString::SectionSkipEmpty);
285  if (url.isEmpty())
286  return result;
287 
288  ++numLine;
289  if (!url.startsWith("#")) // ignore comments
290  ++result;
291  }
292 }
293 
295  const QString &reallyrawdata, IPTVChannelFetcher *fetcher)
296 {
297  fbox_chan_map_t chanmap;
298  int nextChanNum = 1;
299 
300  QString rawdata = reallyrawdata;
301  rawdata.replace("\r\n", "\n");
302 
303  // Verify header is ok
304  QString header = rawdata.section("\n", 0, 0);
305  if (!header.startsWith("#EXTM3U"))
306  {
307  LOG(VB_GENERAL, LOG_ERR, LOC +
308  QString("Invalid channel list header (%1)").arg(header));
309 
310  if (fetcher)
311  {
312  fetcher->SetMessage(
313  tr("ERROR: M3U channel list is malformed"));
314  }
315 
316  return chanmap;
317  }
318 
319  // estimate number of channels
320  if (fetcher)
321  {
322  uint num_channels = estimate_number_of_channels(rawdata);
323  fetcher->SetTotalNumChannels(num_channels);
324 
325  LOG(VB_CHANNEL, LOG_INFO, LOC +
326  QString("Estimating there are %1 channels in playlist")
327  .arg(num_channels));
328  }
329 
330  // get the next available channel number for the source (only used if we can't find one in the playlist)
331  if (fetcher)
332  {
333  MSqlQuery query(MSqlQuery::InitCon());
334  QString sql = "select MAX(CONVERT(channum, UNSIGNED INTEGER)) from channel where sourceid = :SOURCEID;";
335 
336  query.prepare(sql);
337  query.bindValue(":SOURCEID", fetcher->m_sourceId);
338 
339  if (!query.exec())
340  {
341  MythDB::DBError("Get next max channel number", query);
342  }
343  else
344  {
345  if (query.first())
346  {
347  nextChanNum = query.value(0).toInt() + 1;
348  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Next available channel number from DB is: %1").arg(nextChanNum));
349  }
350  else
351  {
352  nextChanNum = 1;
353  LOG(VB_GENERAL, LOG_INFO, LOC + QString("No channels found for this source, using default channel number: %1").arg(nextChanNum));
354  }
355  }
356  }
357 
358  // Parse each channel
359  uint lineNum = 1;
360  for (uint i = 1; true; ++i)
361  {
362  IPTVChannelInfo info;
363  QString channum;
364 
365  if (!parse_chan_info(rawdata, info, channum, nextChanNum, lineNum))
366  break;
367 
368  QString msg = tr("Encountered malformed channel");
369  if (!channum.isEmpty())
370  {
371  chanmap[channum] = info;
372 
373  msg = QString("Parsing Channel #%1 : %2 : %3")
374  .arg(channum, info.m_name,
375  info.m_tuning.GetDataURL().toString());
376  LOG(VB_CHANNEL, LOG_INFO, LOC + msg);
377 
378  msg.clear(); // don't tell fetcher
379  }
380 
381  if (fetcher)
382  {
383  if (!msg.isEmpty())
384  fetcher->SetMessage(msg);
385  fetcher->SetNumChannelsParsed(i);
386  }
387  }
388 
389  return chanmap;
390 }
391 
392 static bool parse_chan_info(const QString &rawdata,
393  IPTVChannelInfo &info,
394  QString &channum,
395  int &nextChanNum,
396  uint &lineNum)
397 {
398  // #EXTINF:0,2 - France 2 <-- duration,channum - channame
399  // #EXTMYTHTV:xmltvid=C2.telepoche.com <-- optional line (myth specific)
400  // #EXTMYTHTV:bitrate=BITRATE <-- optional line (myth specific)
401  // #EXTMYTHTV:fectype=FECTYPE <-- optional line (myth specific)
402  // The FECTYPE can be rfc2733, rfc5109, or smpte2022
403  // #EXTMYTHTV:fecurl0=URL <-- optional line (myth specific)
404  // #EXTMYTHTV:fecurl1=URL <-- optional line (myth specific)
405  // #EXTMYTHTV:fecbitrate0=BITRATE <-- optional line (myth specific)
406  // #EXTMYTHTV:fecbitrate1=BITRATE <-- optional line (myth specific)
407  // #EXTVLCOPT:program=program_number <-- optional line (used by MythTV and VLC)
408  // #... <-- ignored comments
409  // rtsp://maiptv.iptv.fr/iptvtv/201 <-- url
410 
411  QString name;
412  QMap<QString,QString> values;
413 
414  while (true)
415  {
416  QString line = rawdata.section("\n", lineNum, lineNum, QString::SectionSkipEmpty);
417  if (line.isEmpty())
418  return false;
419 
420  ++lineNum;
421  if (line.startsWith("#"))
422  {
423  if (line.startsWith("#EXTINF:"))
424  {
425  parse_extinf(line.mid(line.indexOf(':')+1), channum, name, nextChanNum);
426  }
427  else if (line.startsWith("#EXTMYTHTV:"))
428  {
429  QString data = line.mid(line.indexOf(':')+1);
430  QString key = data.left(data.indexOf('='));
431  if (!key.isEmpty())
432  {
433  if (key == "name")
434  name = data.mid(data.indexOf('=')+1);
435  else if (key == "channum")
436  channum = data.mid(data.indexOf('=')+1);
437  else
438  values[key] = data.mid(data.indexOf('=')+1);
439  }
440  }
441  else if (line.startsWith("#EXTVLCOPT:program="))
442  {
443  values["programnumber"] = line.mid(line.indexOf('=')+1);
444  }
445  continue;
446  }
447 
448  if (name.isEmpty())
449  return false;
450 
451  LOG(VB_GENERAL, LOG_INFO, LOC +
452  QString("parse_chan_info name='%2'").arg(name));
453  LOG(VB_GENERAL, LOG_INFO, LOC +
454  QString("parse_chan_info channum='%2'").arg(channum));
455  for (auto it = values.cbegin(); it != values.cend(); ++it)
456  {
457  LOG(VB_GENERAL, LOG_INFO, LOC +
458  QString("parse_chan_info [%1]='%2'")
459  .arg(it.key(), *it));
460  }
461  info = IPTVChannelInfo(
462  name, values["xmltvid"],
463  line, values["bitrate"].toUInt(),
464  values["fectype"],
465  values["fecurl0"], values["fecbitrate0"].toUInt(),
466  values["fecurl1"], values["fecbitrate1"].toUInt(),
467  values["programnumber"].toUInt());
468  return true;
469  }
470 }
471 
472 static bool parse_extinf(const QString &line,
473  QString &channum,
474  QString &name,
475  int &nextChanNum)
476 {
477  // Parse extension portion, Freebox or SAT>IP format
478  static const QRegularExpression chanNumName1
479  { R"(^-?\d+,(\d+)(?:\.\s|\s-\s)(.*)$)" };
480  auto match = chanNumName1.match(line);
481  if (match.hasMatch())
482  {
483  channum = match.captured(1);
484  name = match.captured(2);
485  return true;
486  }
487 
488  // Parse extension portion, A1 TV format
489  static const QRegularExpression chanNumName2
490  { "^-?\\d+\\s+[^,]*tvg-num=\"(\\d+)\"[^,]*,(.*)$" };
491  match = chanNumName2.match(line);
492  if (match.hasMatch())
493  {
494  channum = match.captured(1);
495  name = match.captured(2);
496  return true;
497  }
498 
499  // Parse extension portion, Moviestar TV number then name
500  static const QRegularExpression chanNumName3
501  { R"(^-?\d+,\[(\d+)\]\s+(.*)$)" };
502  match = chanNumName3.match(line);
503  if (match.hasMatch())
504  {
505  channum = match.captured(1);
506  name = match.captured(2);
507  return true;
508  }
509 
510  // Parse extension portion, Moviestar TV name then number
511  static const QRegularExpression chanNumName4
512  { R"(^-?\d+,(.*)\s+\[(\d+)\]$)" };
513  match = chanNumName4.match(line);
514  if (match.hasMatch())
515  {
516  channum = match.captured(2);
517  name = match.captured(1);
518  return true;
519  }
520 
521  // Parse extension portion, russion iptv plugin style
522  static const QRegularExpression chanNumName5
523  { R"(^(-?\d+)\s+[^,]*,\s*(.*)$)" };
524  match = chanNumName5.match(line);
525  if (match.hasMatch())
526  {
527  channum = match.captured(1).simplified();
528  name = match.captured(2).simplified();
529  bool ok = false;
530  int channel_number = channum.toInt (&ok);
531  if (ok && (channel_number > 0))
532  {
533  return true;
534  }
535  }
536 
537  // Parse extension, HDHomeRun style
538  // EG. #EXTINF:-1 channel-id="22" channel-number="22" tvg-name="Omroep Brabant",22 Omroep Brabant
539  // #EXTINF:-1 channel-id="2.1" channel-number="2.1" tvg-name="CBS2-HD",2.1 CBS2-HD
540  static const QRegularExpression chanNumName6
541  { R"(^-?\d+\s+channel-id=\"([^\"]+)\"\s+channel-number=\"([^\"]+)\"\s+tvg-name=\"([^\"]+)\".*$)" };
542  match = chanNumName6.match(line);
543  if (match.hasMatch())
544  {
545  channum = match.captured(2).simplified();
546  name = match.captured(3).simplified();
547  if (!channum.isEmpty() && !name.isEmpty())
548  {
549  return true;
550  }
551  }
552 
553  // Parse extension portion, https://github.com/iptv-org/iptv/blob/master/channels/ style
554  // EG. #EXTINF:-1 tvg-id="" tvg-name="" tvg-logo="https://i.imgur.com/VejnhiB.png" group-title="News",BBC News
555  static const QRegularExpression chanNumName7
556  { "(^-?\\d+)\\s+[^,]*[^,]*,(.*)$" };
557  match = chanNumName7.match(line);
558  if (match.hasMatch())
559  {
560  channum = match.captured(1).simplified();
561  name = match.captured(2).simplified();
562 
563  bool ok = false;
564  int channel_number = channum.toInt(&ok);
565  if (ok && channel_number > 0)
566  {
567  if (channel_number >= nextChanNum)
568  nextChanNum = channel_number + 1;
569  return true;
570  }
571 
572  // no valid channel number found use the default next one
573  LOG(VB_GENERAL, LOG_ERR, QString("No channel number found, using next available: %1 for channel: %2").arg(nextChanNum).arg(name));
574  channum = QString::number(nextChanNum);
575  nextChanNum++;
576  return true;
577  }
578 
579  // not one of the formats we support
580  QString msg = LOC + QString("Invalid header in channel list line \n\t\t\tEXTINF:%1").arg(line);
581  LOG(VB_GENERAL, LOG_ERR, msg);
582  return false;
583 }
584 
585 /* vim: set expandtab tabstop=4 shiftwidth=4: */
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
IPTVChannelFetcher::m_sourceId
uint m_sourceId
Definition: iptvchannelfetcher.h:94
IPTVChannelFetcher::m_channels
fbox_chan_map_t m_channels
Definition: iptvchannelfetcher.h:96
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
IPTVChannelInfo::m_name
QString m_name
Definition: iptvchannelfetcher.h:57
IPTVChannelFetcher::m_cardId
uint m_cardId
Definition: iptvchannelfetcher.h:92
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
IPTVChannelFetcher::m_thread
MThread * m_thread
Definition: iptvchannelfetcher.h:100
parse_extinf
static bool parse_extinf(const QString &line, QString &channum, QString &name, int &nextChanNum)
Definition: iptvchannelfetcher.cpp:472
IPTVChannelFetcher::SetNumChannelsInserted
void SetNumChannelsInserted(uint val)
Definition: iptvchannelfetcher.cpp:224
ScanMonitor::ScanPercentComplete
void ScanPercentComplete(int pct)
Definition: scanmonitor.cpp:103
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
IPTVChannelFetcher::SetMessage
void SetMessage(const QString &status)
Definition: iptvchannelfetcher.cpp:233
IPTVChannelFetcher::m_threadRunning
bool m_threadRunning
Definition: iptvchannelfetcher.h:98
IPTVTuningData::GetDataURL
QUrl GetDataURL(void) const
Definition: iptvtuningdata.h:139
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
parse_chan_info
static bool parse_chan_info(const QString &rawdata, IPTVChannelInfo &info, QString &channum, int &nextChanNum, uint &lineNum)
Definition: iptvchannelfetcher.cpp:392
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
IPTVChannelFetcher::Scan
void Scan(void)
Scans the given frequency list.
Definition: iptvchannelfetcher.cpp:86
build_compdb.file
file
Definition: build_compdb.py:55
IPTVChannelFetcher::IPTVChannelFetcher
IPTVChannelFetcher(uint cardid, QString inputname, uint sourceid, bool is_mpts, ScanMonitor *monitor=nullptr)
Definition: iptvchannelfetcher.cpp:36
IPTVChannelFetcher::run
void run(void) override
Definition: iptvchannelfetcher.cpp:93
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
ScanMonitor::ScanErrored
void ScanErrored(const QString &error)
Definition: scanmonitor.cpp:128
scanmonitor.h
IPTVChannelFetcher::Stop
void Stop(void)
Stops the scanning thread running.
Definition: iptvchannelfetcher.cpp:58
ChannelUtil::GetChanID
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
Definition: channelutil.cpp:1312
mythlogging.h
IPTVChannelFetcher::m_chanCnt
uint m_chanCnt
Definition: iptvchannelfetcher.h:97
IPTVChannelInfo
Definition: iptvchannelfetcher.h:26
MSqlQuery::first
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
Definition: mythdbcon.cpp:823
LOC
#define LOC
Definition: iptvchannelfetcher.cpp:23
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
ChannelUtil::UpdateChannel
static bool UpdateChannel(uint db_mplexid, uint source_id, uint channel_id, const QString &callsign, const QString &service_name, const QString &chan_num, uint service_id, uint atsc_major_channel, uint atsc_minor_channel, bool use_on_air_guide, ChannelVisibleType visible, const QString &freqid=QString(), const QString &icon=QString(), QString format=QString(), const QString &xmltvid=QString(), const QString &default_authority=QString(), uint service_type=0, int recpriority=INT_MIN, int tmOffset=INT_MIN, int commMethod=INT_MIN)
Definition: channelutil.cpp:1573
IPTVChannelFetcher
Definition: iptvchannelfetcher.h:64
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
ChannelUtil::CreateChanID
static int CreateChanID(uint sourceid, const QString &chan_num)
Creates a unique channel ID for database use.
Definition: channelutil.cpp:1448
MThread::isFinished
bool isFinished(void) const
Definition: mthread.cpp:258
uint
unsigned int uint
Definition: compat.h:81
ScanMonitor::ScanAppendTextToLog
void ScanAppendTextToLog(const QString &status)
Definition: scanmonitor.cpp:109
ChannelUtil::CreateChannel
static bool CreateChannel(uint db_mplexid, uint db_sourceid, uint new_channel_id, const QString &callsign, const QString &service_name, const QString &chan_num, uint service_id, uint atsc_major_channel, uint atsc_minor_channel, bool use_on_air_guide, ChannelVisibleType visible, const QString &freqid, const QString &icon=QString(), QString format="Default", const QString &xmltvid=QString(), const QString &default_authority=QString(), uint service_type=0, int recpriority=0, int tmOffset=0, int commMethod=-1)
Definition: channelutil.cpp:1485
channelutil.h
IPTVChannelFetcher::m_lock
QMutex m_lock
Definition: iptvchannelfetcher.h:101
kChannelVisible
@ kChannelVisible
Definition: channelinfo.h:23
cardutil.h
ScanMonitor::ScanComplete
void ScanComplete(void)
Definition: scanmonitor.cpp:98
ChannelUtil::CreateIPTVTuningData
static bool CreateIPTVTuningData(uint channel_id, const IPTVTuningData &tuning)
Definition: channelutil.h:155
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:889
std
Definition: mythchrono.h:23
IPTVChannelFetcher::m_scanMonitor
ScanMonitor * m_scanMonitor
Definition: iptvchannelfetcher.h:91
mythcontext.h
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
IPTVChannelFetcher::m_isMpts
bool m_isMpts
Definition: iptvchannelfetcher.h:95
IPTVChannelFetcher::~IPTVChannelFetcher
~IPTVChannelFetcher() override
Definition: iptvchannelfetcher.cpp:48
IPTVChannelFetcher::GetChannels
fbox_chan_map_t GetChannels(void)
Definition: iptvchannelfetcher.cpp:75
IPTVChannelFetcher::m_stopNow
bool m_stopNow
Definition: iptvchannelfetcher.h:99
estimate_number_of_channels
static uint estimate_number_of_channels(const QString &rawdata)
Definition: iptvchannelfetcher.cpp:278
IPTVChannelFetcher::DownloadPlaylist
static QString DownloadPlaylist(const QString &url)
Definition: iptvchannelfetcher.cpp:240
mythdownloadmanager.h
iptvchannelfetcher.h
fbox_chan_map_t
QMap< QString, IPTVChannelInfo > fbox_chan_map_t
Definition: iptvchannelfetcher.h:62
IPTVChannelInfo::m_tuning
IPTVTuningData m_tuning
Definition: iptvchannelfetcher.h:60
ScanMonitor
Definition: scanmonitor.h:44
IPTVChannelFetcher::SetTotalNumChannels
void SetTotalNumChannels(uint val)
Definition: iptvchannelfetcher.h:82
IPTVChannelFetcher::SetNumChannelsParsed
void SetNumChannelsParsed(uint val)
Definition: iptvchannelfetcher.cpp:215
CardUtil::GetVideoDevice
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:294
IPTVChannelFetcher::ParsePlaylist
static MTV_PUBLIC fbox_chan_map_t ParsePlaylist(const QString &rawdata, IPTVChannelFetcher *fetcher=nullptr)
Definition: iptvchannelfetcher.cpp:294
ChannelUtil::UpdateIPTVTuningData
static bool UpdateIPTVTuningData(uint channel_id, const IPTVTuningData &tuning)
Definition: channelutil.cpp:1729
GetMythDownloadManager
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
Definition: mythdownloadmanager.cpp:145
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:838