1 /*
2      File: CAAUMIDIMapManager.cpp
3  Abstract: CAAUMIDIMapManager.h
4   Version: 1.1
5 
6  Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
7  Inc. ("Apple") in consideration of your agreement to the following
8  terms, and your use, installation, modification or redistribution of
9  this Apple software constitutes acceptance of these terms.  If you do
10  not agree with these terms, please do not use, install, modify or
11  redistribute this Apple software.
12 
13  In consideration of your agreement to abide by the following terms, and
14  subject to these terms, Apple grants you a personal, non-exclusive
15  license, under Apple's copyrights in this original Apple software (the
16  "Apple Software"), to use, reproduce, modify and redistribute the Apple
17  Software, with or without modifications, in source and/or binary forms;
18  provided that if you redistribute the Apple Software in its entirety and
19  without modifications, you must retain this notice and the following
20  text and disclaimers in all such redistributions of the Apple Software.
21  Neither the name, trademarks, service marks or logos of Apple Inc. may
22  be used to endorse or promote products derived from the Apple Software
23  without specific prior written permission from Apple.  Except as
24  expressly stated in this notice, no other rights or licenses, express or
25  implied, are granted by Apple herein, including but not limited to any
26  patent rights that may be infringed by your derivative works or by other
27  works in which the Apple Software may be incorporated.
28 
29  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
30  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 
35  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42  POSSIBILITY OF SUCH DAMAGE.
43 
44  Copyright (C) 2014 Apple Inc. All Rights Reserved.
45 
46 */
47 #include "CAAUMIDIMapManager.h"
48 #include <AudioToolbox/AudioUnitUtilities.h>
49 
CAAUMIDIMapManager()50 CAAUMIDIMapManager::CAAUMIDIMapManager()
51 {
52 	hotMapping = false;
53 }
54 
FillInMap(CAAUMIDIMap & map,AUBase & That)55 static void FillInMap (CAAUMIDIMap &map, AUBase &That)
56 {
57 	AudioUnitParameterInfo info;
58 	That.GetParameterInfo (map.mScope, map.mParameterID, info);
59 
60 	if (map.IsSubRange()) {
61 		map.mMinValue = map.mSubRangeMin;
62 		map.mMaxValue = map.mSubRangeMax;
63 	} else {
64 		map.mMinValue = info.minValue;
65 		map.mMaxValue = info.maxValue;
66 	}
67 
68 	map.mTransType = CAAUMIDIMap::GetTransformer(info.flags);
69 }
70 
SortedInsertToParamaterMaps(AUParameterMIDIMapping * maps,UInt32 inNumMaps,AUBase & That)71 OSStatus	CAAUMIDIMapManager::SortedInsertToParamaterMaps	(AUParameterMIDIMapping *maps, UInt32 inNumMaps, AUBase &That)
72 {
73 	for (unsigned int i = 0; i < inNumMaps; ++i)
74 	{
75 		CAAUMIDIMap map(maps[i]);
76 
77 		FillInMap (map, That);
78 
79 		int idx = FindParameterIndex (maps[i]);
80 		if (idx > -1)
81 			mParameterMaps.erase(mParameterMaps.begin() + idx);
82 
83 			// least disruptive place to put this is at the end
84 		mParameterMaps.push_back(map);
85 	}
86 
87 	std::sort(mParameterMaps.begin(), mParameterMaps.end(), CompareMIDIMap());
88 
89 	return noErr;
90 }
91 
GetHotParameterMap(AUParameterMIDIMapping & outMap)92 void CAAUMIDIMapManager::GetHotParameterMap(AUParameterMIDIMapping &outMap )
93 {
94 	outMap = mHotMap;
95 }
96 
SortedRemoveFromParameterMaps(AUParameterMIDIMapping * maps,UInt32 inNumMaps,bool & outMapDidChange)97 void CAAUMIDIMapManager::SortedRemoveFromParameterMaps(AUParameterMIDIMapping *maps, UInt32 inNumMaps, bool &outMapDidChange)
98 {
99 	if (hotMapping) {
100 		hotMapping = false;
101 	}
102 
103 	outMapDidChange = false;
104 	for (unsigned int i = 0; i < inNumMaps; ++i) {
105 		int idx = FindParameterIndex (maps[i]);
106 		if (idx > -1) {
107 			//mParameterMaps[idx].Print();
108 			mParameterMaps.erase(mParameterMaps.begin() + idx);
109 			outMapDidChange = true;
110 		}
111 	}
112 }
113 
ReplaceAllMaps(AUParameterMIDIMapping * inMappings,UInt32 inNumMaps,AUBase & That)114 void	CAAUMIDIMapManager::ReplaceAllMaps (AUParameterMIDIMapping* inMappings, UInt32 inNumMaps, AUBase &That)
115 {
116 	mParameterMaps.clear();
117 
118 	for (unsigned int i = 0; i < inNumMaps; ++i) {
119 		CAAUMIDIMap mapping(inMappings[i]);
120 
121 		FillInMap (mapping, That);
122 		mParameterMaps.push_back (mapping);
123 	}
124 
125 	std::sort(mParameterMaps.begin(),mParameterMaps.end(), CompareMIDIMap());
126 }
127 
HandleHotMapping(UInt8 inStatus,UInt8 inChannel,UInt8 inData1,AUBase & That)128 bool CAAUMIDIMapManager::HandleHotMapping(UInt8 	inStatus,
129 										  UInt8 	inChannel,
130 										  UInt8 	inData1,
131 										  AUBase	&That)
132 { //used to set the hot map info
133 
134 	if (inStatus == 0xf0) return false;
135 
136 	if (!hotMapping) return false;
137 	hotMapping = false;
138 
139 	mHotMap.mStatus = inStatus | inChannel;
140 	mHotMap.mData1 = inData1;
141 
142 	SortedInsertToParamaterMaps (&mHotMap, 1, That);
143 	return true;
144 }
145 
146 #if DEBUG
147 
Print()148 void CAAUMIDIMapManager::Print()
149 {
150 	for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
151 		CAAUMIDIMap* listmap =  &(*i);
152 		listmap->Print();
153 	}
154 }
155 
156 #endif // DEBUG
157 
GetMaps(AUParameterMIDIMapping * maps)158 void CAAUMIDIMapManager::GetMaps(AUParameterMIDIMapping* maps)
159 {
160 	int i = 0;
161 	for ( ParameterMaps::iterator iter = mParameterMaps.begin(); iter < mParameterMaps.end(); ++iter, ++i) {
162 		AUParameterMIDIMapping &listmap =  (*iter);
163 		maps[i] = listmap;
164 	}
165 }
166 
FindParameterIndex(AUParameterMIDIMapping & inMap)167 int CAAUMIDIMapManager::FindParameterIndex (AUParameterMIDIMapping &inMap)
168 {
169 	//used to get back hot mapping and one at a time maps, for ui
170 
171 	int idx = 0;
172 	for ( ParameterMaps::iterator i = mParameterMaps.begin(); i < mParameterMaps.end(); ++i) {
173 		CAAUMIDIMap & listmap =  (*i);
174 		if ( (listmap.mParameterID == inMap.mParameterID) &&
175 			 (listmap.mScope == inMap.mScope) &&
176 			 (listmap.mElement == inMap.mElement) )
177 		{
178 				return idx;
179 		}
180 		idx++;
181 	}
182 	return -1;
183 }
184 
FindParameterMapEventMatch(UInt8 inStatus,UInt8 inChannel,UInt8 inData1,UInt8 inData2,UInt32 inBufferOffset,AUBase & inAUBase)185 bool CAAUMIDIMapManager::FindParameterMapEventMatch(	UInt8			inStatus,
186 														UInt8			inChannel,
187 														UInt8			inData1,
188 														UInt8			inData2,
189 														UInt32			inBufferOffset,
190 														AUBase&			inAUBase)
191 {
192 	bool ret_value = false;
193 
194 	if (inStatus == 0x90 && !inData2)
195 		inStatus = 0x80 | inChannel;
196 
197 	//used to test for midi matches once map is made
198 	CAAUMIDIMap tempMap;
199 	tempMap.mStatus = inStatus | inChannel;
200 	tempMap.mData1 = inData1;
201 
202 	CompareMIDIMap compareObj;
203 
204 	AudioUnitEvent event;
205 	event.mEventType = kAudioUnitEvent_ParameterValueChange;
206 	event.mArgument.mParameter.mAudioUnit = inAUBase.GetComponentInstance();
207 
208 	ParameterMaps::iterator lower_iter =
209 	std::lower_bound(mParameterMaps.begin(), mParameterMaps.end(), tempMap, compareObj);
210 
211 	while (lower_iter < mParameterMaps.end())
212 	{
213 		CAAUMIDIMap & map = (*lower_iter);
214 		if (compareObj.Finish(map, tempMap))
215 			break;
216 
217 		Float32 value;
218 		if (map.MIDI_Matches(inChannel, inData1, inData2, value))
219 		{
220 			inAUBase.SetParameter ( map.mParameterID, map.mScope, map.mElement,
221 									map.ParamValueFromMIDILinear(value), inBufferOffset);
222 
223 			event.mArgument.mParameter.mParameterID = map.mParameterID;
224 			event.mArgument.mParameter.mScope = map.mScope;
225 			event.mArgument.mParameter.mElement = map.mElement;
226 
227 			AUEventListenerNotify(NULL, NULL, &event);
228 			ret_value = true;
229 		}
230 		++lower_iter;
231 	}
232 	return ret_value;
233 }
234