Merge pull request #4700 from MartijnKaijser/13.1b2 13.1b2-Gotham
authorjmarshallnz <jcmarsha@gmail.com>
Sat, 17 May 2014 23:28:04 +0000 (11:28 +1200)
committerjmarshallnz <jcmarsha@gmail.com>
Sat, 17 May 2014 23:28:04 +0000 (11:28 +1200)
13.1b2

xbmc/Application.cpp
xbmc/FileItem.cpp
xbmc/FileItem.h
xbmc/interfaces/AnnouncementManager.cpp
xbmc/interfaces/AnnouncementManager.h
xbmc/network/AirPlayServer.cpp
xbmc/network/AirPlayServer.h
xbmc/network/upnp/UPnPServer.cpp
xbmc/pvr/windows/GUIWindowPVRRecordings.cpp

index b7eaca3..9242d53 100644 (file)
@@ -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())
       {
index eb0e4a5..75f70b8 100644 (file)
@@ -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;
+}
index 286bd34..56df810 100644 (file)
@@ -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;
index 287f5a4..2932e59 100644 (file)
@@ -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)
index b8f1a7b..6f4208d 100644 (file)
@@ -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);
index 127a765..8040d9b 100644 (file)
@@ -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;
index 4c486fb..27c7f40 100644 (file)
@@ -112,6 +112,7 @@ private:
   CStdString m_password;
   int m_origVolume;
 
+  static CCriticalSection ServerInstanceLock;
   static CAirPlayServer *ServerInstance;
 };
 
index 49a21c4..4fd42af 100644 (file)
@@ -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);
         }
     }
index feb3900..573b464 100644 (file)
@@ -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())