aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Marshall <jmarshall@xbmc.org>2013-12-30 12:44:48 +1300
committerJonathan Marshall <jmarshall@xbmc.org>2014-02-22 09:04:47 +1300
commitc13a3d4af22d5a2443fadaeeb4cd70cf2d8154e2 (patch)
treeea32a98ce6f618518b43dcf0a7c349e01c97c5c8
parente585af6237e4f010b564daf04e1560e118fb0dc2 (diff)
[ios/osx] adds Darwin sinks for ActiveAE and drop the CoreAudio engine.
-rw-r--r--XBMC.xcodeproj/project.pbxproj162
-rw-r--r--xbmc/cores/AudioEngine/AEFactory.cpp19
-rw-r--r--xbmc/cores/AudioEngine/AESinkFactory.cpp28
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp929
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.h181
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.cpp1342
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.h201
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp483
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.h75
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.cpp124
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.h56
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp921
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.h189
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.cpp581
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.h76
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioMixMap.cpp277
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioMixMap.h58
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.cpp816
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.h121
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioAEHAL.h49
-rw-r--r--xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioSource.h50
-rw-r--r--xbmc/cores/AudioEngine/Makefile.in25
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.cpp780
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.h68
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp636
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.h66
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioChannelLayout.cpp (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioChannelLayout.cpp)0
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioChannelLayout.h (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioChannelLayout.h)0
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.cpp)60
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.h)13
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHardware.cpp (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.cpp)2
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHardware.h (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.h)2
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHelpers.cpp (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHAL.cpp)4
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHelpers.h (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHAL.h)1
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.cpp)38
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h (renamed from xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.h)14
-rw-r--r--xbmc/osx/IOSScreenManager.mm5
-rw-r--r--xbmc/settings/Settings.cpp10
38 files changed, 1697 insertions, 6765 deletions
diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj
index 7c15e43fd9..c3e8eb2c0d 100644
--- a/XBMC.xcodeproj/project.pbxproj
+++ b/XBMC.xcodeproj/project.pbxproj
@@ -328,6 +328,11 @@
7C89619213B6A16F003631FE /* GUIWindowScreensaverDim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89619013B6A16F003631FE /* GUIWindowScreensaverDim.cpp */; };
7C8A14571154CB2600E5FCFA /* TextureCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8A14541154CB2600E5FCFA /* TextureCache.cpp */; };
7C8A187D115B2A8200E5FCFA /* TextureDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8A187A115B2A8200E5FCFA /* TextureDatabase.cpp */; };
+ 7C8AE84E189DE3CD00C33786 /* CoreAudioChannelLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8AE849189DE3CD00C33786 /* CoreAudioChannelLayout.cpp */; };
+ 7C8AE84F189DE3CD00C33786 /* CoreAudioDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8AE84A189DE3CD00C33786 /* CoreAudioDevice.cpp */; };
+ 7C8AE850189DE3CD00C33786 /* CoreAudioHardware.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8AE84B189DE3CD00C33786 /* CoreAudioHardware.cpp */; };
+ 7C8AE851189DE3CD00C33786 /* CoreAudioStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8AE84C189DE3CD00C33786 /* CoreAudioStream.cpp */; };
+ 7C8AE854189DE47F00C33786 /* CoreAudioHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8AE852189DE47400C33786 /* CoreAudioHelpers.cpp */; };
7C8FC6EE1829A4580045153D /* DirectoryProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */; };
7C8FC6EF1829A4580045153D /* DirectoryProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */; };
7C8FC6F01829A4580045153D /* DirectoryProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */; };
@@ -457,6 +462,8 @@
DF3488E713FD958F0026A711 /* GUIAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF3488E513FD958F0026A711 /* GUIAction.cpp */; };
DF34892A13FD9C780026A711 /* AirPlayServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF34892813FD9C780026A711 /* AirPlayServer.cpp */; };
DF34898213FDAAF60026A711 /* HttpParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF34898113FDAAF60026A711 /* HttpParser.cpp */; };
+ DF374B2418AC2BA20076B514 /* CoreAudioHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8AE852189DE47400C33786 /* CoreAudioHelpers.cpp */; };
+ DF374B2518AC2BA20076B514 /* CoreAudioHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C8AE852189DE47400C33786 /* CoreAudioHelpers.cpp */; };
DF3C3C0E1752A7EE000989C3 /* IOSEAGLView.mm in Sources */ = {isa = PBXBuildFile; fileRef = E49910D7174E4A6400741B6D /* IOSEAGLView.mm */; };
DF3C3C0F1752A7EE000989C3 /* IOSExternalTouchController.mm in Sources */ = {isa = PBXBuildFile; fileRef = E49910D9174E4A6400741B6D /* IOSExternalTouchController.mm */; };
DF3C3C101752A7EE000989C3 /* IOSScreenManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = E49910DB174E4A6400741B6D /* IOSScreenManager.mm */; };
@@ -567,12 +574,6 @@
DFB25D48163D4743006C4A48 /* WindowXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF1AD1EC15FCE77900E10810 /* WindowXML.cpp */; };
DFB65FB515373AE7006B8FF1 /* AEFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6515373AE7006B8FF1 /* AEFactory.cpp */; };
DFB65FB715373AE7006B8FF1 /* AEEncoderFFmpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6A15373AE7006B8FF1 /* AEEncoderFFmpeg.cpp */; };
- DFB65FB815373AE7006B8FF1 /* CoreAudioAE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6D15373AE7006B8FF1 /* CoreAudioAE.cpp */; };
- DFB65FB915373AE7006B8FF1 /* CoreAudioAEHAL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6F15373AE7006B8FF1 /* CoreAudioAEHAL.cpp */; };
- DFB65FBA15373AE7006B8FF1 /* CoreAudioAEHALIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7115373AE7006B8FF1 /* CoreAudioAEHALIOS.cpp */; };
- DFB65FBB15373AE7006B8FF1 /* CoreAudioAEHALOSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7315373AE7006B8FF1 /* CoreAudioAEHALOSX.cpp */; };
- DFB65FBC15373AE7006B8FF1 /* CoreAudioAESound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7515373AE7006B8FF1 /* CoreAudioAESound.cpp */; };
- DFB65FBD15373AE7006B8FF1 /* CoreAudioAEStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7715373AE7006B8FF1 /* CoreAudioAEStream.cpp */; };
DFB65FCC15373AE7006B8FF1 /* AEBitstreamPacker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65FA315373AE7006B8FF1 /* AEBitstreamPacker.cpp */; };
DFB65FCD15373AE7006B8FF1 /* AEBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65FA515373AE7006B8FF1 /* AEBuffer.cpp */; };
DFB65FCE15373AE7006B8FF1 /* AEChannelInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65FA715373AE7006B8FF1 /* AEChannelInfo.cpp */; };
@@ -796,11 +797,6 @@
DFF0F13617528350002DA3A4 /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DE0443315828F4B005DDB4D /* Exception.cpp */; };
DFF0F13717528350002DA3A4 /* ilog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC720A8D155091BB00FFD782 /* ilog.cpp */; };
DFF0F13817528350002DA3A4 /* AEEncoderFFmpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6A15373AE7006B8FF1 /* AEEncoderFFmpeg.cpp */; };
- DFF0F13917528350002DA3A4 /* CoreAudioAE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6D15373AE7006B8FF1 /* CoreAudioAE.cpp */; };
- DFF0F13A17528350002DA3A4 /* CoreAudioAEHAL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6F15373AE7006B8FF1 /* CoreAudioAEHAL.cpp */; };
- DFF0F13B17528350002DA3A4 /* CoreAudioAEHALIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7115373AE7006B8FF1 /* CoreAudioAEHALIOS.cpp */; };
- DFF0F13C17528350002DA3A4 /* CoreAudioAESound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7515373AE7006B8FF1 /* CoreAudioAESound.cpp */; };
- DFF0F13D17528350002DA3A4 /* CoreAudioAEStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7715373AE7006B8FF1 /* CoreAudioAEStream.cpp */; };
DFF0F13E17528350002DA3A4 /* AEBitstreamPacker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65FA315373AE7006B8FF1 /* AEBitstreamPacker.cpp */; };
DFF0F13F17528350002DA3A4 /* AEBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65FA515373AE7006B8FF1 /* AEBuffer.cpp */; };
DFF0F14017528350002DA3A4 /* AEChannelInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65FA715373AE7006B8FF1 /* AEChannelInfo.cpp */; };
@@ -2210,11 +2206,6 @@
E4991196174E5CEB00741B6D /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DE0443315828F4B005DDB4D /* Exception.cpp */; };
E4991197174E5CEB00741B6D /* ilog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC720A8D155091BB00FFD782 /* ilog.cpp */; };
E4991198174E5CF600741B6D /* AEEncoderFFmpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6A15373AE7006B8FF1 /* AEEncoderFFmpeg.cpp */; };
- E4991199174E5CFA00741B6D /* CoreAudioAE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6D15373AE7006B8FF1 /* CoreAudioAE.cpp */; };
- E499119A174E5CFA00741B6D /* CoreAudioAEHAL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F6F15373AE7006B8FF1 /* CoreAudioAEHAL.cpp */; };
- E499119B174E5CFA00741B6D /* CoreAudioAEHALIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7115373AE7006B8FF1 /* CoreAudioAEHALIOS.cpp */; };
- E499119D174E5CFA00741B6D /* CoreAudioAESound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7515373AE7006B8FF1 /* CoreAudioAESound.cpp */; };
- E499119E174E5CFA00741B6D /* CoreAudioAEStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65F7715373AE7006B8FF1 /* CoreAudioAEStream.cpp */; };
E49911A6174E5CFE00741B6D /* AEBitstreamPacker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65FA315373AE7006B8FF1 /* AEBitstreamPacker.cpp */; };
E49911A7174E5CFE00741B6D /* AEBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65FA515373AE7006B8FF1 /* AEBuffer.cpp */; };
E49911A8174E5CFE00741B6D /* AEChannelInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB65FA715373AE7006B8FF1 /* AEChannelInfo.cpp */; };
@@ -3156,6 +3147,9 @@
F5BDB80C120202F400F0B710 /* DVDSubtitleTagSami.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5BDB80B120202F400F0B710 /* DVDSubtitleTagSami.cpp */; };
F5BDB81A1202032400F0B710 /* DVDSubtitleTagMicroDVD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5BDB8191202032400F0B710 /* DVDSubtitleTagMicroDVD.cpp */; };
F5BDB820120203C200F0B710 /* AutoPtrHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5BDB81F120203C200F0B710 /* AutoPtrHandle.cpp */; };
+ F5CC228B1814F7E9006B5E91 /* AESinkDARWINOSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5CC22891814F7E9006B5E91 /* AESinkDARWINOSX.cpp */; };
+ F5CC228E1814F7F7006B5E91 /* AESinkDARWINIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5CC228C1814F7F7006B5E91 /* AESinkDARWINIOS.cpp */; };
+ F5CC228F1814F7F7006B5E91 /* AESinkDARWINIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5CC228C1814F7F7006B5E91 /* AESinkDARWINIOS.cpp */; };
F5CC22DF1814FF3B006B5E91 /* ActiveAE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5CC22D31814FF3B006B5E91 /* ActiveAE.cpp */; };
F5CC22E01814FF3B006B5E91 /* ActiveAEBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5CC22D51814FF3B006B5E91 /* ActiveAEBuffer.cpp */; };
F5CC22E11814FF3B006B5E91 /* ActiveAEResample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5CC22D71814FF3B006B5E91 /* ActiveAEResample.cpp */; };
@@ -3221,13 +3215,6 @@
F5ED8D6C1551F91400842059 /* BlurayDirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED8D6A1551F91400842059 /* BlurayDirectory.cpp */; };
F5ED908815538DCE00842059 /* XBMCTinyXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED908615538DCE00842059 /* XBMCTinyXML.cpp */; };
F5ED908E15538E2300842059 /* POUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED908C15538E2300842059 /* POUtils.cpp */; };
- F5ED942E155D729500842059 /* CoreAudioDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED942A155D729500842059 /* CoreAudioDevice.cpp */; };
- F5ED942F155D729500842059 /* CoreAudioHardware.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED942C155D729500842059 /* CoreAudioHardware.cpp */; };
- F5ED943E155D743700842059 /* CoreAudioStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED943C155D743700842059 /* CoreAudioStream.cpp */; };
- F5ED9462155D777B00842059 /* CoreAudioChannelLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED9460155D777B00842059 /* CoreAudioChannelLayout.cpp */; };
- F5ED9496155D7B9900842059 /* CoreAudioMixMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED9494155D7B9900842059 /* CoreAudioMixMap.cpp */; };
- F5ED94AB155D7F8000842059 /* CoreAudioUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED94A9155D7F8000842059 /* CoreAudioUnit.cpp */; };
- F5ED9509155D855200842059 /* CoreAudioGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5ED9507155D855200842059 /* CoreAudioGraph.cpp */; };
F5ED9A0C155EBDC000842059 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E38E238E0D2626E600618676 /* CoreAudio.framework */; };
F5ED9A15155EBE0000842059 /* DiskArbitration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88ECB6580DE013C4003396A7 /* DiskArbitration.framework */; };
F5ED9BFB155EC77400842059 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E38E25340D26365C00618676 /* ApplicationServices.framework */; };
@@ -3850,6 +3837,16 @@
7C8A14551154CB2600E5FCFA /* TextureCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureCache.h; sourceTree = "<group>"; };
7C8A187A115B2A8200E5FCFA /* TextureDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureDatabase.cpp; sourceTree = "<group>"; };
7C8A187B115B2A8200E5FCFA /* TextureDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureDatabase.h; sourceTree = "<group>"; };
+ 7C8AE844189DE3CD00C33786 /* CoreAudioChannelLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioChannelLayout.h; path = Sinks/osx/CoreAudioChannelLayout.h; sourceTree = "<group>"; };
+ 7C8AE845189DE3CD00C33786 /* CoreAudioDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioDevice.h; path = Sinks/osx/CoreAudioDevice.h; sourceTree = "<group>"; };
+ 7C8AE846189DE3CD00C33786 /* CoreAudioHardware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioHardware.h; path = Sinks/osx/CoreAudioHardware.h; sourceTree = "<group>"; };
+ 7C8AE847189DE3CD00C33786 /* CoreAudioStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioStream.h; path = Sinks/osx/CoreAudioStream.h; sourceTree = "<group>"; };
+ 7C8AE849189DE3CD00C33786 /* CoreAudioChannelLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioChannelLayout.cpp; path = Sinks/osx/CoreAudioChannelLayout.cpp; sourceTree = "<group>"; };
+ 7C8AE84A189DE3CD00C33786 /* CoreAudioDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioDevice.cpp; path = Sinks/osx/CoreAudioDevice.cpp; sourceTree = "<group>"; };
+ 7C8AE84B189DE3CD00C33786 /* CoreAudioHardware.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioHardware.cpp; path = Sinks/osx/CoreAudioHardware.cpp; sourceTree = "<group>"; };
+ 7C8AE84C189DE3CD00C33786 /* CoreAudioStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioStream.cpp; path = Sinks/osx/CoreAudioStream.cpp; sourceTree = "<group>"; };
+ 7C8AE852189DE47400C33786 /* CoreAudioHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioHelpers.cpp; path = Sinks/osx/CoreAudioHelpers.cpp; sourceTree = "<group>"; };
+ 7C8AE853189DE47700C33786 /* CoreAudioHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioHelpers.h; path = Sinks/osx/CoreAudioHelpers.h; sourceTree = "<group>"; };
7C8FC6EC1829A4580045153D /* DirectoryProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DirectoryProvider.cpp; path = xbmc/listproviders/DirectoryProvider.cpp; sourceTree = SOURCE_ROOT; };
7C8FC6ED1829A4580045153D /* DirectoryProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DirectoryProvider.h; path = xbmc/listproviders/DirectoryProvider.h; sourceTree = SOURCE_ROOT; };
7C920CF7181669FF00DA1477 /* TextureOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureOperations.cpp; sourceTree = "<group>"; };
@@ -4302,20 +4299,6 @@
DFB65F6615373AE7006B8FF1 /* AEFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEFactory.h; sourceTree = "<group>"; };
DFB65F6A15373AE7006B8FF1 /* AEEncoderFFmpeg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AEEncoderFFmpeg.cpp; sourceTree = "<group>"; };
DFB65F6B15373AE7006B8FF1 /* AEEncoderFFmpeg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEEncoderFFmpeg.h; sourceTree = "<group>"; };
- DFB65F6D15373AE7006B8FF1 /* CoreAudioAE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioAE.cpp; path = CoreAudio/CoreAudioAE.cpp; sourceTree = "<group>"; };
- DFB65F6E15373AE7006B8FF1 /* CoreAudioAE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioAE.h; path = CoreAudio/CoreAudioAE.h; sourceTree = "<group>"; };
- DFB65F6F15373AE7006B8FF1 /* CoreAudioAEHAL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioAEHAL.cpp; path = CoreAudio/CoreAudioAEHAL.cpp; sourceTree = "<group>"; };
- DFB65F7015373AE7006B8FF1 /* CoreAudioAEHAL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioAEHAL.h; path = CoreAudio/CoreAudioAEHAL.h; sourceTree = "<group>"; };
- DFB65F7115373AE7006B8FF1 /* CoreAudioAEHALIOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioAEHALIOS.cpp; path = CoreAudio/CoreAudioAEHALIOS.cpp; sourceTree = "<group>"; };
- DFB65F7215373AE7006B8FF1 /* CoreAudioAEHALIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioAEHALIOS.h; path = CoreAudio/CoreAudioAEHALIOS.h; sourceTree = "<group>"; };
- DFB65F7315373AE7006B8FF1 /* CoreAudioAEHALOSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioAEHALOSX.cpp; path = CoreAudio/CoreAudioAEHALOSX.cpp; sourceTree = "<group>"; };
- DFB65F7415373AE7006B8FF1 /* CoreAudioAEHALOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioAEHALOSX.h; path = CoreAudio/CoreAudioAEHALOSX.h; sourceTree = "<group>"; };
- DFB65F7515373AE7006B8FF1 /* CoreAudioAESound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioAESound.cpp; path = CoreAudio/CoreAudioAESound.cpp; sourceTree = "<group>"; };
- DFB65F7615373AE7006B8FF1 /* CoreAudioAESound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioAESound.h; path = CoreAudio/CoreAudioAESound.h; sourceTree = "<group>"; };
- DFB65F7715373AE7006B8FF1 /* CoreAudioAEStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioAEStream.cpp; path = CoreAudio/CoreAudioAEStream.cpp; sourceTree = "<group>"; };
- DFB65F7815373AE7006B8FF1 /* CoreAudioAEStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioAEStream.h; path = CoreAudio/CoreAudioAEStream.h; sourceTree = "<group>"; };
- DFB65F7A15373AE7006B8FF1 /* ICoreAudioAEHAL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ICoreAudioAEHAL.h; path = CoreAudio/ICoreAudioAEHAL.h; sourceTree = "<group>"; };
- DFB65F7B15373AE7006B8FF1 /* ICoreAudioSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ICoreAudioSource.h; path = CoreAudio/ICoreAudioSource.h; sourceTree = "<group>"; };
DFB65F8915373AE7006B8FF1 /* AE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AE.h; sourceTree = "<group>"; };
DFB65F8A15373AE7006B8FF1 /* AEEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AEEncoder.h; sourceTree = "<group>"; };
DFB65F8C15373AE7006B8FF1 /* AESink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESink.h; sourceTree = "<group>"; };
@@ -5562,6 +5545,10 @@
F5BDB8191202032400F0B710 /* DVDSubtitleTagMicroDVD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDSubtitleTagMicroDVD.cpp; sourceTree = "<group>"; };
F5BDB81E120203C200F0B710 /* AutoPtrHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoPtrHandle.h; sourceTree = "<group>"; };
F5BDB81F120203C200F0B710 /* AutoPtrHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AutoPtrHandle.cpp; sourceTree = "<group>"; };
+ F5CC22891814F7E9006B5E91 /* AESinkDARWINOSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AESinkDARWINOSX.cpp; path = Sinks/AESinkDARWINOSX.cpp; sourceTree = "<group>"; };
+ F5CC228A1814F7E9006B5E91 /* AESinkDARWINOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AESinkDARWINOSX.h; path = Sinks/AESinkDARWINOSX.h; sourceTree = "<group>"; };
+ F5CC228C1814F7F7006B5E91 /* AESinkDARWINIOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AESinkDARWINIOS.cpp; path = Sinks/AESinkDARWINIOS.cpp; sourceTree = "<group>"; };
+ F5CC228D1814F7F7006B5E91 /* AESinkDARWINIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AESinkDARWINIOS.h; path = Sinks/AESinkDARWINIOS.h; sourceTree = "<group>"; };
F5CC22D31814FF3B006B5E91 /* ActiveAE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActiveAE.cpp; sourceTree = "<group>"; };
F5CC22D41814FF3B006B5E91 /* ActiveAE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActiveAE.h; sourceTree = "<group>"; };
F5CC22D51814FF3B006B5E91 /* ActiveAEBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActiveAEBuffer.cpp; sourceTree = "<group>"; };
@@ -5648,20 +5635,6 @@
F5ED908715538DCE00842059 /* XBMCTinyXML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XBMCTinyXML.h; sourceTree = "<group>"; };
F5ED908C15538E2300842059 /* POUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = POUtils.cpp; sourceTree = "<group>"; };
F5ED908D15538E2300842059 /* POUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POUtils.h; sourceTree = "<group>"; };
- F5ED942A155D729500842059 /* CoreAudioDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioDevice.cpp; path = CoreAudio/CoreAudioDevice.cpp; sourceTree = "<group>"; };
- F5ED942B155D729500842059 /* CoreAudioDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioDevice.h; path = CoreAudio/CoreAudioDevice.h; sourceTree = "<group>"; };
- F5ED942C155D729500842059 /* CoreAudioHardware.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioHardware.cpp; path = CoreAudio/CoreAudioHardware.cpp; sourceTree = "<group>"; };
- F5ED942D155D729500842059 /* CoreAudioHardware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioHardware.h; path = CoreAudio/CoreAudioHardware.h; sourceTree = "<group>"; };
- F5ED943C155D743700842059 /* CoreAudioStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioStream.cpp; path = CoreAudio/CoreAudioStream.cpp; sourceTree = "<group>"; };
- F5ED943D155D743700842059 /* CoreAudioStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioStream.h; path = CoreAudio/CoreAudioStream.h; sourceTree = "<group>"; };
- F5ED9460155D777B00842059 /* CoreAudioChannelLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioChannelLayout.cpp; path = CoreAudio/CoreAudioChannelLayout.cpp; sourceTree = "<group>"; };
- F5ED9461155D777B00842059 /* CoreAudioChannelLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioChannelLayout.h; path = CoreAudio/CoreAudioChannelLayout.h; sourceTree = "<group>"; };
- F5ED9494155D7B9900842059 /* CoreAudioMixMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioMixMap.cpp; path = CoreAudio/CoreAudioMixMap.cpp; sourceTree = "<group>"; };
- F5ED9495155D7B9900842059 /* CoreAudioMixMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioMixMap.h; path = CoreAudio/CoreAudioMixMap.h; sourceTree = "<group>"; };
- F5ED94A9155D7F8000842059 /* CoreAudioUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioUnit.cpp; path = CoreAudio/CoreAudioUnit.cpp; sourceTree = "<group>"; };
- F5ED94AA155D7F8000842059 /* CoreAudioUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioUnit.h; path = CoreAudio/CoreAudioUnit.h; sourceTree = "<group>"; };
- F5ED9507155D855200842059 /* CoreAudioGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CoreAudioGraph.cpp; path = CoreAudio/CoreAudioGraph.cpp; sourceTree = "<group>"; };
- F5ED9508155D855200842059 /* CoreAudioGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreAudioGraph.h; path = CoreAudio/CoreAudioGraph.h; sourceTree = "<group>"; };
F5EDC48A1651A6F900B852D8 /* GroupUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GroupUtils.cpp; sourceTree = "<group>"; };
F5EDC48B1651A6F900B852D8 /* GroupUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupUtils.h; sourceTree = "<group>"; };
F5F240EB110A4F76009126C6 /* CrystalHD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CrystalHD.cpp; sourceTree = "<group>"; };
@@ -6816,6 +6789,23 @@
path = info;
sourceTree = "<group>";
};
+ 7C8AE7FE189DE3A700C33786 /* osx */ = {
+ isa = PBXGroup;
+ children = (
+ 7C8AE849189DE3CD00C33786 /* CoreAudioChannelLayout.cpp */,
+ 7C8AE844189DE3CD00C33786 /* CoreAudioChannelLayout.h */,
+ 7C8AE84A189DE3CD00C33786 /* CoreAudioDevice.cpp */,
+ 7C8AE845189DE3CD00C33786 /* CoreAudioDevice.h */,
+ 7C8AE84B189DE3CD00C33786 /* CoreAudioHardware.cpp */,
+ 7C8AE846189DE3CD00C33786 /* CoreAudioHardware.h */,
+ 7C8AE852189DE47400C33786 /* CoreAudioHelpers.cpp */,
+ 7C8AE853189DE47700C33786 /* CoreAudioHelpers.h */,
+ 7C8AE84C189DE3CD00C33786 /* CoreAudioStream.cpp */,
+ 7C8AE847189DE3CD00C33786 /* CoreAudioStream.h */,
+ );
+ name = osx;
+ sourceTree = "<group>";
+ };
810C9F5F0D67BCC80095F5DD /* MediaConnect */ = {
isa = PBXGroup;
children = (
@@ -7214,7 +7204,6 @@
DFB65F6C15373AE7006B8FF1 /* Engines */ = {
isa = PBXGroup;
children = (
- F5ED9362155CECC800842059 /* CoreAudio */,
F5CC22D21814FF3B006B5E91 /* ActiveAE */,
);
path = Engines;
@@ -9214,6 +9203,7 @@
F5CC22851814F7B5006B5E91 /* Sinks */ = {
isa = PBXGroup;
children = (
+ 7C8AE7FE189DE3A700C33786 /* osx */,
F5CC228C1814F7F7006B5E91 /* AESinkDARWINIOS.cpp */,
F5CC228D1814F7F7006B5E91 /* AESinkDARWINIOS.h */,
F5CC22891814F7E9006B5E91 /* AESinkDARWINOSX.cpp */,
@@ -9432,41 +9422,6 @@
name = playercorefactory;
sourceTree = "<group>";
};
- F5ED9362155CECC800842059 /* CoreAudio */ = {
- isa = PBXGroup;
- children = (
- DFB65F6D15373AE7006B8FF1 /* CoreAudioAE.cpp */,
- DFB65F6E15373AE7006B8FF1 /* CoreAudioAE.h */,
- DFB65F6F15373AE7006B8FF1 /* CoreAudioAEHAL.cpp */,
- DFB65F7015373AE7006B8FF1 /* CoreAudioAEHAL.h */,
- DFB65F7115373AE7006B8FF1 /* CoreAudioAEHALIOS.cpp */,
- DFB65F7215373AE7006B8FF1 /* CoreAudioAEHALIOS.h */,
- DFB65F7315373AE7006B8FF1 /* CoreAudioAEHALOSX.cpp */,
- DFB65F7415373AE7006B8FF1 /* CoreAudioAEHALOSX.h */,
- DFB65F7515373AE7006B8FF1 /* CoreAudioAESound.cpp */,
- DFB65F7615373AE7006B8FF1 /* CoreAudioAESound.h */,
- DFB65F7715373AE7006B8FF1 /* CoreAudioAEStream.cpp */,
- DFB65F7815373AE7006B8FF1 /* CoreAudioAEStream.h */,
- F5ED9460155D777B00842059 /* CoreAudioChannelLayout.cpp */,
- F5ED9461155D777B00842059 /* CoreAudioChannelLayout.h */,
- F5ED942A155D729500842059 /* CoreAudioDevice.cpp */,
- F5ED942B155D729500842059 /* CoreAudioDevice.h */,
- F5ED9507155D855200842059 /* CoreAudioGraph.cpp */,
- F5ED9508155D855200842059 /* CoreAudioGraph.h */,
- F5ED942C155D729500842059 /* CoreAudioHardware.cpp */,
- F5ED942D155D729500842059 /* CoreAudioHardware.h */,
- F5ED9494155D7B9900842059 /* CoreAudioMixMap.cpp */,
- F5ED9495155D7B9900842059 /* CoreAudioMixMap.h */,
- F5ED943C155D743700842059 /* CoreAudioStream.cpp */,
- F5ED943D155D743700842059 /* CoreAudioStream.h */,
- F5ED94A9155D7F8000842059 /* CoreAudioUnit.cpp */,
- F5ED94AA155D7F8000842059 /* CoreAudioUnit.h */,
- DFB65F7A15373AE7006B8FF1 /* ICoreAudioAEHAL.h */,
- DFB65F7B15373AE7006B8FF1 /* ICoreAudioSource.h */,
- );
- name = CoreAudio;
- sourceTree = "<group>";
- };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -10611,12 +10566,6 @@
F5ED908E15538E2300842059 /* POUtils.cpp in Sources */,
DFB65FB515373AE7006B8FF1 /* AEFactory.cpp in Sources */,
DFB65FB715373AE7006B8FF1 /* AEEncoderFFmpeg.cpp in Sources */,
- DFB65FB815373AE7006B8FF1 /* CoreAudioAE.cpp in Sources */,
- DFB65FB915373AE7006B8FF1 /* CoreAudioAEHAL.cpp in Sources */,
- DFB65FBA15373AE7006B8FF1 /* CoreAudioAEHALIOS.cpp in Sources */,
- DFB65FBB15373AE7006B8FF1 /* CoreAudioAEHALOSX.cpp in Sources */,
- DFB65FBC15373AE7006B8FF1 /* CoreAudioAESound.cpp in Sources */,
- DFB65FBD15373AE7006B8FF1 /* CoreAudioAEStream.cpp in Sources */,
DFB65FCC15373AE7006B8FF1 /* AEBitstreamPacker.cpp in Sources */,
DFB65FCD15373AE7006B8FF1 /* AEBuffer.cpp in Sources */,
DFB65FCE15373AE7006B8FF1 /* AEChannelInfo.cpp in Sources */,
@@ -10628,13 +10577,6 @@
DFB65FD415373AE7006B8FF1 /* AEWAVLoader.cpp in Sources */,
DFB6610915374E80006B8FF1 /* DVDAudioCodecPassthrough.cpp in Sources */,
7C0B98A4154B79C30065A238 /* AEDeviceInfo.cpp in Sources */,
- F5ED942E155D729500842059 /* CoreAudioDevice.cpp in Sources */,
- F5ED942F155D729500842059 /* CoreAudioHardware.cpp in Sources */,
- F5ED943E155D743700842059 /* CoreAudioStream.cpp in Sources */,
- F5ED9462155D777B00842059 /* CoreAudioChannelLayout.cpp in Sources */,
- F5ED9496155D7B9900842059 /* CoreAudioMixMap.cpp in Sources */,
- F5ED94AB155D7F8000842059 /* CoreAudioUnit.cpp in Sources */,
- F5ED9509155D855200842059 /* CoreAudioGraph.cpp in Sources */,
7C6EB330155BD1D40080368A /* ImageFile.cpp in Sources */,
7C6EB6FA155F32C30080368A /* HTTPImageHandler.cpp in Sources */,
C84828C0156CFCD8005A996F /* PVRClient.cpp in Sources */,
@@ -10850,6 +10792,7 @@
7C1409A9184015C9009F9411 /* InfoExpression.cpp in Sources */,
AE32174218313ADF0003FAFC /* XSLTUtils.cpp in Sources */,
7C15DCBC1892481400FCE564 /* InfoBool.cpp in Sources */,
+ F5CC228B1814F7E9006B5E91 /* AESinkDARWINOSX.cpp in Sources */,
F5CC22EB1814FF3B006B5E91 /* ActiveAE.cpp in Sources */,
F5CC22EC1814FF3B006B5E91 /* ActiveAEBuffer.cpp in Sources */,
F5CC22ED1814FF3B006B5E91 /* ActiveAEResample.cpp in Sources */,
@@ -10861,6 +10804,11 @@
F5CC230E18150118006B5E91 /* AESinkFactory.cpp in Sources */,
F5CC234918150277006B5E91 /* AESinkNULL.cpp in Sources */,
F5CC238A18150768006B5E91 /* AESinkProfiler.cpp in Sources */,
+ 7C8AE84E189DE3CD00C33786 /* CoreAudioChannelLayout.cpp in Sources */,
+ 7C8AE84F189DE3CD00C33786 /* CoreAudioDevice.cpp in Sources */,
+ 7C8AE850189DE3CD00C33786 /* CoreAudioHardware.cpp in Sources */,
+ 7C8AE851189DE3CD00C33786 /* CoreAudioStream.cpp in Sources */,
+ 7C8AE854189DE47F00C33786 /* CoreAudioHelpers.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -11027,11 +10975,6 @@
DFF0F13617528350002DA3A4 /* Exception.cpp in Sources */,
DFF0F13717528350002DA3A4 /* ilog.cpp in Sources */,
DFF0F13817528350002DA3A4 /* AEEncoderFFmpeg.cpp in Sources */,
- DFF0F13917528350002DA3A4 /* CoreAudioAE.cpp in Sources */,
- DFF0F13A17528350002DA3A4 /* CoreAudioAEHAL.cpp in Sources */,
- DFF0F13B17528350002DA3A4 /* CoreAudioAEHALIOS.cpp in Sources */,
- DFF0F13C17528350002DA3A4 /* CoreAudioAESound.cpp in Sources */,
- DFF0F13D17528350002DA3A4 /* CoreAudioAEStream.cpp in Sources */,
DFF0F13E17528350002DA3A4 /* AEBitstreamPacker.cpp in Sources */,
DFF0F13F17528350002DA3A4 /* AEBuffer.cpp in Sources */,
DFF0F14017528350002DA3A4 /* AEChannelInfo.cpp in Sources */,
@@ -11905,6 +11848,7 @@
7C1409AB184015C9009F9411 /* InfoExpression.cpp in Sources */,
AE32174318313AE10003FAFC /* XSLTUtils.cpp in Sources */,
7C15DCBE1892481400FCE564 /* InfoBool.cpp in Sources */,
+ F5CC228F1814F7F7006B5E91 /* AESinkDARWINIOS.cpp in Sources */,
F5CC22E51814FF3B006B5E91 /* ActiveAE.cpp in Sources */,
F5CC22E61814FF3B006B5E91 /* ActiveAEBuffer.cpp in Sources */,
F5CC22E71814FF3B006B5E91 /* ActiveAEResample.cpp in Sources */,
@@ -11916,6 +11860,7 @@
F5CC230D18150118006B5E91 /* AESinkFactory.cpp in Sources */,
F5CC234818150277006B5E91 /* AESinkNULL.cpp in Sources */,
F5CC238918150768006B5E91 /* AESinkProfiler.cpp in Sources */,
+ DF374B2518AC2BA20076B514 /* CoreAudioHelpers.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -12089,11 +12034,6 @@
E4991196174E5CEB00741B6D /* Exception.cpp in Sources */,
E4991197174E5CEB00741B6D /* ilog.cpp in Sources */,
E4991198174E5CF600741B6D /* AEEncoderFFmpeg.cpp in Sources */,
- E4991199174E5CFA00741B6D /* CoreAudioAE.cpp in Sources */,
- E499119A174E5CFA00741B6D /* CoreAudioAEHAL.cpp in Sources */,
- E499119B174E5CFA00741B6D /* CoreAudioAEHALIOS.cpp in Sources */,
- E499119D174E5CFA00741B6D /* CoreAudioAESound.cpp in Sources */,
- E499119E174E5CFA00741B6D /* CoreAudioAEStream.cpp in Sources */,
E49911A6174E5CFE00741B6D /* AEBitstreamPacker.cpp in Sources */,
E49911A7174E5CFE00741B6D /* AEBuffer.cpp in Sources */,
E49911A8174E5CFE00741B6D /* AEChannelInfo.cpp in Sources */,
@@ -12962,6 +12902,7 @@
7C1409AA184015C9009F9411 /* InfoExpression.cpp in Sources */,
AE4E87A717354C4A00D15206 /* XSLTUtils.cpp in Sources */,
7C15DCBD1892481400FCE564 /* InfoBool.cpp in Sources */,
+ F5CC228E1814F7F7006B5E91 /* AESinkDARWINIOS.cpp in Sources */,
F5CC22DF1814FF3B006B5E91 /* ActiveAE.cpp in Sources */,
F5CC22E01814FF3B006B5E91 /* ActiveAEBuffer.cpp in Sources */,
F5CC22E11814FF3B006B5E91 /* ActiveAEResample.cpp in Sources */,
@@ -12973,6 +12914,7 @@
F5CC230C18150118006B5E91 /* AESinkFactory.cpp in Sources */,
F5CC234718150277006B5E91 /* AESinkNULL.cpp in Sources */,
F5CC238818150768006B5E91 /* AESinkProfiler.cpp in Sources */,
+ DF374B2418AC2BA20076B514 /* CoreAudioHelpers.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/xbmc/cores/AudioEngine/AEFactory.cpp b/xbmc/cores/AudioEngine/AEFactory.cpp
index fff42a6130..17ebcc9765 100644
--- a/xbmc/cores/AudioEngine/AEFactory.cpp
+++ b/xbmc/cores/AudioEngine/AEFactory.cpp
@@ -22,12 +22,7 @@
#include "AEFactory.h"
#include "Utils/AEUtil.h"
-#if defined(TARGET_DARWIN)
- #include "Engines/CoreAudio/CoreAudioAE.h"
- #include "settings/lib/SettingsManager.h"
-#else
- #include "Engines/ActiveAE/ActiveAE.h"
-#endif
+#include "Engines/ActiveAE/ActiveAE.h"
#include "guilib/LocalizeStrings.h"
#include "settings/lib/Setting.h"
@@ -45,11 +40,7 @@ IAE *CAEFactory::GetEngine()
bool CAEFactory::LoadEngine()
{
-#if defined(TARGET_DARWIN)
- return CAEFactory::LoadEngine(AE_ENGINE_COREAUDIO);
-#else
return CAEFactory::LoadEngine(AE_ENGINE_ACTIVE);
-#endif
}
bool CAEFactory::LoadEngine(enum AEEngine engine)
@@ -61,11 +52,7 @@ bool CAEFactory::LoadEngine(enum AEEngine engine)
switch(engine)
{
case AE_ENGINE_NULL :
-#if defined(TARGET_DARWIN)
- case AE_ENGINE_COREAUDIO: AE = new CCoreAudioAE(); break;
-#else
case AE_ENGINE_ACTIVE : AE = new ActiveAE::CActiveAE(); break;
-#endif
default:
return false;
}
@@ -355,12 +342,10 @@ void CAEFactory::SettingOptionsAudioDevicesFillerGeneral(const CSetting *setting
bool foundValue = false;
AEDeviceList sinkList;
EnumerateOutputDevices(sinkList, passthrough);
-#if !defined(TARGET_DARWIN)
if (sinkList.size() == 0)
list.push_back(std::make_pair("Error - no devices found", "error"));
else
{
-#endif
for (AEDeviceList::const_iterator sink = sinkList.begin(); sink != sinkList.end(); ++sink)
{
if (sink == sinkList.begin())
@@ -371,9 +356,7 @@ void CAEFactory::SettingOptionsAudioDevicesFillerGeneral(const CSetting *setting
if (StringUtils::EqualsNoCase(current, sink->second))
foundValue = true;
}
-#if !defined(TARGET_DARWIN)
}
-#endif
if (!foundValue)
current = firstDevice;
diff --git a/xbmc/cores/AudioEngine/AESinkFactory.cpp b/xbmc/cores/AudioEngine/AESinkFactory.cpp
index bfd43a0109..128010ea9d 100644
--- a/xbmc/cores/AudioEngine/AESinkFactory.cpp
+++ b/xbmc/cores/AudioEngine/AESinkFactory.cpp
@@ -27,6 +27,10 @@
#include "Sinks/AESinkAUDIOTRACK.h"
#elif defined(TARGET_RASPBERRY_PI)
#include "Sinks/AESinkPi.h"
+#elif defined(TARGET_DARWIN_IOS)
+ #include "Sinks/AESinkDARWINIOS.h"
+#elif defined(TARGET_DARWIN_OSX)
+ #include "Sinks/AESinkDARWINOSX.h"
#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
#if defined(HAS_ALSA)
#include "Sinks/AESinkALSA.h"
@@ -62,6 +66,10 @@ void CAESinkFactory::ParseDevice(std::string &device, std::string &driver)
driver == "AUDIOTRACK" ||
#elif defined(TARGET_RASPBERRY_PI)
driver == "PI" ||
+#elif defined(TARGET_DARWIN_IOS)
+ driver == "DARWINIOS" ||
+#elif defined(TARGET_DARWIN_OSX)
+ driver == "DARWINOSX" ||
#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
#if defined(HAS_ALSA)
driver == "ALSA" ||
@@ -97,6 +105,10 @@ IAESink *CAESinkFactory::TrySink(std::string &driver, std::string &device, AEAud
sink = new CAESinkAUDIOTRACK();
#elif defined(TARGET_RASPBERRY_PI)
sink = new CAESinkPi();
+#elif defined(TARGET_DARWIN_IOS)
+ sink = new CAESinkDARWINIOS();
+#elif defined(TARGET_DARWIN_OSX)
+ sink = new CAESinkDARWINOSX();
#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
#if defined(HAS_PULSEAUDIO)
else if (driver == "PULSE")
@@ -175,6 +187,22 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force)
if(!info.m_deviceInfoList.empty())
list.push_back(info);
+#elif defined(TARGET_DARWIN_IOS)
+
+ info.m_deviceInfoList.clear();
+ info.m_sinkName = "DARWINIOS";
+ CAESinkDARWINIOS::EnumerateDevicesEx(info.m_deviceInfoList, force);
+ if(!info.m_deviceInfoList.empty())
+ list.push_back(info);
+
+#elif defined(TARGET_DARWIN_OSX)
+
+ info.m_deviceInfoList.clear();
+ info.m_sinkName = "DARWINOSX";
+ CAESinkDARWINOSX::EnumerateDevicesEx(info.m_deviceInfoList, force);
+ if(!info.m_deviceInfoList.empty())
+ list.push_back(info);
+
#elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
// check if user wants us to do something specific
if (getenv("AE_SINK"))
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp
deleted file mode 100644
index 1cd49cb1d9..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.cpp
+++ /dev/null
@@ -1,929 +0,0 @@
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "system.h"
-
-#include "CoreAudioAE.h"
-
-#include "CoreAudioAEStream.h"
-#include "CoreAudioAESound.h"
-#include "Application.h"
-#include "cores/AudioEngine/Utils/AEUtil.h"
-#include "settings/AdvancedSettings.h"
-#include "settings/Settings.h"
-#include "threads/SingleLock.h"
-#include "utils/EndianSwap.h"
-#include "utils/log.h"
-#include "utils/TimeUtils.h"
-#include "utils/MathUtils.h"
-#include "threads/SystemClock.h"
-
-#define DELAY_FRAME_TIME 20
-#define BUFFERSIZE 16416
-
-// on darwin when the devicelist changes
-// reinit by calling opencoreaudio with the last engine parameters
-// (this will fallback to default
-// device when our current output device vanishes
-// and on the other hand will go back to that device
-// if it re-appears).
-#if defined(TARGET_DARWIN_OSX)
-OSStatus deviceChangedCB( AudioObjectID inObjectID,
- UInt32 inNumberAddresses,
- const AudioObjectPropertyAddress inAddresses[],
- void* inClientData)
-{
- CCoreAudioAE *pEngine = (CCoreAudioAE *)inClientData;
- if (pEngine->GetHAL())
- {
- pEngine->AudioDevicesChanged();
- CLog::Log(LOGDEBUG, "CCoreAudioAE - audiodevicelist changed!");
- }
- return noErr;
-}
-
-void RegisterDeviceChangedCB(bool bRegister, void *ref)
-{
- OSStatus ret = noErr;
- const AudioObjectPropertyAddress inAdr =
- {
- kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- if (bRegister)
- ret = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &inAdr, deviceChangedCB, ref);
- else
- ret = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &inAdr, deviceChangedCB, ref);
-
- if (ret != noErr)
- CLog::Log(LOGERROR, "CCoreAudioAE::Deinitialize - error %s a listener callback for device changes!", bRegister?"attaching":"removing");
-}
-#else//ios
-void RegisterDeviceChangedCB(bool bRegister, void *ref){}
-#endif
-
-CCoreAudioAE::CCoreAudioAE() :
- m_Initialized (false ),
- m_deviceLost (false ),
- m_callbackRunning (false ),
- m_lastStreamFormat (AE_FMT_INVALID),
- m_lastChLayoutCount (0 ),
- m_lastSampleRate (0 ),
- m_chLayoutCount (0 ),
- m_rawPassthrough (false ),
- m_volume (1.0f ),
- m_volumeBeforeMute (1.0f ),
- m_muted (false ),
- m_soundMode (AE_SOUND_OFF ),
- m_streamsPlaying (false ),
- m_isSuspended (false ),
- m_softSuspend (false ),
- m_softSuspendTimer (0 )
-{
- HAL = new CCoreAudioAEHAL;
-
- RegisterDeviceChangedCB(true, this);
-}
-
-CCoreAudioAE::~CCoreAudioAE()
-{
- RegisterDeviceChangedCB(false, this);
- Shutdown();
-}
-
-void CCoreAudioAE::Shutdown()
-{
- CSingleLock engineLock(m_engineLock);
-
- Stop();
-
- Deinitialize();
-
- /* free the streams */
- CSingleLock streamLock(m_streamLock);
- while (!m_streams.empty())
- {
- CCoreAudioAEStream *s = m_streams.front();
- m_sounds.pop_front();
- delete s;
- }
-
- /* free the sounds */
- CSingleLock soundLock(m_soundLock);
- while (!m_sounds.empty())
- {
- CCoreAudioAESound *s = m_sounds.front();
- m_sounds.pop_front();
- delete s;
- }
-
- delete HAL;
- HAL = NULL;
-}
-
-void CCoreAudioAE::AudioDevicesChanged()
-{
- if (!m_Initialized && !m_deviceLost)
- return;
-
- CSingleLock engineLock(m_engineLock);
-
- // re-check initialized since it can have changed when we waited and grabbed the lock
- if (!m_Initialized && !m_deviceLost)
- return;
-
- OpenCoreAudio(m_lastSampleRate, COREAUDIO_IS_RAW(m_lastStreamFormat), m_lastStreamFormat, m_transcode);
-
- // when we tried to open the default device or the last device
- // again there was an error preventing us from doing it (mostly
- // the device couldn't be found) - in that case
- // mark our device as lost and hope that another callback
- // for changed device list fires (e.x. device reappears)
- if (!m_Initialized)
- m_deviceLost = true;
- else
- m_deviceLost = false;
-}
-
-bool CCoreAudioAE::Initialize()
-{
- CSingleLock engineLock(m_engineLock);
-
- Stop();
-
- Deinitialize();
-
- bool ret = OpenCoreAudio(44100, false, AE_FMT_FLOAT, false);
- m_lastSampleRate = 44100;
- m_lastStreamFormat = AE_FMT_FLOAT;
-
- Start();
-
- return ret;
-}
-
-bool CCoreAudioAE::OpenCoreAudio(unsigned int sampleRate, bool forceRaw,
- enum AEDataFormat rawDataFormat, bool forceTranscode)
-{
- unsigned int maxChannelCountInStreams = 0;
- // remove any deleted streams
- CSingleLock streamLock(m_streamLock);
- for (StreamList::iterator itt = m_streams.begin(); itt != m_streams.end();)
- {
- CCoreAudioAEStream *stream = *itt;
- if (stream->IsDestroyed())
- {
- itt = m_streams.erase(itt);
- delete stream;
- continue;
- }
- else
- {
- // close all converter
- stream->CloseConverter();
- }
-
- if (stream->GetChannelCount() > maxChannelCountInStreams)
- maxChannelCountInStreams = stream->GetChannelCount();
-
- ++itt;
- }
-
- /* override the sample rate based on the oldest stream if there is one */
- if (!m_streams.empty())
- sampleRate = m_streams.front()->GetSampleRate();
-
- if (forceRaw)
- m_rawPassthrough = true;
- else
- m_rawPassthrough = !m_streams.empty() && m_streams.front()->IsRaw();
- streamLock.Leave();
-
- if (m_rawPassthrough)
- CLog::Log(LOGINFO, "CCoreAudioAE::OpenCoreAudio - RAW passthrough enabled");
-
- m_transcode = forceTranscode;
-
- if (m_transcode)
- CLog::Log(LOGINFO, "CCoreAudioAE::OpenCoreAudio - transcode to ac3 enabled");
-
- std::string m_outputDevice = CSettings::Get().GetString("audiooutput.audiodevice");
-
- // on iOS devices we set fixed to two channels.
- m_stdChLayout = AE_CH_LAYOUT_2_0;
-#if defined(TARGET_DARWIN_OSX)
- switch (CSettings::Get().GetInt("audiooutput.channels"))
- {
- default:
- case 0: m_stdChLayout = AE_CH_LAYOUT_2_0; break; /* do not allow 1_0 output */
- case 1: m_stdChLayout = AE_CH_LAYOUT_2_0; break;
- case 2: m_stdChLayout = AE_CH_LAYOUT_2_1; break;
- case 3: m_stdChLayout = AE_CH_LAYOUT_3_0; break;
- case 4: m_stdChLayout = AE_CH_LAYOUT_3_1; break;
- case 5: m_stdChLayout = AE_CH_LAYOUT_4_0; break;
- case 6: m_stdChLayout = AE_CH_LAYOUT_4_1; break;
- case 7: m_stdChLayout = AE_CH_LAYOUT_5_0; break;
- case 8: m_stdChLayout = AE_CH_LAYOUT_5_1; break;
- case 9: m_stdChLayout = AE_CH_LAYOUT_7_0; break;
- case 10: m_stdChLayout = AE_CH_LAYOUT_7_1; break;
- }
-#endif
-
- // setup the desired format
- m_format.m_channelLayout = CAEChannelInfo(m_stdChLayout);
-
- // if there is an audio resample rate set, use it.
- if (CSettings::Get().GetInt("audiooutput.config") == AE_CONFIG_FIXED && !m_rawPassthrough)
- {
- sampleRate = CSettings::Get().GetInt("audiooutput.samplerate");
- CLog::Log(LOGINFO, "CCoreAudioAE::passthrough - Forcing samplerate to %d", sampleRate);
- }
-
- if (m_rawPassthrough && !m_transcode)
- {
- switch (rawDataFormat)
- {
- case AE_FMT_AC3:
- case AE_FMT_DTS:
- m_format.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_2_0);
- m_format.m_sampleRate = 48000;
- m_format.m_dataFormat = AE_FMT_S16NE;
- break;
- case AE_FMT_EAC3:
- m_format.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_2_0);
- m_format.m_sampleRate = 192000;
- m_format.m_dataFormat = AE_FMT_S16NE;
- break;
- case AE_FMT_DTSHD:
- case AE_FMT_TRUEHD:
- m_format.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_7_1);
- m_format.m_sampleRate = 192000;
- m_format.m_dataFormat = AE_FMT_S16NE;
- break;
- case AE_FMT_LPCM:
- // audio midi setup can be setup to 2.0 or 7.1
- // if we have the number of max channels from streams we use that for
- // selecting either 2.0 or 7.1 setup depending on that.
- // This allows DPII modes on amps for enhancing stereo sound
- // (when switching to 7.1 - all 8 channels will be pushed out preventing most amps
- // to switch to DPII mode)
- if (maxChannelCountInStreams == 1 || maxChannelCountInStreams == 2)
- m_format.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_2_0);
- else
- m_format.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_7_1);
- m_format.m_sampleRate = sampleRate;
- m_format.m_dataFormat = AE_FMT_FLOAT;
- break;
- default:
- break;
- }
- }
- else if (m_transcode)
- {
- // transcode is to ac3 only, do we copy the ac3 settings from above
- m_format.m_channelLayout = CAEChannelInfo(AE_CH_LAYOUT_2_0);
- m_format.m_sampleRate = 48000;
- m_format.m_dataFormat = AE_FMT_S16NE;
- }
- else
- {
- m_format.m_sampleRate = sampleRate;
- m_format.m_channelLayout = CAEChannelInfo(m_stdChLayout);
- m_format.m_dataFormat = AE_FMT_FLOAT;
- }
-
- m_format.m_encodedRate = 0;
-
- if (m_outputDevice.empty())
- m_outputDevice = "default";
-
- AEAudioFormat initformat = m_format;
-
- // initialize audio hardware
- m_Initialized = HAL->Initialize(this, m_rawPassthrough || m_transcode, initformat, m_transcode ? AE_FMT_AC3 : rawDataFormat, m_outputDevice, m_volume);
-
- unsigned int bps = CAEUtil::DataFormatToBits(m_format.m_dataFormat);
- m_chLayoutCount = m_format.m_channelLayout.Count();
- m_format.m_frameSize = (bps>>3) * m_chLayoutCount; //initformat.m_frameSize;
- //m_format.m_frames = (unsigned int)(((float)m_format.m_sampleRate / 1000.0f) * (float)DELAY_FRAME_TIME);
- //m_format.m_frameSamples = m_format.m_frames * m_format.m_channelLayout.Count();
-
- if ((initformat.m_channelLayout.Count() != m_chLayoutCount) && !m_rawPassthrough && !m_transcode)
- {
- /* readjust parameters. hardware didn't accept channel count*/
- CLog::Log(LOGINFO, "CCoreAudioAE::Initialize: Setup channels (%d) greater than possible hardware channels (%d).",
- m_chLayoutCount, initformat.m_channelLayout.Count());
-
- m_format.m_channelLayout = CAEChannelInfo(initformat.m_channelLayout);
- m_chLayoutCount = m_format.m_channelLayout.Count();
- m_format.m_frameSize = (bps>>3) * m_chLayoutCount; //initformat.m_frameSize;
- //m_format.m_frameSamples = m_format.m_frames * m_format.m_channelLayout.Count();
- }
-
- CLog::Log(LOGINFO, "CCoreAudioAE::Initialize:");
- CLog::Log(LOGINFO, " Output Device : %s", m_outputDevice.c_str());
- CLog::Log(LOGINFO, " Sample Rate : %d", m_format.m_sampleRate);
- CLog::Log(LOGINFO, " Sample Format : %s", CAEUtil::DataFormatToStr(m_format.m_dataFormat));
- CLog::Log(LOGINFO, " Channel Count : %d", m_chLayoutCount);
- CLog::Log(LOGINFO, " Channel Layout: %s", ((std::string)m_format.m_channelLayout).c_str());
- CLog::Log(LOGINFO, " Frame Size : %d", m_format.m_frameSize);
- CLog::Log(LOGINFO, " Volume Level : %f", m_volume);
- CLog::Log(LOGINFO, " Passthrough : %d", m_rawPassthrough);
- CLog::Log(LOGINFO, " Transcode : %d", m_transcode);
-
- CSingleLock soundLock(m_soundLock);
- StopAllSounds();
-
- // re-init sounds and unlock
- for (SoundList::iterator itt = m_sounds.begin(); itt != m_sounds.end(); ++itt)
- (*itt)->Initialize();
-
- soundLock.Leave();
-
- // if we are not in m_rawPassthrough reinit the streams
- if (!m_rawPassthrough)
- {
- /* re-init streams */
- streamLock.Enter();
- for (StreamList::iterator itt = m_streams.begin(); itt != m_streams.end(); ++itt)
- (*itt)->Initialize();
- streamLock.Leave();
- }
-
- return m_Initialized;
-}
-
-void CCoreAudioAE::Deinitialize()
-{
- if (!m_Initialized)
- return;
-
- // close all open converters
- CSingleLock streamLock(m_streamLock);
- for (StreamList::iterator itt = m_streams.begin(); itt != m_streams.end();++itt)
- (*itt)->CloseConverter();
- streamLock.Leave();
-
- m_Initialized = false;
-
- CSingleLock callbackLock(m_callbackLock);
-
- /*
- while(m_callbackRunning)
- Sleep(100);
- */
-
- HAL->Deinitialize();
-}
-
-void CCoreAudioAE::OnSettingsChange(const std::string& setting)
-{
- if (setting == "audiooutput.dontnormalizelevels")
- {
- // re-init streams remapper
- CSingleLock streamLock(m_streamLock);
- for (StreamList::iterator itt = m_streams.begin(); itt != m_streams.end(); ++itt)
- (*itt)->InitializeRemap();
- streamLock.Leave();
- }
-
- if (setting == "audiooutput.passthroughdevice" ||
- setting == "audiooutput.custompassthrough" ||
- setting == "audiooutput.audiodevice" ||
- setting == "audiooutput.customdevice" ||
- setting == "audiooutput.ac3passthrough" ||
- setting == "audiooutput.eac3passthrough" ||
- setting == "audiooutput.dtspassthrough" ||
- setting == "audiooutput.channels" ||
- setting == "audiooutput.samplerate" ||
- setting == "audiooutput.config" ||
- setting == "audiooutput.passthrough" )
- {
- // only reinit the engine if we not
- // suspended (resume will initialize
- // us again in that case)
- if (!m_isSuspended)
- Initialize();
- }
-}
-
-unsigned int CCoreAudioAE::GetSampleRate()
-{
- return m_format.m_sampleRate;
-}
-
-unsigned int CCoreAudioAE::GetEncodedSampleRate()
-{
- return m_format.m_encodedRate;
-}
-
-CAEChannelInfo CCoreAudioAE::GetChannelLayout()
-{
- return m_format.m_channelLayout;
-}
-
-unsigned int CCoreAudioAE::GetChannelCount()
-{
- return m_chLayoutCount;
-}
-
-enum AEDataFormat CCoreAudioAE::GetDataFormat()
-{
- return m_format.m_dataFormat;
-}
-
-AEAudioFormat CCoreAudioAE::GetAudioFormat()
-{
- return m_format;
-}
-
-double CCoreAudioAE::GetDelay()
-{
- return HAL->GetDelay();
-}
-
-float CCoreAudioAE::GetVolume()
-{
- return m_volume;
-}
-
-void CCoreAudioAE::SetVolume(float volume)
-{
- if (m_rawPassthrough)
- return;
-
- m_volume = volume;
- // track volume if we are not muted
- // we need this because m_volume is init'ed via
- // SetVolume and need to also init m_volumeBeforeMute.
- if (!m_muted)
- m_volumeBeforeMute = volume;
-
- HAL->SetVolume(m_volume);
-}
-
-void CCoreAudioAE::SetMute(const bool enabled)
-{
- m_muted = enabled;
- if(m_muted)
- {
- m_volumeBeforeMute = m_volume;
- SetVolume(VOLUME_MINIMUM);
- }
- else
- {
- SetVolume(m_volumeBeforeMute);
- }
-}
-
-bool CCoreAudioAE::IsMuted()
-{
- return m_muted;
-}
-
-bool CCoreAudioAE::IsSuspended()
-{
- return m_isSuspended;
-}
-
-void CCoreAudioAE::SetSoundMode(const int mode)
-{
- m_soundMode = mode;
-
- /* stop all currently playing sounds if they are being turned off */
- if (mode == AE_SOUND_OFF || (mode == AE_SOUND_IDLE && m_streamsPlaying))
- StopAllSounds();
-}
-
-bool CCoreAudioAE::SupportsRaw(AEDataFormat format)
-{
- switch(format)
- {
- case AE_FMT_AC3:
- case AE_FMT_DTS:
- case AE_FMT_EAC3:
- case AE_FMT_LPCM:
- return true;
- default:
- return false;
- }
-}
-
-bool CCoreAudioAE::IsSettingVisible(const std::string &settingId)
-{
- if (settingId == "audiooutput.samplerate")
- {
- if (CSettings::Get().GetInt("audiooutput.config") == AE_CONFIG_FIXED)
- return true;
- else
- return false;
- }
- else if (settingId == "audiooutput.stereoupmix")
- {
- if (CSettings::Get().GetInt("audiooutput.channels") > AE_CH_LAYOUT_2_0)
- return true;
- }
-
- return true;
-}
-
-CCoreAudioAEHAL* CCoreAudioAE::GetHAL()
-{
- return HAL;
-}
-
-IAEStream* CCoreAudioAE::MakeStream(enum AEDataFormat dataFormat,
- unsigned int sampleRate, unsigned int encodedSamplerate, CAEChannelInfo channelLayout, unsigned int options)
-{
- // if we are suspended we don't
- // want anyone to mess with us
- if (m_isSuspended && !m_softSuspend)
-#if defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV)
- Resume();
-#else
- return NULL;
-#endif
-
- CAEChannelInfo channelInfo(channelLayout);
- CLog::Log(LOGINFO, "CCoreAudioAE::MakeStream - %s, %u, %u, %s",
- CAEUtil::DataFormatToStr(dataFormat), sampleRate, encodedSamplerate, ((std::string)channelInfo).c_str());
-
- bool multichannelpcm = CSettings::Get().GetInt("audiooutput.channels") > AE_CH_LAYOUT_2_0; //if more then 2 channels are set - assume lpcm capability
-#if defined(TARGET_DARWIN_IOS)
- multichannelpcm = false;
-#endif
- // determine if we need to transcode this audio
- // when we're called, we'll either get the audio in an encoded form (COREAUDIO_IS_RAW==true)
- // that we can passthrough based on user options, or we'll get it unencoded
- // if it's unencoded, and is 5.1, we'll transcode it to AC3 if possible
- bool transcode = CSettings::Get().GetBool("audiooutput.passthrough") && CSettings::Get().GetBool("audiooutput.ac3passthrough") && !multichannelpcm &&
- !COREAUDIO_IS_RAW(dataFormat) &&
- (channelInfo.Count() == 6);
-
- CCoreAudioAEStream *stream = new CCoreAudioAEStream(dataFormat, sampleRate, encodedSamplerate, channelLayout, options, transcode);
- CSingleLock streamLock(m_streamLock);
- m_streams.push_back(stream);
- streamLock.Leave();
-
- if ((options & AESTREAM_PAUSED) == 0)
- Stop();
-
- // reinit the engine if pcm format changes or always on raw format or always on transcode
- if (m_Initialized && ( m_lastStreamFormat != dataFormat ||
- m_lastChLayoutCount != channelLayout.Count() ||
- m_lastSampleRate != sampleRate ||
- COREAUDIO_IS_RAW(dataFormat) ||
- transcode))
- {
- CSingleLock engineLock(m_engineLock);
- Stop();
- Deinitialize();
- m_Initialized = OpenCoreAudio(sampleRate, COREAUDIO_IS_RAW(dataFormat), dataFormat, transcode);
- m_lastStreamFormat = dataFormat;
- m_lastChLayoutCount = channelLayout.Count();
- m_lastSampleRate = sampleRate;
- }
-
- /* if the stream was not initialized, do it now */
- if (!stream->IsValid())
- stream->Initialize();
-
- if ((options & AESTREAM_PAUSED) == 0)
- Start();
-
- m_streamsPlaying = true;
-
- return stream;
-}
-
-IAEStream* CCoreAudioAE::FreeStream(IAEStream *stream)
-{
- CSingleLock streamLock(m_streamLock);
- /* ensure the stream still exists */
- for (StreamList::iterator itt = m_streams.begin(); itt != m_streams.end(); )
- {
- CCoreAudioAEStream *del = *itt;
- if (*itt == stream)
- {
- itt = m_streams.erase(itt);
- delete (CCoreAudioAEStream *)stream;
- }
- else if (del->IsDestroyed())
- {
- itt = m_streams.erase(itt);
- delete del;
- }
- else
- {
- ++itt;
- }
-
- }
- m_streamsPlaying = !m_streams.empty();
-
- streamLock.Leave();
-
- // When we have been in passthrough mode and are not suspended,
- // reinit the hardware to come back to anlog out
- if (/*m_streams.empty() || */ m_rawPassthrough && !m_isSuspended)
- {
- CLog::Log(LOGINFO, "CCoreAudioAE::FreeStream Reinit, no streams left" );
- Initialize();
- }
-
- return NULL;
-}
-
-void CCoreAudioAE::PlaySound(IAESound *sound)
-{
- if (m_soundMode == AE_SOUND_OFF || (m_soundMode == AE_SOUND_IDLE && m_streamsPlaying) || (m_isSuspended && !m_softSuspend))
- return;
-
- float *samples = ((CCoreAudioAESound*)sound)->GetSamples();
- if (!samples && !m_Initialized)
- return;
-
- /* add the sound to the play list */
- CSingleLock soundSampleLock(m_soundSampleLock);
- SoundState ss = {
- ((CCoreAudioAESound*)sound),
- samples,
- ((CCoreAudioAESound*)sound)->GetSampleCount()
- };
- m_playing_sounds.push_back(ss);
-}
-
-void CCoreAudioAE::StopSound(IAESound *sound)
-{
- CSingleLock lock(m_soundSampleLock);
- for (SoundStateList::iterator itt = m_playing_sounds.begin(); itt != m_playing_sounds.end(); )
- {
- if ((*itt).owner == sound)
- {
- (*itt).owner->ReleaseSamples();
- itt = m_playing_sounds.erase(itt);
- }
- else
- ++itt;
- }
-}
-
-IAESound *CCoreAudioAE::MakeSound(const std::string& file)
-{
- // we don't make sounds
- // when suspended
- if (m_isSuspended)
- return NULL;
-
- CSingleLock soundLock(m_soundLock);
-
- // first check if we have the file cached
- for (SoundList::iterator itt = m_sounds.begin(); itt != m_sounds.end(); ++itt)
- {
- if ((*itt)->GetFileName() == file)
- return *itt;
- }
-
- CCoreAudioAESound *sound = new CCoreAudioAESound(file);
- if (!sound->Initialize())
- {
- delete sound;
- return NULL;
- }
-
- m_sounds.push_back(sound);
- return sound;
-}
-
-void CCoreAudioAE::FreeSound(IAESound *sound)
-{
- if (!sound)
- return;
-
- sound->Stop();
- CSingleLock soundLock(m_soundLock);
- for (SoundList::iterator itt = m_sounds.begin(); itt != m_sounds.end(); ++itt)
- if (*itt == sound)
- {
- m_sounds.erase(itt);
- break;
- }
-
- delete (CCoreAudioAESound*)sound;
-}
-
-void CCoreAudioAE::StopAllSounds()
-{
- CSingleLock lock(m_soundSampleLock);
- while (!m_playing_sounds.empty())
- {
- SoundState *ss = &(*m_playing_sounds.begin());
- m_playing_sounds.pop_front();
- ss->owner->ReleaseSamples();
- }
-}
-
-void CCoreAudioAE::MixSounds(float *buffer, unsigned int samples)
-{
- if (!m_Initialized)
- return;
-
- SoundStateList::iterator itt;
-
- CSingleLock lock(m_soundSampleLock);
- for (itt = m_playing_sounds.begin(); itt != m_playing_sounds.end(); )
- {
- SoundState *ss = &(*itt);
-
- // no more frames, so remove it from the list
- if (ss->sampleCount == 0)
- {
- ss->owner->ReleaseSamples();
- itt = m_playing_sounds.erase(itt);
- continue;
- }
-
- unsigned int mixSamples = std::min(ss->sampleCount, samples);
- float volume = ss->owner->GetVolume();
-
- for (unsigned int i = 0; i < mixSamples; ++i)
- buffer[i] = (buffer[i] + (ss->samples[i] * volume));
-
- ss->sampleCount -= mixSamples;
- ss->samples += mixSamples;
-
- ++itt;
- }
-}
-
-void CCoreAudioAE::GarbageCollect()
-{
-#if defined(TARGET_DARWIN_OSX)
- if (CSettings::Get().GetInt("audiooutput.streamsilence") != 0)
- return;
-
- if (!m_streamsPlaying && m_playing_sounds.empty())
- {
- if (!m_softSuspend)
- {
- m_softSuspend = true;
- m_softSuspendTimer = XbmcThreads::SystemClockMillis() + 10000; //10.0 second delay for softSuspend
- }
- }
- else
- {
- if (m_isSuspended)
- {
- CSingleLock engineLock(m_engineLock);
- CLog::Log(LOGDEBUG, "CCoreAudioAE::GarbageCollect - Acquire CA HAL.");
- Start();
- m_isSuspended = false;
- }
- m_softSuspend = false;
- }
-
- unsigned int curSystemClock = XbmcThreads::SystemClockMillis();
- if (!m_isSuspended && m_softSuspend && curSystemClock > m_softSuspendTimer)
- {
- Suspend();// locks m_engineLock internally
- CLog::Log(LOGDEBUG, "CCoreAudioAE::GarbageCollect - Release CA HAL.");
- }
-#endif // TARGET_DARWIN_OSX
-}
-
-void CCoreAudioAE::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
-{
- if (m_isSuspended && !m_softSuspend)
- return;
-
- HAL->EnumerateOutputDevices(devices, passthrough);
-}
-
-void CCoreAudioAE::Start()
-{
- if (!m_Initialized)
- return;
-
- HAL->Start();
-}
-
-void CCoreAudioAE::Stop()
-{
- if (!m_Initialized)
- return;
-
- HAL->Stop();
-}
-
-bool CCoreAudioAE::Suspend()
-{
- CSingleLock engineLock(m_engineLock);
- CLog::Log(LOGDEBUG, "CCoreAudioAE::Suspend - Suspending AE processing");
- m_isSuspended = true;
- // stop all gui sounds
- StopAllSounds();
- // stop the CA thread
- Stop();
-
- return true;
-}
-
-bool CCoreAudioAE::Resume()
-{
- // fire up the engine again
- bool ret = Initialize();
- CLog::Log(LOGDEBUG, "CCoreAudioAE::Resume - Resuming AE processing");
- m_isSuspended = false;
-
- return ret;
-}
-
-//***********************************************************************************************
-// Rendering Methods
-//***********************************************************************************************
-OSStatus CCoreAudioAE::OnRender(AudioUnitRenderActionFlags *actionFlags,
- const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
-{
- UInt32 frames = inNumberFrames;
-
- unsigned int rSamples = frames * m_chLayoutCount;
- int size = frames * m_format.m_frameSize;
- //int size = frames * HAL->m_BytesPerFrame;
-
- for (UInt32 i = 0; i < ioData->mNumberBuffers; i++)
- bzero(ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize);
-
- if (!m_Initialized)
- {
- m_callbackRunning = false;
- return noErr;
- }
-
- CSingleLock callbackLock(m_callbackLock);
-
- m_callbackRunning = true;
-
- /*
- CSingleLock streamLock(m_streamLock);
- // Remove any destroyed stream
- if (!m_streams.empty())
- {
- for(StreamList::iterator itt = m_streams.begin(); itt != m_streams.end();)
- {
- CCoreAudioAEStream *stream = *itt;
-
- if (stream->IsDestroyed())
- {
- itt = m_streams.erase(itt);
- delete stream;
- continue;
- }
- ++itt;
- }
- }
- streamLock.Leave();
- */
-
- // when not in passthrough output mix sounds
- if (!m_rawPassthrough && m_soundMode != AE_SOUND_OFF)
- {
- MixSounds((float *)ioData->mBuffers[0].mData, rSamples);
- ioData->mBuffers[0].mDataByteSize = size;
- if (!size && actionFlags)
- *actionFlags |= kAudioUnitRenderAction_OutputIsSilence;
- }
-
- m_callbackRunning = false;
-
- return noErr;
-}
-
-// Static Callback from AudioUnit
-OSStatus CCoreAudioAE::Render(AudioUnitRenderActionFlags* actionFlags,
- const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufList)
-{
- OSStatus ret = OnRender(actionFlags, pTimeStamp, busNumber, frameCount, pBufList);
-
- return ret;
-}
-
-
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.h
deleted file mode 100644
index 3f465c457c..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAE.h
+++ /dev/null
@@ -1,181 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <list>
-#include <map>
-
-#include "system.h"
-
-#include "cores/AudioEngine/Interfaces/AE.h"
-#include "ICoreAudioAEHAL.h"
-#include "ICoreAudioSource.h"
-#include "CoreAudioAEStream.h"
-#include "CoreAudioAESound.h"
-#include "threads/CriticalSection.h"
-
-#if defined(TARGET_DARWIN_IOS)
-#include "CoreAudioAEHALIOS.h"
-#else
-#include "CoreAudioAEHALOSX.h"
-#endif
-
-#define COREAUDIO_IS_RAW(x) \
-( \
- (x) == AE_FMT_AC3 || \
- (x) == AE_FMT_DTS || \
- (x) == AE_FMT_LPCM || \
- (x) == AE_FMT_EAC3 || \
- (x) == AE_FMT_DTSHD || \
- (x) == AE_FMT_TRUEHD \
-)
-
-#if defined(TARGET_DARWIN_IOS)
-# define CCoreAudioAEHAL CCoreAudioAEHALIOS
-#else
-# define CCoreAudioAEHAL CCoreAudioAEHALOSX
-#endif
-
-class CCoreAudioAEStream;
-class CCoreAudioAESound;
-class CCoreAudioAEEventThread;
-
-class CCoreAudioAE : public IAE, public ICoreAudioSource
-{
-protected:
- friend class CAEFactory;
- CCoreAudioAE();
- virtual ~CCoreAudioAE();
-
- // Give the HAL access to the engine
- friend class CCoreAudioAEHAL;
- CCoreAudioAEHAL *HAL;
-
-public:
- virtual void Shutdown();
-
- virtual bool Initialize();
- virtual void OnSettingsChange(const std::string& setting);
-
- virtual bool Suspend(); /* Suspend output and de-initialize "hog-mode" sink for external players and power savings */
- virtual bool Resume(); /* Resume ouput and re-initialize sink after Suspend() above */
- virtual bool IsSuspended(); /* Returns true if in Suspend mode - used by players */
-
- unsigned int GetSampleRate();
- unsigned int GetEncodedSampleRate();
- CAEChannelInfo GetChannelLayout();
- unsigned int GetChannelCount();
- enum AEDataFormat GetDataFormat();
- AEAudioFormat GetAudioFormat();
-
- virtual double GetDelay();
- virtual float GetVolume();
- virtual void SetVolume(float volume);
- virtual void SetMute(const bool enabled);
- virtual bool IsMuted();
- virtual void SetSoundMode(const int mode);
- virtual bool SupportsRaw(AEDataFormat format);
- virtual bool IsSettingVisible(const std::string &settingId);
- virtual bool SupportsDrain() { return true; }
-
- CCoreAudioAEHAL* GetHAL();
-
- // returns a new stream for data in the specified format
- virtual IAEStream* MakeStream(enum AEDataFormat dataFormat,
- unsigned int sampleRate,unsigned int encodedSamplerate,
- CAEChannelInfo channelLayout, unsigned int options = 0);
-
- virtual IAEStream* FreeStream(IAEStream *stream);
-
- // returns a new sound object
- virtual IAESound* MakeSound(const std::string& file);
- void StopAllSounds();
- virtual void FreeSound(IAESound *sound);
- virtual void PlaySound(IAESound *sound);
- virtual void StopSound(IAESound *sound);
- void MixSounds(float *buffer, unsigned int samples);
-
- // free's sounds that have expired
- virtual void GarbageCollect();
-
- virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough);
-
- virtual OSStatus Render(AudioUnitRenderActionFlags* actionFlags,
- const AudioTimeStamp* pTimeStamp, UInt32 busNumber,
- UInt32 frameCount, AudioBufferList* pBufList);
-
- void AudioDevicesChanged();
-
-
-private:
- CCriticalSection m_callbackLock;
- CCriticalSection m_engineLock;
- CCriticalSection m_streamLock;
- CCriticalSection m_soundLock;
- CCriticalSection m_soundSampleLock;
-
- // currently playing sounds
- typedef struct {
- CCoreAudioAESound *owner;
- float *samples;
- unsigned int sampleCount;
- } SoundState;
-
- typedef std::list<CCoreAudioAEStream*> StreamList;
- typedef std::list<CCoreAudioAESound* > SoundList;
- typedef std::list<SoundState > SoundStateList;
-
- StreamList m_streams;
- SoundList m_sounds;
- SoundStateList m_playing_sounds;
-
- // Prevent multiple init/deinit
- bool m_Initialized;
- bool m_deviceLost;
- bool m_callbackRunning;
-
- AEAudioFormat m_format;
- enum AEDataFormat m_lastStreamFormat;
- unsigned int m_lastChLayoutCount;
- unsigned int m_lastSampleRate;
- unsigned int m_chLayoutCount;
- bool m_rawPassthrough;
- bool m_transcode;
-
- enum AEStdChLayout m_stdChLayout;
-
- bool OpenCoreAudio(unsigned int sampleRate, bool forceRaw, enum AEDataFormat rawDataFormat, bool forceTranscode);
- void Deinitialize();
- void Start();
- void Stop();
-
- OSStatus OnRender(AudioUnitRenderActionFlags *actionFlags,
- const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
- UInt32 inNumberFrames, AudioBufferList *ioData);
-
- float m_volume;
- float m_volumeBeforeMute;
- bool m_muted;
- int m_soundMode;
- bool m_streamsPlaying;
- bool m_isSuspended;
- bool m_softSuspend;
- unsigned int m_softSuspendTimer;
-};
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.cpp
deleted file mode 100644
index 879b56d535..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.cpp
+++ /dev/null
@@ -1,1342 +0,0 @@
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#if defined(TARGET_DARWIN_IOS)
-#include "system.h"
-
-#include "CoreAudioAEHALIOS.h"
-
-#include "xbmc/cores/AudioEngine/Utils/AEUtil.h"
-#include "AEFactory.h"
-#include "CoreAudioAE.h"
-#include "utils/log.h"
-
-#include <math.h>
-
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
-// use the maximum frames per slice allows audio play when the screen is locked
-#define BUFFERED_FRAMES 4096
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// CIOSCoreAudioHardware
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-AudioComponentInstance CIOSCoreAudioHardware::FindAudioDevice(std::string searchName)
-{
- if (!searchName.length())
- return 0;
-
- AudioComponentInstance defaultDevice = GetDefaultOutputDevice();
-
- return defaultDevice;
-}
-
-AudioComponentInstance CIOSCoreAudioHardware::GetDefaultOutputDevice()
-{
- AudioComponentInstance ret = (AudioComponentInstance)1;
-
- return ret;
-}
-
-UInt32 CIOSCoreAudioHardware::GetOutputDevices(IOSCoreAudioDeviceList* pList)
-{
- if (!pList)
- return 0;
-
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// CCoreAudioUnit
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-CCoreAudioUnit::CCoreAudioUnit() :
-m_pSource (NULL ),
-m_audioUnit (NULL ),
-m_audioNode (NULL ),
-m_audioGraph (NULL ),
-m_Initialized (false ),
-m_renderProc (NULL ),
-m_busNumber (INVALID_BUS )
-{
-}
-
-CCoreAudioUnit::~CCoreAudioUnit()
-{
- Close();
-}
-
-bool CCoreAudioUnit::Open(AUGraph audioGraph, AudioComponentDescription desc)
-{
- if (m_audioUnit)
- Close();
-
- OSStatus ret;
-
- m_Initialized = false;
-
- ret = AUGraphAddNode(audioGraph, &desc, &m_audioNode);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error add m_outputNode. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- ret = AUGraphNodeInfo(audioGraph, m_audioNode, NULL, &m_audioUnit);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error getting m_outputNode. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_audioGraph = audioGraph;
- m_Initialized = true;
-
- Start();
-
- return true;
-}
-
-bool CCoreAudioUnit::Open(AUGraph audioGraph, OSType type, OSType subType, OSType manufacturer)
-{
- AudioComponentDescription desc;
- desc.componentType = type;
- desc.componentSubType = subType;
- desc.componentManufacturer = manufacturer;
- desc.componentFlags = 0;
- desc.componentFlagsMask = 0;
- return Open(audioGraph, desc);
-}
-
-void CCoreAudioUnit::Close()
-{
- if (!m_Initialized && !m_audioUnit)
- return;
-
- if (m_renderProc)
- SetInputSource(NULL);
-
- Stop();
-
- if (m_busNumber != INVALID_BUS)
- {
- OSStatus ret = AUGraphDisconnectNodeInput(m_audioGraph, m_audioNode, m_busNumber);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::Close: Unable to disconnect AudioUnit. Error = %s", GetError(ret).c_str());
- }
-
- ret = AUGraphRemoveNode(m_audioGraph, m_audioNode);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::Close: Unable to disconnect AudioUnit. Error = %s", GetError(ret).c_str());
- }
- }
-
- AUGraphUpdate(m_audioGraph, NULL);
-
- m_Initialized = false;
- m_audioUnit = NULL;
- m_audioNode = NULL;
- m_pSource = NULL;
-}
-
-bool CCoreAudioUnit::GetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus)
-{
- if (!m_audioUnit || !pDesc)
- return false;
-
- UInt32 size = sizeof(AudioStreamBasicDescription);
- OSStatus ret = AudioUnitGetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope, bus, pDesc, &size);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetFormat: Unable to get AudioUnit format. Bus : %d Scope : %d : Error = %s", (int)scope, (int)bus, GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-bool CCoreAudioUnit::SetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus)
-{
- if (!m_audioUnit || !pDesc)
- return false;
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, scope, bus, pDesc, sizeof(AudioStreamBasicDescription));
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetFormat: Unable to set AudioUnit format. Bus : %d Scope : %d : Error = %s", (int)scope, (int)bus, GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-bool CCoreAudioUnit::SetMaxFramesPerSlice(UInt32 maxFrames)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFrames, sizeof(UInt32));
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetMaxFramesPerSlice: Unable to set AudioUnit max frames per slice. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-bool CCoreAudioUnit::SetInputSource(ICoreAudioSource* pSource)
-{
- m_pSource = pSource;
- if (pSource)
- return SetRenderProc();
- else
- return RemoveRenderProc();
-}
-
-bool CCoreAudioUnit::SetRenderProc()
-{
- if (!m_audioUnit || m_renderProc)
- return false;
-
- AURenderCallbackStruct callbackInfo;
- callbackInfo.inputProc = RenderCallback; // Function to be called each time the AudioUnit needs data
- callbackInfo.inputProcRefCon = this; // Pointer to be returned in the callback proc
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Input, 0, &callbackInfo, sizeof(AURenderCallbackStruct));
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetRenderProc: Unable to set AudioUnit render callback. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_renderProc = RenderCallback;
-
- return true;
-}
-
-bool CCoreAudioUnit::RemoveRenderProc()
-{
- if (!m_audioUnit || !m_renderProc)
- return false;
-
-
- AURenderCallbackStruct callbackInfo;
- callbackInfo.inputProc = nil;
- callbackInfo.inputProcRefCon = nil;
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Input, 0, &callbackInfo, sizeof(AURenderCallbackStruct));
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::RemoveRenderProc: Unable to remove AudioUnit render callback. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_renderProc = NULL;
-
- Sleep(100);
-
- return true;
-}
-
-OSStatus CCoreAudioUnit::RenderCallback(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList *ioData)
-{
- OSStatus ret = noErr;
- CCoreAudioUnit *audioUnit = (CCoreAudioUnit*)inRefCon;
-
- if (audioUnit->m_pSource)
- {
- ret = audioUnit->m_pSource->Render(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
- }
- else
- {
- ioData->mBuffers[0].mDataByteSize = 0;
- if (ioActionFlags)
- *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
- }
-
-
- return ret;
-}
-
-void CCoreAudioUnit::GetFormatDesc(AEAudioFormat format,
- AudioStreamBasicDescription *streamDesc)
-{
- unsigned int bps = CAEUtil::DataFormatToBits(format.m_dataFormat);
-
- // Set the input stream format for the AudioUnit
- // We use the default DefaultOuput AudioUnit, so we only can set the input stream format.
- // The autput format is automaticaly set to the input format.
- streamDesc->mFormatID = kAudioFormatLinearPCM; // Data encoding format
- streamDesc->mFormatFlags = kLinearPCMFormatFlagIsPacked;
- switch (format.m_dataFormat)
- {
- case AE_FMT_FLOAT:
- streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
- streamDesc->mFormatFlags |= kAudioFormatFlagIsFloat;
- break;
- case AE_FMT_S16NE:
- case AE_FMT_AC3:
- case AE_FMT_DTS:
- case AE_FMT_DTSHD:
- case AE_FMT_TRUEHD:
- case AE_FMT_EAC3:
- streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
- streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
- break;
- case AE_FMT_S16LE:
- streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
- break;
- case AE_FMT_S16BE:
- streamDesc->mFormatFlags |= kAudioFormatFlagIsBigEndian;
- streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
- break;
- default:
- streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
- streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
- break;
- }
- streamDesc->mChannelsPerFrame = format.m_channelLayout.Count(); // Number of interleaved audiochannels
- streamDesc->mSampleRate = (Float64)format.m_sampleRate; // the sample rate of the audio stream
- streamDesc->mBitsPerChannel = bps; // Number of bits per sample, per channel
- streamDesc->mBytesPerFrame = (bps>>3) * format.m_channelLayout.Count(); // Size of a frame == 1 sample per channel
- streamDesc->mFramesPerPacket = 1; // The smallest amount of indivisible data. Always 1 for uncompressed audio
- streamDesc->mBytesPerPacket = streamDesc->mBytesPerFrame * streamDesc->mFramesPerPacket;
- streamDesc->mReserved = 0;
-}
-
-float CCoreAudioUnit::GetLatency()
-{
- if (!m_audioUnit)
- return 0.0f;
-
- //kAudioSessionProperty_CurrentHardwareIOBufferDuration
- //kAudioSessionProperty_CurrentHardwareOutputLatency
-
- Float32 preferredBufferSize = 0.0f;
- UInt32 size = sizeof(preferredBufferSize);
- AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputLatency, &size, &preferredBufferSize);
- return preferredBufferSize;
-}
-
-bool CCoreAudioUnit::SetSampleRate(Float64 sampleRate, AudioUnitScope scope, AudioUnitElement bus)
-{
- if (!m_audioUnit)
- return false;
-
- UInt32 size = sizeof(Float64);
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_SampleRate, scope, bus, &sampleRate, size);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetSampleRate: Unable to set AudioUnit format. Bus : %d Scope : %d : Error = %s", (int)scope, (int)bus, GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-bool CCoreAudioUnit::Stop()
-{
- if (!m_audioUnit)
- return false;
-
- AudioOutputUnitStop(m_audioUnit);
-
- return true;
-}
-
-bool CCoreAudioUnit::Start()
-{
- if (!m_audioUnit)
- return false;
-
- AudioOutputUnitStart(m_audioUnit);
-
- return true;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// CAUOutputDevice
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-CAUOutputDevice::CAUOutputDevice()
-{
-}
-
-CAUOutputDevice::~CAUOutputDevice()
-{
-}
-
-/*
-Float32 CAUOutputDevice::GetCurrentVolume()
-{
- if (!m_audioUnit)
- return 0.0f;
-
- Float32 volPct = 0.0f;
- OSStatus ret = AudioUnitGetParameter(m_audioUnit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, &volPct);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetCurrentVolume: Unable to get AudioUnit volume. Error = %s", GetError(ret).c_str());
- return 0.0f;
- }
- return volPct;
-}
-
-bool CAUOutputDevice::SetCurrentVolume(Float32 vol)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetParameter(m_audioUnit, kHALOutputParam_Volume,
- kAudioUnitScope_Global, 0, vol, 0);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetCurrentVolume: Unable to set AudioUnit volume. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-*/
-
-UInt32 CAUOutputDevice::GetBufferFrameSize()
-{
- if (!m_audioUnit)
- return 0;
-
- return BUFFERED_FRAMES;
-}
-
-bool CAUOutputDevice::EnableInputOuput()
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret;
- UInt32 enable;
- UInt32 hasio = 0;
- UInt32 size=sizeof(UInt32);
-
- ret = AudioUnitGetProperty(m_audioUnit,kAudioOutputUnitProperty_HasIO,kAudioUnitScope_Input, 1, &hasio, &size);
-
- if (!ret && hasio)
- {
- enable = 1;
- ret = AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &enable, sizeof(enable));
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUOutputDevice::EnableInputOuput:: Unable to enable input on bus 1. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- enable = 1;
- ret = AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &enable, sizeof(enable));
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUOutputDevice::EnableInputOuput:: Unable to disable output on bus 0. Error = %s", GetError(ret).c_str());
- return false;
- }
- }
-
- return true;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// CAUMultiChannelMixer
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-CAUMultiChannelMixer::CAUMultiChannelMixer()
-{
-}
-
-CAUMultiChannelMixer::~CAUMultiChannelMixer()
-{
-
-}
-
-UInt32 CAUMultiChannelMixer::GetInputBusCount()
-{
- if (!m_audioUnit)
- return 0;
-
- UInt32 busCount = 0;
- UInt32 size = sizeof(busCount);
- OSStatus ret = AudioUnitGetProperty(m_audioUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &busCount, &size);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMultiChannelMixer::GetInputBusCount: Unable to get input bus count. Error = %s", GetError(ret).c_str());
- return 0;
- }
- return busCount;
-}
-
-bool CAUMultiChannelMixer::SetInputBusFormat(UInt32 busCount, AudioStreamBasicDescription *pFormat)
-{
- if (!m_audioUnit)
- return false;
-
- for (UInt32 i = 0; i < busCount; i++)
- {
- if (!SetFormat(pFormat, kAudioUnitScope_Input, i))
- return false;
- }
-
- return true;
-}
-
-bool CAUMultiChannelMixer::SetInputBusCount(UInt32 busCount)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &busCount, sizeof(UInt32));
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMultiChannelMixer::SetInputBusCount: Unable to set input bus count. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-UInt32 CAUMultiChannelMixer::GetOutputBusCount()
-{
- if (!m_audioUnit)
- return 0;
-
- UInt32 busCount = 0;
- UInt32 size = sizeof(busCount);
- OSStatus ret = AudioUnitGetProperty(m_audioUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Output, 0, &busCount, &size);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMultiChannelMixer::GetOutputBusCount: Unable to get output bus count. Error = %s", GetError(ret).c_str());
- return 0;
- }
- return busCount;
-}
-
-bool CAUMultiChannelMixer::SetOutputBusCount(UInt32 busCount)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_ElementCount, kAudioUnitScope_Output, 0, &busCount, sizeof(UInt32));
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMultiChannelMixer::SetOutputBusCount: Unable to set output bus count. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-Float32 CAUMultiChannelMixer::GetCurrentVolume()
-{
-
- if (!m_audioUnit)
- return false;
-
- Float32 volPct = 0.0f;
- OSStatus ret = AudioUnitGetParameter(m_audioUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, kInputBus, &volPct);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMultiChannelMixer::GetCurrentVolume: Unable to get Mixer volume. Error = %s", GetError(ret).c_str());
- return 0.0f;
- }
- return volPct;
-
-}
-
-bool CAUMultiChannelMixer::SetCurrentVolume(Float32 vol)
-{
-
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetParameter(m_audioUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, kOutputBus, vol, 0);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMultiChannelMixer::SetCurrentVolume: Unable to set Mixer volume. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- return true;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// CCoreAudioGraph
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-CCoreAudioGraph::CCoreAudioGraph() :
-m_audioGraph (NULL ),
-m_audioUnit (NULL ),
-m_mixerUnit (NULL ),
-m_inputUnit (NULL ),
-m_initialized (false),
-m_allowMixing (false)
-{
- for (int i = 0; i < MAX_CONNECTION_LIMIT; i++)
- {
- m_reservedBusNumber[i] = false;
- }
-}
-
-CCoreAudioGraph::~CCoreAudioGraph()
-{
- Close();
-}
-
-bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing, float initVolume)
-{
- OSStatus ret;
-
- AudioStreamBasicDescription inputFormat;
- AudioStreamBasicDescription outputFormat;
-
- m_allowMixing = allowMixing;
-
- ret = NewAUGraph(&m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error create audio grpah. Error = %s", GetError(ret).c_str());
- return false;
- }
- ret = AUGraphOpen(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error open audio grpah. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- // get output unit
- if (m_audioUnit)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error audio unit already open. double call ?");
- return false;
- }
-
- m_audioUnit = new CAUOutputDevice();
- if (!m_audioUnit->Open(m_audioGraph, kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple))
- return false;
-
- UInt32 bufferFrames = m_audioUnit->GetBufferFrameSize();
-
- if (!m_audioUnit->EnableInputOuput())
- return false;
-
- m_audioUnit->SetMaxFramesPerSlice(bufferFrames);
-
- m_audioUnit->GetFormatDesc(format, &inputFormat);
-
- //if(!allowMixing)
- //{
- if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus))
- return false;
-
- if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Output, kInputBus))
- return false;
- //}
-
- if (allowMixing)
- {
- // get mixer unit
- if (m_mixerUnit)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?");
- return false;
- }
-
- m_mixerUnit = new CAUMultiChannelMixer();
-
- if (!m_mixerUnit->Open(m_audioGraph, kAudioUnitType_Mixer, kAudioUnitSubType_MultiChannelMixer, kAudioUnitManufacturer_Apple))
- return false;
-
- m_mixerUnit->SetMaxFramesPerSlice(bufferFrames);
-
- // set number of input buses
- if (!m_mixerUnit->SetInputBusCount(MAX_CONNECTION_LIMIT))
- return false;
-
- //if(!m_mixerUnit->SetFormat(&fmt, kAudioUnitScope_Output, kOutputBus))
- // return false;
-
- m_mixerUnit->SetBus(0);
-
- if (!m_audioUnit->GetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus))
- return false;
-
- /*
- if(!m_mixerUnit->SetInputBusFormat(MAX_CONNECTION_LIMIT, &outputFormat))
- return false;
- */
-
- ret = AUGraphConnectNodeInput(m_audioGraph, m_mixerUnit->GetNode(), 0, m_audioUnit->GetNode(), 0);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error connecting m_m_mixerNode. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- // get output unit
- if (m_inputUnit)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?");
- return false;
- }
-
- m_inputUnit = new CAUOutputDevice();
-
- if (!m_inputUnit->Open(m_audioGraph, kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter, kAudioUnitManufacturer_Apple))
- return false;
-
- m_inputUnit->SetMaxFramesPerSlice(bufferFrames);
-
- if (!m_inputUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus))
- return false;
-
- /*
- if(!m_inputUnit->SetFormat(&outputFormat, kAudioUnitScope_Output, kOutputBus))
- return false;
- */
-
- // configure output unit
- int busNumber = GetFreeBus();
-
- ret = AUGraphConnectNodeInput(m_audioGraph, m_inputUnit->GetNode(), 0, m_mixerUnit->GetNode(), busNumber);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error connecting m_converterNode. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_inputUnit->SetBus(busNumber);
-
- ret = AUGraphUpdate(m_audioGraph, NULL);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error update graph. Error = %s", GetError(ret).c_str());
- return false;
- }
- ret = AUGraphInitialize(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error initialize graph. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- // Regenerate audio format and copy format for the Output AU
- }
-
- ret = AUGraphUpdate(m_audioGraph, NULL);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error update graph. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- std::string formatString;
- AudioStreamBasicDescription inputDesc_end, outputDesc_end;
- m_audioUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
- m_audioUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kInputBus);
- CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputDesc_end, formatString));
- CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString));
-
- if (m_mixerUnit)
- {
- m_mixerUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
- m_mixerUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus);
- CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputDesc_end, formatString));
- CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString));
- }
-
- if (m_inputUnit)
- {
- m_inputUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
- m_inputUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus);
- CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputDesc_end, formatString));
- CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputDesc_end, formatString));
- }
-
- ret = AUGraphInitialize(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error initialize graph. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- SetCurrentVolume(initVolume);
-
- SetInputSource(pSource);
-
- ShowGraph();
-
- return Start();
-}
-
-bool CCoreAudioGraph::Close()
-{
- if (!m_audioGraph)
- return false;
-
- OSStatus ret;
-
- Stop();
-
- SetInputSource(NULL);
-
- while (!m_auUnitList.empty())
- {
- CAUOutputDevice *d = m_auUnitList.front();
- m_auUnitList.pop_front();
- ReleaseBus(d->GetBus());
- d->Close();
- delete d;
- }
-
- if (m_inputUnit)
- {
- ReleaseBus(m_inputUnit->GetBus());
- m_inputUnit->Close();
- delete m_inputUnit;
- m_inputUnit = NULL;
- }
-
- if (m_mixerUnit)
- {
- m_mixerUnit->Close();
- delete m_mixerUnit;
- m_mixerUnit = NULL;
- }
-
- if (m_audioUnit)
- {
- m_audioUnit->Close();
- delete m_audioUnit;
- m_audioUnit = NULL;
- }
-
- ret = AUGraphUninitialize(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Close: Error unitialize. Error = %s", GetError(ret).c_str());
- }
-
- ret = AUGraphClose(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Close: Error close. Error = %s", GetError(ret).c_str());
- }
-
- ret = DisposeAUGraph(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Close: Error dispose. Error = %s", GetError(ret).c_str());
- }
-
- return true;
-}
-
-bool CCoreAudioGraph::Start()
-{
- if (!m_audioGraph)
- return false;
-
- OSStatus ret;
- Boolean isRunning = false;
-
- ret = AUGraphIsRunning(m_audioGraph, &isRunning);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Start: Audio graph not running. Error = %s", GetError(ret).c_str());
- return false;
- }
- if (!isRunning)
- {
-
- if (m_audioUnit)
- m_audioUnit->Start();
- if (m_mixerUnit)
- m_mixerUnit->Start();
- if (m_inputUnit)
- m_inputUnit->Start();
-
- ret = AUGraphStart(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Start: Error starting audio graph. Error = %s", GetError(ret).c_str());
- }
- ShowGraph();
- }
-
- return true;
-}
-
-bool CCoreAudioGraph::Stop()
-{
- if (!m_audioGraph)
- return false;
-
- OSStatus ret;
- Boolean isRunning = false;
-
- ret = AUGraphIsRunning(m_audioGraph, &isRunning);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Stop: Audio graph not running. Error = %s", GetError(ret).c_str());
- return false;
- }
- if (isRunning)
- {
-
- if (m_inputUnit)
- m_inputUnit->Stop();
- if (m_mixerUnit)
- m_mixerUnit->Stop();
- if (m_audioUnit)
- m_audioUnit->Stop();
-
- ret = AUGraphStop(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Stop: Error stopping audio graph. Error = %s", GetError(ret).c_str());
- }
- }
-
- return true;
-}
-
-bool CCoreAudioGraph::SetInputSource(ICoreAudioSource* pSource)
-{
- if (m_inputUnit)
- return m_inputUnit->SetInputSource(pSource);
- else if (m_audioUnit)
- return m_audioUnit->SetInputSource(pSource);
-
- return false;
-}
-
-bool CCoreAudioGraph::SetCurrentVolume(Float32 vol)
-{
- if (!m_mixerUnit)
- return false;
-
- return m_mixerUnit->SetCurrentVolume(vol);
-}
-
-CAUOutputDevice *CCoreAudioGraph::DestroyUnit(CAUOutputDevice *outputUnit)
-{
- if (!outputUnit)
- return NULL;
-
- Stop();
-
- for (AUUnitList::iterator itt = m_auUnitList.begin(); itt != m_auUnitList.end(); ++itt)
- if (*itt == outputUnit)
- {
- m_auUnitList.erase(itt);
- break;
- }
-
- ReleaseBus(outputUnit->GetBus());
- outputUnit->Close();
- delete outputUnit;
-
- AUGraphUpdate(m_audioGraph, NULL);
-
- printf("Remove unit\n\n");
- ShowGraph();
- printf("\n");
-
- Start();
-
- return NULL;
-}
-
-CAUOutputDevice *CCoreAudioGraph::CreateUnit(AEAudioFormat &format)
-{
- if (!m_audioUnit || !m_mixerUnit)
- return NULL;
-
- std::string formatString;
- AudioStreamBasicDescription inputFormat;
- AudioStreamBasicDescription outputFormat;
-
- OSStatus ret;
-
- int busNumber = GetFreeBus();
- if (busNumber == INVALID_BUS)
- return NULL;
-
- // create output unit
- CAUOutputDevice *outputUnit = new CAUOutputDevice();
- if (!outputUnit->Open(m_audioGraph, kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter, kAudioUnitManufacturer_Apple))
- goto error;
-
- outputUnit->SetMaxFramesPerSlice(m_audioUnit->GetBufferFrameSize());
-
- m_audioUnit->GetFormatDesc(format, &inputFormat);
-
- // get the format frm the mixer
- if (!m_mixerUnit->GetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus))
- goto error;
-
- if (!outputUnit->SetFormat(&outputFormat, kAudioUnitScope_Output, kOutputBus))
- goto error;
-
- if (!outputUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus))
- goto error;
-
- ret = AUGraphConnectNodeInput(m_audioGraph, outputUnit->GetNode(), 0, m_mixerUnit->GetNode(), busNumber);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::CreateUnit: Error connecting outputUnit. Error = %s", GetError(ret).c_str());
- goto error;
- }
-
- // TODO: setup mixmap, get free bus number for connection
-
- outputUnit->SetBus(busNumber);
-
- AUGraphUpdate(m_audioGraph, NULL);
-
- printf("Add unit\n\n");
- ShowGraph();
- printf("\n");
-
- CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Input Stream Format %s", StreamDescriptionToString(inputFormat, formatString));
- CLog::Log(LOGINFO, "CCoreAudioGraph::Open: Output Stream Format %s", StreamDescriptionToString(outputFormat, formatString));
-
- m_auUnitList.push_back(outputUnit);
-
- return outputUnit;
-
-error:
- delete outputUnit;
- return NULL;
-}
-
-int CCoreAudioGraph::GetFreeBus()
-{
- for (int i = 0; i < MAX_CONNECTION_LIMIT; i++)
- {
- if (!m_reservedBusNumber[i])
- {
- m_reservedBusNumber[i] = true;
- return i;
- }
- }
- return INVALID_BUS;
-}
-
-void CCoreAudioGraph::ReleaseBus(int busNumber)
-{
- if (busNumber > MAX_CONNECTION_LIMIT || busNumber < 0)
- return;
-
- m_reservedBusNumber[busNumber] = false;
-}
-
-bool CCoreAudioGraph::IsBusFree(int busNumber)
-{
- if (busNumber > MAX_CONNECTION_LIMIT || busNumber < 0)
- return false;
- return m_reservedBusNumber[busNumber];
-}
-
-int CCoreAudioGraph::GetMixerChannelOffset(int busNumber)
-{
- if (!m_mixerUnit)
- return 0;
-
- int offset = 0;
- AudioStreamBasicDescription fmt;
-
- for (int i = 0; i < busNumber; i++)
- {
- memset(&fmt, 0x0, sizeof(fmt));
- m_mixerUnit->GetFormat(&fmt, kAudioUnitScope_Input, busNumber);
- offset += fmt.mChannelsPerFrame;
- }
- return offset;
-}
-
-void CCoreAudioGraph::ShowGraph()
-{
- CAShow(m_audioGraph);
-}
-
-float CCoreAudioGraph::GetLatency()
-{
- float delay = 0.0f;
-
- if (m_audioUnit)
- delay += m_audioUnit->GetLatency();
-
- return delay;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// CCoreAudioAEHALIOS
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-CCoreAudioAEHALIOS::CCoreAudioAEHALIOS() :
-m_audioGraph (NULL ),
-m_Initialized (false ),
-m_Passthrough (false ),
-m_allowMixing (false ),
-m_encoded (false ),
-m_initVolume (1.0f ),
-m_NumLatencyFrames (0 ),
-m_OutputBufferIndex (0 ),
-m_ae (NULL )
-{
-}
-
-CCoreAudioAEHALIOS::~CCoreAudioAEHALIOS()
-{
- Deinitialize();
-
- delete m_audioGraph;
-}
-
-bool CCoreAudioAEHALIOS::InitializePCM(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing)
-{
-
- if (m_audioGraph)
- {
- m_audioGraph->Close();
- delete m_audioGraph;
- }
- m_audioGraph = new CCoreAudioGraph();
-
- if (!m_audioGraph)
- return false;
-
- if (!m_audioGraph->Open(pSource, format, allowMixing, m_initVolume))
- {
- CLog::Log(LOGERROR, "CCoreAudioAEHALIOS::Initialize: Unable to initialize audio due a missconfiguration. Try 2.0 speaker configuration.");
- return false;
- }
-
- m_NumLatencyFrames = 0;
-
- m_allowMixing = allowMixing;
-
- return true;
-}
-
-bool CCoreAudioAEHALIOS::InitializePCMEncoded(ICoreAudioSource *pSource, AEAudioFormat &format)
-{
- if (!InitializePCM(pSource, format, false))
- return false;
-
- return true;
-}
-
-bool CCoreAudioAEHALIOS::Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume)
-{
- m_ae = (CCoreAudioAE *)ae;
-
- if (!m_ae)
- return false;
-
- m_initformat = format;
- m_Passthrough = passThrough;
- m_encoded = false;
- m_OutputBufferIndex = 0;
- m_rawDataFormat = rawDataFormat;
- m_initVolume = initVolume;
-
- if (format.m_channelLayout.Count() == 0)
- {
- CLog::Log(LOGERROR, "CCoreAudioAEHALIOS::Initialize - Unable to open the requested channel layout");
- return false;
- }
-
- if (device.find("CoreAudio:"))
- device.erase(0, strlen("CoreAudio:"));
-
- // If this is a passthrough (AC3/DTS) stream, attempt to handle it natively
- if (m_Passthrough)
- {
- m_encoded = false;
- }
-
- // If this is a PCM stream, or we failed to handle a passthrough stream natively,
- // prepare the standard interleaved PCM interface
- if (!m_encoded)
- {
- // If we are here and this is a passthrough stream, native handling failed.
- // Try to handle it as IEC61937 data over straight PCM (DD-Wav)
- bool configured = false;
- if (m_Passthrough)
- {
- CLog::Log(LOGERROR, "CCoreAudioAEHALIOS::Initialize: No suitable AC3 output format found. Attempting DD-Wav.");
- configured = InitializePCMEncoded(ae, format);
- }
- else
- {
- // Standard PCM data
- configured = InitializePCM(ae, format, true);
- }
-
- if (!configured) // No suitable output format was able to be configured
- return false;
- }
-
- if (m_audioGraph)
- m_audioGraph->ShowGraph();
-
- m_Initialized = true;
-
- return true;
-}
-
-CAUOutputDevice *CCoreAudioAEHALIOS::DestroyUnit(CAUOutputDevice *outputUnit)
-{
- if (m_audioGraph && outputUnit)
- return m_audioGraph->DestroyUnit(outputUnit);
-
- return NULL;
-}
-
-CAUOutputDevice *CCoreAudioAEHALIOS::CreateUnit(ICoreAudioSource *pSource, AEAudioFormat &format)
-{
- CAUOutputDevice *outputUnit = NULL;
-
- // when HAL is using a mixer, the input is routed through converter units.
- // therefore we create a converter unit attach the source and give it back.
- if (m_allowMixing && m_audioGraph)
- {
- outputUnit = m_audioGraph->CreateUnit(format);
-
- if (pSource && outputUnit)
- outputUnit->SetInputSource(pSource);
- }
-
- return outputUnit;
-}
-
-void CCoreAudioAEHALIOS::Deinitialize()
-{
- if (!m_Initialized)
- return;
-
- Stop();
-
- //if (m_encoded)
-
- if (m_audioGraph)
- m_audioGraph->SetInputSource(NULL);
-
- if (m_audioGraph)
- {
- //m_audioGraph->Close();
- delete m_audioGraph;
- }
- m_audioGraph = NULL;
-
- m_NumLatencyFrames = 0;
- m_OutputBufferIndex = 0;
-
- m_Initialized = false;
- m_Passthrough = false;
-}
-
-void CCoreAudioAEHALIOS::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
-{
- IOSCoreAudioDeviceList deviceList;
- CIOSCoreAudioHardware::GetOutputDevices(&deviceList);
-
- // Add default output device if GetOutputDevices return nothing
- devices.push_back(AEDevice("Default", "IOSCoreAudio:default"));
-
- std::string deviceName;
- for (int i = 0; !deviceList.empty(); i++)
- {
- std::string deviceName_Internal = std::string("IOSCoreAudio:") + deviceName;
- devices.push_back(AEDevice(deviceName, deviceName_Internal));
-
- deviceList.pop_front();
-
- }
-}
-
-void CCoreAudioAEHALIOS::Stop()
-{
- if (!m_Initialized)
- return;
-
- m_audioGraph->Stop();
-}
-
-bool CCoreAudioAEHALIOS::Start()
-{
- if (!m_Initialized)
- return false;
-
- m_audioGraph->Start();
-
- return true;
-}
-
-void CCoreAudioAEHALIOS::SetDirectInput(ICoreAudioSource *pSource, AEAudioFormat &format)
-{
- if (!m_Initialized)
- return;
-
- // when HAL is initialized encoded we use directIO
- // when HAL is not in encoded mode and there is no mixer attach source the audio unit
- // when mixing is allowed in HAL, HAL is working with converter units where we attach the source.
-
- if (!m_encoded && !m_allowMixing)
- {
- // register render callback for the audio unit
- m_audioGraph->SetInputSource(pSource);
- }
-
- if (m_audioGraph)
- m_audioGraph->ShowGraph();
-
-}
-
-double CCoreAudioAEHALIOS::GetDelay()
-{
- /*
- float delay;
-
- delay = (float)(m_NumLatencyFrames) / (m_initformat.m_sampleRate);
-
- return delay;
- */
-
- return (double)(BUFFERED_FRAMES) / (double)(m_initformat.m_sampleRate);
-}
-
-void CCoreAudioAEHALIOS::SetVolume(float volume)
-{
- if (!m_encoded)
- m_audioGraph->SetCurrentVolume(volume);
-}
-
-unsigned int CCoreAudioAEHALIOS::GetBufferIndex()
-{
- return m_OutputBufferIndex;
-}
-
-#endif
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.h
deleted file mode 100644
index 3e39fb4f93..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALIOS.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#if defined(TARGET_DARWIN_IOS)
-
-#include <list>
-#include <vector>
-
-#include "ICoreAudioAEHAL.h"
-#include "CoreAudioAEHAL.h"
-#include "utils/StdString.h"
-
-#include <AudioUnit/AudioUnit.h>
-#include <AudioUnit/AudioUnitProperties.h>
-#include <AudioToolbox/AudioToolbox.h>
-#include <AudioToolbox/AudioServices.h>
-#include <CoreAudio/CoreAudioTypes.h>
-
-#define kOutputBus 0
-#define kInputBus 1
-#define MAX_CONNECTION_LIMIT 8
-#define INVALID_BUS -1
-
-// Forward declarations
-class CCoreAudioAE;
-class CIOSCoreAudioConverter;
-
-typedef std::list<AudioComponentInstance> IOSCoreAudioDeviceList;
-
-// There is only one AudioSystemObject instance system-side.
-// Therefore, all CIOSCoreAudioHardware methods are static
-class CIOSCoreAudioHardware
-{
-public:
- static AudioComponentInstance FindAudioDevice(std::string deviceName);
- static AudioComponentInstance GetDefaultOutputDevice();
- static UInt32 GetOutputDevices(IOSCoreAudioDeviceList* pList);
-};
-
-class CCoreAudioUnit
-{
-public:
- CCoreAudioUnit();
- virtual ~CCoreAudioUnit();
-
- virtual bool Open(AUGraph audioGraph, AudioComponentDescription desc);
- virtual bool Open(AUGraph audioGraph, OSType type, OSType subType, OSType manufacturer);
- virtual void Close();
- virtual bool SetInputSource(ICoreAudioSource* pSource);
- virtual bool IsInitialized() {return m_Initialized;}
- virtual bool GetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus);
- virtual bool SetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus);
- virtual bool SetMaxFramesPerSlice(UInt32 maxFrames);
- virtual void GetFormatDesc(AEAudioFormat format, AudioStreamBasicDescription *streamDesc);
- virtual float GetLatency();
- virtual bool SetSampleRate(Float64 sampleRate, AudioUnitScope scope, AudioUnitElement bus);
- virtual bool Stop();
- virtual bool Start();
- virtual AudioUnit GetUnit (){return m_audioUnit;}
- virtual AUGraph GetGraph (){return m_audioGraph;}
- virtual AUNode GetNode (){return m_audioNode;}
- virtual int GetBus (){return m_busNumber;}
- virtual void SetBus (int busNumber){m_busNumber = busNumber;}
-protected:
- bool SetRenderProc();
- bool RemoveRenderProc();
- static OSStatus RenderCallback(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList *ioData);
- ICoreAudioSource* m_pSource;
- AudioUnit m_audioUnit;
- AUNode m_audioNode;
- AUGraph m_audioGraph;
- bool m_Initialized;
- AURenderCallback m_renderProc;
- int m_busNumber;
-};
-
-class CAUOutputDevice : public CCoreAudioUnit
-{
-public:
- CAUOutputDevice();
- virtual ~CAUOutputDevice();
- UInt32 GetBufferFrameSize();
-
- /*
- Float32 GetCurrentVolume();
- bool SetCurrentVolume(Float32 vol);
- */
- bool EnableInputOuput();
-};
-
-class CAUMultiChannelMixer : public CAUOutputDevice
-{
-public:
- CAUMultiChannelMixer();
- virtual ~CAUMultiChannelMixer();
-
- UInt32 GetInputBusCount();
- bool SetInputBusFormat(UInt32 busCount, AudioStreamBasicDescription *pFormat);
- bool SetInputBusCount(UInt32 busCount);
- UInt32 GetOutputBusCount();
- bool SetOutputBusCount(UInt32 busCount);
-
- Float32 GetCurrentVolume();
- bool SetCurrentVolume(Float32 vol);
-};
-
-class CCoreAudioGraph
-{
-private:
- AUGraph m_audioGraph;
-
- CAUOutputDevice *m_audioUnit;
- CAUMultiChannelMixer *m_mixerUnit;
- CAUOutputDevice *m_inputUnit;
-
- int m_reservedBusNumber[MAX_CONNECTION_LIMIT];
- bool m_initialized;
- bool m_allowMixing;
-
- typedef std::list<CAUOutputDevice*> AUUnitList;
- AUUnitList m_auUnitList;
-
-public:
- CCoreAudioGraph();
- ~CCoreAudioGraph();
-
- bool Open(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing, float initVolume);
- bool Close();
- bool Start();
- bool Stop();
- bool SetInputSource(ICoreAudioSource* pSource);
- bool SetCurrentVolume(Float32 vol);
- CAUOutputDevice *DestroyUnit(CAUOutputDevice *outputUnit);
- CAUOutputDevice *CreateUnit(AEAudioFormat &format);
- int GetFreeBus();
- void ReleaseBus(int busNumber);
- bool IsBusFree(int busNumber);
- int GetMixerChannelOffset(int busNumber);
- void ShowGraph();
- float GetLatency();
-};
-
-class CCoreAudioAEHALIOS : public ICoreAudioAEHAL
-{
-protected:
- CCoreAudioGraph *m_audioGraph;
- bool m_Initialized;
- bool m_Passthrough;
- AEAudioFormat m_initformat;
- bool m_allowMixing;
- bool m_encoded;
- AEDataFormat m_rawDataFormat;
- float m_initVolume;
-public:
- unsigned int m_NumLatencyFrames;
- unsigned int m_OutputBufferIndex;
- CCoreAudioAE *m_ae;
-
- CCoreAudioAEHALIOS();
- virtual ~CCoreAudioAEHALIOS();
-
- virtual bool InitializePCM(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing);
- virtual bool InitializePCMEncoded(ICoreAudioSource *pSource, AEAudioFormat &format);
- virtual bool Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume);
- virtual void Deinitialize();
- virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough);
- virtual void SetDirectInput(ICoreAudioSource *pSource, AEAudioFormat &format);
- virtual void Stop();
- virtual bool Start();
- virtual double GetDelay();
- virtual void SetVolume(float volume);
- virtual unsigned int GetBufferIndex();
- virtual CAUOutputDevice *DestroyUnit(CAUOutputDevice *outputUnit);
- virtual CAUOutputDevice *CreateUnit(ICoreAudioSource *pSource, AEAudioFormat &format);
- virtual bool AllowMixing() { return m_allowMixing; }
-};
-
-#endif
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp
deleted file mode 100644
index 10025bbde9..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.cpp
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifdef TARGET_DARWIN_OSX
-
-#include "system.h"
-
-#include "CoreAudioAEHALOSX.h"
-
-#include "CoreAudioAE.h"
-#include "CoreAudioAEHAL.h"
-#include "CoreAudioUnit.h"
-#include "CoreAudioDevice.h"
-#include "CoreAudioGraph.h"
-#include "CoreAudioMixMap.h"
-#include "CoreAudioHardware.h"
-#include "CoreAudioChannelLayout.h"
-
-#include "cores/AudioEngine/Utils/AEUtil.h"
-#include "utils/log.h"
-#include "settings/Settings.h"
-
-CCoreAudioAEHALOSX::CCoreAudioAEHALOSX() :
- m_audioGraph (NULL ),
- m_Initialized (false ),
- m_Passthrough (false ),
- m_allowMixing (false ),
- m_encoded (false ),
- m_initVolume (1.0f ),
- m_NumLatencyFrames (0 ),
- m_OutputBufferIndex (0 ),
- m_ae (NULL )
-{
- m_AudioDevice = new CCoreAudioDevice();
- m_OutputStream = new CCoreAudioStream();
-
- SInt32 major, minor;
- Gestalt(gestaltSystemVersionMajor, &major);
- Gestalt(gestaltSystemVersionMinor, &minor);
-
- // By default, kAudioHardwarePropertyRunLoop points at the process's main thread on SnowLeopard,
- // If your process lacks such a run loop, you can set kAudioHardwarePropertyRunLoop to NULL which
- // tells the HAL to run it's own thread for notifications (which was the default prior to SnowLeopard).
- // So tell the HAL to use its own thread for similar behavior under all supported versions of OSX.
- if (major == 10 && minor >= 6)
- {
- CFRunLoopRef theRunLoop = NULL;
- AudioObjectPropertyAddress theAddress = {
- kAudioHardwarePropertyRunLoop,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
- OSStatus theError = AudioObjectSetPropertyData(kAudioObjectSystemObject,
- &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
- if (theError != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioAE::constructor: kAudioHardwarePropertyRunLoop error.");
- }
- }
-}
-
-CCoreAudioAEHALOSX::~CCoreAudioAEHALOSX()
-{
- Deinitialize();
-
- delete m_audioGraph;
- delete m_AudioDevice;
- delete m_OutputStream;
-}
-
-bool CCoreAudioAEHALOSX::InitializePCM(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing, AudioDeviceID outputDevice, bool encoded)
-{
- if (m_audioGraph)
- m_audioGraph->Close(), delete m_audioGraph;
- m_audioGraph = new CCoreAudioGraph();
- if (!m_audioGraph)
- return false;
-
- AudioChannelLayoutTag layout = g_LayoutMap[ CSettings::Get().GetInt("audiooutput.channels") ];
- // force optical/coax to 2.0 output channels
- if (!m_Passthrough && CSettings::Get().GetInt("audiooutput.channels") == AE_CH_LAYOUT_2_0)
- layout = g_LayoutMap[1];
-
- if (!m_audioGraph->Open(pSource, format, outputDevice, allowMixing, layout, m_initVolume, encoded ))
- {
- CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::Initialize: "
- "Unable to initialize audio due a missconfiguration. Try 2.0 speaker configuration.");
- return false;
- }
-
- m_NumLatencyFrames = m_AudioDevice->GetNumLatencyFrames();
-
- m_allowMixing = allowMixing;
-
- return true;
-}
-
-bool CCoreAudioAEHALOSX::InitializePCMEncoded(ICoreAudioSource *pSource, AEAudioFormat &format, AudioDeviceID outputDevice)
-{
- // Prevent any other application from using this device.
- m_AudioDevice->SetHogStatus(true);
- // Try to disable mixing support. Effectiveness depends on the device.
- m_AudioDevice->SetMixingSupport(false);
- // Set the Sample Rate as defined by the spec.
- m_AudioDevice->SetNominalSampleRate((float)format.m_sampleRate);
-
- if (!InitializePCM(pSource, format, false, outputDevice, true))
- return false;
-
- return true;
-}
-
-bool CCoreAudioAEHALOSX::InitializeEncoded(AudioDeviceID outputDevice, AEAudioFormat &format)
-{
- std::string formatString;
- AudioStreamID outputStream = 0;
- AudioStreamBasicDescription outputFormat = {0};
-
- // Fetch a list of the streams defined by the output device
- UInt32 streamIndex = 0;
- AudioStreamIdList streams;
- m_AudioDevice->GetStreams(&streams);
-
- m_OutputBufferIndex = 0;
-
- while (!streams.empty())
- {
- // Get the next stream
- CCoreAudioStream stream;
- stream.Open(streams.front());
- streams.pop_front(); // We copied it, now we are done with it
-
- // Probe physical formats
- StreamFormatList physicalFormats;
- stream.GetAvailablePhysicalFormats(&physicalFormats);
- while (!physicalFormats.empty())
- {
- AudioStreamRangedDescription& desc = physicalFormats.front();
- CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::InitializeEncoded: "
- "Considering Physical Format: %s", StreamDescriptionToString(desc.mFormat, formatString));
-
- if (m_rawDataFormat == AE_FMT_LPCM || m_rawDataFormat == AE_FMT_DTSHD ||
- m_rawDataFormat == AE_FMT_TRUEHD || m_rawDataFormat == AE_FMT_EAC3)
- {
- // check pcm output formats
- unsigned int bps = CAEUtil::DataFormatToBits(AE_FMT_S16NE);
- if (desc.mFormat.mChannelsPerFrame == m_initformat.m_channelLayout.Count() &&
- desc.mFormat.mBitsPerChannel == bps &&
- desc.mFormat.mSampleRate == m_initformat.m_sampleRate )
- {
- outputFormat = desc.mFormat; // Select this format
- m_OutputBufferIndex = streamIndex;
- outputStream = stream.GetId();
- break;
- }
- }
- else
- {
- // check encoded formats
- if (desc.mFormat.mFormatID == kAudioFormat60958AC3 || desc.mFormat.mFormatID == 'IAC3')
- {
- if (desc.mFormat.mChannelsPerFrame == m_initformat.m_channelLayout.Count() &&
- desc.mFormat.mSampleRate == m_initformat.m_sampleRate )
- {
- outputFormat = desc.mFormat; // Select this format
- m_OutputBufferIndex = streamIndex;
- outputStream = stream.GetId();
- break;
- }
- }
- }
- physicalFormats.pop_front();
- }
-
- // TODO: How do we determine if this is the right stream (not just the right format) to use?
- if (outputFormat.mFormatID)
- break; // We found a suitable format. No need to continue.
- streamIndex++;
- }
-
- if (!outputFormat.mFormatID) // No match found
- {
- CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::InitializeEncoded: "
- "Unable to identify suitable output format.");
- return false;
- }
-
- CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::InitializeEncoded: "
- "Selected stream[%u] - id: 0x%04X, Physical Format: %s",
- m_OutputBufferIndex, (uint)outputStream, StreamDescriptionToString(outputFormat, formatString));
-
- // TODO: Auto hogging sets this for us. Figure out how/when to turn it off or use it
- // It appears that leaving this set will aslo restore the previous stream format when the
- // Application exits. If auto hogging is set and we try to set hog mode, we will deadlock
- // From the SDK docs: "If the AudioDevice is in a non-mixable mode, the HAL will automatically take hog mode on behalf of the first process to start an IOProc."
-
- // Lock down the device. This MUST be done PRIOR to switching to a non-mixable format, if it is done at all
- // If it is attempted after the format change, there is a high likelihood of a deadlock
- // We may need to do this sooner to enable mix-disable (i.e. before setting the stream format)
-
- // Auto-Hog does not always un-hog the device when changing back to a mixable mode.
- // Handle this on our own until it is fixed.
- CCoreAudioHardware::SetAutoHogMode(false);
- bool autoHog = CCoreAudioHardware::GetAutoHogMode();
- CLog::Log(LOGDEBUG, " CoreAudioRenderer::InitializeEncoded: "
- "Auto 'hog' mode is set to '%s'.", autoHog ? "On" : "Off");
- if (!autoHog) // Try to handle this ourselves
- {
- // Hog the device if it is not set to be done automatically
- m_AudioDevice->SetHogStatus(true);
- // Try to disable mixing. If we cannot, it may not be a problem
- m_AudioDevice->SetMixingSupport(false);
- }
-
- m_NumLatencyFrames = m_AudioDevice->GetNumLatencyFrames();
-
- // Configure the output stream object, this is the one we will keep
- m_OutputStream->Open(outputStream);
-
- AudioStreamBasicDescription virtualFormat;
- m_OutputStream->GetVirtualFormat(&virtualFormat);
- CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::InitializeEncoded: "
- "Previous Virtual Format: %s", StreamDescriptionToString(virtualFormat, formatString));
-
- AudioStreamBasicDescription previousPhysicalFormat;
- m_OutputStream->GetPhysicalFormat(&previousPhysicalFormat);
- CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::InitializeEncoded: "
- "Previous Physical Format: %s", StreamDescriptionToString(previousPhysicalFormat, formatString));
-
- // Set the active format (the old one will be reverted when we close)
- m_OutputStream->SetPhysicalFormat(&outputFormat);
- m_NumLatencyFrames += m_OutputStream->GetNumLatencyFrames();
-
- m_OutputStream->GetVirtualFormat(&virtualFormat);
- CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::InitializeEncoded: "
- "New Virtual Format: %s", StreamDescriptionToString(virtualFormat, formatString));
- CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::InitializeEncoded: "
- "New Physical Format: %s", StreamDescriptionToString(outputFormat, formatString));
-
- m_allowMixing = false;
-
- return true;
-}
-
-bool CCoreAudioAEHALOSX::Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume)
-{
- // Reset all the devices to a default 'non-hog' and mixable format.
- // If we don't do this we may be unable to find the Default Output device.
- // (e.g. if we crashed last time leaving it stuck in AC-3 mode)
-
- CCoreAudioHardware::ResetAudioDevices();
-
- m_ae = (CCoreAudioAE*)ae;
- if (!m_ae)
- return false;
-
- m_initformat = format;
- m_rawDataFormat = rawDataFormat;
- m_Passthrough = passThrough;
- m_encoded = false;
- m_OutputBufferIndex = 0;
- m_initVolume = initVolume;
-
- if (format.m_channelLayout.Count() == 0)
- {
- CLog::Log(LOGERROR, "CCoreAudioAEHALOSX::Initialize - "
- "Unable to open the requested channel layout");
- return false;
- }
-
- if (device.find("CoreAudio:") != std::string::npos)
- device.erase(0, strlen("CoreAudio:"));
-
- AudioDeviceID outputDevice = CCoreAudioHardware::FindAudioDevice(device);
- if (!outputDevice)
- {
- // Fall back to the default device if no match is found
- CLog::Log(LOGWARNING, "CCoreAudioAEHALOSX::Initialize: "
- "Unable to locate configured device, falling-back to the system default.");
- outputDevice = CCoreAudioHardware::GetDefaultOutputDevice();
- if (!outputDevice) // Not a lot to be done with no device. TODO: Should we just grab the first existing device?
- return false;
- }
-
- // Attach our output object to the device
- m_AudioDevice->Open(outputDevice);
- m_AudioDevice->SetHogStatus(false);
- m_AudioDevice->SetMixingSupport(true);
-
- // If this is a passthrough (AC3/DTS) stream, attempt to handle it natively
- if (m_Passthrough)
- m_encoded = InitializeEncoded(outputDevice, format);
-
- // If this is a PCM stream, or we failed to handle a passthrough stream natively,
- // prepare the standard interleaved PCM interface
- if (!m_encoded)
- {
- // If we are here and this is a passthrough stream, native handling failed.
- // Try to handle it as IEC61937 data over straight PCM (DD-Wav)
- bool configured = false;
- if (m_Passthrough)
- {
- CLog::Log(LOGDEBUG, "CCoreAudioAEHALOSX::Initialize: "
- "No suitable AC3 output format found. Attempting DD-Wav.");
- configured = InitializePCMEncoded(ae, format, outputDevice);
- }
- else
- {
- // Standard PCM data
- configured = InitializePCM(ae, format, true, outputDevice);
- }
-
- // No suitable output format was able to be configured
- if (!configured)
- return false;
- }
-
- m_Initialized = true;
-
- return true;
-}
-
-CAUOutputDevice *CCoreAudioAEHALOSX::DestroyUnit(CAUOutputDevice *outputUnit)
-{
- if (m_audioGraph && outputUnit)
- return m_audioGraph->DestroyUnit(outputUnit);
-
- return NULL;
-}
-
-CAUOutputDevice *CCoreAudioAEHALOSX::CreateUnit(ICoreAudioSource *pSource, AEAudioFormat &format)
-{
- CAUOutputDevice *outputUnit = NULL;
-
- // when HAL is using a mixer, the input is routed through converter units.
- // therefore we create a converter unit attach the source and give it back.
- if (m_allowMixing && m_audioGraph)
- {
- outputUnit = m_audioGraph->CreateUnit(format);
-
- if (pSource && outputUnit)
- outputUnit->SetInputSource(pSource);
- }
-
- return outputUnit;
-}
-
-void CCoreAudioAEHALOSX::Deinitialize()
-{
- if (!m_Initialized)
- return;
-
- Stop();
-
- if (m_encoded)
- m_AudioDevice->SetInputSource(NULL, 0, 0);
-
- if (m_audioGraph)
- m_audioGraph->SetInputSource(NULL);
-
- m_OutputStream->Close();
- m_AudioDevice->Close();
-
- if (m_audioGraph)
- {
- //m_audioGraph->Close();
- delete m_audioGraph;
- }
- m_audioGraph = NULL;
-
- m_NumLatencyFrames = 0;
- m_OutputBufferIndex = 0;
-
- m_Initialized = false;
- m_Passthrough = false;
-}
-
-void CCoreAudioAEHALOSX::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
-{
- CoreAudioDeviceList deviceList;
- CCoreAudioHardware::GetOutputDevices(&deviceList);
-
- devices.push_back(AEDevice("Default", "CoreAudio:default"));
-
- std::string deviceName;
- for (int i = 0; !deviceList.empty(); i++)
- {
- CCoreAudioDevice device(deviceList.front());
- deviceName = device.GetName();
-
- std::string deviceName_Internal = std::string("CoreAudio:");
- deviceName_Internal.append(deviceName);
- devices.push_back(AEDevice(deviceName, deviceName_Internal));
-
- deviceList.pop_front();
- }
-}
-
-void CCoreAudioAEHALOSX::Stop()
-{
- if (!m_Initialized)
- return;
-
- if (m_encoded)
- m_AudioDevice->Stop();
- else
- m_audioGraph->Stop();
-}
-
-bool CCoreAudioAEHALOSX::Start()
-{
- if (!m_Initialized)
- return false;
-
- if (m_encoded)
- m_AudioDevice->Start();
- else
- m_audioGraph->Start();
-
- return true;
-}
-
-void CCoreAudioAEHALOSX::SetDirectInput(ICoreAudioSource *pSource, AEAudioFormat &format)
-{
- if (!m_Initialized)
- return;
-
- // when HAL is initialized encoded we use directIO
- // when HAL is not in encoded mode and there is no mixer attach source the audio unit
- // when mixing is allowed in HAL, HAL is working with converter units where we attach the source.
-
- if (m_encoded)
- {
- // register directcallback for the audio HAL
- // direct render callback need to know the framesize and buffer index
- if (pSource)
- m_AudioDevice->SetInputSource(pSource, format.m_frameSize, m_OutputBufferIndex);
- else
- m_AudioDevice->SetInputSource(pSource, 0, 0);
- }
- else if (!m_encoded && !m_allowMixing)
- {
- // register render callback for the audio unit
- m_audioGraph->SetInputSource(pSource);
- }
-}
-
-double CCoreAudioAEHALOSX::GetDelay()
-{
- return (double)(m_NumLatencyFrames) / (m_initformat.m_sampleRate);
-}
-
-void CCoreAudioAEHALOSX::SetVolume(float volume)
-{
- if (m_encoded || m_Passthrough)
- return;
-
- m_audioGraph->SetCurrentVolume(volume);
-}
-
-unsigned int CCoreAudioAEHALOSX::GetBufferIndex()
-{
- return m_OutputBufferIndex;
-}
-
-#endif
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.h
deleted file mode 100644
index c96a4e1bfe..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHALOSX.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#if defined(TARGET_DARWIN_OSX)
-
-#include "ICoreAudioAEHAL.h"
-#include "ICoreAudioSource.h"
-
-#include <CoreAudio/CoreAudio.h>
-
-// Forward declarations
-class CCoreAudioAE;
-class CCoreAudioGraph;
-class CCoreAudioDevice;
-class CCoreAudioStream;
-
-class CAUOutputDevice;
-
-class CCoreAudioAEHALOSX : public ICoreAudioAEHAL
-{
-protected:
- CCoreAudioGraph *m_audioGraph;
- CCoreAudioDevice *m_AudioDevice;
- CCoreAudioStream *m_OutputStream;
- bool m_Initialized;
- bool m_Passthrough;
- AEAudioFormat m_initformat;
- bool m_allowMixing;
- bool m_encoded;
- AEDataFormat m_rawDataFormat;
- float m_initVolume;
-public:
- unsigned int m_NumLatencyFrames;
- unsigned int m_OutputBufferIndex;
- CCoreAudioAE *m_ae;
-
- CCoreAudioAEHALOSX();
- virtual ~CCoreAudioAEHALOSX();
-
- virtual bool InitializePCM(ICoreAudioSource *pSource, AEAudioFormat &format, bool allowMixing, AudioDeviceID outputDevice, bool encoded = false);
- virtual bool InitializePCMEncoded(ICoreAudioSource *pSource, AEAudioFormat &format, AudioDeviceID outputDevice);
- virtual bool InitializeEncoded(AudioDeviceID outputDevice, AEAudioFormat &format);
- virtual bool Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume);
- virtual void Deinitialize();
- virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough);
- virtual void SetDirectInput(ICoreAudioSource *pSource, AEAudioFormat &format);
- virtual void Stop();
- virtual bool Start();
- virtual double GetDelay();
- virtual void SetVolume(float volume);
- virtual unsigned int GetBufferIndex();
- virtual CAUOutputDevice* DestroyUnit(CAUOutputDevice *outputUnit);
- virtual CAUOutputDevice* CreateUnit(ICoreAudioSource *pSource, AEAudioFormat &format);
- virtual bool AllowMixing() { return m_allowMixing; }
-};
-
-#endif
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.cpp
deleted file mode 100644
index e57f26327a..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <samplerate.h>
-
-#include "CoreAudioAESound.h"
-
-#include "CoreAudioAE.h"
-#include "threads/SingleLock.h"
-#include "cores/AudioEngine/AEFactory.h"
-#include "cores/AudioEngine/Utils/AEAudioFormat.h"
-#include "cores/AudioEngine/Interfaces/AESound.h"
-#include "cores/AudioEngine/Utils/AEConvert.h"
-#include "cores/AudioEngine/Utils/AERemap.h"
-#include "cores/AudioEngine/Utils/AEUtil.h"
-#include "utils/log.h"
-#include "utils/EndianSwap.h"
-
-/* typecast AE to CCoreAudioAE */
-#define AE (*(CCoreAudioAE*)CAEFactory::GetEngine())
-
-CCoreAudioAESound::CCoreAudioAESound(const std::string &filename) :
- IAESound (filename),
- m_filename (filename),
- m_volume (1.0f ),
- m_inUse (0 )
-{
- m_wavLoader.Load(filename);
-}
-
-CCoreAudioAESound::~CCoreAudioAESound()
-{
- DeInitialize();
-}
-
-
-std::string CCoreAudioAESound::GetFileName()
-{
- return m_filename;
-}
-
-void CCoreAudioAESound::DeInitialize()
-{
-}
-
-bool CCoreAudioAESound::Initialize()
-{
- if (!m_wavLoader.IsValid())
- return false;
-
- return m_wavLoader.Initialize(
- AE.GetSampleRate (),
- AE.GetChannelLayout(),
- AE_CH_LAYOUT_INVALID
- );
-}
-
-void CCoreAudioAESound::SetVolume(float volume)
-{
- m_volume = std::max(0.0f, std::min(1.0f, volume));
-}
-
-float CCoreAudioAESound::GetVolume()
-{
- return m_volume;
-}
-
-unsigned int CCoreAudioAESound::GetSampleCount()
-{
- CSingleLock cs(m_critSection);
- if (m_wavLoader.IsValid())
- return m_wavLoader.GetSampleCount();
- return 0;
-}
-
-float* CCoreAudioAESound::GetSamples()
-{
- CSingleLock cs(m_critSection);
- if (!m_wavLoader.IsValid())
- return NULL;
-
- ++m_inUse;
- return m_wavLoader.GetSamples();
-}
-
-void CCoreAudioAESound::ReleaseSamples()
-{
- CSingleLock cs(m_critSection);
- if(m_inUse > 0)
- --m_inUse;
-}
-
-bool CCoreAudioAESound::IsPlaying()
-{
- CSingleLock cs(m_critSection);
- return (m_inUse > 0);
-}
-
-void CCoreAudioAESound::Play()
-{
- AE.PlaySound(this);
-}
-
-void CCoreAudioAESound::Stop()
-{
- AE.StopSound(this);
-}
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.h
deleted file mode 100644
index 68fdb2a801..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAESound.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "cores/AudioEngine/Interfaces/AESound.h"
-#include "cores/AudioEngine/Utils/AEWAVLoader.h"
-#include "threads/CriticalSection.h"
-
-class CCoreAudioAESound : public IAESound
-{
-public:
- CCoreAudioAESound(const std::string &filename);
- virtual ~CCoreAudioAESound();
-
- virtual std::string GetFileName();
- virtual void DeInitialize();
- virtual bool Initialize();
-
- virtual void Play();
- virtual void Stop();
- virtual bool IsPlaying();
-
- virtual void SetVolume(float volume);
- virtual float GetVolume();
-
- unsigned int GetSampleCount();
-
- /* ReleaseSamples must be called for each time GetSamples has been called */
- virtual float* GetSamples();
- void ReleaseSamples();
-
-private:
- CCriticalSection m_critSection;
- std::string m_filename;
- CAEWAVLoader m_wavLoader;
- float m_volume;
- int m_inUse;
-};
-
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp
deleted file mode 100644
index 581daf93ec..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.cpp
+++ /dev/null
@@ -1,921 +0,0 @@
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "system.h"
-
-#include "CoreAudioAE.h"
-#include "CoreAudioAEStream.h"
-
-#include "xbmc/cores/AudioEngine/Interfaces/AE.h"
-#include "xbmc/cores/AudioEngine/AEFactory.h"
-#include "xbmc/cores/AudioEngine/Utils/AEUtil.h"
-#include "xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.h"
-#include "settings/Settings.h"
-#include "threads/SingleLock.h"
-#include "settings/AdvancedSettings.h"
-#include "utils/MathUtils.h"
-#include "utils/log.h"
-
-
-
-// typecast AE to CCoreAudioAE
-#define AE (*(CCoreAudioAE*)CAEFactory::GetEngine())
-
-void CheckOutputBufferSize(void **buffer, int *oldSize, int newSize)
-{
- if (newSize > *oldSize)
- {
- if (*buffer)
- _aligned_free(*buffer);
- *buffer = _aligned_malloc(newSize, 16);
- *oldSize = newSize;
- }
- memset(*buffer, 0x0, *oldSize);
-}
-
-using namespace std;
-
-template <class AudioDataType>
-static inline void _Upmix(AudioDataType *input,
- unsigned int channelsInput, AudioDataType *output,
- unsigned int channelsOutput, unsigned int frames)
-{
- unsigned int unused = channelsOutput - channelsInput;
- AudioDataType *_input = input;
- AudioDataType *_output = output;
-
- for (unsigned int i = 0; i < frames; i++)
- {
- // get input channels
- for(unsigned int j = 0; j < channelsInput; j++)
- *_output++ = *_input++;
- // set unused channels
- for(unsigned int j = 0; j < unused; j++)
- *_output++ = 0;
- }
-}
-
-void CCoreAudioAEStream::Upmix(void *input,
- unsigned int channelsInput, void *output,
- unsigned int channelsOutput, unsigned int frames, AEDataFormat dataFormat)
-{
- // input channels must be less than output channels
- if (channelsInput >= channelsOutput)
- return;
-
- switch (CAEUtil::DataFormatToBits(dataFormat))
- {
- case 8: _Upmix ( (unsigned char *) input, channelsInput, (unsigned char *) output, channelsOutput, frames ); break;
- case 16: _Upmix ( (short *) input, channelsInput, (short *) output, channelsOutput, frames ); break;
- case 32: _Upmix ( (float *) input, channelsInput, (float *) output, channelsOutput, frames ); break;
- default: _Upmix ( (int *) input, channelsInput, (int *) output, channelsOutput, frames ); break;
- }
-}
-
-CCoreAudioAEStream::CCoreAudioAEStream(enum AEDataFormat dataFormat, unsigned int sampleRate, unsigned int encodedSamplerate, CAEChannelInfo channelLayout, unsigned int options, bool transcode) :
- m_outputUnit (NULL ),
- m_valid (false),
- m_delete (false),
- m_volume (1.0f ),
- m_rgain (1.0f ),
- m_slave (NULL ),
- m_convertFn (NULL ),
- m_Buffer (NULL ),
- m_convertBuffer (NULL ),
- m_ssrc (NULL ),
- m_draining (false),
- m_AvgBytesPerSec (0 ),
- m_audioCallback (NULL ),
- m_fadeRunning (false),
- m_frameSize (0 ),
- m_doRemap (true ),
- m_firstInput (true ),
- m_flushRequested (false),
- m_encoder (NULL )
-{
- m_ssrcData.data_out = NULL;
- m_transcode = transcode;
-
- if (!transcode)
- {
- m_rawDataFormat = dataFormat;
- m_StreamFormat.m_dataFormat = dataFormat;
- m_StreamFormat.m_sampleRate = sampleRate;
- m_StreamFormat.m_encodedRate = 0; //we don't support this
- m_StreamFormat.m_channelLayout = channelLayout;
- m_isRaw = COREAUDIO_IS_RAW(dataFormat);
- }
- else
- {
- m_rawDataFormat = AE_FMT_AC3;
- m_StreamFormat.m_dataFormat = AE_FMT_AC3;
- m_StreamFormat.m_sampleRate = 48000;
- m_StreamFormat.m_encodedRate = 0;
- enum AEChannel ac3Layout[3] = {AE_CH_RAW, AE_CH_RAW, AE_CH_NULL};
- m_StreamFormat.m_channelLayout = ac3Layout;
- m_isRaw = true;
-
- // setup encoder format
- m_encoderFormat.m_dataFormat = dataFormat;
- m_encoderFormat.m_sampleRate = sampleRate;
- m_encoderFormat.m_encodedRate = 0;
- m_encoderFormat.m_channelLayout = channelLayout;
- m_encoderFormat.m_frames = 0;
- m_encoderFormat.m_frameSamples = 0;
- m_encoderFormat.m_frameSize = 0;
- }
-
- m_incomingFormat = dataFormat;
- m_chLayoutCountStream = m_StreamFormat.m_channelLayout.Count();
- m_StreamFormat.m_frameSize = (CAEUtil::DataFormatToBits(m_rawDataFormat) >> 3) * m_chLayoutCountStream;
- m_OutputFormat = AE.GetAudioFormat();
- m_chLayoutCountOutput = m_OutputFormat.m_channelLayout.Count();
-
- //m_forceResample = (options & AESTREAM_FORCE_RESAMPLE) != 0;
- m_paused = (options & AESTREAM_PAUSED) != 0;
-
- m_vizRemapBufferSize = m_remapBufferSize = /*m_resampleBufferSize = */ m_upmixBufferSize = m_convertBufferSize = 16*1024;
- m_convertBuffer = (float *)_aligned_malloc(m_convertBufferSize,16);
- //m_resampleBuffer = (float *)_aligned_malloc(m_resampleBufferSize,16);
- m_upmixBuffer = (uint8_t *)_aligned_malloc(m_upmixBufferSize,16);
- m_remapBuffer = (uint8_t *)_aligned_malloc(m_remapBufferSize,16);
- m_vizRemapBuffer = (uint8_t *)_aligned_malloc(m_vizRemapBufferSize,16);
-
- m_limiter.SetSamplerate(AE.GetSampleRate());
-}
-
-CCoreAudioAEStream::~CCoreAudioAEStream()
-{
- CloseConverter();
-
- m_delete = true;
- m_valid = false;
-
- InternalFlush();
-
- _aligned_free(m_convertBuffer); m_convertBuffer = NULL;
- //_aligned_free(m_resampleBuffer); m_resampleBuffer = NULL;
- _aligned_free(m_remapBuffer); m_remapBuffer = NULL;
- _aligned_free(m_vizRemapBuffer); m_vizRemapBuffer = NULL;
- _aligned_free(m_upmixBuffer); m_upmixBuffer = NULL;
-
- delete m_Buffer; m_Buffer = NULL;
-
- delete m_encoder;
- m_encoder = NULL;
- ResetEncoder();
-
- m_unencodedBuffer.DeAlloc();
-
- /*
- if (m_resample)
- {
- _aligned_free(m_ssrcData.data_out);
- src_delete(m_ssrc);
- m_ssrc = NULL;
- }
- */
-
- CLog::Log(LOGDEBUG, "CCoreAudioAEStream::~CCoreAudioAEStream - Destructed");
-}
-
-void CCoreAudioAEStream::InitializeRemap()
-{
- if (!m_isRaw)
- {
- if (m_OutputFormat.m_channelLayout != AE.GetChannelLayout())
- {
- m_OutputFormat = AE.GetAudioFormat();
- m_chLayoutCountOutput = m_OutputFormat.m_channelLayout.Count();
- m_OutputBytesPerSample = (CAEUtil::DataFormatToBits(m_OutputFormat.m_dataFormat) >> 3);
-
- // re-init the remappers
- m_remap .Initialize(m_StreamFormat.m_channelLayout, m_OutputFormat.m_channelLayout, false);
- m_vizRemap.Initialize(m_StreamFormat.m_channelLayout, CAEChannelInfo(AE_CH_LAYOUT_2_0), false, true);
-
- InternalFlush();
- }
- }
-}
-
-void CCoreAudioAEStream::ReinitConverter()
-{
- CloseConverter();
- OpenConverter();
-}
-
-// The source logic is in the HAL. The only thing we have to do here
-// is to allocate the convrter and set the direct input call.
-void CCoreAudioAEStream::CloseConverter()
-{
- // we have a converter, delete it
- if (m_outputUnit)
- m_outputUnit = (CAUOutputDevice *) AE.GetHAL()->DestroyUnit(m_outputUnit);
-
- // it is save to unregister any direct input. the HAL takes care about it.
- AE.GetHAL()->SetDirectInput(NULL, m_OutputFormat);
-}
-
-void CCoreAudioAEStream::OpenConverter()
-{
- // we always allocate a converter
- // the HAL decides if we get converter.
- // if there is already a converter delete it.
- if (m_outputUnit)
- m_outputUnit = (CAUOutputDevice *) AE.GetHAL()->DestroyUnit(m_outputUnit);
-
- AEAudioFormat format = m_OutputFormat;
-
- format.m_sampleRate = m_StreamFormat.m_sampleRate;
- m_outputUnit = (CAUOutputDevice *) AE.GetHAL()->CreateUnit(this, format);
-
- // it is safe to register any direct input. the HAL takes care about it.
- AE.GetHAL()->SetDirectInput(this, m_OutputFormat);
-}
-
-void CCoreAudioAEStream::Initialize()
-{
- if (m_valid)
- InternalFlush();
-
- m_OutputFormat = AE.GetAudioFormat();
- m_chLayoutCountOutput = m_OutputFormat.m_channelLayout.Count();
-
- if (m_rawDataFormat == AE_FMT_LPCM)
- m_OutputBytesPerSample = (CAEUtil::DataFormatToBits(AE_FMT_FLOAT) >> 3);
- else
- m_OutputBytesPerSample = (CAEUtil::DataFormatToBits(m_OutputFormat.m_dataFormat) >> 3);
-
- if (m_isRaw || m_transcode)
- {
- // we are raw or transcode, which means we need to work in the output format
- if (m_rawDataFormat != AE_FMT_LPCM)
- {
- m_StreamFormat = AE.GetAudioFormat();
- m_chLayoutCountStream = m_StreamFormat.m_channelLayout.Count();
- }
- m_StreamBytesPerSample = (CAEUtil::DataFormatToBits(m_StreamFormat.m_dataFormat) >> 3);
- m_doRemap = false;
- }
- else
- {
- if (!m_chLayoutCountStream)
- {
- m_valid = false;
- return;
- }
- // Work around a bug in TrueHD and DTSHD deliver
- if (m_StreamFormat.m_dataFormat == AE_FMT_TRUEHD || m_StreamFormat.m_dataFormat == AE_FMT_DTSHD)
- m_StreamBytesPerSample = (CAEUtil::DataFormatToBits(AE_FMT_S16NE) >> 3);
- else
- m_StreamBytesPerSample = (CAEUtil::DataFormatToBits(m_StreamFormat.m_dataFormat) >> 3);
- m_StreamFormat.m_frameSize = m_StreamBytesPerSample * m_chLayoutCountStream;
- }
-
- if (!m_isRaw)
- {
- if (!m_remap.Initialize(m_StreamFormat.m_channelLayout, m_OutputFormat.m_channelLayout, false))
- {
- m_valid = false;
- return;
- }
-
- m_doRemap = m_chLayoutCountStream != 2;
-
- if (!m_vizRemap.Initialize(m_OutputFormat.m_channelLayout, CAEChannelInfo(AE_CH_LAYOUT_2_0), false, true))
- {
- m_valid = false;
- return;
- }
- }
-
- // only try to convert if we're not in AE_FMT_FLOAT and (we're not raw or we are transcoding)
- m_convert =
- (m_StreamFormat.m_dataFormat != AE_FMT_FLOAT && !m_isRaw)
- ||
- (m_incomingFormat != AE_FMT_FLOAT && m_transcode);
-
-
- //m_resample = false; //(m_StreamFormat.m_sampleRate != m_OutputFormat.m_sampleRate) && !m_isRaw;
-
- // if we need to convert, set it up
- if (m_convert)
- {
- // get the conversion function and allocate a buffer for the data
- CLog::Log(LOGDEBUG, "CCoreAudioAEStream::CCoreAudioAEStream - Converting from %s to AE_FMT_FLOAT", CAEUtil::DataFormatToStr(m_StreamFormat.m_dataFormat));
-
- if (!m_transcode)
- m_convertFn = CAEConvert::ToFloat(m_StreamFormat.m_dataFormat);
- else
- m_convertFn = CAEConvert::ToFloat(m_incomingFormat);
-
- if (!m_convertFn)
- m_valid = false;
- }
-
- // if we need to transcode, set it up
- if (m_transcode)
- {
- m_unencodedBuffer.Empty();
-
- if (!m_encoder || !m_encoder->IsCompatible(m_encoderFormat))
- SetupEncoder();
- }
-
- // if we need to resample, set it up
- /*
- if (m_resample)
- {
- int err;
- m_ssrc = src_new(SRC_SINC_MEDIUM_QUALITY, m_chLayoutCountStream, &err);
- m_ssrcData.src_ratio = (double)m_OutputFormat.m_sampleRate / (double)m_StreamFormat.m_sampleRate;
- m_ssrcData.data_in = m_convertBuffer;
- m_ssrcData.end_of_input = 0;
- }
- */
-
- // m_AvgBytesPerSec is calculated based on the output format.
- // we have to keep in mind that we convert our data to the output format
- m_AvgBytesPerSec = m_OutputFormat.m_frameSize * m_OutputFormat.m_sampleRate;
-
- delete m_Buffer;
- m_Buffer = new AERingBuffer(m_AvgBytesPerSec);
-
- m_fadeRunning = false;
-
- OpenConverter();
-
- m_valid = true;
-}
-
-void CCoreAudioAEStream::Destroy()
-{
- m_valid = false;
- m_delete = true;
- InternalFlush();
-}
-
-unsigned int CCoreAudioAEStream::AddData(void *data, unsigned int size)
-{
- unsigned int frames = size / m_StreamFormat.m_frameSize;
- unsigned int samples = size / m_StreamBytesPerSample;
- uint8_t *adddata = (uint8_t *)data;
- unsigned int addsize = size;
- unsigned int channelsInBuffer = m_chLayoutCountStream;
-
- if (m_flushRequested && m_paused)
- InternalFlush();
-
- if (!m_valid || size == 0 || data == NULL || !m_Buffer || m_flushRequested)
- return 0;
-
- // if the stream is draining
- if (m_draining)
- {
- // if the stream has finished draining, cork it
- if (m_Buffer && m_Buffer->GetReadSize() == 0)
- m_draining = false;
- else
- return 0;
- }
-
- // convert the data if we need to
- if (m_convert)
- {
- CheckOutputBufferSize((void **)&m_convertBuffer, &m_convertBufferSize, frames * channelsInBuffer * m_OutputBytesPerSample);
-
- samples = m_convertFn(adddata, size / m_StreamBytesPerSample, m_convertBuffer);
- frames = samples / channelsInBuffer;
- addsize = frames * channelsInBuffer * m_OutputBytesPerSample;
- adddata = (uint8_t *)m_convertBuffer;
- }
- else
- {
- samples = size / m_StreamBytesPerSample;
- adddata = (uint8_t *)data;
- addsize = size;
- }
-
- if (samples == 0)
- return 0;
-
- // transcode if we need to
- if (m_transcode && m_encoder)
- {
- // put adddata in the unencodedBuffer
- if (m_unencodedBuffer.Free() < addsize)
- m_unencodedBuffer.ReAlloc(m_unencodedBuffer.Used() + addsize);
-
- m_unencodedBuffer.Push(adddata, addsize);
-
- unsigned int block = m_encoderFormat.m_frames * m_encoderFormat.m_frameSize;
-
- // only try to encode if we have enough data
- if (m_unencodedBuffer.Used() >= block)
- {
- frames = m_encoder->Encode((float *)m_unencodedBuffer.Raw(block), m_encoderFormat.m_frames);
- m_unencodedBuffer.Shift(NULL, frames * m_encoderFormat.m_frameSize);
- addsize = m_encoder->GetData(&adddata);
- samples = addsize / m_OutputBytesPerSample;
- }
- else
- // return size here or whoever calling us will block if we return 0
- // we have essentially been successful, because we add the audio to our buffer to encode
- return size;
- }
-
- if (samples == 0)
- return 0;
-
-
- // resample it if we need to
- /*
- if (m_resample)
- {
- unsigned int resample_frames = samples / m_chLayoutCountStream;
-
- CheckOutputBufferSize((void **)&m_resampleBuffer, &m_resampleBufferSize,
- resample_frames * std::ceil(m_ssrcData.src_ratio) * sizeof(float) * 2);
-
- m_ssrcData.input_frames = resample_frames;
- m_ssrcData.output_frames = resample_frames * std::ceil(m_ssrcData.src_ratio);
- m_ssrcData.data_in = (float *)adddata;
- m_ssrcData.data_out = m_resampleBuffer;
-
- if (src_process(m_ssrc, &m_ssrcData) != 0)
- return 0;
-
- frames = m_ssrcData.output_frames_gen;
- samples = frames * m_chLayoutCountStream;
- adddata = (uint8_t *)m_ssrcData.data_out;
- }
- else
- {
- frames = samples / m_chLayoutCountStream;
- samples = frames * m_chLayoutCountStream;
- }
- */
-
- if (m_doRemap)
- {
- addsize = frames * m_OutputBytesPerSample * m_chLayoutCountOutput;
- CheckOutputBufferSize((void **)&m_remapBuffer, &m_remapBufferSize, addsize);
-
- // downmix/remap the data
- m_remap.Remap((float *)adddata, (float *)m_remapBuffer, frames);
- adddata = (uint8_t *)m_remapBuffer;
- channelsInBuffer = m_OutputFormat.m_channelLayout.Count();
- }
-
- // upmix the ouput to output channels
- if ( (!m_isRaw || m_rawDataFormat == AE_FMT_LPCM) && (m_chLayoutCountOutput > channelsInBuffer) )
- {
- CheckOutputBufferSize((void **)&m_upmixBuffer, &m_upmixBufferSize, frames * m_chLayoutCountOutput * sizeof(float));
- Upmix(adddata, channelsInBuffer, m_upmixBuffer, m_chLayoutCountOutput, frames, m_OutputFormat.m_dataFormat);
- adddata = m_upmixBuffer;
- addsize = frames * m_chLayoutCountOutput * sizeof(float);
- }
-
- unsigned int total_ms_sleep = 0;
- unsigned int room = m_Buffer->GetWriteSize();
- while (addsize > room && !m_paused && total_ms_sleep < 100)
- {
- // we got deleted
- if (!m_valid || !m_Buffer || m_draining )
- return 0;
-
- unsigned int ms_sleep_time = (1000 * room) / m_AvgBytesPerSec;
- if (ms_sleep_time == 0)
- ms_sleep_time++;
-
- // sleep until we have space (estimated) or 1ms min
- Sleep(ms_sleep_time);
- total_ms_sleep += ms_sleep_time;
-
- room = m_Buffer->GetWriteSize();
- }
-
- if (addsize > room)
- size = 0;
- else
- m_Buffer->Write(adddata, addsize);
-
- // still only return size to indicate success
- // we likely wrote something !size to m_Buffer, but our called doesn't realy care
- return size;
-}
-
-// this is only called on the context of the coreaudio thread!
-unsigned int CCoreAudioAEStream::GetFrames(uint8_t *buffer, unsigned int size)
-{
- // if we have been deleted
- if (!m_valid || m_delete || !m_Buffer || m_paused)
- return 0;
-
- if (m_flushRequested)
- {
- InternalFlush();
- return 0;
- }
-
- unsigned int readsize = std::min(m_Buffer->GetReadSize(), size);
- m_Buffer->Read(buffer, readsize);
-
- if (!m_isRaw)
- {
- float *floatBuffer = (float *)buffer;
- unsigned int samples = readsize / m_OutputBytesPerSample;
- unsigned int frames = samples / m_chLayoutCountOutput;
-
- // we have a frame, if we have a viz we need to hand the data to it.
- // Keep in mind that our buffer is already in output format.
- // So we remap output format to viz format !!!
- if (m_OutputFormat.m_dataFormat == AE_FMT_FLOAT)
- {
- // TODO : Why the hell is vizdata limited ?
- unsigned int samplesClamped = (samples > 512) ? 512 : samples;
- if (samplesClamped)
- {
- // Viz channel count is 2
- CheckOutputBufferSize((void **)&m_vizRemapBuffer, &m_vizRemapBufferSize, frames * 2 * sizeof(float));
-
- m_vizRemap.Remap(floatBuffer, (float*)m_vizRemapBuffer, frames);
- if (m_audioCallback)
- m_audioCallback->OnAudioData((float *)m_vizRemapBuffer, samplesClamped);
- }
- }
-
- // if we are fading
- if (m_fadeRunning)
- {
- // TODO: check if we correctly respect the amount of our blockoperation
- m_volume += (m_fadeStep * ((float)readsize / (float)m_OutputFormat.m_frameSize));
- m_volume = std::min(1.0f, std::max(0.0f, m_volume));
- if (m_fadeDirUp)
- {
- if (m_volume >= m_fadeTarget)
- m_fadeRunning = false;
- }
- else
- {
- if (m_volume <= m_fadeTarget)
- m_fadeRunning = false;
- }
- }
-
- if (m_volume < 1.0f)
- {
-#ifdef __SSE__
- CAEUtil::SSEMulArray(floatBuffer, m_volume, samples);
-#else
- for(unsigned int i = 0; i < samples; i++)
- floatBuffer[i] *= m_volume;
-#endif
- CAEUtil::ClampArray(floatBuffer, samples);
- }
- // apply volume amplification by using the sogt limiter
- // TODO - maybe reinvent the coreaudio compressor for this after frodo
- else if (GetAmplification() != 1.0f)
- {
- for(unsigned int i = 0; i < frames; i++)
- {
- int frameIdx = i*m_chLayoutCountOutput;
- float amplification = RunLimiter(&floatBuffer[frameIdx], m_chLayoutCountOutput);
- float *frameStart = &floatBuffer[frameIdx];
-#ifdef __SSE___
- CAEUtil::SSEMulArray(frameStart, amplification, m_chLayoutCountOutput);
-#else
- for(unsigned int n = 0; n < m_chLayoutCountOutput; n++)
- frameStart[n] *= amplification;
-#endif
-
- }
- }
- }
-
- return readsize;
-}
-
-const unsigned int CCoreAudioAEStream::GetFrameSize() const
-{
- return m_OutputFormat.m_frameSize;
-}
-
-unsigned int CCoreAudioAEStream::GetSpace()
-{
- if (!m_valid || m_draining)
- return 0;
-
- return m_Buffer->GetWriteSize() / m_OutputBytesPerSample * m_StreamBytesPerSample;
-}
-
-double CCoreAudioAEStream::GetDelay()
-{
- if (m_delete || !m_Buffer || m_flushRequested)
- return 0.0f;
-
- double delayBuffer = (double)(m_Buffer->GetReadSize()) / (double)m_AvgBytesPerSec;
- double delayTranscoder = 0.0;
-
- if (m_transcode)
- delayTranscoder = (double)(m_unencodedBuffer.Used()) / (double)(m_encoderFormat.m_frameSize * m_encoderFormat.m_sampleRate);
-
- return AE.GetDelay() + delayBuffer + delayTranscoder;
-}
-
-bool CCoreAudioAEStream::IsBuffering()
-{
- return (m_Buffer->GetReadSize() == 0 && m_unencodedBuffer.Used() == 0);
-}
-
-double CCoreAudioAEStream::GetCacheTime()
-{
- if (m_delete || !m_Buffer || m_flushRequested)
- return 0.0f;
- double delayBuffer = (double)(m_Buffer->GetReadSize()) / (double)m_AvgBytesPerSec;
- double delayTranscoder = 0.0;
-
- if (m_transcode)
- delayTranscoder = (double)(m_unencodedBuffer.Used()) / (double)(m_encoderFormat.m_frameSize * m_encoderFormat.m_sampleRate);
-
- return AE.GetDelay() + delayBuffer + delayTranscoder;
-}
-
-double CCoreAudioAEStream::GetCacheTotal()
-{
- if (m_delete || !m_Buffer)
- return 0.0f;
-
- return (double)m_Buffer->GetMaxSize() / (double)m_AvgBytesPerSec;
-}
-
-
-bool CCoreAudioAEStream::IsPaused()
-{
- return m_paused;
-}
-
-bool CCoreAudioAEStream::IsDraining()
-{
- return m_draining;
-}
-
-bool CCoreAudioAEStream::IsDestroyed()
-{
- return m_delete;
-}
-
-bool CCoreAudioAEStream::IsValid()
-{
- return m_valid;
-}
-
-void CCoreAudioAEStream::Pause()
-{
- m_paused = true;
-}
-
-void CCoreAudioAEStream::Resume()
-{
-#if defined(TARGET_DARWIN_IOS) && !defined(TARGET_DARWIN_IOS_ATV)
- if (CAEFactory::IsSuspended())
- CAEFactory::Resume();
-#endif
- m_paused = false;
-}
-
-void CCoreAudioAEStream::Drain(bool wait)
-{
- m_draining = true;
-}
-
-bool CCoreAudioAEStream::IsDrained()
-{
- return m_Buffer->GetReadSize() == 0;
-}
-
-void CCoreAudioAEStream::Flush()
-{
- if (m_Buffer)
- m_flushRequested = true;
-}
-
-float CCoreAudioAEStream::GetVolume()
-{
- return m_volume;
-}
-
-float CCoreAudioAEStream::GetReplayGain()
-{
- return m_rgain;
-}
-
-void CCoreAudioAEStream::SetVolume(float volume)
-{
- m_volume = std::max( 0.0f, std::min(1.0f, volume));
-}
-
-void CCoreAudioAEStream::SetReplayGain(float factor)
-{
- m_rgain = std::max(-1.0f, std::max(1.0f, factor));
-}
-
-void CCoreAudioAEStream::InternalFlush()
-{
- // reset the resampler
- /*
- if (m_resample) {
- m_ssrcData.end_of_input = 0;
- src_reset(m_ssrc);
- }
- */
-
- // Read the buffer empty to avoid Reset
- // Reset is not lock free.
- if (m_Buffer)
- {
- unsigned int readsize = m_Buffer->GetReadSize();
- if (readsize)
- {
- uint8_t *buffer = (uint8_t *)_aligned_malloc(readsize, 16);
- m_Buffer->Read(buffer, readsize);
- _aligned_free(buffer);
- }
-
- // if we are draining and are out of packets, tell the slave to resume
- if (m_draining && m_slave)
- {
- m_slave->Resume();
- m_slave = NULL;
- }
- }
-
- m_flushRequested = false;
- //if (m_Buffer)
- // m_Buffer->Reset();
-}
-
-const unsigned int CCoreAudioAEStream::GetChannelCount() const
-{
- return m_chLayoutCountStream;
-}
-
-const unsigned int CCoreAudioAEStream::GetSampleRate() const
-{
- return m_StreamFormat.m_sampleRate;
-}
-
-const unsigned int CCoreAudioAEStream::GetEncodedSampleRate() const
-{
- return m_StreamFormat.m_encodedRate;
-}
-
-const enum AEDataFormat CCoreAudioAEStream::GetDataFormat() const
-{
- return m_StreamFormat.m_dataFormat;
-}
-
-const bool CCoreAudioAEStream::IsRaw() const
-{
- return m_isRaw;
-}
-
-double CCoreAudioAEStream::GetResampleRatio()
-{
- /*
- if (!m_resample)
- return 1.0f;
-
- double ret = m_ssrcData.src_ratio;
- return ret;
- */
-
- return 1.0f;
-}
-
-bool CCoreAudioAEStream::SetResampleRatio(double ratio)
-{
- return false;
- /*
- if (!m_resample)
- return;
-
- src_set_ratio(m_ssrc, ratio);
- m_ssrcData.src_ratio = ratio;
- */
-}
-
-void CCoreAudioAEStream::RegisterAudioCallback(IAudioCallback* pCallback)
-{
- m_audioCallback = pCallback;
- if (m_audioCallback)
- m_audioCallback->OnInitialize(2, m_StreamFormat.m_sampleRate, 32);
-}
-
-void CCoreAudioAEStream::UnRegisterAudioCallback()
-{
- m_audioCallback = NULL;
-}
-
-void CCoreAudioAEStream::FadeVolume(float from, float target, unsigned int time)
-{
- if (m_isRaw)
- {
- m_fadeRunning = false;
- }
- else
- {
- float delta = target - from;
- m_fadeDirUp = target > from;
- m_fadeTarget = target;
- m_fadeStep = delta / (((float)m_OutputFormat.m_sampleRate / 1000.0f) * (float)time);
- m_fadeRunning = true;
- }
-}
-
-bool CCoreAudioAEStream::IsFading()
-{
- return m_fadeRunning;
-}
-
-void CCoreAudioAEStream::RegisterSlave(IAEStream *stream)
-{
- m_slave = stream;
-}
-
-OSStatus CCoreAudioAEStream::Render(AudioUnitRenderActionFlags* actionFlags,
- const AudioTimeStamp* pTimeStamp, UInt32 busNumber, UInt32 frameCount, AudioBufferList* pBufList)
-{
- OSStatus ret = OnRender(actionFlags, pTimeStamp, busNumber, frameCount, pBufList);
- return ret;
-}
-
-OSStatus CCoreAudioAEStream::OnRender(AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
-{
- // if we have no valid data output silence
- if (!m_valid || m_delete || !m_Buffer || m_firstInput || m_paused)
- {
- for (UInt32 i = 0; i < ioData->mNumberBuffers; i++)
- bzero(ioData->mBuffers[i].mData, ioData->mBuffers[i].mDataByteSize);
- if (ioActionFlags)
- *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
- m_firstInput = false;
- return noErr;
- }
-
- unsigned int size = inNumberFrames * m_OutputFormat.m_frameSize;
- //unsigned int size = inNumberFrames * m_StreamFormat.m_frameSize;
-
- // the index is important if we run encoded
- unsigned int outputBufferIndex = AE.GetHAL()->GetBufferIndex();
-
- ioData->mBuffers[outputBufferIndex].mDataByteSize = GetFrames(
- (uint8_t*)ioData->mBuffers[outputBufferIndex].mData, size);
- if (!ioData->mBuffers[outputBufferIndex].mDataByteSize && ioActionFlags)
- *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
-
- return noErr;
-}
-
-void CCoreAudioAEStream::ResetEncoder()
-{
- if (m_encoder)
- m_encoder->Reset();
- m_unencodedBuffer.Empty();
-}
-
-bool CCoreAudioAEStream::SetupEncoder()
-{
- ResetEncoder();
- delete m_encoder;
- m_encoder = NULL;
-
- if (!m_transcode)
- return false;
-
- m_encoder = new CAEEncoderFFmpeg();
- if (m_encoder && m_encoder->Initialize(m_encoderFormat))
- return true;
-
- delete m_encoder;
- m_encoder = NULL;
- return false;
-}
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.h
deleted file mode 100644
index ebb7201adf..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEStream.h
+++ /dev/null
@@ -1,189 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <samplerate.h>
-#include <list>
-
-#include "ICoreAudioSource.h"
-#include "cores/AudioEngine/Utils/AEAudioFormat.h"
-#include "cores/AudioEngine/Interfaces/AEStream.h"
-#include "cores/AudioEngine/Utils/AEConvert.h"
-#include "cores/AudioEngine/Utils/AERemap.h"
-#include "cores/AudioEngine/Utils/AELimiter.h"
-#include "cores/AudioEngine/Utils/AERingBuffer.h"
-#include "cores/AudioEngine/Utils/AEBuffer.h"
-
-#if defined(TARGET_DARWIN_IOS)
-# include "CoreAudioAEHALIOS.h"
-#else
-# include "CoreAudioAEHALOSX.h"
-#endif
-
-class AERingBuffer;
-class CoreAudioRingBuffer;
-class IAEEncoder;
-
-class CCoreAudioAEStream : public IAEStream, public ICoreAudioSource
-{
-protected:
- friend class CCoreAudioAE;
- CCoreAudioAEStream(enum AEDataFormat format, unsigned int sampleRate, unsigned int encodedSamplerate, CAEChannelInfo channelLayout, unsigned int options, bool transcode);
- virtual ~CCoreAudioAEStream();
-
- CAUOutputDevice *m_outputUnit;
-
-public:
- void ReinitConverter();
- void CloseConverter();
- void OpenConverter();
-
- void Initialize();
- void InitializeRemap();
- virtual void Destroy();
-
- virtual const unsigned int GetFrameSize() const;
- virtual unsigned int GetSpace();
- virtual unsigned int AddData(void *data, unsigned int size);
- unsigned int GetFrames(uint8_t *buffer, unsigned int size);
- virtual double GetDelay();
- virtual bool IsBuffering();
- virtual double GetCacheTime();
- virtual double GetCacheTotal();
-
- bool IsPaused();
- virtual bool IsDraining();
- virtual bool IsDrained();
- bool IsDestroyed();
- bool IsValid();
-
- virtual void Pause();
- virtual void Resume();
- virtual void Drain(bool wait);
- virtual void Flush();
-
- virtual float GetVolume();
- virtual float GetReplayGain();
- virtual float GetAmplification() { return m_limiter.GetAmplification(); }
- virtual void SetVolume(float volume);
- virtual void SetReplayGain(float factor);
- virtual void SetAmplification(float amplify){ m_limiter.SetAmplification(amplify); }
-
- virtual float RunLimiter(float* frame, int channels) { return m_limiter.Run(&frame, channels); }
-
- virtual const unsigned int GetChannelCount() const;
- virtual const unsigned int GetSampleRate() const;
- virtual const unsigned int GetEncodedSampleRate() const;
- virtual const enum AEDataFormat GetDataFormat() const;
- virtual const bool IsRaw() const;
-
- /* for dynamic sample rate changes (smoothvideo) */
- virtual double GetResampleRatio();
- virtual bool SetResampleRatio(double ratio);
-
- virtual void RegisterAudioCallback(IAudioCallback* pCallback);
- virtual void UnRegisterAudioCallback();
-
- virtual void FadeVolume(float from, float to, unsigned int time);
- virtual bool IsFading();
- virtual void RegisterSlave(IAEStream *stream);
-
- OSStatus Render(AudioUnitRenderActionFlags* actionFlags,
- const AudioTimeStamp* pTimeStamp,
- UInt32 busNumber,
- UInt32 frameCount,
- AudioBufferList* pBufList);
-
-private:
- void InternalFlush();
- void ResetEncoder();
- bool SetupEncoder();
-
- OSStatus OnRender(AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList *ioData);
-
- AEDataFormat m_rawDataFormat; /* the format we're output if we're outputting in raw mode */
- AEDataFormat m_incomingFormat; /* the format of the stream being sent to us */
-
- AEAudioFormat m_OutputFormat;
- unsigned int m_chLayoutCountOutput;
- AEAudioFormat m_StreamFormat;
- unsigned int m_chLayoutCountStream;
- unsigned int m_StreamBytesPerSample;
- unsigned int m_OutputBytesPerSample;
-
- //bool m_forceResample; /* true if we are to force resample even when the rates match */
- //bool m_resample; /* true if the audio needs to be resampled */
- bool m_transcode; /* true if we need to transcode to ac3 */
- bool m_convert; /* true if the bitspersample needs converting */
- bool m_valid; /* true if the stream is valid */
- bool m_delete; /* true if CCoreAudioAE is to free this object */
- CAERemap m_remap; /* the remapper */
- float m_volume; /* the volume level */
- float m_rgain; /* replay gain level */
- CAELimiter m_limiter; /* volume amplification/limiter*/
- IAEStream *m_slave; /* slave aestream */
-
- CAEConvert::AEConvertToFn m_convertFn;
-
- AERingBuffer *m_Buffer;
- float *m_convertBuffer; /* buffer for converted data */
- int m_convertBufferSize;
- //float *m_resampleBuffer; /* buffer for resample data */
- //int m_resampleBufferSize;
- uint8_t *m_upmixBuffer; /* buffer for remap data */
- int m_upmixBufferSize;
- uint8_t *m_remapBuffer; /* buffer for remap data */
- int m_remapBufferSize;
- uint8_t *m_vizRemapBuffer; /* buffer for remap data */
- int m_vizRemapBufferSize;
-
- SRC_STATE *m_ssrc;
- SRC_DATA m_ssrcData;
- bool m_paused;
- bool m_draining;
- unsigned int m_AvgBytesPerSec;
-
- /* vizualization internals */
- CAERemap m_vizRemap;
- IAudioCallback *m_audioCallback;
-
- /* fade values */
- bool m_fadeRunning;
- bool m_fadeDirUp;
- float m_fadeStep;
- float m_fadeTarget;
- unsigned int m_fadeTime;
- bool m_isRaw;
- unsigned int m_frameSize;
- bool m_doRemap;
- void Upmix(void *input, unsigned int channelsInput, void *output, unsigned int channelsOutput, unsigned int frames, AEDataFormat dataFormat);
- bool m_firstInput;
- bool m_flushRequested;
-
- /* the encoder */
- AEAudioFormat m_encoderFormat;
- IAEEncoder *m_encoder;
- CAEBuffer m_unencodedBuffer; /* this spools up the data before we encode it */
-};
-
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.cpp
deleted file mode 100644
index e55e3000f6..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.cpp
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "CoreAudioGraph.h"
-
-#include "CoreAudioAEHAL.h"
-#include "CoreAudioMixMap.h"
-#include "CoreAudioUnit.h"
-
-#include "utils/log.h"
-#include "utils/SystemInfo.h"
-
-CCoreAudioGraph::CCoreAudioGraph() :
- m_audioGraph (NULL ),
- m_inputUnit (NULL ),
- m_audioUnit (NULL ),
- m_mixerUnit (NULL ),
- m_initialized (false),
- m_deviceId (NULL ),
- m_allowMixing (false),
- m_mixMap (NULL )
-{
- for (int i = 0; i < MAX_CONNECTION_LIMIT; i++)
- {
- m_reservedBusNumber[i] = false;
- }
-}
-
-CCoreAudioGraph::~CCoreAudioGraph()
-{
- Close();
-
- delete m_mixMap;
-}
-
-bool CCoreAudioGraph::Open(ICoreAudioSource *pSource, AEAudioFormat &format,
- AudioDeviceID deviceId, bool allowMixing, AudioChannelLayoutTag layoutTag, float initVolume, bool encoded)
-{
- AudioStreamBasicDescription fmt = {0};
- AudioStreamBasicDescription inputFormat = {0};
- AudioStreamBasicDescription outputFormat = {0};
-
- m_deviceId = deviceId;
- m_allowMixing = allowMixing;
-
- OSStatus ret = NewAUGraph(&m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error create audio grpah. Error = %s", GetError(ret).c_str());
- return false;
- }
- ret = AUGraphOpen(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error open audio grpah. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- // get output unit
- if (m_audioUnit)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error audio unit already open. double call ?");
- return false;
- }
-
- m_audioUnit = new CAUOutputDevice();
- if (!m_audioUnit->Open(m_audioGraph,
- kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple))
- return false;
- m_audioUnit->SetBus(GetFreeBus());
-
- m_audioUnit->GetFormatDesc(format, &inputFormat, &fmt, encoded);
-
- if (!m_audioUnit->EnableInputOuput())
- return false;
-
- if (!m_audioUnit->SetCurrentDevice(deviceId))
- return false;
-
- SetCurrentVolume(initVolume);
-
- if (allowMixing)
- {
- delete m_mixMap;
- m_mixMap = CCoreAudioMixMap::CreateMixMap(m_audioUnit, format, layoutTag);
-
- if (m_mixMap && m_mixMap->IsValid())
- {
- // maximum input channel ber input bus
- //fmt.mChannelsPerFrame = MAXIMUM_MIXER_CHANNELS;
-
- // get output unit
- if (m_inputUnit)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?");
- return false;
- }
-
- m_inputUnit = new CAUOutputDevice();
-
- if (!m_inputUnit->Open(m_audioGraph,
- kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter, kAudioUnitManufacturer_Apple))
- return false;
-
- if (!m_inputUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus))
- return false;
-
- if (!m_inputUnit->SetFormat(&fmt, kAudioUnitScope_Output, kOutputBus))
- return false;
-
- // get mixer unit
- if (m_mixerUnit)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: Error mixer unit already open. double call ?");
- return false;
- }
-
- m_mixerUnit = new CAUMatrixMixer();
-
- if (!m_mixerUnit->Open(m_audioGraph,
- kAudioUnitType_Mixer, kAudioUnitSubType_MatrixMixer, kAudioUnitManufacturer_Apple))
- return false;
-
- // set number of input buses
- if (!m_mixerUnit->SetInputBusCount(MAX_CONNECTION_LIMIT))
- return false;
-
- // set number of output buses
- if (!m_mixerUnit->SetOutputBusCount(1))
- return false;
-
- if (!m_mixerUnit->SetInputBusFormat(MAX_CONNECTION_LIMIT, &fmt))
- return false;
-
- // Update format structure to reflect the desired format from the mixer
- // The output format of the mixer is identical to the input format, except for the channel count
- AudioStreamBasicDescription mixOutput(fmt);
- mixOutput.mChannelsPerFrame = m_mixMap->GetOutputChannels();
-
- if (!m_mixerUnit->SetFormat(&mixOutput, kAudioUnitScope_Output, kOutputBus))
- return false;
-
- ret = AUGraphConnectNodeInput(m_audioGraph, m_mixerUnit->GetNode(), 0, m_audioUnit->GetNode(), 0);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error connecting m_m_mixerNode. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_mixerUnit->SetBus(0);
-
- // configure output unit
- int busNumber = GetFreeBus();
-
- ret = AUGraphConnectNodeInput(m_audioGraph, m_inputUnit->GetNode(), 0, m_mixerUnit->GetNode(), busNumber);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error connecting m_converterNode. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_inputUnit->SetBus(busNumber);
-
- ret = AUGraphUpdate(m_audioGraph, NULL);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error update graph. Error = %s", GetError(ret).c_str());
- return false;
- }
- ret = AUGraphInitialize(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error initialize graph. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- UInt32 inputNumber = m_inputUnit->GetBus();
- int channelOffset = GetMixerChannelOffset(inputNumber);
- if (!CCoreAudioMixMap::SetMixingMatrix(m_mixerUnit, m_mixMap, &fmt, &mixOutput, channelOffset))
- return false;
-
- // Regenerate audio format and copy format for the Output AU
- outputFormat = mixOutput;
- }
- else
- {
- outputFormat = inputFormat;
- }
-
- }
- else
- {
- outputFormat = inputFormat;
- }
-
- if (!m_audioUnit->SetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus))
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error setting input format on audio device. Channel count %d, set it to %d",
- (int)outputFormat.mChannelsPerFrame, format.m_channelLayout.Count());
- outputFormat.mChannelsPerFrame = format.m_channelLayout.Count();
- if (!m_audioUnit->SetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus))
- return false;
- }
-
- std::string formatString;
- // asume we are in dd-wave mode
- if (!m_inputUnit)
- {
- if (!m_audioUnit->SetFormat(&inputFormat, kAudioUnitScope_Output, kInputBus))
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error setting Device Output Stream Format %s",
- StreamDescriptionToString(inputFormat, formatString));
- }
- }
-
- ret = AUGraphUpdate(m_audioGraph, NULL);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error update graph. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- AudioStreamBasicDescription inputDesc_end, outputDesc_end;
- m_audioUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
- m_audioUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kInputBus);
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::Open: audioUnit, Input Stream Format %s",
- StreamDescriptionToString(inputDesc_end, formatString));
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::Open: audioUnit, Output Stream Format %s",
- StreamDescriptionToString(outputDesc_end, formatString));
-
- if (m_mixerUnit)
- {
- m_mixerUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
- m_mixerUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus);
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::Open: mixerUnit, Input Stream Format %s",
- StreamDescriptionToString(inputDesc_end, formatString));
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::Open: mixerUnit, Output Stream Format %s",
- StreamDescriptionToString(outputDesc_end, formatString));
- }
-
- if (m_inputUnit)
- {
- m_inputUnit->GetFormat(&inputDesc_end, kAudioUnitScope_Input, kOutputBus);
- m_inputUnit->GetFormat(&outputDesc_end, kAudioUnitScope_Output, kOutputBus);
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::Open: inputUnit, Input Stream Format %s",
- StreamDescriptionToString(inputDesc_end, formatString));
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::Open: inputUnit, Output Stream Format %s",
- StreamDescriptionToString(outputDesc_end, formatString));
- }
-
- ret = AUGraphInitialize(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error initialize graph. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- UInt32 bufferFrames = m_audioUnit->GetBufferFrameSize();
- if (!m_audioUnit->SetMaxFramesPerSlice(bufferFrames))
- return false;
-
- SetInputSource(pSource);
-
- return Start();
-}
-
-bool CCoreAudioGraph::Close()
-{
- if (!m_audioGraph)
- return false;
-
- Stop();
-
- SetInputSource(NULL);
-
- while (!m_auUnitList.empty())
- {
- CAUOutputDevice *d = m_auUnitList.front();
- m_auUnitList.pop_front();
- ReleaseBus(d->GetBus());
- d->SetInputSource(NULL);
- d->Close();
- delete d;
- }
-
- if (m_inputUnit)
- {
- ReleaseBus(m_inputUnit->GetBus());
- m_inputUnit->Close();
- delete m_inputUnit;
- m_inputUnit = NULL;
- }
-
- if (m_mixerUnit)
- {
- m_mixerUnit->Close();
- delete m_mixerUnit;
- m_mixerUnit = NULL;
- }
-
- if (m_audioUnit)
- {
- m_audioUnit->Close();
- delete m_audioUnit;
- m_audioUnit = NULL;
- }
-
- OSStatus ret = AUGraphUninitialize(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Close: "
- "Error unitialize. Error = %s", GetError(ret).c_str());
- }
-
- ret = AUGraphClose(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Close: "
- "Error close. Error = %s", GetError(ret).c_str());
- }
-
- ret = DisposeAUGraph(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Close: "
- "Error dispose. Error = %s", GetError(ret).c_str());
- }
-
- return true;
-}
-
-bool CCoreAudioGraph::Start()
-{
- if (!m_audioGraph)
- return false;
-
- Boolean isRunning = false;
- OSStatus ret = AUGraphIsRunning(m_audioGraph, &isRunning);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Start: "
- "Audio graph not running. Error = %s", GetError(ret).c_str());
- return false;
- }
- if (!isRunning)
- {
- if (m_audioUnit)
- m_audioUnit->Start();
- if (m_mixerUnit)
- m_mixerUnit->Start();
- if (m_inputUnit)
- m_inputUnit->Start();
-
- ret = AUGraphStart(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Start: "
- "Error starting audio graph. Error = %s", GetError(ret).c_str());
- }
- }
-
- return true;
-}
-
-bool CCoreAudioGraph::Stop()
-{
- if (!m_audioGraph)
- return false;
-
- Boolean isRunning = false;
- OSStatus ret = AUGraphIsRunning(m_audioGraph, &isRunning);
- if (ret)
- {
- if (m_inputUnit)
- m_inputUnit->Stop();
- if (m_mixerUnit)
- m_mixerUnit->Stop();
- if (m_audioUnit)
- m_audioUnit->Stop();
-
- CLog::Log(LOGERROR, "CCoreAudioGraph::Stop: "
- "Audio graph not running. Error = %s", GetError(ret).c_str());
- return false;
- }
- if (isRunning)
- {
- ret = AUGraphStop(m_audioGraph);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Stop: "
- "Error stopping audio graph. Error = %s", GetError(ret).c_str());
- }
- }
-
- return true;
-}
-
-AudioChannelLayoutTag CCoreAudioGraph::GetChannelLayoutTag(int layout)
-{
- return g_LayoutMap[layout];
-}
-
-bool CCoreAudioGraph::SetInputSource(ICoreAudioSource* pSource)
-{
- if (m_inputUnit)
- return m_inputUnit->SetInputSource(pSource);
- else if (m_audioUnit)
- return m_audioUnit->SetInputSource(pSource);
-
- return false;
-}
-
-bool CCoreAudioGraph::SetCurrentVolume(Float32 vol)
-{
- if (!m_audioUnit)
- return false;
-
- return m_audioUnit->SetCurrentVolume(vol);
-}
-
-CAUOutputDevice *CCoreAudioGraph::DestroyUnit(CAUOutputDevice *outputUnit)
-{
- if (!outputUnit)
- return NULL;
-
- Stop();
-
- for (AUUnitList::iterator itt = m_auUnitList.begin(); itt != m_auUnitList.end(); ++itt)
- {
- if (*itt == outputUnit)
- {
- m_auUnitList.erase(itt);
- break;
- }
- }
-
- ReleaseBus(outputUnit->GetBus());
- outputUnit->SetInputSource(NULL);
- outputUnit->Close();
- delete outputUnit;
-
- AUGraphUpdate(m_audioGraph, NULL);
-
- Start();
-
- return NULL;
-}
-
-CAUOutputDevice *CCoreAudioGraph::CreateUnit(AEAudioFormat &format)
-{
- if (!m_audioUnit || !m_mixerUnit)
- return NULL;
-
- AudioStreamBasicDescription fmt = {0};
- AudioStreamBasicDescription inputFormat = {0};
- AudioStreamBasicDescription outputFormat = {0};
-
- int busNumber = GetFreeBus();
- if (busNumber == INVALID_BUS)
- return NULL;
-
- OSStatus ret;
- // create output unit
- CAUOutputDevice *outputUnit = new CAUOutputDevice();
- if (!outputUnit->Open(m_audioGraph,
- kAudioUnitType_FormatConverter, kAudioUnitSubType_AUConverter, kAudioUnitManufacturer_Apple))
- goto error;
-
- m_audioUnit->GetFormatDesc(format, &inputFormat, &fmt);
-
- // get the format frm the mixer
- if (!m_mixerUnit->GetFormat(&outputFormat, kAudioUnitScope_Input, kOutputBus))
- goto error;
-
- if (!outputUnit->SetFormat(&inputFormat, kAudioUnitScope_Input, kOutputBus))
- goto error;
-
- if (!outputUnit->SetFormat(&outputFormat, kAudioUnitScope_Output, kOutputBus))
- goto error;
-
- ret = AUGraphConnectNodeInput(m_audioGraph, outputUnit->GetNode(), 0, m_mixerUnit->GetNode(), busNumber);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::CreateUnit: "
- "Error connecting outputUnit. Error = %s", GetError(ret).c_str());
- goto error;
- }
-
- // TODO: setup mixmap, get free bus number for connection
-
- outputUnit->SetBus(busNumber);
-
- if (m_mixMap || m_mixMap->IsValid())
- {
- UInt32 inputNumber = outputUnit->GetBus();
- int channelOffset = GetMixerChannelOffset(inputNumber);
- CCoreAudioMixMap::SetMixingMatrix(m_mixerUnit, m_mixMap, &inputFormat, &fmt, channelOffset);
- }
-
- AUGraphUpdate(m_audioGraph, NULL);
- m_auUnitList.push_back(outputUnit);
-
- return outputUnit;
-
-error:
- delete outputUnit;
- return NULL;
-}
-
-int CCoreAudioGraph::GetFreeBus()
-{
- for (int i = 0; i < MAX_CONNECTION_LIMIT; i++)
- {
- if (!m_reservedBusNumber[i])
- {
- m_reservedBusNumber[i] = true;
- return i;
- }
- }
- return INVALID_BUS;
-}
-
-void CCoreAudioGraph::ReleaseBus(int busNumber)
-{
- if (busNumber > MAX_CONNECTION_LIMIT || busNumber < 0)
- return;
-
- m_reservedBusNumber[busNumber] = false;
-}
-
-bool CCoreAudioGraph::IsBusFree(int busNumber)
-{
- if (busNumber > MAX_CONNECTION_LIMIT || busNumber < 0)
- return false;
- return m_reservedBusNumber[busNumber];
-}
-
-int CCoreAudioGraph::GetMixerChannelOffset(int busNumber)
-{
- if (!m_mixerUnit)
- return 0;
-
- int offset = 0;
- AudioStreamBasicDescription fmt = {0};
-
- for (int i = 0; i < busNumber; i++)
- {
- memset(&fmt, 0x0, sizeof(fmt));
- m_mixerUnit->GetFormat(&fmt, kAudioUnitScope_Input, busNumber);
- offset += fmt.mChannelsPerFrame;
- }
- return offset;
-}
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.h
deleted file mode 100644
index d704ac6dfc..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioGraph.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "system.h"
-
-#if defined(TARGET_DARWIN_OSX)
-#include <list>
-
-#include "ICoreAudioSource.h"
-#include <AudioToolbox/AUGraph.h>
-#include <CoreAudio/CoreAudio.h>
-
-#define MAX_CONNECTION_LIMIT 8
-#define MAXIMUM_MIXER_CHANNELS 9
-
-class CAUMatrixMixer;
-class CAUOutputDevice;
-class CCoreAudioMixMap;
-
-class CCoreAudioGraph
-{
-public:
- CCoreAudioGraph();
- ~CCoreAudioGraph();
-
- bool Open(ICoreAudioSource *pSource, AEAudioFormat &format, AudioDeviceID deviceId,
- bool allowMixing, AudioChannelLayoutTag layoutTag, float initVolume, bool encoded);
- bool Close();
- bool Start();
- bool Stop();
- static AudioChannelLayoutTag GetChannelLayoutTag(int layout);
- bool SetInputSource(ICoreAudioSource *pSource);
- bool SetCurrentVolume(Float32 vol);
- CAUOutputDevice* DestroyUnit(CAUOutputDevice *outputUnit);
- CAUOutputDevice* CreateUnit(AEAudioFormat &format);
- int GetFreeBus();
- void ReleaseBus(int busNumber);
- bool IsBusFree(int busNumber);
- int GetMixerChannelOffset(int busNumber);
-
-private:
- AUGraph m_audioGraph;
-
- CAUOutputDevice *m_inputUnit;
- CAUOutputDevice *m_audioUnit;
- CAUMatrixMixer *m_mixerUnit;
-
- int m_reservedBusNumber[MAX_CONNECTION_LIMIT];
- bool m_initialized;
- AudioDeviceID m_deviceId;
- bool m_allowMixing;
- CCoreAudioMixMap *m_mixMap;
-
- typedef std::list<CAUOutputDevice*> AUUnitList;
- AUUnitList m_auUnitList;
-};
-
-#endif
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioMixMap.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioMixMap.cpp
deleted file mode 100644
index b045ed07de..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioMixMap.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "CoreAudioMixMap.h"
-
-#include "CoreAudioUnit.h"
-#include "CoreAudioAEHAL.h"
-#include "utils/log.h"
-
-
-#include <AudioToolbox/AudioToolbox.h>
-#include <sstream>
-
-CCoreAudioMixMap::CCoreAudioMixMap() :
- m_isValid(false)
-{
- m_pMap = (Float32*)calloc(sizeof(AudioChannelLayout), 1);
-}
-
-CCoreAudioMixMap::CCoreAudioMixMap(AudioChannelLayout& inLayout, AudioChannelLayout& outLayout) :
- m_isValid(false)
-{
- Rebuild(inLayout, outLayout);
-}
-
-CCoreAudioMixMap::~CCoreAudioMixMap()
-{
- free(m_pMap);
- m_pMap = NULL;
-}
-
-void CCoreAudioMixMap::Rebuild(AudioChannelLayout& inLayout, AudioChannelLayout& outLayout)
-{
- // map[in][out] = mix-level of input_channel[in] into output_channel[out]
-
- free(m_pMap);
- m_pMap = NULL;
-
- m_inChannels = CCoreAudioChannelLayout::GetChannelCountForLayout(inLayout);
- m_outChannels = CCoreAudioChannelLayout::GetChannelCountForLayout(outLayout);
-
- // Try to find a 'well-known' matrix
- const AudioChannelLayout* layouts[] = {&inLayout, &outLayout};
- UInt32 propSize = 0;
- AudioFormatGetPropertyInfo(kAudioFormatProperty_MatrixMixMap,
- sizeof(layouts), layouts, &propSize);
- m_pMap = (Float32*)calloc(1,propSize);
-
- // Try and get a predefined mixmap
- OSStatus ret = AudioFormatGetProperty(kAudioFormatProperty_MatrixMixMap,
- sizeof(layouts), layouts, &propSize, m_pMap);
- if (ret)
- {
- // If we for some reason don't find a predefined matrix let's build a diagonal matrix,
- // basically guessing here, but we need to have a mixmap that matches the output and input
- CLog::Log(LOGDEBUG, "CCoreAudioMixMap::CreateMap: No pre-defined mapping from %d to %d channels, building diagonal matrix.", m_inChannels, m_outChannels);
- for (UInt32 chan = 0; chan < std::min(m_inChannels, m_outChannels); ++chan)
- {
- Float32 *vol = m_pMap + (chan * m_outChannels + chan);
- CLog::Log(LOGDEBUG, "CCoreAudioMixMap::Rebuild %d = %f", chan, *vol);
- *vol = 1.;
- }
- }
- m_isValid = true;
-}
-
-CCoreAudioMixMap *CCoreAudioMixMap::CreateMixMap(CAUOutputDevice *audioUnit, AEAudioFormat &format, AudioChannelLayoutTag layoutTag)
-{
- if (!audioUnit)
- return NULL;
-
- AudioStreamBasicDescription fmt;
- AudioStreamBasicDescription inputFormat;
-
- // get the stream input format
- audioUnit->GetFormatDesc(format, &inputFormat, &fmt);
-
- unsigned int channels = format.m_channelLayout.Count();
- CAEChannelInfo channelLayout = format.m_channelLayout;
- bool hasLFE = false;
- // Convert XBMC input channel layout format to CoreAudio layout format
- AudioChannelLayout* pInLayout = (AudioChannelLayout*)malloc(sizeof(AudioChannelLayout) + sizeof(AudioChannelDescription) * channels);
- pInLayout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
- pInLayout->mChannelBitmap = 0;
- pInLayout->mNumberChannelDescriptions = channels;
- for (unsigned int chan=0; chan < channels; chan++)
- {
- AudioChannelDescription* pDesc = &pInLayout->mChannelDescriptions[chan];
- // Convert from XBMC channel tag to CoreAudio channel tag
- pDesc->mChannelLabel = g_LabelMap[(unsigned int)channelLayout[chan]];
- pDesc->mChannelFlags = kAudioChannelFlags_AllOff;
- pDesc->mCoordinates[0] = 0.0f;
- pDesc->mCoordinates[1] = 0.0f;
- pDesc->mCoordinates[2] = 0.0f;
- if (pDesc->mChannelLabel == kAudioChannelLabel_LFEScreen)
- hasLFE = true;
- }
- // HACK: Fix broken channel layouts coming from some aac sources
- // that include rear channel but no side channels.
- // 5.1 streams should include front and side channels.
- // Rear channels are added by 6.1 and 7.1, so any 5.1
- // source that claims to have rear channels is wrong.
- if (inputFormat.mChannelsPerFrame == 6 && hasLFE)
- {
- // Check for 5.1 configuration (as best we can without getting too silly)
- for (unsigned int chan=0; chan < inputFormat.mChannelsPerFrame; chan++)
- {
- AudioChannelDescription* pDesc = &pInLayout->mChannelDescriptions[chan];
- if (pDesc->mChannelLabel == kAudioChannelLabel_LeftSurround || pDesc->mChannelLabel == kAudioChannelLabel_RightSurround)
- break; // Required condition cannot be true
-
- if (pDesc->mChannelLabel == kAudioChannelLabel_LeftSurroundDirect)
- {
- // Change [Back Left] to [Side Left]
- pDesc->mChannelLabel = kAudioChannelLabel_LeftSurround;
- CLog::Log(LOGINFO, "CCoreAudioGraph::CreateMixMap: "
- "Detected faulty input channel map...fixing(Back Left-->Side Left)");
- }
- if (pDesc->mChannelLabel == kAudioChannelLabel_RightSurroundDirect)
- {
- // Change [Back Left] to [Side Left]
- pDesc->mChannelLabel = kAudioChannelLabel_RightSurround;
- CLog::Log(LOGINFO, "CCoreAudioGraph::CreateMixMap: "
- "Detected faulty input channel map...fixing(Back Right-->Side Right)");
- }
- }
- }
-
- CCoreAudioChannelLayout sourceLayout(*pInLayout);
- free(pInLayout);
- pInLayout = NULL;
-
- std::string strInLayout;
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::CreateMixMap: Source Stream Layout: %s",
- CCoreAudioChannelLayout::ChannelLayoutToString(*(AudioChannelLayout*)sourceLayout, strInLayout));
-
- // Get User-Configured (XBMC) Speaker Configuration
- AudioChannelLayout guiLayout;
- guiLayout.mChannelLayoutTag = layoutTag;
- CCoreAudioChannelLayout userLayout(guiLayout);
- std::string strUserLayout;
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::CreateMixMap: User-Configured Speaker Layout: %s",
- CCoreAudioChannelLayout::ChannelLayoutToString(*(AudioChannelLayout*)userLayout, strUserLayout));
-
- // Get OS-Configured (Audio MIDI Setup) Speaker Configuration (Channel Layout)
- CCoreAudioChannelLayout deviceLayout;
- if (!audioUnit->GetPreferredChannelLayout(deviceLayout))
- return NULL;
-
- // When all channels on the output device are unknown take the gui layout
- //if(deviceLayout.AllChannelUnknown())
- // deviceLayout.CopyLayout(guiLayout);
-
- std::string strOutLayout;
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::CreateMixMap: Output Device Layout: %s",
- CCoreAudioChannelLayout::ChannelLayoutToString(*(AudioChannelLayout*)deviceLayout, strOutLayout));
-
- // TODO:
- // Reconcile the OS and GUI layout configurations. Clamp to the minimum number of speakers
- // For each OS-defined output, see if it exists in the GUI configuration
- // If it does, add it to the 'union' layout (bitmap?)
- // User may have configured 5.1 in GUI, but only 2.0 in OS
- // Resulting layout would be {FL, FR}
- // User may have configured 2.0 in GUI, and 5.1 in OS
- // Resulting layout would be {FL, FR}
-
- // Correct any configuration incompatibilities
- //if (CCoreAudioChannelLayout::GetChannelCountForLayout(guiLayout) < CCoreAudioChannelLayout::GetChannelCountForLayout(deviceLayout))
- // deviceLayout.CopyLayout(guiLayout);
-
- // TODO: Skip matrix mixer if input/output are compatible
- CCoreAudioMixMap *mixMap = new CCoreAudioMixMap();
- mixMap->Rebuild(*sourceLayout, *(AudioChannelLayout*)deviceLayout);
- return mixMap;
-}
-
-bool CCoreAudioMixMap::SetMixingMatrix(CAUMatrixMixer *mixerUnit,
- CCoreAudioMixMap *mixMap, AudioStreamBasicDescription *inputFormat,
- AudioStreamBasicDescription *fmt, int channelOffset)
-{
- if (!mixerUnit || !inputFormat || !fmt)
- return false;
-
- // Fetch the mixing unit size
- UInt32 dims[2];
- UInt32 size = sizeof(dims);
- AudioUnitGetProperty(mixerUnit->GetUnit(),
- kAudioUnitProperty_MatrixDimensions, kAudioUnitScope_Global, 0, dims, &size);
-
- if(inputFormat->mChannelsPerFrame + channelOffset > dims[0])
- {
- CLog::Log(LOGERROR, "CCoreAudioMixMap::SetMixingMatrix - input format doesn't fit mixer size %u+%u > %u"
- , inputFormat->mChannelsPerFrame, channelOffset, dims[0]);
- return false;
- }
-
- if(fmt->mChannelsPerFrame > dims[1])
- {
- CLog::Log(LOGERROR, "CCoreAudioMixMap::SetMixingMatrix - ouput format doesn't fit mixer size %u > %u"
- , fmt->mChannelsPerFrame, dims[1]);
- return false;
- }
-
- if(fmt->mChannelsPerFrame < dims[1])
- {
- CLog::Log(LOGWARNING, "CCoreAudioMixMap::SetMixingMatrix - ouput format doesn't specify all outputs %u < %u"
- , fmt->mChannelsPerFrame, dims[1]);
- }
-
- // Configure the mixing matrix
- // The return from kAudioFormatProperty_MatrixMixMap (See Rebuild above)
- // is a Float32* which is laid out like this:
- //
- // mapping 2 chan -> 2 chan
- // 1 0 0 1
- //
- // or better represented in a tow dimensional array:
- //
- // 1 0
- // 0 1
- //
- // mapping 6 chan -> 6 chan:
- // 1 0 0 0 0 0
- // 0 1 0 0 0 0
- // 0 0 1 0 0 0
- // ....
-
- Float32* val = (Float32*)*mixMap;
- for (UInt32 i = 0; i < inputFormat->mChannelsPerFrame; ++i)
- {
- UInt32 j = 0;
- std::stringstream layoutStr;
- for (; j < fmt->mChannelsPerFrame; ++j)
- {
- Float32 *vol = val + (i * mixMap->m_outChannels + j);
- layoutStr << *vol << ", ";
- AudioUnitSetParameter(mixerUnit->GetUnit(),
- kMatrixMixerParam_Volume, kAudioUnitScope_Global, ( (i + channelOffset) << 16 ) | j, *vol, 0);
- }
- // zero out additional outputs from this input
- for (; j < dims[1]; ++j)
- {
- AudioUnitSetParameter(mixerUnit->GetUnit(),
- kMatrixMixerParam_Volume, kAudioUnitScope_Global, ( (i + channelOffset) << 16 ) | j, 0.0f, 0);
- layoutStr << "0, ";
- }
-
- CLog::Log(LOGDEBUG, "CCoreAudioMixMap::SetMixingMatrix channel %d = [%s]", i, layoutStr.str().c_str());
- }
-
- CLog::Log(LOGDEBUG, "CCoreAudioGraph::Open: "
- "Mixer Output Format: %d channels, %0.1f kHz, %d bits, %d bytes per frame",
- (int)fmt->mChannelsPerFrame, fmt->mSampleRate / 1000.0f, (int)fmt->mBitsPerChannel, (int)fmt->mBytesPerFrame);
-
- if (!mixerUnit->InitMatrixMixerVolumes())
- return false;
-
- return true;
-}
-
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioMixMap.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioMixMap.h
deleted file mode 100644
index a24de7f3ad..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioMixMap.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "system.h"
-
-#if defined(TARGET_DARWIN_OSX)
-
-#include "cores/AudioEngine/Utils/AEAudioFormat.h"
-
-#include <CoreAudio/CoreAudio.h>
-
-class CAUMatrixMixer;
-class CAUOutputDevice;
-
-class CCoreAudioMixMap
-{
-public:
- CCoreAudioMixMap();
- CCoreAudioMixMap(AudioChannelLayout& inLayout, AudioChannelLayout& outLayout);
- virtual ~CCoreAudioMixMap();
-
- operator Float32*() const {return m_pMap;}
-
- const Float32* GetBuffer() {return m_pMap;}
- UInt32 GetInputChannels() {return m_inChannels;}
- UInt32 GetOutputChannels() {return m_outChannels;}
- bool IsValid() {return m_isValid;}
- void Rebuild(AudioChannelLayout& inLayout, AudioChannelLayout& outLayout);
- static CCoreAudioMixMap *CreateMixMap(CAUOutputDevice *audioUnit,
- AEAudioFormat &format, AudioChannelLayoutTag layoutTag);
- static bool SetMixingMatrix(CAUMatrixMixer *mixerUnit, CCoreAudioMixMap *mixMap,
- AudioStreamBasicDescription *inputFormat, AudioStreamBasicDescription *fmt, int channelOffset);
-private:
- Float32 *m_pMap;
- UInt32 m_inChannels;
- UInt32 m_outChannels;
- bool m_isValid;
-};
-
-#endif
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.cpp b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.cpp
deleted file mode 100644
index 03b2fdce7c..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.cpp
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "CoreAudioUnit.h"
-
-#include "CoreAudioAEHAL.h"
-#include "cores/AudioEngine/Utils/AEUtil.h"
-#include "utils/log.h"
-
-#include <AudioToolbox/AUGraph.h>
-
-CCoreAudioUnit::CCoreAudioUnit() :
- m_pSource (NULL ),
- m_audioUnit (NULL ),
- m_audioNode (NULL ),
- m_audioGraph (NULL ),
- m_Initialized (false ),
- m_renderProc (NULL ),
- m_busNumber (INVALID_BUS )
-{
-}
-
-CCoreAudioUnit::~CCoreAudioUnit()
-{
- Close();
-}
-
-bool CCoreAudioUnit::Open(AUGraph audioGraph, AudioComponentDescription desc)
-{
- if (m_audioUnit)
- Close();
-
- OSStatus ret;
-
- m_Initialized = false;
-
- ret = AUGraphAddNode(audioGraph, &desc, &m_audioNode);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error add m_outputNode. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- ret = AUGraphNodeInfo(audioGraph, m_audioNode, 0, &m_audioUnit);
- if (ret)
- {
- CLog::Log(LOGERROR, "CCoreAudioGraph::Open: "
- "Error getting m_outputNode. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_audioGraph = audioGraph;
- m_Initialized = true;
-
- return true;
-}
-
-bool CCoreAudioUnit::Open(AUGraph audioGraph, OSType type, OSType subType, OSType manufacturer)
-{
- AudioComponentDescription desc = {0};
- desc.componentType = type;
- desc.componentSubType = subType;
- desc.componentManufacturer = manufacturer;
-
- return Open(audioGraph, desc);
-}
-
-void CCoreAudioUnit::Close()
-{
- if (!m_Initialized && !m_audioUnit)
- return;
-
- if (m_renderProc)
- SetInputSource(NULL);
-
- Stop();
-
- if (m_busNumber != INVALID_BUS)
- {
- OSStatus ret = AUGraphDisconnectNodeInput(m_audioGraph, m_audioNode, m_busNumber);
- if (ret && ret != kAUGraphErr_NodeNotFound)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::Close: "
- "Unable to disconnect AudioUnit. Error = %s", GetError(ret).c_str());
- }
-
- ret = AUGraphRemoveNode(m_audioGraph, m_audioNode);
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::Close: "
- "Unable to remove AudioUnit. Error = %s", GetError(ret).c_str());
- }
- }
-
- AUGraphUpdate(m_audioGraph, NULL);
-
- m_Initialized = false;
- m_audioUnit = NULL;
- m_audioNode = NULL;
- m_pSource = NULL;
-}
-
-bool CCoreAudioUnit::GetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus)
-{
- if (!m_audioUnit || !pDesc)
- return false;
-
- UInt32 size = sizeof(AudioStreamBasicDescription);
- OSStatus ret = AudioUnitGetProperty(m_audioUnit,
- kAudioUnitProperty_StreamFormat, scope, bus, pDesc, &size);
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetFormat: "
- "Unable to get AudioUnit format. Bus : %d Scope : %d : Error = %s",
- (int)bus, (int)scope, GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-bool CCoreAudioUnit::SetFormat(AudioStreamBasicDescription* pDesc, AudioUnitScope scope, AudioUnitElement bus)
-{
- if (!m_audioUnit || !pDesc)
- return false;
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit,
- kAudioUnitProperty_StreamFormat, scope, bus, pDesc, sizeof(AudioStreamBasicDescription));
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetFormat: "
- "Unable to set AudioUnit format. Bus : %d Scope : %d : Error = %s",
- (int)bus, (int)scope, GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-bool CCoreAudioUnit::SetMaxFramesPerSlice(UInt32 maxFrames)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit,
- kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFrames, sizeof(UInt32));
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetMaxFramesPerSlice: "
- "Unable to set AudioUnit max frames per slice. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-bool CCoreAudioUnit::GetSupportedChannelLayouts(AudioChannelLayoutList* pLayouts)
-{
- if (!m_audioUnit || !pLayouts)
- return false;
-
- UInt32 propSize = 0;
- Boolean writable = false;
- OSStatus ret = AudioUnitGetPropertyInfo(m_audioUnit,
- kAudioUnitProperty_SupportedChannelLayoutTags, kAudioUnitScope_Input, 0, &propSize, &writable);
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetSupportedChannelLayouts: "
- "Unable to retrieve supported channel layout property info. Error = %s", GetError(ret).c_str());
- return false;
- }
- UInt32 layoutCount = propSize / sizeof(AudioChannelLayoutTag);
- AudioChannelLayoutTag* pSuppLayouts = new AudioChannelLayoutTag[layoutCount];
- ret = AudioUnitGetProperty(m_audioUnit,
- kAudioUnitProperty_SupportedChannelLayoutTags, kAudioUnitScope_Output, 0, pSuppLayouts, &propSize);
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetSupportedChannelLayouts: "
- "Unable to retrieve supported channel layouts. Error = %s", GetError(ret).c_str());
- return false;
- }
- for (UInt32 layout = 0; layout < layoutCount; layout++)
- pLayouts->push_back(pSuppLayouts[layout]);
- delete[] pSuppLayouts;
- return true;
-}
-
-bool CCoreAudioUnit::SetInputSource(ICoreAudioSource* pSource)
-{
- m_pSource = pSource;
- if (pSource)
- return SetRenderProc();
- else
- return RemoveRenderProc();
-}
-
-bool CCoreAudioUnit::SetRenderProc()
-{
- if (!m_audioUnit || m_renderProc)
- return false;
-
- AURenderCallbackStruct callbackInfo;
- callbackInfo.inputProc = RenderCallback; // Function to be called each time the AudioUnit needs data
- callbackInfo.inputProcRefCon = this; // Pointer to be returned in the callback proc
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Input, 0, &callbackInfo, sizeof(AURenderCallbackStruct));
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetRenderProc: "
- "Unable to set AudioUnit render callback. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_renderProc = RenderCallback;
-
- return true;
-}
-
-bool CCoreAudioUnit::RemoveRenderProc()
-{
- if (!m_audioUnit || !m_renderProc)
- return false;
-
- AudioUnitInitialize(m_audioUnit);
-
- AURenderCallbackStruct callbackInfo;
- callbackInfo.inputProc = nil;
- callbackInfo.inputProcRefCon = nil;
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Input, 0, &callbackInfo, sizeof(AURenderCallbackStruct));
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::RemoveRenderProc: "
- "Unable to remove AudioUnit render callback. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_renderProc = NULL;
- Sleep(100);
-
- return true;
-}
-
-OSStatus CCoreAudioUnit::RenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
-{
- OSStatus ret = noErr;
- CCoreAudioUnit *audioUnit = (CCoreAudioUnit*)inRefCon;
-
- if (audioUnit->m_pSource)
- {
- ret = audioUnit->m_pSource->Render(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
- }
- else
- {
- ioData->mBuffers[0].mDataByteSize = 0;
- if (ioActionFlags)
- *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
- }
-
-
- return ret;
-}
-
-void CCoreAudioUnit::GetFormatDesc(AEAudioFormat format,
- AudioStreamBasicDescription *streamDesc, AudioStreamBasicDescription *coreaudioDesc, bool encoded)
-{
- unsigned int bps = CAEUtil::DataFormatToBits(format.m_dataFormat);
-
- // Set the input stream format for the AudioUnit
- // We use the default DefaultOuput AudioUnit, so we only can set the input stream format.
- // The autput format is automaticaly set to the input format.
- streamDesc->mFormatID = kAudioFormatLinearPCM; // Data encoding format
- streamDesc->mFormatFlags = kLinearPCMFormatFlagIsPacked;
- switch (format.m_dataFormat)
- {
- case AE_FMT_FLOAT:
- case AE_FMT_LPCM:
- streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
- streamDesc->mFormatFlags |= kAudioFormatFlagIsFloat;
- break;
- case AE_FMT_AC3:
- case AE_FMT_DTS:
- case AE_FMT_DTSHD:
- case AE_FMT_TRUEHD:
- case AE_FMT_EAC3:
- streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
- streamDesc->mFormatFlags |= kAudioFormatFlagsAudioUnitCanonical;
- break;
- case AE_FMT_S16LE:
- if (encoded)
- streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
- else
- streamDesc->mFormatFlags |= kAudioFormatFlagsAudioUnitCanonical;
- break;
- case AE_FMT_S16BE:
- streamDesc->mFormatFlags |= kAudioFormatFlagIsBigEndian;
- if (encoded)
- streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
- else
- streamDesc->mFormatFlags |= kAudioFormatFlagsAudioUnitCanonical;
- break;
- default:
- streamDesc->mFormatFlags |= kAudioFormatFlagsNativeEndian;
- if (encoded)
- streamDesc->mFormatFlags |= kAudioFormatFlagIsSignedInteger;
- else
- streamDesc->mFormatFlags |= kAudioFormatFlagsAudioUnitCanonical;
- break;
- }
- streamDesc->mChannelsPerFrame = format.m_channelLayout.Count(); // Number of interleaved audiochannels
- streamDesc->mSampleRate = (Float64)format.m_sampleRate; // the sample rate of the audio stream
- streamDesc->mBitsPerChannel = bps; // Number of bits per sample, per channel
- streamDesc->mBytesPerFrame = (bps>>3) * format.m_channelLayout.Count(); // Size of a frame == 1 sample per channel
- streamDesc->mFramesPerPacket = 1; // The smallest amount of indivisible data. Always 1 for uncompressed audio
- streamDesc->mBytesPerPacket = streamDesc->mBytesPerFrame * streamDesc->mFramesPerPacket;
- streamDesc->mReserved = 0;
-
- // Audio units use noninterleaved 32-bit floating point
- // linear PCM data for input and output, ...except in the
- // case of an audio unit that is a data format converter,
- // which converts to or from this format.
- coreaudioDesc->mFormatID = kAudioFormatLinearPCM;
- coreaudioDesc->mFormatFlags = kAudioFormatFlagsNativeEndian |
- kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved;
- switch (format.m_dataFormat)
- {
- case AE_FMT_FLOAT:
- coreaudioDesc->mFormatFlags |= kAudioFormatFlagIsFloat;
- default:
- coreaudioDesc->mFormatFlags |= kAudioFormatFlagsAudioUnitCanonical;
- break;
- }
- coreaudioDesc->mBitsPerChannel = bps; //sizeof(Float32)<<3;
- coreaudioDesc->mSampleRate = (Float64)format.m_sampleRate;;
- coreaudioDesc->mFramesPerPacket = 1;
- coreaudioDesc->mChannelsPerFrame = streamDesc->mChannelsPerFrame;
- coreaudioDesc->mBytesPerFrame = (bps>>3); //sizeof(Float32);
- coreaudioDesc->mBytesPerPacket = (bps>>3); //sizeof(Float32);
-}
-
-float CCoreAudioUnit::GetLatency()
-{
- if (!m_audioUnit)
- return 0.0f;
-
- Float64 latency;
- UInt32 size = sizeof(latency);
-
- OSStatus ret = AudioUnitGetProperty(m_audioUnit,
- kAudioUnitProperty_Latency, kAudioUnitScope_Global, 0, &latency, &size);
-
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetLatency: "
- "Unable to set AudioUnit latency. Error = %s", GetError(ret).c_str());
- return 0.0f;
- }
-
- return latency;
-}
-
-bool CCoreAudioUnit::Stop()
-{
- if (!m_audioUnit)
- return false;
-
- AudioOutputUnitStop(m_audioUnit);
-
- return true;
-}
-
-bool CCoreAudioUnit::Start()
-{
- if (!m_audioUnit)
- return false;
-
- AudioOutputUnitStart(m_audioUnit);
-
- return true;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// CAUOutputDevice
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-CAUOutputDevice::CAUOutputDevice() :
- m_DeviceId (NULL )
-{
-}
-
-CAUOutputDevice::~CAUOutputDevice()
-{
-}
-
-bool CAUOutputDevice::SetCurrentDevice(AudioDeviceID deviceId)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global, kOutputBus, &deviceId, sizeof(AudioDeviceID));
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetCurrentDevice: "
- "Unable to set current device. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- m_DeviceId = deviceId;
-
- return true;
-}
-
-bool CAUOutputDevice::GetChannelMap(CoreAudioChannelList* pChannelMap)
-{
- if (!m_audioUnit)
- return false;
-
- UInt32 size = 0;
- Boolean writable = false;
- AudioUnitGetPropertyInfo(m_audioUnit,
- kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 0, &size, &writable);
-
- UInt32 channels = size/sizeof(SInt32);
- SInt32* pMap = new SInt32[channels];
- OSStatus ret = AudioUnitGetProperty(m_audioUnit,
- kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 0, pMap, &size);
- if (ret != noErr)
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetInputChannelMap: "
- "Unable to retrieve AudioUnit input channel map. Error = %s", GetError(ret).c_str());
- else
- for (UInt32 i = 0; i < channels; i++)
- pChannelMap->push_back(pMap[i]);
- delete[] pMap;
- return (!ret);
-}
-
-bool CAUOutputDevice::SetChannelMap(CoreAudioChannelList* pChannelMap)
-{
- // The number of array elements must match the
- // number of output channels provided by the device
- if (!m_audioUnit || !pChannelMap)
- return false;
-
- UInt32 channels = pChannelMap->size();
- UInt32 size = sizeof(SInt32) * channels;
- SInt32* pMap = new SInt32[channels];
- for (UInt32 i = 0; i < channels; i++)
- pMap[i] = (*pChannelMap)[i];
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit,
- kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 0, pMap, size);
- if (ret != noErr)
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetBufferFrameSize: "
- "Unable to get current device's buffer size. Error = %s", GetError(ret).c_str());
- delete[] pMap;
- return (!ret);
-}
-
-Float32 CAUOutputDevice::GetCurrentVolume()
-{
- if (!m_audioUnit)
- return 0.0f;
-
- Float32 volPct = 0.0f;
- OSStatus ret = AudioUnitGetParameter(m_audioUnit,
- kHALOutputParam_Volume, kAudioUnitScope_Global, 0, &volPct);
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetCurrentVolume: "
- "Unable to get AudioUnit volume. Error = %s", GetError(ret).c_str());
- return 0.0f;
- }
- return volPct;
-}
-
-bool CAUOutputDevice::SetCurrentVolume(Float32 vol)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetParameter(m_audioUnit, kHALOutputParam_Volume,
- kAudioUnitScope_Global, 0, vol, 0);
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::SetCurrentVolume: "
- "Unable to set AudioUnit volume. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-UInt32 CAUOutputDevice::GetBufferFrameSize()
-{
- if (!m_audioUnit)
- return 0;
-
- UInt32 bufferSize = 0;
- UInt32 size = sizeof(UInt32);
-
- OSStatus ret = AudioUnitGetProperty(m_audioUnit,
- kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Input, 0, &bufferSize, &size);
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CCoreAudioUnit::GetBufferFrameSize: "
- "Unable to get current device's buffer size. Error = %s", GetError(ret).c_str());
- return 0;
- }
- return bufferSize;
-}
-
-bool CAUOutputDevice::EnableInputOuput()
-{
- if (!m_audioUnit)
- return false;
-
- UInt32 hasio;
- UInt32 size=sizeof(UInt32);
- OSStatus ret = AudioUnitGetProperty(m_audioUnit,
- kAudioOutputUnitProperty_HasIO,kAudioUnitScope_Input, 1, &hasio, &size);
-
- if (hasio)
- {
- UInt32 enable;
- enable = 0;
- ret = AudioUnitSetProperty(m_audioUnit,
- kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &enable, sizeof(enable));
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CAUOutputDevice::EnableInputOuput:: "
- "Unable to enable input on bus 1. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- enable = 1;
- ret = AudioUnitSetProperty(m_audioUnit,
- kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &enable, sizeof(enable));
- if (ret != noErr)
- {
- CLog::Log(LOGERROR, "CAUOutputDevice::EnableInputOuput:: "
- "Unable to disable output on bus 0. Error = %s", GetError(ret).c_str());
- return false;
- }
- }
-
- return true;
-}
-
-bool CAUOutputDevice::GetPreferredChannelLayout(CCoreAudioChannelLayout& layout)
-{
- if (!m_DeviceId)
- return false;
-
- AudioObjectPropertyAddress propertyAddress;
- propertyAddress.mScope = kAudioDevicePropertyScopeOutput;
- propertyAddress.mElement = 0;
- propertyAddress.mSelector = kAudioDevicePropertyPreferredChannelLayout;
- if (!AudioObjectHasProperty(m_DeviceId, &propertyAddress))
- return false;
-
- UInt32 propertySize = 0;
- OSStatus ret = AudioObjectGetPropertyDataSize(m_DeviceId, &propertyAddress, 0, NULL, &propertySize);
- if (ret != noErr)
- CLog::Log(LOGERROR, "CAUOutputDevice::GetPreferredChannelLayout: "
- "Unable to retrieve preferred channel layout size. Error = %s", GetError(ret).c_str());
-
- void *pBuf = malloc(propertySize);
- ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, pBuf);
- if (ret != noErr)
- CLog::Log(LOGERROR, "CAUOutputDevice::GetPreferredChannelLayout: "
- "Unable to retrieve preferred channel layout. Error = %s", GetError(ret).c_str());
- else
- {
- // Copy the result into the caller's instance
- layout.CopyLayout(*((AudioChannelLayout*)pBuf));
- }
- free(pBuf);
- return (ret == noErr);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// CAUMatrixMixer
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-CAUMatrixMixer::CAUMatrixMixer()
-{
-}
-
-CAUMatrixMixer::~CAUMatrixMixer()
-{
-}
-
-bool CAUMatrixMixer::InitMatrixMixerVolumes()
-{
- // Fetch thechannel configuration
- UInt32 dims[2];
- UInt32 size = sizeof(dims);
- OSStatus ret = AudioUnitGetProperty(m_audioUnit,
- kAudioUnitProperty_MatrixDimensions, kAudioUnitScope_Global, 0, dims, &size);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::Initialize:: "
- "Get matrix dimesion. Error = %s", GetError(ret).c_str());
- return false;
- }
-
- // Initialize global, input, and output levels
- if (!SetGlobalVolume(1.0f))
- return false;
- for (UInt32 i = 0; i < dims[0]; i++)
- if (!SetInputVolume(i, 1.0f))
- return false;
- for (UInt32 i = 0; i < dims[1]; i++)
- if (!SetOutputVolume(i, 1.0f))
- return false;
-
- return true;
-}
-
-UInt32 CAUMatrixMixer::GetInputBusCount()
-{
- if (!m_audioUnit)
- return 0;
-
- UInt32 busCount = 0;
- UInt32 size = sizeof(busCount);
- OSStatus ret = AudioUnitGetProperty(m_audioUnit,
- kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &busCount, &size);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::GetInputBusCount: "
- "Unable to get input bus count. Error = %s", GetError(ret).c_str());
- return 0;
- }
- return busCount;
-}
-
-bool CAUMatrixMixer::SetInputBusFormat(UInt32 busCount, AudioStreamBasicDescription *pFormat)
-{
- if (!m_audioUnit)
- return false;
-
- UInt32 enable = 1;
- for (UInt32 i = 0; i < busCount; i++)
- {
- AudioUnitSetParameter(m_audioUnit, kMatrixMixerParam_Enable, kAudioUnitScope_Input, i, enable, 0);
- if (!SetFormat(pFormat, kAudioUnitScope_Input, i))
- return false;
- }
-
- return true;
-}
-
-bool CAUMatrixMixer::SetInputBusCount(UInt32 busCount)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit,
- kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &busCount, sizeof(UInt32));
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::SetInputBusCount: "
- "Unable to set input bus count. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-UInt32 CAUMatrixMixer::GetOutputBusCount()
-{
- if (!m_audioUnit)
- return 0;
-
- UInt32 busCount = 0;
- UInt32 size = sizeof(busCount);
- OSStatus ret = AudioUnitGetProperty(m_audioUnit,
- kAudioUnitProperty_ElementCount, kAudioUnitScope_Output, 0, &busCount, &size);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::GetOutputBusCount: "
- "Unable to get output bus count. Error = %s", GetError(ret).c_str());
- return 0;
- }
- return busCount;
-}
-
-bool CAUMatrixMixer::SetOutputBusCount(UInt32 busCount)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetProperty(m_audioUnit,
- kAudioUnitProperty_BusCount, kAudioUnitScope_Output, 0, &busCount, sizeof(UInt32));
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::SetOutputBusCount: "
- "Unable to set output bus count. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-Float32 CAUMatrixMixer::GetGlobalVolume()
-{
- if (!m_audioUnit)
- return 0.0f;
-
- Float32 vol = 0.0f;
- OSStatus ret = AudioUnitGetParameter(m_audioUnit,
- kMatrixMixerParam_Volume, kAudioUnitScope_Global, 0xFFFFFFFF, &vol);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::GetGlobalVolume: "
- "Unable to get global volume. Error = %s", GetError(ret).c_str());
- return 0.0f;
- }
- return vol;
-}
-
-bool CAUMatrixMixer::SetGlobalVolume(Float32 vol)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetParameter(m_audioUnit,
- kMatrixMixerParam_Volume, kAudioUnitScope_Global, 0xFFFFFFFF, vol, 0);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::SetGlobalVolume: "
- "Unable to set global volume. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-Float32 CAUMatrixMixer::GetInputVolume(UInt32 element)
-{
- if (!m_audioUnit)
- return 0.0f;
-
- Float32 vol = 0.0f;
- OSStatus ret = AudioUnitGetParameter(m_audioUnit,
- kMatrixMixerParam_Volume, kAudioUnitScope_Input, element, &vol);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::GetInputVolume: "
- "Unable to get input volume. Error = %s", GetError(ret).c_str());
- return 0.0f;
- }
- return vol;
-}
-
-bool CAUMatrixMixer::SetInputVolume(UInt32 element, Float32 vol)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetParameter(m_audioUnit,
- kMatrixMixerParam_Volume, kAudioUnitScope_Input, element, vol, 0);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::SetInputVolume: "
- "Unable to set input volume. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
-Float32 CAUMatrixMixer::GetOutputVolume(UInt32 element)
-{
- if (!m_audioUnit)
- return 0.0f;
-
- Float32 vol = 0.0f;
- OSStatus ret = AudioUnitGetParameter(m_audioUnit,
- kMatrixMixerParam_Volume, kAudioUnitScope_Output, element, &vol);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::GetOutputVolume: "
- "Unable to get output volume. Error = %s", GetError(ret).c_str());
- return 0.0f;
- }
- return vol;
-}
-
-bool CAUMatrixMixer::SetOutputVolume(UInt32 element, Float32 vol)
-{
- if (!m_audioUnit)
- return false;
-
- OSStatus ret = AudioUnitSetParameter(m_audioUnit,
- kMatrixMixerParam_Volume, kAudioUnitScope_Output, element, vol, 0);
- if (ret)
- {
- CLog::Log(LOGERROR, "CAUMatrixMixer::SetOutputVolume: "
- "Unable to set output volume. Error = %s", GetError(ret).c_str());
- return false;
- }
- return true;
-}
-
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.h
deleted file mode 100644
index d300a18104..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioUnit.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "system.h"
-
-#if defined(TARGET_DARWIN_OSX)
-
-#define INVALID_BUS -1
-#define kOutputBus 0
-#define kInputBus 1
-
-#include "ICoreAudioSource.h"
-#include "CoreAudioChannelLayout.h"
-
-#include <AudioToolbox/AUGraph.h>
-#include <CoreAudio/CoreAudio.h>
-#include <CoreServices/CoreServices.h>
-
-class CCoreAudioUnit
-{
-public:
- CCoreAudioUnit();
- virtual ~CCoreAudioUnit();
-
- virtual bool Open(AUGraph audioGraph, AudioComponentDescription desc);
- virtual bool Open(AUGraph audioGraph, OSType type, OSType subType, OSType manufacturer);
- virtual void Close();
- virtual bool SetInputSource(ICoreAudioSource *pSource);
- virtual bool IsInitialized() {return m_Initialized;}
- virtual bool GetFormat(AudioStreamBasicDescription *pDesc, AudioUnitScope scope, AudioUnitElement bus);
- virtual bool SetFormat(AudioStreamBasicDescription *pDesc, AudioUnitScope scope, AudioUnitElement bus);
- virtual bool SetMaxFramesPerSlice(UInt32 maxFrames);
- virtual bool GetSupportedChannelLayouts(AudioChannelLayoutList* pLayouts);
- virtual void GetFormatDesc(AEAudioFormat format,
- AudioStreamBasicDescription *streamDesc, AudioStreamBasicDescription *coreaudioDesc, bool encoded = false);
- virtual float GetLatency();
- virtual bool Stop();
- virtual bool Start();
- virtual AudioUnit GetUnit (){return m_audioUnit;}
- virtual AUGraph GetGraph (){return m_audioGraph;}
- virtual AUNode GetNode (){return m_audioNode;}
- virtual int GetBus (){return m_busNumber;}
- virtual void SetBus (int busNumber){m_busNumber = busNumber;}
-
-protected:
- bool SetRenderProc();
- bool RemoveRenderProc();
- static OSStatus RenderCallback(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData);
-
- ICoreAudioSource* m_pSource;
- AudioUnit m_audioUnit;
- AUNode m_audioNode;
- AUGraph m_audioGraph;
- bool m_Initialized;
- AURenderCallback m_renderProc;
- int m_busNumber;
-};
-
-class CAUOutputDevice : public CCoreAudioUnit
-{
-public:
- CAUOutputDevice();
- virtual ~CAUOutputDevice();
-
- bool SetCurrentDevice(AudioDeviceID deviceId);
- bool GetChannelMap(CoreAudioChannelList *pChannelMap);
- bool SetChannelMap(CoreAudioChannelList *pChannelMap);
- UInt32 GetBufferFrameSize();
-
- Float32 GetCurrentVolume();
- bool SetCurrentVolume(Float32 vol);
- bool EnableInputOuput();
- virtual bool GetPreferredChannelLayout(CCoreAudioChannelLayout &layout);
-
-protected:
- AudioDeviceID m_DeviceId;
-};
-
-class CAUMatrixMixer : public CAUOutputDevice
-{
-public:
- CAUMatrixMixer();
- virtual ~CAUMatrixMixer();
-
- bool InitMatrixMixerVolumes();
-
- UInt32 GetInputBusCount();
- bool SetInputBusFormat(UInt32 busCount, AudioStreamBasicDescription *pFormat);
- bool SetInputBusCount(UInt32 busCount);
- UInt32 GetOutputBusCount();
- bool SetOutputBusCount(UInt32 busCount);
-
- Float32 GetGlobalVolume();
- bool SetGlobalVolume(Float32 vol);
- Float32 GetInputVolume(UInt32 element);
- bool SetInputVolume(UInt32 element, Float32 vol);
- Float32 GetOutputVolume(UInt32 element);
- bool SetOutputVolume(UInt32 element, Float32 vol);
-};
-
-#endif \ No newline at end of file
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioAEHAL.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioAEHAL.h
deleted file mode 100644
index 9c6936cbca..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioAEHAL.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "cores/AudioEngine/Utils/AEAudioFormat.h"
-#include "cores/AudioEngine/Interfaces/AE.h"
-#include "ICoreAudioSource.h"
-
-class ICoreAudioAEHAL;
-class CAUOutputDevice;
-
-/**
- * ICoreAudioAEHAL Interface
- */
-class ICoreAudioAEHAL
-{
-protected:
- ICoreAudioAEHAL() {}
- virtual ~ICoreAudioAEHAL() {}
-
-public:
- virtual bool Initialize(ICoreAudioSource *ae, bool passThrough, AEAudioFormat &format, AEDataFormat rawDataFormat, std::string &device, float initVolume) = 0;
- virtual void Deinitialize() = 0;
- virtual void EnumerateOutputDevices(AEDeviceList &devices, bool passthrough) = 0;
- //virtual CAUOutputDevice *DestroyUnit(CAUOutputDevice *outputUnit);
- //virtual CAUOutputDevice *CreateUnit(ICoreAudioSource *pSource, AEAudioFormat &format);
- //virtual void SetDirectInput(ICoreAudioSource *pSource, AEAudioFormat &format);
- virtual void Stop() = 0;
- virtual bool Start() = 0;
- virtual double GetDelay() = 0;
- virtual void SetVolume(float volume) = 0;
-};
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioSource.h b/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioSource.h
deleted file mode 100644
index 5930ec282b..0000000000
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/ICoreAudioSource.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2011-2013 Team XBMC
- * http://xbmc.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with XBMC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <AudioUnit/AudioUnit.h>
-
-#include "cores/AudioEngine/Utils/AEAudioFormat.h"
-#include "cores/AudioEngine/Interfaces/AE.h"
-#include "utils/StdString.h"
-
-class ICoreAudioSource;
-
-/**
- * ICoreAudioSource Interface
- */
-class ICoreAudioSource
-{
-private:
- std::string m_inputName;
- AudioUnitElement m_inputBus;
-public:
- // Function to request rendered data from a data source
- virtual OSStatus Render(AudioUnitRenderActionFlags* actionFlags,
- const AudioTimeStamp* pTimeStamp,
- UInt32 busNumber,
- UInt32 frameCount,
- AudioBufferList* pBufList) = 0;
- //std::string InputName() { return m_inputName; };
- //void InputName(std::string inputName) { m_inputName = inputName; };
-
- //AudioUnitElement InputBus() { return m_inputBus; };
- //void InputBus(AudioUnitElement inputBus) { m_inputBus = m_inputBus; };
-};
diff --git a/xbmc/cores/AudioEngine/Makefile.in b/xbmc/cores/AudioEngine/Makefile.in
index 3815a16bcb..c22c87e874 100644
--- a/xbmc/cores/AudioEngine/Makefile.in
+++ b/xbmc/cores/AudioEngine/Makefile.in
@@ -20,21 +20,6 @@ CXXFLAGS += -D__STDC_LIMIT_MACROS
SRCS = AEFactory.cpp
-ifeq ($(findstring osx,@ARCH@),osx)
-SRCS += Engines/CoreAudio/CoreAudioAE.cpp
-SRCS += Engines/CoreAudio/CoreAudioAEHAL.cpp
-SRCS += Engines/CoreAudio/CoreAudioAEHALOSX.cpp
-SRCS += Engines/CoreAudio/CoreAudioAESound.cpp
-SRCS += Engines/CoreAudio/CoreAudioAEStream.cpp
-SRCS += Engines/CoreAudio/CoreAudioChannelLayout.cpp
-SRCS += Engines/CoreAudio/CoreAudioDevice.cpp
-SRCS += Engines/CoreAudio/CoreAudioGraph.cpp
-SRCS += Engines/CoreAudio/CoreAudioHardware.cpp
-SRCS += Engines/CoreAudio/CoreAudioMixMap.cpp
-SRCS += Engines/CoreAudio/CoreAudioStream.cpp
-SRCS += Engines/CoreAudio/CoreAudioUnit.cpp
-else
-
SRCS += AESinkFactory.cpp
SRCS += Sinks/AESinkNULL.cpp
SRCS += Sinks/AESinkProfiler.cpp
@@ -50,6 +35,15 @@ SRCS += Engines/ActiveAE/ActiveAEBuffer.cpp
ifeq (@USE_ANDROID@,1)
SRCS += Sinks/AESinkAUDIOTRACK.cpp
+else ifeq ($(findstring ios,@ARCH@),ios)
+SRCS += Sinks/AESinkDARWINIOS.cpp
+else ifeq ($(findstring osx,@ARCH@),osx)
+SRCS += Sinks/AESinkDARWINOSX.cpp
+SRCS += Sinks/osx/CoreAudioChannelCount.cpp
+SRCS += Sinks/osx/CoreAudioDevice.cpp
+SRCS += Sinks/osx/CoreAudioHardware.cpp
+SRCS += Sinks/osx/CoreAudioHelpers.cpp
+SRCS += Sinks/osx/CoreAudioStream.cpp
else
SRCS += Sinks/AESinkALSA.cpp
SRCS += Sinks/AESinkOSS.cpp
@@ -57,7 +51,6 @@ ifeq (@USE_PULSE@,1)
SRCS += Sinks/AESinkPULSE.cpp
endif
endif
-endif
SRCS += Utils/AEChannelInfo.cpp
SRCS += Utils/AEBuffer.cpp
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.cpp
new file mode 100644
index 0000000000..fa49cba2fb
--- /dev/null
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.cpp
@@ -0,0 +1,780 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "cores/AudioEngine/Sinks/AESinkDARWINIOS.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
+#include "cores/AudioEngine/Utils/AERingBuffer.h"
+#include "cores/AudioEngine/Sinks/osx/CoreAudioHelpers.h"
+#include "osx/DarwinUtils.h"
+#include "utils/log.h"
+#include "utils/StringUtils.h"
+#include "threads/Condition.h"
+#include "windowing/WindowingFactory.h"
+
+#include <sstream>
+#include <AudioToolbox/AudioToolbox.h>
+
+#define CA_MAX_CHANNELS 8
+static enum AEChannel CAChannelMap[CA_MAX_CHANNELS + 1] = {
+ AE_CH_FL , AE_CH_FR , AE_CH_BL , AE_CH_BR , AE_CH_FC , AE_CH_LFE , AE_CH_SL , AE_CH_SR ,
+ AE_CH_NULL
+};
+
+/***************************************************************************************/
+/***************************************************************************************/
+#if DO_440HZ_TONE_TEST
+static void SineWaveGeneratorInitWithFrequency(SineWaveGenerator *ctx, double frequency, double samplerate)
+{
+ // Given:
+ // frequency in cycles per second
+ // 2*PI radians per sine wave cycle
+ // sample rate in samples per second
+ //
+ // Then:
+ // cycles radians seconds radians
+ // ------ * ------- * ------- = -------
+ // second cycle sample sample
+ ctx->currentPhase = 0.0;
+ ctx->phaseIncrement = frequency * 2*M_PI / samplerate;
+}
+
+static int16_t SineWaveGeneratorNextSampleInt16(SineWaveGenerator *ctx)
+{
+ int16_t sample = INT16_MAX * sinf(ctx->currentPhase);
+
+ ctx->currentPhase += ctx->phaseIncrement;
+ // Keep the value between 0 and 2*M_PI
+ while (ctx->currentPhase > 2*M_PI)
+ ctx->currentPhase -= 2*M_PI;
+
+ return sample / 4;
+}
+static float SineWaveGeneratorNextSampleFloat(SineWaveGenerator *ctx)
+{
+ float sample = MAXFLOAT * sinf(ctx->currentPhase);
+
+ ctx->currentPhase += ctx->phaseIncrement;
+ // Keep the value between 0 and 2*M_PI
+ while (ctx->currentPhase > 2*M_PI)
+ ctx->currentPhase -= 2*M_PI;
+
+ return sample / 4;
+}
+#endif
+
+/***************************************************************************************/
+/***************************************************************************************/
+class CAAudioUnitSink
+{
+ public:
+ CAAudioUnitSink();
+ ~CAAudioUnitSink();
+
+ bool open(AudioStreamBasicDescription outputFormat);
+ bool close();
+ bool play(bool mute);
+ bool mute(bool mute);
+ bool pause();
+ void drain();
+ double getDelay();
+ double cacheSize();
+ unsigned int write(uint8_t *data, unsigned int byte_count);
+ unsigned int chunkSize() { return m_bufferDuration * m_sampleRate; }
+ unsigned int getRealisedSampleRate() { return m_outputFormat.mSampleRate; }
+ static Float64 getCoreAudioRealisedSampleRate();
+
+ private:
+ void setCoreAudioBuffersize();
+ bool setCoreAudioInputFormat();
+ void setCoreAudioPreferredSampleRate();
+ bool setupAudio();
+ bool checkAudioRoute();
+ bool checkSessionProperties();
+ bool activateAudioSession();
+ void deactivateAudioSession();
+
+ // callbacks
+ 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;
+ AERingBuffer *m_buffer;
+
+ bool m_mute;
+ Float32 m_outputVolume;
+ Float32 m_outputLatency;
+ Float32 m_bufferDuration;
+
+ unsigned int m_sampleRate;
+ unsigned int m_frameSize;
+ unsigned int m_frames;
+
+ bool m_playing;
+ bool m_playing_saved;
+ volatile bool m_started;
+};
+
+CAAudioUnitSink::CAAudioUnitSink()
+: m_initialized(false)
+, m_activated(false)
+, m_buffer(NULL)
+, m_playing(false)
+, m_playing_saved(false)
+, m_started(false)
+{
+}
+
+CAAudioUnitSink::~CAAudioUnitSink()
+{
+ close();
+}
+
+bool CAAudioUnitSink::open(AudioStreamBasicDescription outputFormat)
+{
+ m_mute = false;
+ m_setup = false;
+ m_outputFormat = outputFormat;
+ m_outputLatency = 0.0;
+ m_bufferDuration= 0.0;
+ m_outputVolume = 1.0;
+ m_sampleRate = (unsigned int)outputFormat.mSampleRate;
+ m_frameSize = outputFormat.mChannelsPerFrame * outputFormat.mBitsPerChannel / 8;
+
+ /* TODO: Reduce the size of this buffer, pre-calculate the size based on how large
+ the buffers are that CA calls us with in the renderCallback - perhaps call
+ the checkSessionProperties() before running this? */
+ m_buffer = new AERingBuffer(16384);
+
+ return setupAudio();
+}
+
+bool CAAudioUnitSink::close()
+{
+ deactivateAudioSession();
+
+ delete m_buffer;
+ m_buffer = NULL;
+
+ m_started = false;
+ return true;
+}
+
+bool CAAudioUnitSink::play(bool mute)
+{
+ if (!m_playing)
+ {
+ if (activateAudioSession())
+ {
+ CAAudioUnitSink::mute(mute);
+ m_playing = !AudioOutputUnitStart(m_audioUnit);
+ }
+ }
+
+ return m_playing;
+}
+
+bool CAAudioUnitSink::mute(bool mute)
+{
+ m_mute = mute;
+
+ return true;
+}
+
+bool CAAudioUnitSink::pause()
+{
+ if (m_playing)
+ m_playing = AudioOutputUnitStop(m_audioUnit);
+
+ return m_playing;
+}
+
+double CAAudioUnitSink::getDelay()
+{
+ double delay = (double)m_buffer->GetReadSize() / m_frameSize;
+ delay /= m_sampleRate;
+ delay += m_bufferDuration + m_outputLatency;
+
+ return delay;
+}
+
+double CAAudioUnitSink::cacheSize()
+{
+ return (double)m_buffer->GetMaxSize() / (double)(m_frameSize * m_sampleRate);
+}
+
+CCriticalSection mutex;
+XbmcThreads::ConditionVariable condVar;
+
+unsigned int CAAudioUnitSink::write(uint8_t *data, unsigned int frames)
+{
+ if (m_buffer->GetWriteSize() < frames * m_frameSize)
+ { // no space to write - wait for a bit
+ CSingleLock lock(mutex);
+ if (!m_started)
+ condVar.wait(lock);
+ else
+ condVar.wait(lock, 900 * frames / m_sampleRate);
+ }
+
+ unsigned int write_frames = std::min(frames, m_buffer->GetWriteSize() / m_frameSize);
+ if (write_frames)
+ m_buffer->Write(data, write_frames * m_frameSize);
+
+ return write_frames;
+}
+
+void CAAudioUnitSink::drain()
+{
+ CCriticalSection mutex;
+ unsigned int bytes = m_buffer->GetReadSize();
+ while (bytes)
+ {
+ CSingleLock lock(mutex);
+ condVar.wait(mutex, 900 * bytes / (m_sampleRate * m_frameSize));
+ bytes = m_buffer->GetReadSize();
+ }
+}
+
+void CAAudioUnitSink::setCoreAudioBuffersize()
+{
+#if !TARGET_IPHONE_SIMULATOR
+ OSStatus status = noErr;
+ // set the buffer size, this affects the number of samples
+ // that get rendered every time the audio callback is fired.
+ Float32 preferredBufferSize = 512 * m_outputFormat.mChannelsPerFrame / m_outputFormat.mSampleRate;
+ CLog::Log(LOGNOTICE, "%s setting buffer duration to %f", __PRETTY_FUNCTION__, preferredBufferSize);
+ status = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration,
+ sizeof(preferredBufferSize), &preferredBufferSize);
+ if (status != noErr)
+ CLog::Log(LOGWARNING, "%s preferredBufferSize couldn't be set (error: %d)", __PRETTY_FUNCTION__, (int)status);
+#endif
+}
+
+bool CAAudioUnitSink::setCoreAudioInputFormat()
+{
+ // Set the output stream format
+ UInt32 ioDataSize = sizeof(AudioStreamBasicDescription);
+ OSStatus status = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input, 0, &m_outputFormat, ioDataSize);
+ if (status != noErr)
+ {
+ CLog::Log(LOGERROR, "%s error setting stream format on audioUnit (error: %d)", __PRETTY_FUNCTION__, (int)status);
+ return false;
+ }
+ return true;
+}
+
+void CAAudioUnitSink::setCoreAudioPreferredSampleRate()
+{
+ Float64 preferredSampleRate = m_outputFormat.mSampleRate;
+ CLog::Log(LOGNOTICE, "%s requesting hw samplerate %f", __PRETTY_FUNCTION__, preferredSampleRate);
+ OSStatus status = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate,
+ sizeof(preferredSampleRate), &preferredSampleRate);
+ if (status != noErr)
+ CLog::Log(LOGWARNING, "%s preferredSampleRate couldn't be set (error: %d)", __PRETTY_FUNCTION__, (int)status);
+}
+
+Float64 CAAudioUnitSink::getCoreAudioRealisedSampleRate()
+{
+ Float64 outputSampleRate = 0.0;
+ UInt32 ioDataSize = sizeof(outputSampleRate);
+ if (AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate,
+ &ioDataSize, &outputSampleRate) != noErr)
+ CLog::Log(LOGERROR, "%s: error getting CurrentHardwareSampleRate", __FUNCTION__);
+ return outputSampleRate;
+}
+
+bool CAAudioUnitSink::setupAudio()
+{
+ OSStatus status = noErr;
+ 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 = {};
+ description.componentType = kAudioUnitType_Output;
+ description.componentSubType = kAudioUnitSubType_RemoteIO;
+ description.componentManufacturer = kAudioUnitManufacturer_Apple;
+
+ // Get component
+ AudioComponent component;
+ component = AudioComponentFindNext(NULL, &description);
+ status = AudioComponentInstanceNew(component, &m_audioUnit);
+ if (status != noErr)
+ {
+ CLog::Log(LOGERROR, "%s error creating audioUnit (error: %d)", __PRETTY_FUNCTION__, (int)status);
+ return false;
+ }
+
+ setCoreAudioPreferredSampleRate();
+
+ // Get the output samplerate for knowing what was setup in reality
+ Float64 realisedSampleRate = getCoreAudioRealisedSampleRate();
+ if (m_outputFormat.mSampleRate != realisedSampleRate)
+ {
+ CLog::Log(LOGNOTICE, "%s couldn't set requested samplerate %d, coreaudio will resample to %d instead", __PRETTY_FUNCTION__, (int)m_outputFormat.mSampleRate, (int)realisedSampleRate);
+ // if we don't ca to resample - but instead let activeae resample -
+ // reflect the realised samplerate to the outputformat here
+ // well maybe it is handy in the future - as of writing this
+ // ca was about 6 times faster then activeae ;)
+ //m_outputFormat.mSampleRate = realisedSampleRate;
+ //m_sampleRate = realisedSampleRate;
+ }
+
+ setCoreAudioBuffersize();
+ if (!setCoreAudioInputFormat())
+ return false;
+
+ // Attach a render callback on the unit
+ AURenderCallbackStruct callbackStruct = {};
+ callbackStruct.inputProc = renderCallback;
+ callbackStruct.inputProcRefCon = this;
+ status = AudioUnitSetProperty(m_audioUnit,
+ kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
+ 0, &callbackStruct, sizeof(callbackStruct));
+ if (status != noErr)
+ {
+ CLog::Log(LOGERROR, "%s error setting render callback for audioUnit (error: %d)", __PRETTY_FUNCTION__, (int)status);
+ return false;
+ }
+
+ status = AudioUnitInitialize(m_audioUnit);
+ if (status != noErr)
+ {
+ CLog::Log(LOGERROR, "%s error initializing audioUnit (error: %d)", __PRETTY_FUNCTION__, (int)status);
+ return false;
+ }
+
+ checkSessionProperties();
+
+ m_setup = true;
+ std::string formatString;
+ CLog::Log(LOGNOTICE, "%s setup audio format: %s", __PRETTY_FUNCTION__, StreamDescriptionToString(m_outputFormat, formatString));
+
+ return m_setup;
+}
+
+bool CAAudioUnitSink::checkAudioRoute()
+{
+ // why do we need to know the audio route ?
+ CFStringRef route;
+ UInt32 propertySize = sizeof(CFStringRef);
+ if (AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route) != noErr)
+ return false;
+
+ return true;
+}
+
+bool CAAudioUnitSink::checkSessionProperties()
+{
+ checkAudioRoute();
+
+ UInt32 ioDataSize;
+ ioDataSize = sizeof(m_outputVolume);
+ if (AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputVolume,
+ &ioDataSize, &m_outputVolume) != noErr)
+ CLog::Log(LOGERROR, "%s: error getting CurrentHardwareOutputVolume", __FUNCTION__);
+
+ ioDataSize = sizeof(m_outputLatency);
+ if (AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputLatency,
+ &ioDataSize, &m_outputLatency) != noErr)
+ CLog::Log(LOGERROR, "%s: error getting CurrentHardwareOutputLatency", __FUNCTION__);
+
+ ioDataSize = sizeof(m_bufferDuration);
+ if (AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration,
+ &ioDataSize, &m_bufferDuration) != noErr)
+ CLog::Log(LOGERROR, "%s: error getting CurrentHardwareIOBufferDuration", __FUNCTION__);
+
+ CLog::Log(LOGDEBUG, "%s: volume = %f, latency = %f, buffer = %f", __FUNCTION__, m_outputVolume, m_outputLatency, m_bufferDuration);
+ return true;
+}
+
+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;
+ }
+
+ return m_activated;
+}
+
+void CAAudioUnitSink::deactivateAudioSession()
+{
+ if (m_activated)
+ {
+ pause();
+ AudioUnitUninitialize(m_audioUnit);
+ AudioComponentInstanceDispose(m_audioUnit), m_audioUnit = NULL;
+ AudioSessionSetActive(false);
+ AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_AudioRouteChange,
+ sessionPropertyCallback, this);
+ AudioSessionRemovePropertyListenerWithUserData(kAudioSessionProperty_CurrentHardwareOutputVolume,
+ sessionPropertyCallback, this);
+
+ m_setup = false;
+ m_activated = false;
+ }
+}
+
+void CAAudioUnitSink::sessionPropertyCallback(void *inClientData,
+ AudioSessionPropertyID inID, UInt32 inDataSize, const void *inData)
+{
+ CAAudioUnitSink *sink = (CAAudioUnitSink*)inClientData;
+
+ if (inID == kAudioSessionProperty_AudioRouteChange)
+ {
+ if (sink->checkAudioRoute())
+ sink->checkSessionProperties();
+ }
+ else if (inID == kAudioSessionProperty_CurrentHardwareOutputVolume)
+ {
+ if (inData && inDataSize == 4)
+ sink->m_outputVolume = *(float*)inData;
+ }
+}
+
+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);
+ }
+ }
+}
+
+OSStatus CAAudioUnitSink::renderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
+{
+ CAAudioUnitSink *sink = (CAAudioUnitSink*)inRefCon;
+
+ sink->m_started = true;
+
+ for (unsigned int i = 0; i < ioData->mNumberBuffers; i++)
+ {
+ // buffers come from CA already zero'd, so just copy what is wanted
+ unsigned int wanted = ioData->mBuffers[i].mDataByteSize;
+ unsigned int bytes = std::min(sink->m_buffer->GetReadSize(), wanted);
+ sink->m_buffer->Read((unsigned char*)ioData->mBuffers[i].mData, bytes);
+ if (bytes != wanted)
+ CLog::Log(LOGERROR, "%s: %sFLOW (%i vs %i) bytes", __FUNCTION__, bytes > wanted ? "OVER" : "UNDER", bytes, wanted);
+ }
+ // tell the sink we're good for more data
+ condVar.notifyAll();
+
+ return noErr;
+}
+
+/***************************************************************************************/
+/***************************************************************************************/
+static void EnumerateDevices(AEDeviceInfoList &list)
+{
+ CAEDeviceInfo device;
+
+ device.m_deviceName = "default";
+ device.m_displayName = "Default";
+ device.m_displayNameExtra = "";
+#if defined(TARGET_DARWIN_IOS_ATV2)
+ device.m_deviceType = AE_DEVTYPE_IEC958;
+ device.m_dataFormats.push_back(AE_FMT_AC3);
+ device.m_dataFormats.push_back(AE_FMT_DTS);
+#else
+ // TODO screen changing on ios needs to call
+ // devices changed once this is available in activae
+ if (g_Windowing.GetCurrentScreen() > 0)
+ {
+ device.m_deviceType = AE_DEVTYPE_IEC958; //allow passthrough for tvout
+ device.m_dataFormats.push_back(AE_FMT_AC3);
+ device.m_dataFormats.push_back(AE_FMT_DTS);
+ }
+ else
+ device.m_deviceType = AE_DEVTYPE_PCM;
+#endif
+
+ // add channel info
+ CAEChannelInfo channel_info;
+ for (UInt32 chan = 0; chan < 2; ++chan)
+ {
+ if (!device.m_channels.HasChannel(CAChannelMap[chan]))
+ device.m_channels += CAChannelMap[chan];
+ channel_info += CAChannelMap[chan];
+ }
+
+ // there are more supported ( one of those 2 gets resampled
+ // by coreaudio anyway) - but for keeping it save ignore
+ // the others...
+ device.m_sampleRates.push_back(44100);
+ device.m_sampleRates.push_back(48000);
+
+ device.m_dataFormats.push_back(AE_FMT_S16LE);
+ //device.m_dataFormats.push_back(AE_FMT_S24LE3);
+ //device.m_dataFormats.push_back(AE_FMT_S32LE);
+ // AE_FMT_FLOAT is 3% slower on atv2
+ // then S16LE - so leave it out for now
+ //device.m_dataFormats.push_back(AE_FMT_FLOAT);
+
+ CLog::Log(LOGDEBUG, "EnumerateDevices:Device(%s)" , device.m_deviceName.c_str());
+
+ list.push_back(device);
+}
+
+/***************************************************************************************/
+/***************************************************************************************/
+AEDeviceInfoList CAESinkDARWINIOS::m_devices;
+
+CAESinkDARWINIOS::CAESinkDARWINIOS()
+: m_audioSink(NULL)
+{
+}
+
+CAESinkDARWINIOS::~CAESinkDARWINIOS()
+{
+}
+
+bool CAESinkDARWINIOS::Initialize(AEAudioFormat &format, std::string &device)
+{
+ bool found = false;
+ bool forceRaw = false;
+
+ std::string devicelower = device;
+ StringUtils::ToLower(devicelower);
+ for (size_t i = 0; i < m_devices.size(); i++)
+ {
+ if (devicelower.find(m_devices[i].m_deviceName) != std::string::npos)
+ {
+ m_info = m_devices[i];
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return false;
+
+ AudioStreamBasicDescription audioFormat = {};
+
+ // AE_FMT_FLOAT is 3% slower on atv2
+ // then S16LE - so leave it out for now
+ // just leave the code commented in here
+ // as it might come handy at some point maybe ...
+ //if (format.m_dataFormat == AE_FMT_FLOAT)
+ // audioFormat.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
+ //else// this will be selected when AE wants AC3 or DTS or anything other then float
+ {
+ audioFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
+ if (AE_IS_RAW(format.m_dataFormat))
+ forceRaw = true;
+ format.m_dataFormat = AE_FMT_S16LE;
+ }
+
+ format.m_channelLayout = m_info.m_channels;
+ format.m_frameSize = format.m_channelLayout.Count() * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
+
+
+ audioFormat.mFormatID = kAudioFormatLinearPCM;
+ switch(format.m_sampleRate)
+ {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ case 176400:
+ audioFormat.mSampleRate = 44100;
+ break;
+ default:
+ case 8000:
+ case 12000:
+ case 16000:
+ case 24000:
+ case 32000:
+ case 48000:
+ case 96000:
+ case 192000:
+ case 384000:
+ audioFormat.mSampleRate = 48000;
+ break;
+ }
+
+ if (forceRaw)//make sure input and output samplerate match for preventing resampling
+ audioFormat.mSampleRate = CAAudioUnitSink::getCoreAudioRealisedSampleRate();
+
+ audioFormat.mFramesPerPacket = 1;
+ audioFormat.mChannelsPerFrame= 2;// ios only supports 2 channels
+ audioFormat.mBitsPerChannel = CAEUtil::DataFormatToBits(format.m_dataFormat);
+ audioFormat.mBytesPerFrame = format.m_frameSize;
+ audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket;
+ audioFormat.mFormatFlags |= kLinearPCMFormatFlagIsPacked;
+
+#if DO_440HZ_TONE_TEST
+ SineWaveGeneratorInitWithFrequency(&m_SineWaveGenerator, 440.0, audioFormat.mSampleRate);
+#endif
+
+ m_audioSink = new CAAudioUnitSink;
+ m_audioSink->open(audioFormat);
+
+ format.m_frames = m_audioSink->chunkSize();
+ format.m_frameSamples = format.m_frames * audioFormat.mChannelsPerFrame;
+ // reset to the realised samplerate
+ format.m_sampleRate = m_audioSink->getRealisedSampleRate();
+ m_format = format;
+
+ m_volume_changed = false;
+ m_audioSink->play(false);
+
+ return true;
+}
+
+void CAESinkDARWINIOS::Deinitialize()
+{
+ delete m_audioSink;
+ m_audioSink = NULL;
+}
+
+bool CAESinkDARWINIOS::IsCompatible(const AEAudioFormat &format, const std::string &device)
+{
+ return ((m_format.m_sampleRate == format.m_sampleRate) &&
+ (m_format.m_dataFormat == format.m_dataFormat) &&
+ (m_format.m_channelLayout == format.m_channelLayout));
+}
+
+double CAESinkDARWINIOS::GetDelay()
+{
+ if (m_audioSink)
+ return m_audioSink->getDelay();
+ return 0.0;
+}
+
+double CAESinkDARWINIOS::GetCacheTotal()
+{
+ if (m_audioSink)
+ return m_audioSink->cacheSize();
+ return 0.0;
+}
+
+unsigned int CAESinkDARWINIOS::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
+{
+
+#if DO_440HZ_TONE_TEST
+ if (m_format.m_dataFormat == AE_FMT_FLOAT)
+ {
+ float *samples = (float*)data;
+ for (unsigned int j = 0; j < frames ; j++)
+ {
+ float sample = SineWaveGeneratorNextSampleFloat(&m_SineWaveGenerator);
+ *samples++ = sample;
+ *samples++ = sample;
+ }
+
+ }
+ else
+ {
+ int16_t *samples = (int16_t*)data;
+ for (unsigned int j = 0; j < frames ; j++)
+ {
+ int16_t sample = SineWaveGeneratorNextSampleInt16(&m_SineWaveGenerator);
+ *samples++ = sample;
+ *samples++ = sample;
+ }
+ }
+#endif
+ if (m_audioSink)
+ return m_audioSink->write(data, frames);
+ return 0;
+}
+
+void CAESinkDARWINIOS::Drain()
+{
+ if (m_audioSink)
+ m_audioSink->drain();
+}
+
+bool CAESinkDARWINIOS::HasVolume()
+{
+ return false;
+}
+
+void CAESinkDARWINIOS::SetVolume(float scale)
+{
+ // CoreAudio uses fixed steps, reverse scale back to percent
+ float gain = CAEUtil::ScaleToGain(scale);
+ m_volume = CAEUtil::GainToPercent(gain);
+ m_volume_changed = true;
+}
+
+void CAESinkDARWINIOS::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
+{
+ m_devices.clear();
+ EnumerateDevices(m_devices);
+ list = m_devices;
+}
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.h b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.h
new file mode 100644
index 0000000000..f1fec67e25
--- /dev/null
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINIOS.h
@@ -0,0 +1,68 @@
+#pragma once
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "cores/AudioEngine/Interfaces/AESink.h"
+#include "cores/AudioEngine/Utils/AEDeviceInfo.h"
+
+#define DO_440HZ_TONE_TEST 0
+
+#if DO_440HZ_TONE_TEST
+typedef struct {
+ float currentPhase;
+ float phaseIncrement;
+} SineWaveGenerator;
+#endif
+
+class AERingBuffer;
+class CAAudioUnitSink;
+
+class CAESinkDARWINIOS : public IAESink
+{
+public:
+ virtual const char *GetName() { return "DARWINIOS"; }
+
+ CAESinkDARWINIOS();
+ virtual ~CAESinkDARWINIOS();
+
+ virtual bool Initialize(AEAudioFormat &format, std::string &device);
+ virtual void Deinitialize();
+ virtual bool IsCompatible(const AEAudioFormat &format, const std::string &device);
+
+ virtual double GetDelay ();
+ virtual double GetCacheTotal ();
+ virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio, bool blocking = false);
+ virtual void Drain ();
+ virtual bool HasVolume ();
+ virtual void SetVolume (float scale);
+ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false);
+
+private:
+ static AEDeviceInfoList m_devices;
+ CAEDeviceInfo m_info;
+ AEAudioFormat m_format;
+ double m_volume;
+ bool m_volume_changed;
+
+ CAAudioUnitSink *m_audioSink;
+#if DO_440HZ_TONE_TEST
+ SineWaveGenerator m_SineWaveGenerator;
+#endif
+}; \ No newline at end of file
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp
new file mode 100644
index 0000000000..f19acba58c
--- /dev/null
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2005-2014 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "cores/AudioEngine/AEFactory.h"
+#include "cores/AudioEngine/Sinks/AESinkDARWINOSX.h"
+#include "cores/AudioEngine/Utils/AEUtil.h"
+#include "cores/AudioEngine/Utils/AERingBuffer.h"
+#include "cores/AudioEngine/Sinks/osx/CoreAudioHelpers.h"
+#include "cores/AudioEngine/Sinks/osx/CoreAudioHardware.h"
+#include "osx/DarwinUtils.h"
+#include "utils/log.h"
+#include "utils/StringUtils.h"
+#include "threads/Condition.h"
+#include "threads/CriticalSection.h"
+
+#include <sstream>
+
+#define CA_MAX_CHANNELS 8
+static enum AEChannel CAChannelMap[CA_MAX_CHANNELS + 1] = {
+ AE_CH_FL , AE_CH_FR , AE_CH_BL , AE_CH_BR , AE_CH_FC , AE_CH_LFE , AE_CH_SL , AE_CH_SR ,
+ AE_CH_NULL
+};
+
+static bool HasSampleRate(const AESampleRateList &list, const unsigned int samplerate)
+{
+ for (size_t i = 0; i < list.size(); ++i)
+ {
+ if (list[i] == samplerate)
+ return true;
+ }
+ return false;
+}
+
+static bool HasDataFormat(const AEDataFormatList &list, const enum AEDataFormat format)
+{
+ for (size_t i = 0; i < list.size(); ++i)
+ {
+ if (list[i] == format)
+ return true;
+ }
+ return false;
+}
+
+typedef std::vector< std::pair<AudioDeviceID, CAEDeviceInfo> > CADeviceList;
+
+static void EnumerateDevices(CADeviceList &list)
+{
+ CAEDeviceInfo device;
+
+ std::string defaultDeviceName;
+ CCoreAudioHardware::GetOutputDeviceName(defaultDeviceName);
+
+ CoreAudioDeviceList deviceIDList;
+ CCoreAudioHardware::GetOutputDevices(&deviceIDList);
+ while (!deviceIDList.empty())
+ {
+ AudioDeviceID deviceID = deviceIDList.front();
+ CCoreAudioDevice caDevice(deviceID);
+
+ device.m_channels.Reset();
+ device.m_dataFormats.clear();
+ device.m_sampleRates.clear();
+
+ device.m_deviceType = AE_DEVTYPE_PCM;
+ device.m_deviceName = caDevice.GetName();
+ device.m_displayName = device.m_deviceName;
+ device.m_displayNameExtra = "";
+
+ if (device.m_deviceName.find("HDMI") != std::string::npos)
+ device.m_deviceType = AE_DEVTYPE_HDMI;
+
+ CLog::Log(LOGDEBUG, "EnumerateDevices:Device(%s)" , device.m_deviceName.c_str());
+ AudioStreamIdList streams;
+ if (caDevice.GetStreams(&streams))
+ {
+ for (AudioStreamIdList::iterator j = streams.begin(); j != streams.end(); ++j)
+ {
+ StreamFormatList streams;
+ if (CCoreAudioStream::GetAvailablePhysicalFormats(*j, &streams))
+ {
+ for (StreamFormatList::iterator i = streams.begin(); i != streams.end(); ++i)
+ {
+ AudioStreamBasicDescription desc = i->mFormat;
+ std::string formatString;
+ CLog::Log(LOGDEBUG, "EnumerateDevices:Format(%s)" ,
+ StreamDescriptionToString(desc, formatString));
+ // add stream format info
+ switch (desc.mFormatID)
+ {
+ case kAudioFormatAC3:
+ case kAudioFormat60958AC3:
+ if (!HasDataFormat(device.m_dataFormats, AE_FMT_AC3))
+ device.m_dataFormats.push_back(AE_FMT_AC3);
+ if (!HasDataFormat(device.m_dataFormats, AE_FMT_DTS))
+ device.m_dataFormats.push_back(AE_FMT_DTS);
+ // if we are not hdmi, this is an S/PDIF device
+ if (device.m_deviceType != AE_DEVTYPE_HDMI)
+ device.m_deviceType = AE_DEVTYPE_IEC958;
+ break;
+ default:
+ AEDataFormat format = AE_FMT_INVALID;
+ switch(desc.mBitsPerChannel)
+ {
+ case 16:
+ if (desc.mFormatFlags & kAudioFormatFlagIsBigEndian)
+ format = AE_FMT_S16BE;
+ else
+ {
+ /* Passthrough is possible with a 2ch digital output */
+ if (desc.mChannelsPerFrame == 2 && CCoreAudioStream::IsDigitalOuptut(*j))
+ {
+ if (desc.mSampleRate == 48000)
+ {
+ if (!HasDataFormat(device.m_dataFormats, AE_FMT_AC3))
+ device.m_dataFormats.push_back(AE_FMT_AC3);
+ if (!HasDataFormat(device.m_dataFormats, AE_FMT_DTS))
+ device.m_dataFormats.push_back(AE_FMT_DTS);
+ }
+ else if (desc.mSampleRate == 192000)
+ {
+ if (!HasDataFormat(device.m_dataFormats, AE_FMT_EAC3))
+ device.m_dataFormats.push_back(AE_FMT_EAC3);
+ }
+ }
+ format = AE_FMT_S16LE;
+ }
+ break;
+ case 24:
+ if (desc.mFormatFlags & kAudioFormatFlagIsBigEndian)
+ format = AE_FMT_S24BE3;
+ else
+ format = AE_FMT_S24LE3;
+ break;
+ case 32:
+ if (desc.mFormatFlags & kAudioFormatFlagIsFloat)
+ format = AE_FMT_FLOAT;
+ else
+ {
+ if (desc.mFormatFlags & kAudioFormatFlagIsBigEndian)
+ format = AE_FMT_S32BE;
+ else
+ format = AE_FMT_S32LE;
+ }
+ break;
+ }
+ if (format != AE_FMT_INVALID && !HasDataFormat(device.m_dataFormats, format))
+ device.m_dataFormats.push_back(format);
+ break;
+ }
+
+ // add channel info
+ CAEChannelInfo channel_info;
+ for (UInt32 chan = 0; chan < CA_MAX_CHANNELS && chan < desc.mChannelsPerFrame; ++chan)
+ {
+ if (!device.m_channels.HasChannel(CAChannelMap[chan]))
+ device.m_channels += CAChannelMap[chan];
+ channel_info += CAChannelMap[chan];
+ }
+
+ // add sample rate info
+ if (!HasSampleRate(device.m_sampleRates, desc.mSampleRate))
+ device.m_sampleRates.push_back(desc.mSampleRate);
+ }
+ }
+ }
+ }
+
+ list.push_back(std::make_pair(deviceID, device));
+ //in the first place of the list add the default device
+ //with name "default" - if this is selected
+ //we will output to whatever osx claims to be default
+ //(allows transition from headphones to speaker and stuff
+ //like that
+ if(defaultDeviceName == device.m_deviceName)
+ {
+ device.m_deviceName = "default";
+ device.m_displayName = "Default";
+ list.insert(list.begin(), std::make_pair(deviceID, device));
+ }
+
+ deviceIDList.pop_front();
+ }
+}
+
+/* static, threadsafe access to the device list */
+static CADeviceList s_devices;
+static CCriticalSection s_devicesLock;
+
+static void EnumerateDevices()
+{
+ CADeviceList devices;
+ EnumerateDevices(devices);
+ {
+ CSingleLock lock(s_devicesLock);
+ s_devices = devices;
+ }
+}
+
+static CADeviceList GetDevices()
+{
+ CADeviceList list;
+ {
+ CSingleLock lock(s_devicesLock);
+ list = s_devices;
+ }
+ return list;
+}
+
+OSStatus deviceChangedCB(AudioObjectID inObjectID,
+ UInt32 inNumberAddresses,
+ const AudioObjectPropertyAddress inAddresses[],
+ void* inClientData)
+{
+ CLog::Log(LOGDEBUG, "CoreAudio: audiodevicelist changed - reenumerating");
+ CAEFactory::DeviceChange();
+ CLog::Log(LOGDEBUG, "CoreAudio: audiodevicelist changed - done");
+ return noErr;
+}
+
+void RegisterDeviceChangedCB(bool bRegister, void *ref)
+{
+ OSStatus ret = noErr;
+ const AudioObjectPropertyAddress inAdr =
+ {
+ kAudioHardwarePropertyDevices,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster
+ };
+
+ if (bRegister)
+ ret = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &inAdr, deviceChangedCB, ref);
+ else
+ ret = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &inAdr, deviceChangedCB, ref);
+
+ if (ret != noErr)
+ CLog::Log(LOGERROR, "CCoreAudioAE::Deinitialize - error %s a listener callback for device changes!", bRegister?"attaching":"removing");
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+CAESinkDARWINOSX::CAESinkDARWINOSX()
+: m_latentFrames(0), m_outputBufferIndex(0), m_outputBitstream(false), m_outputBuffer(NULL), m_buffer(NULL)
+{
+ // By default, kAudioHardwarePropertyRunLoop points at the process's main thread on SnowLeopard,
+ // If your process lacks such a run loop, you can set kAudioHardwarePropertyRunLoop to NULL which
+ // tells the HAL to run it's own thread for notifications (which was the default prior to SnowLeopard).
+ // So tell the HAL to use its own thread for similar behavior under all supported versions of OSX.
+ CFRunLoopRef theRunLoop = NULL;
+ AudioObjectPropertyAddress theAddress = {
+ kAudioHardwarePropertyRunLoop,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster
+ };
+ OSStatus theError = AudioObjectSetPropertyData(kAudioObjectSystemObject,
+ &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
+ if (theError != noErr)
+ {
+ CLog::Log(LOGERROR, "CCoreAudioAE::constructor: kAudioHardwarePropertyRunLoop error.");
+ }
+ RegisterDeviceChangedCB(true, this);
+ m_started = false;
+}
+
+CAESinkDARWINOSX::~CAESinkDARWINOSX()
+{
+ RegisterDeviceChangedCB(false, this);
+}
+
+float ScoreStream(const AudioStreamBasicDescription &desc, const AEAudioFormat &format)
+{
+ float score = 0;
+ if (format.m_dataFormat == AE_FMT_AC3 ||
+ format.m_dataFormat == AE_FMT_DTS)
+ {
+ if (desc.mFormatID == kAudioFormat60958AC3 ||
+ desc.mFormatID == 'IAC3' ||
+ desc.mFormatID == kAudioFormatAC3)
+ {
+ if (desc.mSampleRate == format.m_sampleRate &&
+ desc.mBitsPerChannel == CAEUtil::DataFormatToBits(format.m_dataFormat) &&
+ desc.mChannelsPerFrame == format.m_channelLayout.Count())
+ {
+ // perfect match
+ score = FLT_MAX;
+ }
+ }
+ }
+ if (format.m_dataFormat == AE_FMT_AC3 ||
+ format.m_dataFormat == AE_FMT_DTS ||
+ format.m_dataFormat == AE_FMT_EAC3)
+ { // we should be able to bistreaming in PCM if the samplerate, bitdepth and channels match
+ if (desc.mSampleRate == format.m_sampleRate &&
+ desc.mBitsPerChannel == CAEUtil::DataFormatToBits(format.m_dataFormat) &&
+ desc.mChannelsPerFrame == format.m_channelLayout.Count() &&
+ desc.mFormatID == kAudioFormatLinearPCM)
+ {
+ score = FLT_MAX / 2;
+ }
+ }
+ else
+ { // non-passthrough, whatever works is fine
+ if (desc.mFormatID == kAudioFormatLinearPCM)
+ {
+ if (desc.mSampleRate == format.m_sampleRate)
+ score += 10;
+ else if (desc.mSampleRate > format.m_sampleRate)
+ score += 1;
+ if (desc.mChannelsPerFrame == format.m_channelLayout.Count())
+ score += 5;
+ else if (desc.mChannelsPerFrame > format.m_channelLayout.Count())
+ score += 1;
+ if (format.m_dataFormat == AE_FMT_FLOAT)
+ { // for float, prefer the highest bitdepth we have
+ if (desc.mBitsPerChannel >= 16)
+ score += (desc.mBitsPerChannel / 8);
+ }
+ else
+ {
+ if (desc.mBitsPerChannel == CAEUtil::DataFormatToBits(format.m_dataFormat))
+ score += 5;
+ else if (desc.mBitsPerChannel == CAEUtil::DataFormatToBits(format.m_dataFormat))
+ score += 1;
+ }
+ }
+ }
+ return score;
+}
+
+bool CAESinkDARWINOSX::Initialize(AEAudioFormat &format, std::string &device)
+{
+ AudioDeviceID deviceID = 0;
+ CADeviceList devices = GetDevices();
+ if (StringUtils::EqualsNoCase(device, "default"))
+ {
+ CCoreAudioHardware::GetOutputDeviceName(device);
+ CLog::Log(LOGNOTICE, "%s: Opening default device %s", __PRETTY_FUNCTION__, device.c_str());
+ }
+
+ for (size_t i = 0; i < devices.size(); i++)
+ {
+ if (device.find(devices[i].second.m_deviceName) != std::string::npos)
+ {
+ m_info = devices[i].second;
+ deviceID = devices[i].first;
+ break;
+ }
+ }
+ if (!deviceID)
+ {
+ CLog::Log(LOGERROR, "%s: Unable to find device %s", __FUNCTION__, device.c_str());
+ return false;
+ }
+
+ m_device.Open(deviceID);
+
+ // Fetch a list of the streams defined by the output device
+ AudioStreamIdList streams;
+ m_device.GetStreams(&streams);
+
+ CLog::Log(LOGDEBUG, "%s: Finding stream for format %s", __FUNCTION__, CAEUtil::DataFormatToStr(format.m_dataFormat));
+
+ bool passthrough = false;
+ UInt32 outputIndex = 0;
+ float outputScore = 0;
+ AudioStreamBasicDescription outputFormat = {0};
+ AudioStreamID outputStream = 0;
+
+ /* The theory is to score based on
+ 1. Matching passthrough characteristics (i.e. passthrough flag)
+ 2. Matching sample rate.
+ 3. Matching bits per channel (or higher).
+ 4. Matching number of channels (or higher).
+ */
+ UInt32 index = 0;
+ for (AudioStreamIdList::const_iterator i = streams.begin(); i != streams.end(); ++i)
+ {
+ // Probe physical formats
+ StreamFormatList formats;
+ CCoreAudioStream::GetAvailablePhysicalFormats(*i, &formats);
+ for (StreamFormatList::const_iterator j = formats.begin(); j != formats.end(); ++j)
+ {
+ const AudioStreamBasicDescription &desc = j->mFormat;
+
+ float score = ScoreStream(desc, format);
+
+ std::string formatString;
+ CLog::Log(LOGDEBUG, "%s: Physical Format: %s rated %f", __FUNCTION__, StreamDescriptionToString(desc, formatString), score);
+
+ if (score > outputScore)
+ {
+ passthrough = score > 1000;
+ outputScore = score;
+ outputFormat = desc;
+ outputStream = *i;
+ outputIndex = index;
+ }
+ }
+ index++;
+ }
+
+ if (!outputFormat.mFormatID)
+ {
+ CLog::Log(LOGERROR, "%s, Unable to find suitable stream", __FUNCTION__);
+ return false;
+ }
+
+ /* Update our AE format */
+ format.m_sampleRate = outputFormat.mSampleRate;
+ if (outputFormat.mChannelsPerFrame != format.m_channelLayout.Count())
+ { /* update the channel count. We assume that they're layed out as given in CAChannelMap.
+ if they're not, this is plain wrong */
+ format.m_channelLayout.Reset();
+ for (unsigned int i = 0; i < outputFormat.mChannelsPerFrame; i++)
+ format.m_channelLayout += CAChannelMap[i];
+ }
+
+ m_outputBufferIndex = outputIndex;
+ m_outputBitstream = passthrough && outputFormat.mFormatID == kAudioFormatLinearPCM;
+
+ std::string formatString;
+ CLog::Log(LOGDEBUG, "%s: Selected stream[%u] - id: 0x%04X, Physical Format: %s %s", __FUNCTION__, m_outputBufferIndex, outputStream, StreamDescriptionToString(outputFormat, formatString), m_outputBitstream ? "bitstreamed passthrough" : "");
+
+ SetHogMode(passthrough);
+
+ // Configure the output stream object
+ m_outputStream.Open(outputStream);
+
+ AudioStreamBasicDescription virtualFormat, previousPhysicalFormat;
+ m_outputStream.GetVirtualFormat(&virtualFormat);
+ m_outputStream.GetPhysicalFormat(&previousPhysicalFormat);
+ CLog::Log(LOGDEBUG, "%s: Previous Virtual Format: %s", __FUNCTION__, StreamDescriptionToString(virtualFormat, formatString));
+ CLog::Log(LOGDEBUG, "%s: Previous Physical Format: %s", __FUNCTION__, StreamDescriptionToString(previousPhysicalFormat, formatString));
+
+ m_outputStream.SetPhysicalFormat(&outputFormat); // Set the active format (the old one will be reverted when we close)
+ m_outputStream.GetVirtualFormat(&virtualFormat);
+ CLog::Log(LOGDEBUG, "%s: New Virtual Format: %s", __FUNCTION__, StreamDescriptionToString(virtualFormat, formatString));
+ CLog::Log(LOGDEBUG, "%s: New Physical Format: %s", __FUNCTION__, StreamDescriptionToString(outputFormat, formatString));
+
+ m_latentFrames = m_device.GetNumLatencyFrames();
+ m_latentFrames += m_outputStream.GetNumLatencyFrames();
+
+ /* TODO: Should we use the virtual format to determine our data format? */
+ format.m_frameSize = format.m_channelLayout.Count() * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
+ format.m_frames = m_device.GetBufferSize();
+ format.m_frameSamples = format.m_frames * format.m_channelLayout.Count();
+
+ if (m_outputBitstream)
+ {
+ m_outputBuffer = new int16_t[format.m_frameSamples];
+ /* TODO: Do we need this? */
+ m_device.SetNominalSampleRate(format.m_sampleRate);
+ }
+
+ unsigned int num_buffers = 4;
+ m_buffer = new AERingBuffer(num_buffers * format.m_frames * format.m_frameSize);
+ CLog::Log(LOGDEBUG, "%s: using buffer size: %u (%f ms)", __FUNCTION__, m_buffer->GetMaxSize(), (float)m_buffer->GetMaxSize() / (format.m_sampleRate * format.m_frameSize));
+
+ m_format = format;
+ if (passthrough)
+ format.m_dataFormat = AE_FMT_S16NE;
+ else
+ format.m_dataFormat = AE_FMT_FLOAT;
+
+ // Register for data request callbacks from the driver and start
+ m_device.AddIOProc(renderCallback, this);
+ m_device.Start();
+ return true;
+}
+
+void CAESinkDARWINOSX::SetHogMode(bool on)
+{
+ // TODO: Auto hogging sets this for us. Figure out how/when to turn it off or use it
+ // It appears that leaving this set will aslo restore the previous stream format when the
+ // Application exits. If auto hogging is set and we try to set hog mode, we will deadlock
+ // From the SDK docs: "If the AudioDevice is in a non-mixable mode, the HAL will automatically take hog mode on behalf of the first process to start an IOProc."
+
+ // Lock down the device. This MUST be done PRIOR to switching to a non-mixable format, if it is done at all
+ // If it is attempted after the format change, there is a high likelihood of a deadlock
+ // We may need to do this sooner to enable mix-disable (i.e. before setting the stream format)
+ if (on)
+ {
+ // Auto-Hog does not always un-hog the device when changing back to a mixable mode.
+ // Handle this on our own until it is fixed.
+ CCoreAudioHardware::SetAutoHogMode(false);
+ bool autoHog = CCoreAudioHardware::GetAutoHogMode();
+ CLog::Log(LOGDEBUG, " CoreAudioRenderer::InitializeEncoded: "
+ "Auto 'hog' mode is set to '%s'.", autoHog ? "On" : "Off");
+ if (autoHog)
+ return;
+ }
+ m_device.SetHogStatus(on);
+ m_device.SetMixingSupport(!on);
+}
+
+void CAESinkDARWINOSX::Deinitialize()
+{
+ m_device.Stop();
+ m_device.RemoveIOProc();
+
+ m_outputStream.Close();
+ m_device.Close();
+ if (m_buffer)
+ {
+ delete m_buffer;
+ m_buffer = NULL;
+ }
+ m_outputBufferIndex = 0;
+ m_outputBitstream = false;
+
+ delete[] m_outputBuffer;
+ m_outputBuffer = NULL;
+
+ m_started = false;
+}
+
+bool CAESinkDARWINOSX::IsCompatible(const AEAudioFormat &format, const std::string &device)
+{
+ return ((m_format.m_sampleRate == format.m_sampleRate) &&
+ (m_format.m_dataFormat == format.m_dataFormat) &&
+ (m_format.m_channelLayout == format.m_channelLayout));
+}
+
+double CAESinkDARWINOSX::GetDelay()
+{
+ if (m_buffer)
+ {
+ // Calculate the duration of the data in the cache
+ double delay = (double)m_buffer->GetReadSize() / (double)m_format.m_frameSize;
+ delay += (double)m_latentFrames;
+ delay /= (double)m_format.m_sampleRate;
+ return delay;
+ }
+ return 0.0;
+}
+
+double CAESinkDARWINOSX::GetCacheTotal()
+{
+ return (double)m_buffer->GetMaxSize() / (double)(m_format.m_frameSize * m_format.m_sampleRate);
+}
+
+CCriticalSection mutex;
+XbmcThreads::ConditionVariable condVar;
+
+unsigned int CAESinkDARWINOSX::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
+{
+ if (m_buffer->GetWriteSize() < frames * m_format.m_frameSize)
+ { // no space to write - wait for a bit
+ CSingleLock lock(mutex);
+ if (!m_started)
+ condVar.wait(lock);
+ else
+ condVar.wait(lock, 900 * frames / m_format.m_sampleRate);
+ }
+
+ unsigned int write_frames = std::min(frames, m_buffer->GetWriteSize() / m_format.m_frameSize);
+ if (write_frames)
+ m_buffer->Write(data, write_frames * m_format.m_frameSize);
+
+ return write_frames;
+}
+
+void CAESinkDARWINOSX::Drain()
+{
+ CCriticalSection mutex;
+ int bytes = m_buffer->GetReadSize();
+ while (bytes)
+ {
+ CSingleLock lock(mutex);
+ condVar.wait(mutex, 900 * bytes / (m_format.m_sampleRate * m_format.m_frameSize));
+ bytes = m_buffer->GetReadSize();
+ }
+}
+
+void CAESinkDARWINOSX::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
+{
+ EnumerateDevices();
+ list.clear();
+ for (CADeviceList::const_iterator i = s_devices.begin(); i != s_devices.end(); ++i)
+ list.push_back(i->second);
+}
+
+OSStatus CAESinkDARWINOSX::renderCallback(AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* inClientData)
+{
+ CAESinkDARWINOSX *sink = (CAESinkDARWINOSX*)inClientData;
+
+ sink->m_started = true;
+ if (sink->m_outputBufferIndex < outOutputData->mNumberBuffers)
+ {
+ if (sink->m_outputBitstream)
+ {
+ /* HACK for bitstreaming AC3/DTS via PCM.
+ We reverse the float->S16LE conversion done in the stream or device */
+ static const float mul = 1.0f / (INT16_MAX + 1);
+
+ unsigned int wanted = std::min(outOutputData->mBuffers[sink->m_outputBufferIndex].mDataByteSize / sizeof(float), (size_t)sink->m_format.m_frameSamples) * sizeof(int16_t);
+ if (wanted <= sink->m_buffer->GetReadSize())
+ {
+ sink->m_buffer->Read((unsigned char *)sink->m_outputBuffer, wanted);
+ int16_t *src = sink->m_outputBuffer;
+ float *dest = (float*)outOutputData->mBuffers[sink->m_outputBufferIndex].mData;
+ for (unsigned int i = 0; i < wanted / 2; i++)
+ *dest++ = *src++ * mul;
+ }
+ }
+ else
+ {
+ /* buffers appear to come from CA already zero'd, so just copy what is wanted */
+ unsigned int wanted = outOutputData->mBuffers[sink->m_outputBufferIndex].mDataByteSize;
+ unsigned int bytes = std::min(sink->m_buffer->GetReadSize(), wanted);
+ sink->m_buffer->Read((unsigned char*)outOutputData->mBuffers[sink->m_outputBufferIndex].mData, bytes);
+ if (bytes != wanted)
+ CLog::Log(LOGERROR, "%s: %sFLOW (%i vs %i) bytes", __FUNCTION__, bytes > wanted ? "OVER" : "UNDER", bytes, wanted);
+ }
+
+ // tell the sink we're good for more data
+ condVar.notifyAll();
+ }
+ return noErr;
+}
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.h b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.h
new file mode 100644
index 0000000000..6df15c4db5
--- /dev/null
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.h
@@ -0,0 +1,66 @@
+#pragma once
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "cores/AudioEngine/Interfaces/AESink.h"
+#include "cores/AudioEngine/Utils/AEDeviceInfo.h"
+#include "cores/AudioEngine/Sinks/osx/CoreAudioDevice.h"
+#include "cores/AudioEngine/Sinks/osx/CoreAudioStream.h"
+
+class AERingBuffer;
+
+class CAESinkDARWINOSX : public IAESink
+{
+public:
+ virtual const char *GetName() { return "DARWINOSX"; }
+
+ CAESinkDARWINOSX();
+ virtual ~CAESinkDARWINOSX();
+
+ virtual bool Initialize(AEAudioFormat &format, std::string &device);
+ virtual void Deinitialize();
+ virtual bool IsCompatible(const AEAudioFormat &format, const std::string &device);
+
+ virtual double GetDelay ();
+ virtual double GetCacheTotal ();
+ virtual unsigned int AddPackets (uint8_t *data, unsigned int frames, bool hasAudio, bool blocking = false);
+ virtual void Drain ();
+ static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false);
+
+private:
+ static OSStatus renderCallback(AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* inClientData);
+ void SetHogMode(bool on);
+
+ CAEDeviceInfo m_info;
+ AEAudioFormat m_format;
+
+ volatile bool m_draining;
+
+ CCoreAudioDevice m_device;
+ CCoreAudioStream m_outputStream;
+ unsigned int m_latentFrames;
+ unsigned int m_outputBufferIndex;
+
+ bool m_outputBitstream; ///< true if we're bistreaming into a LinearPCM stream rather than AC3 stream.
+ int16_t *m_outputBuffer; ///< buffer for bitstreaming
+
+ AERingBuffer *m_buffer;
+ volatile bool m_started; // set once we get a callback from CoreAudio, which can take a little while.
+};
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioChannelLayout.cpp b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioChannelLayout.cpp
index 8abecfaa9e..8abecfaa9e 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioChannelLayout.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioChannelLayout.cpp
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioChannelLayout.h b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioChannelLayout.h
index cf95c83666..cf95c83666 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioChannelLayout.h
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioChannelLayout.h
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.cpp b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp
index a03673f1a5..937e561b42 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp
@@ -19,7 +19,7 @@
*/
#include "CoreAudioDevice.h"
-#include "CoreAudioAEHAL.h"
+#include "CoreAudioHelpers.h"
#include "CoreAudioChannelLayout.h"
#include "CoreAudioHardware.h"
#include "utils/log.h"
@@ -29,7 +29,6 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CCoreAudioDevice::CCoreAudioDevice() :
m_Started (false ),
- m_pSource (NULL ),
m_DeviceId (0 ),
m_MixerRestore (-1 ),
m_IoProc (NULL ),
@@ -44,7 +43,6 @@ CCoreAudioDevice::CCoreAudioDevice() :
CCoreAudioDevice::CCoreAudioDevice(AudioDeviceID deviceId) :
m_Started (false ),
- m_pSource (NULL ),
m_DeviceId (deviceId ),
m_MixerRestore (-1 ),
m_IoProc (NULL ),
@@ -78,8 +76,7 @@ void CCoreAudioDevice::Close()
Stop();
// Unregister the IOProc if we have one
- if (m_IoProc)
- SetInputSource(NULL, 0, 0);
+ RemoveIOProc();
SetHogStatus(false);
CCoreAudioHardware::SetAutoHogMode(false);
@@ -98,7 +95,6 @@ void CCoreAudioDevice::Close()
}
m_IoProc = NULL;
- m_pSource = NULL;
m_DeviceId = 0;
m_ObjectListenerProc = NULL;
}
@@ -170,26 +166,13 @@ bool CCoreAudioDevice::SetObjectListenerProc(AudioObjectPropertyListenerProc cal
m_ObjectListenerProc = callback;
return true;
}
-
-bool CCoreAudioDevice::SetInputSource(ICoreAudioSource* pSource, unsigned int frameSize, unsigned int outputBufferIndex)
-{
- m_pSource = pSource;
- m_frameSize = frameSize;
- m_OutputBufferIndex = outputBufferIndex;
-
- if (pSource)
- return AddIOProc();
- else
- return RemoveIOProc();
-}
-
-bool CCoreAudioDevice::AddIOProc()
+bool CCoreAudioDevice::AddIOProc(AudioDeviceIOProc ioProc, void* pCallbackData)
{
// Allow only one IOProc at a time
if (!m_DeviceId || m_IoProc)
return false;
- OSStatus ret = AudioDeviceCreateIOProcID(m_DeviceId, DirectRenderCallback, this, &m_IoProc);
+ OSStatus ret = AudioDeviceCreateIOProcID(m_DeviceId, ioProc, pCallbackData, &m_IoProc);
if (ret)
{
CLog::Log(LOGERROR, "CCoreAudioDevice::AddIOProc: "
@@ -216,7 +199,6 @@ bool CCoreAudioDevice::RemoveIOProc()
"Unable to remove IOProc. Error = %s", GetError(ret).c_str());
m_IoProc = NULL; // Clear the reference no matter what
- m_pSource = NULL;
Sleep(100);
@@ -226,7 +208,7 @@ bool CCoreAudioDevice::RemoveIOProc()
std::string CCoreAudioDevice::GetName()
{
if (!m_DeviceId)
- return NULL;
+ return "";
AudioObjectPropertyAddress propertyAddress;
propertyAddress.mScope = kAudioDevicePropertyScopeOutput;
@@ -236,9 +218,9 @@ std::string CCoreAudioDevice::GetName()
UInt32 propertySize;
OSStatus ret = AudioObjectGetPropertyDataSize(m_DeviceId, &propertyAddress, 0, NULL, &propertySize);
if (ret != noErr)
- return NULL;
+ return "";
- std::string name = "";
+ std::string name;
char *buff = new char[propertySize + 1];
buff[propertySize] = 0x00;
ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, buff);
@@ -250,10 +232,10 @@ std::string CCoreAudioDevice::GetName()
else
{
name = buff;
+ name.erase(name.find_last_not_of(" ") + 1);
}
delete[] buff;
-
return name;
}
@@ -478,7 +460,7 @@ bool CCoreAudioDevice::GetMixingSupport()
mix = 0;
}
}
- CLog::Log(LOGERROR, "CCoreAudioDevice::SupportsMixing: "
+ CLog::Log(LOGDEBUG, "CCoreAudioDevice::SupportsMixing: "
"Device mixing support : %s.", mix ? "'Yes'" : "'No'");
return (mix > 0);
@@ -685,27 +667,3 @@ bool CCoreAudioDevice::SetBufferSize(UInt32 size)
return (ret == noErr);
}
-
-OSStatus CCoreAudioDevice::DirectRenderCallback(AudioDeviceID inDevice,
- const AudioTimeStamp *inNow,
- const AudioBufferList *inInputData,
- const AudioTimeStamp *inInputTime,
- AudioBufferList *outOutputData,
- const AudioTimeStamp *inOutputTime,
- void *inClientData)
-{
- OSStatus ret = noErr;
- CCoreAudioDevice *audioDevice = (CCoreAudioDevice*)inClientData;
-
- if (audioDevice->m_pSource && audioDevice->m_frameSize)
- {
- UInt32 frames = outOutputData->mBuffers[audioDevice->m_OutputBufferIndex].mDataByteSize / audioDevice->m_frameSize;
- ret = audioDevice->m_pSource->Render(NULL, inInputTime, 0, frames, outOutputData);
- }
- else
- {
- outOutputData->mBuffers[audioDevice->m_OutputBufferIndex].mDataByteSize = 0;
- }
-
- return ret;
-}
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.h b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h
index b94a256c0e..dcd5bf6cbb 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioDevice.h
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h
@@ -25,8 +25,7 @@
#include <string>
-#include "ICoreAudioSource.h"
-#include "CoreAudioStream.h"
+#include "cores/AudioEngine/Sinks/osx/CoreAudioStream.h"
#include <CoreAudio/CoreAudio.h>
@@ -68,17 +67,11 @@ public:
UInt32 GetBufferSize();
bool SetBufferSize(UInt32 size);
- virtual bool SetInputSource(ICoreAudioSource *pSource, unsigned int frameSize, unsigned int outputBufferIndex);
-protected:
- bool AddIOProc();
+ bool AddIOProc(AudioDeviceIOProc ioProc, void* pCallbackData);
bool RemoveIOProc();
-
- static OSStatus DirectRenderCallback(AudioDeviceID inDevice,
- const AudioTimeStamp *inNow, const AudioBufferList *inInputData, const AudioTimeStamp *inInputTime,
- AudioBufferList *outOutputData, const AudioTimeStamp *inOutputTime, void *inClientData);
+protected:
bool m_Started;
- ICoreAudioSource *m_pSource;
AudioDeviceID m_DeviceId;
int m_MixerRestore;
AudioDeviceIOProc m_IoProc;
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.cpp b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHardware.cpp
index 51984441ce..51cba80e0d 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHardware.cpp
@@ -20,7 +20,7 @@
#include "CoreAudioHardware.h"
-#include "CoreAudioAEHAL.h"
+#include "CoreAudioHelpers.h"
#include "utils/log.h"
#include "osx/DarwinUtils.h"
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.h b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHardware.h
index 95d33f6862..7762eb1177 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.h
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHardware.h
@@ -23,7 +23,7 @@
#if defined(TARGET_DARWIN_OSX)
-#include "CoreAudioDevice.h"
+#include "cores/AudioEngine/Sinks/osx/CoreAudioDevice.h"
// There is only one AudioSystemObject instance system-side.
// Therefore, all CCoreAudioHardware methods are static
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHAL.cpp b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHelpers.cpp
index 50bd3d5503..e8355d7854 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHAL.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHelpers.cpp
@@ -18,9 +18,7 @@
*
*/
-#include "CoreAudioAEHAL.h"
-#include "CoreAudioAE.h"
-#include "utils/log.h"
+#include "CoreAudioHelpers.h"
#include <sstream>
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHAL.h b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHelpers.h
index df2dd5737f..5233565a35 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHAL.h
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioHelpers.h
@@ -20,7 +20,6 @@
*/
#include <string>
-#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
// Helper Functions
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.cpp b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp
index 0e2598779a..4b7a5795e0 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp
@@ -20,7 +20,7 @@
#include "CoreAudioStream.h"
-#include "CoreAudioAEHAL.h"
+#include "CoreAudioHelpers.h"
#include "utils/log.h"
#include "utils/StdString.h"
@@ -127,9 +127,17 @@ UInt32 CCoreAudioStream::GetDirection()
return val;
}
-UInt32 CCoreAudioStream::GetTerminalType()
+bool CCoreAudioStream::IsDigitalOuptut(AudioStreamID id)
{
- if (!m_StreamId)
+ UInt32 type = GetTerminalType(id);
+ return (type == kAudioStreamTerminalTypeDigitalAudioInterface ||
+ type == kAudioStreamTerminalTypeDisplayPort ||
+ type == kAudioStreamTerminalTypeHDMI);
+}
+
+UInt32 CCoreAudioStream::GetTerminalType(AudioStreamID id)
+{
+ if (!id)
return 0;
UInt32 val = 0;
@@ -140,7 +148,7 @@ UInt32 CCoreAudioStream::GetTerminalType()
propertyAddress.mElement = kAudioObjectPropertyElementMaster;
propertyAddress.mSelector = kAudioStreamPropertyTerminalType;
- OSStatus ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &size, &val);
+ OSStatus ret = AudioObjectGetPropertyData(id, &propertyAddress, 0, NULL, &size, &val);
if (ret)
return 0;
return val;
@@ -335,7 +343,12 @@ bool CCoreAudioStream::SetPhysicalFormat(AudioStreamBasicDescription* pDesc)
bool CCoreAudioStream::GetAvailableVirtualFormats(StreamFormatList* pList)
{
- if (!pList || !m_StreamId)
+ return GetAvailableVirtualFormats(m_StreamId, pList);
+}
+
+bool CCoreAudioStream::GetAvailableVirtualFormats(AudioStreamID id, StreamFormatList* pList)
+{
+ if (!pList || !id)
return false;
AudioObjectPropertyAddress propertyAddress;
@@ -344,13 +357,13 @@ bool CCoreAudioStream::GetAvailableVirtualFormats(StreamFormatList* pList)
propertyAddress.mSelector = kAudioStreamPropertyAvailableVirtualFormats;
UInt32 propertySize = 0;
- OSStatus ret = AudioObjectGetPropertyDataSize(m_StreamId, &propertyAddress, 0, NULL, &propertySize);
+ OSStatus ret = AudioObjectGetPropertyDataSize(id, &propertyAddress, 0, NULL, &propertySize);
if (ret)
return false;
UInt32 formatCount = propertySize / sizeof(AudioStreamRangedDescription);
AudioStreamRangedDescription *pFormatList = new AudioStreamRangedDescription[formatCount];
- ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &propertySize, pFormatList);
+ ret = AudioObjectGetPropertyData(id, &propertyAddress, 0, NULL, &propertySize, pFormatList);
if (!ret)
{
for (UInt32 format = 0; format < formatCount; format++)
@@ -362,7 +375,12 @@ bool CCoreAudioStream::GetAvailableVirtualFormats(StreamFormatList* pList)
bool CCoreAudioStream::GetAvailablePhysicalFormats(StreamFormatList* pList)
{
- if (!pList || !m_StreamId)
+ return GetAvailablePhysicalFormats(m_StreamId, pList);
+}
+
+bool CCoreAudioStream::GetAvailablePhysicalFormats(AudioStreamID id, StreamFormatList* pList)
+{
+ if (!pList || !id)
return false;
AudioObjectPropertyAddress propertyAddress;
@@ -371,13 +389,13 @@ bool CCoreAudioStream::GetAvailablePhysicalFormats(StreamFormatList* pList)
propertyAddress.mSelector = kAudioStreamPropertyAvailablePhysicalFormats;
UInt32 propertySize = 0;
- OSStatus ret = AudioObjectGetPropertyDataSize(m_StreamId, &propertyAddress, 0, NULL, &propertySize);
+ OSStatus ret = AudioObjectGetPropertyDataSize(id, &propertyAddress, 0, NULL, &propertySize);
if (ret)
return false;
UInt32 formatCount = propertySize / sizeof(AudioStreamRangedDescription);
AudioStreamRangedDescription *pFormatList = new AudioStreamRangedDescription[formatCount];
- ret = AudioObjectGetPropertyData(m_StreamId, &propertyAddress, 0, NULL, &propertySize, pFormatList);
+ ret = AudioObjectGetPropertyData(id, &propertyAddress, 0, NULL, &propertySize, pFormatList);
if (!ret)
{
for (UInt32 format = 0; format < formatCount; format++)
diff --git a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.h b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h
index 008800e56d..3f3d1d0f79 100644
--- a/xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioStream.h
+++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h
@@ -23,7 +23,7 @@
#if defined(TARGET_DARWIN_OSX)
-#include "threads/Thread.h"
+#include "threads/Event.h"
#include <CoreAudio/CoreAudio.h>
#include <list>
@@ -39,10 +39,10 @@ public:
bool Open(AudioStreamID streamId);
void Close(bool restore = true);
-
+
AudioStreamID GetId() {return m_StreamId;}
UInt32 GetDirection();
- UInt32 GetTerminalType();
+ static UInt32 GetTerminalType(AudioStreamID id);
UInt32 GetNumLatencyFrames();
bool GetVirtualFormat(AudioStreamBasicDescription *pDesc);
bool GetPhysicalFormat(AudioStreamBasicDescription *pDesc);
@@ -50,7 +50,10 @@ public:
bool SetPhysicalFormat(AudioStreamBasicDescription *pDesc);
bool GetAvailableVirtualFormats(StreamFormatList *pList);
bool GetAvailablePhysicalFormats(StreamFormatList *pList);
-
+ static bool GetAvailableVirtualFormats(AudioStreamID id, StreamFormatList *pList);
+ static bool GetAvailablePhysicalFormats(AudioStreamID id, StreamFormatList *pList);
+ static bool IsDigitalOuptut(AudioStreamID id);
+
protected:
static OSStatus HardwareStreamListener(AudioObjectID inObjectID,
UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[], void* inClientData);
@@ -58,10 +61,9 @@ protected:
CEvent m_virtual_format_event;
CEvent m_physical_format_event;
-
AudioStreamID m_StreamId;
AudioStreamBasicDescription m_OriginalVirtualFormat;
- AudioStreamBasicDescription m_OriginalPhysicalFormat;
+ AudioStreamBasicDescription m_OriginalPhysicalFormat;
};
#endif
diff --git a/xbmc/osx/IOSScreenManager.mm b/xbmc/osx/IOSScreenManager.mm
index 1fe7f7a90b..ad2a7cb611 100644
--- a/xbmc/osx/IOSScreenManager.mm
+++ b/xbmc/osx/IOSScreenManager.mm
@@ -29,6 +29,7 @@
#include "Application.h"
#include "WindowingFactory.h"
#include "settings/DisplaySettings.h"
+#include "cores/AudioEngine/AEFactory.h"
#undef BOOL
#import <Foundation/Foundation.h>
@@ -205,6 +206,10 @@ static CEvent screenChangeEvent;
{
[self changeScreenSelector:dict];
}
+
+ // re-enumerate audio devices in that case too
+ // as we might gain passthrough capabilities via HDMI
+ CAEFactory::DeviceChange();
return true;
}
//--------------------------------------------------------------
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index d30aa30d4c..892a1392c8 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -55,7 +55,6 @@
#include "network/WakeOnAccess.h"
#if defined(TARGET_DARWIN_OSX)
#include "osx/XBMCHelper.h"
-#include "cores/AudioEngine/Engines/CoreAudio/CoreAudioHardware.h"
#endif // defined(TARGET_DARWIN_OSX)
#if defined(TARGET_DARWIN)
#include "osx/DarwinUtils.h"
@@ -798,14 +797,7 @@ void CSettings::InitializeDefaults()
#endif
#endif
-#if defined(TARGET_DARWIN)
- #if !defined(TARGET_DARWIN_IOS)
- CStdString defaultAudioDeviceName;
- CCoreAudioHardware::GetOutputDeviceName(defaultAudioDeviceName);
- ((CSettingString*)m_settingsManager->GetSetting("audiooutput.audiodevice"))->SetDefault(defaultAudioDeviceName);
- ((CSettingString*)m_settingsManager->GetSetting("audiooutput.passthroughdevice"))->SetDefault(defaultAudioDeviceName);
- #endif
-#elif !defined(TARGET_WINDOWS)
+#if !defined(TARGET_WINDOWS)
((CSettingString*)m_settingsManager->GetSetting("audiooutput.audiodevice"))->SetDefault(CAEFactory::GetDefaultDevice(false));
((CSettingString*)m_settingsManager->GetSetting("audiooutput.passthroughdevice"))->SetDefault(CAEFactory::GetDefaultDevice(true));
#endif