Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge remote branch 'opdenkamp/master'

  • Loading branch information...
commit 955a1baa706d0a0f3902cafe97da3b8b43534cb3 2 parents fa41cca + 91eb062
Marcel Groothuis authored
Showing with 1,389 additions and 1,005 deletions.
  1. +3 −0  configure.in
  2. 0  lib/addons/library.xbmc.addon/{Makefile → Makefile.in}
  3. 0  lib/addons/library.xbmc.gui/{Makefile → Makefile.in}
  4. 0  lib/addons/library.xbmc.pvr/{Makefile → Makefile.in}
  5. +0 −13 xbmc/addons/include/xbmc_pvr_types.h
  6. +34 −9 xbmc/epg/Epg.cpp
  7. +15 −1 xbmc/epg/Epg.h
  8. +1 −1  xbmc/epg/EpgContainer.cpp
  9. +4 −11 xbmc/epg/EpgDatabase.cpp
  10. +23 −8 xbmc/pvr/PVRDatabase.cpp
  11. +1 −0  xbmc/pvr/PVRDatabase.h
  12. +1 −1  xbmc/pvr/PVRGUIInfo.cpp
  13. +6 −10 xbmc/pvr/PVRManager.cpp
  14. +0 −7 xbmc/pvr/PVRManager.h
  15. +3 −6 xbmc/pvr/addons/PVRClient.cpp
  16. +1 −9 xbmc/pvr/addons/PVRClient.h
  17. +689 −709 xbmc/pvr/addons/PVRClients.cpp
  18. +379 −145 xbmc/pvr/addons/PVRClients.h
  19. +12 −16 xbmc/pvr/channels/PVRChannel.cpp
  20. +3 −2 xbmc/pvr/channels/PVRChannelGroup.cpp
  21. +2 −1  xbmc/pvr/channels/PVRChannelGroup.h
  22. +9 −16 xbmc/pvr/channels/PVRChannelGroups.cpp
  23. +3 −3 xbmc/pvr/epg/PVREpg.cpp
  24. +2 −1  xbmc/pvr/epg/PVREpg.h
  25. +1 −1  xbmc/pvr/epg/PVREpgContainer.cpp
  26. +2 −1  xbmc/pvr/recordings/PVRRecordings.cpp
  27. +3 −1 xbmc/pvr/recordings/PVRRecordings.h
  28. +2 −8 xbmc/pvr/timers/PVRTimers.cpp
  29. +13 −0 xbmc/pvr/windows/GUIWindowPVR.cpp
  30. +1 −0  xbmc/pvr/windows/GUIWindowPVR.h
  31. +37 −0 xbmc/pvr/windows/GUIWindowPVRChannels.cpp
  32. +5 −1 xbmc/pvr/windows/GUIWindowPVRChannels.h
  33. +38 −15 xbmc/pvr/windows/GUIWindowPVRGuide.cpp
  34. +2 −0  xbmc/pvr/windows/GUIWindowPVRGuide.h
  35. +44 −0 xbmc/pvr/windows/GUIWindowPVRRecordings.cpp
  36. +7 −3 xbmc/pvr/windows/GUIWindowPVRRecordings.h
  37. +33 −0 xbmc/pvr/windows/GUIWindowPVRTimers.cpp
  38. +6 −2 xbmc/pvr/windows/GUIWindowPVRTimers.h
  39. +1 −1  xbmc/pvrclients/tvheadend/HTSPData.cpp
  40. +1 −1  xbmc/pvrclients/tvheadend/HTSPData.h
  41. +1 −1  xbmc/pvrclients/tvheadend/HTSPSession.cpp
  42. +1 −1  xbmc/pvrclients/tvheadend/HTSPSession.h
3  configure.in
View
@@ -1436,6 +1436,9 @@ OUTPUT_FILES="Makefile \
xbmc/pvrclients/mythtv/Makefile \
xbmc/pvrclients/tvheadend/Makefile \
xbmc/pvrclients/vdr-vnsi/Makefile \
+ lib/addons/library.xbmc.addon/Makefile \
+ lib/addons/library.xbmc.gui/Makefile \
+ lib/addons/library.xbmc.pvr/Makefile \
tools/Linux/xbmc.sh \
tools/Linux/xbmc-standalone.sh \
tools/TexturePacker/Makefile \
0  lib/addons/library.xbmc.addon/Makefile → lib/addons/library.xbmc.addon/Makefile.in
View
File renamed without changes
0  lib/addons/library.xbmc.gui/Makefile → lib/addons/library.xbmc.gui/Makefile.in
View
File renamed without changes
0  lib/addons/library.xbmc.pvr/Makefile → lib/addons/library.xbmc.pvr/Makefile.in
View
File renamed without changes
13 xbmc/addons/include/xbmc_pvr_types.h
View
@@ -124,19 +124,6 @@ extern "C" {
} PVR_PROPERTIES;
/*!
- * @brief PVR add-on event codes, sent via PVRManager callback.
- */
- typedef enum
- {
- PVR_EVENT_UNKNOWN = 0,
- PVR_EVENT_CLOSE = 1,
- PVR_EVENT_RECORDINGS_CHANGE = 2,
- PVR_EVENT_CHANNELS_CHANGE = 3,
- PVR_EVENT_TIMERS_CHANGE = 4,
- PVR_EVENT_CHANNEL_GROUPS_CHANGE = 5
- } PVR_EVENT;
-
- /*!
* @brief PVR add-on capabilities. All capabilities are set to "false" as default.
*/
typedef struct PVR_ADDON_CAPABILITIES
43 xbmc/epg/Epg.cpp
View
@@ -44,7 +44,8 @@ struct sortEPGbyDate
}
};
-CEpg::CEpg(int iEpgID, const CStdString &strName /* = "" */, const CStdString &strScraperName /* = "" */) :
+CEpg::CEpg(int iEpgID, const CStdString &strName /* = "" */, const CStdString &strScraperName /* = "" */, bool bLoadedFromDb /* = false */) :
+ m_bChanged(!bLoadedFromDb),
m_bInhibitSorting(false),
m_iEpgID(iEpgID),
m_strName(strName),
@@ -65,6 +66,28 @@ CEpg::~CEpg(void)
/** @name Public methods */
//@{
+void CEpg::SetName(const CStdString &strName)
+{
+ CSingleLock lock(m_critSection);
+
+ if (!m_strName.Equals(strName))
+ {
+ m_bChanged = true;
+ m_strName = strName;
+ }
+}
+
+void CEpg::SetScraperName(const CStdString &strScraperName)
+{
+ CSingleLock lock(m_critSection);
+
+ if (!m_strScraperName.Equals(strScraperName))
+ {
+ m_bChanged = true;
+ m_strScraperName = strScraperName;
+ }
+}
+
bool CEpg::HasValidEntries(void) const
{
CSingleLock lock(m_critSection);
@@ -621,19 +644,21 @@ bool CEpg::Persist(bool bPersistTags /* = false */, bool bQueueWrite /* = false
}
CSingleLock lock(m_critSection);
-
- int iId = database->Persist(*this, bQueueWrite && m_iEpgID > 0);
- if (iId >= 0)
+ if (m_iEpgID <= 0 || m_bChanged)
{
+ int iId = database->Persist(*this, bQueueWrite && m_iEpgID > 0);
if (iId > 0)
+ {
m_iEpgID = iId;
-
- if (bPersistTags)
- bReturn = PersistTags(bQueueWrite);
- else
- bReturn = true;
+ m_bChanged = false;
+ }
}
+ if (bPersistTags)
+ bReturn = PersistTags(bQueueWrite);
+ else
+ bReturn = true;
+
database->Close();
return bReturn;
16 xbmc/epg/Epg.h
View
@@ -37,6 +37,7 @@ namespace EPG
friend class CEpgDatabase;
protected:
+ bool m_bChanged; /*!< true if anything changed that needs to be persisted, false otherwise */
bool m_bInhibitSorting; /*!< don't sort the table if this is true */
int m_iEpgID; /*!< the database ID of this table */
CStdString m_strName; /*!< the name of this table */
@@ -145,8 +146,9 @@ namespace EPG
* @param iEpgID The ID of this table or <= 0 to create a new ID.
* @param strName The name of this table.
* @param strScraperName The name of the scraper to use.
+ * @param bLoadedFromDb True if this table was loaded from the database, false otherwise.
*/
- CEpg(int iEpgID, const CStdString &strName = "", const CStdString &strScraperName = "");
+ CEpg(int iEpgID, const CStdString &strName = "", const CStdString &strScraperName = "", bool bLoadedFromDb = false);
/*!
* @brief Destroy this EPG instance.
@@ -172,12 +174,24 @@ namespace EPG
const CStdString &ScraperName(void) const { return m_strScraperName; }
/*!
+ * @brief Change the name of the scraper to use.
+ * @param strScraperName The new scraper.
+ */
+ void SetScraperName(const CStdString &strScraperName);
+
+ /*!
* @brief Get the name of this table.
* @return The name of this table.
*/
const CStdString &Name(void) const { return m_strName; }
/*!
+ * @brief Changed the name of this table.
+ * @param strName The new name.
+ */
+ void SetName(const CStdString &strName);
+
+ /*!
* @brief Get the database ID of this table.
* @return The database ID of this table.
*/
2  xbmc/epg/EpgContainer.cpp
View
@@ -110,8 +110,8 @@ void CEpgContainer::Start(void)
CSingleLock lock(m_critSection);
m_bStop = false;
- LoadSettings();
g_guiSettings.AddObserver(this);
+ LoadSettings();
Create();
SetName("XBMC EPG thread");
15 xbmc/epg/EpgDatabase.cpp
View
@@ -193,7 +193,7 @@ int CEpgDatabase::Get(CEpgContainer &container)
CStdString strName = m_pDS->fv("sName").get_asString().c_str();
CStdString strScraperName = m_pDS->fv("sScraperName").get_asString().c_str();
- CEpg newEpg(iEpgID, strName, strScraperName);
+ CEpg newEpg(iEpgID, strName, strScraperName, true);
if (container.UpdateEntry(newEpg))
++iReturn;
else
@@ -223,12 +223,9 @@ int CEpgDatabase::Get(CEpg &epg)
{
int iReturn = -1;
- CStdString strWhereClause;
- strWhereClause = FormatSQL("idEpg = %u", epg.EpgID());
-
- CStdString strQuery;
- strQuery.Format("SELECT * FROM epgtags WHERE %s ORDER BY iStartTime ASC;", strWhereClause.c_str());
+ CLog::Log(LOGDEBUG, "get table '%s' id %d", epg.Name().c_str(), epg.EpgID());
+ CStdString strQuery = FormatSQL("SELECT * FROM epgtags WHERE idEpg = %u ORDER BY iStartTime ASC;", epg.EpgID());
if (ResultQuery(strQuery))
{
iReturn = 0;
@@ -314,15 +311,11 @@ int CEpgDatabase::Persist(const CEpg &epg, bool bQueueWrite /* = false */)
CStdString strQuery;
if (epg.EpgID() > 0)
- {
strQuery = FormatSQL("REPLACE INTO epg (idEpg, sName, sScraperName) "
"VALUES (%u, '%s', '%s');", epg.EpgID(), epg.Name().c_str(), epg.ScraperName().c_str());
- }
else
- {
- strQuery = FormatSQL("REPLACE INTO epg (sName, sScraperName) "
+ strQuery = FormatSQL("INSERT INTO epg (sName, sScraperName) "
"VALUES ('%s', '%s');", epg.Name().c_str(), epg.ScraperName().c_str());
- }
if (bQueueWrite)
{
31 xbmc/pvr/PVRDatabase.cpp
View
@@ -464,6 +464,12 @@ bool CPVRDatabase::RemoveChannelsFromGroup(const CPVRChannelGroup &group)
return DeleteValues("map_channelgroups_channels", strWhereClause);
}
+bool CPVRDatabase::RemoveStaleChannelsFromGroup(const CPVRChannelGroup &group)
+{
+ CStdString strWhereClause = FormatSQL("idGroup = %u AND iChannelNumber > %u", group.GroupID(), group.size());
+ return DeleteValues("map_channelgroups_channels", strWhereClause);
+}
+
bool CPVRDatabase::DeleteChannelGroups(void)
{
CLog::Log(LOGDEBUG, "PVRDB - %s - deleting all channel groups from the database", __FUNCTION__);
@@ -600,27 +606,36 @@ bool CPVRDatabase::Persist(CPVRChannelGroup &group)
bool CPVRDatabase::PersistGroupMembers(CPVRChannelGroup &group)
{
- bool bReturn = RemoveChannelsFromGroup(group);
+ bool bReturn = false;
+ bool bRemoveChannels = false;
CStdString strQuery;
CSingleLock lock(group.m_critSection);
- if (bReturn && group.size() > 0)
+ if (group.size() > 0)
{
for (unsigned int iChannelPtr = 0; iChannelPtr < group.size(); iChannelPtr++)
{
PVRChannelGroupMember member = group.at(iChannelPtr);
- strQuery = FormatSQL("REPLACE INTO map_channelgroups_channels ("
- "idGroup, idChannel, iChannelNumber) "
- "VALUES (%i, %i, %i);",
- group.GroupID(), member.channel->ChannelID(), member.iChannelNumber);
- QueueInsertQuery(strQuery);
+
+ CStdString strWhereClause = FormatSQL("idChannel = %u AND idGroup = %u AND iChannelNumber = %u",
+ member.channel->ChannelID(), group.GroupID(), member.iChannelNumber);
+
+ CStdString strValue = GetSingleValue("map_channelgroups_channels", "idChannel", strWhereClause);
+ if (strValue.IsEmpty()) {
+ strQuery = FormatSQL("REPLACE INTO map_channelgroups_channels ("
+ "idGroup, idChannel, iChannelNumber) "
+ "VALUES (%i, %i, %i);",
+ group.GroupID(), member.channel->ChannelID(), member.iChannelNumber);
+ QueueInsertQuery(strQuery);
+ }
}
lock.Leave();
bReturn = CommitInsertQueries();
+ bRemoveChannels = RemoveStaleChannelsFromGroup(group);
}
- return bReturn;
+ return bReturn && bRemoveChannels;
}
/********** Client methods **********/
1  xbmc/pvr/PVRDatabase.h
View
@@ -142,6 +142,7 @@ namespace PVR
//@{
bool RemoveChannelsFromGroup(const CPVRChannelGroup &group);
+ bool RemoveStaleChannelsFromGroup(const CPVRChannelGroup &group);
/*!
* @brief Remove all channel groups from the database
2  xbmc/pvr/PVRGUIInfo.cpp
View
@@ -95,7 +95,7 @@ void CPVRGUIInfo::Stop(void)
void CPVRGUIInfo::Notify(const Observable &obs, const CStdString& msg)
{
- if (msg.Equals("timers"))
+ if (msg.Equals("timers") || msg.Equals("timers-reset"))
UpdateTimersCache();
}
16 xbmc/pvr/PVRManager.cpp
View
@@ -232,6 +232,11 @@ void CPVRManager::Process(void)
return;
}
+ /* reset observers that are observing pvr related data in the pvr windows, or updates won't work after a reload */
+ CGUIWindowPVR *pWindow = (CGUIWindowPVR *) g_windowManager.GetWindow(WINDOW_PVR);
+ if (pWindow)
+ pWindow->ResetObservers();
+
/* start the other pvr related update threads */
m_addons->Start();
m_guiInfo->Start();
@@ -246,7 +251,6 @@ void CPVRManager::Process(void)
ShowBusyDialog(false);
/* signal to window that clients are loaded */
- CGUIWindowPVR *pWindow = (CGUIWindowPVR *) g_windowManager.GetWindow(WINDOW_PVR);
if (pWindow)
pWindow->UnlockWindow();
@@ -338,14 +342,6 @@ bool CPVRManager::ContinueLastChannel(void)
return bReturn;
}
-void CPVRManager::UpdateWindow(PVRWindow window, bool bResetContents /* = true */)
-{
- /* TODO use an observable for this! */
- CGUIWindowPVR *pWindow = (CGUIWindowPVR *) g_windowManager.GetWindow(WINDOW_PVR);
- if (pWindow)
- pWindow->UpdateWindow(window, bResetContents);
-}
-
void CPVRManager::ResetProperties(void)
{
m_currentFile = NULL;
@@ -971,7 +967,7 @@ bool CPVRManager::IsRunningChannelScan(void) const
PVR_ADDON_CAPABILITIES *CPVRManager::GetCurrentClientProperties(void)
{
- return m_addons->GetCurrentClientProperties();
+ return m_addons->GetCurrentAddonCapabilities();
}
void CPVRManager::StartChannelScan(void)
7 xbmc/pvr/PVRManager.h
View
@@ -341,13 +341,6 @@ namespace PVR
void UpdateCurrentFile(void);
/*!
- * @brief Update the data in a pvr window if that window is currently visible.
- * @param window The window to update.
- * @param bResetContents True to reset the contents of the given window, false to just mark all the window's items invalid.
- */
- void UpdateWindow(PVRWindow window, bool bResetContents = true);
-
- /*!
* @brief Check whether names are still correct after the language settings changed.
*/
void LocalizationChanged(void);
9 xbmc/pvr/addons/PVRClient.cpp
View
@@ -76,14 +76,13 @@ CPVRClient::~CPVRClient(void)
{
}
-bool CPVRClient::Create(int iClientId, IPVRClientCallback *pvrCB)
+bool CPVRClient::Create(int iClientId)
{
bool bReturn(false);
CSingleLock lock(m_critSection);
CLog::Log(LOGDEBUG, "PVR - %s - creating PVR add-on instance '%s'", __FUNCTION__, Name().c_str());
/* initialise members */
- m_manager = pvrCB;
if (!m_pInfo)
m_pInfo = new PVR_PROPERTIES;
m_pInfo->iClienId = iClientId;
@@ -126,11 +125,9 @@ void CPVRClient::Destroy(void)
bool CPVRClient::ReCreate(void)
{
- long clientID = m_pInfo->iClienId;
- IPVRClientCallback *pvrCB = m_manager;
-
+ int clientID = m_pInfo->iClienId;
Destroy();
- return Create(clientID, pvrCB);
+ return Create(clientID);
}
bool CPVRClient::ReadyToUse(void) const
10 xbmc/pvr/addons/PVRClient.h
View
@@ -38,12 +38,6 @@ namespace PVR
typedef std::vector<PVR_MENUHOOK> PVR_MENUHOOKS;
- class IPVRClientCallback
- {
- public:
- virtual void OnClientMessage(const int clientID, const PVR_EVENT clientEvent, const char* msg)=0;
- };
-
/*!
* Interface from XBMC to a PVR add-on.
*
@@ -62,10 +56,9 @@ namespace PVR
/*!
* @brief Initialise the instance of this add-on.
* @param iClientId The ID of this add-on.
- * @param pvrCB The call-back to use.
* @return True if it was created successfully, false otherwise.
*/
- bool Create(int iClientId, IPVRClientCallback *pvrCB);
+ bool Create(int iClientId);
/*!
* @brief Destroy the instance of this add-on.
@@ -447,7 +440,6 @@ namespace PVR
protected:
bool m_bReadyToUse; /*!< true if this add-on is connected to the backend, false otherwise */
- IPVRClientCallback *m_manager; /*!< the callback to use for this add-on */
CStdString m_strHostName; /*!< the host name */
CCriticalSection m_critSection; /*!< mutex for this class */
PVR_MENUHOOKS m_menuhooks; /*!< the menu hooks for this add-on */
1,398 xbmc/pvr/addons/PVRClients.cpp
View
@@ -41,16 +41,14 @@ using namespace std;
using namespace ADDON;
using namespace PVR;
-CPVRClients::CPVRClients(void)
+CPVRClients::CPVRClients(void) :
+ m_bChannelScanRunning(false),
+ m_bAllClientsLoaded(false),
+ m_currentChannel(NULL),
+ m_currentRecording(NULL),
+ m_scanStart(0),
+ m_strPlayingClientName("")
{
- m_bChannelScanRunning = false;
- m_bAllClientsLoaded = false;
- m_currentChannel = NULL;
- m_currentRecording = NULL;
- m_scanStart = 0;
- m_strPlayingClientName = "";
- m_clientsProps.clear();
- m_clientMap.clear();
ResetQualityData();
}
@@ -59,157 +57,42 @@ CPVRClients::~CPVRClients(void)
Unload();
}
-void CPVRClients::Unload(void)
-{
- CSingleLock lock(m_critSection);
-
- for (CLIENTMAPITR itr = m_clientMap.begin(); itr != m_clientMap.end(); itr++)
- {
- boost::shared_ptr<CPVRClient> client = m_clientMap[(*itr).first];
- CLog::Log(LOGDEBUG, "PVR - %s - destroying addon '%s' (%s)",
- __FUNCTION__, client->Name().c_str(), client->ID().c_str());
-
- client->Destroy();
- }
-
- m_bAllClientsLoaded = false;
- m_currentChannel = NULL;
- m_currentRecording = NULL;
- m_clientsProps.clear();
- m_clientMap.clear();
-}
-
-int CPVRClients::GetFirstID(void)
-{
- int iReturn = -1;
- CSingleLock lock(m_critSection);
-
- if (m_clientMap.size() > 0)
- {
- CLIENTMAPITR itr = m_clientMap.begin();
- iReturn = m_clientMap[(*itr).first]->GetID();
- }
-
- return iReturn;
-}
-
-int CPVRClients::GetClients(map<long, CStdString> *clients)
-{
- CLIENTMAPITR itr;
- int iInitialSize = clients->size();
- CSingleLock lock(m_critSection);
-
- for (itr = m_clientMap.begin() ; itr != m_clientMap.end(); itr++)
- {
- if (!m_clientMap[(*itr).first]->ReadyToUse())
- continue;
-
- CStdString strClient = (*itr).second->GetFriendlyName();
- clients->insert(std::make_pair(m_clientMap[(*itr).first]->GetID(), strClient));
- }
-
- return clients->size() - iInitialSize;
-}
-
-bool CPVRClients::AllClientsLoaded(void) const
-{
- CSingleLock lock(m_critSection);
- return m_bAllClientsLoaded;
-}
-
-bool CPVRClients::HasClients(void) const
-{
- CSingleLock lock(m_critSection);
- return !m_clientMap.empty();
-}
-
-int CPVRClients::ActiveClientAmount(void)
-{
- int iReturn = 0;
- CSingleLock lock(m_critSection);
- if (!m_clientMap.empty())
- {
- CLIENTMAPITR itr = m_clientMap.begin();
- while (itr != m_clientMap.end())
- {
- if (m_clientMap[(*itr).first]->ReadyToUse())
- ++iReturn;
- itr++;
- }
- }
-
- return iReturn;
-}
-
-bool CPVRClients::HasActiveClients(void)
+void CPVRClients::Start(void)
{
- return ActiveClientAmount() > 0;
-}
+ Stop();
-bool CPVRClients::HasTimerSupport(int iClientId)
-{
- CSingleLock lock(m_critSection);
+ ResetQualityData();
- return m_clientsProps[iClientId].bSupportsTimers;
+ Create();
+ SetName("XBMC PVR backend info");
+ SetPriority(-1);
}
-bool CPVRClients::GetValidClient(int iClientId, boost::shared_ptr<CPVRClient> &addon)
+void CPVRClients::Stop(void)
{
- bool bReturn = false;
- CSingleLock lock(m_critSection);
-
- CLIENTMAPITR itr = m_clientMap.find(iClientId);
- if (itr != m_clientMap.end() && itr->second->ReadyToUse())
- {
- addon = itr->second;
- bReturn = true;
- }
-
- return bReturn;
+ StopThread();
}
bool CPVRClients::IsValidClient(int iClientId)
{
- bool bReturn = false;
+ bool bReturn(false);
CSingleLock lock(m_critSection);
CLIENTMAPITR itr = m_clientMap.find(iClientId);
if (itr != m_clientMap.end() && itr->second->ReadyToUse())
bReturn = true;
- else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, iClientId);
return bReturn;
}
-bool CPVRClients::IsPlaying(void) const
-{
- CSingleLock lock(m_critSection);
- return m_currentRecording != NULL || m_currentChannel != NULL;
-}
-
-bool CPVRClients::IsPlayingTV(void) const
-{
- CSingleLock lock(m_critSection);
- return m_currentChannel != NULL && !m_currentChannel->IsRadio();
-}
-
-bool CPVRClients::IsPlayingRadio(void) const
-{
- CSingleLock lock(m_critSection);
- return m_currentChannel != NULL && m_currentChannel->IsRadio();
-}
-
-bool CPVRClients::IsRunningChannelScan(void) const
+bool CPVRClients::RequestRestart(AddonPtr addon, bool bDataChanged)
{
- CSingleLock lock(m_critSection);
- return m_bChannelScanRunning;
+ return StopClient(addon, true);
}
-bool CPVRClients::IsEncrypted(void) const
+bool CPVRClients::RequestRemoval(AddonPtr addon)
{
- CSingleLock lock(m_critSection);
- return m_currentChannel != NULL && m_currentChannel->IsEncrypted();
+ return StopClient(addon, false);
}
bool CPVRClients::TryLoadClients(int iMaxTime /* = 0 */)
@@ -248,105 +131,67 @@ bool CPVRClients::TryLoadClients(int iMaxTime /* = 0 */)
return m_bAllClientsLoaded;
}
-bool CPVRClients::ClientLoaded(const CStdString &strClientId)
+void CPVRClients::Unload(void)
{
- bool bStarted = false;
+ Stop();
+
CSingleLock lock(m_critSection);
- for (unsigned int iClientPtr = 0; iClientPtr < m_clientMap.size(); iClientPtr++)
+ /* destroy all clients */
+ for (CLIENTMAPITR itr = m_clientMap.begin(); itr != m_clientMap.end(); itr++)
{
- if (m_clientMap[iClientPtr]->ID() == strClientId && m_clientMap[iClientPtr]->ReadyToUse())
- {
- /* already started */
- bStarted = true;
- break;
- }
- }
-
- return bStarted;
-}
+ boost::shared_ptr<CPVRClient> client = m_clientMap[(*itr).first];
+ CLog::Log(LOGDEBUG, "PVR - %s - destroying addon '%s' (%s)",
+ __FUNCTION__, client->Name().c_str(), client->ID().c_str());
-int CPVRClients::AddClientToDb(const CStdString &strClientId, const CStdString &strName)
-{
- /* add this client to the database if it's not in there yet */
- CPVRDatabase *database = OpenPVRDatabase();
- int iClientDbId = database ? database->AddClient(strName, strClientId) : -1;
- if (iClientDbId == -1)
- {
- CLog::Log(LOGERROR, "PVR - %s - can't add client '%s' to the database",
- __FUNCTION__, strName.c_str());
+ client->Destroy();
}
- return iClientDbId;
+ /* reset class properties */
+ m_bChannelScanRunning = false;
+ m_bAllClientsLoaded = false;
+ m_currentChannel = NULL;
+ m_currentRecording = NULL;
+ m_scanStart = 0;
+ m_strPlayingClientName = "";
+
+ m_clientsProps.clear();
+ m_clientMap.clear();
}
-bool CPVRClients::LoadClients(void)
+int CPVRClients::GetFirstID(void)
{
+ int iReturn(-1);
CSingleLock lock(m_critSection);
- if (m_bAllClientsLoaded)
- return !m_clientMap.empty();
-
- CAddonMgr::Get().RegisterAddonMgrCallback(ADDON_PVRDLL, this);
-
- /* get all PVR addons */
- VECADDONS addons;
- if (!CAddonMgr::Get().GetAddons(ADDON_PVRDLL, addons, true))
- return false;
-
- /* load and initialise the clients */
- CPVRDatabase *database = OpenPVRDatabase();
- if (!database)
- return false;
- m_bAllClientsLoaded = true;
- for (unsigned iClientPtr = 0; iClientPtr < addons.size(); iClientPtr++)
+ for (CLIENTMAPITR itr = m_clientMap.begin(); itr != m_clientMap.end(); itr++)
{
- const AddonPtr clientAddon = addons.at(iClientPtr);
- if (!clientAddon->Enabled())
- continue;
-
- int iClientId = AddClientToDb(clientAddon->ID(), clientAddon->Name());
- if (iClientId == -1)
- continue; // don't set "m_bAllClientsLoaded = false;" here because this will enter a neverending loop
-
- /* check if this client isn't active already */
- if (ClientLoaded(clientAddon->ID()))
- continue;
-
- /* load and initialise the client libraries */
- boost::shared_ptr<CPVRClient> addon = boost::dynamic_pointer_cast<CPVRClient>(clientAddon);
- if (addon && addon->Create(iClientId, this))
- {
- /* get the client's properties */
- PVR_ADDON_CAPABILITIES props;
- if (addon->GetAddonCapabilities(&props) == PVR_ERROR_NO_ERROR)
- {
- m_clientMap.insert(std::make_pair(iClientId, addon));
- m_clientsProps.insert(std::make_pair(iClientId, props));
- }
- else
- {
- CLog::Log(LOGERROR, "PVR - %s - can't get client properties from addon '%s'",
- __FUNCTION__, clientAddon->Name().c_str());
- m_bAllClientsLoaded = false;
- }
- }
- else
+ boost::shared_ptr<CPVRClient> client = m_clientMap[(*itr).first];
+ if (client->ReadyToUse())
{
- CLog::Log(LOGERROR, "PVR - %s - can't initialise client '%s'",
- __FUNCTION__, clientAddon->Name().c_str());
- m_bAllClientsLoaded = false;
+ iReturn = client->GetID();
+ break;
}
}
- database->Close();
+ return iReturn;
+}
+
+bool CPVRClients::AllClientsLoaded(void) const
+{
+ CSingleLock lock(m_critSection);
+ return m_bAllClientsLoaded;
+}
+bool CPVRClients::HasClients(void) const
+{
+ CSingleLock lock(m_critSection);
return !m_clientMap.empty();
}
bool CPVRClients::StopClient(AddonPtr client, bool bRestart)
{
- bool bReturn = false;
+ bool bReturn(false);
if (!client)
return bReturn;
@@ -361,9 +206,14 @@ bool CPVRClients::StopClient(AddonPtr client, bool bRestart)
g_PVRManager.StopUpdateThreads();
if (bRestart)
+ {
m_clientMap[(*itr).first]->ReCreate();
+ }
else
+ {
m_clientMap[(*itr).first]->Destroy();
+ m_clientMap.erase((*itr).first);
+ }
g_PVRManager.StartUpdateThreads();
bReturn = true;
@@ -375,164 +225,130 @@ bool CPVRClients::StopClient(AddonPtr client, bool bRestart)
return bReturn;
}
-const CStdString CPVRClients::GetClientName(int iClientId)
+int CPVRClients::ActiveClientAmount(void)
{
- static CStdString strClientName;
+ int iReturn(0);
CSingleLock lock(m_critSection);
- if (IsValidClient(iClientId))
- strClientName = m_clientMap.find(iClientId)->second->GetFriendlyName();
- else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, iClientId);
+ if (!m_clientMap.empty())
+ {
+ CLIENTMAPITR itr = m_clientMap.begin();
+ while (itr != m_clientMap.end())
+ {
+ if (m_clientMap[(*itr).first]->ReadyToUse())
+ ++iReturn;
+ itr++;
+ }
+ }
- return strClientName;
+ return iReturn;
}
-void CPVRClients::ResetQualityData(void)
+bool CPVRClients::HasActiveClients(void)
{
- if (g_guiSettings.GetBool("pvrplayback.signalquality"))
- {
- strncpy(m_qualityInfo.strAdapterName, g_localizeStrings.Get(13205).c_str(), 1024);
- strncpy(m_qualityInfo.strAdapterStatus, g_localizeStrings.Get(13205).c_str(), 1024);
- }
- else
- {
- strncpy(m_qualityInfo.strAdapterName, g_localizeStrings.Get(13106).c_str(), 1024);
- strncpy(m_qualityInfo.strAdapterStatus, g_localizeStrings.Get(13106).c_str(), 1024);
- }
- m_qualityInfo.iSNR = 0;
- m_qualityInfo.iSignal = 0;
- m_qualityInfo.iSNR = 0;
- m_qualityInfo.iUNC = 0;
- m_qualityInfo.dVideoBitrate = 0;
- m_qualityInfo.dAudioBitrate = 0;
- m_qualityInfo.dDolbyBitrate = 0;
-}
-
-void CPVRClients::GetQualityData(PVR_SIGNAL_STATUS *status) const
-{
- *status = m_qualityInfo;
-}
-
-bool CPVRClients::IsReadingLiveStream(void) const
-{
- CSingleLock lock(m_critSection);
- return m_currentChannel != NULL;
-}
-
-bool CPVRClients::OpenLiveStream(const CPVRChannel &tag)
-{
- bool bReturn = false;
+ bool bReturn(false);
CSingleLock lock(m_critSection);
- if (m_currentChannel)
- delete m_currentChannel;
- if (m_currentRecording)
- delete m_currentRecording;
-
- ResetQualityData();
-
- /* try to open the stream on the client */
- if ((tag.StreamURL().IsEmpty() == false ||
- m_clientsProps[tag.ClientID()].bHandlesInputStream) &&
- m_clientMap[tag.ClientID()]->OpenLiveStream(tag))
+ if (!m_clientMap.empty())
{
- m_currentChannel = &tag;
- if (tag.ClientID() == XBMC_VIRTUAL_CLIENTID)
- m_strPlayingClientName = g_localizeStrings.Get(19209);
- else if (!tag.IsVirtual())
- m_strPlayingClientName = GetClientName(tag.ClientID());
- else
- m_strPlayingClientName = g_localizeStrings.Get(13205);
-
- m_scanStart = CTimeUtils::GetTimeMS(); /* Reset the stream scan timer */
- bReturn = true;
+ CLIENTMAPITR itr = m_clientMap.begin();
+ while (itr != m_clientMap.end())
+ {
+ if (m_clientMap[(*itr).first]->ReadyToUse())
+ {
+ bReturn = true;
+ break;
+ }
+ itr++;
+ }
}
return bReturn;
}
-int CPVRClients::ReadLiveStream(void* lpBuf, int64_t uiBufSize)
+const CStdString CPVRClients::GetClientName(int iClientId)
{
+ static CStdString strClientName;
CSingleLock lock(m_critSection);
- return m_currentChannel ? m_clientMap[m_currentChannel->ClientID()]->ReadLiveStream(lpBuf, uiBufSize) : 0;
+
+ if (IsValidClient(iClientId))
+ strClientName = m_clientMap.find(iClientId)->second->GetFriendlyName();
+ else
+ CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, iClientId);
+
+ return strClientName;
}
-bool CPVRClients::CloseLiveStream(void)
+int CPVRClients::GetActiveClients(CLIENTMAP *clients)
{
- bool bReturn = false;
+ int iReturn(0);
CSingleLock lock(m_critSection);
- ResetQualityData();
-
- if (!m_currentChannel)
- return bReturn;
- if ((m_currentChannel->StreamURL().IsEmpty()) || (m_currentChannel->StreamURL().compare(0,13, "pvr://stream/") == 0))
+ if (m_clientMap.size() > 0)
{
- m_clientMap[m_currentChannel->ClientID()]->CloseLiveStream();
- m_currentChannel = NULL;
- bReturn = true;
+ CLIENTMAPITR itr = m_clientMap.begin();
+ while (itr != m_clientMap.end())
+ {
+ if (m_clientMap[(*itr).first]->ReadyToUse())
+ {
+ clients->insert(std::make_pair(m_clientMap[(*itr).first]->GetID(), m_clientMap[(*itr).first]));
+ ++iReturn;
+ break;
+ }
+ itr++;
+ }
}
- return bReturn;
-}
-
-bool CPVRClients::IsPlayingRecording(void) const
-{
- CSingleLock lock(m_critSection);
- return m_currentRecording != NULL;
+ return iReturn;
}
-bool CPVRClients::OpenRecordedStream(const CPVRRecording &tag)
+int CPVRClients::GetPlayingClientID(void) const
{
- bool bReturn = false;
+ int iReturn(-1);
CSingleLock lock(m_critSection);
if (m_currentChannel)
- delete m_currentChannel;
- if (m_currentRecording)
- delete m_currentRecording;
-
- /* try to open the recording stream on the client */
- if (m_clientMap[tag.m_iClientId]->OpenRecordedStream(tag))
- {
- m_currentRecording = &tag;
- m_strPlayingClientName = GetClientName(tag.m_iClientId);
- m_scanStart = CTimeUtils::GetTimeMS(); /* Reset the stream scan timer */
- bReturn = true;
- }
+ iReturn = m_currentChannel->ClientID();
+ else if (m_currentRecording)
+ iReturn = m_currentRecording->m_iClientId;
- return bReturn;
+ return iReturn;
}
-int CPVRClients::ReadRecordedStream(void* lpBuf, int64_t uiBufSize)
+PVR_ADDON_CAPABILITIES *CPVRClients::GetAddonCapabilities(int iClientId)
{
+ PVR_ADDON_CAPABILITIES *props = NULL;
CSingleLock lock(m_critSection);
- return m_currentRecording ? m_clientMap[m_currentRecording->m_iClientId]->ReadRecordedStream(lpBuf, uiBufSize) : 0;
+
+ if (IsValidClient(iClientId))
+ props = &m_clientsProps[iClientId];
+
+ return props;
}
-bool CPVRClients::CloseRecordedStream(void)
+PVR_ADDON_CAPABILITIES *CPVRClients::GetCurrentAddonCapabilities(void)
{
- bool bReturn = false;
+ PVR_ADDON_CAPABILITIES *props = NULL;
CSingleLock lock(m_critSection);
- if (!m_currentRecording)
- return bReturn;
+ if (m_currentChannel)
+ props = &m_clientsProps[m_currentChannel->ClientID()];
+ else if (m_currentRecording)
+ props = &m_clientsProps[m_currentRecording->m_iClientId];
- if (m_currentRecording->m_iClientId > 0 && m_clientMap[m_currentRecording->m_iClientId])
- {
- m_clientMap[m_currentRecording->m_iClientId]->CloseRecordedStream();
- bReturn = true;
- }
+ return props;
+}
- return bReturn;
+bool CPVRClients::IsPlaying(void) const
+{
+ CSingleLock lock(m_critSection);
+ return m_currentRecording != NULL || m_currentChannel != NULL;
}
-void CPVRClients::CloseStream(void)
+const CStdString CPVRClients::GetPlayingClientName(void) const
{
CSingleLock lock(m_critSection);
- CloseLiveStream() || CloseRecordedStream();
- m_strPlayingClientName = "";
+ return m_strPlayingClientName;
}
int CPVRClients::ReadStream(void* lpBuf, int64_t uiBufSize)
@@ -563,39 +379,10 @@ int CPVRClients::ReadStream(void* lpBuf, int64_t uiBufSize)
return 0;
}
-void CPVRClients::DemuxReset(void)
-{
- /* don't lock here cause it'll cause a dead lock when the client connection is dropped while playing */
- if (m_currentChannel)
- m_clientMap[m_currentChannel->ClientID()]->DemuxReset();
-}
-
-void CPVRClients::DemuxAbort(void)
-{
- /* don't lock here cause it'll cause a dead lock when the client connection is dropped while playing */
- if (m_currentChannel)
- m_clientMap[m_currentChannel->ClientID()]->DemuxAbort();
-}
-
-void CPVRClients::DemuxFlush(void)
-{
- /* don't lock here cause it'll cause a dead lock when the client connection is dropped while playing */
- if (m_currentChannel)
- m_clientMap[m_currentChannel->ClientID()]->DemuxFlush();
-}
-
-DemuxPacket* CPVRClients::ReadDemuxStream(void)
-{
- /* don't lock here cause it'll cause a dead lock when the client connection is dropped while playing */
- if (m_currentChannel)
- return m_clientMap[m_currentChannel->ClientID()]->DemuxRead();
-
- return NULL;
-}
-
int64_t CPVRClients::LengthStream(void)
{
- int64_t streamLength = 0;
+ int64_t streamLength(0);
+ CSingleLock lock(m_critSection);
if (m_currentChannel)
streamLength = 0;
@@ -607,7 +394,8 @@ int64_t CPVRClients::LengthStream(void)
int64_t CPVRClients::SeekStream(int64_t iFilePosition, int iWhence/* = SEEK_SET*/)
{
- int64_t streamNewPos = 0;
+ int64_t streamNewPos(0);
+ CSingleLock lock(m_critSection);
if (m_currentChannel)
streamNewPos = 0;
@@ -619,7 +407,8 @@ int64_t CPVRClients::SeekStream(int64_t iFilePosition, int iWhence/* = SEEK_SET*
int64_t CPVRClients::GetStreamPosition(void)
{
- int64_t streamPos = 0;
+ int64_t streamPos(0);
+ CSingleLock lock(m_critSection);
if (m_currentChannel)
streamPos = 0;
@@ -629,390 +418,510 @@ int64_t CPVRClients::GetStreamPosition(void)
return streamPos;
}
-bool CPVRClients::AddTimer(const CPVRTimerInfoTag &timer, PVR_ERROR *error)
+void CPVRClients::CloseStream(void)
{
- *error = PVR_ERROR_UNKOWN;
- boost::shared_ptr<CPVRClient> client;
- if (GetValidClient(timer.m_iClientId, client))
- *error = client->AddTimer(timer);
- else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, timer.m_iClientId);
-
- return *error == PVR_ERROR_NO_ERROR;
+ CSingleLock lock(m_critSection);
+ CloseLiveStream() || CloseRecordedStream();
+ m_strPlayingClientName = "";
}
-bool CPVRClients::UpdateTimer(const CPVRTimerInfoTag &timer, PVR_ERROR *error)
+PVR_STREAM_PROPERTIES *CPVRClients::GetCurrentStreamProperties(void)
{
- *error = PVR_ERROR_UNKOWN;
- boost::shared_ptr<CPVRClient> client;
- if (GetValidClient(timer.m_iClientId, client))
- *error = client->UpdateTimer(timer);
- else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, timer.m_iClientId);
+ PVR_STREAM_PROPERTIES *props = NULL;
+ CSingleLock lock(m_critSection);
- return *error == PVR_ERROR_NO_ERROR;
-}
+ if (m_currentChannel)
+ {
+ int iChannelId = m_currentChannel->ClientID();
+ m_clientMap[iChannelId]->GetStreamProperties(&m_streamProps[iChannelId]);
-bool CPVRClients::DeleteTimer(const CPVRTimerInfoTag &timer, bool bForce, PVR_ERROR *error)
-{
- *error = PVR_ERROR_UNKOWN;
- boost::shared_ptr<CPVRClient> client;
- if (GetValidClient(timer.m_iClientId, client))
- *error = client->DeleteTimer(timer, bForce);
- else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, timer.m_iClientId);
+ props = &m_streamProps[iChannelId];
+ }
- return *error == PVR_ERROR_NO_ERROR;
+ return props;
}
-bool CPVRClients::RenameTimer(const CPVRTimerInfoTag &timer, const CStdString &strNewName, PVR_ERROR *error)
+const char *CPVRClients::GetCurrentInputFormat(void) const
{
- *error = PVR_ERROR_UNKOWN;
- boost::shared_ptr<CPVRClient> client;
- if (GetValidClient(timer.m_iClientId, client))
- *error = client->RenameTimer(timer, strNewName);
- else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, timer.m_iClientId);
+ static CStdString strReturn("");
+ CSingleLock lock(m_critSection);
- return *error == PVR_ERROR_NO_ERROR;
+ if (m_currentChannel)
+ strReturn = m_currentChannel->InputFormat();
+
+ return strReturn.c_str();
}
-int CPVRClients::GetTimers(CPVRTimers *timers)
+bool CPVRClients::IsReadingLiveStream(void) const
{
- int iCurSize = timers->size();
- CLIENTMAP clients;
- GetActiveClients(&clients);
-
- /* get the timer list from each client */
- CLIENTMAPITR itrClients = clients.begin();
- while (itrClients != clients.end())
- {
- if (!GetClientProperties((*itrClients).second->GetID())->bSupportsTimers ||
- (*itrClients).second->GetTimersAmount() <= 0)
- {
- ++itrClients;
- continue;
- }
+ CSingleLock lock(m_critSection);
+ return m_currentChannel != NULL;
+}
- (*itrClients).second->GetTimers(timers);
- ++itrClients;
- }
+bool CPVRClients::IsPlayingTV(void) const
+{
+ CSingleLock lock(m_critSection);
+ return m_currentChannel != NULL && !m_currentChannel->IsRadio();
+}
- return timers->size() - iCurSize;
+bool CPVRClients::IsPlayingRadio(void) const
+{
+ CSingleLock lock(m_critSection);
+ return m_currentChannel != NULL && m_currentChannel->IsRadio();
}
-int CPVRClients::GetRecordings(CPVRRecordings *recordings)
+bool CPVRClients::IsEncrypted(void) const
{
- int iCurSize = recordings->size();
- CLIENTMAP clients;
- GetActiveClients(&clients);
+ CSingleLock lock(m_critSection);
+ return m_currentChannel != NULL && m_currentChannel->IsEncrypted();
+}
+
+bool CPVRClients::OpenLiveStream(const CPVRChannel &tag)
+{
+ bool bReturn(false);
+ CSingleLock lock(m_critSection);
+
+ if (m_currentChannel)
+ delete m_currentChannel;
+ if (m_currentRecording)
+ delete m_currentRecording;
- CLIENTMAPITR itr = clients.begin();
- while (itr != clients.end())
+ ResetQualityData();
+
+ /* try to open the stream on the client */
+ if ((tag.StreamURL().IsEmpty() == false ||
+ m_clientsProps[tag.ClientID()].bHandlesInputStream) &&
+ m_clientMap[tag.ClientID()]->OpenLiveStream(tag))
{
- /* Load only if the client have Recordings */
- if ((*itr).second->GetRecordingsAmount() > 0)
- {
- (*itr).second->GetRecordings(recordings);
- }
- itr++;
+ m_currentChannel = &tag;
+ if (tag.ClientID() == XBMC_VIRTUAL_CLIENTID)
+ m_strPlayingClientName = g_localizeStrings.Get(19209);
+ else if (!tag.IsVirtual())
+ m_strPlayingClientName = GetClientName(tag.ClientID());
+ else
+ m_strPlayingClientName = g_localizeStrings.Get(13205);
+
+ m_scanStart = CTimeUtils::GetTimeMS(); /* Reset the stream scan timer */
+ bReturn = true;
}
- return recordings->size() - iCurSize;
+ return bReturn;
}
-bool CPVRClients::RenameRecording(const CPVRRecording &recording, PVR_ERROR *error)
+bool CPVRClients::CloseLiveStream(void)
{
- *error = PVR_ERROR_UNKOWN;
- boost::shared_ptr<CPVRClient> client;
- if (GetValidClient(recording.m_iClientId, client))
- *error = client->RenameRecording(recording);
- else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, recording.m_iClientId);
+ bool bReturn(false);
+ CSingleLock lock(m_critSection);
+ ResetQualityData();
- return *error == PVR_ERROR_NO_ERROR;
+ if (!m_currentChannel)
+ return bReturn;
+
+ if ((m_currentChannel->StreamURL().IsEmpty()) || (m_currentChannel->StreamURL().compare(0,13, "pvr://stream/") == 0))
+ {
+ m_clientMap[m_currentChannel->ClientID()]->CloseLiveStream();
+ m_currentChannel = NULL;
+ bReturn = true;
+ }
+
+ return bReturn;
}
-bool CPVRClients::DeleteRecording(const CPVRRecording &recording, PVR_ERROR *error)
+const char *CPVRClients::GetStreamURL(const CPVRChannel &tag)
{
- *error = PVR_ERROR_UNKOWN;
+ static CStdString strReturn("");
boost::shared_ptr<CPVRClient> client;
- if (GetValidClient(recording.m_iClientId, client))
- *error = client->DeleteRecording(recording);
+ if (GetValidClient(tag.ClientID(), client))
+ strReturn = client->GetLiveStreamURL(tag);
else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, recording.m_iClientId);
+ CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, tag.ClientID());
- return *error == PVR_ERROR_NO_ERROR;
+ return strReturn.c_str();
}
-bool CPVRClients::GetEPGForChannel(const CPVRChannel &channel, CPVREpg *epg, time_t start, time_t end, PVR_ERROR *error)
+bool CPVRClients::SwitchChannel(const CPVRChannel &channel)
{
- *error = PVR_ERROR_UNKOWN;
+ bool bReturn(false);
+ CSingleLock lock(m_critSection);
+ if (m_currentChannel && m_currentChannel->ClientID() != channel.ClientID())
+ {
+ lock.Leave();
+ CloseStream();
+ return OpenLiveStream(channel);
+ }
+
boost::shared_ptr<CPVRClient> client;
if (GetValidClient(channel.ClientID(), client))
- *error = client->GetEPGForChannel(channel, epg, start, end);
+ {
+ if (client->SwitchChannel(channel))
+ {
+ m_currentChannel = &channel;
+ m_scanStart = CTimeUtils::GetTimeMS(); /* Reset the stream scan timer */
+ ResetQualityData();
+
+ bReturn = true;
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "PVR - %s - cannot switch channel on client %d",__FUNCTION__, channel.ClientID());
+ }
+ }
else
+ {
CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, channel.ClientID());
+ }
- return *error == PVR_ERROR_NO_ERROR;
+ return bReturn;
}
-int CPVRClients::GetChannelGroups(CPVRChannelGroups *groups, PVR_ERROR *error)
+bool CPVRClients::GetPlayingChannel(CPVRChannel *channel) const
{
- *error = PVR_ERROR_UNKOWN;
- int iCurSize = groups->size();
- CLIENTMAP clients;
- GetActiveClients(&clients);
+ CSingleLock lock(m_critSection);
- /* get the channel groups list from each client */
- CLIENTMAPITR itrClients = clients.begin();
- while (itrClients != clients.end())
- {
- if ((*itrClients).second->ReadyToUse())
- (*itrClients).second->GetChannelGroups(groups);
+ if (m_currentChannel != NULL)
+ *channel = *m_currentChannel;
+ else
+ channel = NULL;
- itrClients++;
- }
+ return m_currentChannel != NULL;
+}
- return groups->size() - iCurSize;
+bool CPVRClients::IsPlayingRecording(void) const
+{
+ CSingleLock lock(m_critSection);
+ return m_currentRecording != NULL;
}
-int CPVRClients::GetChannelGroupMembers(CPVRChannelGroup *group, PVR_ERROR *error)
+bool CPVRClients::OpenRecordedStream(const CPVRRecording &tag)
{
- *error = PVR_ERROR_NO_ERROR;
- int iCurSize = group->GetNumChannels();
- CLIENTMAP clients;
- GetActiveClients(&clients);
+ bool bReturn(false);
+ CSingleLock lock(m_critSection);
- /* get the member list from each client */
- CLIENTMAPITR itrClients = clients.begin();
- while (itrClients != clients.end())
+ if (m_currentChannel)
+ delete m_currentChannel;
+ if (m_currentRecording)
+ delete m_currentRecording;
+
+ /* try to open the recording stream on the client */
+ if (m_clientMap[tag.m_iClientId]->OpenRecordedStream(tag))
{
- if ((*itrClients).second->ReadyToUse())
- {
- PVR_ERROR currentError;
- currentError = (*itrClients).second->GetChannelGroupMembers(group);
+ m_currentRecording = &tag;
+ m_strPlayingClientName = GetClientName(tag.m_iClientId);
+ m_scanStart = CTimeUtils::GetTimeMS(); /* Reset the stream scan timer */
+ bReturn = true;
+ }
- if (currentError != PVR_ERROR_NO_ERROR)
- *error = currentError;
- }
+ return bReturn;
+}
- itrClients++;
+bool CPVRClients::CloseRecordedStream(void)
+{
+ bool bReturn(false);
+ CSingleLock lock(m_critSection);
+
+ if (!m_currentRecording)
+ return bReturn;
+
+ if (m_currentRecording->m_iClientId > 0 && m_clientMap[m_currentRecording->m_iClientId])
+ {
+ m_clientMap[m_currentRecording->m_iClientId]->CloseRecordedStream();
+ bReturn = true;
}
- return group->GetNumChannels() - iCurSize;
+ return bReturn;
}
-int CPVRClients::GetChannels(CPVRChannelGroupInternal *group, PVR_ERROR *error)
+bool CPVRClients::GetPlayingRecording(CPVRRecording *recording) const
{
- *error = PVR_ERROR_NO_ERROR;
- int iCurSize = group->GetNumChannels();
+ CSingleLock lock(m_critSection);
+ if (m_currentRecording != NULL)
+ *recording = *m_currentRecording;
+
+ return m_currentRecording != NULL;
+}
+
+void CPVRClients::DemuxReset(void)
+{
+ /* don't lock here cause it'll cause a dead lock when the client connection is dropped while playing */
+ if (m_currentChannel)
+ m_clientMap[m_currentChannel->ClientID()]->DemuxReset();
+}
+
+void CPVRClients::DemuxAbort(void)
+{
+ /* don't lock here cause it'll cause a dead lock when the client connection is dropped while playing */
+ if (m_currentChannel)
+ m_clientMap[m_currentChannel->ClientID()]->DemuxAbort();
+}
+
+void CPVRClients::DemuxFlush(void)
+{
+ /* don't lock here cause it'll cause a dead lock when the client connection is dropped while playing */
+ if (m_currentChannel)
+ m_clientMap[m_currentChannel->ClientID()]->DemuxFlush();
+}
+
+DemuxPacket* CPVRClients::ReadDemuxStream(void)
+{
+ /* don't lock here cause it'll cause a dead lock when the client connection is dropped while playing */
+ if (m_currentChannel)
+ return m_clientMap[m_currentChannel->ClientID()]->DemuxRead();
+
+ return NULL;
+}
+
+void CPVRClients::GetQualityData(PVR_SIGNAL_STATUS *status) const
+{
+ CSingleLock lock(m_critSection);
+ *status = m_qualityInfo;
+}
+
+int CPVRClients::GetSignalLevel(void) const
+{
+ CSingleLock lock(m_critSection);
+ return (int) ((float) m_qualityInfo.iSignal / 0xFFFF * 100);
+}
+
+int CPVRClients::GetSNR(void) const
+{
+ CSingleLock lock(m_critSection);
+ return (int) ((float) m_qualityInfo.iSNR / 0xFFFF * 100);
+}
+
+bool CPVRClients::HasTimerSupport(int iClientId)
+{
+ CSingleLock lock(m_critSection);
+
+ return IsValidClient(iClientId) && m_clientsProps[iClientId].bSupportsTimers;
+}
+
+int CPVRClients::GetTimers(CPVRTimers *timers)
+{
+ int iCurSize = timers->size();
CLIENTMAP clients;
GetActiveClients(&clients);
- /* get the channel list from each client */
+ /* get the timer list from each client */
CLIENTMAPITR itrClients = clients.begin();
while (itrClients != clients.end())
{
- if ((*itrClients).second->ReadyToUse())
- {
- PVR_ERROR currentError;
- currentError = (*itrClients).second->GetChannels(*group, group->IsRadio());
+ if (HasTimerSupport((*itrClients).first))
+ (*itrClients).second->GetTimers(timers);
- if (currentError != PVR_ERROR_NO_ERROR)
- *error = currentError;
- }
-
- itrClients++;
+ ++itrClients;
}
- return group->GetNumChannels() - iCurSize;
+ return timers->size() - iCurSize;
}
-const CStdString CPVRClients::GetStreamURL(const CPVRChannel &tag)
+bool CPVRClients::AddTimer(const CPVRTimerInfoTag &timer, PVR_ERROR *error)
{
- static CStdString strReturn;
+ *error = PVR_ERROR_UNKOWN;
boost::shared_ptr<CPVRClient> client;
- if (GetValidClient(tag.ClientID(), client))
- strReturn = client->GetLiveStreamURL(tag);
+ if (HasTimerSupport(timer.m_iClientId) && GetValidClient(timer.m_iClientId, client))
+ *error = client->AddTimer(timer);
else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, tag.ClientID());
+ CLog::Log(LOGERROR, "PVR - %s - client %d does not support timers",__FUNCTION__, timer.m_iClientId);
- return strReturn;
+ return *error == PVR_ERROR_NO_ERROR;
}
-void CPVRClients::Start(void)
+bool CPVRClients::UpdateTimer(const CPVRTimerInfoTag &timer, PVR_ERROR *error)
{
- Stop();
+ *error = PVR_ERROR_UNKOWN;
+ boost::shared_ptr<CPVRClient> client;
+ if (HasTimerSupport(timer.m_iClientId) && GetValidClient(timer.m_iClientId, client))
+ *error = client->UpdateTimer(timer);
+ else
+ CLog::Log(LOGERROR, "PVR - %s - client %d doest not support timers",__FUNCTION__, timer.m_iClientId);
- Create();
- SetName("XBMC PVR backend info");
- SetPriority(-1);
+ return *error == PVR_ERROR_NO_ERROR;
}
-void CPVRClients::Stop(void)
+bool CPVRClients::DeleteTimer(const CPVRTimerInfoTag &timer, bool bForce, PVR_ERROR *error)
{
- StopThread();
+ *error = PVR_ERROR_UNKOWN;
+ boost::shared_ptr<CPVRClient> client;
+ if (HasTimerSupport(timer.m_iClientId) && GetValidClient(timer.m_iClientId, client))
+ *error = client->DeleteTimer(timer, bForce);
+ else
+ CLog::Log(LOGERROR, "PVR - %s - client %d does not support timers",__FUNCTION__, timer.m_iClientId);
+
+ return *error == PVR_ERROR_NO_ERROR;
}
-void CPVRClients::Process(void)
+bool CPVRClients::RenameTimer(const CPVRTimerInfoTag &timer, const CStdString &strNewName, PVR_ERROR *error)
{
- while (!m_bStop)
- {
- UpdateCharInfoSignalStatus();
- Sleep(1000);
- }
+ *error = PVR_ERROR_UNKOWN;
+ boost::shared_ptr<CPVRClient> client;
+ if (HasTimerSupport(timer.m_iClientId) && GetValidClient(timer.m_iClientId, client))
+ *error = client->RenameTimer(timer, strNewName);
+ else
+ CLog::Log(LOGERROR, "PVR - %s - client %d does not support timers",__FUNCTION__, timer.m_iClientId);
+
+ return *error == PVR_ERROR_NO_ERROR;
}
-void CPVRClients::UpdateCharInfoSignalStatus(void)
+bool CPVRClients::HasRecordingsSupport(int iClientId)
{
CSingleLock lock(m_critSection);
- if (m_currentChannel && g_guiSettings.GetBool("pvrplayback.signalquality") &&
- !m_currentChannel->IsVirtual() && m_currentChannel->ClientID() >= 0 &&
- m_clientMap[m_currentChannel->ClientID()])
- {
- m_clientMap[m_currentChannel->ClientID()]->SignalQuality(m_qualityInfo);
- }
- else
- {
- ResetQualityData();
- }
+ return IsValidClient(iClientId) && m_clientsProps[iClientId].bSupportsRecordings;
}
-void CPVRClients::StartChannelScan(void)
+int CPVRClients::GetRecordings(CPVRRecordings *recordings)
{
- vector<long> clients;
- int scanningClientID = -1;
- CSingleLock lock(m_critSection);
- m_bChannelScanRunning = true;
+ int iCurSize = recordings->size();
+ CLIENTMAP clients;
+ GetActiveClients(&clients);
- /* get clients that support channel scanning */
- CLIENTMAPITR itr = m_clientMap.begin();
- while (itr != m_clientMap.end())
+ CLIENTMAPITR itrClients = clients.begin();
+ while (itrClients != clients.end())
{
- if (m_clientMap[(*itr).first]->ReadyToUse() && GetClientProperties(m_clientMap[(*itr).first]->GetID())->bSupportsChannelScan)
- clients.push_back(m_clientMap[(*itr).first]->GetID());
+ if (HasRecordingsSupport((*itrClients).first))
+ (*itrClients).second->GetRecordings(recordings);
- itr++;
+ itrClients++;
}
- /* multiple clients found */
- if (clients.size() > 1)
- {
- CGUIDialogSelect* pDialog= (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
-
- pDialog->Reset();
- pDialog->SetHeading(19119);
-
- for (unsigned int i = 0; i < clients.size(); i++)
- pDialog->Add(m_clientMap[clients[i]]->GetFriendlyName());
-
- pDialog->DoModal();
+ return recordings->size() - iCurSize;
+}
- int selection = pDialog->GetSelectedLabel();
- if (selection >= 0)
- scanningClientID = clients[selection];
- }
- /* one client found */
- else if (clients.size() == 1)
- {
- scanningClientID = clients[0];
- }
- /* no clients found */
- else if (scanningClientID < 0)
- {
- CGUIDialogOK::ShowAndGetInput(19033,0,19192,0);
- return;
- }
+bool CPVRClients::RenameRecording(const CPVRRecording &recording, PVR_ERROR *error)
+{
+ *error = PVR_ERROR_UNKOWN;
+ boost::shared_ptr<CPVRClient> client;
+ if (HasRecordingsSupport(recording.m_iClientId) && GetValidClient(recording.m_iClientId, client))
+ *error = client->RenameRecording(recording);
+ else
+ CLog::Log(LOGERROR, "PVR - %s - client %d does not support recordings",__FUNCTION__, recording.m_iClientId);
- /* start the channel scan */
- CLog::Log(LOGNOTICE,"PVR - %s - starting to scan for channels on client %s",
- __FUNCTION__, m_clientMap[scanningClientID]->GetFriendlyName());
- long perfCnt = CTimeUtils::GetTimeMS();
+ return *error == PVR_ERROR_NO_ERROR;
+}
- /* stop the supervisor thread */
- g_PVRManager.StopUpdateThreads();
+bool CPVRClients::DeleteRecording(const CPVRRecording &recording, PVR_ERROR *error)
+{
+ *error = PVR_ERROR_UNKOWN;
+ boost::shared_ptr<CPVRClient> client;
+ if (HasRecordingsSupport(recording.m_iClientId) && GetValidClient(recording.m_iClientId, client))
+ *error = client->DeleteRecording(recording);
+ else
+ CLog::Log(LOGERROR, "PVR - %s - client %d does not support recordings",__FUNCTION__, recording.m_iClientId);
- /* do the scan */
- if (m_clientMap[scanningClientID]->StartChannelScan() != PVR_ERROR_NO_ERROR)
- /* an error occured */
- CGUIDialogOK::ShowAndGetInput(19111,0,19193,0);
+ return *error == PVR_ERROR_NO_ERROR;
+}
- /* restart the supervisor thread */
- g_PVRManager.StartUpdateThreads();
+bool CPVRClients::IsRecordingOnPlayingChannel(void) const
+{
+ return m_currentChannel && m_currentChannel->IsRecording();
+}
- CLog::Log(LOGNOTICE, "PVRManager - %s - channel scan finished after %li.%li seconds",
- __FUNCTION__, (CTimeUtils::GetTimeMS()-perfCnt)/1000, (CTimeUtils::GetTimeMS()-perfCnt)%1000);
- m_bChannelScanRunning = false;
+bool CPVRClients::CanRecordInstantly(void)
+{
+ return m_currentChannel != NULL && HasRecordingsSupport(m_currentChannel->ClientID());
}
-PVR_ADDON_CAPABILITIES *CPVRClients::GetCurrentClientProperties(void)
+bool CPVRClients::HasEPGSupport(int iClientId)
{
- PVR_ADDON_CAPABILITIES * props = NULL;
CSingleLock lock(m_critSection);
- if (m_currentChannel)
- props = &m_clientsProps[m_currentChannel->ClientID()];
- else if (m_currentRecording)
- props = &m_clientsProps[m_currentRecording->m_iClientId];
+ return IsValidClient(iClientId) && m_clientsProps[iClientId].bSupportsEPG;
+}
- return props;
+bool CPVRClients::GetEPGForChannel(const CPVRChannel &channel, CPVREpg *epg, time_t start, time_t end, PVR_ERROR *error)
+{
+ *error = PVR_ERROR_UNKOWN;
+ boost::shared_ptr<CPVRClient> client;
+ if (HasEPGSupport(channel.ClientID()) && GetValidClient(channel.ClientID(), client))
+ *error = client->GetEPGForChannel(channel, epg, start, end);
+ else
+ CLog::Log(LOGERROR, "PVR - %s - client %d does not support EPG",__FUNCTION__, channel.ClientID());
+
+ return *error == PVR_ERROR_NO_ERROR;
}
-PVR_STREAM_PROPERTIES *CPVRClients::GetCurrentStreamProperties(void)
+int CPVRClients::GetChannels(CPVRChannelGroupInternal *group, PVR_ERROR *error)
{
- PVR_STREAM_PROPERTIES *props = NULL;
- CSingleLock lock(m_critSection);
+ *error = PVR_ERROR_NO_ERROR;
+ int iCurSize = group->GetNumChannels();
+ CLIENTMAP clients;
+ GetActiveClients(&clients);
- if (m_currentChannel)
+ /* get the channel list from each client */
+ CLIENTMAPITR itrClients = clients.begin();
+ while (itrClients != clients.end())
{
- int iChannelId = m_currentChannel->ClientID();
- m_clientMap[iChannelId]->GetStreamProperties(&m_streamProps[iChannelId]);
+ if ((*itrClients).second->ReadyToUse())
+ {
+ PVR_ERROR currentError;
+ currentError = (*itrClients).second->GetChannels(*group, group->IsRadio());
- props = &m_streamProps[iChannelId];
+ if (currentError != PVR_ERROR_NO_ERROR)
+ *error = currentError;
+ }
+
+ itrClients++;
}
- return props;
+ return group->GetNumChannels() - iCurSize;
}
-bool CPVRClients::GetPlayingChannel(CPVRChannel *channel) const
+bool CPVRClients::HasChannelGroupSupport(int iClientId)
{
CSingleLock lock(m_critSection);
- if (m_currentChannel != NULL)
- *channel = *m_currentChannel;
- else
- channel = NULL;
+ return IsValidClient(iClientId) && m_clientsProps[iClientId].bSupportsChannelGroups;
+}
- return m_currentChannel != NULL;
+int CPVRClients::GetChannelGroups(CPVRChannelGroups *groups, PVR_ERROR *error)
+{
+ *error = PVR_ERROR_UNKOWN;
+ int iCurSize = groups->size();
+ CLIENTMAP clients;
+ GetActiveClients(&clients);
+
+ /* get the channel groups list from each client */
+ CLIENTMAPITR itrClients = clients.begin();
+ while (itrClients != clients.end())
+ {
+ if (HasChannelGroupSupport((*itrClients).first))
+ (*itrClients).second->GetChannelGroups(groups);
+
+ itrClients++;
+ }
+
+ return groups->size() - iCurSize;
}
-bool CPVRClients::GetPlayingRecording(CPVRRecording *recording) const
+int CPVRClients::GetChannelGroupMembers(CPVRChannelGroup *group, PVR_ERROR *error)
{
- CSingleLock lock(m_critSection);
- if (m_currentRecording != NULL)
- *recording = *m_currentRecording;
+ *error = PVR_ERROR_NO_ERROR;
+ int iCurSize = group->GetNumChannels();
+ CLIENTMAP clients;
+ GetActiveClients(&clients);
- return m_currentRecording != NULL;
-}
+ /* get the member list from each client */
+ CLIENTMAPITR itrClients = clients.begin();
+ while (itrClients != clients.end())
+ {
+ if (HasChannelGroupSupport((*itrClients).first))
+ {
+ PVR_ERROR currentError;
+ currentError = (*itrClients).second->GetChannelGroupMembers(group);
-int CPVRClients::GetPlayingClientID(void) const
-{
- int iReturn = -1;
- CSingleLock lock(m_critSection);
+ if (currentError != PVR_ERROR_NO_ERROR)
+ *error = currentError;
+ }
- if (m_currentChannel)
- iReturn = m_currentChannel->ClientID();
- else if (m_currentRecording)
- iReturn = m_currentRecording->m_iClientId;
+ itrClients++;
+ }
- return iReturn;
+ return group->GetNumChannels() - iCurSize;
}
bool CPVRClients::HasMenuHooks(int iClientID)
{
- bool bReturn = false;
+ bool bReturn(false);
if (iClientID < 0)
iClientID = GetPlayingClientID();
@@ -1020,15 +929,13 @@ bool CPVRClients::HasMenuHooks(int iClientID)
boost::shared_ptr<CPVRClient> client;
if (GetValidClient(iClientID, client))
bReturn = client->HaveMenuHooks();
- else
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, iClientID);
return bReturn;
}
bool CPVRClients::GetMenuHooks(int iClientID, PVR_MENUHOOKS *hooks)
{
- bool bReturn = false;
+ bool bReturn(false);
if (iClientID < 0)
iClientID = GetPlayingClientID();
@@ -1042,10 +949,6 @@ bool CPVRClients::GetMenuHooks(int iClientID, PVR_MENUHOOKS *hooks)
bReturn = true;
}
}
- else
- {
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, iClientID);
- }
return bReturn;
}
@@ -1062,7 +965,7 @@ void CPVRClients::ProcessMenuHooks(int iClientID)
boost::shared_ptr<CPVRClient> client;
if (!GetValidClient(iClientID, client))
return;
- std::vector<long> hookIDs;
+ std::vector<int> hookIDs;
CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
pDialog->Reset();
@@ -1083,149 +986,226 @@ void CPVRClients::ProcessMenuHooks(int iClientID)
}
}
-bool CPVRClients::CanRecordInstantly(void)
-{
- return m_currentChannel != NULL &&
- m_clientsProps[m_currentChannel->ClientID()].bSupportsTimers;
-}
-
-
-bool CPVRClients::IsRecordingOnPlayingChannel(void) const
+bool CPVRClients::IsRunningChannelScan(void) const
{
- return m_currentChannel && m_currentChannel->IsRecording();
+ CSingleLock lock(m_critSection);
+ return m_bChannelScanRunning;
}
-bool CPVRClients::SwitchChannel(const CPVRChannel &channel)
+void CPVRClients::StartChannelScan(void)
{
- bool bReturn = false;
+ vector<int> clients;
+ int scanningClientID = -1;
CSingleLock lock(m_critSection);
- if (m_currentChannel && m_currentChannel->ClientID() != channel.ClientID())
+ m_bChannelScanRunning = true;
+
+ /* get clients that support channel scanning */
+ CLIENTMAPITR itr = m_clientMap.begin();
+ while (itr != m_clientMap.end())
{
- lock.Leave();
- CloseStream();
- return OpenLiveStream(channel);
+ if (m_clientMap[(*itr).first]->ReadyToUse() && m_clientsProps[m_clientMap[(*itr).first]->GetID()].bSupportsChannelScan)
+ clients.push_back(m_clientMap[(*itr).first]->GetID());
+
+ itr++;
}
- boost::shared_ptr<CPVRClient> client;
- if (GetValidClient(channel.ClientID(), client))
+ /* multiple clients found */
+ if (clients.size() > 1)
{
- if (client->SwitchChannel(channel))
- {
- m_currentChannel = &channel;
- m_scanStart = CTimeUtils::GetTimeMS(); /* Reset the stream scan timer */
- ResetQualityData();
+ CGUIDialogSelect* pDialog= (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
- bReturn = true;
- }
- else
- {
- CLog::Log(LOGERROR, "PVR - %s - cannot switch channel on client %d",__FUNCTION__, channel.ClientID());
- }
+ pDialog->Reset();
+ pDialog->SetHeading(19119);
+
+ for (unsigned int i = 0; i < clients.size(); i++)
+ pDialog->Add(m_clientMap[clients[i]]->GetFriendlyName());
+
+ pDialog->DoModal();
+
+ int selection = pDialog->GetSelectedLabel();
+ if (selection >= 0)
+ scanningClientID = clients[selection];
}
- else
+ /* one client found */
+ else if (clients.size() == 1)
{
- CLog::Log(LOGERROR, "PVR - %s - cannot find client %d",__FUNCTION__, channel.ClientID());
+ scanningClientID = clients[0];
+ }
+ /* no clients found */
+ else if (scanningClientID < 0)
+ {
+ CGUIDialogOK::ShowAndGetInput(19033,0,19192,0);
+ return;
}
- return bReturn;
+ /* start the channel scan */
+ CLog::Log(LOGNOTICE,"PVR - %s - starting to scan for channels on client %s",
+ __FUNCTION__, m_clientMap[scanningClientID]->GetFriendlyName());
+ long perfCnt = CTimeUtils::GetTimeMS();
+
+ /* stop the supervisor thread */
+ g_PVRManager.StopUpdateThreads();
+
+ /* do the scan */
+ if (m_clientMap[scanningClientID]->StartChannelScan() != PVR_ERROR_NO_ERROR)
+ /* an error occured */
+ CGUIDialogOK::ShowAndGetInput(19111,0,19193,0);
+
+ /* restart the supervisor thread */
+ g_PVRManager.StartUpdateThreads();
+
+ CLog::Log(LOGNOTICE, "PVRManager - %s - channel scan finished after %li.%li seconds",
+ __FUNCTION__, (CTimeUtils::GetTimeMS()-perfCnt)/1000, (CTimeUtils::GetTimeMS()-perfCnt)%1000);
+ m_bChannelScanRunning = false;
}
-CStdString CPVRClients::GetCurrentInputFormat(void) const
+bool CPVRClients::GetValidClient(int iClientId, boost::shared_ptr<CPVRClient> &addon)
{
- static CStdString strReturn = "";
+ bool bReturn(false);
CSingleLock lock(m_critSection);
- if (m_currentChannel)
- strReturn = m_currentChannel->InputFormat();
+ CLIENTMAPITR itr = m_clientMap.find(iClientId);
+ if (itr != m_clientMap.end() && itr->second->ReadyToUse())
+ {
+ addon = itr->second;
+ bReturn = true;
+ }
- return strReturn;
+ return bReturn;
}
-void CPVRClients::OnClientMessage(const int iClientId, const PVR_EVENT clientEvent, const char *strMessage)
+int CPVRClients::AddClientToDb(const CStdString &strClientId, const CStdString &strName)
{
- /* here the manager reacts to messages sent from any of the clients via the IPVRClientCallback */
- switch (clientEvent)
+ /* add this client to the database if it's not in there yet */
+ CPVRDatabase *database = OpenPVRDatabase();
+ int iClientDbId = database ? database->AddClient(strName, strClientId) : -1;
+ if (iClientDbId == -1)
{
- case PVR_EVENT_TIMERS_CHANGE:
- {
- CLog::Log(LOGDEBUG, "PVR - %s - timers changed on client '%d'",
- __FUNCTION__, iClientId);
- g_PVRManager.TriggerTimersUpdate();
- }
- break;
+ CLog::Log(LOGERROR, "PVR - %s - can't add client '%s' to the database",
+ __FUNCTION__, strName.c_str());
+ }
- case PVR_EVENT_RECORDINGS_CHANGE:
- {
- CLog::Log(LOGDEBUG, "PVR - %s - recording list changed on client '%d'",
- __FUNCTION__, iClientId);
- g_PVRManager.TriggerRecordingsUpdate();
- }
- break;
+ return iClientDbId;
+}
+
+bool CPVRClients::LoadClients(void)
+{
+ CSingleLock lock(m_critSection);
+ if (m_bAllClientsLoaded)
+ return !m_clientMap.empty();
+
+ CAddonMgr::Get().RegisterAddonMgrCallback(ADDON_PVRDLL, this);
+
+ /* get all PVR addons */
+ VECADDONS addons;
+ if (!CAddonMgr::Get().GetAddons(ADDON_PVRDLL, addons, true))
+ return false;
+
+ /* load and initialise the clients */
+ CPVRDatabase *database = OpenPVRDatabase();
+ if (!database)
+ return false;
+
+ m_bAllClientsLoaded = true;
+ for (unsigned iClientPtr = 0; iClientPtr < addons.size(); iClientPtr++)
+ {
+ const AddonPtr clientAddon = addons.at(iClientPtr);
+ if (!clientAddon->Enabled())
+ continue;
+
+ int iClientId = AddClientToDb(clientAddon->ID(), clientAddon->Name());
+ if (iClientId == -1)
+ continue; // don't set "m_bAllClientsLoaded = false;" here because this will enter a neverending loop
+
+ /* check if this client isn't active already */
+ if (IsValidClient(iClientId))
+ continue;
- case PVR_EVENT_CHANNELS_CHANGE:
+ /* load and initialise the client libraries */
+ boost::shared_ptr<CPVRClient> addon = boost::dynamic_pointer_cast<CPVRClient>(clientAddon);
+ if (addon && addon->Create(iClientId))
{
- CLog::Log(LOGDEBUG, "PVR - %s - channel list changed on client '%d'",
- __FUNCTION__, iClientId);
- g_PVRManager.TriggerChannelsUpdate();
+ /* get the client's properties */
+ PVR_ADDON_CAPABILITIES props;
+ if (addon->GetAddonCapabilities(&props) == PVR_ERROR_NO_ERROR)
+ {
+ m_clientMap.insert(std::make_pair(iClientId, addon));
+ m_clientsProps.insert(std::make_pair(iClientId, props));
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "PVR - %s - can't get client properties from addon '%s'",
+ __FUNCTION__, clientAddon->Name().c_str());
+ m_bAllClientsLoaded = false;
+ }
}
- break;
-
- case PVR_EVENT_CHANNEL_GROUPS_CHANGE:
+ else
{
- CLog::Log(LOGDEBUG, "PVR - %s - channel groups list changed on client '%d'",
- __FUNCTION__, iClientId);
- g_PVRManager.TriggerChannelGroupsUpdate();
+ CLog::Log(LOGERROR, "PVR - %s - can't initialise client '%s'",
+ __FUNCTION__, clientAddon->Name().c_str());
+ m_bAllClientsLoaded = false;
}
- break;
-
- default:
- CLog::Log(LOGWARNING, "PVR - %s - client '%d' sent unknown event '%s'",
- __FUNCTION__, iClientId, strMessage);
- break;
}
+
+ database->Close();
+
+ return !m_clientMap.empty();
}
-bool CPVRClients::RequestRestart(AddonPtr addon, bool bDataChanged)
+void CPVRClients::ResetQualityData(void)
{
- return StopClient(addon, true);
+ if (g_guiSettings.GetBool("pvrplayback.signalquality"))
+ {
+ strncpy(m_qualityInfo.strAdapterName, g_localizeStrings.Get(13205).c_str(), 1024);
+ strncpy(m_qualityInfo.strAdapterStatus, g_localizeStrings.Get(13205).c_str(), 1024);
+ }
+ else
+ {
+ strncpy(m_qualityInfo.strAdapterName, g_localizeStrings.Get(13106).c_str(), 1024);
+ strncpy(m_qualityInfo.strAdapterStatus, g_localizeStrings.Get(13106).c_str(), 1024);
+ }
+ m_qualityInfo.iSNR = 0;
+ m_qualityInfo.iSignal = 0;
+ m_qualityInfo.iSNR = 0;
+ m_qualityInfo.iUNC = 0;
+ m_qualityInfo.dVideoBitrate = 0;
+ m_qualityInfo.dAudioBitrate = 0;
+ m_qualityInfo.dDolbyBitrate = 0;
}
-bool CPVRClients::RequestRemoval(AddonPtr addon)
+int CPVRClients::ReadLiveStream(void* lpBuf, int64_t uiBufSize)
{
- return StopClient(addon, false);
+ CSingleLock lock(m_critSection);
+ return m_currentChannel ? m_clientMap[m_currentChannel->ClientID()]->ReadLiveStream(lpBuf, uiBufSize) : 0;
}
-int CPVRClients::GetSignalLevel(void) const
+int CPVRClients::ReadRecordedStream(void* lpBuf, int64_t uiBufSize)
{
CSingleLock lock(m_critSection);
- return (int) ((float) m_qualityInfo.iSignal / 0xFFFF * 100);
+ return m_currentRecording ? m_clientMap[m_currentRecording->m_iClientId]->ReadRecordedStream(lpBuf, uiBufSize) : 0;
}
-int CPVRClients::GetSNR(void) const
+void CPVRClients::Process(void)
{
- CSingleLock lock(m_critSection);
- return (int) ((float) m_qualityInfo.iSNR / 0xFFFF * 100);
+ while (!m_bStop)
+ {
+ UpdateCharInfoSignalStatus();
+ Sleep(1000);
+ }
}
-int CPVRClients::GetActiveClients(CLIENTMAP *clients)
+void CPVRClients::UpdateCharInfoSignalStatus(void)
{
- int iReturn = 0;
CSingleLock lock(m_critSection);
- if (m_clientMap.size() > 0)
+ if (m_currentChannel && g_guiSettings.GetBool("pvrplayback.signalquality") &&
+ !m_currentChannel->IsVirtual() && m_currentChannel->ClientID() >= 0 &&
+ m_clientMap[m_currentChannel->ClientID()])
{
- CLIENTMAPITR itr = m_clientMap.begin();
- while (itr != m_clientMap.end())
- {
- if (m_clientMap[(*itr).first]->ReadyToUse())
- {
- clients->insert(std::make_pair(m_clientMap[(*itr).first]->GetID(), m_clientMap[(*itr).first]));
- ++iReturn;
- break;
- }
- itr++;
- }
+ m_clientMap[m_currentChannel->ClientID()]->SignalQuality(m_qualityInfo);
+ }
+ else
+ {
+ ResetQualityData();
}
-
- return iReturn;
}
524 xbmc/pvr/addons/PVRClients.h
View
@@ -31,15 +31,14 @@ namespace PVR
{
class CPVRGUIInfo;
- typedef std::map< long, boost::shared_ptr<CPVRClient> > CLIENTMAP;
- typedef std::map< long, boost::shared_ptr<CPVRClient> >::iterator CLIENTMAPITR;
- typedef std::map< long, PVR_ADDON_CAPABILITIES > CLIENTPROPS;
- typedef std::map< long, PVR_STREAM_PROPERTIES > STREAMPROPS;
+ typedef std::map< int, boost::shared_ptr<CPVRClient> > CLIENTMAP;
+ typedef std::map< int, boost::shared_ptr<CPVRClient> >::iterator CLIENTMAPITR;
+ typedef std::map< int, PVR_ADDON_CAPABILITIES > CLIENTPROPS;
+ typedef std::map< int, PVR_STREAM_PROPERTIES > STREAMPROPS;
#define XBMC_VIRTUAL_CLIENTID -1
- class CPVRClients : IPVRClientCallback,
- public ADDON::IAddonMgrCallback,
+ class CPVRClients : public ADDON::IAddonMgrCallback,
private CThread
{
friend class CPVRGUIInfo;
@@ -49,10 +48,39 @@ namespace PVR
virtual ~CPVRClients(void);
/*!
- * @brief Get the ID of the first client.
- * @return The ID of the first client or -1 if no clients are active;
+ * @brief Start the backend info updater thread.
*/
- int GetFirstID(void);
+ void Start(void);
+
+ /*!
+ * @brief Stop the backend info updater thread.
+ */
+ void Stop(void);
+
+ /*! @name Backend methods */
+ //@{
+
+ /*!
+ * @brief Check whether a client ID points to a valid add-on.
+ * @param iClientId The client ID.
+ * @return True when the client ID is valid, false otherwise.
+ */
+ bool IsValidClient(int iClientId);
+
+ /*!
+ * @brief Restart a single client add-on.
+ * @param addon The add-on to restart.
+ * @param bDataChanged True if the client's data changed, false otherwise (unused).
+ * @return True if the client was found and restarted, false otherwise.
+ */
+ bool RequestRestart(ADDON::AddonPtr addon, bool bDataChanged);
+
+ /*!
+ * @brief Remove a single client add-on.
+ * @param addon The add-on to remove.
+ * @return True if the client was found and removed, false otherwise.
+ */
+ bool RequestRemoval(ADDON::AddonPtr addon);
/*!
* @brief Try to load and initialise all clients.
@@ -62,6 +90,26 @@ namespace PVR
bool TryLoadClients(int iMaxTime = 0);
/*!
+ * @brief Unload all loaded add-ons and reset all class properties.
+ */
+ void Unload(void);
+
+ /*!
+ * @brief The ID of the first active client or -1 if no clients are active;
+ */
+ int GetFirstID(void);
+
+ /*!
+ * @return True when all clients are loaded, false otherwise.
+ */
+ bool AllClientsLoaded(void) const;
+
+ /*!
+ * @return True when at least one client is known, false otherwise.
+ */
+ bool HasClients(void) const;
+
+ /*!
* @brief Stop a client.
* @param addon The client to stop.
* @param bRestart If true, restart the client.
@@ -70,55 +118,70 @@ namespace PVR
bool StopClient(ADDON::AddonPtr client, bool bRestart);
/*!
- * @brief Open a stream on the given channel.
- * @param tag The channel to start playing.
- * @return True if the stream was opened successfully, false otherwise.
+ * @return The amount of active clients.
*/
- bool OpenLiveStream(const CPVRChannel &tag);
- bool CloseLiveStream(void);
+ int ActiveClientAmount(void);
/*!
- * @brief Open a stream from the given recording.
- * @param tag The recording to start playing.
- * @return True if the stream was opened successfully, false otherwise.
+ * @brief Check whether there are any active clients.
+ * @return True if at least one client is active.
*/
- bool OpenRecordedStream(const CPVRRecording &tag);
- bool CloseRecordedStream(void);
+ bool HasActiveClients(void);
/*!
- * @brief Close a PVR stream.
+ * @brief Get the friendly name for the client with the given id.
+ * @param iClientId The id of the client.
+ * @return The friendly name of the client or an empty string when it wasn't found.
*/
- void CloseStream(void);
+ const CStdString GetClientName(int iClientId);
/*!
- * @brief Read from an open stream.
- * @param lpBuf Target buffer.
- * @param uiBufSize The size of the buffer.
- * @return The amount of bytes that was added.
+ * @bried Get all active clients.
+ * @param clients Store the active clients in this map.
+ * @return The amount of added clients.
*/
- int ReadStream(void* lpBuf, int64_t uiBufSize);
+ int GetActiveClients(CLIENTMAP *clients);
/*!
- * @brief Reset the demuxer.
+ * @return The client ID of the client that is currently playing a stream or -1 if no client is playing.
*/
- void DemuxReset(void);
+ int GetPlayingClientID(void) const;
/*!
- * @brief Abort any internal reading that might be stalling main thread.
- * NOTICE - this can be called from another thread.
+ * @brief Get the properties for a specific client.
+ * @param clientID The ID of the client.
+ * @return A pointer to the properties or NULL if the client wasn't found.
*/
- void DemuxAbort(void);
+ PVR_ADDON_CAPABILITIES *GetAddonCapabilities(int iClientId);
/*!
- * @brief Flush the demuxer. If any data is kept in buffers, this should be freed now.
+ * @brief Get the properties of the current playing client.
+ * @return A pointer to the properties or NULL if no stream is playing.
*/
- void DemuxFlush(void);
+ PVR_ADDON_CAPABILITIES *GetCurrentAddonCapabilities(void);
+
+ //@}
+
+ /*! @name Stream methods */
+ //@{
/*!
- * @brief Read the stream from the demuxer
- * @return An allocated demuxer packet
+ * @return True if a stream is playing, false otherwise.
*/
- DemuxPacket* ReadDemuxStream(void);
+ bool IsPlaying(void) const;
+
+ /*!
+ * @return The friendly name of the client that is currently playing or an empty string if nothing is playing.
+ */
+ const CStdString GetPlayingClientName(void) const;
+
+ /*!
+ * @brief Read from an open stream.
+ * @param lpBuf Target buffer.
+ * @param uiBufSize The size of the buffer.
+ * @return The amount of bytes that was added.
+ */
+ int ReadStream(void* lpBuf, int64_t uiBufSize);
/*!
* @brief Return the filesize of the currently running stream.
@@ -142,161 +205,246 @@ namespace PVR
*/
int64_t GetStreamPosition(void);
- const CStdString GetClientName(int iClientId);
- const CStdString GetStreamURL(const CPVRChannel &tag);
- int GetSignalLevel(void) const;
- int GetSNR(void) const;
- bool HasClients(void) const;
- bool HasTimerSupport(int iClientId);
- bool IsEncrypted(void) const;
- bool IsPlaying(void) const;
- bool AllClientsLoaded(void) const;
+ /*!
+ * @brief Close a PVR stream.
+ */
+ void CloseStream(void);
+
+ /*!
+ * @brief Get the properties of the current playing stream content.
+ * @return A pointer to the properties or NULL if no stream is playing.
+ */
+ PVR_STREAM_PROPERTIES *GetCurrentStreamProperties(void);
+
+ /*!
+ * @brief Get the input format name of the current playing stream content.
+ * @return A pointer to the properties or NULL if no stream is playing.
+ */
+ const char *GetCurrentInputFormat(void) const;
+ //@}
+