Permalink
Browse files

Merge pull request #4336 from Memphiz/osxdisplayport

[osxsink] - properly set the ae device type based on either ca or heuris...
  • Loading branch information...
2 parents 601cbc2 + dc87b59 commit 5abc49118e0cd9addde17b2b5c75970ed56953e5 @jmarshallnz jmarshallnz committed Mar 7, 2014
View
71 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,16 +130,14 @@ static void EnumerateDevices(CADeviceList &list)
format = AE_FMT_S16BE;
else
{
- bool isDigital = CCoreAudioStream::IsDigitalOuptut(*j);
-
// 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);
+ StringUtils::ToLower(devNameLower);
isDigital = devNameLower.find("digital") != std::string::npos;
}
@@ -145,15 +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);
-
- // treat it like optical - else ActiveAE
- // won't enable the pass through options in the gui
- device.m_deviceType = AE_DEVTYPE_IEC958;
+ 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;
@@ -177,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;
@@ -199,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
View
32 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;
View
1 xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h
@@ -51,6 +51,7 @@ class CCoreAudioDevice
AudioDeviceID GetId() {return m_DeviceId;}
std::string GetName();
+ bool IsDigital(UInt32 &transportType);
UInt32 GetTotalOutputChannels();
bool GetStreams(AudioStreamIdList *pList);
bool IsRunning();
View
20 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)
View
7 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;

0 comments on commit 5abc491

Please sign in to comment.