aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/skin.confluence/720p/MyPVRChannels.xml4
-rw-r--r--addons/xbmc.pvr/addon.xml3
-rw-r--r--xbmc/GUIInfoManager.cpp30
-rw-r--r--xbmc/GUIInfoManager.h2
-rw-r--r--xbmc/addons/include/xbmc_pvr_types.h5
-rw-r--r--xbmc/epg/Epg.cpp6
-rw-r--r--xbmc/epg/Epg.h1
-rw-r--r--xbmc/pvr/PVRDatabase.cpp44
-rw-r--r--xbmc/pvr/PVRDatabase.h2
-rw-r--r--xbmc/pvr/addons/PVRClient.cpp1
-rw-r--r--xbmc/pvr/channels/PVRChannel.cpp144
-rw-r--r--xbmc/pvr/channels/PVRChannel.h67
-rw-r--r--xbmc/pvr/channels/PVRChannelGroup.cpp62
-rw-r--r--xbmc/pvr/channels/PVRChannelGroup.h14
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.