aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjmarshallnz <jcmarsha@gmail.com>2014-03-08 09:19:25 +1300
committerjmarshallnz <jcmarsha@gmail.com>2014-03-08 09:19:25 +1300
commit8f35990de049bda85ac76501947043c046886caa (patch)
tree0238a0aab65231cbf143e45340b435a4f180099b
parent0e01dd91cfefc6abf5a56328a34daa19072255e5 (diff)
parent9a05eed7d22e2743e17b05b63bb3d0f1267008cf (diff)
Merge pull request #4348 from Memphiz/osxdisplayportbp
[osxsink] - properly set the ae device type based on either ca or ...
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp74
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp32
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h1
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp20
-rw-r--r--xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h7
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;