Jamoma API  0.6.0.a19
AUDispatch.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 "AUBase.h"
42 #include "CAXException.h"
43 
44 
45 
46 #if TARGET_OS_MAC
47  #if __LP64__
48  // comp instance, parameters in forward order
49  #define PARAM(_typ, _name, _index, _nparams) \
50  _typ _name = *(_typ *)&params->params[_index + 1];
51  #else
52  // parameters in reverse order, then comp instance
53  #define PARAM(_typ, _name, _index, _nparams) \
54  _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
55  #endif
56 #elif TARGET_OS_WIN32
57  // (no comp instance), parameters in forward order
58  #define PARAM(_typ, _name, _index, _nparams) \
59  _typ _name = *(_typ *)&params->params[_index];
60 #endif
61 
62 
63 #if AU_DEBUG_DISPATCHER
64  #include "AUDebugDispatcher.h"
65 
66  #define INIT_DEBUG_DISPATCHER(This) \
67  UInt64 nowTime = 0; \
68  if (This->mDebugDispatcher != NULL) \
69  nowTime = CAHostTimeBase::GetTheCurrentTime();
70 #endif
71 
72 OSStatus AUBase::ComponentEntryDispatch(ComponentParameters *params, AUBase *This)
73 {
74  if (This == NULL) return paramErr;
75 
76 #if AU_DEBUG_DISPATCHER
77  INIT_DEBUG_DISPATCHER(This)
78 #endif
79 
80  OSStatus result = noErr;
81 
82  switch (params->what) {
83  case kComponentCanDoSelect:
84  switch (params->params[0]) {
85  // any selectors
86  case kAudioUnitInitializeSelect:
87  case kAudioUnitUninitializeSelect:
88  case kAudioUnitGetPropertyInfoSelect:
89  case kAudioUnitGetPropertySelect:
90  case kAudioUnitSetPropertySelect:
91  case kAudioUnitAddPropertyListenerSelect:
92 #if (!__LP64__)
93  case kAudioUnitRemovePropertyListenerSelect:
94 #endif
95  case kAudioUnitGetParameterSelect:
96  case kAudioUnitSetParameterSelect:
97  case kAudioUnitResetSelect:
98  result = 1;
99  break;
100  // v1 selectors
101 
102  // v2 selectors
103  case kAudioUnitRemovePropertyListenerWithUserDataSelect:
104  case kAudioUnitAddRenderNotifySelect:
105  case kAudioUnitRemoveRenderNotifySelect:
106  case kAudioUnitScheduleParametersSelect:
107  case kAudioUnitRenderSelect:
108  result = (This->AudioUnitAPIVersion() > 1);
109  break;
110 
111  default:
112  return ComponentBase::ComponentEntryDispatch(params, This);
113  }
114  break;
115 
116  case kAudioUnitInitializeSelect:
117  {
118  result = This->DoInitialize();
119 
120  #if AU_DEBUG_DISPATCHER
121  if (This->mDebugDispatcher)
122  This->mDebugDispatcher->Initialize (nowTime, result);
123  #endif
124  }
125  break;
126 
127  case kAudioUnitUninitializeSelect:
128  {
129  This->DoCleanup();
130  result = noErr;
131 
132  #if AU_DEBUG_DISPATCHER
133  if (This->mDebugDispatcher)
134  This->mDebugDispatcher->Uninitialize (nowTime, result);
135  #endif
136  }
137  break;
138 
139  case kAudioUnitGetPropertyInfoSelect:
140  {
141  PARAM(AudioUnitPropertyID, pinID, 0, 5);
142  PARAM(AudioUnitScope, pinScope, 1, 5);
143  PARAM(AudioUnitElement, pinElement, 2, 5);
144  PARAM(UInt32 *, poutDataSize, 3, 5);
145  PARAM(Boolean *, poutWritable, 4, 5);
146 
147  // pass our own copies so that we assume responsibility for testing
148  // the caller's pointers against null and our C++ classes can
149  // always assume they're non-null
150  UInt32 dataSize;
151  Boolean writable;
152 
153  result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
154  if (poutDataSize != NULL)
155  *poutDataSize = dataSize;
156  if (poutWritable != NULL)
157  *poutWritable = writable;
158 
159  #if AU_DEBUG_DISPATCHER
160  if (This->mDebugDispatcher)
161  This->mDebugDispatcher->GetPropertyInfo (nowTime, result, pinID, pinScope, pinElement,
162  poutDataSize, poutWritable);
163  #endif
164 
165 
166  }
167  break;
168 
169  case kAudioUnitGetPropertySelect:
170  {
171  PARAM(AudioUnitPropertyID, pinID, 0, 5);
172  PARAM(AudioUnitScope, pinScope, 1, 5);
173  PARAM(AudioUnitElement, pinElement, 2, 5);
174  PARAM(void *, poutData, 3, 5);
175  PARAM(UInt32 *, pioDataSize, 4, 5);
176 
177  UInt32 actualPropertySize, clientBufferSize;
178  Boolean writable;
179  char *tempBuffer;
180  void *destBuffer;
181 
182  if (pioDataSize == NULL) {
183  ca_debug_string("AudioUnitGetProperty: null size pointer");
184  result = paramErr;
185  goto finishGetProperty;
186  }
187  if (poutData == NULL) {
188  UInt32 dataSize;
189 
190  result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
191  *pioDataSize = dataSize;
192  goto finishGetProperty;
193  }
194 
195  clientBufferSize = *pioDataSize;
196  if (clientBufferSize == 0)
197  {
198  ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
199  // $$$ or should we allow this as a shortcut for finding the size?
200  result = paramErr;
201  goto finishGetProperty;
202  }
203 
204  result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement,
205  actualPropertySize, writable);
206  if (result)
207  goto finishGetProperty;
208 
209  if (clientBufferSize < actualPropertySize)
210  {
211  tempBuffer = new char[actualPropertySize];
212  destBuffer = tempBuffer;
213  } else {
214  tempBuffer = NULL;
215  destBuffer = poutData;
216  }
217 
218  result = This->DispatchGetProperty(pinID, pinScope, pinElement, destBuffer);
219 
220  if (result == noErr) {
221  if (clientBufferSize < actualPropertySize)
222  {
223  memcpy(poutData, tempBuffer, clientBufferSize);
224  delete[] tempBuffer;
225  // pioDataSize remains correct, the number of bytes we wrote
226  } else
227  *pioDataSize = actualPropertySize;
228  } else
229  *pioDataSize = 0;
230 
231  finishGetProperty:
232 
233  #if AU_DEBUG_DISPATCHER
234  if (This->mDebugDispatcher)
235  This->mDebugDispatcher->GetProperty (nowTime, result, pinID, pinScope, pinElement,
236  pioDataSize, poutData);
237  #else
238  ;
239  #endif
240 
241  }
242  break;
243 
244  case kAudioUnitSetPropertySelect:
245  {
246  PARAM(AudioUnitPropertyID, pinID, 0, 5);
247  PARAM(AudioUnitScope, pinScope, 1, 5);
248  PARAM(AudioUnitElement, pinElement, 2, 5);
249  PARAM(const void *, pinData, 3, 5);
250  PARAM(UInt32, pinDataSize, 4, 5);
251 
252  if (pinData && pinDataSize)
253  result = This->DispatchSetProperty(pinID, pinScope, pinElement, pinData, pinDataSize);
254  else {
255  if (pinData == NULL && pinDataSize == 0) {
256  result = This->DispatchRemovePropertyValue (pinID, pinScope, pinElement);
257  } else {
258  if (pinData == NULL) {
259  ca_debug_string("AudioUnitSetProperty: inData == NULL");
260  result = paramErr;
261  goto finishSetProperty;
262  }
263 
264  if (pinDataSize == 0) {
265  ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
266  result = paramErr;
267  goto finishSetProperty;
268  }
269  }
270  }
271  finishSetProperty:
272 
273  #if AU_DEBUG_DISPATCHER
274  if (This->mDebugDispatcher)
275  This->mDebugDispatcher->SetProperty (nowTime, result, pinID, pinScope, pinElement,
276  pinData, pinDataSize);
277  #else
278  ;
279  #endif
280 
281  }
282  break;
283 
284  case kAudioUnitAddPropertyListenerSelect:
285  {
286  PARAM(AudioUnitPropertyID, pinID, 0, 3);
287  PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
288  PARAM(void *, pinProcRefCon, 2, 3);
289  result = This->AddPropertyListener(pinID, pinProc, pinProcRefCon);
290  }
291  break;
292 
293 #if (!__LP64__)
294  case kAudioUnitRemovePropertyListenerSelect:
295  {
296  PARAM(AudioUnitPropertyID, pinID, 0, 2);
297  PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 2);
298  result = This->RemovePropertyListener(pinID, pinProc, NULL, false);
299  }
300  break;
301 #endif
302 
303  case kAudioUnitRemovePropertyListenerWithUserDataSelect:
304  {
305  PARAM(AudioUnitPropertyID, pinID, 0, 3);
306  PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
307  PARAM(void *, pinProcRefCon, 2, 3);
308  result = This->RemovePropertyListener(pinID, pinProc, pinProcRefCon, true);
309  }
310  break;
311 
312  case kAudioUnitAddRenderNotifySelect:
313  {
314  PARAM(AURenderCallback, pinProc, 0, 2);
315  PARAM(void *, pinProcRefCon, 1, 2);
316  result = This->SetRenderNotification (pinProc, pinProcRefCon);
317  }
318  break;
319 
320  case kAudioUnitRemoveRenderNotifySelect:
321  {
322  PARAM(AURenderCallback, pinProc, 0, 2);
323  PARAM(void *, pinProcRefCon, 1, 2);
324  result = This->RemoveRenderNotification (pinProc, pinProcRefCon);
325  }
326  break;
327 
328  case kAudioUnitGetParameterSelect:
329  {
330  PARAM(AudioUnitParameterID, pinID, 0, 4);
331  PARAM(AudioUnitScope, pinScope, 1, 4);
332  PARAM(AudioUnitElement, pinElement, 2, 4);
333  PARAM(AudioUnitParameterValue *, poutValue, 3, 4);
334  result = (poutValue == NULL ? paramErr : This->GetParameter(pinID, pinScope, pinElement, *poutValue));
335  }
336  break;
337 
338  case kAudioUnitSetParameterSelect:
339  {
340  PARAM(AudioUnitParameterID, pinID, 0, 5);
341  PARAM(AudioUnitScope, pinScope, 1, 5);
342  PARAM(AudioUnitElement, pinElement, 2, 5);
343  PARAM(AudioUnitParameterValue, pinValue, 3, 5);
344  PARAM(UInt32, pinBufferOffsetInFrames, 4, 5);
345  result = This->SetParameter(pinID, pinScope, pinElement, pinValue, pinBufferOffsetInFrames);
346  }
347  break;
348 
349  case kAudioUnitScheduleParametersSelect:
350  {
351  if (This->AudioUnitAPIVersion() > 1)
352  {
353  PARAM(AudioUnitParameterEvent *, pinParameterEvent, 0, 2);
354  PARAM(UInt32, pinNumParamEvents, 1, 2);
355  result = This->ScheduleParameter (pinParameterEvent, pinNumParamEvents);
356  } else
357  result = badComponentSelector;
358  }
359  break;
360 
361 
362  case kAudioUnitRenderSelect:
363  {
364  {
365  PARAM(AudioUnitRenderActionFlags *, pinActionFlags, 0, 5);
366  PARAM(const AudioTimeStamp *, pinTimeStamp, 1, 5);
367  PARAM(UInt32, pinOutputBusNumber, 2, 5);
368  PARAM(UInt32, pinNumberFrames, 3, 5);
369  PARAM(AudioBufferList *, pioData, 4, 5);
370  AudioUnitRenderActionFlags tempFlags;
371 
372  if (pinTimeStamp == NULL || pioData == NULL)
373  result = paramErr;
374  else {
375  if (pinActionFlags == NULL) {
376  tempFlags = 0;
377  pinActionFlags = &tempFlags;
378  }
379  result = This->DoRender(*pinActionFlags, *pinTimeStamp, pinOutputBusNumber, pinNumberFrames, *pioData);
380  }
381 
382  #if AU_DEBUG_DISPATCHER
383  if (This->mDebugDispatcher)
384  This->mDebugDispatcher->Render (nowTime, result, pinActionFlags, pinTimeStamp,
385  pinOutputBusNumber, pinNumberFrames, pioData);
386  #endif
387  }
388  }
389  break;
390 
391  case kAudioUnitResetSelect:
392  {
393  PARAM(AudioUnitScope, pinScope, 0, 2);
394  PARAM(AudioUnitElement, pinElement, 1, 2);
395  This->mLastRenderedSampleTime = -1;
396  result = This->Reset(pinScope, pinElement);
397  }
398  break;
399 
400  default:
401  result = ComponentBase::ComponentEntryDispatch(params, This);
402  break;
403  }
404 
405  return result;
406 }
407 
408 // Fast dispatch entry points -- these need to replicate all error-checking logic from above
409 
410 OSStatus AudioUnitBaseGetParameter( AUBase * This,
411  AudioUnitParameterID inID,
412  AudioUnitScope inScope,
413  AudioUnitElement inElement,
414  float *outValue)
415 {
416  OSStatus result = AUBase::noErr;
417 
418  try {
419  if (This == NULL || outValue == NULL) return AUBase::paramErr;
420  result = This->GetParameter(inID, inScope, inElement, *outValue);
421  }
422  COMPONENT_CATCH
423 
424  return result;
425 }
426 
427 OSStatus AudioUnitBaseSetParameter( AUBase * This,
428  AudioUnitParameterID inID,
429  AudioUnitScope inScope,
430  AudioUnitElement inElement,
431  float inValue,
432  UInt32 inBufferOffset)
433 {
434  OSStatus result = AUBase::noErr;
435 
436  try {
437  if (This == NULL) return AUBase::paramErr;
438  result = This->SetParameter(inID, inScope, inElement, inValue, inBufferOffset);
439  }
440  COMPONENT_CATCH
441 
442  return result;
443 }
444 
445 OSStatus AudioUnitBaseRender( AUBase * This,
446  AudioUnitRenderActionFlags *ioActionFlags,
447  const AudioTimeStamp * inTimeStamp,
448  UInt32 inBusNumber,
449  UInt32 inNumberFrames,
450  AudioBufferList * ioData)
451 {
452  if (inTimeStamp == NULL || ioData == NULL) return AUBase::paramErr;
453 
454 #if AU_DEBUG_DISPATCHER
455  INIT_DEBUG_DISPATCHER(This)
456 #endif
457 
458  OSStatus result = AUBase::noErr;
459  AudioUnitRenderActionFlags tempFlags;
460 
461  try {
462  if (ioActionFlags == NULL) {
463  tempFlags = 0;
464  ioActionFlags = &tempFlags;
465  }
466  result = This->DoRender(*ioActionFlags, *inTimeStamp, inBusNumber, inNumberFrames, *ioData);
467  }
468  COMPONENT_CATCH
469 
470  #if AU_DEBUG_DISPATCHER
471  if (This->mDebugDispatcher)
472  This->mDebugDispatcher->Render (nowTime, result, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
473  #endif
474 
475  return result;
476 }