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 
7 // Qt headers
8 #include <QFile>
9 #include <QTextStream>
10 
11 // MythTV headers
12 #include "mythcontext.h"
13 #include "cardutil.h"
14 #include "channelutil.h"
15 #include "externrecscanner.h"
16 #include "scanmonitor.h"
17 #include "mythlogging.h"
19 
20 #define LOC QString("ExternRecChanFetch: ")
21 
23  const QString &inputname,
24  uint sourceid,
25  ScanMonitor *monitor)
26  : m_scan_monitor(monitor)
27  , m_cardid(cardid)
28  , m_inputname(inputname)
29  , m_sourceid(sourceid)
30  , m_thread(new MThread("ExternRecChannelScanner", this))
31 {
32  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Has ScanMonitor %1")
33  .arg(monitor ? "true" : "false"));
34 }
35 
37 {
38  Stop();
39  delete m_thread;
40  m_thread = nullptr;
41 }
42 
47 {
48  m_lock.lock();
49 
50  while (m_thread_running)
51  {
52  m_stop_now = true;
53  m_lock.unlock();
54  m_thread->wait(5);
55  m_lock.lock();
56  }
57 
58  m_lock.unlock();
59 
60  m_thread->wait();
61 }
62 
65 {
66  Stop();
67  m_stop_now = false;
68  m_thread->start();
69 }
70 
72 {
73  m_lock.lock();
74  m_thread_running = true;
75  m_lock.unlock();
76 
77 
78  // Step 1/4 : Get info from DB
79  QString cmd = CardUtil::GetVideoDevice(m_cardid);
80 
81  if (m_stop_now || cmd.isEmpty())
82  {
83  LOG(VB_CHANNEL, LOG_INFO, LOC + "Invalid external command");
84  QMutexLocker locker(&m_lock);
85  m_thread_running = false;
86  m_stop_now = true;
87  return;
88  }
89 
90  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("External Command: '%1'").arg(cmd));
91 
92 
93  // Step 2/4 : Download
94  if (m_scan_monitor)
95  {
97  m_scan_monitor->ScanAppendTextToLog(tr("Creating channel list"));
98  }
99 
101 
102  if ((m_channel_total = fetch.LoadChannels()) < 1)
103  {
104  LOG(VB_CHANNEL, LOG_ERR, LOC + "Failed to load channels");
105  QMutexLocker locker(&m_lock);
106  m_thread_running = false;
107  m_stop_now = true;
108  return;
109  }
110 
111  vector<uint> existing = ChannelUtil::GetChanIDs(m_sourceid);
112  vector<uint>::iterator Iold;
113 
114  // Step 3/4 : Process
115  if (m_scan_monitor)
116  m_scan_monitor->ScanAppendTextToLog(tr("Processing channels"));
117 
118  QString channum;
119  QString name;
120  QString callsign;
121  QString xmltvid;
122  int cnt = 0;
123 
124  if (!fetch.FirstChannel(channum, name, callsign, xmltvid))
125  {
126  LOG(VB_CHANNEL, LOG_WARNING, LOC + "No channels found.");
127  QMutexLocker locker(&m_lock);
128  m_thread_running = false;
129  m_stop_now = true;
130  return;
131  }
132 
133  if (m_scan_monitor)
134  m_scan_monitor->ScanAppendTextToLog(tr("Adding Channels"));
135 
136  uint idx = 0;
137  for (;;)
138  {
139  QString msg = tr("Channel #%1 : %2").arg(channum).arg(name);
140 
141  LOG(VB_CHANNEL, LOG_INFO, QString("Handling channel %1 %2")
142  .arg(channum).arg(name));
143 
144  int chanid = ChannelUtil::GetChanID(m_sourceid, channum);
145 
146  if (m_scan_monitor)
148 
149  if (chanid <= 0)
150  {
151  if (m_scan_monitor)
152  m_scan_monitor->ScanAppendTextToLog(tr("Adding %1").arg(msg));
153 
154  chanid = ChannelUtil::CreateChanID(m_sourceid, channum);
155  ChannelUtil::CreateChannel(0, m_sourceid, chanid, callsign, name,
156  channum, 1, 0, 0,
157  false, false, false, QString(),
158  QString(), "Default", xmltvid);
159  }
160  else
161  {
162  if (m_scan_monitor)
163  m_scan_monitor->ScanAppendTextToLog(tr("Updating %1").arg(msg));
164 
165  ChannelUtil::UpdateChannel(0, m_sourceid, chanid, callsign, name,
166  channum, 1, 0, 0,
167  false, false, false, QString(),
168  QString(), "Default", xmltvid);
169  }
170 
172 
173  if ((Iold = std::find(existing.begin(), existing.end(), chanid)) !=
174  existing.end())
175  {
176  existing.erase(Iold);
177  }
178 
179  if (++idx < m_channel_total)
180  fetch.NextChannel(channum, name, callsign, xmltvid);
181  else
182  break;
183  }
184 
185  // Remove any channels which are no longer valid
186  for (Iold = existing.begin(); Iold != existing.end(); ++Iold)
187  {
188  channum = ChannelUtil::GetChanNum(*Iold);
189 
190  if (m_scan_monitor)
192  (tr("Removing unused Channel #%1").arg(channum));
193 
195  }
196 
197  // Step 4/4 : Finish up
198  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Found %1 channels").arg(cnt));
199  if (m_scan_monitor)
201  (tr("Found %1 channels.").arg(cnt));
202 
203  if (m_scan_monitor)
204  {
205  m_scan_monitor->ScanAppendTextToLog(tr("Done"));
209  }
210 
211  QMutexLocker locker(&m_lock);
212  m_thread_running = false;
213  m_stop_now = true;
214 }
215 
217 {
218  uint minval = 35, range = 70 - minval;
219  uint pct = minval + (uint) truncf((((float)val) / m_channel_cnt) * range);
220  if (m_scan_monitor)
222 }
223 
225 {
226  uint minval = 70, range = 100 - minval;
227  uint pct = minval + (uint) truncf((((float)val) / m_channel_cnt) * range);
228  if (m_scan_monitor)
230 }
231 
232 void ExternRecChannelScanner::SetMessage(const QString &status)
233 {
234  if (m_scan_monitor)
236 }
237 
238 /* vim: set expandtab tabstop=4 shiftwidth=4: */
ScanMonitor * m_scan_monitor
void start(QThread::Priority=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:294
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, bool hidden, bool hidden_in_guide, const QString &freqid, QString icon=QString(), QString format="Default", QString xmltvid=QString(), QString default_authority=QString())
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:46
bool FirstChannel(QString &channum, QString &name, QString &callsign, QString &xmltvid)
void SetNumChannelsInserted(uint val)
ExternRecChannelScanner(uint cardid, const QString &inputname, uint sourceid, ScanMonitor *monitor=nullptr)
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)
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:311
void ScanPercentComplete(int pct)
unsigned int uint
Definition: compat.h:140
void run(void) override
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
#define LOC
void ScanAppendTextToLog(const QString &status)
const char * name
Definition: ParseText.cpp:328
static int CreateChanID(uint sourceid, const QString &chan_num)
Creates a unique channel ID for database use.
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, bool hidden, bool hidden_in_guide, const QString &freqid=QString(), const QString &icon=QString(), QString format=QString(), const QString &xmltvid=QString(), const QString &default_authority=QString())
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:273
void SetMessage(const QString &status)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
void Scan(void)
Scans the list.
static vector< uint > GetChanIDs(int sourceid=-1, bool onlyVisible=false)
void ScanComplete(void)
Definition: scanmonitor.cpp:98
void Stop(void)
Stops the scanning thread running.
static QString GetChanNum(int chan_id)
Returns the channel-number string of the given channel.
static bool DeleteChannel(uint channel_id)
void SetNumChannelsParsed(uint val)
bool NextChannel(QString &channum, QString &name, QString &callsign, QString &xmltvid)