MythTV  master
channelinfo.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 // Qt headers
4 #include <QFile>
5 #include <QDir>
6 #include <QFileInfo>
7 #include <QImage>
8 #include <QUrl>
9 
10 // MythTV headers
11 #include "channelinfo.h"
12 #include "mythcorecontext.h"
13 #include "mythdb.h"
14 #include "mythdirs.h"
15 #include "mpegstreamdata.h" // for CryptStatus
16 #include "remotefile.h"
17 #include "channelgroup.h"
18 #include "sourceutil.h"
19 
22 
24 {
25  // Channel table
26  m_chanId = other.m_chanId;
27  m_chanNum = other.m_chanNum;
28  m_freqId = other.m_freqId;
29  m_sourceId = other.m_sourceId;
30  m_callSign = other.m_callSign;
31  m_name = other.m_name;
32  m_icon = other.m_icon;
33  m_fineTune = other.m_fineTune;
35  m_xmltvId = other.m_xmltvId;
37  m_contrast = other.m_contrast;
38  m_brightness = other.m_brightness;
39  m_colour = other.m_colour;
40  m_hue = other.m_hue;
41  m_tvFormat = other.m_tvFormat;
42  m_visible = other.m_visible;
45  m_mplexId = (other.m_mplexId == 32767) ? 0 : other.m_mplexId;
46  m_serviceId = other.m_serviceId;
50  m_lastRecord = other.m_lastRecord;
52  m_commMethod = other.m_commMethod;
53  m_tmOffset = other.m_tmOffset;
54  m_iptvId = other.m_iptvId;
55 
56  // Not in channel table
59  m_oldXmltvId = other.m_oldXmltvId;
60  m_sourceName = other.m_sourceName;
61 }
62 
64  const QString &_channum, const QString &_callsign,
65  uint _chanid, uint _major_chan, uint _minor_chan,
66  uint _mplexid, ChannelVisibleType _visible,
67  const QString &_name, const QString &_icon,
68  uint _sourceid)
69 {
70  m_chanNum = _channum;
71  m_callSign = _callsign;
72  m_name = _name;
73  m_icon = _icon;
74  m_chanId = _chanid;
75  m_atscMajorChan = _major_chan;
76  m_atscMinorChan = _minor_chan;
77  m_mplexId = (_mplexid == 32767) ? 0 : _mplexid;
78  m_sourceId = _sourceid;
79  m_visible = _visible;
80 }
81 
83 {
84  if (this == &other)
85  return *this;
86 
87  // Channel table
88  m_chanId = other.m_chanId;
89  m_chanNum = other.m_chanNum;
90  m_freqId = other.m_freqId;
91  m_sourceId = other.m_sourceId;
92  m_callSign = other.m_callSign;
93  m_name = other.m_name;
94  m_icon = other.m_icon;
95  m_fineTune = other.m_fineTune;
97  m_xmltvId = other.m_xmltvId;
99  m_contrast = other.m_contrast;
100  m_brightness = other.m_brightness;
101  m_colour = other.m_colour;
102  m_hue = other.m_hue;
103  m_tvFormat = other.m_tvFormat;
104  m_visible = other.m_visible;
107  m_mplexId = (other.m_mplexId == 32767) ? 0 : other.m_mplexId;
108  m_serviceId = other.m_serviceId;
111  m_lastRecord = other.m_lastRecord;
113  m_commMethod = other.m_commMethod;
114  m_tmOffset = other.m_tmOffset;
115  m_iptvId = other.m_iptvId;
116 
117  // Not in channel table
120  m_oldXmltvId = other.m_oldXmltvId;
121  m_sourceName = other.m_sourceName;
122 
123  return *this;
124 }
125 
126 bool ChannelInfo::Load(uint lchanid)
127 {
128  if (lchanid == 0 && m_chanId == 0)
129  return false;
130 
131  if (lchanid == 0)
132  lchanid = m_chanId;
133 
134  MSqlQuery query(MSqlQuery::InitCon());
135  query.prepare("SELECT channum, freqid, sourceid, "
136  "callsign, name, icon, finetune, videofilters, xmltvid, "
137  "recpriority, contrast, brightness, colour, hue, tvformat, "
138  "visible, outputfilters, useonairguide, mplexid, "
139  "serviceid, atsc_major_chan, atsc_minor_chan, last_record, "
140  "default_authority, commmethod, tmoffset, iptvid "
141  "FROM channel WHERE chanid = :CHANID ;");
142 
143  query.bindValue(":CHANID", lchanid);
144 
145  if (!query.exec())
146  {
147  MythDB::DBError("ChannelInfo::Load()", query);
148  return false;
149  }
150 
151  if (!query.next())
152  return false;
153 
154  m_chanId = lchanid;
155  m_chanNum = query.value(0).toString();
156  m_freqId = query.value(1).toString();
157  m_sourceId = query.value(2).toUInt();
158  m_callSign = query.value(3).toString();
159  m_name = query.value(4).toString();
160  m_icon = query.value(5).toString();
161  m_fineTune = query.value(6).toInt();
162  m_videoFilters = query.value(7).toString();
163  m_xmltvId = query.value(8).toString();
164  m_recPriority = query.value(9).toInt();
165  m_contrast = query.value(10).toUInt();
166  m_brightness = query.value(11).toUInt();
167  m_colour = query.value(12).toUInt();
168  m_hue = query.value(13).toUInt();
169  m_tvFormat = query.value(14).toString();
170  m_visible =
171  static_cast<ChannelVisibleType>(query.value(15).toInt());
172  m_outputFilters = query.value(16).toString();
173  m_useOnAirGuide = query.value(17).toBool();
174  m_mplexId = query.value(18).toUInt();
175  m_serviceId = query.value(19).toUInt();
176  m_atscMajorChan = query.value(20).toUInt();
177  m_atscMinorChan = query.value(21).toUInt();
178  m_lastRecord = query.value(22).toDateTime();
179  m_defaultAuthority = query.value(23).toString();
180  m_commMethod = query.value(24).toUInt();
181  m_tmOffset = query.value(25).toUInt();
182  m_iptvId = query.value(26).toUInt();
183 
184  return true;
185 }
186 
187 QString ChannelInfo::GetFormatted(const ChannelFormat &format) const
188 {
189  QString tmp;
190 
191  if (format & kChannelLong)
192  tmp = gCoreContext->GetSetting("LongChannelFormat", "<num> <name>");
193  else // kChannelShort
194  tmp = gCoreContext->GetSetting("ChannelFormat", "<num> <sign>");
195 
196 
197  if (tmp.isEmpty())
198  return QString();
199 
200  tmp.replace("<num>", m_chanNum);
201  tmp.replace("<sign>", m_callSign);
202  tmp.replace("<name>", m_name);
203 
204  return tmp;
205 }
206 
208 {
209  if (m_sourceId > 0 && m_sourceName.isNull())
211 
212  return m_sourceName;
213 }
214 
216 {
217  infoMap["callsign"] = m_callSign;
218  infoMap["channeliconpath"] = m_icon;
219  //infoMap["chanstr"] = chanstr;
220  infoMap["channelname"] = m_name;
221  infoMap["channelid"] = QString().setNum(m_chanId);
222  infoMap["channelsourcename"] = GetSourceName();
223  infoMap["channelrecpriority"] = QString().setNum(m_recPriority);
224 
225  infoMap["channelnumber"] = m_chanNum;
226 
227  infoMap["majorchan"] = QString().setNum(m_atscMajorChan);
228  infoMap["minorchan"] = QString().setNum(m_atscMinorChan);
229  infoMap["mplexid"] = QString().setNum(m_mplexId);
230  infoMap["channelvisible"] = m_visible ? QObject::tr("Yes") : QObject::tr("No");
231 
232  if (!GetGroupIds().isEmpty())
233  infoMap["channelgroupname"] = ChannelGroup::GetChannelGroupName(GetGroupIds().first());
234 }
235 
237 {
238  if (m_chanId && m_inputIdList.isEmpty())
239  {
240  MSqlQuery query(MSqlQuery::InitCon());
241  query.prepare("SELECT capturecard.cardid FROM channel "
242  "JOIN capturecard ON capturecard.sourceid = channel.sourceid "
243  "WHERE chanid = :CHANID");
244  query.bindValue(":CHANID", m_chanId);
245 
246  if (!query.exec())
247  MythDB::DBError("ChannelInfo::LoadInputIds()", query);
248  else
249  {
250  while(query.next())
251  {
252  AddInputId(query.value(0).toUInt());
253  }
254  }
255  }
256 }
257 
259 {
260  if (m_chanId && m_groupIdList.isEmpty())
261  {
262  MSqlQuery query(MSqlQuery::InitCon());
263  query.prepare("SELECT grpid FROM channelgroup "
264  "WHERE chanid = :CHANID");
265  query.bindValue(":CHANID", m_chanId);
266 
267  if (!query.exec())
268  MythDB::DBError("ChannelInfo::LoadGroupIds()", query);
269  else if (query.size() == 0)
270  {
271  // HACK Avoid re-running this query each time for channels
272  // which don't belong to any group
273  AddGroupId(0);
274  }
275  else
276  {
277  while(query.next())
278  {
279  AddGroupId(query.value(0).toUInt());
280  }
281  }
282  }
283 }
284 
287 
288 bool ChannelInsertInfo::SaveScan(uint scanid, uint transportid) const
289 {
290  MSqlQuery query(MSqlQuery::InitCon());
291  query.prepare(
292  "INSERT INTO channelscan_channel "
293  " ( scanid, transportid, "
294  " mplex_id, source_id, channel_id, "
295  " callsign, service_name, chan_num, "
296  " service_id, atsc_major_channel, atsc_minor_channel, "
297  " use_on_air_guide, hidden, hidden_in_guide, "
298  " freqid, icon, tvformat, "
299  " xmltvid, pat_tsid, vct_tsid, "
300  " vct_chan_tsid, sdt_tsid, orig_netid, "
301  " netid, si_standard, in_channels_conf, "
302  " in_pat, in_pmt, in_vct, "
303  " in_nit, in_sdt, is_encrypted, "
304  " is_data_service, is_audio_service, is_opencable, "
305  " could_be_opencable, decryption_status, default_authority "
306  " ) "
307  "VALUES "
308  " ( :SCANID, :TRANSPORTID, "
309  " :MPLEX_ID, :SOURCE_ID, :CHANNEL_ID, "
310  " :CALLSIGN, :SERVICE_NAME, :CHAN_NUM, "
311  " :SERVICE_ID, :ATSC_MAJOR_CHANNEL,:ATSC_MINOR_CHANNEL, "
312  " :USE_ON_AIR_GUIDE, :HIDDEN, :HIDDEN_IN_GUIDE, "
313  " :FREQID, :ICON, :TVFORMAT, "
314  " :XMLTVID, :PAT_TSID, :VCT_TSID, "
315  " :VCT_CHAN_TSID, :SDT_TSID, :ORIG_NETID, "
316  " :NETID, :SI_STANDARD, :IN_CHANNELS_CONF, "
317  " :IN_PAT, :IN_PMT, :IN_VCT, "
318  " :IN_NIT, :IN_SDT, :IS_ENCRYPTED, "
319  " :IS_DATA_SERVICE, :IS_AUDIO_SERVICE, :IS_OPENCABLE, "
320  " :COULD_BE_OPENCABLE,:DECRYPTION_STATUS, :DEFAULT_AUTHORITY "
321  " );");
322 
323  query.bindValue(":SCANID", scanid);
324  query.bindValue(":TRANSPORTID", transportid);
325  query.bindValue(":MPLEX_ID", m_dbMplexId);
326  query.bindValue(":SOURCE_ID", m_sourceId);
327  query.bindValue(":CHANNEL_ID", m_channelId);
328  query.bindValueNoNull(":CALLSIGN", m_callSign);
329  query.bindValueNoNull(":SERVICE_NAME", m_serviceName);
330  query.bindValueNoNull(":CHAN_NUM", m_chanNum);
331  query.bindValue(":SERVICE_ID", m_serviceId);
332  query.bindValue(":ATSC_MAJOR_CHANNEL", m_atscMajorChannel);
333  query.bindValue(":ATSC_MINOR_CHANNEL", m_atscMinorChannel);
334  query.bindValue(":USE_ON_AIR_GUIDE", m_useOnAirGuide);
335  query.bindValue(":HIDDEN", m_hidden);
336  query.bindValue(":HIDDEN_IN_GUIDE", m_hiddenInGuide);
337  query.bindValueNoNull(":FREQID", m_freqId);
338  query.bindValueNoNull(":ICON", m_icon);
339  query.bindValueNoNull(":TVFORMAT", m_format);
340  query.bindValueNoNull(":XMLTVID", m_xmltvId);
341  query.bindValue(":PAT_TSID", m_patTsId);
342  query.bindValue(":VCT_TSID", m_vctTsId);
343  query.bindValue(":VCT_CHAN_TSID", m_vctChanTsId);
344  query.bindValue(":SDT_TSID", m_sdtTsId);
345  query.bindValue(":ORIG_NETID", m_origNetId);
346  query.bindValue(":NETID", m_netId);
347  query.bindValueNoNull(":SI_STANDARD", m_siStandard);
348  query.bindValue(":IN_CHANNELS_CONF", m_inChannelsConf);
349  query.bindValue(":IN_PAT", m_inPat);
350  query.bindValue(":IN_PMT", m_inPmt);
351  query.bindValue(":IN_VCT", m_inVct);
352  query.bindValue(":IN_NIT", m_inNit);
353  query.bindValue(":IN_SDT", m_inSdt);
354  query.bindValue(":IS_ENCRYPTED", m_isEncrypted);
355  query.bindValue(":IS_DATA_SERVICE", m_isDataService);
356  query.bindValue(":IS_AUDIO_SERVICE", m_isAudioService);
357  query.bindValue(":IS_OPENCABLE", m_isOpencable);
358  query.bindValue(":COULD_BE_OPENCABLE", m_couldBeOpencable);
359  query.bindValue(":DECRYPTION_STATUS", m_decryptionStatus);
360  query.bindValueNoNull(":DEFAULT_AUTHORITY", m_defaultAuthority);
361 
362  if (!query.exec())
363  {
364  MythDB::DBError("ChannelInsertInfo::SaveScan()", query);
365  return false;
366  }
367 
368  return true;
369 }
370 
372 {
373  if (other.m_dbMplexId && !m_dbMplexId)
374  m_dbMplexId = other.m_dbMplexId;
375  if (other.m_sourceId && !m_sourceId)
376  m_sourceId = other.m_sourceId;
377  if (other.m_channelId && !m_channelId)
378  m_channelId = other.m_channelId;
379  if (!other.m_callSign.isEmpty() && m_callSign.isEmpty())
380  m_callSign = other.m_callSign;
381  if (!other.m_serviceName.isEmpty() && m_serviceName.isEmpty())
383  if (!other.m_chanNum.isEmpty() &&
384  ((m_chanNum.isEmpty() || m_chanNum == "0")))
385  m_chanNum = other.m_chanNum;
386  if (other.m_serviceId && !m_serviceId)
387  m_serviceId = other.m_serviceId;
392  //m_useOnAirGuide = other.m_useOnAirGuide;
393  //m_hidden = other.m_hidden;
394  //m_hiddenInGuide = other.m_hiddenInGuide;
395  if (!other.m_freqId.isEmpty() && m_freqId.isEmpty())
396  m_freqId = other.m_freqId;
397  if (!other.m_icon.isEmpty() && m_icon.isEmpty())
398  m_icon = other.m_icon;
399  if (!other.m_format.isEmpty() && m_format.isEmpty())
400  m_format = other.m_format;
401  if (!other.m_xmltvId.isEmpty() && m_xmltvId.isEmpty())
402  m_xmltvId = other.m_xmltvId;
403  if (!other.m_defaultAuthority.isEmpty() && m_defaultAuthority.isEmpty())
405  // non-DB info
406  if (other.m_patTsId && !m_patTsId)
407  m_patTsId = other.m_patTsId;
408  if (other.m_vctTsId && !m_vctTsId)
409  m_vctTsId = other.m_vctTsId;
410  if (other.m_vctChanTsId && !m_vctChanTsId)
412  if (other.m_sdtTsId && !m_sdtTsId)
413  m_sdtTsId = other.m_sdtTsId;
414  if (other.m_origNetId && !m_origNetId)
415  m_origNetId = other.m_origNetId;
416  if (other.m_netId && !m_netId)
417  m_netId = other.m_netId;
418  if (!other.m_siStandard.isEmpty() &&
419  (m_siStandard.isEmpty() || ("mpeg" == m_siStandard)))
420  m_siStandard = other.m_siStandard;
421  if (other.m_inChannelsConf && !m_inChannelsConf)
423  if (other.m_inPat && !m_inPat)
424  m_inPat = other.m_inPat;
425  if (other.m_inPmt && !m_inPmt)
426  m_inPmt = other.m_inPmt;
427  if (other.m_inVct && !m_inVct)
428  m_inVct = other.m_inVct;
429  if (other.m_inNit && !m_inNit)
430  m_inNit = other.m_inNit;
431  if (other.m_inSdt && !m_inSdt)
432  m_inSdt = other.m_inSdt;
433  if (other.m_inPat && !m_inPat)
435  if (other.m_isDataService && !m_isDataService)
437  if (other.m_isAudioService && !m_isAudioService)
439  if (other.m_isOpencable && !m_isOpencable)
445 }
446 
447 // relaxed 0 compare channels to check for duplicates
448 // 1 compare channels across transports after rescan
449 // 2 compare channels in same transport
450 //
452  const ChannelInsertInfo &other, int relaxed) const
453 {
454  if (m_atscMajorChannel)
455  {
456  if ((m_atscMajorChannel == other.m_atscMajorChannel &&
458  {
459  return true;
460  }
461  return false;
462  }
463 
464  if ((m_origNetId == other.m_origNetId) &&
465  (m_sdtTsId == other.m_sdtTsId) &&
466  (m_serviceId == other.m_serviceId))
467  {
468  return true;
469  }
470 
471  if (!m_origNetId && !other.m_origNetId &&
472  (m_patTsId == other.m_patTsId) &&
473  (m_serviceId == other.m_serviceId))
474  {
475  return true;
476  }
477 
478  if (relaxed > 0)
479  {
480  if ((m_origNetId == other.m_origNetId) &&
481  (m_serviceId == other.m_serviceId))
482  {
483  return true;
484  }
485  }
486 
487  if (relaxed > 1)
488  {
489  if (("mpeg" == m_siStandard || "mpeg" == other.m_siStandard ||
490  "dvb" == m_siStandard || "dvb" == other.m_siStandard ||
491  m_siStandard.isEmpty() || other.m_siStandard.isEmpty()) &&
492  (m_serviceId == other.m_serviceId))
493  {
494  return true;
495  }
496  }
497 
498  return false;
499 }
500 
502 {
503  switch (type)
504  {
506  return QObject::tr("Always Visible");
507  case kChannelVisible:
508  return QObject::tr("Visible");
509  case kChannelNotVisible:
510  return QObject::tr("Not Visible");
512  return QObject::tr("Never Visible");
513  default:
514  return QObject::tr("Unknown");
515  }
516 }
517 
519 {
520  switch (type)
521  {
523  return QString("Always Visible");
524  case kChannelVisible:
525  return QString("Visible");
526  case kChannelNotVisible:
527  return QString("Not Visible");
529  return QString("Never Visible");
530  default:
531  return QString("Unknown");
532  }
533 }
534 
536 {
537  if (type.toLower() == "always visible" ||
538  type.toLower() == "always")
539  return kChannelAlwaysVisible;
540  if (type.toLower() == "visible" ||
541  type.toLower() == "yes")
542  return kChannelVisible;
543  if (type.toLower() == "not visible" ||
544  type.toLower() == "not" ||
545  type.toLower() == "no")
546  return kChannelNotVisible;
547  if (type.toLower() == "never visible" ||
548  type.toLower() == "never")
549  return kChannelNeverVisible;
550  return kChannelVisible;
551 }
552 
553 /* vim: set expandtab tabstop=4 shiftwidth=4: */
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
QString m_outputFilters
Definition: channelinfo.h:109
ChannelInfo & operator=(const ChannelInfo &other)
Definition: channelinfo.cpp:82
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
void ToMap(InfoMap &infoMap)
QString m_defaultAuthority
Definition: channelinfo.h:233
uint m_mplexId
Definition: channelinfo.h:112
QString m_name
Definition: channelinfo.h:94
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
QString GetFormatted(const ChannelFormat &format) const
void ImportExtraInfo(const ChannelInsertInfo &other)
QString m_freqId
Definition: channelinfo.h:89
int size(void) const
Definition: mythdbcon.h:203
bool m_useOnAirGuide
Definition: channelinfo.h:110
void AddInputId(uint linputid)
Definition: channelinfo.h:73
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
ChannelVisibleType channelVisibleTypeFromString(const QString &type)
uint m_chanId
Definition: channelinfo.h:87
bool SaveScan(uint scanid, uint transportid) const
void LoadInputIds()
static guint32 * tmp
Definition: goom_core.c:35
ChannelInfo()=default
QString GetSourceName()
int m_fineTune
Definition: channelinfo.h:97
QString m_icon
Definition: channelinfo.h:95
static QString GetSourceName(uint sourceid)
Definition: sourceutil.cpp:45
uint m_atscMajorChan
Definition: channelinfo.h:115
QVariant value(int i) const
Definition: mythdbcon.h:198
QString m_oldXmltvId
Definition: channelinfo.h:125
int m_commMethod
Definition: channelinfo.h:121
void AddGroupId(uint lgroupid)
Definition: channelinfo.h:61
QString GetSetting(const QString &key, const QString &defaultval="")
QList< uint > GetGroupIds() const
Definition: channelinfo.h:59
uint m_atscMinorChan
Definition: channelinfo.h:116
bool IsSameChannel(const ChannelInsertInfo &other, int relaxed=0) const
QString m_chanNum
Definition: channelinfo.h:88
QList< uint > m_inputIdList
Definition: channelinfo.h:131
unsigned int uint
Definition: compat.h:140
void LoadGroupIds()
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
static QString GetChannelGroupName(int grpid)
uint m_sourceId
Definition: channelinfo.h:91
uint m_contrast
Definition: channelinfo.h:102
uint m_serviceId
Definition: channelinfo.h:113
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808
bool Load(uint lchanid=-1)
QString m_serviceName
Definition: channelinfo.h:219
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
Definition: mythdbcon.cpp:869
ChannelVisibleType
Definition: channelinfo.h:22
QString toRawString(ChannelVisibleType type)
QString m_siStandard
Definition: channelinfo.h:242
QString m_callSign
Definition: channelinfo.h:93
QString m_tvFormat
Definition: channelinfo.h:107
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
QString m_xmltvId
Definition: channelinfo.h:99
QString m_sourceName
Definition: channelinfo.h:128
QString m_defaultAuthority
Definition: channelinfo.h:120
QString toString(ChannelVisibleType type)
QDateTime m_lastRecord
Definition: channelinfo.h:118
int m_recPriority
Definition: channelinfo.h:100
QList< uint > m_groupIdList
Definition: channelinfo.h:130
uint m_brightness
Definition: channelinfo.h:103
uint m_serviceType
Definition: channelinfo.h:114
ChannelVisibleType m_visible
Definition: channelinfo.h:108
QString m_videoFilters
Definition: channelinfo.h:98