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