Skip to content
This repository
Browse code

Merge pull request #2144 from Memphiz/canotify

[AE/CA] - add and handle devicechange notification
  • Loading branch information...
commit 7484699527c3dbd648e05b6337eede13fe819af9 2 parents 68faea5 + d0cf53c
Memphiz authored January 31, 2013
85  xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp
@@ -24,7 +24,6 @@
24 24
 
25 25
 #include "CoreAudioAEStream.h"
26 26
 #include "CoreAudioAESound.h"
27  
-#include "CoreAudioHardware.h"
28 27
 #include "cores/AudioEngine/Utils/AEUtil.h"
29 28
 #include "settings/GUISettings.h"
30 29
 #include "settings/Settings.h"
@@ -39,6 +38,46 @@
39 38
 #define DELAY_FRAME_TIME  20
40 39
 #define BUFFERSIZE        16416
41 40
 
  41
+// on darwin when the devicelist changes
  42
+// reinit by calling opencoreaudio with the last engine parameters 
  43
+// (this will fallback to default
  44
+// device when our current output device vanishes
  45
+// and on the other hand will go back to that device
  46
+// if it re-appears).
  47
+#if defined(TARGET_DARWIN_OSX)
  48
+OSStatus deviceChangedCB( AudioObjectID                       inObjectID,
  49
+                          UInt32                              inNumberAddresses,
  50
+                          const AudioObjectPropertyAddress    inAddresses[],
  51
+                          void*                               inClientData)
  52
+{
  53
+  CCoreAudioAE *pEngine = (CCoreAudioAE *)inClientData;
  54
+  pEngine->AudioDevicesChanged();
  55
+  CLog::Log(LOGDEBUG, "CCoreAudioAE - audiodevicelist changed!");
  56
+  return noErr;
  57
+}
  58
+
  59
+void RegisterDeviceChangedCB(bool bRegister, void *ref)
  60
+{
  61
+  OSStatus ret = noErr;
  62
+  const AudioObjectPropertyAddress inAdr = 
  63
+  {  
  64
+    kAudioHardwarePropertyDevices,
  65
+    kAudioObjectPropertyScopeGlobal,
  66
+    kAudioObjectPropertyElementMaster 
  67
+  };
  68
+  
  69
+  if (bRegister)
  70
+    ret = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &inAdr, deviceChangedCB, ref);
  71
+  else
  72
+    ret = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &inAdr, deviceChangedCB, ref);
  73
+
  74
+  if (ret != noErr)
  75
+    CLog::Log(LOGERROR, "CCoreAudioAE::Deinitialize - error %s a listener callback for device changes!", bRegister?"attaching":"removing");   
  76
+}
  77
+#else//ios
  78
+void RegisterDeviceChangedCB(bool bRegister, void *ref){}
  79
+#endif
  80
+
42 81
 CCoreAudioAE::CCoreAudioAE() :
43 82
   m_Initialized        (false         ),
44 83
   m_callbackRunning    (false         ),
@@ -54,14 +93,16 @@ CCoreAudioAE::CCoreAudioAE() :
54 93
   m_streamsPlaying     (false         ),
55 94
   m_isSuspended        (false         ),
56 95
   m_softSuspend        (false         ),
57  
-  m_softSuspendTimer   (0             ),
58  
-  m_currentAudioDevice (0             )
  96
+  m_softSuspendTimer   (0             )
59 97
 {
60 98
   HAL = new CCoreAudioAEHAL;
  99
+  
  100
+  RegisterDeviceChangedCB(true, this);
61 101
 }
62 102
 
63 103
 CCoreAudioAE::~CCoreAudioAE()
64 104
 {
  105
+  RegisterDeviceChangedCB(false, this);
65 106
   Shutdown();
66 107
 }
67 108
 
@@ -95,6 +136,17 @@ void CCoreAudioAE::Shutdown()
95 136
   HAL = NULL;
96 137
 }
97 138
 
  139
+void CCoreAudioAE::AudioDevicesChanged()
  140
+{
  141
+  // give CA a bit time to realise that maybe the 
  142
+  // default device might have changed now - else
  143
+  // OpenCoreAudio might open the old default device
  144
+  // again (yeah that really is the case - duh)
  145
+  Sleep(500);
  146
+  CSingleLock engineLock(m_engineLock);
  147
+  OpenCoreAudio(m_lastSampleRate, COREAUDIO_IS_RAW(m_lastStreamFormat), m_lastStreamFormat);
  148
+}
  149
+
98 150
 bool CCoreAudioAE::Initialize()
99 151
 {
100 152
   CSingleLock engineLock(m_engineLock);
@@ -104,6 +156,8 @@ bool CCoreAudioAE::Initialize()
104 156
   Deinitialize();
105 157
 
106 158
   bool ret = OpenCoreAudio(44100, false, AE_FMT_FLOAT);
  159
+  m_lastSampleRate = 44100;
  160
+  m_lastStreamFormat = AE_FMT_FLOAT;
107 161
 
108 162
   Start();
109 163
 
@@ -274,13 +328,6 @@ bool CCoreAudioAE::OpenCoreAudio(unsigned int sampleRate, bool forceRaw,
274 328
       (*itt)->Initialize();
275 329
     streamLock.Leave();
276 330
   }
277  
-  
278  
-#if defined(TARGET_DARWIN_OSX)
279  
-  if (m_Initialized)
280  
-  {
281  
-    m_currentAudioDevice = CCoreAudioHardware::FindAudioDevice(m_outputDevice);
282  
-  }
283  
-#endif
284 331
 
285 332
   return m_Initialized;
286 333
 }
@@ -438,7 +485,6 @@ CCoreAudioAEHAL* CCoreAudioAE::GetHAL()
438 485
 IAEStream* CCoreAudioAE::MakeStream(enum AEDataFormat dataFormat,
439 486
   unsigned int sampleRate, unsigned int encodedSamplerate, CAEChannelInfo channelLayout, unsigned int options)
440 487
 {
441  
-  bool defaultDeviceChanged = false;
442 488
   // if we are suspended we don't
443 489
   // want anyone to mess with us
444 490
   if (m_isSuspended && !m_softSuspend)
@@ -453,20 +499,6 @@ IAEStream* CCoreAudioAE::MakeStream(enum AEDataFormat dataFormat,
453 499
   m_streams.push_back(stream);
454 500
   streamLock.Leave();
455 501
 
456  
-#if defined(TARGET_DARWIN_OSX)
457  
-  // check if default device has changed - in that case we need to reinit
458  
-  // TODO hook into osx callbacks for getting notifiaction on device
459  
-  // changes and then queue a change of the default device
460  
-  // to a point where engine is idle.
461  
-  std::string outputDevice = g_guiSettings.GetString("audiooutput.audiodevice");
462  
-  if (outputDevice.compare("CoreAudio:default") == 0)
463  
-  {
464  
-    AudioDeviceID currentId = CCoreAudioHardware::FindAudioDevice("default");
465  
-    if (currentId != m_currentAudioDevice)
466  
-      defaultDeviceChanged = true;
467  
-  }
468  
-#endif
469  
-
470 502
   if ((options & AESTREAM_PAUSED) == 0)
471 503
     Stop();
472 504
 
@@ -474,8 +506,7 @@ IAEStream* CCoreAudioAE::MakeStream(enum AEDataFormat dataFormat,
474 506
   if (m_Initialized && ( m_lastStreamFormat != dataFormat ||
475 507
                          m_lastChLayoutCount != channelLayout.Count() ||
476 508
                          m_lastSampleRate != sampleRate ||
477  
-                         COREAUDIO_IS_RAW(dataFormat) ||
478  
-                         defaultDeviceChanged))
  509
+                         COREAUDIO_IS_RAW(dataFormat)))
479 510
   {
480 511
     CSingleLock engineLock(m_engineLock);
481 512
     Stop();
4  xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.h
@@ -33,7 +33,6 @@
33 33
 
34 34
 #if defined(TARGET_DARWIN_IOS)
35 35
 #include "CoreAudioAEHALIOS.h"
36  
-#define AudioDeviceID unsigned
37 36
 #else
38 37
 #include "CoreAudioAEHALOSX.h"
39 38
 #endif
@@ -121,6 +120,8 @@ class CCoreAudioAE : public IAE, public ICoreAudioSource
121 120
   virtual OSStatus  Render(AudioUnitRenderActionFlags* actionFlags,
122 121
     const AudioTimeStamp* pTimeStamp, UInt32 busNumber,
123 122
     UInt32 frameCount, AudioBufferList* pBufList);
  123
+    
  124
+  void AudioDevicesChanged();
124 125
 
125 126
 
126 127
 private:
@@ -175,5 +176,4 @@ class CCoreAudioAE : public IAE, public ICoreAudioSource
175 176
   bool              m_isSuspended;
176 177
   bool              m_softSuspend;
177 178
   unsigned int      m_softSuspendTimer;
178  
-  AudioDeviceID     m_currentAudioDevice;
179 179
 };

0 notes on commit 7484699

Please sign in to comment.
Something went wrong with that request. Please try again.