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