Skip to content

Commit

Permalink
[osxsink] - properly set the ae device type based on either ca or heu…
Browse files Browse the repository at this point in the history
…ristical criteria - fixes DisplayPort not detected as LPCM capable and maybe others

Conflicts:
	xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp
  • Loading branch information
Memphiz committed Mar 7, 2014
1 parent 1cba479 commit 9a05eed
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 16 deletions.
74 changes: 69 additions & 5 deletions xbmc/cores/AudioEngine/Sinks/AESinkDARWINOSX.cpp
Expand Up @@ -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;
Expand All @@ -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)
{
Expand All @@ -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;
Expand All @@ -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))
{
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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
Expand Down
32 changes: 32 additions & 0 deletions xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.cpp
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions xbmc/cores/AudioEngine/Sinks/osx/CoreAudioDevice.h
Expand Up @@ -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();
Expand Down
20 changes: 9 additions & 11 deletions xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.cpp
Expand Up @@ -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 )
{
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions xbmc/cores/AudioEngine/Sinks/osx/CoreAudioStream.h
Expand Up @@ -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;

Expand Down

0 comments on commit 9a05eed

Please sign in to comment.