diff options
-rw-r--r-- | addons/skin.confluence/720p/MyPVRChannels.xml | 4 | ||||
-rw-r--r-- | addons/xbmc.pvr/addon.xml | 3 | ||||
-rw-r--r-- | xbmc/GUIInfoManager.cpp | 30 | ||||
-rw-r--r-- | xbmc/GUIInfoManager.h | 2 | ||||
-rw-r--r-- | xbmc/addons/include/xbmc_pvr_types.h | 5 | ||||
-rw-r--r-- | xbmc/epg/Epg.cpp | 6 | ||||
-rw-r--r-- | xbmc/epg/Epg.h | 1 | ||||
-rw-r--r-- | xbmc/pvr/PVRDatabase.cpp | 44 | ||||
-rw-r--r-- | xbmc/pvr/PVRDatabase.h | 2 | ||||
-rw-r--r-- | xbmc/pvr/addons/PVRClient.cpp | 1 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannel.cpp | 144 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannel.h | 67 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroup.cpp | 62 | ||||
-rw-r--r-- | xbmc/pvr/channels/PVRChannelGroup.h | 14 |
14 files changed, 233 insertions, 152 deletions
diff --git a/addons/skin.confluence/720p/MyPVRChannels.xml b/addons/skin.confluence/720p/MyPVRChannels.xml index e9eb87606a..3d6f2aff29 100644 --- a/addons/skin.confluence/720p/MyPVRChannels.xml +++ b/addons/skin.confluence/720p/MyPVRChannels.xml @@ -218,7 +218,7 @@ <aligny>center</aligny> <textcolor>grey</textcolor> <selectedcolor>grey</selectedcolor> - <info>ListItem.ChannelNumber</info> + <info>ListItem.ChannelNumberLabel</info> </control> <control type="label"> <left>50</left> @@ -314,7 +314,7 @@ <aligny>center</aligny> <textcolor>grey</textcolor> <selectedcolor>grey</selectedcolor> - <info>ListItem.ChannelNumber</info> + <info>ListItem.ChannelNumberLabel</info> </control> <control type="label"> <left>50</left> diff --git a/addons/xbmc.pvr/addon.xml b/addons/xbmc.pvr/addon.xml index 9296eae565..63bb6808af 100644 --- a/addons/xbmc.pvr/addon.xml +++ b/addons/xbmc.pvr/addon.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<addon id="xbmc.pvr" version="1.9.1" provider-name="Team-Kodi"> - <backwards-compatibility abi="1.9.0"/> +<addon id="xbmc.pvr" version="1.9.2" provider-name="Team-Kodi"> <requires> <import addon="xbmc.core" version="0.1.0"/> </requires> diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index c262c1bb24..6492562c40 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -579,6 +579,8 @@ const infomap listitem_labels[]= {{ "thumb", LISTITEM_THUMB }, { "nextenddate", LISTITEM_NEXT_ENDDATE }, { "channelname", LISTITEM_CHANNEL_NAME }, { "channelnumber", LISTITEM_CHANNEL_NUMBER }, + { "subchannelnumber", LISTITEM_SUB_CHANNEL_NUMBER }, + { "channelnumberlabel", LISTITEM_CHANNEL_NUMBER_LBL }, { "channelgroup", LISTITEM_CHANNEL_GROUP }, { "hasepg", LISTITEM_HAS_EPG }, { "hastimer", LISTITEM_HASTIMER }, @@ -4956,6 +4958,34 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std::s return number; } break; + case LISTITEM_SUB_CHANNEL_NUMBER: + { + CStdString number; + if (item->HasPVRChannelInfoTag()) + number = StringUtils::Format("%i", item->GetPVRChannelInfoTag()->SubChannelNumber()); + if (item->HasEPGInfoTag() && item->GetEPGInfoTag()->HasPVRChannel()) + number = StringUtils::Format("%i", item->GetEPGInfoTag()->ChannelTag()->SubChannelNumber()); + if (item->HasPVRTimerInfoTag()) + number = StringUtils::Format("%i", item->GetPVRTimerInfoTag()->ChannelTag()->SubChannelNumber()); + + return number; + } + break; + case LISTITEM_CHANNEL_NUMBER_LBL: + { + CPVRChannelPtr channel; + if (item->HasPVRChannelInfoTag()) + channel = CPVRChannelPtr(new CPVRChannel(*item->GetPVRChannelInfoTag())); + else if (item->HasEPGInfoTag() && item->GetEPGInfoTag()->HasPVRChannel()) + channel = item->GetEPGInfoTag()->ChannelTag(); + else if (item->HasPVRTimerInfoTag()) + channel = item->GetPVRTimerInfoTag()->ChannelTag(); + + return channel ? + channel->FormattedChannelNumber() : + ""; + } + break; case LISTITEM_CHANNEL_NAME: if (item->HasPVRChannelInfoTag()) return item->GetPVRChannelInfoTag()->ChannelName(); diff --git a/xbmc/GUIInfoManager.h b/xbmc/GUIInfoManager.h index e595c59a20..0b5f5e938f 100644 --- a/xbmc/GUIInfoManager.h +++ b/xbmc/GUIInfoManager.h @@ -649,6 +649,8 @@ namespace INFO #define LISTITEM_IS_STEREOSCOPIC (LISTITEM_START + 141) #define LISTITEM_INPROGRESS (LISTITEM_START + 142) #define LISTITEM_HASRECORDING (LISTITEM_START + 143) +#define LISTITEM_SUB_CHANNEL_NUMBER (LISTITEM_START + 144) +#define LISTITEM_CHANNEL_NUMBER_LBL (LISTITEM_START + 145) #define LISTITEM_PROPERTY_START (LISTITEM_START + 200) #define LISTITEM_PROPERTY_END (LISTITEM_PROPERTY_START + 1000) diff --git a/xbmc/addons/include/xbmc_pvr_types.h b/xbmc/addons/include/xbmc_pvr_types.h index 70bd5fae12..b218943534 100644 --- a/xbmc/addons/include/xbmc_pvr_types.h +++ b/xbmc/addons/include/xbmc_pvr_types.h @@ -75,10 +75,10 @@ struct DemuxPacket; #define PVR_STREAM_MAX_STREAMS 20 /* current PVR API version */ -#define XBMC_PVR_API_VERSION "1.9.1" +#define XBMC_PVR_API_VERSION "1.9.2" /* min. PVR API version */ -#define XBMC_PVR_MIN_API_VERSION "1.9.1" +#define XBMC_PVR_MIN_API_VERSION "1.9.2" #ifdef __cplusplus extern "C" { @@ -225,6 +225,7 @@ extern "C" { unsigned int iUniqueId; /*!< @brief (required) unique identifier for this channel */ bool bIsRadio; /*!< @brief (required) true if this is a radio channel, false if it's a TV channel */ unsigned int iChannelNumber; /*!< @brief (optional) channel number of this channel on the backend */ + unsigned int iSubChannelNumber; /*!< @brief (optional) sub channel number of this channel on the backend (ATSC) */ char strChannelName[PVR_ADDON_NAME_STRING_LENGTH]; /*!< @brief (optional) channel name given to this channel */ char strInputFormat[PVR_ADDON_INPUT_FORMAT_STRING_LENGTH]; /*!< @brief (optional) input format type. types can be found in ffmpeg/libavformat/allformats.c leave empty if unknown */ diff --git a/xbmc/epg/Epg.cpp b/xbmc/epg/Epg.cpp index 3ec1e8e492..44ea32b397 100644 --- a/xbmc/epg/Epg.cpp +++ b/xbmc/epg/Epg.cpp @@ -844,6 +844,12 @@ int CEpg::ChannelNumber(void) const return m_pvrChannel ? m_pvrChannel->ChannelNumber() : -1; } +int CEpg::SubChannelNumber(void) const +{ + CSingleLock lock(m_critSection); + return m_pvrChannel ? m_pvrChannel->SubChannelNumber() : -1; +} + void CEpg::SetChannel(PVR::CPVRChannelPtr channel) { CSingleLock lock(m_critSection); diff --git a/xbmc/epg/Epg.h b/xbmc/epg/Epg.h index e91db4abed..4a5c66eb44 100644 --- a/xbmc/epg/Epg.h +++ b/xbmc/epg/Epg.h @@ -80,6 +80,7 @@ namespace EPG int ChannelID(void) const; int ChannelNumber(void) const; + int SubChannelNumber(void) const; /*! * @brief Channel the channel tag linked to this EPG table. diff --git a/xbmc/pvr/PVRDatabase.cpp b/xbmc/pvr/PVRDatabase.cpp index 807b9a297c..975f31d563 100644 --- a/xbmc/pvr/PVRDatabase.cpp +++ b/xbmc/pvr/PVRDatabase.cpp @@ -75,6 +75,7 @@ void CPVRDatabase::CreateTables() // TODO use mapping table "iClientId integer, " "iClientChannelNumber integer, " + "iClientSubChannelNumber integer, " "sInputFormat varchar(32), " "sStreamURL varchar(255), " "iEncryptionSystem integer, " @@ -90,6 +91,7 @@ void CPVRDatabase::CreateTables() // "idChannel integer primary key, " // "idClient integer, " // "iClientChannelNumber integer," + // "iClientSubChannelNumber integer," // "sInputFormat string," // "sStreamURL string," // "iEncryptionSystem integer" @@ -111,9 +113,10 @@ void CPVRDatabase::CreateTables() CLog::Log(LOGDEBUG, "PVR - %s - creating table 'map_channelgroups_channels'", __FUNCTION__); m_pDS->exec( "CREATE TABLE map_channelgroups_channels (" - "idChannel integer, " - "idGroup integer, " - "iChannelNumber integer" + "idChannel integer, " + "idGroup integer, " + "iChannelNumber integer, " + "iSubChannelNumber integer" ")" ); @@ -176,6 +179,14 @@ void CPVRDatabase::UpdateTables(int iVersion) if (iVersion < 25) m_pDS->exec("DROP TABLE IF EXISTS channelsettings"); + + if (iVersion < 26) + { + m_pDS->exec("ALTER TABLE channels ADD iClientSubChannelNumber integer"); + m_pDS->exec("UPDATE channels SET iClientSubChannelNumber = 0"); + m_pDS->exec("ALTER TABLE map_channelgroups_channels ADD iSubChannelNumber integer"); + m_pDS->exec("UPDATE map_channelgroups_channels SET iSubChannelNumber = 0"); + } } int CPVRDatabase::GetLastChannelId(void) @@ -242,7 +253,7 @@ int CPVRDatabase::Get(CPVRChannelGroupInternal &results) std::string strQuery = PrepareSQL("SELECT channels.idChannel, channels.iUniqueId, channels.bIsRadio, channels.bIsHidden, channels.bIsUserSetIcon, channels.bIsUserSetName, " "channels.sIconPath, channels.sChannelName, channels.bIsVirtual, channels.bEPGEnabled, channels.sEPGScraper, channels.iLastWatched, channels.iClientId, channels.bIsLocked, " - "channels.iClientChannelNumber, channels.sInputFormat, channels.sInputFormat, channels.sStreamURL, channels.iEncryptionSystem, map_channelgroups_channels.iChannelNumber, channels.idEpg " + "channels.iClientChannelNumber, channels.iClientSubChannelNumber, channels.sInputFormat, channels.sInputFormat, channels.sStreamURL, channels.iEncryptionSystem, map_channelgroups_channels.iChannelNumber, channels.idEpg " "FROM map_channelgroups_channels " "LEFT JOIN channels ON channels.idChannel = map_channelgroups_channels.idChannel " "WHERE map_channelgroups_channels.idGroup = %u", results.IsRadio() ? XBMC_INTERNAL_GROUP_RADIO : XBMC_INTERNAL_GROUP_TV); @@ -269,7 +280,8 @@ int CPVRDatabase::Get(CPVRChannelGroupInternal &results) channel->m_strEPGScraper = m_pDS->fv("sEPGScraper").get_asString(); channel->m_iLastWatched = (time_t) m_pDS->fv("iLastWatched").get_asInt(); channel->m_iClientId = m_pDS->fv("iClientId").get_asInt(); - channel->m_iClientChannelNumber = m_pDS->fv("iClientChannelNumber").get_asInt(); + channel->m_iClientChannelNumber.channel = m_pDS->fv("iClientChannelNumber").get_asInt(); + channel->m_iClientChannelNumber.subchannel = m_pDS->fv("iClientSubChannelNumber").get_asInt(); channel->m_strInputFormat = m_pDS->fv("sInputFormat").get_asString(); channel->m_strStreamURL = m_pDS->fv("sStreamURL").get_asString(); channel->m_iClientEncryptionSystem = m_pDS->fv("iEncryptionSystem").get_asInt(); @@ -609,16 +621,16 @@ bool CPVRDatabase::PersistGroupMembers(CPVRChannelGroup &group) { PVRChannelGroupMember member = group.m_members.at(iChannelPtr); - std::string strWhereClause = PrepareSQL("idChannel = %u AND idGroup = %u AND iChannelNumber = %u", - member.channel->ChannelID(), group.GroupID(), member.iChannelNumber); + std::string strWhereClause = PrepareSQL("idChannel = %u AND idGroup = %u AND iChannelNumber = %u AND iSubChannelNumber = %u", + member.channel->ChannelID(), group.GroupID(), member.iChannelNumber, member.iSubChannelNumber); std::string strValue = GetSingleValue("map_channelgroups_channels", "idChannel", strWhereClause); if (strValue.empty()) { strQuery = PrepareSQL("REPLACE INTO map_channelgroups_channels (" - "idGroup, idChannel, iChannelNumber) " - "VALUES (%i, %i, %i);", - group.GroupID(), member.channel->ChannelID(), member.iChannelNumber); + "idGroup, idChannel, iChannelNumber, iSubChannelNumber) " + "VALUES (%i, %i, %i, %i);", + group.GroupID(), member.channel->ChannelID(), member.iChannelNumber, member.iSubChannelNumber); QueueInsertQuery(strQuery); } } @@ -751,11 +763,11 @@ bool CPVRDatabase::Persist(CPVRChannel &channel, bool bQueueWrite /* = false */) strQuery = PrepareSQL("INSERT INTO channels (" "iUniqueId, bIsRadio, bIsHidden, bIsUserSetIcon, bIsUserSetName, bIsLocked, " "sIconPath, sChannelName, bIsVirtual, bEPGEnabled, sEPGScraper, iLastWatched, iClientId, " - "iClientChannelNumber, sInputFormat, sStreamURL, iEncryptionSystem, idEpg) " - "VALUES (%i, %i, %i, %i, %i, %i, '%s', '%s', %i, %i, '%s', %u, %i, %i, '%s', '%s', %i, %i)", + "iClientChannelNumber, iClientSubChannelNumber, sInputFormat, sStreamURL, iEncryptionSystem, idEpg) " + "VALUES (%i, %i, %i, %i, %i, %i, '%s', '%s', %i, %i, '%s', %u, %i, %i, %i, '%s', '%s', %i, %i)", channel.UniqueID(), (channel.IsRadio() ? 1 :0), (channel.IsHidden() ? 1 : 0), (channel.IsUserSetIcon() ? 1 : 0), (channel.IsUserSetName() ? 1 : 0), (channel.IsLocked() ? 1 : 0), channel.IconPath().c_str(), channel.ChannelName().c_str(), (channel.IsVirtual() ? 1 : 0), (channel.EPGEnabled() ? 1 : 0), channel.EPGScraper().c_str(), channel.LastWatched(), channel.ClientID(), - channel.ClientChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem(), + channel.ClientChannelNumber(), channel.ClientSubChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem(), channel.EpgID()); } else @@ -764,11 +776,11 @@ bool CPVRDatabase::Persist(CPVRChannel &channel, bool bQueueWrite /* = false */) strQuery = PrepareSQL("REPLACE INTO channels (" "iUniqueId, bIsRadio, bIsHidden, bIsUserSetIcon, bIsUserSetName, bIsLocked, " "sIconPath, sChannelName, bIsVirtual, bEPGEnabled, sEPGScraper, iLastWatched, iClientId, " - "iClientChannelNumber, sInputFormat, sStreamURL, iEncryptionSystem, idChannel, idEpg) " - "VALUES (%i, %i, %i, %i, %i, %i, '%s', '%s', %i, %i, '%s', %u, %i, %i, '%s', '%s', %i, %i, %i)", + "iClientChannelNumber, iClientSubChannelNumber, sInputFormat, sStreamURL, iEncryptionSystem, idChannel, idEpg) " + "VALUES (%i, %i, %i, %i, %i, %i, '%s', '%s', %i, %i, '%s', %u, %i, %i, %i, '%s', '%s', %i, %i, %i)", channel.UniqueID(), (channel.IsRadio() ? 1 :0), (channel.IsHidden() ? 1 : 0), (channel.IsUserSetIcon() ? 1 : 0), (channel.IsUserSetName() ? 1 : 0), (channel.IsLocked() ? 1 : 0), channel.IconPath().c_str(), channel.ChannelName().c_str(), (channel.IsVirtual() ? 1 : 0), (channel.EPGEnabled() ? 1 : 0), channel.EPGScraper().c_str(), channel.LastWatched(), channel.ClientID(), - channel.ClientChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem(), channel.ChannelID(), + channel.ClientChannelNumber(), channel.ClientSubChannelNumber(), channel.InputFormat().c_str(), channel.StreamURL().c_str(), channel.EncryptionSystem(), channel.ChannelID(), channel.EpgID()); } diff --git a/xbmc/pvr/PVRDatabase.h b/xbmc/pvr/PVRDatabase.h index b05c36b63d..f57459c2a6 100644 --- a/xbmc/pvr/PVRDatabase.h +++ b/xbmc/pvr/PVRDatabase.h @@ -59,7 +59,7 @@ namespace PVR * @brief Get the minimal database version that is required to operate correctly. * @return The minimal database version. */ - virtual int GetSchemaVersion() const { return 25; }; + virtual int GetSchemaVersion() const { return 26; }; /*! * @brief Get the default sqlite database filename. diff --git a/xbmc/pvr/addons/PVRClient.cpp b/xbmc/pvr/addons/PVRClient.cpp index f6b1ad3a5e..842e717d01 100644 --- a/xbmc/pvr/addons/PVRClient.cpp +++ b/xbmc/pvr/addons/PVRClient.cpp @@ -300,6 +300,7 @@ void CPVRClient::WriteClientChannelInfo(const CPVRChannel &xbmcChannel, PVR_CHAN addonChannel.iUniqueId = xbmcChannel.UniqueID(); addonChannel.iChannelNumber = xbmcChannel.ClientChannelNumber(); + addonChannel.iSubChannelNumber = xbmcChannel.ClientSubChannelNumber(); strncpy(addonChannel.strChannelName, xbmcChannel.ClientChannelName().c_str(), sizeof(addonChannel.strChannelName) - 1); strncpy(addonChannel.strIconPath, xbmcChannel.IconPath().c_str(), sizeof(addonChannel.strIconPath) - 1); addonChannel.iEncryptionSystem = xbmcChannel.EncryptionSystem(); diff --git a/xbmc/pvr/channels/PVRChannel.cpp b/xbmc/pvr/channels/PVRChannel.cpp index 262bf381a1..ee860024f1 100644 --- a/xbmc/pvr/channels/PVRChannel.cpp +++ b/xbmc/pvr/channels/PVRChannel.cpp @@ -60,6 +60,7 @@ CPVRChannel::CPVRChannel(bool bRadio /* = false */) m_iLastWatched = 0; m_bChanged = false; m_iCachedChannelNumber = 0; + m_iCachedSubChannelNumber = 0; m_iEpgId = -1; m_bEPGCreated = false; @@ -68,7 +69,8 @@ CPVRChannel::CPVRChannel(bool bRadio /* = false */) m_iUniqueId = -1; m_iClientId = -1; - m_iClientChannelNumber = -1; + m_iClientChannelNumber.channel = 0; + m_iClientChannelNumber.subchannel = 0; m_iClientEncryptionSystem = -1; UpdateEncryptionName(); } @@ -84,12 +86,14 @@ CPVRChannel::CPVRChannel(const PVR_CHANNEL &channel, unsigned int iClientId) m_strIconPath = channel.strIconPath; m_strChannelName = channel.strChannelName; m_iUniqueId = channel.iUniqueId; - m_iClientChannelNumber = channel.iChannelNumber; + m_iClientChannelNumber.channel = channel.iChannelNumber; + m_iClientChannelNumber.subchannel = channel.iSubChannelNumber; m_strClientChannelName = channel.strChannelName; m_strInputFormat = channel.strInputFormat; m_strStreamURL = channel.strStreamURL; m_iClientEncryptionSystem = channel.iEncryptionSystem; m_iCachedChannelNumber = 0; + m_iCachedSubChannelNumber = 0; m_iClientId = iClientId; m_bIsVirtual = false; m_iLastWatched = 0; @@ -126,13 +130,15 @@ CPVRChannel &CPVRChannel::operator=(const CPVRChannel &channel) m_strEPGScraper = channel.m_strEPGScraper; m_iUniqueId = channel.m_iUniqueId; m_iClientId = channel.m_iClientId; - m_iClientChannelNumber = channel.m_iClientChannelNumber; + m_iClientChannelNumber.channel = channel.m_iClientChannelNumber.channel; + m_iClientChannelNumber.subchannel = channel.m_iClientChannelNumber.subchannel; m_strClientChannelName = channel.m_strClientChannelName; m_strInputFormat = channel.m_strInputFormat; m_strStreamURL = channel.m_strStreamURL; m_strFileNameAndPath = channel.m_strFileNameAndPath; m_iClientEncryptionSystem = channel.m_iClientEncryptionSystem; m_iCachedChannelNumber = channel.m_iCachedChannelNumber; + m_iCachedSubChannelNumber = channel.m_iCachedSubChannelNumber; m_iEpgId = channel.m_iEpgId; m_bEPGCreated = channel.m_bEPGCreated; m_bChanged = channel.m_bChanged; @@ -153,6 +159,7 @@ void CPVRChannel::Serialize(CVariant& value) const CDateTime lastPlayed(m_iLastWatched); value["lastplayed"] = lastPlayed.IsValid() ? lastPlayed.GetAsDBDate() : ""; value["channelnumber"] = m_iCachedChannelNumber; + value["subchannelnumber"] = m_iCachedSubChannelNumber; CEpgInfoTag epg; if (GetEPGNow(epg)) @@ -198,14 +205,27 @@ CEpg *CPVRChannel::GetEPG(void) const bool CPVRChannel::UpdateFromClient(const CPVRChannel &channel) { SetClientID(channel.ClientID()); - SetClientChannelNumber(channel.ClientChannelNumber()); - SetInputFormat(channel.InputFormat()); SetStreamURL(channel.StreamURL()); - SetEncryptionSystem(channel.EncryptionSystem()); - SetClientChannelName(channel.ClientChannelName()); CSingleLock lock(m_critSection); - + + if (m_iClientChannelNumber.channel != channel.ClientChannelNumber() || + m_iClientChannelNumber.subchannel != channel.ClientSubChannelNumber() || + m_strInputFormat != channel.InputFormat() || + m_iClientEncryptionSystem != channel.EncryptionSystem() || + m_strClientChannelName != channel.ClientChannelName()) + { + m_iClientChannelNumber.channel = channel.ClientChannelNumber(); + m_iClientChannelNumber.subchannel = channel.ClientSubChannelNumber(); + m_strInputFormat = channel.InputFormat(); + m_iClientEncryptionSystem = channel.EncryptionSystem(); + m_strClientChannelName = channel.ClientChannelName(); + + UpdateEncryptionName(); + m_bChanged = true; + SetChanged(); + } + // only update the channel name and icon if the user hasn't changed them manually if (m_strChannelName.empty() || !IsUserSetName()) SetChannelName(channel.ClientChannelName()); @@ -257,6 +277,12 @@ int CPVRChannel::ChannelNumber(void) const return m_iCachedChannelNumber; } +int CPVRChannel::SubChannelNumber(void) const +{ + CSingleLock lock(m_critSection); + return m_iCachedSubChannelNumber; +} + bool CPVRChannel::SetHidden(bool bIsHidden) { CSingleLock lock(m_critSection); @@ -422,57 +448,6 @@ bool CPVRChannel::SetClientID(int iClientId) return false; } -bool CPVRChannel::SetClientChannelNumber(int iClientChannelNumber) -{ - CSingleLock lock(m_critSection); - - if (m_iClientChannelNumber != iClientChannelNumber && iClientChannelNumber > 0) - { - /* update the client channel number */ - m_iClientChannelNumber = iClientChannelNumber; - SetChanged(); - m_bChanged = true; - - return true; - } - - return false; -} - -bool CPVRChannel::SetClientChannelName(const std::string &strClientChannelName) -{ - CSingleLock lock(m_critSection); - - if (m_strClientChannelName != strClientChannelName) - { - /* update the client channel name */ - m_strClientChannelName = StringUtils::Format("%s", strClientChannelName.c_str()); - SetChanged(); - // this is not persisted, so don't update m_bChanged - - return true; - } - - return false; -} - -bool CPVRChannel::SetInputFormat(const std::string &strInputFormat) -{ - CSingleLock lock(m_critSection); - - if (m_strInputFormat != strInputFormat) - { - /* update the input format */ - m_strInputFormat = StringUtils::Format("%s", strInputFormat.c_str()); - SetChanged(); - m_bChanged = true; - - return true; - } - - return false; -} - bool CPVRChannel::SetStreamURL(const std::string &strStreamURL) { CSingleLock lock(m_critSection); @@ -504,24 +479,6 @@ void CPVRChannel::UpdatePath(CPVRChannelGroupInternal* group, unsigned int iNewC } } -bool CPVRChannel::SetEncryptionSystem(int iClientEncryptionSystem) -{ - CSingleLock lock(m_critSection); - - if (m_iClientEncryptionSystem != iClientEncryptionSystem) - { - /* update the client encryption system */ - m_iClientEncryptionSystem = iClientEncryptionSystem; - UpdateEncryptionName(); - SetChanged(); - m_bChanged = true; - - return true; - } - - return false; -} - void CPVRChannel::UpdateEncryptionName(void) { // http://www.dvb.org/index.php?id=174 @@ -711,6 +668,12 @@ void CPVRChannel::SetCachedChannelNumber(unsigned int iChannelNumber) m_iCachedChannelNumber = iChannelNumber; } +void CPVRChannel::SetCachedSubChannelNumber(unsigned int iSubChannelNumber) +{ + CSingleLock lock(m_critSection); + m_iCachedSubChannelNumber = iSubChannelNumber; +} + void CPVRChannel::ToSortable(SortItem& sortable, Field field) const { CSingleLock lock(m_critSection); @@ -738,6 +701,23 @@ bool CPVRChannel::IsHidden(void) const return m_bIsHidden; } +bool CPVRChannel::IsSubChannel(void) const +{ + return SubChannelNumber() > 0; +} + +bool CPVRChannel::IsClientSubChannel(void) const +{ + return ClientSubChannelNumber() > 0; +} + +std::string CPVRChannel::FormattedChannelNumber(void) const +{ + return !IsSubChannel() ? + StringUtils::Format("%i", ChannelNumber()) : + StringUtils::Format("%i.%i", ChannelNumber(), SubChannelNumber()); +} + bool CPVRChannel::IsLocked(void) const { CSingleLock lock(m_critSection); @@ -804,10 +784,16 @@ int CPVRChannel::ClientID(void) const return m_iClientId; } -int CPVRChannel::ClientChannelNumber(void) const +unsigned int CPVRChannel::ClientChannelNumber(void) const +{ + CSingleLock lock(m_critSection); + return m_iClientChannelNumber.channel; +} + +unsigned int CPVRChannel::ClientSubChannelNumber(void) const { CSingleLock lock(m_critSection); - return m_iClientChannelNumber; + return m_iClientChannelNumber.subchannel; } std::string CPVRChannel::ClientChannelName(void) const diff --git a/xbmc/pvr/channels/PVRChannel.h b/xbmc/pvr/channels/PVRChannel.h index 9610294a94..63a16a1177 100644 --- a/xbmc/pvr/channels/PVRChannel.h +++ b/xbmc/pvr/channels/PVRChannel.h @@ -42,6 +42,12 @@ namespace PVR class CPVRChannel; typedef boost::shared_ptr<PVR::CPVRChannel> CPVRChannelPtr; + typedef struct + { + unsigned int channel; + unsigned int subchannel; + } pvr_channel_num; + /** PVR Channel class */ class CPVRChannel : public Observable, public ISerializable, public ISortable { @@ -107,6 +113,11 @@ namespace PVR int ChannelNumber(void) const; /*! + * @return The sub channel number used by XBMC by the currently active group. + */ + int SubChannelNumber(void) const; + + /*! * @return True if this channel is a radio channel, false if not. */ bool IsRadio(void) const { return m_bIsRadio; } @@ -116,6 +127,21 @@ namespace PVR */ bool IsHidden(void) const; + /** + * @return True when this is a sub channel, false if it's a main channel + */ + bool IsSubChannel(void) const; + + /** + * @return the channel number, formatted as [channel] or [channel].[subchannel] + */ + std::string FormattedChannelNumber(void) const; + + /** + * @return True when this channel is marked as sub channel by the add-on, false if it's marked as main channel + */ + bool IsClientSubChannel(void) const; + /*! * @brief Set to true to hide this channel. Set to false to unhide it. * @@ -256,18 +282,12 @@ namespace PVR /*! * @return The channel number on the client. */ - int ClientChannelNumber(void) const; + unsigned int ClientChannelNumber(void) const; /*! - * @brief Set the channel number on the client. - * - * Set the channel number on the client. - * It will only be changed in this tag and won't change anything on the client. - * - * @param iClientChannelNumber The new channel number - * @return True if the something changed, false otherwise. + * @return The sub channel number on the client (ATSC). */ - bool SetClientChannelNumber(int iClientChannelNumber); + unsigned int ClientSubChannelNumber(void) const; /*! * @return The name of this channel on the client. @@ -275,17 +295,6 @@ namespace PVR std::string ClientChannelName(void) const; /*! - * @brief Set the name of this channel on the client. - * - * Set the name of this channel on the client. - * It will only be changed in this tag and won't change anything on the client. - * - * @param strClientChannelName The new channel name - * @return True if the something changed, false otherwise. - */ - bool SetClientChannelName(const std::string &strClientChannelName); - - /*! * @brief The stream input type * * The stream input type @@ -298,13 +307,6 @@ namespace PVR std::string InputFormat(void) const; /*! - * @brief Set the stream input type - * @param strInputFormat The new input format. - * @return True if the something changed, false otherwise. - */ - bool SetInputFormat(const std::string &strInputFormat); - - /*! * @brief The stream URL to access this channel. * * The stream URL to access this channel. @@ -362,13 +364,6 @@ namespace PVR int EncryptionSystem(void) const; /*! - * @brief Set the encryption ID (CAID) for this channel. - * @param iClientEncryptionSystem The new CAID. - * @return True if the something changed, false otherwise. - */ - bool SetEncryptionSystem(int iClientEncryptionSystem); - - /*! * @return A friendly name for the used encryption system. */ std::string EncryptionName(void) const; @@ -462,6 +457,7 @@ namespace PVR bool SetEPGScraper(const std::string &strScraper); void SetCachedChannelNumber(unsigned int iChannelNumber); + void SetCachedSubChannelNumber(unsigned int iSubChannelNumber); bool CanRecord(void) const; //@} @@ -486,6 +482,7 @@ namespace PVR time_t m_iLastWatched; /*!< last time channel has been watched */ bool m_bChanged; /*!< true if anything in this entry was changed that needs to be persisted */ unsigned int m_iCachedChannelNumber; /*!< the cached channel number in the selected group */ + unsigned int m_iCachedSubChannelNumber; /*!< the cached sub channel number in the selected group */ //@} /*! @name EPG related channel data @@ -502,7 +499,7 @@ namespace PVR //@{ int m_iUniqueId; /*!< the unique identifier for this channel */ int m_iClientId; /*!< the identifier of the client that serves this channel */ - int m_iClientChannelNumber; /*!< the channel number on the client */ + pvr_channel_num m_iClientChannelNumber; /*!< the channel number on the client */ std::string m_strClientChannelName; /*!< the name of this channel on the client */ std::string m_strInputFormat; /*!< the stream input type based on ffmpeg/libavformat/allformats.c */ std::string m_strStreamURL; /*!< URL of the stream. Use the client to read stream if this is empty */ diff --git a/xbmc/pvr/channels/PVRChannelGroup.cpp b/xbmc/pvr/channels/PVRChannelGroup.cpp index 44913268e6..7fc3efaba0 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.cpp +++ b/xbmc/pvr/channels/PVRChannelGroup.cpp @@ -170,20 +170,22 @@ bool CPVRChannelGroup::Update(void) return UpdateGroupEntries(PVRChannels_tmp); } -bool CPVRChannelGroup::SetChannelNumber(const CPVRChannel &channel, unsigned int iChannelNumber) +bool CPVRChannelGroup::SetChannelNumber(const CPVRChannel &channel, unsigned int iChannelNumber, unsigned int iSubChannelNumber /* = 0 */) { bool bReturn(false); CSingleLock lock(m_critSection); - for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++) + for (std::vector<PVRChannelGroupMember>::iterator it = m_members.begin(); it != m_members.end(); ++it) { - if (*m_members.at(iChannelPtr).channel == channel) + if (*((*it).channel) == channel) { - if (m_members.at(iChannelPtr).iChannelNumber != iChannelNumber) + if ((*it).iChannelNumber != iChannelNumber || + (*it).iSubChannelNumber != iSubChannelNumber) { m_bChanged = true; bReturn = true; - m_members.at(iChannelPtr).iChannelNumber = iChannelNumber; + (*it).iChannelNumber = iChannelNumber; + (*it).iSubChannelNumber = iSubChannelNumber; } break; } @@ -317,6 +319,8 @@ struct sortByClientChannelNumber { bool operator()(const PVRChannelGroupMember &channel1, const PVRChannelGroupMember &channel2) { + if (channel1.channel->ClientChannelNumber() == channel2.channel->ClientChannelNumber()) + return channel1.channel->ClientSubChannelNumber() < channel2.channel->ClientSubChannelNumber(); return channel1.channel->ClientChannelNumber() < channel2.channel->ClientChannelNumber(); } }; @@ -325,6 +329,8 @@ struct sortByChannelNumber { bool operator()(const PVRChannelGroupMember &channel1, const PVRChannelGroupMember &channel2) { + if (channel1.iChannelNumber == channel2.iChannelNumber) + return channel1.iSubChannelNumber < channel2.iSubChannelNumber; return channel1.iChannelNumber < channel2.iChannelNumber; } }; @@ -463,6 +469,22 @@ CFileItemPtr CPVRChannelGroup::GetLastPlayedChannel(unsigned int iCurrentChannel return retVal; } +unsigned int CPVRChannelGroup::GetSubChannelNumber(const CPVRChannel &channel) const +{ + unsigned int iReturn = 0; + CSingleLock lock(m_critSection); + + for (std::vector<PVRChannelGroupMember>::const_iterator it = m_members.begin(); it != m_members.end(); ++it) + { + if ((*it).channel->ChannelID() == channel.ChannelID()) + { + iReturn = (*it).iSubChannelNumber; + break; + } + } + + return iReturn; +} unsigned int CPVRChannelGroup::GetChannelNumber(const CPVRChannel &channel) const { @@ -483,14 +505,14 @@ unsigned int CPVRChannelGroup::GetChannelNumber(const CPVRChannel &channel) cons return iReturn; } -CFileItemPtr CPVRChannelGroup::GetByChannelNumber(unsigned int iChannelNumber) const +CFileItemPtr CPVRChannelGroup::GetByChannelNumber(unsigned int iChannelNumber, unsigned int iSubChannelNumber /* = 0 */) const { CSingleLock lock(m_critSection); for (unsigned int ptr = 0; ptr < m_members.size(); ptr++) { PVRChannelGroupMember groupMember = m_members.at(ptr); - if (groupMember.iChannelNumber == iChannelNumber) + if (groupMember.iChannelNumber == iChannelNumber && (iSubChannelNumber == 0 || iSubChannelNumber == groupMember.iSubChannelNumber)) { CFileItemPtr retVal = CFileItemPtr(new CFileItem(*groupMember.channel)); return retVal; @@ -917,23 +939,34 @@ bool CPVRChannelGroup::Renumber(void) CSingleLock lock(m_critSection); - for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++) + for (std::vector<PVRChannelGroupMember>::iterator it = m_members.begin(); it != m_members.end(); ++it) { - unsigned int iCurrentChannelNumber; - if (m_members.at(iChannelPtr).channel->IsHidden()) + unsigned int iCurrentChannelNumber, iSubChannelNumber; + if ((*it).channel->IsHidden()) + { iCurrentChannelNumber = 0; + iSubChannelNumber = 0; + } else if (bUseBackendChannelNumbers) - iCurrentChannelNumber = m_members.at(iChannelPtr).channel->ClientChannelNumber(); + { + iCurrentChannelNumber = (*it).channel->ClientChannelNumber(); + iSubChannelNumber = (*it).channel->ClientSubChannelNumber(); + } else + { iCurrentChannelNumber = ++iChannelNumber; + iSubChannelNumber = 0; + } - if (m_members.at(iChannelPtr).iChannelNumber != iCurrentChannelNumber) + if ((*it).iChannelNumber != iCurrentChannelNumber || + (*it).iSubChannelNumber != iSubChannelNumber) { bReturn = true; m_bChanged = true; } - m_members.at(iChannelPtr).iChannelNumber = iCurrentChannelNumber; + (*it).iChannelNumber = iCurrentChannelNumber; + (*it).iSubChannelNumber = iSubChannelNumber; } SortByChannelNumber(); @@ -954,7 +987,10 @@ void CPVRChannelGroup::ResetChannelNumberCache(void) /* set all channel numbers on members of this group */ for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++) + { m_members.at(iChannelPtr).channel->SetCachedChannelNumber(m_members.at(iChannelPtr).iChannelNumber); + m_members.at(iChannelPtr).channel->SetCachedSubChannelNumber(m_members.at(iChannelPtr).iSubChannelNumber); + } } bool CPVRChannelGroup::HasChangedChannels(void) const diff --git a/xbmc/pvr/channels/PVRChannelGroup.h b/xbmc/pvr/channels/PVRChannelGroup.h index bc6ca4222d..f6a13de9eb 100644 --- a/xbmc/pvr/channels/PVRChannelGroup.h +++ b/xbmc/pvr/channels/PVRChannelGroup.h @@ -49,6 +49,7 @@ namespace PVR { CPVRChannelPtr channel; unsigned int iChannelNumber; + unsigned int iSubChannelNumber; } PVRChannelGroupMember; enum EpgDateType @@ -113,8 +114,9 @@ namespace PVR * @brief Change the channelnumber of a group. Used by CGUIDialogPVRChannelManager. Call SortByChannelNumber() and Renumber() after all changes are done. * @param channel The channel to change the channel number for. * @param iChannelNumber The new channel number. + * @param iSubChannelNumber The new sub channel number. */ - bool SetChannelNumber(const CPVRChannel &channel, unsigned int iChannelNumber); + bool SetChannelNumber(const CPVRChannel &channel, unsigned int iChannelNumber, unsigned int iSubChannelNumber = 0); /*! * @brief Move a channel from position iOldIndex to iNewIndex. @@ -270,9 +272,10 @@ namespace PVR /*! * @brief Get a channel given it's channel number. * @param iChannelNumber The channel number. + * * @param iSubChannelNumber The sub channel number. * @return The channel or NULL if it wasn't found. */ - CFileItemPtr GetByChannelNumber(unsigned int iChannelNumber) const; + CFileItemPtr GetByChannelNumber(unsigned int iChannelNumber, unsigned int iSubChannelNumber = 0) const; /*! * @brief Get the channel number in this group of the given channel. @@ -282,6 +285,13 @@ namespace PVR unsigned int GetChannelNumber(const CPVRChannel &channel) const; /*! + * @brief Get the sub channel number in this group of the given channel. + * @param channel The channel to get the sub channel number for. + * @return The sub channel number in this group or 0 if the channel isn't a member of this group. + */ + unsigned int GetSubChannelNumber(const CPVRChannel &channel) const; + + /*! * @brief Get the next channel in this group. * @param channel The current channel. * @return The channel or NULL if it wasn't found. |