| @@ -36,6 +36,15 @@ struct CoreAudioLayouts | |||
| return AudioChannelSet::channelSetWithChannels (getCoreAudioLayoutChannels (layout)); | |||
| } | |||
| /** Convert CoreAudio's native AudioChannelLayoutTag to JUCE's AudioChannelSet. | |||
| Note that this method cannot preserve the order of channels. | |||
| */ | |||
| static AudioChannelSet fromCoreAudio (AudioChannelLayoutTag layoutTag) | |||
| { | |||
| return AudioChannelSet::channelSetWithChannels (getSpeakerLayoutForCoreAudioTag (layoutTag)); | |||
| } | |||
| /** Convert JUCE's AudioChannelSet to CoreAudio's AudioChannelLayoutTag. | |||
| Note that this method cannot preserve the order of channels. | |||
| @@ -67,7 +76,7 @@ struct CoreAudioLayouts | |||
| /** Convert CoreAudio's native AudioChannelLayout to an array of JUCE ChannelTypes. */ | |||
| static Array<AudioChannelSet::ChannelType> getCoreAudioLayoutChannels (const AudioChannelLayout& layout) | |||
| { | |||
| switch (layout.mChannelLayoutTag) | |||
| switch (layout.mChannelLayoutTag & 0xffff0000) | |||
| { | |||
| case kAudioChannelLayoutTag_UseChannelBitmap: | |||
| return AudioChannelSet::fromWaveChannelMask (static_cast<int> (layout.mChannelBitmap)).getChannelTypes(); | |||
| @@ -94,30 +103,12 @@ struct CoreAudioLayouts | |||
| return getSpeakerLayoutForCoreAudioTag (layout.mChannelLayoutTag); | |||
| } | |||
| //============================================================================== | |||
| /* Convert between a CoreAudio and JUCE channel indices - and vice versa. */ | |||
| // TODO: Fabian remove this | |||
| // static int convertChannelIndex (const AudioChannelLayout& caLayout, const AudioChannelSet& juceLayout, int index, bool fromJUCE) | |||
| // { | |||
| // auto coreAudioChannels = getCoreAudioLayoutChannels (caLayout); | |||
| // | |||
| // jassert (juceLayout.size() == coreAudioChannels.size()); | |||
| // jassert (index >= 0 && index < juceLayout.size()); | |||
| // | |||
| // return (fromJUCE ? coreAudioChannels.indexOf (juceLayout.getTypeOfChannel (index)) | |||
| // : juceLayout.getChannelIndexForType (coreAudioChannels.getReference (index))); | |||
| // } | |||
| private: | |||
| //============================================================================== | |||
| struct LayoutTagSpeakerList | |||
| { | |||
| AudioChannelLayoutTag tag; | |||
| AudioChannelSet::ChannelType channelTypes[16]; | |||
| }; | |||
| static Array<AudioChannelSet::ChannelType> getSpeakerLayoutForCoreAudioTag (AudioChannelLayoutTag tag) | |||
| { | |||
| // You need to specify the full AudioChannelLayout when using | |||
| // the UseChannelBitmap and UseChannelDescriptions layout tag | |||
| jassert (tag != kAudioChannelLayoutTag_UseChannelBitmap && tag != kAudioChannelLayoutTag_UseChannelDescriptions); | |||
| Array<AudioChannelSet::ChannelType> speakers; | |||
| for (auto* tbl = SpeakerLayoutTable::get(); tbl->tag != 0; ++tbl) | |||
| @@ -139,6 +130,14 @@ private: | |||
| return speakers; | |||
| } | |||
| private: | |||
| //============================================================================== | |||
| struct LayoutTagSpeakerList | |||
| { | |||
| AudioChannelLayoutTag tag; | |||
| AudioChannelSet::ChannelType channelTypes[16]; | |||
| }; | |||
| static Array<AudioChannelLayoutTag> createKnownCoreAudioTags() | |||
| { | |||
| Array<AudioChannelLayoutTag> tags; | |||
| @@ -619,8 +619,7 @@ public: | |||
| for (auto tagEntry : knownTags) | |||
| { | |||
| AudioChannelLayout layout { tagEntry.tag }; | |||
| auto labels = CoreAudioLayouts::fromCoreAudio (layout); | |||
| auto labels = CoreAudioLayouts::fromCoreAudio (tagEntry.tag); | |||
| expect (! labels.isDiscreteLayout(), String ("Tag \"") + String (tagEntry.name) + "\" is not handled by JUCE"); | |||
| } | |||
| @@ -631,8 +630,7 @@ public: | |||
| for (auto tagEntry : knownTags) | |||
| { | |||
| AudioChannelLayout layout { tagEntry.tag }; | |||
| auto labels = CoreAudioLayouts::getCoreAudioLayoutChannels (layout); | |||
| auto labels = CoreAudioLayouts::getSpeakerLayoutForCoreAudioTag (tagEntry.tag); | |||
| expect (labels.size() == (tagEntry.tag & 0xffff), String ("Tag \"") + String (tagEntry.name) + "\" has incorrect channel count"); | |||
| } | |||
| @@ -643,8 +641,7 @@ public: | |||
| for (auto tagEntry : knownTags) | |||
| { | |||
| AudioChannelLayout layout { tagEntry.tag }; | |||
| auto labels = CoreAudioLayouts::getCoreAudioLayoutChannels (layout); | |||
| auto labels = CoreAudioLayouts::getSpeakerLayoutForCoreAudioTag (tagEntry.tag); | |||
| labels.sort(); | |||
| for (int i = 0; i < (labels.size() - 1); ++i) | |||
| @@ -657,13 +654,9 @@ public: | |||
| beginTest ("CA speaker list and juce layouts are consistent"); | |||
| for (auto tagEntry : knownTags) | |||
| { | |||
| AudioChannelLayout layout { tagEntry.tag }; | |||
| expect (AudioChannelSet::channelSetWithChannels (CoreAudioLayouts::getCoreAudioLayoutChannels (layout)) | |||
| == CoreAudioLayouts::fromCoreAudio (layout), | |||
| expect (AudioChannelSet::channelSetWithChannels (CoreAudioLayouts::getSpeakerLayoutForCoreAudioTag (tagEntry.tag)) | |||
| == CoreAudioLayouts::fromCoreAudio (tagEntry.tag), | |||
| String ("Tag \"") + String (tagEntry.name) + "\" is not converted consistantly by JUCE"); | |||
| } | |||
| } | |||
| { | |||
| @@ -674,9 +667,7 @@ public: | |||
| if (tagEntry.equivalentChannelSet.isDisabled()) | |||
| continue; | |||
| AudioChannelLayout layout { tagEntry.tag }; | |||
| expect (CoreAudioLayouts::fromCoreAudio (layout) == tagEntry.equivalentChannelSet, | |||
| expect (CoreAudioLayouts::fromCoreAudio (tagEntry.tag) == tagEntry.equivalentChannelSet, | |||
| String ("Documentation for tag \"") + String (tagEntry.name) + "\" is incorrect"); | |||
| } | |||
| } | |||
| @@ -1818,12 +1818,7 @@ private: | |||
| if (numChannels != tagNumChannels) | |||
| return kAudioUnitErr_FormatNotSupported; | |||
| AudioChannelLayout layout; | |||
| zerostruct (layout); | |||
| layout.mChannelLayoutTag = currentLayoutTag; | |||
| requestedBuses.add (CoreAudioLayouts::fromCoreAudio (layout)); | |||
| requestedBuses.add (CoreAudioLayouts::fromCoreAudio (currentLayoutTag)); | |||
| } | |||
| } | |||
| @@ -1909,7 +1904,7 @@ private: | |||
| auto& knownTags = CoreAudioLayouts::getKnownCoreAudioTags(); | |||
| for (auto tag : knownTags) | |||
| if (bus->isLayoutSupported (CoreAudioLayouts::fromCoreAudio (AudioChannelLayout {tag}))) | |||
| if (bus->isLayoutSupported (CoreAudioLayouts::fromCoreAudio (tag))) | |||
| tags.addIfNotAlreadyThere (tag); | |||
| #endif | |||
| @@ -629,11 +629,7 @@ public: | |||
| if (layoutTag != 0) | |||
| { | |||
| AudioChannelLayout caLayout; | |||
| zerostruct (caLayout); | |||
| caLayout.mChannelLayoutTag = layoutTag; | |||
| AudioChannelSet newLayout = CoreAudioLayouts::fromCoreAudio (caLayout); | |||
| AudioChannelSet newLayout = CoreAudioLayouts::fromCoreAudio (layoutTag); | |||
| if (newLayout.size() != newNumChannels) | |||
| return false; | |||
| @@ -714,13 +710,7 @@ public: | |||
| const AudioChannelLayoutTag layoutTag = (layout != nullptr ? [layout layoutTag] : 0); | |||
| if (layoutTag != 0) | |||
| { | |||
| AudioChannelLayout caLayout; | |||
| zerostruct (caLayout); | |||
| caLayout.mChannelLayoutTag = layoutTag; | |||
| newLayout = CoreAudioLayouts::fromCoreAudio (caLayout); | |||
| } | |||
| newLayout = CoreAudioLayouts::fromCoreAudio (layoutTag); | |||
| else | |||
| newLayout = bus->supportedLayoutWithChannels (static_cast<int> ([format channelCount])); | |||