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;
52  m_commmethod = other.m_commmethod;
53  m_tmoffset = other.m_tmoffset;
54  m_iptvid = other.m_iptvid;
55 
56  // Not in channel table
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, bool _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_atsc_major_chan = _major_chan;
76  m_atsc_minor_chan = _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;
113  m_commmethod = other.m_commmethod;
114  m_tmoffset = other.m_tmoffset;
115  m_iptvid = other.m_iptvid;
116 
117  // Not in channel table
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 = query.value(15).toBool();
171  m_outputfilters = query.value(16).toString();
172  m_useonairguide = query.value(17).toBool();
173  m_mplexid = query.value(18).toUInt();
174  m_serviceid = query.value(19).toUInt();
175  m_atsc_major_chan = query.value(20).toUInt();
176  m_atsc_minor_chan = query.value(21).toUInt();
177  m_last_record = query.value(22).toDateTime();
178  m_default_authority = query.value(23).toString();
179  m_commmethod = query.value(24).toUInt();
180  m_tmoffset = query.value(25).toUInt();
181  m_iptvid = query.value(26).toUInt();
182 
183  return true;
184 }
185 
186 QString ChannelInfo::GetFormatted(const ChannelFormat &format) const
187 {
188  QString tmp;
189 
190  if (format & kChannelLong)
191  tmp = gCoreContext->GetSetting("LongChannelFormat", "<num> <name>");
192  else // kChannelShort
193  tmp = gCoreContext->GetSetting("ChannelFormat", "<num> <sign>");
194 
195 
196  if (tmp.isEmpty())
197  return QString();
198 
199  tmp.replace("<num>", m_channum);
200  tmp.replace("<sign>", m_callsign);
201  tmp.replace("<name>", m_name);
202 
203  return tmp;
204 }
205 
207 {
208  if (m_sourceid > 0 && m_sourcename.isNull())
210 
211  return m_sourcename;
212 }
213 
215 {
216  infoMap["callsign"] = m_callsign;
217  infoMap["channeliconpath"] = m_icon;
218  //infoMap["chanstr"] = chanstr;
219  infoMap["channelname"] = m_name;
220  infoMap["channelid"] = QString().setNum(m_chanid);
221  infoMap["channelsourcename"] = GetSourceName();
222  infoMap["channelrecpriority"] = QString().setNum(m_recpriority);
223 
224  infoMap["channelnumber"] = m_channum;
225 
226  infoMap["majorchan"] = QString().setNum(m_atsc_major_chan);
227  infoMap["minorchan"] = QString().setNum(m_atsc_minor_chan);
228  infoMap["mplexid"] = QString().setNum(m_mplexid);
229  infoMap["channelvisible"] = m_visible ? QObject::tr("Yes") : QObject::tr("No");
230 
231  if (!GetGroupIds().isEmpty())
232  infoMap["channelgroupname"] = ChannelGroup::GetChannelGroupName(GetGroupIds().first());
233 }
234 
236 {
237  if (m_chanid && m_inputIdList.isEmpty())
238  {
239  MSqlQuery query(MSqlQuery::InitCon());
240  query.prepare("SELECT capturecard.cardid FROM channel "
241  "JOIN capturecard ON capturecard.sourceid = channel.sourceid "
242  "WHERE chanid = :CHANID");
243  query.bindValue(":CHANID", m_chanid);
244 
245  if (!query.exec())
246  MythDB::DBError("ChannelInfo::LoadInputIds()", query);
247  else
248  {
249  while(query.next())
250  {
251  AddInputId(query.value(0).toUInt());
252  }
253  }
254  }
255 }
256 
258 {
259  if (m_chanid && m_groupIdList.isEmpty())
260  {
261  MSqlQuery query(MSqlQuery::InitCon());
262  query.prepare("SELECT grpid FROM channelgroup "
263  "WHERE chanid = :CHANID");
264  query.bindValue(":CHANID", m_chanid);
265 
266  if (!query.exec())
267  MythDB::DBError("ChannelInfo::LoadGroupIds()", query);
268  else if (query.size() == 0)
269  {
270  // HACK Avoid re-running this query each time for channels
271  // which don't belong to any group
272  AddGroupId(0);
273  }
274  else
275  {
276  while(query.next())
277  {
278  AddGroupId(query.value(0).toUInt());
279  }
280  }
281  }
282 }
283 
286 
287 bool ChannelInsertInfo::SaveScan(uint scanid, uint transportid) const
288 {
289  MSqlQuery query(MSqlQuery::InitCon());
290  query.prepare(
291  "INSERT INTO channelscan_channel "
292  " ( scanid, transportid, "
293  " mplex_id, source_id, channel_id, "
294  " callsign, service_name, chan_num, "
295  " service_id, atsc_major_channel, atsc_minor_channel, "
296  " use_on_air_guide, hidden, hidden_in_guide, "
297  " freqid, icon, tvformat, "
298  " xmltvid, pat_tsid, vct_tsid, "
299  " vct_chan_tsid, sdt_tsid, orig_netid, "
300  " netid, si_standard, in_channels_conf, "
301  " in_pat, in_pmt, in_vct, "
302  " in_nit, in_sdt, is_encrypted, "
303  " is_data_service, is_audio_service, is_opencable, "
304  " could_be_opencable, decryption_status, default_authority "
305  " ) "
306  "VALUES "
307  " ( :SCANID, :TRANSPORTID, "
308  " :MPLEX_ID, :SOURCE_ID, :CHANNEL_ID, "
309  " :CALLSIGN, :SERVICE_NAME, :CHAN_NUM, "
310  " :SERVICE_ID, :ATSC_MAJOR_CHANNEL,:ATSC_MINOR_CHANNEL, "
311  " :USE_ON_AIR_GUIDE, :HIDDEN, :HIDDEN_IN_GUIDE, "
312  " :FREQID, :ICON, :TVFORMAT, "
313  " :XMLTVID, :PAT_TSID, :VCT_TSID, "
314  " :VCT_CHAN_TSID, :SDT_TSID, :ORIG_NETID, "
315  " :NETID, :SI_STANDARD, :IN_CHANNELS_CONF, "
316  " :IN_PAT, :IN_PMT, :IN_VCT, "
317  " :IN_NIT, :IN_SDT, :IS_ENCRYPTED, "
318  " :IS_DATA_SERVICE, :IS_AUDIO_SERVICE, :IS_OPENCABLE, "
319  " :COULD_BE_OPENCABLE,:DECRYPTION_STATUS, :DEFAULT_AUTHORITY "
320  " );");
321 
322  query.bindValue(":SCANID", scanid);
323  query.bindValue(":TRANSPORTID", transportid);
324  query.bindValue(":MPLEX_ID", m_db_mplexid);
325  query.bindValue(":SOURCE_ID", m_source_id);
326  query.bindValue(":CHANNEL_ID", m_channel_id);
327  query.bindValueNoNull(":CALLSIGN", m_callsign);
328  query.bindValueNoNull(":SERVICE_NAME", m_service_name);
329  query.bindValueNoNull(":CHAN_NUM", m_chan_num);
330  query.bindValue(":SERVICE_ID", m_service_id);
331  query.bindValue(":ATSC_MAJOR_CHANNEL", m_atsc_major_channel);
332  query.bindValue(":ATSC_MINOR_CHANNEL", m_atsc_minor_channel);
333  query.bindValue(":USE_ON_AIR_GUIDE", m_use_on_air_guide);
334  query.bindValue(":HIDDEN", m_hidden);
335  query.bindValue(":HIDDEN_IN_GUIDE", m_hidden_in_guide);
336  query.bindValueNoNull(":FREQID", m_freqid);
337  query.bindValueNoNull(":ICON", m_icon);
338  query.bindValueNoNull(":TVFORMAT", m_format);
339  query.bindValueNoNull(":XMLTVID", m_xmltvid);
340  query.bindValue(":PAT_TSID", m_pat_tsid);
341  query.bindValue(":VCT_TSID", m_vct_tsid);
342  query.bindValue(":VCT_CHAN_TSID", m_vct_chan_tsid);
343  query.bindValue(":SDT_TSID", m_sdt_tsid);
344  query.bindValue(":ORIG_NETID", m_orig_netid);
345  query.bindValue(":NETID", m_netid);
346  query.bindValueNoNull(":SI_STANDARD", m_si_standard);
347  query.bindValue(":IN_CHANNELS_CONF", m_in_channels_conf);
348  query.bindValue(":IN_PAT", m_in_pat);
349  query.bindValue(":IN_PMT", m_in_pmt);
350  query.bindValue(":IN_VCT", m_in_vct);
351  query.bindValue(":IN_NIT", m_in_nit);
352  query.bindValue(":IN_SDT", m_in_sdt);
353  query.bindValue(":IS_ENCRYPTED", m_is_encrypted);
354  query.bindValue(":IS_DATA_SERVICE", m_is_data_service);
355  query.bindValue(":IS_AUDIO_SERVICE", m_is_audio_service);
356  query.bindValue(":IS_OPENCABLE", m_is_opencable);
357  query.bindValue(":COULD_BE_OPENCABLE", m_could_be_opencable);
358  query.bindValue(":DECRYPTION_STATUS", m_decryption_status);
359  query.bindValueNoNull(":DEFAULT_AUTHORITY", m_default_authority);
360 
361  if (!query.exec())
362  {
363  MythDB::DBError("ChannelInsertInfo::SaveScan()", query);
364  return false;
365  }
366 
367  return true;
368 }
369 
371 {
372  if (other.m_db_mplexid && !m_db_mplexid)
373  m_db_mplexid = other.m_db_mplexid;
374  if (other.m_source_id && !m_source_id)
375  m_source_id = other.m_source_id;
376  if (other.m_channel_id && !m_channel_id)
377  m_channel_id = other.m_channel_id;
378  if (!other.m_callsign.isEmpty() && m_callsign.isEmpty())
379  m_callsign = other.m_callsign;
380  if (!other.m_service_name.isEmpty() && m_service_name.isEmpty())
382  if (!other.m_chan_num.isEmpty() &&
383  ((m_chan_num.isEmpty() || m_chan_num == "0")))
384  m_chan_num = other.m_chan_num;
385  if (other.m_service_id && !m_service_id)
386  m_service_id = other.m_service_id;
391  //m_use_on_air_guide = other.m_use_on_air_guide;
392  //m_hidden = other.m_hidden;
393  //m_hidden_in_guide = other.m_hidden_in_guide;
394  if (!other.m_freqid.isEmpty() && m_freqid.isEmpty())
395  m_freqid = other.m_freqid;
396  if (!other.m_icon.isEmpty() && m_icon.isEmpty())
397  m_icon = other.m_icon;
398  if (!other.m_format.isEmpty() && m_format.isEmpty())
399  m_format = other.m_format;
400  if (!other.m_xmltvid.isEmpty() && m_xmltvid.isEmpty())
401  m_xmltvid = other.m_xmltvid;
402  if (!other.m_default_authority.isEmpty() && m_default_authority.isEmpty())
404  // non-DB info
405  if (other.m_pat_tsid && !m_pat_tsid)
406  m_pat_tsid = other.m_pat_tsid;
407  if (other.m_vct_tsid && !m_vct_tsid)
408  m_vct_tsid = other.m_vct_tsid;
409  if (other.m_vct_chan_tsid && !m_vct_chan_tsid)
411  if (other.m_sdt_tsid && !m_sdt_tsid)
412  m_sdt_tsid = other.m_sdt_tsid;
413  if (other.m_orig_netid && !m_orig_netid)
414  m_orig_netid = other.m_orig_netid;
415  if (other.m_netid && !m_netid)
416  m_netid = other.m_netid;
417  if (!other.m_si_standard.isEmpty() &&
418  (m_si_standard.isEmpty() || ("mpeg" == m_si_standard)))
422  if (other.m_in_pat && !m_in_pat)
423  m_in_pat = other.m_in_pat;
424  if (other.m_in_pmt && !m_in_pmt)
425  m_in_pmt = other.m_in_pmt;
426  if (other.m_in_vct && !m_in_vct)
427  m_in_vct = other.m_in_vct;
428  if (other.m_in_nit && !m_in_nit)
429  m_in_nit = other.m_in_nit;
430  if (other.m_in_sdt && !m_in_sdt)
431  m_in_sdt = other.m_in_sdt;
432  if (other.m_in_pat && !m_in_pat)
434  if (other.m_is_data_service && !m_is_data_service)
438  if (other.m_is_opencable && !m_is_opencable)
444 }
445 
446 // relaxed 0 compare channels to check for duplicates
447 // 1 compare channels across transports after rescan
448 // 2 compare channels in same transport
449 //
451  const ChannelInsertInfo &other, int relaxed) const
452 {
453  if (m_atsc_major_channel &&
456  {
457  return true;
458  }
459 
460  if ((m_orig_netid == other.m_orig_netid) &&
461  (m_sdt_tsid == other.m_sdt_tsid) &&
462  (m_service_id == other.m_service_id))
463  {
464  return true;
465  }
466 
467  if (!m_orig_netid && !other.m_orig_netid &&
468  (m_pat_tsid == other.m_pat_tsid) &&
469  (m_service_id == other.m_service_id))
470  {
471  return true;
472  }
473 
474  if (relaxed > 0)
475  {
476  if ((m_orig_netid == other.m_orig_netid) &&
477  (m_service_id == other.m_service_id))
478  {
479  return true;
480  }
481  }
482 
483  if (relaxed > 1)
484  {
485  if (("mpeg" == m_si_standard || "mpeg" == other.m_si_standard ||
486  "dvb" == m_si_standard || "dvb" == other.m_si_standard ||
487  m_si_standard.isEmpty() || other.m_si_standard.isEmpty()) &&
488  (m_service_id == other.m_service_id))
489  {
490  return true;
491  }
492  }
493 
494  return false;
495 }
496 
497 /* vim: set expandtab tabstop=4 shiftwidth=4: */
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:781
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:862
void ToMap(InfoMap &infoMap)
QString m_name
Definition: channelinfo.h:82
QString m_service_name
Definition: channelinfo.h:207
int m_recpriority
Definition: channelinfo.h:88
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_videofilters
Definition: channelinfo.h:86
QString m_outputfilters
Definition: channelinfo.h:97
ChannelInfo & operator=(const ChannelInfo &)
Definition: channelinfo.cpp:82
int size(void) const
Definition: mythdbcon.h:203
void AddInputId(uint linputid)
Definition: channelinfo.h:61
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
bool SaveScan(uint scanid, uint transportid) const
QString m_xmltvid
Definition: channelinfo.h:87
void LoadInputIds()
static guint32 * tmp
Definition: goom_core.c:35
ChannelInfo()=default
uint m_service_type
Definition: channelinfo.h:102
QString GetSourceName()
QString m_tvformat
Definition: channelinfo.h:95
QString m_icon
Definition: channelinfo.h:83
static QString GetSourceName(uint sourceid)
Definition: sourceutil.cpp:45
QVariant value(int i) const
Definition: mythdbcon.h:198
bool IsSameChannel(const ChannelInsertInfo &, int relaxed=0) const
QString m_sourcename
Definition: channelinfo.h:116
uint m_serviceid
Definition: channelinfo.h:101
void AddGroupId(uint lgroupid)
Definition: channelinfo.h:49
uint m_atsc_major_chan
Definition: channelinfo.h:103
QString GetSetting(const QString &key, const QString &defaultval="")
QString m_freqid
Definition: channelinfo.h:77
uint m_sourceid
Definition: channelinfo.h:79
int m_finetune
Definition: channelinfo.h:85
uint m_mplexid
Definition: channelinfo.h:100
int m_commmethod
Definition: channelinfo.h:109
QList< uint > m_inputIdList
Definition: channelinfo.h:119
unsigned int uint
Definition: compat.h:140
void LoadGroupIds()
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:534
static QString GetChannelGroupName(int grpid)
const QList< uint > GetGroupIds() const
Definition: channelinfo.h:47
QDateTime m_last_record
Definition: channelinfo.h:106
QString m_channum
Definition: channelinfo.h:76
uint m_contrast
Definition: channelinfo.h:90
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:806
bool Load(uint lchanid=-1)
QString m_si_standard
Definition: channelinfo.h:229
QString m_old_xmltvid
Definition: channelinfo.h:113
uint m_atsc_minor_chan
Definition: channelinfo.h:104
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
Definition: mythdbcon.cpp:867
bool m_visible
Definition: channelinfo.h:96
QString m_callsign
Definition: channelinfo.h:81
QString m_default_authority
Definition: channelinfo.h:220
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:602
bool m_useonairguide
Definition: channelinfo.h:98
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
uint m_colour
Definition: channelinfo.h:92
QString m_default_authority
Definition: channelinfo.h:108
QList< uint > m_groupIdList
Definition: channelinfo.h:118
uint m_chanid
Definition: channelinfo.h:75
uint m_brightness
Definition: channelinfo.h:91