Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

[osxsink] - properly set the ae device type based on either ca or ... #4348

Merged
merged 1 commit into from

3 participants

@Memphiz
Owner

...heuristical criteria - fixes DisplayPort not detected as LPCM capable and maybe others.

This hopefully fixes some false decisions the former code does. We treated displayports as optical (preventing the user from doing LPCM) and we might even HDMI devices as optical because we overwrite the device type during enumeration when we find some compatible 2.0 48000 digital stream.

Backport off #4336

@Memphiz Memphiz [osxsink] - properly set the ae device type based on either ca or heu…
…ristical criteria - fixes DisplayPort not detected as LPCM capable and maybe others

Conflicts:
	xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp
9a05eed
@jmarshallnz jmarshallnz merged commit 8f35990 into xbmc:Gotham
@MartijnKaijser MartijnKaijser added this to the Gotham13.0-beta2 milestone
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 7, 2014
  1. @Memphiz

    [osxsink] - properly set the ae device type based on either ca or heu…

    Memphiz authored
    …ristical criteria - fixes DisplayPort not detected as LPCM capable and maybe others
    
    Conflicts:
    	xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp
This page is out of date. Refresh to see the latest.
View
74 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
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;
Something went wrong with that request. Please try again.