void CActiveAE::Dispose()
{
-#if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
+#if defined(HAS_GLX) || defined(TARGET_DARWIN)
g_Windowing.Unregister(this);
#endif
}
// 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
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
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;
};
CAAudioUnitSink::CAAudioUnitSink()
-: m_initialized(false)
-, m_activated(false)
+: m_activated(false)
, m_buffer(NULL)
, m_playing(false)
, m_playing_saved(false)
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 = {};
{
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;
}
pause();
AudioUnitUninitialize(m_audioUnit);
AudioComponentInstanceDispose(m_audioUnit), m_audioUnit = NULL;
- AudioSessionSetActive(false);
AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange,
sessionPropertyCallback, this);
AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_CurrentHardwareOutputVolume,
}
}
-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;
#pragma once
-#if defined(HAS_GLX) || defined(TARGET_DARWIN_OSX)
+#if defined(HAS_GLX) || defined(TARGET_DARWIN)
class IDispResource
{
public:
#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;
#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();
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"];
[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")
{
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)
{
#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
{
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);
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);
#include "guilib/GraphicContext.h"
#include "guilib/Texture.h"
#include "utils/StringUtils.h"
+#include "guilib/DispResource.h"
+#include "threads/SingleLock.h"
#include <vector>
#undef BOOL
m_eWindowSystem = WINDOW_SYSTEM_IOS;
m_iVSyncErrors = 0;
+ m_bIsBackgrounded = false;
}
CWinSystemIOS::~CWinSystemIOS()
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)
{
}