Jamoma API  0.6.0.a19
MusicDeviceBase.cpp
1 /* Copyright © 2007 Apple Inc. All Rights Reserved.
2 
3  Disclaimer: IMPORTANT: This Apple software is supplied to you by
4  Apple Inc. ("Apple") in consideration of your agreement to the
5  following terms, and your use, installation, modification or
6  redistribution of this Apple software constitutes acceptance of these
7  terms. If you do not agree with these terms, please do not use,
8  install, modify or redistribute this Apple software.
9 
10  In consideration of your agreement to abide by the following terms, and
11  subject to these terms, Apple grants you a personal, non-exclusive
12  license, under Apple's copyrights in this original Apple software (the
13  "Apple Software"), to use, reproduce, modify and redistribute the Apple
14  Software, with or without modifications, in source and/or binary forms;
15  provided that if you redistribute the Apple Software in its entirety and
16  without modifications, you must retain this notice and the following
17  text and disclaimers in all such redistributions of the Apple Software.
18  Neither the name, trademarks, service marks or logos of Apple Inc.
19  may be used to endorse or promote products derived from the Apple
20  Software without specific prior written permission from Apple. Except
21  as expressly stated in this notice, no other rights or licenses, express
22  or implied, are granted by Apple herein, including but not limited to
23  any patent rights that may be infringed by your derivative works or by
24  other works in which the Apple Software may be incorporated.
25 
26  The Apple Software is provided by Apple on an "AS IS" basis. APPLE
27  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
28  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
29  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
30  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
31 
32  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
33  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
36  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
37  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
38  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
39  POSSIBILITY OF SUCH DAMAGE.
40 */
41 #include "MusicDeviceBase.h"
42 
43 // compatibility with older OS SDK releases
44 typedef OSStatus
45 (*TEMP_MusicDeviceMIDIEventProc)( void * inComponentStorage,
46  UInt32 inStatus,
47  UInt32 inData1,
48  UInt32 inData2,
49  UInt32 inOffsetSampleFrame);
50 
51 typedef OSStatus
52 (*TEMP_MusicDeviceStartNoteProc)( void * inComponentStorage,
53  MusicDeviceInstrumentID inInstrument,
54  MusicDeviceGroupID inGroupID,
55  NoteInstanceID * outNoteInstanceID,
56  UInt32 inOffsetSampleFrame,
57  const MusicDeviceNoteParams * inParams);
58 
59 typedef OSStatus
60 (*TEMP_MusicDeviceStopNoteProc)(void * inComponentStorage,
61  MusicDeviceGroupID inGroupID,
62  NoteInstanceID inNoteInstanceID,
63  UInt32 inOffsetSampleFrame);
64 
65 
66 static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
67  UInt32 inStatus,
68  UInt32 inData1,
69  UInt32 inData2,
70  UInt32 inOffsetSampleFrame);
71 
72 static OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
73  MusicDeviceInstrumentID inInstrument,
74  MusicDeviceGroupID inGroupID,
75  NoteInstanceID * outNoteInstanceID,
76  UInt32 inOffsetSampleFrame,
77  const MusicDeviceNoteParams * inParams);
78 
79 static OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
80  MusicDeviceGroupID inGroupID,
81  NoteInstanceID inNoteInstanceID,
82  UInt32 inOffsetSampleFrame);
83 
84 
85 
86 MusicDeviceBase::MusicDeviceBase(AudioComponentInstance inInstance,
87  UInt32 numInputs,
88  UInt32 numOutputs,
89  UInt32 numGroups,
90  UInt32 numParts)
91  : AUBase(inInstance, numInputs, numOutputs, numGroups, numParts),
92  AUMIDIBase(this)
93 {
94 }
95 
96 OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID,
97  AudioUnitScope inScope,
98  AudioUnitElement inElement,
99  UInt32 & outDataSize,
100  Boolean & outWritable)
101 {
102  OSStatus result;
103 
104  switch (inID)
105  {
106  case kMusicDeviceProperty_InstrumentCount:
107  if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
108  outDataSize = sizeof(UInt32);
109  outWritable = false;
110  result = noErr;
111  break;
112 
113  default:
114  result = AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
115 
116  if (result == kAudioUnitErr_InvalidProperty)
117  result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
118  break;
119  }
120  return result;
121 }
122 
123 OSStatus MusicDeviceBase::GetProperty( AudioUnitPropertyID inID,
124  AudioUnitScope inScope,
125  AudioUnitElement inElement,
126  void * outData)
127 {
128  OSStatus result;
129 
130  switch (inID)
131  {
132 #if !CA_AU_IS_ONLY_PLUGIN
133  case kAudioUnitProperty_FastDispatch:
134  if (inElement == kMusicDeviceMIDIEventSelect) {
135  *(TEMP_MusicDeviceMIDIEventProc *)outData = MusicDeviceBaseMIDIEvent;
136  return noErr;
137  }
138  else if (inElement == kMusicDeviceStartNoteSelect) {
139  *(TEMP_MusicDeviceStartNoteProc *)outData = MusicDeviceBaseStartNote;
140  return noErr;
141  }
142  else if (inElement == kMusicDeviceStopNoteSelect) {
143  *(TEMP_MusicDeviceStopNoteProc *)outData = MusicDeviceBaseStopNote;
144  return noErr;
145  }
146  return kAudioUnitErr_InvalidElement;
147 #endif
148 
149  case kMusicDeviceProperty_InstrumentCount:
150  if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
151  return GetInstrumentCount (*(UInt32*)outData);
152 
153  default:
154  result = AUBase::GetProperty (inID, inScope, inElement, outData);
155 
156  if (result == kAudioUnitErr_InvalidProperty)
157  result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
158  }
159 
160  return result;
161 }
162 
163 
164 OSStatus MusicDeviceBase::SetProperty( AudioUnitPropertyID inID,
165  AudioUnitScope inScope,
166  AudioUnitElement inElement,
167  const void * inData,
168  UInt32 inDataSize)
169 
170 {
171 
172  OSStatus result = AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
173 
174  if (result == kAudioUnitErr_InvalidProperty)
175  result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
176 
177  return result;
178 }
179 
180 // For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral)
181 // then this call should return an instrument count of zero and noErr
182 OSStatus MusicDeviceBase::GetInstrumentCount (UInt32 &outInstCount) const
183 {
184  outInstCount = 0;
185  return noErr;
186 }
187 
188 OSStatus MusicDeviceBase::HandleNoteOn( UInt8 inChannel,
189  UInt8 inNoteNumber,
190  UInt8 inVelocity,
191  UInt32 inStartFrame)
192 {
193  MusicDeviceNoteParams params;
194  params.argCount = 2;
195  params.mPitch = inNoteNumber;
196  params.mVelocity = inVelocity;
197  return StartNote (kMusicNoteEvent_UseGroupInstrument, inChannel, NULL, inStartFrame, params);
198 }
199 
200 OSStatus MusicDeviceBase::HandleNoteOff( UInt8 inChannel,
201  UInt8 inNoteNumber,
202  UInt8 inVelocity,
203  UInt32 inStartFrame)
204 {
205  return StopNote (inChannel, inNoteNumber, inStartFrame);
206 }
207 
208 OSStatus
209 MusicDeviceBase::HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument,
210  MusicDeviceGroupID inGroupID,
211  NoteInstanceID * outNoteInstanceID,
212  UInt32 inOffsetSampleFrame,
213  const MusicDeviceNoteParams * inParams)
214 {
215  if (inParams == NULL || outNoteInstanceID == NULL) return paramErr;
216 
217  if (!IsInitialized()) return kAudioUnitErr_Uninitialized;
218 
219  return StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
220 }
221 
222 #if TARGET_OS_MAC
223  #if __LP64__
224  // comp instance, parameters in forward order
225  #define PARAM(_typ, _name, _index, _nparams) \
226  _typ _name = *(_typ *)&params->params[_index + 1];
227  #else
228  // parameters in reverse order, then comp instance
229  #define PARAM(_typ, _name, _index, _nparams) \
230  _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
231  #endif
232 #elif TARGET_OS_WIN32
233  // (no comp instance), parameters in forward order
234  #define PARAM(_typ, _name, _index, _nparams) \
235  _typ _name = *(_typ *)&params->params[_index];
236 #endif
237 
238 #if !TARGET_OS_IPHONE
239 OSStatus MusicDeviceBase::ComponentEntryDispatch( ComponentParameters * params,
240  MusicDeviceBase * This)
241 {
242  if (This == NULL) return paramErr;
243 
244  OSStatus result;
245 
246  switch (params->what) {
247  case kMusicDeviceMIDIEventSelect:
248  case kMusicDeviceSysExSelect:
249  {
250  result = AUMIDIBase::ComponentEntryDispatch (params, This);
251  }
252  break;
253  case kMusicDevicePrepareInstrumentSelect:
254  {
255  PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
256  result = This->PrepareInstrument(inInstrument);
257  }
258  break;
259  case kMusicDeviceReleaseInstrumentSelect:
260  {
261  PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
262  result = This->ReleaseInstrument(inInstrument);
263  }
264  break;
265  case kMusicDeviceStartNoteSelect:
266  {
267  PARAM(MusicDeviceInstrumentID, pbinInstrument, 0, 5);
268  PARAM(MusicDeviceGroupID, pbinGroupID, 1, 5);
269  PARAM(NoteInstanceID *, pboutNoteInstanceID, 2, 5);
270  PARAM(UInt32, pbinOffsetSampleFrame, 3, 5);
271  PARAM(const MusicDeviceNoteParams *, pbinParams, 4, 5);
272  result = This->HandleStartNoteMessage(pbinInstrument, pbinGroupID, pboutNoteInstanceID, pbinOffsetSampleFrame, pbinParams);
273  }
274  break;
275  case kMusicDeviceStopNoteSelect:
276  {
277  PARAM(MusicDeviceGroupID, pbinGroupID, 0, 3);
278  PARAM(NoteInstanceID, pbinNoteInstanceID, 1, 3);
279  PARAM(UInt32, pbinOffsetSampleFrame, 2, 3);
280  result = This->StopNote(pbinGroupID, pbinNoteInstanceID, pbinOffsetSampleFrame);
281  }
282  break;
283 
284  default:
285  result = AUBase::ComponentEntryDispatch(params, This);
286  break;
287  }
288 
289  return result;
290 }
291 #endif
292 
293 
294 // fast dispatch
295 static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
296  UInt32 inStatus,
297  UInt32 inData1,
298  UInt32 inData2,
299  UInt32 inOffsetSampleFrame)
300 {
301  OSStatus result = noErr;
302  try {
303  MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
304  if (This == NULL) return paramErr;
305  result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
306  }
307  COMPONENT_CATCH
308  return result;
309 }
310 
311 OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
312  MusicDeviceInstrumentID inInstrument,
313  MusicDeviceGroupID inGroupID,
314  NoteInstanceID * outNoteInstanceID,
315  UInt32 inOffsetSampleFrame,
316  const MusicDeviceNoteParams * inParams)
317 {
318  OSStatus result = noErr;
319  try {
320  if (inParams == NULL || outNoteInstanceID == NULL) return paramErr;
321  MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
322  if (This == NULL) return paramErr;
323  result = This->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
324  }
325  COMPONENT_CATCH
326  return result;
327 }
328 
329 OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
330  MusicDeviceGroupID inGroupID,
331  NoteInstanceID inNoteInstanceID,
332  UInt32 inOffsetSampleFrame)
333 {
334  OSStatus result = noErr;
335  try {
336  MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
337  if (This == NULL) return paramErr;
338  result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
339  }
340  COMPONENT_CATCH
341  return result;
342 }
343