Merge pull request #4350 from Memphiz/iosbgmusic
authorTrent Nelson <trent.a.b.nelson@gmail.com>
Thu, 10 Apr 2014 17:31:38 +0000 (11:31 -0600)
committerTrent Nelson <trent.a.b.nelson@gmail.com>
Thu, 10 Apr 2014 17:40:06 +0000 (11:40 -0600)
[ios] - restore the music background playback ability

xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h
xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.cpp
xbmc/guilib/DispResource.h
xbmc/guilib/TextureManager.cpp
xbmc/osx/ios/XBMCController.mm
xbmc/windowing/osx/WinSystemIOS.h
xbmc/windowing/osx/WinSystemIOS.mm

index f60c9d7..d8b89a1 100644 (file)
@@ -167,7 +167,7 @@ CActiveAE::~CActiveAE()
 
 void CActiveAE::Dispose()
 {
-#if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
+#if defined(HAS_GLX) || defined(TARGET_DARWIN)
   g_Windowing.Unregister(this);
 #endif
 
@@ -2152,7 +2152,7 @@ bool CActiveAE::Initialize()
   }
 
   // hook into windowing for receiving display reset events
-#if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
+#if defined(HAS_GLX) || defined(TARGET_DARWIN
   g_Windowing.Register(this);
 #endif
 
index 118d46a..8596617 100644 (file)
@@ -181,7 +181,7 @@ protected:
   CCriticalSection m_lock;
 };
 
-#if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
+#if defined(HAS_GLX) || defined(TARGET_DARWIN)
 class CActiveAE : public IAE, public IDispResource, private CThread
 #else
 class CActiveAE : public IAE, private CThread
index 973d944..cf9451c 100644 (file)
@@ -114,14 +114,11 @@ class CAAudioUnitSink
     static void sessionPropertyCallback(void *inClientData,
                   AudioSessionPropertyID inID, UInt32 inDataSize, const void *inData);
 
-    static void sessionInterruptionCallback(void *inClientData, UInt32 inInterruption);
-
     static OSStatus renderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
                   const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames,
                   AudioBufferList *ioData);
 
     bool                m_setup;
-    bool                m_initialized;
     bool                m_activated;
     AudioUnit           m_audioUnit;
     AudioStreamBasicDescription m_outputFormat;
@@ -142,8 +139,7 @@ class CAAudioUnitSink
 };
 
 CAAudioUnitSink::CAAudioUnitSink()
-: m_initialized(false)
-, m_activated(false)
+: m_activated(false)
 , m_buffer(NULL)
 , m_playing(false)
 , m_playing_saved(false)
@@ -335,25 +331,12 @@ bool CAAudioUnitSink::setupAudio()
   if (m_setup && m_audioUnit)
     return true;
 
-  // Audio Session Setup
-  UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
-  status = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
-                                   sizeof(sessionCategory), &sessionCategory);
-  if (status != noErr)
-  {
-    CLog::Log(LOGERROR, "%s error setting sessioncategory (error: %d)", __PRETTY_FUNCTION__, (int)status);
-    return false;
-  }
-
   AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange,
     sessionPropertyCallback, this);
 
   AudioSessionAddPropertyListener(kAudioSessionProperty_CurrentHardwareOutputVolume,
     sessionPropertyCallback, this);
  
-  if (AudioSessionSetActive(true) != noErr)
-    return false;
-
   // Audio Unit Setup
   // Describe a default output unit.
   AudioComponentDescription description = {};
@@ -458,17 +441,6 @@ bool CAAudioUnitSink::activateAudioSession()
 {
   if (!m_activated)
   {
-    if (!m_initialized)
-    {
-      OSStatus osstat = AudioSessionInitialize(NULL, kCFRunLoopDefaultMode, sessionInterruptionCallback, this);
-      if (osstat == kAudioSessionNoError || osstat == kAudioSessionAlreadyInitialized)
-        m_initialized = true;
-      else
-      {
-        CLog::Log(LOGERROR, "%s error initializing audio session (error: %d)", __PRETTY_FUNCTION__, (int)osstat);
-        return false;
-      }
-    }
     if (checkAudioRoute() && setupAudio())
       m_activated = true;
   }
@@ -483,7 +455,6 @@ void CAAudioUnitSink::deactivateAudioSession()
     pause();
     AudioUnitUninitialize(m_audioUnit);
     AudioComponentInstanceDispose(m_audioUnit), m_audioUnit = NULL;
-    AudioSessionSetActive(false);
     AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange,
       sessionPropertyCallback, this);
     AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_CurrentHardwareOutputVolume,
@@ -511,27 +482,6 @@ void CAAudioUnitSink::sessionPropertyCallback(void *inClientData,
   }
 }
 
-void CAAudioUnitSink::sessionInterruptionCallback(void *inClientData, UInt32 inInterruption)
-{    
-  CAAudioUnitSink *sink = (CAAudioUnitSink*)inClientData;
-
-  if (inInterruption == kAudioSessionBeginInterruption)
-  {
-    CLog::Log(LOGDEBUG, "Bgn interuption");
-    sink->m_playing_saved = sink->m_playing;
-    sink->pause();
-  }
-  else if (inInterruption == kAudioSessionEndInterruption)
-  {
-    CLog::Log(LOGDEBUG, "End interuption");
-    if (sink->m_playing_saved)
-    {
-      sink->m_playing_saved = false;
-      sink->play(sink->m_mute);
-    }
-  }
-}
-
 inline void LogLevel(unsigned int got, unsigned int wanted)
 {
   static unsigned int lastReported = INT_MAX;
index fc5ab16..3903a13 100644 (file)
@@ -20,7 +20,7 @@
 
 #pragma once
 
-#if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
+#if defined(HAS_GLX) || defined(TARGET_DARWIN)
 class IDispResource
 {
 public:
index 9e0e05d..f8dad80 100644 (file)
 #include "URL.h"
 #include <assert.h>
 
+#if defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV2)
+#include "windowing/WindowingFactory.h" // for g_Windowing in CGUITextureManager::FreeUnusedTextures
+#endif
+
 using namespace std;
 
 
@@ -478,7 +482,13 @@ void CGUITextureManager::FreeUnusedTextures(unsigned int timeDelay)
 #if defined(HAS_GL) || defined(HAS_GLES)
   for (unsigned int i = 0; i < m_unusedHwTextures.size(); ++i)
   {
-    glDeleteTextures(1, (GLuint*) &m_unusedHwTextures[i]);
+  // on ios the hw textures might be deleted from the os
+  // when XBMC is backgrounded (e.x. for backgrounded music playback)
+  // sanity check before delete in that case.
+#if defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV2)
+    if (!g_Windowing.IsBackgrounded() || glIsTexture(m_unusedHwTextures[i]))
+#endif
+      glDeleteTextures(1, (GLuint*) &m_unusedHwTextures[i]);
   }
 #endif
   m_unusedHwTextures.clear();
index d234d42..9a32c0f 100644 (file)
@@ -180,7 +180,7 @@ void AnnounceBridge(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, con
     LOG(@"item: %@", item.description);
     [g_xbmcController performSelectorOnMainThread:@selector(onPlay:) withObject:item  waitUntilDone:NO];
   }
-  else if (msg == "OnSpeedChanged")
+  else if (msg == "OnSpeedChanged" || msg == "OnPause")
   {
     NSDictionary *item = [dict valueForKey:@"item"];
     NSDictionary *player = [dict valueForKey:@"player"];
@@ -188,10 +188,8 @@ void AnnounceBridge(ANNOUNCEMENT::AnnouncementFlag flag, const char *sender, con
     [item setValue:[NSNumber numberWithDouble:g_application.GetTime()] forKey:@"elapsed"];
     LOG(@"item: %@", item.description);
     [g_xbmcController performSelectorOnMainThread:@selector(OnSpeedChanged:) withObject:item  waitUntilDone:NO];
-  }
-  else if (msg == "OnPause")
-  {
-    [g_xbmcController performSelectorOnMainThread:@selector(onPause:) withObject:[dict valueForKey:@"item"]  waitUntilDone:NO];
+    if (msg == "OnPause")
+      [g_xbmcController performSelectorOnMainThread:@selector(onPause:) withObject:[dict valueForKey:@"item"]  waitUntilDone:NO];
   }
   else if (msg == "OnStop")
   {
@@ -1037,11 +1035,13 @@ AnnounceReceiver *AnnounceReceiver::g_announceReceiver = NULL;
     m_isPlayingBeforeInactive = YES;
     CApplicationMessenger::Get().MediaPauseIfPlaying();
   }
+  g_Windowing.OnAppFocusChange(false);
 }
 
 - (void)enterForeground
 {
   PRINT_SIGNATURE();
+  g_Windowing.OnAppFocusChange(true);
   // when we come back, restore playing if we were.
   if (m_isPlayingBeforeInactive)
   {
index 0a7ad7f..5bab45a 100644 (file)
@@ -27,6 +27,9 @@
 #include "windowing/WinSystem.h"
 #include "rendering/gles/RenderSystemGLES.h"
 #include "utils/GlobalsHandling.h"
+#include "threads/CriticalSection.h"
+
+class IDispResource;
 
 class CWinSystemIOS : public CWinSystemBase, public CRenderSystemGLES
 {
@@ -56,12 +59,18 @@ public:
 
   virtual bool BeginRender();
   virtual bool EndRender();
+  
+  virtual void Register(IDispResource *resource);
+  virtual void Unregister(IDispResource *resource);
+  
   virtual int GetNumScreens();    
   virtual int GetCurrentScreen();
   
           void InitDisplayLink(void);
           void DeinitDisplayLink(void);
           double GetDisplayLinkFPS(void);
+          void OnAppFocusChange(bool focus);
+          bool IsBackgrounded() const { return m_bIsBackgrounded; }
 
 protected:
   virtual bool PresentRenderImpl(const CDirtyRegionList &dirty);
@@ -72,6 +81,9 @@ protected:
   bool         m_bWasFullScreenBeforeMinimize;
   CStdString   m_eglext;
   int          m_iVSyncErrors;
+  CCriticalSection             m_resourceSection;
+  std::vector<IDispResource*>  m_resources;
+  bool         m_bIsBackgrounded;
   
 private:
   bool GetScreenResolution(int* w, int* h, double* fps, int screenIdx);
index 677e464..97918ae 100644 (file)
@@ -34,6 +34,8 @@
 #include "guilib/GraphicContext.h"
 #include "guilib/Texture.h"
 #include "utils/StringUtils.h"
+#include "guilib/DispResource.h"
+#include "threads/SingleLock.h"
 #include <vector>
 #undef BOOL
 
@@ -54,6 +56,7 @@ CWinSystemIOS::CWinSystemIOS() : CWinSystemBase()
   m_eWindowSystem = WINDOW_SYSTEM_IOS;
 
   m_iVSyncErrors = 0;
+  m_bIsBackgrounded = false;
 }
 
 CWinSystemIOS::~CWinSystemIOS()
@@ -318,6 +321,29 @@ bool CWinSystemIOS::EndRender()
   return rtn;
 }
 
+void CWinSystemIOS::Register(IDispResource *resource)
+{
+  CSingleLock lock(m_resourceSection);
+  m_resources.push_back(resource);
+}
+
+void CWinSystemIOS::Unregister(IDispResource* resource)
+{
+  CSingleLock lock(m_resourceSection);
+  std::vector<IDispResource*>::iterator i = find(m_resources.begin(), m_resources.end(), resource);
+  if (i != m_resources.end())
+    m_resources.erase(i);
+}
+
+void CWinSystemIOS::OnAppFocusChange(bool focus)
+{
+  CSingleLock lock(m_resourceSection);
+  m_bIsBackgrounded = !focus;
+  CLog::Log(LOGDEBUG, "CWinSystemIOS::OnAppFocusChange: %d", focus ? 1 : 0);
+  for (std::vector<IDispResource *>::iterator i = m_resources.begin(); i != m_resources.end(); i++)
+    (*i)->OnAppFocusChange(focus);
+}
+
 void CWinSystemIOS::InitDisplayLink(void)
 {
 }