2 * Copyright (C) 2012-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
22 #include "guilib/LocalizeStrings.h"
23 #include "utils/log.h"
25 #include "filesystem/File.h"
26 #include "utils/StringUtils.h"
27 #include "threads/SingleLock.h"
29 #include "pvr/channels/PVRChannelGroupInternal.h"
30 #include "epg/EpgContainer.h"
31 #include "pvr/timers/PVRTimers.h"
32 #include "pvr/PVRDatabase.h"
33 #include "pvr/PVRManager.h"
34 #include "pvr/addons/PVRClients.h"
39 bool CPVRChannel::operator==(const CPVRChannel &right) const
41 return (m_bIsRadio == right.m_bIsRadio &&
42 m_iUniqueId == right.m_iUniqueId &&
43 m_iClientId == right.m_iClientId);
46 bool CPVRChannel::operator!=(const CPVRChannel &right) const
48 return !(*this == right);
51 CPVRChannel::CPVRChannel(bool bRadio /* = false */)
56 m_bIsUserSetIcon = false;
58 m_strIconPath = StringUtils::EmptyString;
59 m_strChannelName = StringUtils::EmptyString;
63 m_iCachedChannelNumber = 0;
66 m_bEPGCreated = false;
68 m_strEPGScraper = "client";
72 m_iClientChannelNumber = -1;
73 m_strClientChannelName = StringUtils::EmptyString;
74 m_strInputFormat = StringUtils::EmptyString;
75 m_strStreamURL = StringUtils::EmptyString;
76 m_strFileNameAndPath = StringUtils::EmptyString;
77 m_iClientEncryptionSystem = -1;
78 UpdateEncryptionName();
81 CPVRChannel::CPVRChannel(const PVR_CHANNEL &channel, unsigned int iClientId)
84 m_bIsRadio = channel.bIsRadio;
85 m_bIsHidden = channel.bIsHidden;
86 m_bIsUserSetIcon = false;
88 m_strIconPath = channel.strIconPath;
89 m_strChannelName = channel.strChannelName;
90 m_iUniqueId = channel.iUniqueId;
91 m_iClientChannelNumber = channel.iChannelNumber;
92 m_strClientChannelName = channel.strChannelName;
93 m_strInputFormat = channel.strInputFormat;
94 m_strStreamURL = channel.strStreamURL;
95 m_iClientEncryptionSystem = channel.iEncryptionSystem;
96 m_iCachedChannelNumber = 0;
97 m_iClientId = iClientId;
98 m_strFileNameAndPath = StringUtils::EmptyString;
101 m_bEPGEnabled = !channel.bIsHidden;
102 m_strEPGScraper = "client";
104 m_bEPGCreated = false;
107 if (m_strChannelName.IsEmpty())
108 m_strChannelName.Format("%s %d", g_localizeStrings.Get(19029), m_iUniqueId);
110 UpdateEncryptionName();
113 CPVRChannel::CPVRChannel(const CPVRChannel &channel)
118 CPVRChannel &CPVRChannel::operator=(const CPVRChannel &channel)
120 m_iChannelId = channel.m_iChannelId;
121 m_bIsRadio = channel.m_bIsRadio;
122 m_bIsHidden = channel.m_bIsHidden;
123 m_bIsUserSetIcon = channel.m_bIsUserSetIcon;
124 m_bIsLocked = channel.m_bIsLocked;
125 m_strIconPath = channel.m_strIconPath;
126 m_strChannelName = channel.m_strChannelName;
127 m_bIsVirtual = channel.m_bIsVirtual;
128 m_iLastWatched = channel.m_iLastWatched;
129 m_bEPGEnabled = channel.m_bEPGEnabled;
130 m_strEPGScraper = channel.m_strEPGScraper;
131 m_iUniqueId = channel.m_iUniqueId;
132 m_iClientId = channel.m_iClientId;
133 m_iClientChannelNumber = channel.m_iClientChannelNumber;
134 m_strClientChannelName = channel.m_strClientChannelName;
135 m_strInputFormat = channel.m_strInputFormat;
136 m_strStreamURL = channel.m_strStreamURL;
137 m_strFileNameAndPath = channel.m_strFileNameAndPath;
138 m_iClientEncryptionSystem = channel.m_iClientEncryptionSystem;
139 m_iCachedChannelNumber = channel.m_iCachedChannelNumber;
140 m_iEpgId = channel.m_iEpgId;
141 m_bEPGCreated = channel.m_bEPGCreated;
142 m_bChanged = channel.m_bChanged;
144 UpdateEncryptionName();
149 void CPVRChannel::Serialize(CVariant& value) const
151 value["channelid"] = m_iChannelId;
152 value["channeltype"] = m_bIsRadio ? "radio" : "tv";
153 value["hidden"] = m_bIsHidden;
154 value["locked"] = m_bIsLocked;
155 value["icon"] = m_strIconPath;
156 value["channel"] = m_strChannelName;
157 CDateTime lastPlayed(m_iLastWatched);
158 value["lastplayed"] = lastPlayed.IsValid() ? lastPlayed.GetAsDBDate() : StringUtils::EmptyString;
159 value["channelnumber"] = m_iCachedChannelNumber;
163 epg.Serialize(value);
166 /********** XBMC related channel methods **********/
168 bool CPVRChannel::Delete(void)
170 bool bReturn = false;
171 CPVRDatabase *database = GetPVRDatabase();
175 /* delete the EPG table */
176 CEpg *epg = GetEPG();
179 CPVRChannelPtr empty;
180 epg->SetChannel(empty);
181 g_EpgContainer.DeleteEpg(*epg, true);
182 CSingleLock lock(m_critSection);
183 m_bEPGCreated = false;
186 bReturn = database->Delete(*this);
190 CEpg *CPVRChannel::GetEPG(void) const
194 CSingleLock lock(m_critSection);
195 if (!m_bIsHidden && m_bEPGEnabled && m_iEpgId > 0)
199 return iEpgId > 0 ? g_EpgContainer.GetById(iEpgId) : NULL;
202 bool CPVRChannel::UpdateFromClient(const CPVRChannel &channel)
204 SetClientID(channel.ClientID());
205 SetClientChannelNumber(channel.ClientChannelNumber());
206 SetInputFormat(channel.InputFormat());
207 SetStreamURL(channel.StreamURL());
208 SetEncryptionSystem(channel.EncryptionSystem());
209 SetClientChannelName(channel.ClientChannelName());
211 CSingleLock lock(m_critSection);
212 if (m_strChannelName.IsEmpty())
213 SetChannelName(channel.ClientChannelName());
214 if (m_strIconPath.IsEmpty()||(!m_strIconPath.Equals(channel.IconPath()) && !IsUserSetIcon()))
215 SetIconPath(channel.IconPath());
220 bool CPVRChannel::Persist(bool bQueueWrite /* = false */)
224 CSingleLock lock(m_critSection);
225 if (!m_bChanged && m_iChannelId > 0)
229 if (CPVRDatabase *database = GetPVRDatabase())
231 bool bReturn = database->Persist(*this, bQueueWrite);
232 CSingleLock lock(m_critSection);
233 m_bChanged = !bReturn;
240 bool CPVRChannel::SetChannelID(int iChannelId)
242 CSingleLock lock(m_critSection);
243 if (m_iChannelId != iChannelId)
246 m_iChannelId = iChannelId;
256 int CPVRChannel::ChannelNumber(void) const
258 CSingleLock lock(m_critSection);
259 return m_iCachedChannelNumber;
262 bool CPVRChannel::SetHidden(bool bIsHidden)
264 CSingleLock lock(m_critSection);
266 if (m_bIsHidden != bIsHidden)
268 /* update the hidden flag */
269 m_bIsHidden = bIsHidden;
270 m_bEPGEnabled = !bIsHidden;
280 bool CPVRChannel::SetLocked(bool bIsLocked)
282 CSingleLock lock(m_critSection);
284 if (m_bIsLocked != bIsLocked)
286 /* update the locked flag */
287 m_bIsLocked = bIsLocked;
297 bool CPVRChannel::IsRecording(void) const
299 return g_PVRTimers->IsRecordingOnChannel(*this);
302 bool CPVRChannel::SetIconPath(const CStdString &strIconPath, bool bIsUserSetIcon /* = false */)
304 CSingleLock lock(m_critSection);
306 if (m_strIconPath != strIconPath)
308 /* update the path */
309 m_strIconPath.Format("%s", strIconPath);
313 /* did the user change the icon? */
315 m_bIsUserSetIcon = !m_strIconPath.IsEmpty();
323 bool CPVRChannel::SetChannelName(const CStdString &strChannelName)
325 CStdString strName(strChannelName);
327 if (strName.IsEmpty())
328 strName.Format(g_localizeStrings.Get(19085), ClientChannelNumber());
330 CSingleLock lock(m_critSection);
331 if (m_strChannelName != strName)
333 /* update the channel name */
334 m_strChannelName = strName;
344 bool CPVRChannel::SetVirtual(bool bIsVirtual)
346 CSingleLock lock(m_critSection);
348 if (m_bIsVirtual != bIsVirtual)
350 /* update the virtual flag */
351 m_bIsVirtual = bIsVirtual;
361 bool CPVRChannel::SetLastWatched(time_t iLastWatched)
363 CSingleLock lock(m_critSection);
365 if (m_iLastWatched != iLastWatched)
367 /* update last watched */
368 m_iLastWatched = iLastWatched;
378 bool CPVRChannel::IsEmpty() const
380 CSingleLock lock(m_critSection);
381 return (m_strFileNameAndPath.IsEmpty() ||
382 m_strStreamURL.IsEmpty());
385 /********** Client related channel methods **********/
387 bool CPVRChannel::SetUniqueID(int iUniqueId)
389 CSingleLock lock(m_critSection);
391 if (m_iUniqueId != iUniqueId)
393 /* update the unique ID */
394 m_iUniqueId = iUniqueId;
404 bool CPVRChannel::SetClientID(int iClientId)
406 CSingleLock lock(m_critSection);
408 if (m_iClientId != iClientId)
410 /* update the client ID */
411 m_iClientId = iClientId;
421 bool CPVRChannel::SetClientChannelNumber(int iClientChannelNumber)
423 CSingleLock lock(m_critSection);
425 if (m_iClientChannelNumber != iClientChannelNumber && iClientChannelNumber > 0)
427 /* update the client channel number */
428 m_iClientChannelNumber = iClientChannelNumber;
438 bool CPVRChannel::SetClientChannelName(const CStdString &strClientChannelName)
440 CSingleLock lock(m_critSection);
442 if (m_strClientChannelName != strClientChannelName)
444 /* update the client channel name */
445 m_strClientChannelName.Format("%s", strClientChannelName);
447 // this is not persisted, so don't update m_bChanged
455 bool CPVRChannel::SetInputFormat(const CStdString &strInputFormat)
457 CSingleLock lock(m_critSection);
459 if (m_strInputFormat != strInputFormat)
461 /* update the input format */
462 m_strInputFormat.Format("%s", strInputFormat);
472 bool CPVRChannel::SetStreamURL(const CStdString &strStreamURL)
474 CSingleLock lock(m_critSection);
476 if (m_strStreamURL != strStreamURL)
478 /* update the stream url */
479 m_strStreamURL.Format("%s", strStreamURL);
489 void CPVRChannel::UpdatePath(CPVRChannelGroupInternal* group, unsigned int iNewChannelGroupPosition)
493 CStdString strFileNameAndPath;
494 CSingleLock lock(m_critSection);
495 strFileNameAndPath.Format("pvr://channels/%s/%s/%i.pvr", (m_bIsRadio ? "radio" : "tv"), group->GroupName().c_str(), iNewChannelGroupPosition);
496 if (m_strFileNameAndPath != strFileNameAndPath)
498 m_strFileNameAndPath = strFileNameAndPath;
503 bool CPVRChannel::SetEncryptionSystem(int iClientEncryptionSystem)
505 CSingleLock lock(m_critSection);
507 if (m_iClientEncryptionSystem != iClientEncryptionSystem)
509 /* update the client encryption system */
510 m_iClientEncryptionSystem = iClientEncryptionSystem;
511 UpdateEncryptionName();
521 void CPVRChannel::UpdateEncryptionName(void)
523 // http://www.dvb.org/index.php?id=174
524 // http://en.wikipedia.org/wiki/Conditional_access_system
525 CStdString strName(g_localizeStrings.Get(13205)); /* Unknown */
526 CSingleLock lock(m_critSection);
528 if ( m_iClientEncryptionSystem == 0x0000)
529 strName = g_localizeStrings.Get(19013); /* Free To Air */
530 else if (m_iClientEncryptionSystem >= 0x0001 &&
531 m_iClientEncryptionSystem <= 0x009F)
532 strName = g_localizeStrings.Get(19014); /* Fixed */
533 else if (m_iClientEncryptionSystem >= 0x00A0 &&
534 m_iClientEncryptionSystem <= 0x00A1)
535 strName = g_localizeStrings.Get(338); /* Analog */
536 else if (m_iClientEncryptionSystem >= 0x00A2 &&
537 m_iClientEncryptionSystem <= 0x00FF)
538 strName = g_localizeStrings.Get(19014); /* Fixed */
539 else if (m_iClientEncryptionSystem >= 0x0100 &&
540 m_iClientEncryptionSystem <= 0x01FF)
541 strName = "SECA Mediaguard";
542 else if (m_iClientEncryptionSystem == 0x0464)
544 else if (m_iClientEncryptionSystem >= 0x0500 &&
545 m_iClientEncryptionSystem <= 0x05FF)
546 strName = "Viaccess";
547 else if (m_iClientEncryptionSystem >= 0x0600 &&
548 m_iClientEncryptionSystem <= 0x06FF)
550 else if (m_iClientEncryptionSystem >= 0x0900 &&
551 m_iClientEncryptionSystem <= 0x09FF)
552 strName = "NDS Videoguard";
553 else if (m_iClientEncryptionSystem >= 0x0B00 &&
554 m_iClientEncryptionSystem <= 0x0BFF)
556 else if (m_iClientEncryptionSystem >= 0x0D00 &&
557 m_iClientEncryptionSystem <= 0x0DFF)
558 strName = "CryptoWorks";
559 else if (m_iClientEncryptionSystem >= 0x0E00 &&
560 m_iClientEncryptionSystem <= 0x0EFF)
562 else if (m_iClientEncryptionSystem == 0x1000)
564 else if (m_iClientEncryptionSystem >= 0x1200 &&
565 m_iClientEncryptionSystem <= 0x12FF)
566 strName = "NagraVision";
567 else if (m_iClientEncryptionSystem >= 0x1700 &&
568 m_iClientEncryptionSystem <= 0x17FF)
569 strName = "BetaCrypt";
570 else if (m_iClientEncryptionSystem >= 0x1800 &&
571 m_iClientEncryptionSystem <= 0x18FF)
572 strName = "NagraVision";
573 else if (m_iClientEncryptionSystem == 0x22F0)
574 strName = "Codicrypt";
575 else if (m_iClientEncryptionSystem == 0x2600)
577 else if (m_iClientEncryptionSystem == 0x4347)
579 else if (m_iClientEncryptionSystem == 0x4800)
580 strName = "Accessgate";
581 else if (m_iClientEncryptionSystem == 0x4900)
582 strName = "China Crypt";
583 else if (m_iClientEncryptionSystem == 0x4A10)
585 else if (m_iClientEncryptionSystem == 0x4A20)
586 strName = "AlphaCrypt";
587 else if (m_iClientEncryptionSystem == 0x4A70)
588 strName = "DreamCrypt";
589 else if (m_iClientEncryptionSystem == 0x4A60)
590 strName = "SkyCrypt";
591 else if (m_iClientEncryptionSystem == 0x4A61)
592 strName = "Neotioncrypt";
593 else if (m_iClientEncryptionSystem == 0x4A62)
594 strName = "SkyCrypt";
595 else if (m_iClientEncryptionSystem == 0x4A63)
596 strName = "Neotion SHL";
597 else if (m_iClientEncryptionSystem >= 0x4A64 &&
598 m_iClientEncryptionSystem <= 0x4A6F)
599 strName = "SkyCrypt";
600 else if (m_iClientEncryptionSystem == 0x4A80)
601 strName = "ThalesCrypt";
602 else if (m_iClientEncryptionSystem == 0x4AA1)
604 else if (m_iClientEncryptionSystem == 0x4ABF)
605 strName = "DG-Crypt";
606 else if (m_iClientEncryptionSystem >= 0x4AD0 &&
607 m_iClientEncryptionSystem <= 0x4AD1)
609 else if (m_iClientEncryptionSystem == 0x4AD4)
610 strName = "OmniCrypt";
611 else if (m_iClientEncryptionSystem == 0x4AE0)
612 strName = "RossCrypt";
613 else if (m_iClientEncryptionSystem == 0x5500)
615 else if (m_iClientEncryptionSystem == 0x5501)
618 if (m_iClientEncryptionSystem >= 0)
619 strName.AppendFormat(" (%04X)", m_iClientEncryptionSystem);
621 m_strClientEncryptionName = strName;
624 /********** EPG methods **********/
626 int CPVRChannel::GetEPG(CFileItemList &results) const
628 CEpg *epg = GetEPG();
631 CLog::Log(LOGDEBUG, "PVR - %s - cannot get EPG for channel '%s'",
632 __FUNCTION__, m_strChannelName.c_str());
636 return epg->Get(results);
639 bool CPVRChannel::ClearEPG() const
641 CEpg *epg = GetEPG();
648 bool CPVRChannel::GetEPGNow(CEpgInfoTag &tag) const
650 CEpg *epg = GetEPG();
651 return epg ? epg->InfoTagNow(tag) : false;
654 bool CPVRChannel::GetEPGNext(CEpgInfoTag &tag) const
656 CEpg *epg = GetEPG();
657 return epg ? epg->InfoTagNext(tag) : false;
660 bool CPVRChannel::SetEPGEnabled(bool bEPGEnabled)
662 CSingleLock lock(m_critSection);
664 if (m_bEPGEnabled != bEPGEnabled)
666 /* update the EPG flag */
667 m_bEPGEnabled = bEPGEnabled;
671 /* clear the previous EPG entries if needed */
672 if (!m_bEPGEnabled && m_bEPGCreated)
681 bool CPVRChannel::SetEPGScraper(const CStdString &strScraper)
683 CSingleLock lock(m_critSection);
685 if (m_strEPGScraper != strScraper)
687 bool bCleanEPG = !m_strEPGScraper.IsEmpty() || strScraper.IsEmpty();
689 /* update the scraper name */
690 m_strEPGScraper.Format("%s", strScraper);
694 /* clear the previous EPG entries if needed */
695 if (bCleanEPG && m_bEPGEnabled && m_bEPGCreated)
704 void CPVRChannel::SetCachedChannelNumber(unsigned int iChannelNumber)
706 CSingleLock lock(m_critSection);
707 m_iCachedChannelNumber = iChannelNumber;
710 void CPVRChannel::ToSortable(SortItem& sortable, Field field) const
712 if (field == FieldChannelName)
714 CSingleLock lock(m_critSection);
715 sortable[FieldChannelName] = m_strChannelName;
719 int CPVRChannel::ChannelID(void) const
721 CSingleLock lock(m_critSection);
725 bool CPVRChannel::IsNew(void) const
727 CSingleLock lock(m_critSection);
728 return m_iChannelId <= 0;
731 bool CPVRChannel::IsHidden(void) const
733 CSingleLock lock(m_critSection);
737 bool CPVRChannel::IsLocked(void) const
739 CSingleLock lock(m_critSection);
743 CStdString CPVRChannel::IconPath(void) const
745 CSingleLock lock(m_critSection);
746 CStdString strReturn(m_strIconPath);
750 bool CPVRChannel::IsUserSetIcon(void) const
752 CSingleLock lock(m_critSection);
753 return m_bIsUserSetIcon;
756 CStdString CPVRChannel::ChannelName(void) const
758 CSingleLock lock(m_critSection);
759 return m_strChannelName;
762 bool CPVRChannel::IsVirtual(void) const
764 CSingleLock lock(m_critSection);
768 time_t CPVRChannel::LastWatched(void) const
770 CSingleLock lock(m_critSection);
771 return m_iLastWatched;
774 bool CPVRChannel::IsChanged() const
776 CSingleLock lock(m_critSection);
780 int CPVRChannel::UniqueID(void) const
782 CSingleLock lock(m_critSection);
786 int CPVRChannel::ClientID(void) const
788 CSingleLock lock(m_critSection);
792 int CPVRChannel::ClientChannelNumber(void) const
794 CSingleLock lock(m_critSection);
795 return m_iClientChannelNumber;
798 CStdString CPVRChannel::ClientChannelName(void) const
800 CSingleLock lock(m_critSection);
801 CStdString strReturn(m_strClientChannelName);
805 CStdString CPVRChannel::InputFormat(void) const
807 CSingleLock lock(m_critSection);
808 CStdString strReturn(m_strInputFormat);
812 CStdString CPVRChannel::StreamURL(void) const
814 CSingleLock lock(m_critSection);
815 CStdString strReturn(m_strStreamURL);
819 CStdString CPVRChannel::Path(void) const
821 CSingleLock lock(m_critSection);
822 CStdString strReturn(m_strFileNameAndPath);
826 bool CPVRChannel::IsEncrypted(void) const
828 CSingleLock lock(m_critSection);
829 return m_iClientEncryptionSystem > 0;
832 int CPVRChannel::EncryptionSystem(void) const
834 CSingleLock lock(m_critSection);
835 return m_iClientEncryptionSystem;
838 CStdString CPVRChannel::EncryptionName(void) const
840 CSingleLock lock(m_critSection);
841 CStdString strReturn(m_strClientEncryptionName);
845 int CPVRChannel::EpgID(void) const
847 CSingleLock lock(m_critSection);
851 void CPVRChannel::SetEpgID(int iEpgId)
853 CSingleLock lock(m_critSection);
858 bool CPVRChannel::EPGEnabled(void) const
860 CSingleLock lock(m_critSection);
861 return m_bEPGEnabled;
864 CStdString CPVRChannel::EPGScraper(void) const
866 CSingleLock lock(m_critSection);
867 CStdString strReturn(m_strEPGScraper);
871 bool CPVRChannel::CanRecord(void) const
873 return g_PVRClients->SupportsRecordings(m_iClientId);