aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lance <chris_lance@sbcglobal.net>2012-02-25 10:42:00 -0500
committerChris Lance <chris_lance@sbcglobal.net>2012-02-25 10:42:00 -0500
commitd29575755d23d4ca807df1c9ba89c051e0e8f2d0 (patch)
treed3b8c7d52ce7aa0bbc205e8b8dc6f224b1ff3efb
parentcebe00eec6bff7c4a17396a29b490c2d37db21ac (diff)
FIXED:[osx] Fall-back to a default speaker configuration if one is not configured for the output device.
-rw-r--r--xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp74
-rw-r--r--xbmc/cores/AudioRenderers/CoreAudioRenderer.h1
2 files changed, 72 insertions, 3 deletions
diff --git a/xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp b/xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp
index 67a6d8b756..a5b2b6e172 100644
--- a/xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp
+++ b/xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp
@@ -540,6 +540,7 @@ bool CCoreAudioMixMap::BuildExplicit(AudioChannelLayout& inLayout, AudioChannelL
// Initialize map
// map[in][out] = mix-level of input_channel[in] into output_channel[out]
m_pMap = (Float32*)calloc(sizeof(Float32), inLayout.mNumberChannelDescriptions * outLayout.mNumberChannelDescriptions);
+ int mappedChannels = 0;
// Initialize array of output channel locations
int outPos[MAX_AUDIO_CHANNEL_LABEL + 1];
@@ -570,6 +571,7 @@ bool CCoreAudioMixMap::BuildExplicit(AudioChannelLayout& inLayout, AudioChannelL
// map[in][out] = map[in * outCount + out]
CLog::Log(LOGDEBUG, "CCoreAudioMixMap::BuildExplicit:\tin[%d] -> out[%d] @ %0.02f", channel, outIndex, 1.0f);
m_pMap[channel * outLayout.mNumberChannelDescriptions + outIndex] = 1.0f;
+ mappedChannels++;
}
else // The input channel does not exist in the output layout. Decide where to route it...
{
@@ -603,12 +605,19 @@ bool CCoreAudioMixMap::BuildExplicit(AudioChannelLayout& inLayout, AudioChannelL
int outIndex = outPos[patch->label];
CLog::Log(LOGDEBUG, "CCoreAudioMixMap::BuildExplicit:\tin[%d] -> out[%d] @ %0.02f", channel, outIndex, patch->coeff);
m_pMap[channel * outLayout.mNumberChannelDescriptions + outIndex] = patch->coeff;
+ mappedChannels++;
}
break;
}
}
}
- }
+ }
+ if (!mappedChannels)
+ {
+ CLog::Log(LOGINFO, "CCoreAudioMixMap::BuildExplicit: No valid patches found.");
+ return false;
+ }
+
CLog::Log(LOGINFO, "CCoreAudioMixMap::BuildExplicit: Completed explicit channel map.");
return true;
}
@@ -1249,7 +1258,39 @@ bool CCoreAudioRenderer::InitializePCM(UInt32 channels, UInt32 samplesPerSecond,
CCoreAudioChannelLayout deviceLayout;
if (!m_AudioDevice.GetPreferredChannelLayout(deviceLayout))
return false;
-
+
+ // Detect devices with no Speaker Configuration
+ bool undefinedLayout = true;
+ for (UInt32 c = 0; c < deviceLayout.GetChannelCount(); c++)
+ {
+ // If this is a known channel, then we can't have an undefined layout
+ if (deviceLayout.GetChannelLabel(c) != kAudioChannelLabel_Unknown)
+ {
+ undefinedLayout = false;
+ break;
+ }
+ }
+ if (undefinedLayout)
+ {
+ if (!g_sysinfo.IsAppleTV()) // AppleTV users cannot do this...
+ {
+ CLog::Log(LOGERROR, "CCoreAudioRenderer::InitializePCM: The selected device (%s) does not have a speaker layout configured. Using the default layout.", m_AudioDevice.GetName());
+ CLog::Log(LOGERROR, "CCoreAudioRenderer::InitializePCM: \tPlease go to Applications -> Utilities -> Audio MIDI Setup, and select 'Configure Speakers...'");
+ }
+ // Pick a default layout based on the number of channels
+ AudioChannelLayoutTag newLayoutTag = GetDefaultLayout(deviceLayout.GetChannelCount());
+ if (newLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) // Undefined, give up...
+ {
+ CLog::Log(LOGERROR, "CCoreAudioRenderer::InitializePCM: Unable to find a suitable default layout for this device.");
+ return false;
+ }
+ if (!deviceLayout.SetLayout(newLayoutTag))
+ {
+ CLog::Log(LOGERROR, "CCoreAudioRenderer::InitializePCM: Unable to set channel layout from tag.");
+ return false;
+ }
+ }
+
CStdString strOutLayout;
CLog::Log(LOGDEBUG, "CCoreAudioRenderer::InitializePCM: Output Device Layout: %s", CCoreAudioChannelLayout::ChannelLayoutToString(*(AudioChannelLayout*)deviceLayout, strOutLayout));
@@ -1266,7 +1307,7 @@ bool CCoreAudioRenderer::InitializePCM(UInt32 channels, UInt32 samplesPerSecond,
// if (CCoreAudioChannelLayout::GetChannelCountForLayout(guiLayout) < CCoreAudioChannelLayout::GetChannelCountForLayout(deviceLayout))
// deviceLayout.CopyLayout(guiLayout);
- // TODO: Skip matrix mixer if input/output are compatible
+ // TODO: Skip matrix mixer if input/output are compatible -> Add a IsPurePassthrough() method to the CCoreAudioMixMap class
AudioChannelLayout* layoutCandidates[] = {(AudioChannelLayout*)deviceLayout, (AudioChannelLayout*)userLayout, NULL};
@@ -1560,6 +1601,33 @@ void CCoreAudioRenderer::OnResetDevice()
}
}
}
+
+AudioChannelLayoutTag CCoreAudioRenderer::GetDefaultLayout(UInt32 channelCount)
+{
+ switch(channelCount)
+ {
+ case 1:
+ return kAudioChannelLayoutTag_Mono; // 1.0
+ case 2:
+ return kAudioChannelLayoutTag_Stereo; // 2.0
+ case 3:
+ return kAudioChannelLayoutTag_DVD_4; // 2.1
+ case 4:
+ return kAudioChannelLayoutTag_DVD_10; // 3.1
+ case 5:
+ return kAudioChannelLayoutTag_DVD_6; // 4.1
+ case 6:
+ return kAudioChannelLayoutTag_MPEG_5_1_A; // 5.1
+ case 7:
+ return kAudioChannelLayoutTag_AudioUnit_7_0; // 7.0
+ case 8:
+ return kAudioChannelLayoutTag_MPEG_7_1_A; // 7.1
+ case 0:
+ default:
+ return kAudioChannelLayoutTag_UseChannelBitmap; // Basically 'Undefined'
+ }
+}
+
#endif
#endif
diff --git a/xbmc/cores/AudioRenderers/CoreAudioRenderer.h b/xbmc/cores/AudioRenderers/CoreAudioRenderer.h
index 72319560d7..3b06a518fb 100644
--- a/xbmc/cores/AudioRenderers/CoreAudioRenderer.h
+++ b/xbmc/cores/AudioRenderers/CoreAudioRenderer.h
@@ -165,6 +165,7 @@ private:
bool InitializePCM(UInt32 channels, UInt32 samplesPerSecond, UInt32 bitsPerSample, enum PCMChannels *channelMap, bool allowMixing = true);
bool InitializePCMEncoded(UInt32 sampleRate);
+ AudioChannelLayoutTag GetDefaultLayout(UInt32 channelCount);
static OSStatus HardwareListenerProc(AudioHardwarePropertyID property, void *clientref);
static OSStatus DeviceListenerProc(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void *clientref);