aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xbmc/Application.cpp6
-rw-r--r--xbmc/FileItem.cpp23
-rw-r--r--xbmc/FileItem.h12
-rw-r--r--xbmc/interfaces/AnnouncementManager.cpp6
-rw-r--r--xbmc/interfaces/AnnouncementManager.h2
-rw-r--r--xbmc/network/AirPlayServer.cpp15
-rw-r--r--xbmc/network/AirPlayServer.h1
-rw-r--r--xbmc/network/upnp/UPnPServer.cpp3
-rw-r--r--xbmc/pvr/windows/GUIWindowPVRRecordings.cpp17
9 files changed, 65 insertions, 20 deletions
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
index b7eaca31ec..9242d5363f 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -3555,6 +3555,8 @@ void CApplication::Stop(int exitCode)
CLog::Log(LOGNOTICE, "stop player");
m_pPlayer->ClosePlayer();
+ CAnnouncementManager::Deinitialize();
+
StopPVRManager();
StopServices();
//Sleep(5000);
@@ -4004,8 +4006,8 @@ PlayBackRet CApplication::PlayFile(const CFileItem& item, bool bRestart)
should the playerState be required, it is fetched from the database.
See the note in CGUIWindowVideoBase::ShowResumeMenu.
*/
- if (item.HasVideoInfoTag() && item.GetVideoInfoTag()->m_resumePoint.IsSet())
- options.starttime = item.GetVideoInfoTag()->m_resumePoint.timeInSeconds;
+ if (item.IsResumePointSet())
+ options.starttime = item.GetCurrentResumeTime();
}
else if (item.HasVideoInfoTag())
{
diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp
index eb0e4a5cc4..75f70b81f9 100644
--- a/xbmc/FileItem.cpp
+++ b/xbmc/FileItem.cpp
@@ -3320,3 +3320,26 @@ int CFileItem::GetVideoContentType() const
return type;
}
+bool CFileItem::IsResumePointSet() const
+{
+ return (HasVideoInfoTag() && GetVideoInfoTag()->m_resumePoint.IsSet()) ||
+ (HasPVRRecordingInfoTag() && GetPVRRecordingInfoTag()->GetLastPlayedPosition() > 0);
+}
+
+double CFileItem::GetCurrentResumeTime() const
+{
+ if (HasPVRRecordingInfoTag())
+ {
+ // This will retrieve 'fresh' resume information from the PVR server
+ int rc = GetPVRRecordingInfoTag()->GetLastPlayedPosition();
+ if (rc > 0)
+ return rc;
+ // Fall through to default value
+ }
+ if (HasVideoInfoTag() && GetVideoInfoTag()->m_resumePoint.IsSet())
+ {
+ return GetVideoInfoTag()->m_resumePoint.timeInSeconds;
+ }
+ // Resume from start when resume points are invalid or the PVR server returns an error
+ return 0;
+}
diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h
index 286bd349b2..56df810036 100644
--- a/xbmc/FileItem.h
+++ b/xbmc/FileItem.h
@@ -295,6 +295,18 @@ public:
return m_pvrTimerInfoTag;
}
+ /*!
+ \brief Test if this item has a valid resume point set.
+ \return True if this item has a resume point and it is set, false otherwise.
+ */
+ bool IsResumePointSet() const;
+
+ /*!
+ \brief Return the current resume time.
+ \return The time in seconds from the start to resume playing from.
+ */
+ double GetCurrentResumeTime() const;
+
inline bool HasPictureInfoTag() const
{
return m_pictureInfoTag != NULL;
diff --git a/xbmc/interfaces/AnnouncementManager.cpp b/xbmc/interfaces/AnnouncementManager.cpp
index 287f5a4715..2932e59aba 100644
--- a/xbmc/interfaces/AnnouncementManager.cpp
+++ b/xbmc/interfaces/AnnouncementManager.cpp
@@ -39,6 +39,12 @@ using namespace ANNOUNCEMENT;
#define m_announcers XBMC_GLOBAL_USE(ANNOUNCEMENT::CAnnouncementManager::Globals).m_announcers
#define m_critSection XBMC_GLOBAL_USE(ANNOUNCEMENT::CAnnouncementManager::Globals).m_critSection
+void CAnnouncementManager::Deinitialize()
+{
+ CSingleLock lock (m_critSection);
+ m_announcers.clear();
+}
+
void CAnnouncementManager::AddAnnouncer(IAnnouncer *listener)
{
if (!listener)
diff --git a/xbmc/interfaces/AnnouncementManager.h b/xbmc/interfaces/AnnouncementManager.h
index b8f1a7b37d..6f4208d97c 100644
--- a/xbmc/interfaces/AnnouncementManager.h
+++ b/xbmc/interfaces/AnnouncementManager.h
@@ -38,6 +38,8 @@ namespace ANNOUNCEMENT
std::vector<IAnnouncer *> m_announcers;
};
+ static void Deinitialize();
+
static void AddAnnouncer(IAnnouncer *listener);
static void RemoveAnnouncer(IAnnouncer *listener);
static void Announce(AnnouncementFlag flag, const char *sender, const char *message);
diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp
index 127a765985..8040d9b0d1 100644
--- a/xbmc/network/AirPlayServer.cpp
+++ b/xbmc/network/AirPlayServer.cpp
@@ -63,6 +63,7 @@ using namespace ANNOUNCEMENT;
#define AIRPLAY_STATUS_NOT_IMPLEMENTED 501
#define AIRPLAY_STATUS_NO_RESPONSE_NEEDED 1000
+CCriticalSection CAirPlayServer::ServerInstanceLock;
CAirPlayServer *CAirPlayServer::ServerInstance = NULL;
int CAirPlayServer::m_isPlaying = 0;
@@ -156,6 +157,8 @@ const char *eventStrings[] = {"playing", "paused", "loading", "stopped"};
void CAirPlayServer::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
{
+ CSingleLock lock(ServerInstanceLock);
+
if ( (flag & Player) && strcmp(sender, "xbmc") == 0 && ServerInstance)
{
if (strcmp(message, "OnStop") == 0)
@@ -184,6 +187,8 @@ bool CAirPlayServer::StartServer(int port, bool nonlocal)
{
StopServer(true);
+ CSingleLock lock(ServerInstanceLock);
+
ServerInstance = new CAirPlayServer(port, nonlocal);
if (ServerInstance->Initialize())
{
@@ -196,6 +201,7 @@ bool CAirPlayServer::StartServer(int port, bool nonlocal)
bool CAirPlayServer::SetCredentials(bool usePassword, const CStdString& password)
{
+ CSingleLock lock(ServerInstanceLock);
bool ret = false;
if (ServerInstance)
@@ -214,6 +220,7 @@ bool CAirPlayServer::SetInternalCredentials(bool usePassword, const CStdString&
void CAirPlayServer::StopServer(bool bWait)
{
+ CSingleLock lock(ServerInstanceLock);
if (ServerInstance)
{
ServerInstance->StopThread(bWait);
@@ -694,13 +701,17 @@ bool CAirPlayServer::CTCPClient::checkAuthorization(const CStdString& authStr,
void CAirPlayServer::backupVolume()
{
- if (ServerInstance->m_origVolume == -1)
+ CSingleLock lock(ServerInstanceLock);
+
+ if (ServerInstance && ServerInstance->m_origVolume == -1)
ServerInstance->m_origVolume = (int)g_application.GetVolume();
}
void CAirPlayServer::restoreVolume()
{
- if (ServerInstance->m_origVolume != -1 && CSettings::Get().GetBool("services.airplayvolumecontrol"))
+ CSingleLock lock(ServerInstanceLock);
+
+ if (ServerInstance && ServerInstance->m_origVolume != -1 && CSettings::Get().GetBool("services.airplayvolumecontrol"))
{
g_application.SetVolume((float)ServerInstance->m_origVolume);
ServerInstance->m_origVolume = -1;
diff --git a/xbmc/network/AirPlayServer.h b/xbmc/network/AirPlayServer.h
index 4c486fbff8..27c7f40b2d 100644
--- a/xbmc/network/AirPlayServer.h
+++ b/xbmc/network/AirPlayServer.h
@@ -112,6 +112,7 @@ private:
CStdString m_password;
int m_origVolume;
+ static CCriticalSection ServerInstanceLock;
static CAirPlayServer *ServerInstance;
};
diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp
index 49a21c4fa1..4fd42af4fc 100644
--- a/xbmc/network/upnp/UPnPServer.cpp
+++ b/xbmc/network/upnp/UPnPServer.cpp
@@ -755,7 +755,8 @@ CUPnPServer::BuildResponse(PLT_ActionReference& action,
// this isn't pretty but needed to properly hide the addons node from clients
if (StringUtils::StartsWith(items.GetPath(), "library")) {
for (int i=0; i<items.Size(); i++) {
- if (StringUtils::StartsWith(items[i]->GetPath(), "addons"))
+ if (StringUtils::StartsWith(items[i]->GetPath(), "addons") ||
+ StringUtils::EndsWith(items[i]->GetPath(), "/addons.xml/"))
items.Remove(i);
}
}
diff --git a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp
index feb39008de..573b46493f 100644
--- a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp
+++ b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp
@@ -70,21 +70,8 @@ CStdString CGUIWindowPVRRecordings::GetResumeString(const CFileItem& item)
// First try to find the resume position on the back-end, if that fails use video database
int positionInSeconds = item.GetPVRRecordingInfoTag()->GetLastPlayedPosition();
- // If the back-end does report a saved position then make sure there is a corresponding resume bookmark
- if (positionInSeconds > 0)
- {
- CBookmark bookmark;
- bookmark.timeInSeconds = positionInSeconds;
- bookmark.totalTimeInSeconds = (double)item.GetPVRRecordingInfoTag()->GetDuration();
- CVideoDatabase db;
- if (db.Open())
- {
- CStdString itemPath(item.GetPVRRecordingInfoTag()->m_strFileNameAndPath);
- db.AddBookMarkToFile(itemPath, bookmark, CBookmark::RESUME);
- db.Close();
- }
- }
- else if (positionInSeconds < 0)
+ // If the back-end does report a saved position it will be picked up by FileItem
+ if (positionInSeconds < 0)
{
CVideoDatabase db;
if (db.Open())