Permalink
Browse files

[osx] changed, add a property listener for virtual and physical forma…

…t changes and hook a cevent to them rather than blind sleeps
  • Loading branch information...
1 parent 676b680 commit 6105a33b28af5bfd3eaeeeda1f227a3682f0db80 @davilla davilla committed May 19, 2012
View
79 xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.cpp
@@ -23,6 +23,7 @@
#include "CoreAudioAEHAL.h"
#include "utils/log.h"
+#include "utils/StdString.h"
// AudioHardwareGetProperty and friends are deprecated,
// turn off the warning spew.
@@ -44,6 +45,22 @@ bool CCoreAudioStream::Open(AudioStreamID streamId)
{
m_StreamId = streamId;
CLog::Log(LOGDEBUG, "CCoreAudioStream::Open: Opened stream 0x%04x.", (uint)m_StreamId);
+
+ // watch for physical property changes.
+ AudioObjectPropertyAddress propertyAOPA;
+ propertyAOPA.mScope = kAudioObjectPropertyScopeGlobal;
+ propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
+ propertyAOPA.mSelector = kAudioStreamPropertyPhysicalFormat;
+ if (AudioObjectAddPropertyListener(m_StreamId, &propertyAOPA, HardwareStreamListener, this) != noErr)
+ CLog::Log(LOGERROR, "CCoreAudioStream::Open: couldn't set up a physical property listener.", m_StreamId);
+
+ // watch for virtual property changes.
+ propertyAOPA.mScope = kAudioObjectPropertyScopeGlobal;
+ propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
+ propertyAOPA.mSelector = kAudioStreamPropertyVirtualFormat;
+ if (AudioObjectAddPropertyListener(m_StreamId, &propertyAOPA, HardwareStreamListener, this) != noErr)
+ CLog::Log(LOGERROR, "CCoreAudioStream::Open: couldn't set up a virtual property listener.", m_StreamId);
+
return true;
}
@@ -56,6 +73,21 @@ void CCoreAudioStream::Close()
std::string formatString;
+ // remove the physical/virtual property listeners before we make changes
+ // that will trigger callbacks that we do not care about.
+ AudioObjectPropertyAddress propertyAOPA;
+ propertyAOPA.mScope = kAudioObjectPropertyScopeGlobal;
+ propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
+ propertyAOPA.mSelector = kAudioStreamPropertyPhysicalFormat;
+ if (AudioObjectRemovePropertyListener(m_StreamId, &propertyAOPA, HardwareStreamListener, this) != noErr)
+ CLog::Log(LOGDEBUG, "CCoreAudioStream::Close: Couldn't remove property listener.");
+
+ propertyAOPA.mScope = kAudioObjectPropertyScopeGlobal;
+ propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
+ propertyAOPA.mSelector = kAudioStreamPropertyVirtualFormat;
+ if (AudioObjectRemovePropertyListener(m_StreamId, &propertyAOPA, HardwareStreamListener, this) != noErr)
+ CLog::Log(LOGDEBUG, "CCoreAudioStream::Close: Couldn't remove property listener.");
+
// Revert any format changes we made
if (m_OriginalVirtualFormat.mFormatID && m_StreamId)
{
@@ -152,6 +184,7 @@ bool CCoreAudioStream::SetVirtualFormat(AudioStreamBasicDescription* pDesc)
return false;
}
}
+ m_virtual_format_event.Reset();
OSStatus ret = AudioStreamSetProperty(m_StreamId,
NULL, 0, kAudioStreamPropertyVirtualFormat, sizeof(AudioStreamBasicDescription), pDesc);
if (ret)
@@ -185,7 +218,7 @@ bool CCoreAudioStream::SetVirtualFormat(AudioStreamBasicDescription* pDesc)
(uint)m_StreamId, StreamDescriptionToString(checkVirtualFormat, formatString));
break;
}
- Sleep(100);
+ m_virtual_format_event.WaitMSec(100);
}
return true;
}
@@ -219,6 +252,7 @@ bool CCoreAudioStream::SetPhysicalFormat(AudioStreamBasicDescription* pDesc)
return false;
}
}
+ m_physical_format_event.Reset();
OSStatus ret = AudioStreamSetProperty(m_StreamId,
NULL, 0, kAudioStreamPropertyPhysicalFormat, sizeof(AudioStreamBasicDescription), pDesc);
if (ret)
@@ -243,7 +277,7 @@ bool CCoreAudioStream::SetPhysicalFormat(AudioStreamBasicDescription* pDesc)
return false;
}
if (checkPhysicalFormat.mSampleRate == pDesc->mSampleRate &&
- checkPhysicalFormat.mFormatID == pDesc->mFormatID &&
+ checkPhysicalFormat.mFormatID == pDesc->mFormatID &&
checkPhysicalFormat.mFramesPerPacket == pDesc->mFramesPerPacket)
{
// The right format is now active.
@@ -252,8 +286,9 @@ bool CCoreAudioStream::SetPhysicalFormat(AudioStreamBasicDescription* pDesc)
(uint)m_StreamId, StreamDescriptionToString(checkPhysicalFormat, formatString));
break;
}
- Sleep(100);
+ m_physical_format_event.WaitMSec(100);
}
+
return true;
}
@@ -306,3 +341,41 @@ bool CCoreAudioStream::GetAvailablePhysicalFormats(StreamFormatList* pList)
delete[] pFormatList;
return (ret == noErr);
}
+
+OSStatus CCoreAudioStream::HardwareStreamListener(AudioObjectID inObjectID,
+ UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void *inClientData)
+{
+ CCoreAudioStream *ca_stream = (CCoreAudioStream*)inClientData;
+
+ for (UInt32 i = 0; i < inNumberAddresses; i++)
+ {
+ if (inAddresses[i].mSelector == kAudioStreamPropertyPhysicalFormat)
+ {
+ AudioStreamBasicDescription actualFormat;
+ UInt32 propertySize = sizeof(AudioStreamBasicDescription);
+ // hardware physical format has changed.
+ if (AudioObjectGetPropertyData(ca_stream->m_StreamId, &inAddresses[i], 0, NULL, &propertySize, &actualFormat) == noErr)
+ {
+ CStdString formatString;
+ CLog::Log(LOGINFO, "CCoreAudioStream::HardwareStreamListener: "
+ "Hardware physical format changed to %s", StreamDescriptionToString(actualFormat, formatString));
+ ca_stream->m_physical_format_event.Set();
+ }
+ }
+ else if (inAddresses[i].mSelector == kAudioStreamPropertyVirtualFormat)
+ {
+ // hardware virtual format has changed.
+ AudioStreamBasicDescription actualFormat;
+ UInt32 propertySize = sizeof(AudioStreamBasicDescription);
+ if (AudioObjectGetPropertyData(ca_stream->m_StreamId, &inAddresses[i], 0, NULL, &propertySize, &actualFormat) == noErr)
+ {
+ CStdString formatString;
+ CLog::Log(LOGINFO, "CCoreAudioStream::HardwareStreamListener: "
+ "Hardware virtual format changed to %s", StreamDescriptionToString(actualFormat, formatString));
+ ca_stream->m_virtual_format_event.Set();
+ }
+ }
+ }
+
+ return noErr;
+}
View
8 xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.h
@@ -24,6 +24,7 @@
#if defined(TARGET_DARWIN_OSX)
+#include "threads/Thread.h"
#include <CoreAudio/CoreAudio.h>
#include <list>
@@ -52,6 +53,13 @@ class CCoreAudioStream
bool GetAvailablePhysicalFormats(StreamFormatList *pList);
protected:
+ static OSStatus HardwareStreamListener(AudioObjectID inObjectID,
+ UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void* inClientData);
+
+ CEvent m_virtual_format_event;
+ CEvent m_physical_format_event;
+
+
AudioStreamID m_StreamId;
AudioStreamBasicDescription m_OriginalVirtualFormat;
AudioStreamBasicDescription m_OriginalPhysicalFormat;

0 comments on commit 6105a33

Please sign in to comment.