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