diff options
author | jmarshallnz <jcmarsha@gmail.com> | 2014-03-08 09:19:25 +1300 |
---|---|---|
committer | jmarshallnz <jcmarsha@gmail.com> | 2014-03-08 09:19:25 +1300 |
commit | 8f35990de049bda85ac76501947043c046886caa (patch) | |
tree | 0238a0aab65231cbf143e45340b435a4f180099b | |
parent | 0e01dd91cfefc6abf5a56328a34daa19072255e5 (diff) | |
parent | 9a05eed7d22e2743e17b05b63bb3d0f1267008cf (diff) |
Merge pull request #4348 from Memphiz/osxdisplayportbp
[osxsink] - properly set the ae device type based on either ca or ...
5 files changed, 118 insertions, 16 deletions
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp index a9e123dbb1..3d00305b4a 100644 --- a/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp +++ b/xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp @@ -83,8 +83,15 @@ static void EnumerateDevices(CADeviceList &list) device.m_displayName = device.m_deviceName; device.m_displayNameExtra = ""; - if (device.m_deviceName.find("HDMI") != std::string::npos) - device.m_deviceType = AE_DEVTYPE_HDMI; + // flag indicating that passthroughformats where added throughout the stream enumeration + bool hasPassthroughFormats = false; + // the maximum number of channels found in the streams + UInt32 numMaxChannels = 0; + // the terminal type as reported by ca + UInt32 caTerminalType = 0; + + bool isDigital = caDevice.IsDigital(caTerminalType); + CLog::Log(LOGDEBUG, "EnumerateDevices:Device(%s)" , device.m_deviceName.c_str()); AudioStreamIdList streams; @@ -101,6 +108,7 @@ static void EnumerateDevices(CADeviceList &list) std::string formatString; CLog::Log(LOGDEBUG, "EnumerateDevices:Format(%s)" , StreamDescriptionToString(desc, formatString)); + // add stream format info switch (desc.mFormatID) { @@ -110,9 +118,8 @@ static void EnumerateDevices(CADeviceList &list) 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; + hasPassthroughFormats = true; + isDigital = true;// sanity - those are always digital devices! break; default: AEDataFormat format = AE_FMT_INVALID; @@ -123,6 +130,17 @@ static void EnumerateDevices(CADeviceList &list) format = AE_FMT_S16BE; else { + // if it is no digital stream per definition + // check if the device name suggests that it is digital + // (some hackintonshs are not so smart in announcing correct + // ca devices ... + if (!isDigital) + { + std::string devNameLower = device.m_deviceName; + StringUtils::ToLower(devNameLower); + isDigital = devNameLower.find("digital") != std::string::npos; + } + /* Passthrough is possible with a 2ch digital output */ if (desc.mChannelsPerFrame == 2 && CCoreAudioStream::IsDigitalOuptut(*j)) { @@ -132,11 +150,13 @@ static void EnumerateDevices(CADeviceList &list) device.m_dataFormats.push_back(AE_FMT_AC3); if (!HasDataFormat(device.m_dataFormats, AE_FMT_DTS)) device.m_dataFormats.push_back(AE_FMT_DTS); + hasPassthroughFormats = true; } else if (desc.mSampleRate == 192000) { if (!HasDataFormat(device.m_dataFormats, AE_FMT_EAC3)) device.m_dataFormats.push_back(AE_FMT_EAC3); + hasPassthroughFormats = true; } } format = AE_FMT_S16LE; @@ -160,6 +180,10 @@ static void EnumerateDevices(CADeviceList &list) } break; } + + if (numMaxChannels < desc.mChannelsPerFrame) + numMaxChannels = desc.mChannelsPerFrame; + if (format != AE_FMT_INVALID && !HasDataFormat(device.m_dataFormats, format)) device.m_dataFormats.push_back(format); break; @@ -182,6 +206,46 @@ static void EnumerateDevices(CADeviceList &list) } } + + // flag indicating that the device name "sounds" like HDMI + bool hasHdmiName = device.m_deviceName.find("HDMI") != std::string::npos; + // flag indicating that the device name "sounds" like DisplayPort + bool hasDisplayPortName = device.m_deviceName.find("DisplayPort") != std::string::npos; + + // decide the type of the device based on the discovered information + // in the streams + // device defaults to PCM (see start of the while loop) + // it can be HDMI, DisplayPort or Optical + // for all of those types it needs to support + // passthroughformats and needs to be a digital port + if (hasPassthroughFormats && isDigital) + { + // if the max number of channels was more then 2 + // this can be HDMI or DisplayPort or Thunderbolt + if (numMaxChannels > 2) + { + // either the devicename suggests its HDMI + // or CA reported the terminalType as HDMI + if (hasHdmiName || caTerminalType == kIOAudioDeviceTransportTypeHdmi) + device.m_deviceType = AE_DEVTYPE_HDMI; + + // either the devicename suggests its DisplayPort + // or CA reported the terminalType as DisplayPort or Thunderbolt + if (hasDisplayPortName || caTerminalType == kIOAudioDeviceTransportTypeDisplayPort || caTerminalType == kIOAudioDeviceTransportTypeThunderbolt) + device.m_deviceType = AE_DEVTYPE_DP; + } + else// treat all other digital passthrough devices as optical + device.m_deviceType = AE_DEVTYPE_IEC958; + } + + // devicename based overwrites from former code - maybe FIXME at some point when we + // are sure that the upper detection does its job in all[tm] use cases + if (hasHdmiName) + device.m_deviceType = AE_DEVTYPE_HDMI; + if (hasDisplayPortName) + device.m_deviceType = AE_DEVTYPE_DP; + + 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 diff --git a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp index 937e561b42..20b8728996 100644 --- a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp +++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp @@ -239,6 +239,38 @@ std::string CCoreAudioDevice::GetName() return name; } +bool CCoreAudioDevice::IsDigital(UInt32 &transportType) +{ + bool isDigital = false; + if (!m_DeviceId) + return false; + + AudioObjectPropertyAddress propertyAddress; + propertyAddress.mScope = kAudioDevicePropertyScopeOutput; + propertyAddress.mElement = 0; + propertyAddress.mSelector = kAudioDevicePropertyTransportType; + + UInt32 propertySize = sizeof(transportType); + OSStatus ret = AudioObjectGetPropertyData(m_DeviceId, &propertyAddress, 0, NULL, &propertySize, &transportType); + if (ret != noErr) + return false; + + if (transportType == kIOAudioDeviceTransportTypeFireWire) + isDigital = true; + if (transportType == kIOAudioDeviceTransportTypeUSB) + isDigital = true; + if (transportType == kIOAudioDeviceTransportTypeHdmi) + isDigital = true; + if (transportType == kIOAudioDeviceTransportTypeDisplayPort) + isDigital = true; + if (transportType == kIOAudioDeviceTransportTypeThunderbolt) + isDigital = true; + if (transportType == kAudioStreamTerminalTypeDigitalAudioInterface) + isDigital = true; + + return isDigital; +} + UInt32 CCoreAudioDevice::GetTotalOutputChannels() { UInt32 channels = 0; diff --git a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h index dcd5bf6cbb..e95f8c12f1 100644 --- a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h +++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h @@ -51,6 +51,7 @@ public: AudioDeviceID GetId() {return m_DeviceId;} std::string GetName(); + bool IsDigital(UInt32 &transportType); UInt32 GetTotalOutputChannels(); bool GetStreams(AudioStreamIdList *pList); bool IsRunning(); diff --git a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp index 05fd5bf359..94b1426a49 100644 --- a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp +++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp @@ -24,15 +24,6 @@ #include "utils/log.h" #include "utils/StdString.h" -// defines taken from CoreAudio/AudioHardware.h from SDK 10.8 -#if !defined kAudioStreamTerminalTypeHDMI -#define kAudioStreamTerminalTypeHDMI 'hdmi' -#endif - -#if !defined kAudioStreamTerminalTypeDisplayPort -#define kAudioStreamTerminalTypeDisplayPort 'dprt' -#endif - CCoreAudioStream::CCoreAudioStream() : m_StreamId (0 ) { @@ -136,12 +127,19 @@ UInt32 CCoreAudioStream::GetDirection() return val; } +// WARNING - don't rely on this method - the return value of +// GetTerminalType is driver specific - the checked return +// values are only recommendations from apple bool CCoreAudioStream::IsDigitalOuptut(AudioStreamID id) { UInt32 type = GetTerminalType(id); + // yes apple is mixing types here... return (type == kAudioStreamTerminalTypeDigitalAudioInterface || - type == kAudioStreamTerminalTypeDisplayPort || - type == kAudioStreamTerminalTypeHDMI); + type == kIOAudioDeviceTransportTypeDisplayPort || + type == kIOAudioDeviceTransportTypeHdmi || + type == kIOAudioDeviceTransportTypeFireWire || + type == kIOAudioDeviceTransportTypeThunderbolt || + type == kIOAudioDeviceTransportTypeUSB); } UInt32 CCoreAudioStream::GetTerminalType(AudioStreamID id) diff --git a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h index 3f3d1d0f79..6edc7e2d10 100644 --- a/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h +++ b/xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h @@ -25,9 +25,16 @@ #include "threads/Event.h" #include <CoreAudio/CoreAudio.h> +#include <IOKit/audio/IOAudioTypes.h> #include <list> +// not defined in 10.6 sdk +#ifndef kIOAudioDeviceTransportTypeThunderbolt +#define kIOAudioDeviceTransportTypeThunderbolt 'thun' +#endif + + typedef std::list<AudioStreamID> AudioStreamIdList; typedef std::list<AudioStreamRangedDescription> StreamFormatList; |