MythTV  master
vboxchannelfetcher.cpp
Go to the documentation of this file.
1 // Std C headers
2 #include <cmath>
3 #include <unistd.h>
4 #include <utility>
5 
6 // Qt headers
7 #include <QFile>
8 #include <QTextStream>
9 
10 // MythTV headers
13 #include "cardutil.h"
14 #include "channelutil.h"
15 #include "libmyth/mythcontext.h"
16 #include "recorders/vboxutils.h"
17 #include "scanmonitor.h"
18 #include "vboxchannelfetcher.h"
19 
20 #define LOC QString("VBoxChanFetch: ")
21 
22 VBoxChannelFetcher::VBoxChannelFetcher(uint cardid, QString inputname, uint sourceid,
23  bool ftaOnly, ServiceRequirements serviceType,
24  ScanMonitor *monitor) :
25  m_scanMonitor(monitor),
26  m_cardId(cardid), m_inputName(std::move(inputname)),
27  m_sourceId(sourceid), m_ftaOnly(ftaOnly),
28  m_serviceType(serviceType),
29  m_thread(new MThread("VBoxChannelFetcher", this))
30 {
31  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Has ScanMonitor %1")
32  .arg(monitor?"true":"false"));
33 
34  // videoDev is of the form xx.xx.xx.xx-n-t or xxxxxxx-n-t
35  QString videoDev = CardUtil::GetVideoDevice(cardid);
36  QStringList list = videoDev.split('-');
37  if (list.count() == 3)
38  {
39  const QString& tunerType = list.at(2);
40  if (tunerType == "DVBT")
41  m_transType = "T";
42  else if (tunerType == "DVBT/T2")
43  m_transType = "T2";
44  else if (tunerType == "DVBS")
45  m_transType = "S";
46  else if (tunerType == "DVBS/S2")
47  m_transType = "S2";
48  else if (tunerType == "DVBC")
49  m_transType = "C";
50  else if (tunerType == "ATSC")
51  m_transType = "A";
52  }
53 
54  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("VideoDevice is: %1, tunerType is: %2")
55  .arg(videoDev, m_transType));
56 }
57 
59 {
60  Stop();
61  delete m_thread;
62  m_thread = nullptr;
63  delete m_channels;
64  m_channels = nullptr;
65 }
66 
71 {
72  m_lock.lock();
73 
74  while (m_threadRunning)
75  {
76  m_stopNow = true;
77  m_lock.unlock();
78  m_thread->wait(5ms);
79  m_lock.lock();
80  }
81 
82  m_lock.unlock();
83 
84  m_thread->wait();
85 }
86 
88 {
89  while (!m_thread->isFinished())
90  m_thread->wait(500ms);
91 
92  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Found %1 channels")
93  .arg(m_channels->size()));
94  return *m_channels;
95 }
96 
98 {
99  Stop();
100  m_stopNow = false;
101  m_thread->start();
102 }
103 
105 {
106  m_lock.lock();
107  m_threadRunning = true;
108  m_lock.unlock();
109 
110  // Step 1/3 : Get the IP of the VBox to query
111  QString dev = CardUtil::GetVideoDevice(m_cardId);
112  QString ip = VBox::getIPFromVideoDevice(dev);
113 
114  if (m_stopNow || ip.isEmpty())
115  {
116  LOG(VB_CHANNEL, LOG_INFO, LOC +
117  QString("Failed to get IP address from videodev (%1)").arg(dev));
118  QMutexLocker locker(&m_lock);
119  m_threadRunning = false;
120  m_stopNow = true;
121  return;
122  }
123 
124  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("VBox IP: %1").arg(ip));
125 
126  // Step 2/3 : Download
127  if (m_scanMonitor)
128  {
130  m_scanMonitor->ScanAppendTextToLog(tr("Downloading Channel List"));
131  }
132 
133  delete m_channels;
134 
135  VBox *vbox = new VBox(ip);
136  m_channels = vbox->getChannels();
137  delete vbox;
138 
139  if (m_stopNow || !m_channels)
140  {
141  if (!m_channels && m_scanMonitor)
142  {
143  m_scanMonitor->ScanAppendTextToLog(QCoreApplication::translate("(Common)", "Error"));
145  m_scanMonitor->ScanErrored(tr("Downloading Channel List Failed"));
146  }
147  QMutexLocker locker(&m_lock);
148  m_threadRunning = false;
149  m_stopNow = true;
150  return;
151  }
152 
153  // Step 3/3 : Process
154  if (m_scanMonitor)
155  {
157  m_scanMonitor->ScanAppendTextToLog(tr("Adding Channels"));
158  }
159 
161 
162  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Found %1 channels")
163  .arg(m_channels->size()));
164 
165  // add the channels to the DB
166  vbox_chan_map_t::const_iterator it = m_channels->cbegin();
167  for (uint i = 1; it != m_channels->cend(); ++it, ++i)
168  {
169  const QString& channum = it.key();
170  QString name = (*it).m_name;
171  QString xmltvid = (*it).m_xmltvid.isEmpty() ? "" : (*it).m_xmltvid;
172  uint serviceID = (*it).m_serviceID;
173  bool fta = (*it).m_fta;
174  QString chanType = (*it).m_channelType;
175  QString transType = (*it).m_transType;
176  uint networkID = (*it).m_networkID;
177  uint transportID = (*it).m_transportID;
178 
179  //: %1 is the channel number, %2 is the channel name
180  QString msg = tr("Channel #%1 : %2").arg(channum, name);
181 
182  LOG(VB_CHANNEL, LOG_INFO, QString("Handling channel %1 %2")
183  .arg(channum, name));
184  uint mplexID = 0;
185  if (m_ftaOnly && !fta)
186  {
187  // ignore this encrypted channel
188  if (m_scanMonitor)
189  {
190  m_scanMonitor->ScanAppendTextToLog(tr("Ignoring Encrypted %1")
191  .arg(msg));
192  }
193  }
194  else if (chanType == "Radio" && m_serviceType != kRequireAudio)
195  {
196  // ignore this radio channel
197  if (m_scanMonitor)
198  {
199  m_scanMonitor->ScanAppendTextToLog(tr("Ignoring Radio %1")
200  .arg(msg));
201  }
202  }
203  else if (!SupportedTransmission(transType))
204  {
205  // ignore this channel
206  if (m_scanMonitor)
207  {
208  m_scanMonitor->ScanAppendTextToLog(tr("Ignoring Bad Transmission Type %1").arg(msg));
209  }
210  }
211  else
212  {
213  int chanid = ChannelUtil::GetChanID(m_sourceId, channum);
214 
215  if (chanid <= 0)
216  {
217  if (m_scanMonitor)
218  {
219  m_scanMonitor->ScanAppendTextToLog(tr("Adding %1").arg(msg));
220  }
221  chanid = ChannelUtil::CreateChanID(m_sourceId, channum);
222 
223  // mplexID will be created if necessary
224  // inversion, bandwidth, transmission_mode, polarity, hierarchy, mod_sys and roll_off are given values, but not used
225  // this is to ensure services API Channel/GetVideoMultiplexList returns a valid list
226  mplexID = ChannelUtil::CreateMultiplex(m_sourceId, "dvb", 0, QString(), transportID, networkID, 0,
227  'a', 'v', 'a', 'a', QString(), QString(), 'a', QString(),
228  QString(), QString(), "UNDEFINED", "0.35");
229 
230  ChannelUtil::CreateChannel(mplexID, m_sourceId, chanid, name, name,
231  channum, serviceID, 0, 0,
232  false, kChannelVisible, QString(),
233  QString(), "Default", xmltvid);
234 
235  ChannelUtil::CreateIPTVTuningData(chanid, (*it).m_tuning);
236  }
237  else
238  {
239  if (m_scanMonitor)
240  {
241  m_scanMonitor->ScanAppendTextToLog(tr("Updating %1").arg(msg));
242  }
243 
244  // mplexID will be created if necessary
245  mplexID = ChannelUtil::CreateMultiplex(m_sourceId, "dvb", 0, QString(), transportID, networkID, 0,
246  'a', 'v', 'a', 'a', QString(), QString(), 'a', QString(),
247  QString(), QString(), "UNDEFINED", "0.35");
248 
249  // xmltvid parameter is set to null, user may have changed it, so do not overwrite as we are only updating
250  ChannelUtil::UpdateChannel(mplexID, m_sourceId, chanid, name, name,
251  channum, serviceID, 0, 0,
252  false, kChannelVisible, QString(),
253  QString(), "Default", QString());
254 
255  ChannelUtil::UpdateIPTVTuningData(chanid, (*it).m_tuning);
256  }
257  }
258 
260  }
261 
262  if (m_scanMonitor)
263  {
264  m_scanMonitor->ScanAppendTextToLog(tr("Done"));
268  }
269 
270  QMutexLocker locker(&m_lock);
271  m_threadRunning = false;
272  m_stopNow = true;
273 }
274 
276 {
277  uint minval = 70;
278  uint range = 100 - minval;
279  uint pct = minval + (uint) truncf((((float)val) / m_chanCnt) * range);
280  if (m_scanMonitor)
282 }
283 
284 bool VBoxChannelFetcher::SupportedTransmission(const QString& transType)
285 {
286  if (transType == "UNKNOWN")
287  return true;
288 
289  // both S and S2 tuners can tune an S channel
290  if (transType == "S" && (m_transType == "S" || m_transType == "S2"))
291  return true;
292 
293  // both T and T2 tuners can tune a T channel
294  if (transType == "T" && (m_transType == "T" || m_transType == "T2"))
295  return true;
296 
297  // for S2, T2, A and C the channel and tuner transmission types must match
298  return transType == m_transType;
299 }
VBoxChannelFetcher::m_cardId
uint m_cardId
Definition: vboxchannelfetcher.h:88
VBoxChannelFetcher::m_transType
QString m_transType
Definition: vboxchannelfetcher.h:93
VBoxChannelFetcher::m_sourceId
uint m_sourceId
Definition: vboxchannelfetcher.h:90
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
vbox_chan_map_t
QMap< QString, VBoxChannelInfo > vbox_chan_map_t
Definition: vboxchannelfetcher.h:62
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
VBoxChannelFetcher::~VBoxChannelFetcher
~VBoxChannelFetcher() override
Definition: vboxchannelfetcher.cpp:58
VBoxChannelFetcher::m_threadRunning
bool m_threadRunning
Definition: vboxchannelfetcher.h:96
VBoxChannelFetcher::m_stopNow
bool m_stopNow
Definition: vboxchannelfetcher.h:97
VBoxChannelFetcher::m_thread
MThread * m_thread
Definition: vboxchannelfetcher.h:98
ScanMonitor::ScanPercentComplete
void ScanPercentComplete(int pct)
Definition: scanmonitor.cpp:103
VBoxChannelFetcher::m_lock
QMutex m_lock
Definition: vboxchannelfetcher.h:99
VBoxChannelFetcher::Stop
void Stop(void)
Stops the scanning thread running.
Definition: vboxchannelfetcher.cpp:70
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
VBoxChannelFetcher::m_scanMonitor
ScanMonitor * m_scanMonitor
Definition: vboxchannelfetcher.h:87
VBoxChannelFetcher::SupportedTransmission
bool SupportedTransmission(const QString &transType)
Definition: vboxchannelfetcher.cpp:284
kRequireAudio
@ kRequireAudio
Definition: channelscantypes.h:8
ScanMonitor::ScanErrored
void ScanErrored(const QString &error)
Definition: scanmonitor.cpp:128
VBoxChannelFetcher::m_channels
vbox_chan_map_t * m_channels
Definition: vboxchannelfetcher.h:94
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
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
vboxutils.h
VBoxChannelFetcher::m_ftaOnly
bool m_ftaOnly
Definition: vboxchannelfetcher.h:91
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
VBoxChannelFetcher::GetChannels
vbox_chan_map_t GetChannels(void)
Definition: vboxchannelfetcher.cpp:87
VBoxChannelFetcher::Scan
void Scan(void)
Definition: vboxchannelfetcher.cpp:97
uint
unsigned int uint
Definition: compat.h:81
ScanMonitor::ScanAppendTextToLog
void ScanAppendTextToLog(const QString &status)
Definition: scanmonitor.cpp:109
LOC
#define LOC
Definition: vboxchannelfetcher.cpp:20
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
VBox::getChannels
vbox_chan_map_t * getChannels(void)
Definition: vboxutils.cpp:296
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
ChannelUtil::CreateMultiplex
static uint CreateMultiplex(int sourceid, const QString &sistandard, uint64_t frequency, const QString &modulation, int transport_id=-1, int network_id=-1)
Definition: channelutil.cpp:372
VBox
Definition: vboxutils.h:16
std
Definition: mythchrono.h:23
mythcontext.h
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:48
VBoxChannelFetcher::m_serviceType
ServiceRequirements m_serviceType
Definition: vboxchannelfetcher.h:92
VBoxChannelFetcher::VBoxChannelFetcher
VBoxChannelFetcher(uint cardid, QString inputname, uint sourceid, bool ftaOnly, ServiceRequirements serviceType, ScanMonitor *monitor=nullptr)
Definition: vboxchannelfetcher.cpp:22
VBoxChannelFetcher::m_chanCnt
uint m_chanCnt
Definition: vboxchannelfetcher.h:95
VBoxChannelFetcher::run
void run(void) override
Definition: vboxchannelfetcher.cpp:104
VBoxChannelFetcher::SetNumChannelsInserted
void SetNumChannelsInserted(uint val)
Definition: vboxchannelfetcher.cpp:275
VBoxChannelFetcher::SetTotalNumChannels
void SetTotalNumChannels(uint val)
Definition: vboxchannelfetcher.h:79
mythdownloadmanager.h
ServiceRequirements
ServiceRequirements
Definition: channelscantypes.h:4
VBox::getIPFromVideoDevice
static QString getIPFromVideoDevice(const QString &dev)
Definition: vboxutils.cpp:149
ScanMonitor
Definition: scanmonitor.h:44
vboxchannelfetcher.h
CardUtil::GetVideoDevice
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:294
ChannelUtil::UpdateIPTVTuningData
static bool UpdateIPTVTuningData(uint channel_id, const IPTVTuningData &tuning)
Definition: channelutil.cpp:1729