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