MythTV  master
externrecscanner.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"
16 
17 #include "cardutil.h"
18 #include "channelutil.h"
19 #include "externrecscanner.h"
21 #include "scanmonitor.h"
22 
23 #define LOC QString("ExternRecChanFetch: ")
24 
26  QString inputname,
27  uint sourceid,
28  ScanMonitor *monitor)
29  : m_scanMonitor(monitor)
30  , m_cardId(cardid)
31  , m_inputName(std::move(inputname))
32  , m_sourceId(sourceid)
33  , m_thread(new MThread("ExternRecChannelScanner", this))
34 {
35  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Has ScanMonitor %1")
36  .arg(monitor ? "true" : "false"));
37 }
38 
40 {
41  Stop();
42  delete m_thread;
43  m_thread = nullptr;
44 }
45 
50 {
51  m_lock.lock();
52 
53  while (m_threadRunning)
54  {
55  m_stopNow = true;
56  m_lock.unlock();
57  m_thread->wait(5ms);
58  m_lock.lock();
59  }
60 
61  m_lock.unlock();
62 
63  m_thread->wait();
64 }
65 
68 {
69  Stop();
70  m_stopNow = false;
71  m_thread->start();
72 }
73 
75 {
76  m_lock.lock();
77  m_threadRunning = true;
78  m_lock.unlock();
79 
80 
81  // Step 1/4 : Get info from DB
82  QString cmd = CardUtil::GetVideoDevice(m_cardId);
83 
84  if (m_stopNow || cmd.isEmpty())
85  {
86  LOG(VB_CHANNEL, LOG_INFO, LOC + "Invalid external command");
87  QMutexLocker locker(&m_lock);
88  m_threadRunning = false;
89  m_stopNow = true;
90  return;
91  }
92 
93  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("External Command: '%1'").arg(cmd));
94 
95 
96  // Step 2/4 : Download
97  if (m_scanMonitor)
98  {
100  m_scanMonitor->ScanAppendTextToLog(tr("Creating channel list"));
101  }
102 
104 
105  m_channelTotal = fetch.LoadChannels();
106  if (m_channelTotal < 1)
107  {
108  LOG(VB_CHANNEL, LOG_ERR, LOC + "Failed to load channels");
109  QMutexLocker locker(&m_lock);
110  m_threadRunning = false;
111  m_stopNow = true;
112  return;
113  }
114 
115  std::vector<uint> existing = ChannelUtil::GetChanIDs(m_sourceId);
116  std::vector<uint>::iterator Iold;
117 
118  // Step 3/4 : Process
119  if (m_scanMonitor)
120  m_scanMonitor->ScanAppendTextToLog(tr("Processing channels"));
121 
122  QString channum;
123  QString name;
124  QString callsign;
125  QString xmltvid;
126  QString icon;
127  int atsc_major = 0;
128  int atsc_minor = 0;
129  int cnt = 0;
130 
131  if (!fetch.FirstChannel(channum, name, callsign, xmltvid, icon))
132  {
133  LOG(VB_CHANNEL, LOG_WARNING, LOC + "No channels found.");
134  QMutexLocker locker(&m_lock);
135  m_threadRunning = false;
136  m_stopNow = true;
137  return;
138  }
139 
140  if (m_scanMonitor)
141  m_scanMonitor->ScanAppendTextToLog(tr("Adding Channels"));
142 
143  uint idx = 0;
144  for (;;)
145  {
146  static const QRegularExpression digitRE { "\\D+" };
147  QString msg = tr("Channel #%1 : %2").arg(channum, name);
148  QStringList digits = channum.split(digitRE);
149 
150  if (digits.size() > 1)
151  {
152  atsc_major = digits.at(0).toInt();
153  atsc_minor = digits.at(1).toInt();
154  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
155  QString("ATSC: %1.%2").arg(atsc_major).arg(atsc_minor));
156  }
157  else
158  {
159  atsc_major = atsc_minor = 0;
160  }
161 
162  LOG(VB_CHANNEL, LOG_INFO, QString("Handling channel %1 %2")
163  .arg(channum, name));
164 
165  int chanid = ChannelUtil::GetChanID(m_sourceId, channum);
166 
167  if (m_scanMonitor)
169 
170  if (chanid <= 0)
171  {
172  if (m_scanMonitor)
173  m_scanMonitor->ScanAppendTextToLog(tr("Adding %1").arg(msg));
174 
175  chanid = ChannelUtil::CreateChanID(m_sourceId, channum);
176  ChannelUtil::CreateChannel(0, m_sourceId, chanid, callsign, name,
177  channum, 1, atsc_major, atsc_minor,
178  false, kChannelVisible, QString(),
179  icon, "Default", xmltvid);
180  }
181  else
182  {
183  if (m_scanMonitor)
184  m_scanMonitor->ScanAppendTextToLog(tr("Updating %1").arg(msg));
185 
186  ChannelUtil::UpdateChannel(0, m_sourceId, chanid, callsign, name,
187  channum, 1, atsc_major, atsc_minor,
188  false, kChannelVisible, QString(),
189  icon, "Default", xmltvid);
190  }
191 
193 
194  Iold = std::find(existing.begin(), existing.end(), chanid);
195  if (Iold != existing.end())
196  {
197  existing.erase(Iold);
198  }
199 
200  if (++idx < m_channelTotal)
201  fetch.NextChannel(channum, name, callsign, xmltvid, icon);
202  else
203  break;
204  }
205 
206  // Remove any channels which are no longer valid
207  for (Iold = existing.begin(); Iold != existing.end(); ++Iold)
208  {
209  channum = ChannelUtil::GetChanNum(*Iold);
210 
211  if (m_scanMonitor)
213  (tr("Removing unused Channel #%1").arg(channum));
214 
216  }
217 
218  // Step 4/4 : Finish up
219  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Found %1 channels").arg(cnt));
220  if (m_scanMonitor)
222  (tr("Found %1 channels.").arg(cnt));
223 
224  if (m_scanMonitor)
225  {
226  m_scanMonitor->ScanAppendTextToLog(tr("Done"));
230  }
231 
232  QMutexLocker locker(&m_lock);
233  m_threadRunning = false;
234  m_stopNow = true;
235 }
236 
238 {
239  uint minval = 35;
240  uint range = 70 - minval;
241  uint pct = minval + (uint) truncf((((float)val) / m_channelCnt) * range);
242  if (m_scanMonitor)
244 }
245 
247 {
248  uint minval = 70;
249  uint range = 100 - minval;
250  uint pct = minval + (uint) truncf((((float)val) / m_channelCnt) * range);
251  if (m_scanMonitor)
253 }
254 
255 void ExternRecChannelScanner::SetMessage(const QString &status)
256 {
257  if (m_scanMonitor)
259 }
260 
261 /* vim: set expandtab tabstop=4 shiftwidth=4: */
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
LOC
#define LOC
Definition: externrecscanner.cpp:23
ExternRecChannelScanner::~ExternRecChannelScanner
~ExternRecChannelScanner() override
Definition: externrecscanner.cpp:39
ExternRecChannelScanner::Stop
void Stop(void)
Stops the scanning thread running.
Definition: externrecscanner.cpp:49
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
ChannelUtil::DeleteChannel
static bool DeleteChannel(uint channel_id)
Definition: channelutil.cpp:1787
ExternRecChannelScanner::m_lock
QMutex m_lock
Definition: externrecscanner.h:52
ScanMonitor::ScanPercentComplete
void ScanPercentComplete(int pct)
Definition: scanmonitor.cpp:103
ExternRecChannelScanner::m_channelTotal
uint m_channelTotal
Definition: externrecscanner.h:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
ExternRecChannelScanner::m_sourceId
uint m_sourceId
Definition: externrecscanner.h:46
ExternRecChannelScanner::m_thread
MThread * m_thread
Definition: externrecscanner.h:51
ExternRecChannelScanner::m_stopNow
bool m_stopNow
Definition: externrecscanner.h:50
ExternRecChannelScanner::m_scanMonitor
ScanMonitor * m_scanMonitor
Definition: externrecscanner.h:43
scanmonitor.h
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
ExternRecChannelScanner::SetNumChannelsParsed
void SetNumChannelsParsed(uint val)
Definition: externrecscanner.cpp:237
ExternRecChannelScanner::m_channelCnt
uint m_channelCnt
Definition: externrecscanner.h:48
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
ChannelUtil::CreateChanID
static int CreateChanID(uint sourceid, const QString &chan_num)
Creates a unique channel ID for database use.
Definition: channelutil.cpp:1448
ExternRecChannelScanner::ExternRecChannelScanner
ExternRecChannelScanner(uint cardid, QString inputname, uint sourceid, ScanMonitor *monitor=nullptr)
Definition: externrecscanner.cpp:25
uint
unsigned int uint
Definition: compat.h:81
ExternRecChannelScanner::Scan
void Scan(void)
Scans the list.
Definition: externrecscanner.cpp:67
ScanMonitor::ScanAppendTextToLog
void ScanAppendTextToLog(const QString &status)
Definition: scanmonitor.cpp:109
ExternalRecChannelFetcher::LoadChannels
int LoadChannels(void)
Definition: ExternalRecChannelFetcher.cpp:126
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
ExternRecChannelScanner::m_cardId
uint m_cardId
Definition: externrecscanner.h:44
channelutil.h
ExternalRecChannelFetcher
Definition: ExternalRecChannelFetcher.h:26
ExternRecChannelScanner::SetMessage
void SetMessage(const QString &status)
Definition: externrecscanner.cpp:255
ExternalRecChannelFetcher.h
ExternalRecChannelFetcher::NextChannel
bool NextChannel(QString &channum, QString &name, QString &callsign, QString &xmltvid, QString &icon)
Definition: ExternalRecChannelFetcher.h:44
kChannelVisible
@ kChannelVisible
Definition: channelinfo.h:23
cardutil.h
ExternalRecChannelFetcher::FirstChannel
bool FirstChannel(QString &channum, QString &name, QString &callsign, QString &xmltvid, QString &icon)
Definition: ExternalRecChannelFetcher.h:35
ScanMonitor::ScanComplete
void ScanComplete(void)
Definition: scanmonitor.cpp:98
std
Definition: mythchrono.h:23
mythcontext.h
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
ExternRecChannelScanner::run
void run(void) override
Definition: externrecscanner.cpp:74
ExternRecChannelScanner::SetNumChannelsInserted
void SetNumChannelsInserted(uint val)
Definition: externrecscanner.cpp:246
externrecscanner.h
ChannelUtil::GetChanNum
static QString GetChanNum(int chan_id)
Returns the channel-number string of the given channel.
Definition: channelutil.cpp:777
ChannelUtil::GetChanIDs
static std::vector< uint > GetChanIDs(int sourceid=-1, bool onlyVisible=false)
Definition: channelutil.cpp:2179
ExternRecChannelScanner::m_threadRunning
bool m_threadRunning
Definition: externrecscanner.h:49
ScanMonitor
Definition: scanmonitor.h:44
find
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
Definition: dvbstreamhandler.cpp:363
CardUtil::GetVideoDevice
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:294