28e4d366bcaf3e24fe36f875d6100c5746bfb00e
[ardour.git] / libs / appleutility / CoreAudio / AudioUnits / AUPublic / OtherBases / MusicDeviceBase.cpp
1 /*
2      File: MusicDeviceBase.cpp
3  Abstract: MusicDeviceBase.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 "MusicDeviceBase.h"
48
49 // compatibility with older OS SDK releases
50 typedef OSStatus
51 (*TEMP_MusicDeviceMIDIEventProc)(       void *                  inComponentStorage,
52                                                         UInt32                                  inStatus,
53                                                         UInt32                                  inData1,
54                                                         UInt32                                  inData2,
55                                                         UInt32                                  inOffsetSampleFrame);
56
57 typedef OSStatus
58 (*TEMP_MusicDeviceStartNoteProc)(       void *                          inComponentStorage,
59                                                 MusicDeviceInstrumentID                 inInstrument,
60                                                 MusicDeviceGroupID                              inGroupID,
61                                                 NoteInstanceID *                                outNoteInstanceID,
62                                                 UInt32                                                  inOffsetSampleFrame,
63                                                 const MusicDeviceNoteParams *   inParams);
64
65 typedef OSStatus
66 (*TEMP_MusicDeviceStopNoteProc)(void *                                  inComponentStorage,
67                                                 MusicDeviceGroupID                              inGroupID,
68                                                 NoteInstanceID                                  inNoteInstanceID,
69                                                 UInt32                                                  inOffsetSampleFrame);
70
71 #if !CA_USE_AUDIO_PLUGIN_ONLY
72
73 static OSStatus         MusicDeviceBaseMIDIEvent(void *                 inComponentStorage,
74                                                 UInt32                          inStatus,
75                                                 UInt32                          inData1,
76                                                 UInt32                          inData2,
77                                                 UInt32                          inOffsetSampleFrame);
78
79 static OSStatus         MusicDeviceBaseStartNote(       void *          inComponentStorage,
80                                                 MusicDeviceInstrumentID                 inInstrument,
81                                                 MusicDeviceGroupID                              inGroupID,
82                                                 NoteInstanceID *                                outNoteInstanceID,
83                                                 UInt32                                                  inOffsetSampleFrame,
84                                                 const MusicDeviceNoteParams *   inParams);
85
86 static OSStatus         MusicDeviceBaseStopNote(void *                  inComponentStorage,
87                                                 MusicDeviceGroupID                              inGroupID,
88                                                 NoteInstanceID                                  inNoteInstanceID,
89                                                 UInt32                                                  inOffsetSampleFrame);
90
91 #endif
92
93 MusicDeviceBase::MusicDeviceBase(AudioComponentInstance                 inInstance, 
94                                                                         UInt32                                          numInputs,
95                                                                         UInt32                                          numOutputs,
96                                                                         UInt32                                          numGroups) 
97         : AUBase(inInstance, numInputs, numOutputs, numGroups),
98           AUMIDIBase(this)
99 {
100 }
101
102 OSStatus                        MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID    inID,
103                                                         AudioUnitScope                          inScope,
104                                                         AudioUnitElement                        inElement,
105                                                         UInt32 &                                outDataSize,
106                                                         Boolean &                               outWritable)
107 {
108         OSStatus result;
109         
110         switch (inID) 
111         {
112 #if !TARGET_OS_IPHONE
113                 case kMusicDeviceProperty_InstrumentCount:
114                         if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
115                         outDataSize = sizeof(UInt32);
116                         outWritable = false;
117                         result = noErr;
118                         break;
119 #endif
120                 default:
121                         result = AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
122                         
123                         if (result == kAudioUnitErr_InvalidProperty)
124                                 result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
125                         break;
126         }
127         return result;
128 }
129
130 OSStatus                        MusicDeviceBase::GetProperty(   AudioUnitPropertyID                     inID,
131                                                         AudioUnitScope                          inScope,
132                                                         AudioUnitElement                        inElement,
133                                                         void *                                  outData)
134 {
135         OSStatus result;
136
137         switch (inID) 
138         {
139 #if !CA_USE_AUDIO_PLUGIN_ONLY
140                 case kAudioUnitProperty_FastDispatch:
141                         if (!IsCMgrObject()) return kAudioUnitErr_InvalidProperty;
142                         if (inElement == kMusicDeviceMIDIEventSelect) {
143                                 *(TEMP_MusicDeviceMIDIEventProc *)outData = MusicDeviceBaseMIDIEvent;
144                                 return noErr;
145                         }
146                         else if (inElement == kMusicDeviceStartNoteSelect) {
147                                 *(TEMP_MusicDeviceStartNoteProc *)outData = MusicDeviceBaseStartNote;
148                                 return noErr;
149                         }       
150                         else if (inElement == kMusicDeviceStopNoteSelect) {
151                                 *(TEMP_MusicDeviceStopNoteProc *)outData = MusicDeviceBaseStopNote;
152                                 return noErr;
153                         }
154                         return kAudioUnitErr_InvalidElement;
155 #endif
156
157 #if !TARGET_OS_IPHONE
158                 case kMusicDeviceProperty_InstrumentCount:
159                         if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
160                         return GetInstrumentCount (*(UInt32*)outData);
161 #endif
162                 default:
163                         result = AUBase::GetProperty (inID, inScope, inElement, outData);
164                         
165                         if (result == kAudioUnitErr_InvalidProperty)
166                                 result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
167         }
168         
169         return result;
170 }
171
172
173 OSStatus                        MusicDeviceBase::SetProperty(   AudioUnitPropertyID                     inID,
174                                                         AudioUnitScope                          inScope,
175                                                         AudioUnitElement                        inElement,
176                                                         const void *                            inData,
177                                                         UInt32                                  inDataSize)
178
179 {
180
181         OSStatus result = AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
182                 
183         if (result == kAudioUnitErr_InvalidProperty)
184                 result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
185                 
186         return result;
187 }
188
189 // For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral)
190 // then this call should return an instrument count of zero and noErr
191 OSStatus                        MusicDeviceBase::GetInstrumentCount (UInt32 &outInstCount) const
192 {
193         outInstCount = 0;
194         return noErr;
195 }
196
197 OSStatus        MusicDeviceBase::HandleNoteOn(  UInt8   inChannel,
198                                                                                         UInt8   inNoteNumber,
199                                                                                         UInt8   inVelocity,
200                                                                                         UInt32  inStartFrame)
201 {
202         MusicDeviceNoteParams params;
203         params.argCount = 2;
204         params.mPitch = inNoteNumber;
205         params.mVelocity = inVelocity;
206         return StartNote (kMusicNoteEvent_UseGroupInstrument, inChannel, NULL, inStartFrame, params);
207 }
208                                                                                         
209 OSStatus        MusicDeviceBase::HandleNoteOff( UInt8   inChannel,
210                                                                                         UInt8   inNoteNumber,
211                                                                                         UInt8   inVelocity,
212                                                                                         UInt32  inStartFrame)
213 {
214         return StopNote (inChannel, inNoteNumber, inStartFrame);
215 }
216
217 OSStatus                        
218 MusicDeviceBase::HandleStartNoteMessage (MusicDeviceInstrumentID                inInstrument, 
219                                                                                 MusicDeviceGroupID                              inGroupID, 
220                                                                                 NoteInstanceID *                                outNoteInstanceID, 
221                                                                                 UInt32                                                  inOffsetSampleFrame, 
222                                                                                 const MusicDeviceNoteParams *   inParams)
223 {
224         if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
225
226         if (!IsInitialized()) return kAudioUnitErr_Uninitialized;
227         
228         return StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
229 }
230
231 #if TARGET_OS_MAC
232         #if __LP64__
233                 // comp instance, parameters in forward order
234                 #define PARAM(_typ, _name, _index, _nparams) \
235                         _typ _name = *(_typ *)&params->params[_index + 1];
236         #else
237                 // parameters in reverse order, then comp instance
238                 #define PARAM(_typ, _name, _index, _nparams) \
239                         _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
240         #endif
241 #elif TARGET_OS_WIN32
242                 // (no comp instance), parameters in forward order
243                 #define PARAM(_typ, _name, _index, _nparams) \
244                         _typ _name = *(_typ *)&params->params[_index];
245 #endif
246
247 #if !CA_USE_AUDIO_PLUGIN_ONLY
248 OSStatus                        MusicDeviceBase::ComponentEntryDispatch(        ComponentParameters *           params,
249                                                                                                                                 MusicDeviceBase *                       This)
250 {
251         if (This == NULL) return kAudio_ParamError;
252
253         OSStatus result;
254         
255         switch (params->what) {
256         case kMusicDeviceMIDIEventSelect:
257         case kMusicDeviceSysExSelect:
258                 {
259                         result = AUMIDIBase::ComponentEntryDispatch (params, This);
260                 }
261                 break;
262         case kMusicDevicePrepareInstrumentSelect:
263                 {
264                         PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
265                         result = This->PrepareInstrument(inInstrument);
266                 }
267                 break;
268         case kMusicDeviceReleaseInstrumentSelect:
269                 {
270                         PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
271                         result = This->ReleaseInstrument(inInstrument);
272                 }
273                 break;
274         case kMusicDeviceStartNoteSelect:
275                 {
276                         PARAM(MusicDeviceInstrumentID, pbinInstrument, 0, 5);
277                         PARAM(MusicDeviceGroupID, pbinGroupID, 1, 5);
278                         PARAM(NoteInstanceID *, pboutNoteInstanceID, 2, 5);
279                         PARAM(UInt32, pbinOffsetSampleFrame, 3, 5);
280                         PARAM(const MusicDeviceNoteParams *, pbinParams, 4, 5);
281                         result = This->HandleStartNoteMessage(pbinInstrument, pbinGroupID, pboutNoteInstanceID, pbinOffsetSampleFrame, pbinParams);
282                 }
283                 break;
284         case kMusicDeviceStopNoteSelect:
285                 {
286                         PARAM(MusicDeviceGroupID, pbinGroupID, 0, 3);
287                         PARAM(NoteInstanceID, pbinNoteInstanceID, 1, 3);
288                         PARAM(UInt32, pbinOffsetSampleFrame, 2, 3);
289                         result = This->StopNote(pbinGroupID, pbinNoteInstanceID, pbinOffsetSampleFrame);
290                 }
291                 break;
292
293         default:
294                 result = AUBase::ComponentEntryDispatch(params, This);
295                 break;
296         }
297         
298         return result;
299 }
300 #endif
301
302 #if !CA_USE_AUDIO_PLUGIN_ONLY
303
304 // fast dispatch
305 static OSStatus         MusicDeviceBaseMIDIEvent(void *                                 inComponentStorage,
306                                                 UInt32                                  inStatus,
307                                                 UInt32                                  inData1,
308                                                 UInt32                                  inData2,
309                                                 UInt32                                  inOffsetSampleFrame)
310 {
311         OSStatus result = noErr;
312         try {
313                 MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
314                 if (This == NULL) return kAudio_ParamError;
315                 result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
316         }
317         COMPONENT_CATCH
318         return result;
319 }
320
321 OSStatus                MusicDeviceBaseStartNote(       void *          inComponentStorage,
322                                                 MusicDeviceInstrumentID                 inInstrument,
323                                                 MusicDeviceGroupID                              inGroupID,
324                                                 NoteInstanceID *                                outNoteInstanceID,
325                                                 UInt32                                                  inOffsetSampleFrame,
326                                                 const MusicDeviceNoteParams *   inParams)
327 {
328         OSStatus result = noErr;
329         try {
330                 if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
331                 MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
332                 if (This == NULL) return kAudio_ParamError;
333                 result = This->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
334         }
335         COMPONENT_CATCH
336         return result;
337 }
338
339 OSStatus                MusicDeviceBaseStopNote(void *                  inComponentStorage,
340                                                 MusicDeviceGroupID                              inGroupID,
341                                                 NoteInstanceID                                  inNoteInstanceID,
342                                                 UInt32                                                  inOffsetSampleFrame)
343 {
344         OSStatus result = noErr;
345         try {
346                 MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
347                 if (This == NULL) return kAudio_ParamError;
348                 result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
349         }
350         COMPONENT_CATCH
351         return result;
352 }
353
354 #endif