1 
2 /*
3 #    Sfront, a SAOL to C translator
4 #    This file: audiounit audio driver for sfront
5 #
6 # Copyright (c) 1999-2008, Regents of the University of California
7 # All rights reserved.
8 #
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are
11 # met:
12 #
13 #  Redistributions of source code must retain the above copyright
14 #  notice, this list of conditions and the following disclaimer.
15 #
16 #  Redistributions in binary form must reproduce the above copyright
17 #  notice, this list of conditions and the following disclaimer in the
18 #  documentation and/or other materials provided with the distribution.
19 #
20 #  Neither the name of the University of California, Berkeley nor the
21 #  names of its contributors may be used to endorse or promote products
22 #  derived from this software without specific prior written permission.
23 #
24 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #
36 #    Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu
37 */
38 
39 
40 /****************************************************************/
41 /****************************************************************/
42 /*           Apple AudioUnit audio driver for sfront            */
43 /****************************************************************/
44 
45 /*~~~~~~~~~~~~~*/
46 /* debug level */
47 /*_____________*/
48 
49 /*  Level 0:  No debugging messages            */
50 /*  Level 1:  Session setup and error messages */
51 /*  Level 2:  + All MIDI events                */
52 /*  Level 3:  + All Rendering calls            */
53 
54 #if !defined(ASYS_AUDIOUNIT_DEBUG_LEVEL)
55 #define ASYS_AUDIOUNIT_DEBUG_LEVEL 0
56 #endif
57 
58 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
59 /* output clipping behavior */
60 /*__________________________*/
61 
62 #define ASYS_AUDIOUNIT_OUTPUT_CLIPPING  0
63 
64 /*~~~~~~~~~~~~~~~~~~~~~*/
65 /* aucontrol detection */
66 /*_____________________*/
67 
68 #if defined(CSYS_CDRIVER_AUCONTROL) || defined(CSYS_CDRIVER_AUCONTROLM)
69 #define ASYS_AUDIOUNIT_HAS_AUCONTROL  1
70 #else
71 #define ASYS_AUDIOUNIT_HAS_AUCONTROL  0
72 #endif
73 
74 #if defined(CSYS_CDRIVER_AUCONTROLM)
75 #define ASYS_AUDIOUNIT_MIDISUPPORT  1
76 #else
77 #define ASYS_AUDIOUNIT_MIDISUPPORT  0
78 #endif
79 
80 /*~~~~~~~~~~~~~~~~~~~*/
81 /* reentrant defines */
82 /*___________________*/
83 
84 #if (ENGINE_STYLE == ENGINE_REENTRANT)
85 #define MY_ENGINE_PTR        My->ENGINE_PTR
86 #define MY_ENGINE_PTR_COMMA  My->ENGINE_PTR,
87 #define MY_ENGINE_PTR_ASSIGNED_TO  My->ENGINE_PTR =
88 #define MY_ENGINE_PTR_DESTROY_SEMICOLON  free(MY_ENGINE_PTR);
89 #define MY_ENGINE_PTR_IS_NULL (MY_ENGINE_PTR == NULL)
90 #define MY_ENGINE_PTR_IS_NOT_NULL (MY_ENGINE_PTR != NULL)
91 #define ENGINE_MEMSTATUS_SEMICOLON(x) \
92         asysn_audiounit_memstatus(ENGINE_PTR, ENGINE_SIZE, x);
93 #else
94 #define MY_ENGINE_PTR
95 #define MY_ENGINE_PTR_COMMA
96 #define MY_ENGINE_PTR_ASSIGNED_TO
97 #define MY_ENGINE_PTR_DESTROY_SEMICOLON
98 #define MY_ENGINE_PTR_IS_NULL (0)
99 #define MY_ENGINE_PTR_IS_NOT_NULL (1)
100 #define ENGINE_MEMSTATUS_SEMICOLON(x)
101 #endif
102 
103 /*~~~~~~~~~~~~~~~~~*/
104 /* include headers */
105 /*_________________*/
106 
107 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
108 #include <CoreServices/CoreServices.h>
109 #include <AudioUnit/AudioUnit.h>
110 #include <AudioToolbox/AudioUnitUtilities.h>
111 #else
112 #include <ConditionalMacros.h>
113 #include <CoreServices.h>
114 #include <AudioUnit.h>
115 #include <AudioUnitUtilities.h>
116 #endif
117 
118 /* 64-bit integer headers */
119 
120 #include <stdint.h>
121 
122 /* for control driver socket system */
123 
124 #include <sys/types.h>
125 #include <sys/socket.h>
126 #include <unistd.h>
127 #include <sys/uio.h>
128 #include <fcntl.h>
129 
130 /* include files for memory paging */
131 
132 #include <sys/mman.h>
133 
134 /* include files for synchronization */
135 
136 #include <libkern/OSAtomic.h>
137 
138 /*~~~~~~~~~~~~~~~~~~*/
139 /* endian detection */
140 /*__________________*/
141 
142 Float32 asysn_audiounit_float32_endian_test = -1;
143 
144 #define ASYS_AUDIOUNIT_FLOAT32_BIGENDIAN \
145         ((((char *)(&asysn_audiounit_float32_endian_test))[0]) != 0)
146 
147 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
148 /*     audiounit defines     */
149 /*___________________________*/
150 
151 /* after if if-tree runs, only one audio type should be 1 */
152 
153 #if (!defined(ASYS_HASINPUT) && defined(ASYS_HASOUTPUT) && defined(ASYS_ACTIVE_O))
154 #define ASYS_AUDIOUNIT_MUSICDEVICE 1
155 #else
156 #define ASYS_AUDIOUNIT_MUSICDEVICE 0
157 #endif
158 
159 #if (defined(ASYS_HASINPUT) && defined(ASYS_HASOUTPUT) && defined(ASYS_ACTIVE_IO))
160 #define ASYS_AUDIOUNIT_EFFECT 1
161 #else
162 #define ASYS_AUDIOUNIT_EFFECT 0
163 #endif
164 
165 
166 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
167 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
168 /*  The Wiretap Macro Calls */
169 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
170 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
171 
172 /********************/
173 /* level one macros */
174 /********************/
175 
176 #if (ASYS_AUDIOUNIT_DEBUG_LEVEL >= 1)
177 
178 #define ASYS_AUDIOUNIT_WIRETAP(a, b) do {\
179       asysn_audiounit_wiretap(a, b);\
180       } while (0)
181 #define ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(a) do {\
182       asysn_audiounit_wiretap_putstring(a);\
183       } while (0)
184 #define ASYS_AUDIOUNIT_WIRETAP_PRINT_COMPONENT_RESULT(a) do {\
185       asysn_audiounit_wiretap_print_component_result(a);\
186       } while (0)
187 
188 #else
189 
190 #define ASYS_AUDIOUNIT_WIRETAP(a, b) do { } while (0)
191 #define ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(a) do { } while (0)
192 #define ASYS_AUDIOUNIT_WIRETAP_PRINT_COMPONENT_RESULT(a) do { } while (0)
193 
194 #endif
195 
196 /********************/
197 /* level two macros */
198 /********************/
199 
200 #if (ASYS_AUDIOUNIT_DEBUG_LEVEL >= 2)
201 
202 #define ASYS_AUDIOUNIT_WIRETAP_MIDIEVENT(a, b, c, d, e, f) do {\
203       asysn_audiounit_wiretap_midievent(a, b, c, d, e, f);\
204       } while (0)
205 #define ASYS_AUDIOUNIT_WIRETAP_M(a, b) do {\
206       asysn_audiounit_wiretap(a, b);\
207       } while (0)
208 #define ASYS_AUDIOUNIT_WIRETAP_GETPARAMETER(a, b, c, d, e, f) do {\
209       asysn_audiounit_wiretap_getparameter(a, b, c, d, e, f);\
210       } while (0)
211 #define ASYS_AUDIOUNIT_WIRETAP_SETPARAMETER(a, b, c, d, e, f, g) do {\
212       asysn_audiounit_wiretap_setparameter(a, b, c, d, e, f, g);\
213       } while (0)
214 #else
215 
216 #define ASYS_AUDIOUNIT_WIRETAP_MIDIEVENT(a, b, c, d, e, f) do { } while (0)
217 #define ASYS_AUDIOUNIT_WIRETAP_M(a, b) do { } while (0)
218 #define ASYS_AUDIOUNIT_WIRETAP_GETPARAMETER(a, b, c, d, e, f) do { } while (0)
219 #define ASYS_AUDIOUNIT_WIRETAP_SETPARAMETER(a, b, c, d, e, f, g) do { } while (0)
220 
221 #endif
222 
223 /**********************/
224 /* level three macros */
225 /**********************/
226 
227 #if (ASYS_AUDIOUNIT_DEBUG_LEVEL >= 3)
228 
229 #define ASYS_AUDIOUNIT_WIRETAP_RENDERER(a, b, c, d, e, f) do {\
230       asysn_audiounit_wiretap_renderer(a, b, c, d, e, f);\
231       } while (0)
232 #define ASYS_AUDIOUNIT_WIRETAP_R(a, b) do {\
233       asysn_audiounit_wiretap(a, b);\
234       } while (0)
235 
236 #else
237 
238 #define ASYS_AUDIOUNIT_WIRETAP_RENDERER(a, b, c, d, e, f) do { } while (0)
239 #define ASYS_AUDIOUNIT_WIRETAP_R(a, b) do { } while (0)
240 
241 #endif
242 
243 
244 /****************************************************************/
245 /*        Part One: Sfront asys_ dummy function calls           */
246 /****************************************************************/
247 
248 #if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT))
249 
250 /****************************************************************/
251 /*        sets up audio output for a given srate/channels       */
252 /****************************************************************/
253 
asys_osetup(int srate,int ochannels,int osample,char * oname,int toption)254 int asys_osetup(int srate, int ochannels, int osample,
255 		char * oname, int toption) { return ASYS_DONE; }
256 
257 #endif
258 
259 #if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT))
260 
261 /****************************************************************/
262 /*        sets up audio input for a given srate/channels       */
263 /****************************************************************/
264 
asys_isetup(int srate,int ichannels,int isample,char * iname,int toption)265 int asys_isetup(int srate, int ichannels, int isample,
266                 char * iname, int toption) { return ASYS_DONE; }
267 
268 #endif
269 
270 #if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT))
271 
272 /****************************************************************/
273 /*   sets up audio input and output for a given srate/channels  */
274 /****************************************************************/
275 
asys_iosetup(int srate,int ichannels,int ochannels,int isample,int osample,char * iname,char * oname,int toption)276 int asys_iosetup(int srate, int ichannels, int ochannels,
277                  int isample, int osample, char * iname,
278 		 char * oname, int toption) { return ASYS_DONE; }
279 #endif
280 
281 #if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT)))
282 
283 /****************************************************************/
284 /*                    shuts down audio output                   */
285 /****************************************************************/
286 
asys_oshutdown(void)287 void asys_oshutdown(void)  { }
288 
289 #endif
290 
291 #if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT)))
292 
293 /****************************************************************/
294 /*              shuts down audio input device                   */
295 /****************************************************************/
296 
asys_ishutdown(void)297 void asys_ishutdown(void) { }
298 
299 #endif
300 
301 #if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT)))
302 
303 /****************************************************************/
304 /*              shuts down audio input and output device        */
305 /****************************************************************/
306 
asys_ioshutdown(void)307 void asys_ioshutdown(void) { }
308 
309 #endif
310 
311 /****************************************************************/
312 /*        syntactically necessary, but will never be called     */
313 /****************************************************************/
314 
asys_main(void)315 void asys_main(void) { }
316 
317 /*~~~~~~~~~~~~~~~~~~~~~~~~~~*/
318 /*   ksync function suite  */
319 /*-------------------------*/
320 
321 #if defined(ASYS_KSYNC)
322 
323 /***********************************************************/
324 /*         initializes k-rate boundaries sync              */
325 /***********************************************************/
326 
ksyncinit()327 void ksyncinit() { }
328 
329 /***********************************************************/
330 /*         synchronizes on k-rate boundaries               */
331 /***********************************************************/
332 
ksync()333 float ksync() {  return 0.0F; }  /* encodes "uses no CPU" */
334 
335 #endif   /* ASYS_KSYNC */
336 
337 
338 /*************************************************************/
339 /*         Start of Part Two: The AudioUnit Component        */
340 /*************************************************************/
341 
342 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
343 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
344 /*  AudioUnit Property Constants  */
345 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
346 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
347 
348 #define ASYS_AUDIOUNIT_NULL    0
349 #define ASYS_AUDIOUNIT_MONO    1
350 #define ASYS_AUDIOUNIT_STEREO  2
351 
352 #define ASYS_AUDIOUNIT_OUTPUT_MAXCHANNELS ASYS_AUDIOUNIT_STEREO
353 
354 #if defined(ASYS_HASINPUT)
355 #define ASYS_AUDIOUNIT_INPUT_MAXCHANNELS  ASYS_AUDIOUNIT_STEREO
356 #define ASYS_AUDIOUNIT_SUPPORTED_FORMATS  4
357 #else
358 #define ASYS_AUDIOUNIT_INPUT_MAXCHANNELS  0
359 #define ASYS_AUDIOUNIT_SUPPORTED_FORMATS  2
360 #endif
361 
362 /* static input and output channels, from SAOL program */
363 
364 #define ASYS_AUDIOUNIT_OUTPUT_CHANNELS (ENDBUS_output_bus - BUS_output_bus)
365 
366 #if defined(ASYS_HASINPUT)
367 #define ASYS_AUDIOUNIT_INPUT_CHANNELS (ENDBUS_input_bus - BUS_input_bus)
368 #else
369 #define ASYS_AUDIOUNIT_INPUT_CHANNELS 0
370 #endif
371 
372 /* element limits */
373 
374 #if (ASYS_AUDIOUNIT_EFFECT)
375 
376 #define ASYS_AUDIOUNIT_ELEMENT_INPUTPREF   1  /* our default */
377 #define ASYS_AUDIOUNIT_ELEMENT_INPUTMAX    8  /* maximum we accept */
378 
379 #define ASYS_AUDIOUNIT_ELEMENT_OUTPUTPREF  1  /* our default */
380 #define ASYS_AUDIOUNIT_ELEMENT_OUTPUTMAX   1  /* maximum we accept */
381 
382 #define ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE   8  /* for I-bound data structures */
383 
384 #else
385 
386 #define ASYS_AUDIOUNIT_ELEMENT_INPUTPREF   0  /* our default */
387 #define ASYS_AUDIOUNIT_ELEMENT_INPUTMAX    0  /* maximum we accept */
388 
389 #define ASYS_AUDIOUNIT_ELEMENT_OUTPUTPREF  1  /* our default */
390 #define ASYS_AUDIOUNIT_ELEMENT_OUTPUTMAX   1  /* maximum we accept */
391 
392 #define ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE   1  /* for I-bound data structures */
393 
394 #endif
395 
396 /* maximum number of frames per slice */
397 
398 #define ASYS_AUDIOUNIT_FRAMES_PER_SLICE  4096
399 
400 /* in-place processing not supported */
401 
402 #define ASYS_AUDIOUNIT_INPLACE_PROCESSING 0
403 
404 /* number of instruments -- only used by MusicDevice */
405 
406 #define ASYS_AUDIOUNIT_INSTRUMENT_COUNT  1
407 
408 /* constants for property listeners */
409 
410 #define ASYS_AUDIOUNIT_PROPLISTEN_PARAMETERINFO  0
411 #define ASYS_AUDIOUNIT_PROPLISTEN_PARAMETERLIST  1
412 #define ASYS_AUDIOUNIT_PROPLISTEN_CPULOAD        2
413 #define ASYS_AUDIOUNIT_PROPLISTEN_LATENCY        3
414 #define ASYS_AUDIOUNIT_PROPLISTEN_TAILTIME       4
415 #define ASYS_AUDIOUNIT_PROPLISTEN_FACTORYPRESETS 5
416 #define ASYS_AUDIOUNIT_PROPLISTEN_RENDERQUALITY  6
417 #define ASYS_AUDIOUNIT_PROPLISTEN_CURRENTPRESET  7
418 #define ASYS_AUDIOUNIT_PROPLISTEN_PRESENTPRESET  8
419 #define ASYS_AUDIOUNIT_PROPLISTEN_STREAMFROMDISK 9
420 #define ASYS_AUDIOUNIT_PROPLISTEN_MAXIMUMFRAMESPERSLICE 10
421 #define ASYS_AUDIOUNIT_PROPLISTEN_ARRAYSIZE     11   /* ++ for each property added */
422 
423 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
424 /*  reset/paging behaviors   */
425 /*___________________________*/
426 
427 /* active reset does Uninitialize/Initialize for ResetSelect */
428 
429 #define ASYS_AUDIOUNIT_PASSIVE_RESET 0
430 #define ASYS_AUDIOUNIT_ACTIVE_RESET  1
431 #define ASYS_AUDIOUNIT_RESET_TYPE ASYS_AUDIOUNIT_PASSIVE_RESET
432 
433 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
434 /* istate-machine constants  */
435 /*___________________________*/
436 
437 #define ASYS_AUDIOUNIT_ISTATE_ABSENT           0
438 #define ASYS_AUDIOUNIT_ISTATE_INSTANCE         1
439 #define ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING 2
440 #define ASYS_AUDIOUNIT_ISTATE_FLUX             3
441 #define ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING     4
442 #define ASYS_AUDIOUNIT_ISTATE_ENGINE           5
443 #define ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING   6
444 #define ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER    7
445 
446 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
447 /* istate-machine return values  */
448 /*_______________________________*/
449 
450 #define ASYS_AUDIOUNIT_IRESPONSE_COMPLETE               0
451 #define ASYS_AUDIOUNIT_IRESPONSE_INITIALIZE             1
452 #define ASYS_AUDIOUNIT_IRESPONSE_UNINITIALIZE           2
453 #define ASYS_AUDIOUNIT_IRESPONSE_CLOSE                  3
454 #define ASYS_AUDIOUNIT_IRESPONSE_RENDER                 4
455 #define ASYS_AUDIOUNIT_IRESPONSE_WIRE                   5
456 #define ASYS_AUDIOUNIT_IRESPONSE_REINITIALIZE           6
457 #define ASYS_AUDIOUNIT_IRESPONSE_REUNINITIALIZE         7
458 #define ASYS_AUDIOUNIT_IRESPONSE_UNINITIALIZE_AND_CLOSE 8
459 #define ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL             9
460 #define ASYS_AUDIOUNIT_IRESPONSE_ERROR                 10
461 
462 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
463 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
464 /*   Control Driver Constants     */
465 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
466 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
467 
468 /* retry limit for socket writing */
469 
470 #define ASYS_AUDIOUNIT_RETRY_MAX  256
471 
472 /* bitfield constants for MIDIevent flags variable */
473 
474 #define ASYS_AUDIOUNIT_MIDIFLAGS_WAITING 0x01u  /* queuing flag bit */
475 
476 /* bitfield constants for SASLevent flags variable */
477 
478 #define ASYS_AUDIOUNIT_SASLFLAGS_WAITING 0x01u  /* queuing flag bit */
479 
480 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
481 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
482 /*   SAOL Parameter Constants    */
483 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
484 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
485 
486 #define ASYS_AUDIOUNIT_PARAMETER_DEFAULT_UNIT kAudioUnitParameterUnit_Generic
487 #define ASYS_AUDIOUNIT_PARAMETER_DEFAULT_MINIMUM 0.0F
488 #define ASYS_AUDIOUNIT_PARAMETER_DEFAULT_MAXIMUM 1.0F
489 #define ASYS_AUDIOUNIT_PARAMETER_DEFAULT_DEFAULT 0.5F
490 
491 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
492 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
493 /*           TypeDefs             */
494 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
495 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
496 
497 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
498 /*  typedef for a MIDI event   */
499 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
500 
501 typedef struct asysn_audiounit_MIDIevent {
502   unsigned char cmd;
503   unsigned char d0;
504   unsigned char d1;
505   unsigned char flags;
506   int kcycleidx;
507 } asysn_audiounit_MIDIevent;
508 
509 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
510 /*  typedef for a SASL event   */
511 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
512 
513 typedef struct asysn_audiounit_SASLevent {
514   int index;
515   Float32 value;
516   unsigned char flags;
517   int kcycleidx;
518 } asysn_audiounit_SASLevent;
519 
520 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
521 /*  typedef for SAOL parameter */
522 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
523 
524 typedef struct asysn_audiounit_saolparam {
525   Float32 value;
526   int index;
527   int use;
528 } asysn_audiounit_saolparam;
529 
530 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
531 /*  typedef for a listener proc  */
532 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
533 
534 typedef struct asysn_audiounit_proplisten {
535   AudioUnitPropertyListenerProc lproc;
536   void * lrefcon;
537   struct asysn_audiounit_proplisten * next;
538 } asysn_audiounit_proplisten;
539 
540 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
541 /*  typedef for a render notify proc  */
542 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
543 
544 typedef struct asysn_audiounit_rendernotify {
545   AURenderCallback nproc;
546   void * nrefcon;
547   struct asysn_audiounit_rendernotify * next;
548 } asysn_audiounit_rendernotify;
549 
550 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
551 /* typedef for instance state */
552 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
553 
554 typedef struct asysn_audiounit_InstanceState {
555 
556   ComponentInstance component;  /* component instance ID */
557   volatile int istate;          /* initialization state machine */
558   ENGINE_PTR_DECLARE_SEMICOLON  /* engine pointer for the instance */
559 
560   /*~~~~~~~~~~~~~~~~~~~~~~~*/
561   /* mirrored engine state */
562   /*~~~~~~~~~~~~~~~~~~~~~~~*/
563 
564   UInt32 acycle;
565   Float32 krate;
566   volatile uint64_t acycleidx_kcycleidx;
567 
568   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
569   /* current value of properties */
570   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
571 
572   /* common to Effects and MusicDevices */
573 
574   AudioUnitConnection MakeConnection[ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE];
575   Float32 CPULoad;
576   OSSpinLock lock_CPULoad;
577   AudioStreamBasicDescription OutputStreamFormat;
578   OSType SRCAlgorithm;
579   UInt32 InputElementCount;
580   UInt32 OutputElementCount;
581   Float64 Latency;
582   AUChannelInfo SupportedNumChannels[ASYS_AUDIOUNIT_SUPPORTED_FORMATS];
583   UInt32 MaximumFramesPerSlice;
584   Float64 TailTime;
585   UInt32 BypassEffect;
586   UInt32 LastBypassEffect;
587   OSStatus LastRenderError;
588   AURenderCallbackStruct SetRenderCallback[ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE];
589   asysn_audiounit_rendernotify * rendernotify;
590   OSSpinLock lock_rendernotify;
591   UInt32 RenderQuality;
592   UInt32 InPlaceProcessing;
593   AUPreset PresentPreset;
594   OSSpinLock lock_PresentPreset;
595   UInt32 OfflineRender;
596   Float64 PresentationLatency;
597   UInt32 StreamFromDisk;
598   asysn_audiounit_proplisten * proplisteners[ASYS_AUDIOUNIT_PROPLISTEN_ARRAYSIZE];
599   OSSpinLock lock_proplisteners;
600   OSSpinLock lock_sampledelivery;  /* for MakeConnection and SetRenderCallback */
601 
602   /* exclusive to MusicDevices and MusicEffects (?) */
603 
604   UInt32 InstrumentCount;
605 
606   /* properties exclusive to Effects */
607 
608   AudioStreamBasicDescription InputStreamFormat[ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE];
609 
610   /*~~~~~~~~~~~~~~~~~~~~*/
611   /* per-instance state */
612   /*~~~~~~~~~~~~~~~~~~~~*/
613 
614   /* data output array: common to Effects and Music Devices */
615 
616   Float32 * mData_Output[ASYS_AUDIOUNIT_OUTPUT_MAXCHANNELS];
617 
618   /* rendering templates and data carriers: exclusive to Effects */
619 
620   AudioBufferList * AudioBufferTemplate;
621   AudioBufferList * AudioBufferCarrier;
622 
623   /*~~~~~~~~~~~~~~~~~~~~~*/
624   /* aup_ property state */
625   /*~~~~~~~~~~~~~~~~~~~~~*/
626 
627   int num_saolparams;
628   AudioUnitParameterID * parameterlist;
629   AudioUnitParameterInfo * parameterinfo;
630   int * pvs_size;
631   char *** pvs_cstr;
632   asysn_audiounit_saolparam * saolparam;
633 
634   int num_factory;
635   Float32 ** factorypreset_values;
636   AUPreset * factorypreset_info;
637   CFMutableArrayRef factorypreset_array;
638 
639   /*~~~~~~~~~~~~~*/
640   /* ksync state */
641   /*~~~~~~~~~~~~~*/
642 
643   UInt64 ksync_timespent;  /* total time spent in one kpass */
644   Float32 ksync_normalize;    /* unit translations: 1/ticks to Hz */
645   Float32 ksync_last_cpuload;   /* used for missing data heuristic  */
646 
647   /*~~~~~~~~~~~~~~~~~~~~~~~~*/
648   /* state passed to engine */
649   /*~~~~~~~~~~~~~~~~~~~~~~~~*/
650 
651   char componentname[32];
652 
653   char mpipeflag[32];
654   char mpipevalue[32];
655 
656   char spipeflag[32];
657   char spipevalue[32];
658 
659   char * argv[5];
660   int argc;
661 
662   /*~~~~~~~~~~~~~~~~~*/
663   /* aucontrol state */
664   /*~~~~~~~~~~~~~~~~~*/
665 
666   int mpipepair[2];
667   int spipepair[2];
668 
669 } asysn_audiounit_InstanceState;
670 
671 
672 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
673 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
674 /* The page-management system  */
675 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
676 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
677 
678 int asysn_audiounit_opencount = 0;   /* number of audiounit instances */
679 OSSpinLock asysn_audiounit_lock_opencount;      /* protects opencount */
680 
681 /********************************************/
682 /* set memory status of a region of memory  */
683 /********************************************/
684 
asysn_audiounit_memstatus(void * addr,size_t len,int advice)685 void asysn_audiounit_memstatus(void * addr, size_t len, int advice)
686 
687 {
688   madvise((caddr_t) addr, len, advice);
689   return;
690 }
691 
692 
693 /*~~~~~~~~~~~~~~~~~~~*/
694 /*~~~~~~~~~~~~~~~~~~~*/
695 /* The ksync system  */
696 /*~~~~~~~~~~~~~~~~~~~*/
697 /*~~~~~~~~~~~~~~~~~~~*/
698 
699 /*********************************************/
700 /* startup initialization for ksync system   */
701 /*********************************************/
702 
asysn_audiounit_ksyncinit(asysn_audiounit_InstanceState * My)703 void asysn_audiounit_ksyncinit(asysn_audiounit_InstanceState * My)
704 
705 {
706   My->ksync_timespent = 0;
707 
708   OSSpinLockLock(&(My->lock_CPULoad));
709 
710   My->ksync_normalize = (Float32) (My->krate/AudioGetHostClockFrequency());
711   if (My->CPULoad)
712     My->ksync_normalize = My->ksync_normalize/My->CPULoad;
713 
714   OSSpinLockUnlock(&(My->lock_CPULoad));
715 
716   My->ksync_last_cpuload = 0.0F;
717 }
718 
719 /********************************************/
720 /* computes cpuload value at end of a kpass */
721 /********************************************/
722 
asysn_audiounit_ksync(asysn_audiounit_InstanceState * My)723 Float32 asysn_audiounit_ksync(asysn_audiounit_InstanceState * My)
724 
725 {
726   UInt64 now = AudioGetCurrentHostTime();
727   Float32 ret;
728 
729   ret = My->ksync_normalize*((Float32)(now - My->ksync_timespent));
730 
731   if (ret > 1.0F)
732     ret = 1.0F;
733 
734   if (ret < 1.0F)
735     My->ksync_last_cpuload = ret;
736   else
737     {
738       ret = My->ksync_last_cpuload;
739       My->ksync_last_cpuload = 1.0F;
740     }
741 
742   My->ksync_timespent = now;
743 
744   return ret;
745 }
746 
747 
748 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
749 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
750 /*    Fast Dispatch Functions     */
751 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
752 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
753 
754 /***********************************************/
755 /* Helper Routine for MIDIEvent Fast Dispatch  */
756 /***********************************************/
757 
asysn_audiounit_sendMIDIevent(asysn_audiounit_MIDIevent * MIDIevent,asysn_audiounit_InstanceState * My)758 ComponentResult asysn_audiounit_sendMIDIevent(asysn_audiounit_MIDIevent * MIDIevent,
759 					      asysn_audiounit_InstanceState * My)
760 
761 {
762   uint64_t acycleidx_kcycleidx;
763   int32_t acycleidx, kcycleidx;
764   int write_failed = 0;
765   int retry = 0;
766   int acount;
767 
768   if (!ASYS_AUDIOUNIT_HAS_AUCONTROL)
769     return noErr;
770 
771   /* on entry, MIDIevent->kcycle holds offset of event (in samples) from the */
772   /* start of the next buffer. This start time in the sfront engine is coded */
773   /* by the tuple (kcycleidx, acycleidx).                                    */
774 
775   acycleidx_kcycleidx = My->acycleidx_kcycleidx;
776   kcycleidx = (int32_t)(acycleidx_kcycleidx & 0x00000000FFFFFFFF);
777   acycleidx = (int32_t)(acycleidx_kcycleidx >> 32);
778 
779   acount = acycleidx + MIDIevent->kcycleidx;
780   MIDIevent->kcycleidx = kcycleidx;
781 
782   /* initialization of acycleidx_kcycleidx skirts zero-time condition issue */
783 
784   while (acount >= My->acycle)
785     {
786       acount -= My->acycle;
787       MIDIevent->kcycleidx++;
788     }
789 
790   while (write(My->mpipepair[1], MIDIevent, sizeof(asysn_audiounit_MIDIevent)) < 0)
791     if ((errno != EINTR) || (++retry >= ASYS_AUDIOUNIT_RETRY_MAX))
792       {
793 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING("\tSocket write error in sendMIDIevent\n\n");
794 	write_failed = 1;
795 	break;
796       }
797 
798   return noErr;
799 }
800 
801 /***********************************/
802 /* MIDIEvent Fast Dispatch Handler */
803 /***********************************/
804 
asysn_audiounit_MyMIDIEventProc(void * inComponentStorage,UInt32 inStatus,UInt32 inData1,UInt32 inData2,UInt32 inOffsetSampleFrame)805 ComponentResult asysn_audiounit_MyMIDIEventProc(void * inComponentStorage,
806 						UInt32 inStatus,
807 						UInt32 inData1,
808 						UInt32 inData2,
809 						UInt32 inOffsetSampleFrame)
810 {
811   asysn_audiounit_MIDIevent MIDIevent;
812   int result;
813 
814   if (!inComponentStorage)           /* avoid race condition */
815     return noErr;
816 
817   MIDIevent.cmd = (unsigned char) inStatus;
818   MIDIevent.d0 = (unsigned char)inData1;
819   MIDIevent.d1 = (unsigned char)inData2;
820   MIDIevent.flags = ASYS_AUDIOUNIT_MIDIFLAGS_WAITING;
821   MIDIevent.kcycleidx = (int) inOffsetSampleFrame;
822 
823   result = asysn_audiounit_sendMIDIevent
824     (&MIDIevent, (asysn_audiounit_InstanceState *) inComponentStorage);
825 
826   ASYS_AUDIOUNIT_WIRETAP_MIDIEVENT(inComponentStorage, inStatus, inData1,
827 				   inData2, inOffsetSampleFrame, "Fast Dispatch");
828 
829   return result;
830 }
831 
832 /**************************************************/
833 /* Helper Routine for GetParameter Fast Dispatch  */
834 /**************************************************/
835 
asysn_audiounit_getSASLevent(AudioUnitParameterID inID,Float32 * outValue,asysn_audiounit_InstanceState * My)836 ComponentResult asysn_audiounit_getSASLevent(AudioUnitParameterID inID,
837 					     Float32 * outValue,
838 					     asysn_audiounit_InstanceState * My)
839 
840 {
841   if (inID >= My->num_saolparams)
842     return kAudioUnitErr_InvalidParameter;
843 
844   *outValue = My->saolparam[inID].value;
845   return noErr;
846 }
847 
848 /**************************************/
849 /* GetParameter Fast Dispatch Handler */
850 /**************************************/
851 
asysn_audiounit_MyGetParameterProc(void * inComponentStorage,AudioUnitParameterID inID,AudioUnitScope inScope,AudioUnitElement inElement,Float32 * outValue)852 ComponentResult asysn_audiounit_MyGetParameterProc(void * inComponentStorage,
853 						   AudioUnitParameterID inID,
854 						   AudioUnitScope inScope,
855 						   AudioUnitElement inElement,
856 						   Float32 * outValue)
857 {
858   int result;
859 
860   if (!inComponentStorage)           /* avoid race condition */
861     return noErr;
862 
863   if (inScope != kAudioUnitScope_Global)  /* inScope */
864     return kAudioUnitErr_InvalidScope;
865 
866   result = asysn_audiounit_getSASLevent
867     (inID, outValue, (asysn_audiounit_InstanceState *) inComponentStorage);
868 
869   ASYS_AUDIOUNIT_WIRETAP_GETPARAMETER(inComponentStorage, inID, inScope,
870 				      inElement, outValue, "Fast Dispatch");
871 
872   return result;
873 }
874 
875 /**************************************************/
876 /* Helper Routine for SetParameter Fast Dispatch  */
877 /**************************************************/
878 
asysn_audiounit_sendSASLevent(asysn_audiounit_SASLevent * SASLevent,asysn_audiounit_InstanceState * My)879 ComponentResult asysn_audiounit_sendSASLevent(asysn_audiounit_SASLevent * SASLevent,
880 					      asysn_audiounit_InstanceState * My)
881 
882 {
883   uint64_t acycleidx_kcycleidx;
884   int32_t acycleidx, kcycleidx;
885   int write_failed = 0;
886   int retry = 0;
887   int acount;
888 
889   if (!ASYS_AUDIOUNIT_HAS_AUCONTROL)
890     return noErr;
891 
892   /* on entry:                                                               */
893   /*            SASLevent->index holds AudioUnit index (not SAOL index) and  */
894   /*            has been range-checked.                                      */
895   /*                                                                         */
896   /*            SASLevent->value is range-checked.                           */
897   /*                                                                         */
898   /*            SASLevent->flags is not set.                                 */
899   /*                                                                         */
900   /*            SASLevent->kcycle holds offset of event (in samples) from    */
901   /*            the start of the next buffer. This start time in the sfront  */
902   /*            engine is coded by the tuple (kcycleidx, acycleidx).         */
903 
904   SASLevent->index = My->saolparam[SASLevent->index].index;
905   SASLevent->flags = ASYS_AUDIOUNIT_SASLFLAGS_WAITING;
906 
907   acycleidx_kcycleidx = My->acycleidx_kcycleidx;
908   kcycleidx = (int32_t)(acycleidx_kcycleidx & 0x00000000FFFFFFFF);
909   acycleidx = (int32_t)(acycleidx_kcycleidx >> 32);
910 
911   acount = acycleidx + SASLevent->kcycleidx;
912   SASLevent->kcycleidx = kcycleidx;
913 
914   /* initialization of acycleidx_kcycleidx skirts zero-time condition issue */
915 
916   while (acount >= My->acycle)
917     {
918       acount -= My->acycle;
919       SASLevent->kcycleidx++;
920     }
921 
922   while (write(My->spipepair[1], SASLevent, sizeof(asysn_audiounit_SASLevent)) < 0)
923     if ((errno != EINTR) || (++retry >= ASYS_AUDIOUNIT_RETRY_MAX))
924       {
925 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING("\tSocket write error in sendSASLevent\n\n");
926 	write_failed = 1;
927 	break;
928       }
929 
930   return noErr;
931 }
932 
933 /**************************************/
934 /* SetParameter Fast Dispatch Handler */
935 /**************************************/
936 
asysn_audiounit_MySetParameterProc(void * inComponentStorage,AudioUnitParameterID inID,AudioUnitScope inScope,AudioUnitElement inElement,Float32 inValue,UInt32 inBufferOffsetInFrames)937 ComponentResult asysn_audiounit_MySetParameterProc(void * inComponentStorage,
938 						   AudioUnitParameterID inID,
939 						   AudioUnitScope inScope,
940 						   AudioUnitElement inElement,
941 						   Float32 inValue,
942 						   UInt32 inBufferOffsetInFrames)
943 {
944   asysn_audiounit_InstanceState * My;
945   asysn_audiounit_SASLevent SASLevent;
946   int result;
947 
948   My = ((asysn_audiounit_InstanceState *) inComponentStorage);
949 
950   if (!My)           /* avoid race condition */
951     return noErr;
952 
953   if ((inID < 0) || (inID >= My->num_saolparams))  /* range-check ID */
954     return kAudioUnitErr_InvalidParameter;
955 
956   if (inScope != kAudioUnitScope_Global)  /* inScope */
957     return kAudioUnitErr_InvalidScope;
958 
959   if (inValue > My->parameterinfo[inID].maxValue)
960     inValue = My->parameterinfo[inID].maxValue;
961 
962   if (inValue < My->parameterinfo[inID].minValue)
963     inValue = My->parameterinfo[inID].minValue;
964 
965   SASLevent.index = inID;
966   SASLevent.value = My->saolparam[inID].value = inValue;
967   SASLevent.kcycleidx = (int)(inBufferOffsetInFrames);
968 
969   result = asysn_audiounit_sendSASLevent(&SASLevent, My);
970 
971   ASYS_AUDIOUNIT_WIRETAP_SETPARAMETER(My, inID, inScope,
972 				      inElement, inValue, inBufferOffsetInFrames,
973 				      "Fast Dispatch");
974 
975   return result;
976 }
977 
978 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
979 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
980 /* AUEventListenerNotify support  */
981 /*                                */
982 /* To let global variable writes  */
983 /* by SAOL programs be seen in UI */
984 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
985 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
986 
987 /************************************************/
988 /* checks all variables, does update if needed  */
989 /************************************************/
990 
asysn_audiounit_eventlistenernotify(asysn_audiounit_InstanceState * My)991 void asysn_audiounit_eventlistenernotify(asysn_audiounit_InstanceState * My)
992 
993 {
994   ENGINE_PTR_DECLARE_SEMICOLON
995   AudioUnitEvent event;
996   Float32 value;
997   int i;
998 
999   ENGINE_PTR_ASSIGNED_TO  MY_ENGINE_PTR;  /* for NG() reference */
1000 
1001   for (i = 0; i < My->num_saolparams; i++)
1002     if (My->saolparam[i].use & CSYS_WRITTEN)
1003       if ((value = NG(My->saolparam[i].index)) != My->saolparam[i].value)
1004 	{
1005 	  if (value > My->parameterinfo[i].maxValue)
1006 	    NG(My->saolparam[i].index) = value = My->parameterinfo[i].maxValue;
1007 	  if (value < My->parameterinfo[i].minValue)
1008 	    NG(My->saolparam[i].index) = value = My->parameterinfo[i].minValue;
1009 
1010 	  if (value != My->saolparam[i].value)
1011 	    {
1012 	      My->saolparam[i].value = value;
1013 	      event.mEventType = kAudioUnitEvent_ParameterValueChange;
1014 	      event.mArgument.mParameter.mAudioUnit = My->component;
1015 	      event.mArgument.mParameter.mParameterID = i;
1016 	      event.mArgument.mParameter.mScope = kAudioUnitScope_Global;
1017 	      event.mArgument.mParameter.mElement = 0;
1018 	      OSMemoryBarrier();
1019 	      AUEventListenerNotify(NULL, NULL, &event);
1020 	    }
1021 	}
1022 }
1023 
1024 /*------------------------------------------*/
1025 /*  Specialized Renderers for Each AU Type  */
1026 /*------------------------------------------*/
1027 
1028 #if ASYS_AUDIOUNIT_MUSICDEVICE
1029 
1030 /************************************************************/
1031 /* Helper Routine For Fast-Dispatch Renderer -- MusicDevice */
1032 /************************************************************/
1033 
asysn_audiounit_activeo_renderer(asysn_audiounit_InstanceState * My,AudioBufferList * ioData)1034 void asysn_audiounit_activeo_renderer(asysn_audiounit_InstanceState * My,
1035 				      AudioBufferList * ioData)
1036 
1037 {
1038   ENGINE_PTR_DECLARE_SEMICOLON
1039   UInt32 frames = ioData->mBuffers[0].mDataByteSize/sizeof(Float32);
1040   Float32 eincr, escale;
1041   UInt32 do_effect, do_bypass;
1042   Float32 * out_left, * out_right;
1043   Float32 left;
1044 #if (ASYS_AUDIOUNIT_OUTPUT_CHANNELS > ASYS_AUDIOUNIT_MONO)
1045   Float32 right;
1046 #endif
1047 
1048   ENGINE_PTR_ASSIGNED_TO  MY_ENGINE_PTR;
1049 
1050 
1051   if (My->BypassEffect == 0)
1052     {
1053       if (My->LastBypassEffect == 0)
1054 	{
1055 	  do_effect = 1;
1056 	  do_bypass = 0;
1057 	  eincr = escale = 0.0F;
1058 	}
1059       else
1060 	{
1061 	  do_effect = 1;
1062 	  do_bypass = 1;
1063 	  eincr = escale = 1.0F/(frames + 1);
1064 	  My->LastBypassEffect = 0;
1065 	}
1066     }
1067   else
1068     {
1069       if (My->LastBypassEffect == 1)
1070 	{
1071 	  do_effect = 0;
1072 	  do_bypass = 1;
1073 	  eincr = escale = 0.0F;
1074 	}
1075       else
1076 	{
1077 	  do_effect = 1;
1078 	  do_bypass = 1;
1079 	  eincr = - 1.0F/(frames + 1);
1080 	  escale = 1.0F + eincr;
1081 	  My->LastBypassEffect = 1;
1082 	}
1083     }
1084 
1085   out_left = (Float32 *) (ioData->mBuffers[0].mData);
1086 
1087   if (ioData->mNumberBuffers > ASYS_AUDIOUNIT_MONO)
1088     out_right = (Float32 *) (ioData->mBuffers[1].mData);
1089   else
1090     out_right = NULL;
1091 
1092   while (frames)
1093     if (EV(acycleidx) < EV(ACYCLE))
1094       {
1095 	memset(&(TB(0)), 0, ENDBUS*sizeof(ASYS_OTYPE));  /* set bus to silence */
1096 	main_apass(ENGINE_PTR);                         /* compute samples    */
1097 
1098 	if (do_effect)
1099 	  {
1100 	    left = TB(BUS_output_bus);
1101 
1102 #if (ASYS_AUDIOUNIT_OUTPUT_CLIPPING)
1103 	    if ((left > 1.0F) || (left < -1.0F))
1104 	      left = (left > 0) ? 1.0F : -1.0F;
1105 #endif
1106 	    *out_left = left;
1107 
1108 	    if (out_right)
1109 	      {
1110 #if (ASYS_AUDIOUNIT_OUTPUT_CHANNELS == ASYS_AUDIOUNIT_MONO)
1111 		*out_right = left;
1112 #else
1113 		right = TB(BUS_output_bus + 1);
1114 
1115 #if (ASYS_AUDIOUNIT_OUTPUT_CLIPPING)
1116 		if ((right > 1.0F) || (right < -1.0F))
1117 		  right = (right > 0) ? 1.0F : -1.0F;
1118 #endif
1119 		*out_right = right;
1120 #endif
1121 	      }
1122 	    else
1123 	      {
1124 #if (ASYS_AUDIOUNIT_OUTPUT_CHANNELS > ASYS_AUDIOUNIT_MONO)
1125 		right = TB(BUS_output_bus + 1);
1126 
1127 #if (ASYS_AUDIOUNIT_OUTPUT_CLIPPING)
1128 		if ((right > 1.0F) || (right < -1.0F))
1129 		  right = (right > 0) ? 1.0F : -1.0F;
1130 #endif
1131 		*out_left += right;
1132 		*out_left *= 0.5F;
1133 #endif
1134 	      }
1135 
1136 	    if (do_bypass)
1137 	      {
1138 		*out_left *= escale;
1139 		if (out_right)
1140 		  *out_right *= escale;
1141 		escale += eincr;
1142 	      }
1143 	  }
1144 
1145 	if (do_bypass && !do_effect)
1146 	  {
1147 	    *out_left = 0.0F;
1148 
1149 	    if (out_right)
1150 	      *out_right = 0.0F;
1151 	  }
1152 
1153 	out_left++;
1154 
1155 	if (out_right)
1156 	  out_right++;
1157 
1158 	EV(acycleidx)++; frames--;     /* update all positions */
1159       }
1160     else
1161       {
1162 	EV(acycleidx) = 0;
1163 	if (EV(pass) == APASS)
1164 	  {
1165 	    EV(cpuload) = asysn_audiounit_ksync(My);
1166   	    EV(kcycleidx)++;         /* we run forever; don't test against endkcycle */
1167 	  }
1168 	EV(pass) = IPASS;
1169 	EV(scorebeats) = EV(scoremult)*(EV(kcycleidx) - EV(kbase)) + EV(scorebase);
1170 	EV(absolutetime) = (EV(kcycleidx) - 1)*EV(KTIME);
1171 	main_ipass(ENGINE_PTR);
1172 	EV(pass) = KPASS;
1173 	main_control(ENGINE_PTR);
1174 	main_kpass(ENGINE_PTR);      /* we run forever; don't check return value */
1175 	if (ASYS_AUDIOUNIT_PARAMETERS_WRITTEN)
1176 	  asysn_audiounit_eventlistenernotify(My);
1177 	EV(pass) = APASS;
1178       }
1179 
1180   My->acycleidx_kcycleidx = (((uint64_t) (EV(kcycleidx))) & 0x00000000FFFFFFFF) |
1181     (((uint64_t) (EV(acycleidx))) << 32);
1182 }
1183 
1184 /*****************************************/
1185 /* Fast-Dispatch Renderer -- MusicDevice */
1186 /*****************************************/
1187 
asysn_audiounit_MyRenderer(void * inComponentStorage,AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32 inOutputBusNumber,UInt32 inNumberFrames,AudioBufferList * ioData)1188 ComponentResult asysn_audiounit_MyRenderer(void * inComponentStorage,
1189 					   AudioUnitRenderActionFlags * ioActionFlags,
1190 					   const AudioTimeStamp * inTimeStamp,
1191 					   UInt32 inOutputBusNumber,
1192 					   UInt32 inNumberFrames,
1193 					   AudioBufferList * ioData)
1194 {
1195   UInt32 error_code;
1196   char message[128];
1197   asysn_audiounit_rendernotify * notify;
1198   AudioUnitRenderActionFlags action_flags;
1199   asysn_audiounit_InstanceState * My = ((asysn_audiounit_InstanceState *)
1200 					inComponentStorage);
1201   int i, iresponse;
1202 
1203   if (inNumberFrames > ASYS_AUDIOUNIT_FRAMES_PER_SLICE)
1204     return kAudioUnitErr_TooManyFramesToProcess;
1205 
1206   if (!My)
1207     return kAudioUnitErr_Uninitialized;   /* avoid race condition */
1208 
1209   switch(iresponse = asysn_audiounit_realtime_enterstate(My)) {
1210   case ASYS_AUDIOUNIT_IRESPONSE_WIRE:
1211   case ASYS_AUDIOUNIT_IRESPONSE_RENDER:
1212     break;
1213   case ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL:
1214   case ASYS_AUDIOUNIT_IRESPONSE_ERROR:
1215   default:
1216     return kAudioUnitErr_Uninitialized;   /* avoid race condition, bugs */
1217   }
1218 
1219   /* supply return buffers (only!) if needed */
1220 
1221   for (i = 0; i < ioData->mNumberBuffers; i++)
1222     if (ioData->mBuffers[i].mData == NULL)
1223       ioData->mBuffers[i].mData = (void *) My->mData_Output[i];
1224 
1225   /* do PreRender notification */
1226 
1227   OSSpinLockLock(&(My->lock_rendernotify));
1228 
1229   notify = My->rendernotify;
1230   while (notify)
1231     {
1232       if (notify->nproc)
1233 	{
1234 	  action_flags = kAudioUnitRenderAction_PreRender;
1235 
1236 	  if (error_code = ((* notify->nproc)
1237 			    (notify->nrefcon, &action_flags,
1238 			     inTimeStamp, (AudioUnitElement) 0, inNumberFrames,
1239 			     ioData)))
1240 	    {
1241 	      sprintf(message, "\nasysn_audiounit_MyRenderer"
1242 		      "\n\tError: PreRender Rendernotify callback"
1243 		      " returned OSType %u\n", (unsigned int) error_code);
1244 	      ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message);
1245 	    }
1246 	}
1247       notify = notify->next;
1248     }
1249 
1250   OSSpinLockUnlock(&(My->lock_rendernotify));
1251 
1252   /* the actual rendering done by the audio unit */
1253 
1254   if (iresponse == ASYS_AUDIOUNIT_IRESPONSE_RENDER)
1255     {
1256       My->ksync_timespent = AudioGetCurrentHostTime() - My->ksync_timespent;
1257       asysn_audiounit_activeo_renderer(My, ioData);
1258       My->ksync_timespent = AudioGetCurrentHostTime() - My->ksync_timespent;
1259     }
1260   else   /* for _WIRE, zero all buffers */
1261     for (i = 0; i < ioData->mNumberBuffers; i++)
1262       memset(ioData->mBuffers[i].mData, 0, sizeof(Float32)*inNumberFrames);
1263 
1264   /* do PostRender notification */
1265 
1266   OSSpinLockLock(&(My->lock_rendernotify));
1267 
1268   notify = My->rendernotify;
1269   while (notify)
1270     {
1271       if (notify->nproc)
1272 	{
1273 	  action_flags = kAudioUnitRenderAction_PostRender;
1274 
1275 	  if (error_code = ((* notify->nproc)
1276 			    (notify->nrefcon, &action_flags,
1277 			     inTimeStamp, (AudioUnitElement) 0, inNumberFrames,
1278 			     ioData)))
1279 	    {
1280 	      sprintf(message, "\nasysn_audiounit_MyRenderer"
1281 		      "\n\tError: PostRender Rendernotify callback"
1282 		      " returned OSType %u\n", (unsigned int) error_code);
1283 	      ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message);
1284 	    }
1285 	}
1286       notify = notify->next;
1287     }
1288 
1289   OSSpinLockUnlock(&(My->lock_rendernotify));
1290 
1291   asysn_audiounit_realtime_exitstate(My);
1292 
1293   return noErr;
1294 }
1295 
1296 #endif /* ASYS_AUDIOUNIT_MUSICDEVICE */
1297 
1298 
1299 #if ASYS_AUDIOUNIT_EFFECT
1300 
1301 /********************************************************/
1302 /* Helper Routine For Fast-Dispatch Renderer -- Effects */
1303 /********************************************************/
1304 
asysn_audiounit_activeio_renderer(asysn_audiounit_InstanceState * My,AudioBufferList * ioData)1305 void asysn_audiounit_activeio_renderer(asysn_audiounit_InstanceState * My,
1306 				       AudioBufferList * ioData)
1307 
1308 {
1309   ENGINE_PTR_DECLARE_SEMICOLON
1310   UInt32 frames = ioData->mBuffers[0].mDataByteSize/sizeof(Float32);
1311   Float32 eincr, bincr, escale, bscale;
1312   UInt32 do_effect, do_bypass;
1313   Float32 * out_left, * out_right, * in_left, * in_right;
1314   Float32 left;
1315 #if (ASYS_AUDIOUNIT_OUTPUT_CHANNELS > ASYS_AUDIOUNIT_MONO)
1316   Float32 right;
1317 #endif
1318 
1319   ENGINE_PTR_ASSIGNED_TO  MY_ENGINE_PTR;
1320 
1321   if (My->BypassEffect == 0)
1322     {
1323       if (My->LastBypassEffect == 0)
1324 	{
1325 	  do_effect = 1;
1326 	  do_bypass = 0;
1327 	  eincr = bincr = bscale = escale = 0.0F;
1328 	}
1329       else
1330 	{
1331 	  do_effect = 1;
1332 	  do_bypass = 1;
1333 	  eincr = escale = 1.0F/(frames + 1);
1334 	  bincr = - eincr;
1335 	  bscale = 1.0F - eincr;
1336 	  My->LastBypassEffect = 0;
1337 	}
1338     }
1339   else
1340     {
1341       if (My->LastBypassEffect == 1)
1342 	{
1343 	  do_effect = 0;
1344 	  do_bypass = 1;
1345 	  eincr = bincr = bscale = escale = 0.0F;
1346 	}
1347       else
1348 	{
1349 	  do_effect = 1;
1350 	  do_bypass = 1;
1351 	  bincr = bscale = 1.0F/(frames + 1);
1352 	  eincr = - bincr;
1353 	  escale = 1.0F - bincr;
1354 	  My->LastBypassEffect = 1;
1355 	}
1356     }
1357 
1358   out_left = (Float32 *) (ioData->mBuffers[0].mData);
1359 
1360   if (ioData->mNumberBuffers > ASYS_AUDIOUNIT_MONO)
1361     out_right = (Float32 *) (ioData->mBuffers[1].mData);
1362   else
1363     out_right = NULL;
1364 
1365   in_left = (Float32 *) (My->AudioBufferCarrier->mBuffers[0].mData);
1366 
1367   if (My->AudioBufferCarrier->mNumberBuffers > ASYS_AUDIOUNIT_MONO)
1368     in_right = (Float32 *) (My->AudioBufferCarrier->mBuffers[1].mData);
1369   else
1370     in_right = NULL;
1371 
1372   while (frames)
1373     if (EV(acycleidx) < EV(ACYCLE))
1374       {
1375 	memset(&(TB(0)), 0, ENDBUS*sizeof(ASYS_OTYPE));  /* set bus to silence */
1376 
1377 	TB(BUS_input_bus) = *in_left;
1378 
1379 	if (in_right)
1380 	  {
1381 #if (ASYS_AUDIOUNIT_INPUT_CHANNELS > ASYS_AUDIOUNIT_MONO)
1382 	    TB(BUS_input_bus + 1) = *in_right;
1383 #else
1384 	    TB(BUS_input_bus) += *in_right;
1385 	    TB(BUS_input_bus) *= 0.5F;
1386 #endif
1387 	  }
1388 	else
1389 	  {
1390 #if (ASYS_AUDIOUNIT_INPUT_CHANNELS > ASYS_AUDIOUNIT_MONO)
1391 	    TB(BUS_input_bus + 1) = *in_left;
1392 #endif
1393 	  }
1394 
1395 	main_apass(ENGINE_PTR);                   /* compute samples    */
1396 
1397 	if (do_effect)
1398 	  {
1399 	    left = TB(BUS_output_bus);
1400 
1401 #if (ASYS_AUDIOUNIT_OUTPUT_CLIPPING)
1402 	    if ((left > 1.0F) || (left < -1.0F))
1403 	      left = (left > 0) ? 1.0F : -1.0F;
1404 #endif
1405 	    *out_left = left;
1406 
1407 	    if (out_right)
1408 	      {
1409 #if (ASYS_AUDIOUNIT_OUTPUT_CHANNELS == ASYS_AUDIOUNIT_MONO)
1410 		*out_right = left;
1411 #else
1412 		right = TB(BUS_output_bus + 1);
1413 
1414 #if (ASYS_AUDIOUNIT_OUTPUT_CLIPPING)
1415 		if ((right > 1.0F) || (right < -1.0F))
1416 		  right = (right > 0) ? 1.0F : -1.0F;
1417 #endif
1418 		*out_right = right;
1419 #endif
1420 	      }
1421 	    else
1422 	      {
1423 #if (ASYS_AUDIOUNIT_OUTPUT_CHANNELS > ASYS_AUDIOUNIT_MONO)
1424 		right = TB(BUS_output_bus + 1);
1425 
1426 #if (ASYS_AUDIOUNIT_OUTPUT_CLIPPING)
1427 		if ((right > 1.0F) || (right < -1.0F))
1428 		  right = (right > 0) ? 1.0F : -1.0F;
1429 #endif
1430 		*out_left += right;
1431 		*out_left *= 0.5F;
1432 #endif
1433 	      }
1434 	  }
1435 
1436 	if (do_bypass)
1437 	  {
1438 	    if (!do_effect)
1439 	      *out_left = *in_left;
1440 	    else
1441 	      {
1442 		if (out_right || !in_right)
1443 		  *out_left = escale*(*out_left) + bscale*(*in_left);
1444 		else
1445 		  *out_left = escale*(*out_left) + bscale*0.5F*(*in_left);
1446 	      }
1447 
1448 	    if (out_right)
1449 	      {
1450 		if (!do_effect)
1451 		  {
1452 		    if (in_right)
1453 		      *out_right = *in_right;
1454 		    else
1455 		      *out_right = *in_left;
1456 		  }
1457 		else
1458 		  {
1459 		    if (in_right)
1460 		      *out_right = escale*(*out_right) + bscale*(*in_right);
1461 		    else
1462 		      *out_right = escale*(*out_right) + bscale*(*in_left);
1463 		  }
1464 	      }
1465 	    else
1466 	      {
1467 		if (in_right)
1468 		  {
1469 		    if (!do_effect)
1470 		      *out_left = 0.5F*(*out_left + *in_right);
1471 		    else
1472 		      *out_left = *out_left + bscale*0.5F*(*in_right);
1473 		  }
1474 	      }
1475 
1476 	    if (do_effect)
1477 	      {
1478 		bscale += bincr;
1479 		escale += eincr;
1480 	      }
1481 	  }
1482 
1483 	in_left++;
1484 	out_left++;
1485 
1486 	if (in_right)
1487 	  in_right++;
1488 
1489 	if (out_right)
1490 	  out_right++;
1491 
1492 	EV(acycleidx)++; frames--;  /* updates */
1493       }
1494     else
1495       {
1496 	EV(acycleidx) = 0;
1497 	if (EV(pass) == APASS)
1498 	  {
1499 	    EV(cpuload) = asysn_audiounit_ksync(My);
1500 	    EV(kcycleidx)++;         /* we run forever; don't test against endkcycle */
1501 	  }
1502 	EV(pass) = IPASS;
1503 	EV(scorebeats) = EV(scoremult)*(EV(kcycleidx) - EV(kbase)) + EV(scorebase);
1504 	EV(absolutetime) = (EV(kcycleidx) - 1)*EV(KTIME);
1505 	main_ipass(ENGINE_PTR);
1506 	EV(pass) = KPASS;
1507 	main_control(ENGINE_PTR);
1508 	main_kpass(ENGINE_PTR);      /* we run forever; don't check return value */
1509 	if (ASYS_AUDIOUNIT_PARAMETERS_WRITTEN)
1510 	  asysn_audiounit_eventlistenernotify(My);
1511 	EV(pass) = APASS;
1512       }
1513 
1514   My->acycleidx_kcycleidx = (((uint64_t) (EV(kcycleidx))) & 0x00000000FFFFFFFF) |
1515     (((uint64_t) (EV(acycleidx))) << 32);
1516 }
1517 
1518 /**********************************************************/
1519 /* Helper Routine For Fast-Dispatch Renderer -- Pass-thru */
1520 /**********************************************************/
1521 
asysn_audiounit_activeio_passthru(asysn_audiounit_InstanceState * My,AudioBufferList * ioData)1522 void asysn_audiounit_activeio_passthru(asysn_audiounit_InstanceState * My,
1523 				       AudioBufferList * ioData)
1524 
1525 {
1526   UInt32 frames = ioData->mBuffers[0].mDataByteSize/sizeof(Float32);
1527   Float32 * out_left, * out_right, * in_left, * in_right;
1528 
1529   out_left = (Float32 *) (ioData->mBuffers[0].mData);
1530 
1531   if (ioData->mNumberBuffers > ASYS_AUDIOUNIT_MONO)
1532     out_right = (Float32 *) (ioData->mBuffers[1].mData);
1533   else
1534     out_right = NULL;
1535 
1536   in_left = (Float32 *) (My->AudioBufferCarrier->mBuffers[0].mData);
1537 
1538   if (My->AudioBufferCarrier->mNumberBuffers > ASYS_AUDIOUNIT_MONO)
1539     in_right = (Float32 *) (My->AudioBufferCarrier->mBuffers[1].mData);
1540   else
1541     in_right = NULL;
1542 
1543   while (frames)
1544     {
1545       *out_left = *in_left;
1546 
1547       if (out_right)
1548 	{
1549 	  if (in_right)
1550 	    *out_right = *in_right;
1551 	  else
1552 	    *out_right = *in_left;
1553 	}
1554       else
1555 	if (in_right)
1556 	  *out_left = 0.5F*(*out_left + *in_right);
1557 
1558       in_left++;
1559       out_left++;
1560 
1561       if (in_right)
1562 	in_right++;
1563 
1564       if (out_right)
1565 	out_right++;
1566 
1567       frames--;
1568     }
1569 }
1570 
1571 
1572 /*************************************/
1573 /* Fast-Dispatch Renderer -- Effects */
1574 /*************************************/
1575 
asysn_audiounit_MyRenderer(void * inComponentStorage,AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32 inOutputBusNumber,UInt32 inNumberFrames,AudioBufferList * ioData)1576 ComponentResult asysn_audiounit_MyRenderer(void * inComponentStorage,
1577 					   AudioUnitRenderActionFlags * ioActionFlags,
1578 					   const AudioTimeStamp * inTimeStamp,
1579 					   UInt32 inOutputBusNumber,
1580 					   UInt32 inNumberFrames,
1581 					   AudioBufferList * ioData)
1582 {
1583   UInt32 error_code;
1584   char message[128];
1585   asysn_audiounit_rendernotify * notify;
1586   AudioUnitRenderActionFlags action_flags;
1587   AudioTimeStamp AudioTimeStampCarrier;
1588   asysn_audiounit_InstanceState * My = ((asysn_audiounit_InstanceState *)
1589 					inComponentStorage);
1590   ComponentResult return_value;
1591   int i, iresponse;
1592 
1593   if (inNumberFrames > ASYS_AUDIOUNIT_FRAMES_PER_SLICE)
1594     return kAudioUnitErr_TooManyFramesToProcess;
1595 
1596   if (!My)
1597     return kAudioUnitErr_Uninitialized;    /* avoid race condition */
1598 
1599   switch(iresponse = asysn_audiounit_realtime_enterstate(My)) {
1600   case ASYS_AUDIOUNIT_IRESPONSE_WIRE:
1601   case ASYS_AUDIOUNIT_IRESPONSE_RENDER:
1602     break;
1603   case ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL:
1604   case ASYS_AUDIOUNIT_IRESPONSE_ERROR:
1605   default:
1606     return kAudioUnitErr_Uninitialized;   /* avoid race condition, bugs */
1607   }
1608 
1609   return_value = noErr;
1610   action_flags = 0;
1611 
1612   /* prepare AudioTimeStampCarrier */
1613 
1614   memset(&AudioTimeStampCarrier, 0, sizeof(AudioTimeStamp));
1615   AudioTimeStampCarrier.mSampleTime = inTimeStamp->mSampleTime;
1616   AudioTimeStampCarrier.mFlags = kAudioTimeStampSampleTimeValid;
1617 
1618   /* prepare AudioBufferCarrier */
1619 
1620   memcpy(My->AudioBufferCarrier, My->AudioBufferTemplate,
1621 	 sizeof(UInt32) + My->AudioBufferTemplate->mNumberBuffers*sizeof(AudioBuffer));
1622 
1623   for (i = 0; i < My->AudioBufferCarrier->mNumberBuffers; i++)
1624     My->AudioBufferCarrier->mBuffers[i].mDataByteSize =
1625       ioData->mBuffers[0].mDataByteSize;
1626 
1627   /* retrieve audio samples to process, log errors */
1628   /*   assumptions:
1629      - a callback returning noErr returns the amount of data we asked for
1630   */
1631 
1632   OSSpinLockLock(&(My->lock_sampledelivery));
1633 
1634   if (My->SetRenderCallback[0].inputProc)
1635     {
1636       if (error_code = ((* My->SetRenderCallback[0].inputProc)
1637 			(My->SetRenderCallback[0].inputProcRefCon, &action_flags,
1638 			 &AudioTimeStampCarrier, (AudioUnitElement) 0, inNumberFrames,
1639 			 My->AudioBufferCarrier)))
1640 	{
1641 	  sprintf(message, "\nMyRenderer"
1642 		  "\n\tError: Render callback returned OSType %u\n",
1643 		  (unsigned int) error_code);
1644 	  ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message);
1645 	  return_value = kAudioUnitErr_NoConnection;
1646 	}
1647     }
1648   else
1649     {
1650       if ((My->MakeConnection[0].sourceAudioUnit == 0) ||
1651 	  (error_code = AudioUnitRender(My->MakeConnection[0].sourceAudioUnit,
1652 					&action_flags, &AudioTimeStampCarrier,
1653 					My->MakeConnection[0].sourceOutputNumber,
1654 					inNumberFrames, My->AudioBufferCarrier)))
1655 	{
1656 	  if (My->MakeConnection[0].sourceAudioUnit == 0)
1657 	    {
1658 	      sprintf(message, "\nMyRenderer"
1659 		      "\n\tError: No connection to use with AudioUnitRender\n");
1660 	      ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message);
1661 	      return_value = kAudioUnitErr_NoConnection;
1662 	    }
1663 	  else
1664 	    {
1665 	      sprintf(message, "\nMyRenderer\n\tError: AudioUnitRender returned:\n\t");
1666 	      ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message);
1667 	      ASYS_AUDIOUNIT_WIRETAP_PRINT_COMPONENT_RESULT(error_code);
1668 	      sprintf(message, "\n");
1669 	      ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message);
1670 	      return_value = error_code;
1671 	    }
1672 	}
1673     }
1674 
1675   OSSpinLockUnlock(&(My->lock_sampledelivery));
1676 
1677   /* supply return buffers (only!) if needed */
1678 
1679   for (i = 0; i < ioData->mNumberBuffers; i++)  /* straight-wire, no gain */
1680     if (ioData->mBuffers[i].mData == NULL)
1681       ioData->mBuffers[i].mData = (void *) My->mData_Output[i];
1682 
1683   /* do PreRender notification */
1684 
1685   OSSpinLockLock(&(My->lock_rendernotify));
1686 
1687   notify = My->rendernotify;
1688   while (notify)
1689     {
1690       if (notify->nproc)
1691 	{
1692 	  action_flags = kAudioUnitRenderAction_PreRender;
1693 
1694 	  if (error_code = ((* notify->nproc)
1695 			    (notify->nrefcon, &action_flags,
1696 			     inTimeStamp, (AudioUnitElement) 0, inNumberFrames,
1697 			     ioData)))
1698 	    {
1699 	      sprintf(message, "\nasysn_audiounit_MyRenderer"
1700 		      "\n\tError: PreRender Rendernotify callback"
1701 		      " returned OSType %u\n", (unsigned int) error_code);
1702 	      ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message);
1703 	    }
1704 	}
1705       notify = notify->next;
1706     }
1707 
1708   OSSpinLockUnlock(&(My->lock_rendernotify));
1709 
1710   /* the actual rendering done by the audio unit */
1711 
1712   if (return_value == noErr)
1713     {
1714       if (iresponse == ASYS_AUDIOUNIT_IRESPONSE_RENDER)
1715 	{
1716 	  My->ksync_timespent = AudioGetCurrentHostTime() - My->ksync_timespent;
1717 	  asysn_audiounit_activeio_renderer(My, ioData);
1718 	  My->ksync_timespent = AudioGetCurrentHostTime() - My->ksync_timespent;
1719 	}
1720       else
1721 	asysn_audiounit_activeio_passthru(My, ioData);
1722     }
1723   else
1724     for (i = 0; i < ioData->mNumberBuffers; i++)  /* in case of error, silence */
1725       memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize);
1726 
1727   /* do PostRender notification */
1728 
1729   OSSpinLockLock(&(My->lock_rendernotify));
1730 
1731   notify = My->rendernotify;
1732   while (notify)
1733     {
1734       if (notify->nproc)
1735 	{
1736 	  action_flags = kAudioUnitRenderAction_PostRender;
1737 
1738 	  if (error_code = ((* notify->nproc)
1739 			    (notify->nrefcon, &action_flags,
1740 			     inTimeStamp, (AudioUnitElement) 0, inNumberFrames,
1741 			     ioData)))
1742 	    {
1743 	      sprintf(message, "\nasysn_audiounit_MyRenderer"
1744 		      "\n\tError: PostRender Rendernotify callback"
1745 		      " returned OSType %u\n", (unsigned int) error_code);
1746 	      ASYS_AUDIOUNIT_WIRETAP_PUTSTRING(message);
1747 	    }
1748 	}
1749       notify = notify->next;
1750     }
1751 
1752   OSSpinLockUnlock(&(My->lock_rendernotify));
1753 
1754   asysn_audiounit_realtime_exitstate(My);
1755 
1756   return return_value;
1757 }
1758 
1759 #endif /* ASYS_AUDIOUNIT_EFFECT */
1760 
1761 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1762 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1763 /* Helper Functions for all Selector Calls    */
1764 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1765 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1766 
1767 /****************************************************************/
1768 /* Helper Function for Factory Presets: returns a preset name   */
1769 /****************************************************************/
1770 
asysn_audiounit_factorypresetname(CFIndex idx)1771 CFStringRef asysn_audiounit_factorypresetname(CFIndex idx)
1772 
1773 {
1774   CFStringRef ret = NULL;
1775   char * nptr, * val_name;
1776   int i, j;
1777 
1778   j = 0;
1779 
1780   for (i = 0; i < CSYS_GLOBALNUM; i++)
1781     if ((csys_global[i].type == CSYS_TABLE) && csys_global[i].name &&
1782 	!strncmp("aup_factory_", csys_global[i].name, strlen("aup_factory_")) &&
1783 	strlen(csys_global[i].name) > strlen("aup_factory_") && ((j++) == idx))
1784       {
1785 	nptr = val_name = malloc
1786 	  (strlen(&(csys_global[i].name[strlen("aup_factory_")])) + 1);
1787 
1788 	strcpy(val_name, &(csys_global[i].name[strlen("aup_factory_")]));
1789 
1790 	do {
1791 	  if (*nptr == '_')
1792 	    *nptr = ' ';
1793 	} while (*(++nptr));
1794 
1795 	ret = CFStringCreateWithCString(NULL, val_name, kCFStringEncodingASCII);
1796 	break;
1797       }
1798 
1799   return ret;
1800 }
1801 
1802 /****************************************************************/
1803 /* Helper Function for Factory Presets: returns a preset number */
1804 /****************************************************************/
1805 
asysn_audiounit_factorypresetnumber(CFStringRef cfstr)1806 int asysn_audiounit_factorypresetnumber(CFStringRef cfstr)
1807 
1808 {
1809   char * nptr, * val_name, * match;
1810   int i, j;
1811 
1812   if (!cfstr)
1813     return -1;
1814 
1815   match = calloc(CFStringGetLength(cfstr) + 1, 1);
1816   CFStringGetCString(cfstr, match, CFStringGetLength(cfstr) + 1,
1817 		     kCFStringEncodingASCII);
1818 
1819   j = 0;
1820 
1821   for (i = 0; i < CSYS_GLOBALNUM; i++)
1822     if ((csys_global[i].type == CSYS_TABLE) && csys_global[i].name &&
1823 	!strncmp("aup_factory_", csys_global[i].name, strlen("aup_factory_")) &&
1824 	strlen(csys_global[i].name) > strlen("aup_factory_"))
1825       {
1826 	nptr = val_name = malloc
1827 	  (strlen(&(csys_global[i].name[strlen("aup_factory_")])) + 1);
1828 
1829 	strcpy(val_name, &(csys_global[i].name[strlen("aup_factory_")]));
1830 
1831 	do {
1832 	  if (*nptr == '_')
1833 	    *nptr = ' ';
1834 	} while (*(++nptr));
1835 
1836 	if (!strcmp(match, val_name))
1837 	  return j;
1838 
1839 	j++;
1840       }
1841 
1842   return -1;
1843 }
1844 
1845 
1846 /***********************************************************************/
1847 /* Helper Function for GetProperty: Create ParameterValueStrings array */
1848 /***********************************************************************/
1849 
asysn_audiounit_parametervaluestrings_create(asysn_audiounit_InstanceState * My,AudioUnitParameterID i)1850 CFMutableArrayRef asysn_audiounit_parametervaluestrings_create
1851 (asysn_audiounit_InstanceState * My, AudioUnitParameterID i)
1852 
1853 {
1854   CFMutableArrayRef array;
1855   int j;
1856 
1857   if ((i < 0) || (i >= My->num_saolparams) || (My->pvs_size[i] == 0))
1858     return NULL;
1859 
1860   array = CFArrayCreateMutable(NULL, My->pvs_size[i], &kCFTypeArrayCallBacks);
1861 
1862   for (j = 0; j < My->pvs_size[i]; j++)
1863     CFArrayInsertValueAtIndex(array, j, CFStringCreateWithCString
1864 			      (NULL, My->pvs_cstr[i][j], kCFStringEncodingASCII));
1865 
1866   return array;
1867 }
1868 
1869 /*****************************************************************/
1870 /* Pre-engine-execution passes for initialize_parametersystem()  */
1871 /*****************************************************************/
1872 
asysn_audiounit_earlypass_parametersystem(asysn_audiounit_InstanceState * My)1873 ComponentResult asysn_audiounit_earlypass_parametersystem
1874                         (asysn_audiounit_InstanceState * My)
1875 
1876 {
1877   int i, j, msize;
1878   char * nptr;
1879 
1880   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1881   /* Pass 1 on csys_global[]: count parameters and factory presets  */
1882   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1883 
1884   for (i = 0; i < CSYS_GLOBALNUM; i++)
1885     if (csys_global[i].name &&
1886 	(!strncmp(csys_global[i].name, "aup_", 4)) &&
1887 	(strlen(csys_global[i].name) > 4))
1888       switch (csys_global[i].type) {
1889       case CSYS_IRATE:
1890       case CSYS_KRATE:
1891 	if (csys_global[i].width != 1)
1892 	  break;
1893 
1894 	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1895 	/* change sfront/src/writepre.c line 3206 */
1896 	/* when the code below changes            */
1897 	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1898 
1899 	/* skip over reserved names */
1900 
1901  	if ((nptr = strstr(&(csys_global[i].name[4]), "_idx")) &&
1902 	    (strlen(nptr) > 6) && (nptr[4] >= '0') && (nptr[4] <= '9'))
1903 	  break;
1904 
1905 	if (strstr(&(csys_global[i].name[4]), "_unit_"))
1906 	  break;
1907 
1908 	if ((strstr(&(csys_global[i].name[4]), "_slider_squarelaw")) ||
1909 	    (strstr(&(csys_global[i].name[4]), "_slider_cubic")) ||
1910 	    (strstr(&(csys_global[i].name[4]), "_slider_squareroot")) ||
1911 	    (strstr(&(csys_global[i].name[4]), "_slider_cuberoot")) ||
1912 	    (strstr(&(csys_global[i].name[4]), "_slider_log")) ||
1913 	    (strstr(&(csys_global[i].name[4]), "_slider_exp")) ||
1914 	    (strstr(&(csys_global[i].name[4]), "_slider_linear")) ||
1915 	    (strstr(&(csys_global[i].name[4]), "_slider")) ||
1916 	    (strstr(&(csys_global[i].name[4]), "_checkbox")) ||
1917 	    (strstr(&(csys_global[i].name[4]), "_menu")) ||
1918 	    (strstr(&(csys_global[i].name[4]), "_display_number")) ||
1919 	    (strstr(&(csys_global[i].name[4]), "_display_checkbox")) ||
1920 	    (strstr(&(csys_global[i].name[4]), "_display_menu")))
1921 	  break;
1922 
1923 	My->num_saolparams++;
1924 	break;
1925       case CSYS_TABLE:
1926 	if (!strncmp("aup_factory_", csys_global[i].name, strlen("aup_factory_"))
1927 	    && (strlen(csys_global[i].name) > strlen("aup_factory_")))
1928 	  My->num_factory++;
1929 	break;
1930       default:
1931 	break;
1932       }
1933 
1934   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1935   /* Create data structures for parameters, factory presets, etc  */
1936   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1937 
1938   if (My->num_saolparams == 0)
1939     return noErr;
1940 
1941   if (!(My->parameterlist = (AudioUnitParameterID *)
1942 	malloc(My->num_saolparams*sizeof(AudioUnitParameterID))))
1943     return kAudioUnitErr_FailedInitialization;
1944 
1945   for (i = 0; i < My->num_saolparams; i++)
1946     My->parameterlist[i] = i;
1947 
1948   if (!(My->parameterinfo = (AudioUnitParameterInfo *)
1949 	calloc(My->num_saolparams, sizeof(AudioUnitParameterInfo))))
1950     return kAudioUnitErr_FailedInitialization;
1951 
1952   if (!(My->pvs_size = (int *) calloc(My->num_saolparams, sizeof(int))))
1953     return kAudioUnitErr_FailedInitialization;
1954 
1955   if (!(My->pvs_cstr = (char ***) calloc(My->num_saolparams, sizeof(char **))))
1956     return kAudioUnitErr_FailedInitialization;
1957 
1958   msize = My->num_saolparams*sizeof(asysn_audiounit_saolparam);
1959   if (!(My->saolparam = (asysn_audiounit_saolparam *) malloc(msize)))
1960     return kAudioUnitErr_FailedInitialization;
1961   asysn_audiounit_memstatus(My->saolparam, msize, MADV_WILLNEED);
1962 
1963   if (My->num_factory)
1964     {
1965       if (!(My->factorypreset_info = (AUPreset *)
1966 	    calloc(My->num_factory, sizeof(AUPreset))))
1967 	return kAudioUnitErr_FailedInitialization;
1968 
1969       msize = My->num_factory*sizeof(Float32 *);
1970       if (!(My->factorypreset_values = (Float32 **) calloc(1, msize)))
1971 	return kAudioUnitErr_FailedInitialization;
1972       asysn_audiounit_memstatus(My->factorypreset_values, msize, MADV_WILLNEED);
1973 
1974       for (i = 0; i < My->num_factory; i++)
1975 	{
1976 	  msize = My->num_saolparams*sizeof(Float32);
1977 	  if (!(My->factorypreset_values[i] = (Float32 *) malloc(msize)))
1978 	    return kAudioUnitErr_FailedInitialization;
1979 	  asysn_audiounit_memstatus(My->factorypreset_values[i], msize, MADV_WILLNEED);
1980 	}
1981     }
1982 
1983   /* todo: add parameter value strings data structures */
1984 
1985   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1986   /* Pass 2 on csys_global[]: Initialize parameter names  */
1987   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1988 
1989   j = 0;
1990 
1991   for (i = 0; i < CSYS_GLOBALNUM; i++)
1992     if (csys_global[i].name &&
1993 	(!strncmp(csys_global[i].name, "aup_", 4)) &&
1994 	(strlen(csys_global[i].name) > 4))
1995       switch (csys_global[i].type) {
1996       case CSYS_IRATE:
1997       case CSYS_KRATE:
1998 	if (csys_global[i].width != 1)
1999 	  break;
2000 
2001 	/* skip over reserved names */
2002 
2003 	if ((nptr = strstr(&(csys_global[i].name[4]), "_idx")) &&
2004 	    (strlen(nptr) > 6) && (nptr[4] >= '0') && (nptr[4] <= '9'))
2005 	  break;
2006 
2007 	if (strstr(&(csys_global[i].name[4]), "_unit_"))
2008 	  break;
2009 
2010 	if ((strstr(&(csys_global[i].name[4]), "_slider_squarelaw")) ||
2011 	    (strstr(&(csys_global[i].name[4]), "_slider_cubic")) ||
2012 	    (strstr(&(csys_global[i].name[4]), "_slider_squareroot")) ||
2013 	    (strstr(&(csys_global[i].name[4]), "_slider_cuberoot")) ||
2014 	    (strstr(&(csys_global[i].name[4]), "_slider_log")) ||
2015 	    (strstr(&(csys_global[i].name[4]), "_slider_exp")) ||
2016 	    (strstr(&(csys_global[i].name[4]), "_slider_linear")) ||
2017 	    (strstr(&(csys_global[i].name[4]), "_slider")) ||
2018 	    (strstr(&(csys_global[i].name[4]), "_checkbox")) ||
2019 	    (strstr(&(csys_global[i].name[4]), "_menu")) ||
2020 	    (strstr(&(csys_global[i].name[4]), "_display_number")) ||
2021 	    (strstr(&(csys_global[i].name[4]), "_display_checkbox")) ||
2022 	    (strstr(&(csys_global[i].name[4]), "_display_menu")))
2023 	  break;
2024 
2025 	/* Do all initialization that may be done early */
2026 
2027 	strncpy(My->parameterinfo[j].name, &(csys_global[i].name[4]), 60);
2028 	My->parameterinfo[j].name[59] = '\0';
2029 
2030 	My->parameterinfo[j].unit = ASYS_AUDIOUNIT_PARAMETER_DEFAULT_UNIT;
2031 	My->parameterinfo[j].minValue = ASYS_AUDIOUNIT_PARAMETER_DEFAULT_MINIMUM;
2032 	My->parameterinfo[j].maxValue = ASYS_AUDIOUNIT_PARAMETER_DEFAULT_MAXIMUM;
2033 	My->parameterinfo[j].defaultValue = ASYS_AUDIOUNIT_PARAMETER_DEFAULT_DEFAULT;
2034 
2035 	My->parameterinfo[j].flags = kAudioUnitParameterFlag_HasCFNameString |
2036 	  kAudioUnitParameterFlag_IsReadable | kAudioUnitParameterFlag_IsWritable |
2037 	  kAudioUnitParameterFlag_CFNameRelease;
2038 
2039 	My->saolparam[j].index = csys_global[i].index;
2040 	My->saolparam[j].use = csys_global[i].use;
2041 
2042 	j++;
2043 	break;
2044       default:
2045 	break;
2046       }
2047 
2048   return noErr;
2049 }
2050 
2051 
2052 /******************************************************************/
2053 /* Parameter-value strings pass for initialize_parametersystem()  */
2054 /******************************************************************/
2055 
asysn_audiounit_parametervaluestrings_parametersystem(asysn_audiounit_InstanceState * My)2056 ComponentResult asysn_audiounit_parametervaluestrings_parametersystem
2057                 (asysn_audiounit_InstanceState * My)
2058 
2059 {
2060   int i, j, k, str_idx, len;
2061   char * nptr, * match;
2062 
2063   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2064   /* Create parameter-value strings for Indexed parameters */
2065   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2066 
2067   for (j = 0; j < My->num_saolparams; j++)
2068     if (My->parameterinfo[j].unit == kAudioUnitParameterUnit_Indexed)
2069       {
2070 	My->pvs_size[j] = (My->parameterinfo[j].maxValue
2071 			   - My->parameterinfo[j].minValue + 1);
2072 
2073 	My->pvs_cstr[j] = (char **) calloc(My->pvs_size[j], sizeof(char *));
2074 
2075 	if (!(My->pvs_cstr[j]))
2076 	  return kAudioUnitErr_FailedInitialization;
2077 
2078 	/* create array and default values */
2079 
2080 	for (k = 0; k < My->pvs_size[j]; k++)
2081 	  {
2082 	    My->pvs_cstr[j][k] = (char *)calloc(strlen("4294967295") + 1, sizeof(char));
2083 
2084 	    if (!(My->pvs_cstr[j][k]))
2085 	      return kAudioUnitErr_FailedInitialization;
2086 
2087 	    sprintf(My->pvs_cstr[j][k], "%u", k);
2088 	  }
2089 
2090 	/* overwrite default values with custom strings */
2091 
2092 	len = strlen("aup_") + strlen(My->parameterinfo[j].name) + strlen("_idx");
2093 
2094 	if (!(match = malloc(len + 1)))
2095 	  return kAudioUnitErr_FailedInitialization;
2096 
2097 	sprintf((nptr = match), "aup_%s_idx", My->parameterinfo[j].name);
2098 
2099 	do {
2100 	  if (*nptr == ' ')
2101 	    *nptr = '_';
2102 	} while (*(++nptr));
2103 
2104 	for (i = 0; i < CSYS_GLOBALNUM; i++)
2105 	  if (csys_global[i].name && (csys_global[j].width == 1) &&
2106 	      ((csys_global[i].type == CSYS_IRATE) ||
2107 	       (csys_global[i].type == CSYS_KRATE)) &&
2108 	      (!strncmp(csys_global[i].name, match, len)) &&
2109 	      (strlen(csys_global[i].name) > len) &&
2110 	      (sscanf(&(csys_global[i].name[len]), "%u_", &k) == 1) &&
2111 	      (k >= 0) && (k <= My->pvs_size[j]))
2112 	    {
2113 	      str_idx = len;
2114 	      while (csys_global[i].name[str_idx++] != '_');
2115 
2116 	      if (csys_global[i].name[str_idx] != '\0')
2117 		{
2118 		  free(My->pvs_cstr[j][k]);
2119 
2120 		  nptr = My->pvs_cstr[j][k]
2121 		    = malloc(strlen(&(csys_global[i].name[str_idx])) + 1);
2122 
2123 		  if (!nptr)
2124 		    return kAudioUnitErr_FailedInitialization;
2125 
2126 		  strcpy(My->pvs_cstr[j][k], &(csys_global[i].name[str_idx]));
2127 
2128 		  do {
2129 		    if (*nptr == '_')
2130 		      *nptr = ' ';
2131 		  } while (*(++nptr));
2132 		}
2133 	    }
2134 
2135 	free(match);
2136       }
2137 
2138   return noErr;
2139 }
2140 
2141 /*********************************************************/
2142 /* Factory preset pass for initialize_parametersystem()  */
2143 /*********************************************************/
2144 
asysn_audiounit_factorypreset_parametersystem(ENGINE_PTR_DECLARE_COMMA asysn_audiounit_InstanceState * My)2145 ComponentResult asysn_audiounit_factorypreset_parametersystem
2146                 (ENGINE_PTR_DECLARE_COMMA
2147                  asysn_audiounit_InstanceState * My)
2148 
2149 {
2150   int i, j, k, idx;
2151   char * nptr, * match;
2152 
2153   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2154   /* initialize factory preset data structures */
2155   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2156 
2157   if (My->num_factory)
2158     {
2159       j = 0;
2160       My->factorypreset_array = CFArrayCreateMutable(NULL, My->num_factory, NULL);
2161 
2162       if (!(My->factorypreset_array))
2163 	return kAudioUnitErr_FailedInitialization;
2164 
2165       for (i = 0; i < CSYS_GLOBALNUM; i++)
2166 	if ((csys_global[i].type == CSYS_TABLE) && csys_global[i].name &&
2167 	    !strncmp("aup_factory_", csys_global[i].name, strlen("aup_factory_")) &&
2168 	    strlen(csys_global[i].name) > strlen("aup_factory_"))
2169 	  {
2170 	    nptr = match = malloc
2171 	      (strlen(&(csys_global[i].name[strlen("aup_factory_")])) + 1);
2172 
2173 	    if (!nptr)
2174 	      return kAudioUnitErr_FailedInitialization;
2175 
2176 	    strcpy(match, &(csys_global[i].name[strlen("aup_factory_")]));
2177 	    do {
2178 	      if (*nptr == '_')
2179 		*nptr = ' ';
2180 	    } while (*(++nptr));
2181 
2182 	    My->factorypreset_info[j].presetNumber = j;
2183 	    My->factorypreset_info[j].presetName = CFStringCreateWithCString
2184 	      (NULL, match, kCFStringEncodingASCII);
2185 
2186 	    if (!(My->factorypreset_info[j].presetName))
2187 	      return kAudioUnitErr_FailedInitialization;
2188 
2189 	    CFArrayAppendValue(My->factorypreset_array, &(My->factorypreset_info[j]));
2190 
2191 	    free(match);
2192 
2193 	    for (k = 0; k < My->num_saolparams; k++)
2194 	      My->factorypreset_values[j][k] = My->parameterinfo[k].defaultValue;
2195 
2196 	    if (EV(gtables)[idx = csys_global[i].index].t)
2197 	      for (k = 0; (k < EV(gtables)[idx].len) && (k < My->num_saolparams); k++)
2198 		{
2199 		  My->factorypreset_values[j][k] = EV(gtables)[idx].t[k];
2200 		  My->factorypreset_values[j][k]  =
2201 		    (My->factorypreset_values[j][k] < My->parameterinfo[k].minValue)
2202 		    ? My->parameterinfo[k].minValue : My->factorypreset_values[j][k];
2203 		  My->factorypreset_values[j][k]  =
2204 		    (My->factorypreset_values[j][k] > My->parameterinfo[k].maxValue)
2205 		    ? My->parameterinfo[k].maxValue : My->factorypreset_values[j][k];
2206 		}
2207 
2208 	    j++;
2209 	  }
2210     }
2211 
2212   return noErr;
2213 }
2214 
2215 /************************************************************/
2216 /* Helper for Open Selector: Initializes parameter system.  */
2217 /************************************************************/
2218 
asysn_audiounit_initialize_parametersystem(asysn_audiounit_InstanceState * My)2219 ComponentResult asysn_audiounit_initialize_parametersystem
2220                    (asysn_audiounit_InstanceState * My)
2221 
2222 {
2223   int i, j, k, ret, match_len, unit_num;
2224   char * nptr, * kptr, * match;
2225   ENGINE_PTR_DECLARE_SEMICOLON
2226 
2227   if ((ASYS_AUDIOUNIT_HAS_AUCONTROL == 0) || (CSYS_GLOBALNUM == 0))
2228     return noErr;
2229 
2230   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2231   /* Parameter initialization passes that precede engine start */
2232   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2233 
2234   if ((ret = asysn_audiounit_earlypass_parametersystem(My)) != noErr)
2235     return ret;
2236 
2237   if (My->num_saolparams == 0)
2238     return noErr;
2239 
2240   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2241   /* Execute engine to define parameters and factory presets  */
2242   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2243 
2244   ENGINE_PTR_ASSIGNED_TO  system_init(My->argc, My->argv,
2245 				      My->OutputStreamFormat.mSampleRate);
2246 
2247   if (ENGINE_PTR_IS_NULL)
2248     return kAudioUnitErr_FailedInitialization;
2249 
2250   effects_init(ENGINE_PTR);
2251   main_initpass(ENGINE_PTR);
2252   asysn_audiounit_ksyncinit(My);
2253 
2254   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2255   /* Use engine results to complete parameter data structures */
2256   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2257 
2258   for (j = 0; j < My->num_saolparams; j++)
2259     {
2260       match = malloc(strlen("aup_") + strlen(My->parameterinfo[j].name) +
2261 		     strlen("_pinfo") + 1);
2262 
2263       if (!match)
2264 	{
2265 	  shut_down(ENGINE_PTR);
2266 	  return kAudioUnitErr_FailedInitialization;
2267 	}
2268 
2269       sprintf(match, "aup_%s_pinfo", My->parameterinfo[j].name);
2270 
2271       for (i = 0; i < CSYS_GLOBALNUM; i++)
2272 	if ((csys_global[i].type == CSYS_TABLE) && csys_global[i].name &&
2273 	    !strcmp(match, csys_global[i].name))
2274 	  {
2275 	    k = csys_global[i].index;
2276 
2277 	    if (EV(gtables)[k].t && (EV(gtables)[k].len >= 3) &&
2278 		(EV(gtables)[k].t[0] <= EV(gtables)[k].t[1]) &&
2279 		(EV(gtables)[k].t[1] <= EV(gtables)[k].t[2]))
2280 	      {
2281 		My->parameterinfo[j].minValue = EV(gtables)[k].t[0];
2282 		My->parameterinfo[j].defaultValue = EV(gtables)[k].t[1];
2283 		My->parameterinfo[j].maxValue = EV(gtables)[k].t[2];
2284 
2285 		if (My->parameterinfo[j].minValue > My->parameterinfo[j].maxValue)
2286 		  {
2287 		    My->parameterinfo[j].minValue = EV(gtables)[k].t[2];
2288 		    My->parameterinfo[j].maxValue = EV(gtables)[k].t[0];
2289 		  }
2290 
2291 		if (My->parameterinfo[j].defaultValue > My->parameterinfo[j].maxValue)
2292 		  My->parameterinfo[j].defaultValue = EV(gtables)[k].t[2];
2293 
2294 		if (My->parameterinfo[j].defaultValue < My->parameterinfo[j].minValue)
2295 		  My->parameterinfo[j].defaultValue = EV(gtables)[k].t[0];
2296 	      }
2297 	    break;
2298 	  }
2299 
2300       free(match);
2301 
2302       match = malloc((match_len = strlen("aup_") + strlen(My->parameterinfo[j].name) +
2303 		      strlen("_unit_")) + 1);
2304 
2305       if (!match)
2306 	{
2307 	  shut_down(ENGINE_PTR);
2308 	  return kAudioUnitErr_FailedInitialization;
2309 	}
2310 
2311       sprintf(match, "aup_%s_unit_", My->parameterinfo[j].name);
2312 
2313       for (i = 0; i < CSYS_GLOBALNUM; i++)
2314 	if (((csys_global[i].type == CSYS_IRATE) ||
2315 	     (csys_global[i].type == CSYS_KRATE)) &&
2316 	    (csys_global[i].width == 1) &&
2317 	    csys_global[i].name &&
2318 	    !strncmp(match, csys_global[i].name, match_len))
2319 	  {
2320 	    if (strlen(csys_global[i].name) <= match_len)
2321 	      continue;
2322 
2323 	    nptr = &(csys_global[i].name[match_len]);
2324 
2325 	    /* for now, only support custom units */
2326 
2327 	    kptr = malloc(strlen(nptr) + 1);
2328 
2329 	    if (!kptr)
2330 	      {
2331 		shut_down(ENGINE_PTR);
2332 		return kAudioUnitErr_FailedInitialization;
2333 	      }
2334 
2335 	    strcpy(kptr, &(csys_global[i].name[match_len]));
2336 
2337 	    nptr = kptr;
2338 	    do {
2339 	      if (*nptr == '_')
2340 		*nptr = ' ';
2341 	    } while (*(++nptr));
2342 
2343 	    My->parameterinfo[j].unitName = CFStringCreateWithCString
2344 	      (NULL, kptr, kCFStringEncodingASCII);
2345 
2346 	    if (!(My->parameterinfo[j].unitName))
2347 	      {
2348 		shut_down(ENGINE_PTR);
2349 		return kAudioUnitErr_FailedInitialization;
2350 	      }
2351 
2352 	    My->parameterinfo[j].unit = kAudioUnitParameterUnit_CustomUnit;
2353 
2354 	    free(kptr);
2355 	    break;
2356 	  }
2357 
2358       free(match);
2359 
2360       match = malloc((match_len = strlen("aup_") + strlen(My->parameterinfo[j].name) +
2361 		      strlen("_")) + 1);
2362 
2363       if (!match)
2364 	{
2365 	  shut_down(ENGINE_PTR);
2366 	  return kAudioUnitErr_FailedInitialization;
2367 	}
2368 
2369       sprintf(match, "aup_%s_", My->parameterinfo[j].name);
2370 
2371       for (i = 0; i < CSYS_GLOBALNUM; i++)
2372 
2373 	if (((csys_global[i].type == CSYS_IRATE) ||
2374 	     (csys_global[i].type == CSYS_KRATE)) &&
2375 	    (csys_global[i].width == 1) &&
2376 	    csys_global[i].name &&
2377 	    !strncmp(match, csys_global[i].name, match_len))
2378 	  {
2379 	    if (strlen(csys_global[i].name) <= match_len)
2380 	      continue;
2381 
2382 	    nptr = &(csys_global[i].name[match_len]);
2383 
2384 	    if (!strcmp(nptr, "slider_squarelaw"))
2385 	      My->parameterinfo[j].flags |=
2386 		kAudioUnitParameterFlag_DisplaySquared;
2387 	    else
2388 	      if (!strcmp(nptr, "slider_cubic"))
2389 		My->parameterinfo[j].flags |=
2390 		  kAudioUnitParameterFlag_DisplayCubed;
2391 	      else
2392 		if (!strcmp(nptr, "slider_squareroot"))
2393 		  My->parameterinfo[j].flags |=
2394 		    kAudioUnitParameterFlag_DisplaySquareRoot;
2395 		else
2396 		  if (!strcmp(nptr, "slider_cuberoot"))
2397 		    My->parameterinfo[j].flags |=
2398 		      kAudioUnitParameterFlag_DisplayCubeRoot;
2399 		  else
2400 		    if (!strcmp(nptr, "slider_log"))
2401 		      My->parameterinfo[j].flags |=
2402 			kAudioUnitParameterFlag_DisplayLogarithmic;
2403 		    else
2404 		      if (!strcmp(nptr, "slider_exp"))
2405 			My->parameterinfo[j].flags |=
2406 			  kAudioUnitParameterFlag_DisplayExponential;
2407 		      else
2408 			if (!strcmp(nptr, "menu") || !strcmp(nptr, "display_menu"))
2409 			  {
2410 			    if (!strcmp(nptr, "display_menu"))
2411 			      My->parameterinfo[j].flags &=
2412 				~ kAudioUnitParameterFlag_IsWritable;
2413 
2414 			    My->parameterinfo[j].unit =
2415 			      kAudioUnitParameterUnit_Indexed;
2416 			    if (My->parameterinfo[j].unitName)
2417 			      {
2418 				CFRelease(My->parameterinfo[j].unitName);
2419 				My->parameterinfo[j].unitName = NULL;
2420 			      }
2421 			  }
2422 			else
2423 			  if (!strcmp(nptr, "checkbox") ||
2424 			      !strcmp(nptr, "display_checkbox"))
2425 			    {
2426 			      if (!strcmp(nptr, "display_checkbox"))
2427 				My->parameterinfo[j].flags &=
2428 				  ~ kAudioUnitParameterFlag_IsWritable;
2429 
2430 			      My->parameterinfo[j].unit =
2431 				kAudioUnitParameterUnit_Boolean;
2432 			      if (My->parameterinfo[j].unitName)
2433 				{
2434 				  CFRelease(My->parameterinfo[j].unitName);
2435 				  My->parameterinfo[j].unitName = NULL;
2436 				}
2437 			    }
2438 			  else
2439 			    if (!strcmp(nptr, "display_number"))
2440 			      {
2441 				My->parameterinfo[j].flags &=
2442 				  ~ kAudioUnitParameterFlag_IsWritable;
2443 			      }
2444 			    else
2445 			      if ((strcmp(nptr, "slider_linear") != 0) &&
2446 				  (strcmp(nptr, "slider") != 0))
2447 				continue;
2448 	    break;
2449 	  }
2450 
2451       free(match);
2452 
2453       My->saolparam[j].value = My->parameterinfo[j].defaultValue;
2454 
2455       nptr = &(My->parameterinfo[j].name[0]);
2456       do {
2457 	if (*nptr == '_')
2458 	  *nptr = ' ';
2459       } while (*(++nptr));
2460 
2461       My->parameterinfo[j].cfNameString = CFStringCreateWithCString
2462 	(NULL, My->parameterinfo[j].name, kCFStringEncodingASCII);
2463 
2464       if (!(My->parameterinfo[j].cfNameString))
2465 	{
2466 	  shut_down(ENGINE_PTR);
2467 	  return kAudioUnitErr_FailedInitialization;
2468 	}
2469     }
2470 
2471   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2472   /* Create parameter-value strings for Indexed parameters */
2473   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2474 
2475   if ((ret = asysn_audiounit_parametervaluestrings_parametersystem(My)) != noErr)
2476     {
2477       shut_down(ENGINE_PTR);
2478       return ret;
2479     }
2480 
2481   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2482   /* initialize factory preset data structures */
2483   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2484 
2485   if ((ret = asysn_audiounit_factorypreset_parametersystem
2486        (ENGINE_PTR_COMMA My)) != noErr)
2487     {
2488       shut_down(ENGINE_PTR);
2489       return ret;
2490     }
2491 
2492   /*~~~~~~~~~~~~~~~~~~~*/
2493   /* Shut down engine  */
2494   /*~~~~~~~~~~~~~~~~~~~*/
2495 
2496   shut_down(ENGINE_PTR);
2497   return noErr;
2498 }
2499 
2500 
2501 /************************************************************/
2502 /* Helper for Open Selector: Initializes property variables */
2503 /************************************************************/
2504 
asysn_audiounit_initialize_properties(asysn_audiounit_InstanceState * My)2505 ComponentResult asysn_audiounit_initialize_properties
2506 (asysn_audiounit_InstanceState * My)
2507 
2508 {
2509   int i;
2510 
2511   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2512   /* the first set of parameters define the signal flow  */
2513   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2514 
2515   /* the preferred audiounit bus widths */
2516 
2517   My->InputElementCount = ASYS_AUDIOUNIT_ELEMENT_INPUTPREF;
2518   My->OutputElementCount = ASYS_AUDIOUNIT_ELEMENT_OUTPUTPREF;
2519 
2520   /* defines fixed channel widths. todo: turn into an array of formats */
2521 
2522   if (ASYS_AUDIOUNIT_EFFECT)
2523     {
2524       My->SupportedNumChannels[0].inChannels = ASYS_AUDIOUNIT_MONO;
2525       My->SupportedNumChannels[0].outChannels = ASYS_AUDIOUNIT_MONO;
2526       My->SupportedNumChannels[1].inChannels = ASYS_AUDIOUNIT_MONO;
2527       My->SupportedNumChannels[1].outChannels = ASYS_AUDIOUNIT_STEREO;
2528       My->SupportedNumChannels[2].inChannels = ASYS_AUDIOUNIT_STEREO;
2529       My->SupportedNumChannels[2].outChannels = ASYS_AUDIOUNIT_MONO;
2530       My->SupportedNumChannels[3].inChannels = ASYS_AUDIOUNIT_STEREO;
2531       My->SupportedNumChannels[3].outChannels = ASYS_AUDIOUNIT_STEREO;
2532     }
2533   else
2534     {
2535       My->SupportedNumChannels[0].inChannels = ASYS_AUDIOUNIT_NULL;
2536       My->SupportedNumChannels[0].outChannels = ASYS_AUDIOUNIT_MONO;
2537       My->SupportedNumChannels[1].inChannels = ASYS_AUDIOUNIT_NULL;
2538       My->SupportedNumChannels[1].outChannels = ASYS_AUDIOUNIT_STEREO;
2539     }
2540 
2541 
2542   /* maximum audio sample chunk -- augment with other variables to resize buffers */
2543 
2544   My->MaximumFramesPerSlice = ASYS_AUDIOUNIT_FRAMES_PER_SLICE;
2545 
2546   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2547   /* our desired input and output stream format */
2548   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2549 
2550   for (i=0; i < ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE; i++)
2551     {
2552       /* mChannelsPerFrame code mono, stereo, etc */
2553 
2554       My->InputStreamFormat[i].mChannelsPerFrame = ASYS_AUDIOUNIT_INPUT_CHANNELS;
2555 
2556       /* could also be kAudioStreamAnyRate, once we support setproperty over-ride */
2557 
2558       My->InputStreamFormat[i].mSampleRate = SAOL_SRATE;
2559 
2560       /* a set of non-interleaved mono channels -- do not touch these */
2561 
2562       My->InputStreamFormat[i].mFormatID = kAudioFormatLinearPCM;
2563 
2564       My->InputStreamFormat[i].mFormatFlags = (kAudioFormatFlagIsFloat |
2565 					    kAudioFormatFlagIsPacked |
2566 					    kAudioFormatFlagIsNonInterleaved);
2567 
2568       if (ASYS_AUDIOUNIT_FLOAT32_BIGENDIAN)
2569 	My->InputStreamFormat[i].mFormatFlags |= kAudioFormatFlagIsBigEndian;
2570 
2571       My->InputStreamFormat[i].mBytesPerPacket = 4;
2572       My->InputStreamFormat[i].mBytesPerFrame = 4;
2573       My->InputStreamFormat[i].mFramesPerPacket = 1;
2574       My->InputStreamFormat[i].mBitsPerChannel = 32;
2575 
2576       My->InputStreamFormat[i].mReserved = 0;
2577     }
2578 
2579   /* mChannelsPerFrame code mono, stereo, etc */
2580 
2581   My->OutputStreamFormat.mChannelsPerFrame = ASYS_AUDIOUNIT_OUTPUT_CHANNELS;
2582 
2583   /* could also be kAudioStreamAnyRate, once we support setproperty over-ride */
2584 
2585   My->OutputStreamFormat.mSampleRate = SAOL_SRATE;
2586 
2587   My->acycle = ((int)(SAOL_SRATE))/((int)(SAOL_KRATE));
2588   My->krate = SAOL_KRATE;
2589   My->acycleidx_kcycleidx = 1;     /* acycleidx = 0, kcycleidx = 1 */
2590 
2591   /* a set of non-interleaved mono channels -- do not touch these */
2592 
2593   My->OutputStreamFormat.mFormatID = kAudioFormatLinearPCM;
2594 
2595   My->OutputStreamFormat.mFormatFlags = (kAudioFormatFlagIsFloat |
2596 					 kAudioFormatFlagIsPacked |
2597 					 kAudioFormatFlagIsNonInterleaved);
2598 
2599   if (ASYS_AUDIOUNIT_FLOAT32_BIGENDIAN)
2600     My->OutputStreamFormat.mFormatFlags |= kAudioFormatFlagIsBigEndian;
2601 
2602   My->OutputStreamFormat.mBytesPerPacket = 4;
2603   My->OutputStreamFormat.mBytesPerFrame = 4;
2604   My->OutputStreamFormat.mFramesPerPacket = 1;
2605   My->OutputStreamFormat.mBitsPerChannel = 32;
2606 
2607   My->OutputStreamFormat.mReserved = 0;
2608 
2609   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2610   /* end of streamformat property */
2611   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2612 
2613   /* tracks if the audio unit is currently bypassed */
2614 
2615   My->BypassEffect = 0;
2616   My->LastBypassEffect = 0;
2617 
2618   /* set to 1 if we renderer returns the buffers use for SetRenderCallback */
2619 
2620   My->InPlaceProcessing = ASYS_AUDIOUNIT_INPLACE_PROCESSING;
2621 
2622   /* define the null preset */
2623 
2624   My->PresentPreset.presetName = CFStringCreateWithCString(NULL, "Untitled",
2625 							   kCFStringEncodingASCII);
2626   if (!(My->PresentPreset.presetName))
2627     return kAudioUnitErr_FailedInitialization;
2628 
2629   My->PresentPreset.presetNumber = -1;
2630 
2631   My->lock_PresentPreset = 0;
2632 
2633   /* number of instruments offered by the music device */
2634 
2635   if (ASYS_AUDIOUNIT_MUSICDEVICE)
2636     My->InstrumentCount = ASYS_AUDIOUNIT_INSTRUMENT_COUNT;
2637   else
2638     My->InstrumentCount = 0;
2639 
2640   /* 1 if the audio unit intends to stream samples off of the disk */
2641 
2642   My->StreamFromDisk = 0;
2643 
2644   /* the function pointer and parameters SetRenderCallback provides */
2645 
2646   for (i=0; i < ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE; i++)
2647     {
2648       My->SetRenderCallback[i].inputProc = NULL;
2649       My->SetRenderCallback[i].inputProcRefCon = NULL;
2650     }
2651 
2652   /* how the host tells us who is driving us */
2653 
2654   for (i=0; i < ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE; i++)
2655     {
2656       My->MakeConnection[i].sourceAudioUnit = 0;
2657       My->MakeConnection[i].sourceOutputNumber = 0;
2658       My->MakeConnection[i].destInputNumber = 0;
2659     }
2660 
2661   /* lock for both SetRenderCallback and MakeConnection */
2662 
2663   My->lock_sampledelivery = 0;
2664 
2665  /* the function pointer and parameters RenderNotify provides, and its lock */
2666 
2667   My->rendernotify = NULL;
2668   My->lock_rendernotify = 0;
2669 
2670   /* tracks last rendering error for the rendering proc - clear after returning it */
2671 
2672   My->LastRenderError = noErr;
2673 
2674   /* for now, assume AU algorithm has no latency */
2675 
2676   My->Latency = 0.0;
2677 
2678   /* tail time (in a reverb sense) for the audio unit */
2679 
2680   My->TailTime = 0.0;
2681 
2682   /* to be used for selecting sfront's sample-rate conversion algorithm */
2683 
2684   My->SRCAlgorithm = kAudioUnitSRCAlgorithm_Polyphase;
2685 
2686   /* request for render quality, using 0-127 scaled enum in AudioUnitProperties.h */
2687 
2688   My->RenderQuality = kRenderQuality_Max;
2689 
2690   /* the % of total CPU load the host allots to us, 0 codes no limit */
2691 
2692   My->CPULoad = 0.0;
2693   My->lock_CPULoad = 0;
2694   My->ksync_normalize = (Float32) (My->krate/AudioGetHostClockFrequency());
2695 
2696   /* a heads-up for off-line operation, sent by host */
2697 
2698   My->OfflineRender = 0;
2699 
2700   /* a heads-up for the presentation latency, sent by host */
2701 
2702   My->PresentationLatency = 0.0;
2703 
2704   /* listener callback lists for each supported property */
2705 
2706   for (i = 0; i < ASYS_AUDIOUNIT_PROPLISTEN_ARRAYSIZE; i++)
2707     My->proplisteners[i] = NULL;
2708 
2709   My->lock_proplisteners = 0;
2710 
2711   /*~~~~~~~~~~~~~~~~~~~~~*/
2712   /* aup_ property state */
2713   /*~~~~~~~~~~~~~~~~~~~~~*/
2714 
2715   My->num_saolparams = 0;
2716   My->parameterlist = NULL;
2717   My->parameterinfo = NULL;
2718   My->pvs_size = NULL;
2719   My->pvs_cstr = NULL;
2720   My->saolparam = NULL;
2721   My->num_factory = 0;
2722   My->factorypreset_values = NULL;
2723   My->factorypreset_info = NULL;
2724   My->factorypreset_array = NULL;
2725 
2726   return noErr;
2727 }
2728 
2729 /************************************************************/
2730 /* Helper for Open Selector: Memstatus for global variables */
2731 /************************************************************/
2732 
asysn_audiounit_globalvars_memstatus(int advice)2733 void asysn_audiounit_globalvars_memstatus(int advice)
2734 
2735 {
2736   int msize, i, j;
2737 
2738   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2739   /* global arrays used by main_ipass */
2740   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2741 
2742 #if (defined(CSYS_MAXEXTCHAN) && (CSYS_MAXEXTCHAN > 0))
2743   msize = CSYS_MAXEXTCHAN*sizeof(int);
2744   asysn_audiounit_memstatus(cme_preset, msize, advice);
2745 #endif
2746 
2747 #if (defined(CSYS_MAXSASLINSTR) && (CSYS_MAXSASLINSTR > 0))
2748   msize = CSYS_MAXSASLINSTR*sizeof(int);
2749   asysn_audiounit_memstatus(csys_instrtablesize, msize, advice);
2750   asysn_audiounit_memstatus(csys_instrvarsize, msize, advice);
2751 #endif
2752 
2753   /*~~~~~~~~~~~~~~~~~~~~~*/
2754   /* global table arrays */
2755   /*~~~~~~~~~~~~~~~~~~~~~*/
2756 
2757 #if (defined(CSYS_TABLE_CATALOG_SIZE) && (CSYS_TABLE_CATALOG_SIZE > 0))
2758   for (i = 0; i < CSYS_TABLE_CATALOG_SIZE; i++)
2759     {
2760       msize = csys_table_catalog[i].num*sizeof(float);
2761       asysn_audiounit_memstatus(csys_table_catalog[i].t, msize, advice);
2762     }
2763 #endif
2764 
2765   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2766   /* reflection interface variables */
2767   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2768 
2769 #if (defined(CSYS_GLOBALNUM) && (CSYS_GLOBALNUM > 0))
2770   msize = CSYS_GLOBALNUM*sizeof(csys_varstruct);
2771   asysn_audiounit_memstatus(csys_global, msize, advice);
2772 #endif
2773 
2774 #if (defined(CSYS_TARGETNUM) && (CSYS_TARGETNUM > 0))
2775   msize = CSYS_TARGETNUM*sizeof(csys_targetstruct);
2776   asysn_audiounit_memstatus(csys_target, msize, advice);
2777 #endif
2778 
2779 #if (defined(CSYS_LABELNUM) && (CSYS_LABELNUM > 0))
2780   msize = CSYS_LABELNUM*sizeof(csys_labelstruct);
2781   asysn_audiounit_memstatus(csys_labels, msize, advice);
2782 #endif
2783 
2784 #if (defined(CSYS_PRESETNUM) && (CSYS_PRESETNUM > 0))
2785   msize = CSYS_PRESETNUM*sizeof(csys_presetstruct);
2786   asysn_audiounit_memstatus(csys_presets, msize, advice);
2787 #endif
2788 
2789 #if (defined(CSYS_SAMPLENUM) && (CSYS_SAMPLENUM > 0))
2790   msize = CSYS_SAMPLENUM*sizeof(csys_samplestruct);
2791   asysn_audiounit_memstatus(csys_samples, msize, advice);
2792 #endif
2793 
2794 #if (defined(CSYS_BUSNUM) && (CSYS_BUSNUM > 0))
2795   msize = CSYS_BUSNUM*sizeof(csys_busstruct);
2796   asysn_audiounit_memstatus(csys_bus, msize, advice);
2797 #endif
2798 
2799 #if (defined(CSYS_ROUTENUM) && (CSYS_ROUTENUM > 0))
2800   msize = CSYS_ROUTENUM*sizeof(csys_routestruct);
2801   asysn_audiounit_memstatus(csys_route, msize, advice);
2802 #endif
2803 
2804 #if (defined(CSYS_SENDNUM) && (CSYS_SENDNUM > 0))
2805   msize = CSYS_SENDNUM*sizeof(csys_sendstruct);
2806   asysn_audiounit_memstatus(csys_send, msize, advice);
2807   for (i = 0; i < CSYS_SENDNUM; i++)
2808     if (csys_send[i].bus)
2809       {
2810 	msize = csys_send[i].nbus*sizeof(int);
2811 	asysn_audiounit_memstatus(csys_send[i].bus, msize, advice);
2812       }
2813 #endif
2814 
2815 #if (defined(CSYS_INSTRNUM) && (CSYS_INSTRNUM > 0))
2816   msize = CSYS_INSTRNUM*sizeof(csys_instrstruct);
2817   asysn_audiounit_memstatus(csys_instr, msize, advice);
2818   for (i = 0; i < CSYS_INSTRNUM; i++)
2819     {
2820       if (csys_instr[i].name)
2821 	{
2822 	  msize = (strlen(csys_instr[i].name) + 1)*sizeof(char);
2823 	  asysn_audiounit_memstatus(csys_instr[i].name, msize, advice);
2824 	}
2825       if (csys_instr[i].vars)
2826 	{
2827 	  msize = csys_instr[i].numvars*sizeof(csys_varstruct);
2828 	  asysn_audiounit_memstatus(csys_instr[i].vars, msize, advice);
2829 	  for (j = 0; j < csys_instr[i].numvars; j++)
2830 	    if (csys_instr[i].vars[j].name)
2831 	      {
2832 		msize = (strlen(csys_instr[i].vars[j].name) + 1)*sizeof(char);
2833 		asysn_audiounit_memstatus(csys_instr[i].vars[j].name, msize, advice);
2834 	      }
2835 	}
2836     }
2837 #endif
2838 
2839 }
2840 
2841 /************************************************************/
2842 /* Helper for Open Selector: Recover from a failed open.    */
2843 /************************************************************/
2844 
asysn_audiounit_instance_cleanup(ComponentParameters * p,asysn_audiounit_InstanceState * My)2845 ComponentResult asysn_audiounit_instance_cleanup
2846 (ComponentParameters * p, asysn_audiounit_InstanceState * My)
2847 
2848 {
2849   int i, k, msize;
2850 
2851   if (My)
2852     {
2853       if (My->PresentPreset.presetName)
2854 	CFRelease(My->PresentPreset.presetName);
2855 
2856       if (My->AudioBufferCarrier)
2857 	{
2858 	  msize = sizeof(UInt32) + sizeof(AudioBuffer)*ASYS_AUDIOUNIT_INPUT_MAXCHANNELS;
2859 	  asysn_audiounit_memstatus(My->AudioBufferCarrier, msize, MADV_FREE);
2860 	  free(My->AudioBufferCarrier);
2861 	}
2862 
2863       if (My->AudioBufferTemplate)
2864 	{
2865 	  msize = sizeof(Float32)*ASYS_AUDIOUNIT_FRAMES_PER_SLICE;
2866 	  for(i = 0; i < ASYS_AUDIOUNIT_INPUT_MAXCHANNELS; i++)
2867 	    if (My->AudioBufferTemplate->mBuffers[i].mData)
2868 	      {
2869 		asysn_audiounit_memstatus(My->AudioBufferTemplate->mBuffers[i].mData,
2870 					  msize, MADV_FREE);
2871 		free(My->AudioBufferTemplate->mBuffers[i].mData);
2872 	      }
2873 	  msize = sizeof(UInt32) + sizeof(AudioBuffer)*ASYS_AUDIOUNIT_INPUT_MAXCHANNELS;
2874 	  asysn_audiounit_memstatus(My->AudioBufferTemplate, msize, MADV_FREE);
2875 	  free(My->AudioBufferTemplate);
2876 	}
2877 
2878       for(i = 0; i < ASYS_AUDIOUNIT_OUTPUT_MAXCHANNELS; i++)
2879 	if (My->mData_Output[i])
2880 	  {
2881 	    msize = sizeof(Float32)*ASYS_AUDIOUNIT_FRAMES_PER_SLICE;
2882 	    asysn_audiounit_memstatus(My->mData_Output[i], msize, MADV_FREE);
2883 	    free(My->mData_Output[i]);
2884 	  }
2885 
2886       if (My->mpipepair[0])
2887 	close(My->mpipepair[0]);
2888       if (My->mpipepair[1])
2889 	close(My->mpipepair[1]);
2890       if (My->spipepair[0])
2891 	close(My->spipepair[0]);
2892       if (My->spipepair[1])
2893 	close(My->spipepair[1]);
2894 
2895       if (My->parameterlist)
2896 	free(My->parameterlist);
2897 
2898       if (My->parameterinfo)
2899 	{
2900 	  for (i = 0; i < My->num_saolparams; i++)
2901 	    {
2902 	      if (My->parameterinfo[i].cfNameString)
2903 		CFRelease(My->parameterinfo[i].cfNameString);
2904 	      if (My->parameterinfo[i].unitName)
2905 		CFRelease(My->parameterinfo[i].unitName);
2906 	    }
2907 	  free(My->parameterinfo);
2908 	}
2909 
2910       if (My->pvs_size)
2911 	{
2912 	  if (My->pvs_cstr)
2913 	    {
2914 	      for (i = 0; i < My->num_saolparams; i++)
2915 		if (My->pvs_cstr[i])
2916 		  {
2917 		    for (k = 0; k < My->pvs_size[i]; k++)
2918 		      if (My->pvs_cstr[i][k])
2919 			free(My->pvs_cstr[i][k]);
2920 		    free(My->pvs_cstr[i]);
2921 		  }
2922 	      free(My->pvs_cstr);
2923 	    }
2924 	  free(My->pvs_size);
2925 	}
2926 
2927       if (My->saolparam)
2928 	{
2929 	  msize = My->num_saolparams*sizeof(asysn_audiounit_saolparam);
2930 	  asysn_audiounit_memstatus(My->saolparam, msize, MADV_FREE);
2931 	  free(My->saolparam);
2932 	}
2933 
2934       if (My->factorypreset_info)
2935 	{
2936 	  for (i = 0; i < My->num_factory; i++)
2937 	    if (My->factorypreset_info[i].presetName)
2938 	      CFRelease(My->factorypreset_info[i].presetName);
2939 	  free(My->factorypreset_info);
2940 	}
2941 
2942       if (My->factorypreset_values)
2943 	{
2944 	  msize = My->num_saolparams*sizeof(Float32);
2945 	  for (i = 0; i < My->num_factory; i++)
2946 	    if (My->factorypreset_values[i])
2947 	      {
2948 		asysn_audiounit_memstatus(My->factorypreset_values[i], msize, MADV_FREE);
2949 		free(My->factorypreset_values[i]);
2950 	      }
2951 
2952 	  msize = My->num_factory*sizeof(Float32 *);
2953 	  asysn_audiounit_memstatus(My->factorypreset_values, msize, MADV_FREE);
2954 	  free(My->factorypreset_values);
2955 	}
2956 
2957       if (My->factorypreset_array)
2958 	CFRelease(My->factorypreset_array);
2959 
2960       msize = sizeof(asysn_audiounit_InstanceState);
2961       asysn_audiounit_memstatus(My, msize, MADV_FREE);
2962       free(My);
2963     }
2964 
2965   SetComponentInstanceStorage((ComponentInstance) p->params[0], (Handle) NULL);
2966   return kAudioUnitErr_FailedInitialization;
2967 }
2968 
2969 /**********************************************************************/
2970 /* Helper for Initialize Selector: Send all parameters to SAOL engine */
2971 /**********************************************************************/
2972 
asysn_audiounit_engine_parameter_update(asysn_audiounit_InstanceState * My)2973 ComponentResult asysn_audiounit_engine_parameter_update
2974 (asysn_audiounit_InstanceState * My)
2975 
2976 {
2977   asysn_audiounit_SASLevent SASLevent;
2978   int result = noErr;
2979   int i;
2980 
2981   for (i = 0; i < My->num_saolparams; i++)
2982     {
2983       SASLevent.index = i;
2984       SASLevent.value = My->saolparam[i].value;
2985       SASLevent.kcycleidx = 0;
2986       result |= asysn_audiounit_sendSASLevent(&SASLevent, My);
2987     }
2988 
2989   return result;
2990 }
2991 
2992 /***************************************************************/
2993 /* Helper for Uninitialize Selector: empty MIDI and SASL pipes */
2994 /***************************************************************/
2995 
asysn_audiounit_engine_emptypipes(asysn_audiounit_InstanceState * My)2996 void asysn_audiounit_engine_emptypipes
2997 (asysn_audiounit_InstanceState * My)
2998 {
2999   asysn_audiounit_MIDIevent mdummy;
3000   asysn_audiounit_SASLevent sdummy;
3001   int retry = 0;
3002 
3003   if (ASYS_AUDIOUNIT_MIDISUPPORT && My->mpipepair[0])
3004     do {
3005       if (retry++ > ASYS_AUDIOUNIT_RETRY_MAX)
3006 	break;
3007     } while ((read(My->mpipepair[0], &mdummy,
3008 		   sizeof(asysn_audiounit_MIDIevent)) > 0) || (errno == EINTR));
3009 
3010   retry == 0;
3011 
3012   if (My->spipepair[0])
3013     do {
3014       if (retry++ > ASYS_AUDIOUNIT_RETRY_MAX)
3015 	break;
3016     } while ((read(My->spipepair[0], &sdummy,
3017 		   sizeof(asysn_audiounit_SASLevent)) > 0) || (errno == EINTR));
3018 }
3019 
3020 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3021 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3022 /* Helper Functions for the GetProperty Selector Helper for ClassInfo  */
3023 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3024 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3025 
3026 /***********************************************/
3027 /* Big-endian int append to a CFMutableDataRef */
3028 /***********************************************/
3029 
asysn_audiounit_classinfo_pdata_intwrite(CFMutableDataRef pdata,SInt32 value)3030 void asysn_audiounit_classinfo_pdata_intwrite(CFMutableDataRef pdata, SInt32 value)
3031 
3032 {
3033   unsigned char p[4];
3034 
3035   p[0] = 0x000000FF & (value >> 24);
3036   p[1] = 0x000000FF & (value >> 16);
3037   p[2] = 0x000000FF & (value >> 8);
3038   p[3] = 0x000000FF & (value);
3039 
3040   CFDataAppendBytes(pdata, (UInt8 *) p, 4);
3041 }
3042 
3043 /***************************************************/
3044 /*  Big-endian float append to a CFMutableDataRef  */
3045 /*   Assumes int and float share an enddian-ness   */
3046 /***************************************************/
3047 
asysn_audiounit_classinfo_pdata_floatwrite(CFMutableDataRef pdata,Float32 fval)3048 void asysn_audiounit_classinfo_pdata_floatwrite(CFMutableDataRef pdata, Float32 fval)
3049 
3050 {
3051   union { int i; float f ; } u;
3052   unsigned char p[4];
3053 
3054   u.f = fval;
3055 
3056   p[0] = 0x000000FF & (u.i >> 24);
3057   p[1] = 0x000000FF & (u.i >> 16);
3058   p[2] = 0x000000FF & (u.i >> 8);
3059   p[3] = 0x000000FF & (u.i);
3060 
3061   CFDataAppendBytes(pdata, (UInt8 *) p, 4);
3062 }
3063 
3064 /************************************/
3065 /* Adds integer item to a ClassInfo */
3066 /************************************/
3067 
asysn_audiounit_classinfo_addint(CFMutableDictionaryRef ClassInfo,char * ckey,SInt32 value)3068 int asysn_audiounit_classinfo_addint(CFMutableDictionaryRef ClassInfo,
3069 				     char * ckey, SInt32 value)
3070 
3071 {
3072   CFStringRef key;
3073   CFNumberRef num;
3074   int errcode = -1;
3075 
3076   key = CFStringCreateWithCString(NULL, ckey, kCFStringEncodingASCII);
3077   if (key)
3078     {
3079       num = CFNumberCreate(NULL, kCFNumberSInt32Type, &value);
3080       if (num)
3081 	{
3082 	  CFDictionarySetValue(ClassInfo, key, num);
3083 	  CFRelease(num);
3084 	  errcode = 0;
3085 	}
3086       CFRelease(key);
3087     }
3088 
3089   return errcode;
3090 }
3091 
3092 /************************************/
3093 /* Adds float item to a ClassInfo */
3094 /************************************/
3095 
asysn_audiounit_classinfo_addfloat(CFMutableDictionaryRef ClassInfo,char * ckey,Float32 fval)3096 int asysn_audiounit_classinfo_addfloat(CFMutableDictionaryRef ClassInfo,
3097 				       char * ckey, Float32 fval)
3098 
3099 {
3100   CFStringRef key;
3101   CFNumberRef num;
3102   int errcode = -1;
3103 
3104   key = CFStringCreateWithCString(NULL, ckey, kCFStringEncodingASCII);
3105   if (key)
3106     {
3107       num = CFNumberCreate(NULL, kCFNumberFloatType, &fval);
3108       if (num)
3109 	{
3110 	  CFDictionarySetValue(ClassInfo, key, num);
3111 	  CFRelease(num);
3112 	  errcode = 0;
3113 	}
3114       CFRelease(key);
3115     }
3116 
3117   return errcode;
3118 }
3119 
3120 /*************************************/
3121 /* Adds CFString item to a ClassInfo */
3122 /*************************************/
3123 
asysn_audiounit_classinfo_addcfstr(CFMutableDictionaryRef ClassInfo,char * ckey,CFStringRef cfstr)3124 int asysn_audiounit_classinfo_addcfstr(CFMutableDictionaryRef ClassInfo,
3125 				       char * ckey, CFStringRef cfstr)
3126 
3127 {
3128   CFStringRef key;
3129   int errcode = -1;
3130 
3131   key = CFStringCreateWithCString(NULL, ckey, kCFStringEncodingASCII);
3132   if (key)
3133     {
3134       CFDictionarySetValue(ClassInfo, key, cfstr);
3135       CFRelease(key);
3136       errcode = 0;
3137     }
3138 
3139   return errcode;
3140 }
3141 
3142 /************************************************************************/
3143 /* Helper for GetProperty Selector: Create ClassInfo for use by AU host */
3144 /************************************************************************/
3145 
asysn_audiounit_classinfo_create(asysn_audiounit_InstanceState * My)3146 CFMutableDictionaryRef asysn_audiounit_classinfo_create
3147                                            (asysn_audiounit_InstanceState * My)
3148 
3149 {
3150   CFMutableDictionaryRef ClassInfo;
3151   CFMutableDataRef pdata;
3152   CFStringRef key;
3153   int i;
3154 
3155   ClassInfo = CFDictionaryCreateMutable
3156     (NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
3157 
3158   /* component definitions adapted from volume.r */
3159 
3160   asysn_audiounit_classinfo_addint(ClassInfo, kAUPresetVersionKey,
3161 				   0);  /* version 0 */
3162   asysn_audiounit_classinfo_addint(ClassInfo, kAUPresetTypeKey,
3163 				   ASYS_AUDIOUNIT_COMP_TYPE);
3164   asysn_audiounit_classinfo_addint(ClassInfo, kAUPresetSubtypeKey,
3165 				   ASYS_AUDIOUNIT_COMP_SUBTYPE);
3166   asysn_audiounit_classinfo_addint(ClassInfo, kAUPresetManufacturerKey,
3167 				   ASYS_AUDIOUNIT_COMP_MANU);
3168 
3169   /* parameter data */
3170 
3171   if ((pdata = CFDataCreateMutable(NULL, 0)) && My->num_saolparams)
3172     {
3173       asysn_audiounit_classinfo_pdata_intwrite(pdata,
3174   			              kAudioUnitScope_Global);     /* global scope */
3175       asysn_audiounit_classinfo_pdata_intwrite(pdata,
3176 				      0);                       /* element (bus) 0 */
3177       asysn_audiounit_classinfo_pdata_intwrite(pdata,
3178 				      My->num_saolparams); /* number of parameters */
3179 
3180       for (i = 0; i < My->num_saolparams; i++)
3181 	{
3182 	  /* parameter index */
3183 
3184 	  asysn_audiounit_classinfo_pdata_intwrite(pdata, i);
3185 
3186 	  /* value */
3187 
3188 	  asysn_audiounit_classinfo_pdata_floatwrite
3189 	    (pdata,
3190 	     (My->parameterinfo[i].flags & kAudioUnitParameterFlag_IsWritable) ?
3191 	     My->saolparam[i].value : My->parameterinfo[i].defaultValue);
3192 	}
3193     }
3194 
3195   if (pdata)
3196     {
3197       key = CFStringCreateWithCString(NULL, kAUPresetDataKey, kCFStringEncodingASCII);
3198       if (key)
3199 	{
3200 	  CFDictionarySetValue(ClassInfo, key, pdata);
3201 	  CFRelease(key);
3202 	}
3203       CFRelease(pdata);
3204     }
3205 
3206   asysn_audiounit_classinfo_addcfstr(ClassInfo, kAUPresetNameKey,
3207 				     My->PresentPreset.presetName);
3208   asysn_audiounit_classinfo_addint(ClassInfo, kAUPresetRenderQualityKey,
3209 				   (SInt32) (My->RenderQuality));
3210   asysn_audiounit_classinfo_addfloat(ClassInfo, kAUPresetCPULoadKey,
3211 				     My->CPULoad);
3212 
3213   /* add kAUPresetElementNameKey here if named elements/buses are supported */
3214 
3215   return ClassInfo;
3216 }
3217 
3218 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3219 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3220 /* Helper Functions for the SetProperty Selector Helper for ClassInfo  */
3221 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3222 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3223 
3224 /**************************************/
3225 /* Read integer item from a ClassInfo */
3226 /**************************************/
3227 
asysn_audiounit_classinfo_readint(CFMutableDictionaryRef ClassInfo,char * ckey,SInt32 * value)3228 int asysn_audiounit_classinfo_readint(CFMutableDictionaryRef ClassInfo,
3229 				      char * ckey, SInt32 * value)
3230 
3231 {
3232   CFStringRef key;
3233   CFNumberRef num;
3234   SInt32 newval;
3235   int errcode = -1;
3236 
3237   key = CFStringCreateWithCString(NULL, ckey, kCFStringEncodingASCII);
3238   if (key)
3239     {
3240       num = CFDictionaryGetValue(ClassInfo, key);
3241       if (num && CFNumberGetValue(num, kCFNumberSInt32Type, &newval))
3242 	{
3243 	  errcode = 0;
3244 	  *value = newval;
3245 	}
3246       CFRelease(key);
3247     }
3248   return errcode;
3249 }
3250 
3251 /**************************************/
3252 /*  Read float item from a ClassInfo  */
3253 /**************************************/
3254 
asysn_audiounit_classinfo_readfloat(CFMutableDictionaryRef ClassInfo,char * ckey,Float32 * value)3255 int asysn_audiounit_classinfo_readfloat(CFMutableDictionaryRef ClassInfo,
3256 					char * ckey, Float32 * value)
3257 
3258 {
3259   CFStringRef key;
3260   CFNumberRef num;
3261   Float32 newval;
3262   int errcode = -1;
3263 
3264   key = CFStringCreateWithCString(NULL, ckey, kCFStringEncodingASCII);
3265   if (key)
3266     {
3267       num = CFDictionaryGetValue(ClassInfo, key);
3268       if (num && CFNumberGetValue(num, kCFNumberFloat32Type, &newval))
3269 	{
3270 	  errcode = 0;
3271 	  *value = newval;
3272 	}
3273       CFRelease(key);
3274     }
3275   return errcode;
3276 }
3277 
3278 /***************************************/
3279 /* Read CFString item from a ClassInfo */
3280 /***************************************/
3281 
asysn_audiounit_classinfo_readcfstr(CFMutableDictionaryRef ClassInfo,char * ckey,CFStringRef * cfstr)3282 int asysn_audiounit_classinfo_readcfstr(CFMutableDictionaryRef ClassInfo,
3283 					char * ckey, CFStringRef * cfstr)
3284 
3285 {
3286   CFStringRef key;
3287   CFNumberRef num;
3288   CFStringRef newstr;
3289   int errcode = -1;
3290 
3291   key = CFStringCreateWithCString(NULL, ckey, kCFStringEncodingASCII);
3292   if (key)
3293     {
3294       if (newstr = CFDictionaryGetValue(ClassInfo, key))
3295 	{
3296 	  errcode = 0;
3297 	  CFRetain(newstr);
3298 	  if (*cfstr)
3299 	    CFRelease(*cfstr);
3300 	  *cfstr = newstr;
3301 	}
3302       CFRelease(key);
3303     }
3304   return errcode;
3305 }
3306 
3307 /***********************************************/
3308 /* Big-endian int read from a CFMutableDataRef */
3309 /***********************************************/
3310 
asysn_audiounit_classinfo_pdata_intread(CFMutableDataRef pdata,UInt8 ** p)3311 SInt32 asysn_audiounit_classinfo_pdata_intread(CFMutableDataRef pdata, UInt8 ** p)
3312 
3313 {
3314   SInt32 value;
3315 
3316   value = ((*p)[0] << 24) | ((*p)[1] << 16) | ((*p)[2] << 8) | ((*p)[3]);
3317   (*p) += 4;
3318   return value;
3319 }
3320 
3321 /*************************************************/
3322 /* Big-endian float read from a CFMutableDataRef */
3323 /*************************************************/
3324 
asysn_audiounit_classinfo_pdata_floatread(CFMutableDataRef pdata,UInt8 ** p)3325 Float32 asysn_audiounit_classinfo_pdata_floatread(CFMutableDataRef pdata, UInt8 ** p)
3326 
3327 {
3328   union { SInt32 i; Float32 f ; } u;
3329 
3330   u.i = ((*p)[0] << 24) | ((*p)[1] << 16) | ((*p)[2] << 8) | ((*p)[3]);
3331   (*p) += 4;
3332   return u.f;
3333 }
3334 
3335 /****************************************/
3336 /* Read parameter data from a ClassInfo */
3337 /****************************************/
3338 
asysn_audiounit_classinfo_readpdata(asysn_audiounit_InstanceState * My,CFMutableDictionaryRef ClassInfo)3339 int asysn_audiounit_classinfo_readpdata(asysn_audiounit_InstanceState * My,
3340 					CFMutableDictionaryRef ClassInfo)
3341 
3342 {
3343   int errcode = -1;
3344   CFStringRef key;
3345   CFMutableDataRef pdata;
3346   UInt8 * p, * pmax;
3347   UInt32 scope, bus, count, idx;
3348   Float32 fval;
3349 
3350   key = CFStringCreateWithCString(NULL, kAUPresetDataKey, kCFStringEncodingASCII);
3351 
3352   if (key && (pdata = (CFMutableDataRef) CFDictionaryGetValue(ClassInfo, key)))
3353     {
3354       p = (UInt8 *) CFDataGetBytePtr(pdata);
3355       pmax = p + CFDataGetLength(pdata);
3356 
3357       do {
3358 	if (p == pmax)
3359 	  {
3360 	    errcode = 0;
3361 	    break;
3362 	  }
3363 	if ((pmax - p) >= 12)
3364 	  {
3365 	    scope = asysn_audiounit_classinfo_pdata_intread(pdata, &p);
3366 	    bus = asysn_audiounit_classinfo_pdata_intread(pdata, &p);
3367 	    count = asysn_audiounit_classinfo_pdata_intread(pdata, &p);
3368 	    if ((pmax - p) >= count*(sizeof(SInt32) + sizeof(Float32)))
3369 	      if ((scope == kAudioUnitScope_Global) && !bus)
3370 		while (count--)
3371 		  {
3372 		    idx = asysn_audiounit_classinfo_pdata_intread(pdata, &p);
3373 		    fval = asysn_audiounit_classinfo_pdata_floatread(pdata, &p);
3374 		    if (idx < My->num_saolparams)
3375 		      {
3376 			if (fval > My->parameterinfo[idx].maxValue)
3377 			  fval = My->parameterinfo[idx].maxValue;
3378 
3379 			if (fval < My->parameterinfo[idx].minValue)
3380 			  fval = My->parameterinfo[idx].minValue;
3381 
3382 			My->saolparam[idx].value = fval;
3383 		      }
3384 		  }
3385 	      else
3386 		p += count*(sizeof(SInt32) + sizeof(Float32));
3387 	    else
3388 	      break;
3389 	  }
3390 	else
3391 	  break;
3392       } while (1);
3393 
3394       CFRelease(key);
3395     }
3396 
3397   return errcode;
3398 }
3399 
3400 /************************************************************************/
3401 /* Helper for SetProperty Selector: Reads ClassInfo returned by AU host */
3402 /************************************************************************/
3403 
asysn_audiounit_classinfo_read(asysn_audiounit_InstanceState * My,CFMutableDictionaryRef ClassInfo)3404 void asysn_audiounit_classinfo_read(asysn_audiounit_InstanceState * My,
3405 				    CFMutableDictionaryRef ClassInfo)
3406 
3407 {
3408   asysn_audiounit_classinfo_readpdata(My, ClassInfo);
3409 
3410   asysn_audiounit_engine_parameter_update(My);
3411 
3412   asysn_audiounit_classinfo_readint(ClassInfo, kAUPresetRenderQualityKey,
3413 				    (SInt32 *) &(My->RenderQuality));
3414 
3415 
3416   OSSpinLockLock(&(My->lock_CPULoad));
3417 
3418   asysn_audiounit_classinfo_readfloat(ClassInfo, kAUPresetCPULoadKey,
3419 				      &(My->CPULoad));
3420   My->ksync_normalize = (Float32) (My->krate/AudioGetHostClockFrequency());
3421   if (My->CPULoad)
3422     My->ksync_normalize = My->ksync_normalize/My->CPULoad;
3423 
3424   OSSpinLockUnlock(&(My->lock_CPULoad));
3425 
3426 
3427   OSSpinLockLock(&(My->lock_PresentPreset));
3428 
3429   asysn_audiounit_classinfo_readcfstr(ClassInfo, kAUPresetNameKey,
3430 				      &(My->PresentPreset.presetName));
3431 
3432   My->PresentPreset.presetNumber =
3433     asysn_audiounit_factorypresetnumber(My->PresentPreset.presetName);
3434 
3435   OSSpinLockUnlock(&(My->lock_PresentPreset));
3436 
3437 
3438   /* add kAUPresetElementNameKey here if named elements/buses are supported */
3439 }
3440 
3441 /********************************************************************/
3442 /* Helper Function for SetProperty: PresentProperty Factory Presets */
3443 /********************************************************************/
3444 
asysn_audiounit_presentproperty_setfactory(asysn_audiounit_InstanceState * My)3445 void asysn_audiounit_presentproperty_setfactory
3446 (asysn_audiounit_InstanceState * My)
3447 
3448 {
3449   int j, k;
3450 
3451   j = My->PresentPreset.presetNumber;
3452 
3453   if ((j < 0) || (j > My->num_factory))
3454     return;
3455 
3456   for (k = 0; k < My->num_saolparams; k++)
3457     My->saolparam[k].value = My->factorypreset_values[j][k];
3458 
3459   asysn_audiounit_engine_parameter_update(My);
3460 }
3461 
3462 /*********************************************************************/
3463 /* Helper for Property Selectors: returns 1 for supported properties */
3464 /*********************************************************************/
3465 
asysn_audiounit_supported_property(AudioUnitPropertyID id,AudioUnitScope scope)3466 int asysn_audiounit_supported_property(AudioUnitPropertyID id, AudioUnitScope scope)
3467 
3468 {
3469   switch (id) {
3470   case kAudioUnitProperty_ClassInfo: /* 0 */
3471     return 1;
3472   case kAudioUnitProperty_MakeConnection: /* 1 */
3473     return 1;
3474   case kAudioUnitProperty_SampleRate: /* 2 */
3475     switch (scope) {
3476     case kAudioUnitScope_Input:
3477       return (ASYS_AUDIOUNIT_EFFECT) ? 1 : 0;
3478     case kAudioUnitScope_Global:
3479     case kAudioUnitScope_Output:
3480       return 1;
3481     default:
3482       return 0;
3483     }
3484   case kAudioUnitProperty_ParameterList: /* 3 */
3485     return  (scope == kAudioUnitScope_Global);
3486   case kAudioUnitProperty_ParameterInfo: /* 4 */
3487     return 1;
3488   case kAudioUnitProperty_FastDispatch:  /* 5 */
3489     return 1;
3490   case kAudioUnitProperty_CPULoad: /* 6 */
3491     return (scope == kAudioUnitScope_Global) ?
3492       ASYS_AUDIOUNIT_SUPPORT_PROPERTY_CPULOAD : 0;
3493   case kAudioUnitProperty_StreamFormat: /* 8 */
3494     switch (scope) {
3495     case kAudioUnitScope_Input:
3496       return (ASYS_AUDIOUNIT_EFFECT) ? 1 : 0;
3497     case kAudioUnitScope_Global:
3498     case kAudioUnitScope_Output:
3499       return 1;
3500     default:
3501       return 0;
3502     }
3503   case kAudioUnitProperty_SRCAlgorithm: /* 9 */
3504     return 1;
3505   case kAudioUnitProperty_ElementCount: /* 11, also kAudioUnitProperty_BusCount */
3506     return 1;
3507   case kAudioUnitProperty_Latency: /* 12 */
3508     return (scope == kAudioUnitScope_Global) ? 1 : 0;
3509   case kAudioUnitProperty_SupportedNumChannels: /* 13 */
3510     return (scope == kAudioUnitScope_Global) ? 1 : 0;
3511   case kAudioUnitProperty_MaximumFramesPerSlice: /* 14 */
3512     return (scope == kAudioUnitScope_Global) ? 1 : 0;
3513   case kAudioUnitProperty_ParameterValueStrings: /* 16 */
3514     return (scope == kAudioUnitScope_Global) ? 1 : 0;
3515   case kAudioUnitProperty_TailTime: /* 20 */
3516     return (scope == kAudioUnitScope_Global) ? 1 : 0;
3517   case kAudioUnitProperty_BypassEffect: /* 21 */
3518     return (scope == kAudioUnitScope_Global) ? 1 : 0;
3519   case kAudioUnitProperty_LastRenderError: /* 22 */
3520     return (scope == kAudioUnitScope_Global) ? 1 : 0;
3521   case kAudioUnitProperty_SetRenderCallback:  /* 23 */
3522     return 1;
3523   case kAudioUnitProperty_FactoryPresets: /* 24 */
3524     return 1;
3525   case kAudioUnitProperty_RenderQuality: /* 26 */
3526     return (scope == kAudioUnitScope_Global) ?
3527       ASYS_AUDIOUNIT_SUPPORT_PROPERTY_RENDERQUALITY : 0;
3528   case kAudioUnitProperty_InPlaceProcessing: /* 29 */
3529     return 1;
3530   case kAudioUnitProperty_CocoaUI: /* 31 */
3531 #if defined(ASYS_AUDIOUNIT_VIEW_BUNDLECF)
3532     return 1;
3533 #else
3534     return 0;
3535 #endif
3536   case kAudioUnitProperty_OfflineRender: /* 37 */
3537     return 1;
3538   case kAudioUnitProperty_PresentPreset: /* 36 */
3539     return 1;
3540   case kAudioUnitProperty_PresentationLatency: /* 40 */
3541     return 1;
3542   case kMusicDeviceProperty_InstrumentCount: /* 1000 */
3543     switch (scope) {
3544     case kAudioUnitScope_Global:
3545     case kAudioUnitScope_Input:
3546       return ASYS_AUDIOUNIT_MUSICDEVICE ? 1 : 0;
3547     default:
3548       return 0;
3549     }
3550   case kMusicDeviceProperty_StreamFromDisk: /* 1011 */
3551     return ASYS_AUDIOUNIT_SUPPORT_PROPERTY_STREAMFROMDISK;
3552   default:
3553     return 0;
3554   }
3555 }
3556 
3557 /*******************************************************************/
3558 /* Helper for property Selectors: returns property size (in bytes) */
3559 /*******************************************************************/
3560 
asysn_audiounit_property_size(AudioUnitPropertyID id,asysn_audiounit_InstanceState * My)3561 unsigned int asysn_audiounit_property_size(AudioUnitPropertyID id,
3562 					   asysn_audiounit_InstanceState * My)
3563 
3564 {
3565   switch (id) {
3566   case kAudioUnitProperty_ClassInfo: /* 0 */
3567     return sizeof(CFPropertyListRef);
3568   case kAudioUnitProperty_MakeConnection: /* 1 */
3569     return sizeof(AudioUnitConnection);
3570   case kAudioUnitProperty_SampleRate: /* 2 */
3571     return sizeof(Float64);
3572   case kAudioUnitProperty_ParameterList: /* 3 */
3573     return My->num_saolparams*sizeof(AudioUnitParameterID);
3574   case kAudioUnitProperty_ParameterInfo: /* 4 */
3575     return sizeof(AudioUnitParameterInfo);
3576   case kAudioUnitProperty_FastDispatch:  /* 5 */
3577     return sizeof(void *);
3578   case kAudioUnitProperty_CPULoad: /* 6 */
3579     return sizeof(Float32);
3580   case kAudioUnitProperty_StreamFormat: /* 8 */
3581     return sizeof(AudioStreamBasicDescription);
3582   case kAudioUnitProperty_SRCAlgorithm: /* 9 */
3583     return sizeof(OSType);
3584   case kAudioUnitProperty_ElementCount: /* 11, also kAudioUnitProperty_BusCount */
3585     return sizeof(UInt32);
3586   case kAudioUnitProperty_Latency: /* 12 */
3587     return sizeof(Float64);
3588   case kAudioUnitProperty_SupportedNumChannels: /* 13 */
3589     return ASYS_AUDIOUNIT_SUPPORTED_FORMATS*sizeof(AUChannelInfo);
3590   case kAudioUnitProperty_MaximumFramesPerSlice: /* 14 */
3591     return sizeof(UInt32);
3592   case kAudioUnitProperty_ParameterValueStrings: /* 16 */
3593     return sizeof(CFArrayRef);
3594   case kAudioUnitProperty_TailTime: /* 20 */
3595     return sizeof(Float64);
3596   case kAudioUnitProperty_BypassEffect: /* 21 */
3597     return sizeof(UInt32);
3598   case kAudioUnitProperty_LastRenderError: /* 22 */
3599     return sizeof(OSStatus);
3600   case kAudioUnitProperty_SetRenderCallback:  /* 23 */
3601     return sizeof(AURenderCallbackStruct);
3602   case kAudioUnitProperty_FactoryPresets: /* 24 */
3603     return sizeof(CFArrayRef);
3604   case kAudioUnitProperty_RenderQuality: /* 26 */
3605     return sizeof(UInt32);
3606   case kAudioUnitProperty_InPlaceProcessing: /* 29 */
3607     return sizeof(UInt32);
3608   case kAudioUnitProperty_CocoaUI: /* 31 */
3609 #if defined(ASYS_AUDIOUNIT_VIEW_BUNDLECF)
3610     return sizeof(AudioUnitCocoaViewInfo);
3611 #else
3612     break;
3613 #endif
3614   case kAudioUnitProperty_PresentPreset: /* 36 */
3615     return sizeof(AUPreset);
3616   case kAudioUnitProperty_OfflineRender: /* 37 */
3617     return sizeof(UInt32);
3618   case kAudioUnitProperty_PresentationLatency: /* 40 */
3619     return sizeof(Float64);
3620   case kMusicDeviceProperty_InstrumentCount: /* 1000 */
3621     return sizeof(UInt32);
3622   case kMusicDeviceProperty_StreamFromDisk: /* 1011 */
3623     return sizeof(UInt32);
3624   default:  /* no entries here -- all cases above should specify datasize */
3625     break;
3626   }
3627 
3628   ASYS_AUDIOUNIT_WIRETAP_PUTSTRING("WARNING: asysn_audiounit_property_size()"
3629 				   "called on an unsupported property\n");
3630   return 0;
3631 }
3632 
3633 /***************************************************************/
3634 /* Helper for Property Listener: returns proplisteners[] index */
3635 /***************************************************************/
3636 
asysn_audiounit_proplisteners_index(AudioUnitPropertyID id)3637 int asysn_audiounit_proplisteners_index(AudioUnitPropertyID id)
3638 
3639 {
3640   int property = -1;
3641 
3642   switch (id) {
3643   case kAudioUnitProperty_ParameterList: /* 3 */
3644     property = ASYS_AUDIOUNIT_PROPLISTEN_PARAMETERLIST;
3645     break;
3646   case kAudioUnitProperty_ParameterInfo: /* 4 */
3647     property = ASYS_AUDIOUNIT_PROPLISTEN_PARAMETERINFO;
3648     break;
3649   case kAudioUnitProperty_CPULoad: /* 6 */
3650     property = ASYS_AUDIOUNIT_PROPLISTEN_CPULOAD;
3651     break;
3652   case kAudioUnitProperty_Latency: /* 12 */
3653     property = ASYS_AUDIOUNIT_PROPLISTEN_LATENCY;
3654     break;
3655   case kAudioUnitProperty_MaximumFramesPerSlice: /* 14 */
3656     property = ASYS_AUDIOUNIT_PROPLISTEN_MAXIMUMFRAMESPERSLICE;
3657     break;
3658   case kAudioUnitProperty_TailTime: /* 20 */
3659     property = ASYS_AUDIOUNIT_PROPLISTEN_TAILTIME;
3660     break;
3661   case kAudioUnitProperty_FactoryPresets: /* 24 */
3662     property = ASYS_AUDIOUNIT_PROPLISTEN_FACTORYPRESETS;
3663     break;
3664   case kAudioUnitProperty_RenderQuality: /* 26 */
3665     property = ASYS_AUDIOUNIT_PROPLISTEN_RENDERQUALITY;
3666     break;
3667   case kAudioUnitProperty_CurrentPreset: /* 28 */
3668     property = ASYS_AUDIOUNIT_PROPLISTEN_CURRENTPRESET;
3669     break;
3670   case kAudioUnitProperty_PresentPreset: /* 36 */
3671     property = ASYS_AUDIOUNIT_PROPLISTEN_PRESENTPRESET;
3672     break;
3673   case kMusicDeviceProperty_StreamFromDisk: /* 1011 */
3674     property = ASYS_AUDIOUNIT_PROPLISTEN_STREAMFROMDISK;
3675     break;
3676   }
3677 
3678   return property;
3679 }
3680 
3681 /***************************************************************/
3682 /* Helper for properties: informs listeners of a status change */
3683 /***************************************************************/
3684 
asysn_audiounit_proplisteners_update(asysn_audiounit_InstanceState * My,AudioUnitPropertyID id,AudioUnitScope scope,AudioUnitElement element)3685 void asysn_audiounit_proplisteners_update(
3686                              asysn_audiounit_InstanceState * My,
3687 			     AudioUnitPropertyID id,
3688 			     AudioUnitScope scope,
3689 			     AudioUnitElement element)
3690 
3691 {
3692   int idx = asysn_audiounit_proplisteners_index(id);
3693   asysn_audiounit_proplisten * lp;
3694 
3695   if (idx < 0)
3696     return;
3697 
3698   OSSpinLockLock(&(My->lock_proplisteners));
3699 
3700   for (lp = My->proplisteners[idx]; lp != NULL; lp = lp->next)
3701     (*(lp->lproc))(lp->lrefcon, My->component, id, scope, element);
3702 
3703   /* some apps are buggy and need a double-send ... */
3704 
3705   for (lp = My->proplisteners[idx]; lp != NULL; lp = lp->next)
3706     (*(lp->lproc))(lp->lrefcon, My->component, id, scope, element);
3707 
3708   OSSpinLockUnlock(&(My->lock_proplisteners));
3709 
3710   return;
3711 }
3712 
3713 
3714 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3715 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3716 /*  The istate state transition functions    */
3717 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3718 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3719 
3720 /***************************************************************/
3721 /* State transition diagram on entrance to InitializeSelect:   */
3722 /*                                                             */
3723 /*           ABSENT: Return _MY_IS_NULL.                       */
3724 /*         INSTANCE: Set FLUX, return _INITIALIZE.             */
3725 /* INSTANCE_PASSING: Set FLUX_PASSING, return _INITIALIZE.     */
3726 /*             FLUX: Spin to INSTANCE* or ENGINE*.             */
3727 /*     FLUX_PASSING: Spin to INSTANCE* or ENGINE*.             */
3728 /*           ENGINE: Return _REINITIALIZE.                     */
3729 /*   ENGINE_PASSING: Return _REINITIALIZE.                     */
3730 /*    ENGINE_RENDER: Return _REINITIALIZE.                     */
3731 /***************************************************************/
3732 
asysn_audiounit_initializeselect_enterstate(asysn_audiounit_InstanceState * My)3733 int asysn_audiounit_initializeselect_enterstate(asysn_audiounit_InstanceState * My)
3734 
3735 {
3736   int ret;
3737 
3738   do
3739     {
3740       switch(My->istate) {
3741       case ASYS_AUDIOUNIT_ISTATE_ABSENT:
3742 	ret = ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL;
3743 	break;
3744       case ASYS_AUDIOUNIT_ISTATE_INSTANCE:
3745 	if (!OSAtomicCompareAndSwap32Barrier
3746 	    (ASYS_AUDIOUNIT_ISTATE_INSTANCE,
3747 	     ASYS_AUDIOUNIT_ISTATE_FLUX,
3748 	     (int32_t *) &(My->istate)))
3749 	  continue;
3750 	ret = ASYS_AUDIOUNIT_IRESPONSE_INITIALIZE;
3751 	break;
3752       case ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING:
3753 	if (!OSAtomicCompareAndSwap32Barrier
3754 	    (ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING,
3755 	     ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING,
3756 	     (int32_t *) &(My->istate)))
3757 	  continue;
3758 	ret = ASYS_AUDIOUNIT_IRESPONSE_INITIALIZE;
3759 	break;
3760       case ASYS_AUDIOUNIT_ISTATE_FLUX:
3761       case ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING:
3762 	OSMemoryBarrier();
3763 	continue;          /* spin to _INSTANCE or _ENGINE */
3764 	break;
3765       case ASYS_AUDIOUNIT_ISTATE_ENGINE:
3766       case ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING:
3767       case ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER:
3768 	ret = ASYS_AUDIOUNIT_IRESPONSE_REINITIALIZE;
3769 	break;
3770       default:
3771 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3772 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3773 	  ("\tBad transition - initializeselect_entrance (default)\n\n");
3774 	break;
3775       }
3776     } while (0);
3777 
3778   return ret;
3779 }
3780 
3781 /***************************************************************/
3782 /* State transition diagram on exit from InitializeSelect:     */
3783 /*                                                             */
3784 /*                                                             */
3785 /*           ABSENT: Return _ERROR.                            */
3786 /*         INSTANCE: Return _ERROR.                            */
3787 /* INSTANCE_PASSING: Return _ERROR.                            */
3788 /*             FLUX: Set ENGINE, return _COMPLETE.             */
3789 /*     FLUX_PASSING: Set ENGINE_PASSING, return _COMPLETE.     */
3790 /*           ENGINE: Return _ERROR.                            */
3791 /*   ENGINE_PASSING: Return _ERROR.                            */
3792 /*    ENGINE_RENDER: Return _ERROR.                            */
3793 /*                                                             */
3794 /***************************************************************/
3795 
asysn_audiounit_initializeselect_exitstate(asysn_audiounit_InstanceState * My)3796 int asysn_audiounit_initializeselect_exitstate(asysn_audiounit_InstanceState * My)
3797 
3798 {
3799   int ret;
3800 
3801   do
3802     {
3803       switch(My->istate) {
3804       case ASYS_AUDIOUNIT_ISTATE_ABSENT:
3805 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3806 	  ("\tBad transition - initializeselect_exit (absent)\n\n");
3807 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3808 	break;
3809       case ASYS_AUDIOUNIT_ISTATE_INSTANCE:
3810       case ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING:
3811 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3812 	  ("\tBad transition - initializeselect_exit (instance*)\n\n");
3813 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3814 	break;
3815       case ASYS_AUDIOUNIT_ISTATE_FLUX:
3816 	if (!OSAtomicCompareAndSwap32Barrier
3817 	    (ASYS_AUDIOUNIT_ISTATE_FLUX,
3818 	     ASYS_AUDIOUNIT_ISTATE_ENGINE,
3819 	     (int32_t *) &(My->istate)))
3820 	  continue;
3821 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
3822 	break;
3823       case ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING:
3824 	if (!OSAtomicCompareAndSwap32Barrier
3825 	    (ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING,
3826 	     ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING,
3827 	     (int32_t *) &(My->istate)))
3828 	  continue;
3829 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
3830 	break;
3831       case ASYS_AUDIOUNIT_ISTATE_ENGINE:
3832       case ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING:
3833       case ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER:
3834 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3835 	  ("\tBad transition - initializeselect_exit (engine*)\n\n");
3836 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3837 	break;
3838       default:
3839 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3840 	  ("\tBad transition - initializeselect_exit (default)\n\n");
3841 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3842 	break;
3843       }
3844     } while (0);
3845 
3846   return ret;
3847 }
3848 
3849 
3850 /********************************************************************/
3851 /* State transition diagram on entrance to UninitializeSelect:      */
3852 /*                                                                  */
3853 /*           ABSENT: Return _MY_IS_NULL.                            */
3854 /*         INSTANCE: Return _REUNINITIALIZE.                        */
3855 /* INSTANCE_PASSING: Return _REUNINITIALIZE.                        */
3856 /*             FLUX: Spin to INSTANCE* or ENGINE*.                  */
3857 /*     FLUX_PASSING: Spin to INSTANCE* or ENGINE*.                  */
3858 /*           ENGINE: Set FLUX, return _UNINITIALIZE                 */
3859 /*   ENGINE_PASSING: Spin to ENGINE.                                */
3860 /*    ENGINE_RENDER: Spin to ENGINE.                                */
3861 /********************************************************************/
3862 
asysn_audiounit_uninitializeselect_enterstate(asysn_audiounit_InstanceState * My)3863 int asysn_audiounit_uninitializeselect_enterstate(asysn_audiounit_InstanceState * My)
3864 
3865 {
3866   int ret;
3867 
3868   do
3869     {
3870       switch(My->istate) {
3871       case ASYS_AUDIOUNIT_ISTATE_ABSENT:
3872 	ret = ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL;
3873 	break;
3874       case ASYS_AUDIOUNIT_ISTATE_INSTANCE:
3875       case ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING:
3876 	ret = ASYS_AUDIOUNIT_IRESPONSE_REUNINITIALIZE;
3877 	break;
3878       case ASYS_AUDIOUNIT_ISTATE_FLUX:
3879       case ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING:
3880 	OSMemoryBarrier();
3881 	continue;          /* spin to _INSTANCE or _ENGINE */
3882 	break;
3883       case ASYS_AUDIOUNIT_ISTATE_ENGINE:
3884 	if (!OSAtomicCompareAndSwap32Barrier
3885 	    (ASYS_AUDIOUNIT_ISTATE_ENGINE,
3886 	     ASYS_AUDIOUNIT_ISTATE_FLUX,
3887 	     (int32_t *) &(My->istate)))
3888 	  continue;
3889 	ret = ASYS_AUDIOUNIT_IRESPONSE_UNINITIALIZE;
3890 	break;
3891       case ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING:
3892       case ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER:
3893 	OSMemoryBarrier();
3894 	continue;           /* spin to _ENGINE */
3895       default:
3896 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3897 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3898 	  ("\tBad transition - uninitializeselect_entrance\n\n");
3899 	break;
3900       }
3901     } while (0);
3902 
3903   return ret;
3904 }
3905 
3906 
3907 /***************************************************************/
3908 /* State transition diagram on exit from UninitializeSelect:   */
3909 /*                                                             */
3910 /*           ABSENT: Return _ERROR.                            */
3911 /*         INSTANCE: Return _ERROR.                            */
3912 /* INSTANCE_PASSING: Return _ERROR.                            */
3913 /*             FLUX: Set INSTANCE, return _COMPLETE.           */
3914 /*     FLUX_PASSING: Set INSTANCE_PASSING, return _COMPLETE.   */
3915 /*           ENGINE: Return _ERROR.                            */
3916 /*   ENGINE_PASSING: Return _ERROR.                            */
3917 /*    ENGINE_RENDER: Return _ERROR.                            */
3918 /*                                                             */
3919 /***************************************************************/
3920 
asysn_audiounit_uninitializeselect_exitstate(asysn_audiounit_InstanceState * My)3921 int asysn_audiounit_uninitializeselect_exitstate(asysn_audiounit_InstanceState * My)
3922 
3923 {
3924   int ret;
3925 
3926   do
3927     {
3928       switch(My->istate) {
3929       case ASYS_AUDIOUNIT_ISTATE_ABSENT:
3930 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3931 	  ("\tBad transition - uninitializeselect_exit (absent)\n\n");
3932 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3933 	break;
3934       case ASYS_AUDIOUNIT_ISTATE_INSTANCE:
3935       case ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING:
3936 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3937 	  ("\tBad transition - uninitializeselect_exit (instance*)\n\n");
3938 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3939 	break;
3940       case ASYS_AUDIOUNIT_ISTATE_FLUX:
3941 	if (!OSAtomicCompareAndSwap32Barrier
3942 	    (ASYS_AUDIOUNIT_ISTATE_FLUX,
3943 	     ASYS_AUDIOUNIT_ISTATE_INSTANCE,
3944 	     (int32_t *) &(My->istate)))
3945 	  continue;
3946 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
3947 	break;
3948       case ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING:
3949 	if (!OSAtomicCompareAndSwap32Barrier
3950 	    (ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING,
3951 	     ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING,
3952 	     (int32_t *) &(My->istate)))
3953 	  continue;
3954 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
3955 	break;
3956       case ASYS_AUDIOUNIT_ISTATE_ENGINE:
3957       case ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING:
3958       case ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER:
3959 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3960 	  ("\tBad transition - uninitializeselect_exit (engine*)\n\n");
3961 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3962 	break;
3963       default:
3964 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
3965 	  ("\tBad transition - uninitializeselect_exit (default)\n\n");
3966 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
3967 	break;
3968       }
3969     } while (0);
3970 
3971   return ret;
3972 }
3973 
3974 /*****************************************************************/
3975 /* State transition diagram on entrance to CloseSelect:          */
3976 /*                                                               */
3977 /*           ABSENT: Return _MY_IS_NULL.                         */
3978 /*         INSTANCE: Set ABSENT, return _CLOSE.                  */
3979 /* INSTANCE_PASSING: Spin to INSTANCE                            */
3980 /*             FLUX: Spin to INSTANCE or ENGINE                  */
3981 /*     FLUX_PASSING: Spin to INSTANCE or ENGINE                  */
3982 /*           ENGINE: Set ABSENT, return UNINITIALIZE_AND_CLOSE   */
3983 /*   ENGINE_PASSING: Spin to ENGINE                              */
3984 /*    ENGINE_RENDER: Spin to ENGINE                              */
3985 /*****************************************************************/
3986 
asysn_audiounit_closeselect_enterstate(asysn_audiounit_InstanceState * My)3987 int asysn_audiounit_closeselect_enterstate(asysn_audiounit_InstanceState * My)
3988 
3989 {
3990   int ret;
3991 
3992   do
3993     {
3994       switch(My->istate) {
3995       case ASYS_AUDIOUNIT_ISTATE_ABSENT:
3996 	ret = ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL;
3997 	break;
3998       case ASYS_AUDIOUNIT_ISTATE_INSTANCE:
3999 	if (!OSAtomicCompareAndSwap32Barrier
4000 	    (ASYS_AUDIOUNIT_ISTATE_INSTANCE,
4001 	     ASYS_AUDIOUNIT_ISTATE_ABSENT,
4002 	     (int32_t *) &(My->istate)))
4003 	  continue;
4004 	ret = ASYS_AUDIOUNIT_IRESPONSE_CLOSE;
4005 	break;
4006       case ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING:
4007 	OSMemoryBarrier();
4008 	continue;          /* spin to _INSTANCE */
4009 	break;
4010       case ASYS_AUDIOUNIT_ISTATE_FLUX:
4011       case ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING:
4012 	OSMemoryBarrier();
4013 	continue;          /* spin to _INSTANCE or _ENGINE */
4014 	break;
4015       case ASYS_AUDIOUNIT_ISTATE_ENGINE:
4016 	if (!OSAtomicCompareAndSwap32Barrier
4017 	    (ASYS_AUDIOUNIT_ISTATE_ENGINE,
4018 	     ASYS_AUDIOUNIT_ISTATE_ABSENT,
4019 	     (int32_t *) &(My->istate)))
4020 	  continue;
4021 	ret = ASYS_AUDIOUNIT_IRESPONSE_UNINITIALIZE_AND_CLOSE;
4022 	break;
4023       case ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING:
4024       case ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER:
4025 	OSMemoryBarrier();
4026 	continue;          /* spin to _ENGINE */
4027 	break;
4028       default:
4029 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
4030 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4031 	  ("\tBad transition - closeselect_enter\n\n");
4032 	break;
4033       }
4034     } while (0);
4035 
4036   return ret;
4037 }
4038 
4039 /******************************************************************/
4040 /* State transition diagram on entrance to real-time thread:      */
4041 /*                                                                */
4042 /*           ABSENT: Return _MY_IS_NULL (abnormal)                */
4043 /*         INSTANCE: Set INSTANCE_PASSING, return _WIRE           */
4044 /* INSTANCE_PASSING: Set INSTANCE, return _WIRE (abnormal)        */
4045 /*             FLUX: Set FLUX_PASSING, return _WIRE               */
4046 /*     FLUX_PASSING: Set FLUX, return _WIRE (abnormal)            */
4047 /*           ENGINE: Set ENGINE_RENDER, return _RENDER            */
4048 /*   ENGINE_PASSING: Set ENGINE_RENDER, return _RENDER (abnormal) */
4049 /*    ENGINE_RENDER: Return _RENDER (abnormal)                    */
4050 /******************************************************************/
4051 
asysn_audiounit_realtime_enterstate(asysn_audiounit_InstanceState * My)4052 int asysn_audiounit_realtime_enterstate(asysn_audiounit_InstanceState * My)
4053 
4054 {
4055   int ret;
4056 
4057   do
4058     {
4059       switch(My->istate) {
4060       case ASYS_AUDIOUNIT_ISTATE_ABSENT:
4061 	ret = ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL;
4062 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4063 	  ("\tBad transition - realtime_entrance (absent)\n\n");
4064 	break;
4065       case ASYS_AUDIOUNIT_ISTATE_INSTANCE:
4066 	if (!OSAtomicCompareAndSwap32Barrier
4067 	    (ASYS_AUDIOUNIT_ISTATE_INSTANCE,
4068 	     ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING,
4069 	     (int32_t *) &(My->istate)))
4070 	  continue;
4071 	ret = ASYS_AUDIOUNIT_IRESPONSE_WIRE;
4072 	break;
4073       case ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING:
4074 	if (!OSAtomicCompareAndSwap32Barrier
4075 	    (ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING,
4076 	     ASYS_AUDIOUNIT_ISTATE_INSTANCE,
4077 	     (int32_t *) &(My->istate)))
4078 	  continue;
4079 	ret = ASYS_AUDIOUNIT_IRESPONSE_WIRE;
4080 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4081 	  ("\tBad transition - realtime_entrance (instance_passing)\n\n");
4082 	break;
4083       case ASYS_AUDIOUNIT_ISTATE_FLUX:
4084 	if (!OSAtomicCompareAndSwap32Barrier
4085 	    (ASYS_AUDIOUNIT_ISTATE_FLUX,
4086 	     ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING,
4087 	     (int32_t *) &(My->istate)))
4088 	  continue;
4089 	ret = ASYS_AUDIOUNIT_IRESPONSE_WIRE;
4090 	break;
4091       case ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING:
4092 	if (!OSAtomicCompareAndSwap32Barrier
4093 	    (ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING,
4094 	     ASYS_AUDIOUNIT_ISTATE_FLUX,
4095 	     (int32_t *) &(My->istate)))
4096 	  continue;
4097 	ret = ASYS_AUDIOUNIT_IRESPONSE_WIRE;
4098 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4099 	  ("\tBad transition - realtime_entrance (flux_passing)\n\n");
4100 	break;
4101       case ASYS_AUDIOUNIT_ISTATE_ENGINE:
4102 	if (!OSAtomicCompareAndSwap32Barrier
4103 	    (ASYS_AUDIOUNIT_ISTATE_ENGINE,
4104 	     ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING,
4105 	     (int32_t *) &(My->istate)))
4106 	  continue;
4107 	ret = ASYS_AUDIOUNIT_IRESPONSE_RENDER;
4108 	break;
4109       case ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING:
4110 	if (!OSAtomicCompareAndSwap32Barrier
4111 	    (ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING,
4112 	     ASYS_AUDIOUNIT_ISTATE_ENGINE,
4113 	     (int32_t *) &(My->istate)))
4114 	  continue;
4115 	ret = ASYS_AUDIOUNIT_IRESPONSE_RENDER;
4116 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4117 	  ("\tBad transition - realtime_entrance (engine_passing)\n\n");
4118 	break;
4119       case ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER:
4120 	if (!OSAtomicCompareAndSwap32Barrier
4121 	    (ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER,
4122 	     ASYS_AUDIOUNIT_ISTATE_ENGINE,
4123 	     (int32_t *) &(My->istate)))
4124 	  continue;
4125 	ret = ASYS_AUDIOUNIT_IRESPONSE_RENDER;
4126 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4127 	  ("\tBad transition - realtime_entrance (engine_render)\n\n");
4128 	break;
4129       default:
4130 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
4131 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4132 	  ("\tBad transition - realtime_entrance (default)\n\n");
4133 	break;
4134       }
4135     } while (0);
4136 
4137   return ret;
4138 }
4139 
4140 /************************************************************/
4141 /* State transition diagram on exit from real-time thread:  */
4142 /*                                                          */
4143 /*           ABSENT: Return _MY_IS_NULL (abnormal)          */
4144 /*         INSTANCE: Return _COMPLETE (abnormal)            */
4145 /* INSTANCE_PASSING: Set INSTANCE, return _COMPLETE         */
4146 /*             FLUX: Return _COMPLETE (abnormal)            */
4147 /*     FLUX_PASSING: Set FLUX, return _COMPLETE             */
4148 /*           ENGINE: Return _COMPLETE (abnormal)            */
4149 /*   ENGINE_PASSING: Set ENGINE, return _COMPLETE           */
4150 /*    ENGINE_RENDER: Set ENGINE, return _COMPLETE           */
4151 /************************************************************/
4152 
asysn_audiounit_realtime_exitstate(asysn_audiounit_InstanceState * My)4153 int asysn_audiounit_realtime_exitstate(asysn_audiounit_InstanceState * My)
4154 
4155 {
4156   int ret;
4157 
4158   do
4159     {
4160       switch(My->istate) {
4161       case ASYS_AUDIOUNIT_ISTATE_ABSENT:
4162 	ret = ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL;
4163 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4164 	  ("\tBad transition - realtime_exit (absent)\n\n");
4165 	break;
4166       case ASYS_AUDIOUNIT_ISTATE_INSTANCE:
4167 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
4168 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4169 	  ("\tBad transition - realtime_exit (instance)\n\n");
4170 	break;
4171       case ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING:
4172 	if (!OSAtomicCompareAndSwap32Barrier
4173 	    (ASYS_AUDIOUNIT_ISTATE_INSTANCE_PASSING,
4174 	     ASYS_AUDIOUNIT_ISTATE_INSTANCE,
4175 	     (int32_t *) &(My->istate)))
4176 	  continue;
4177 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
4178 	break;
4179       case ASYS_AUDIOUNIT_ISTATE_FLUX:
4180 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
4181 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4182 	  ("\tBad transition - realtime_exit (flux)\n\n");
4183 	break;
4184       case ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING:
4185 	if (!OSAtomicCompareAndSwap32Barrier
4186 	    (ASYS_AUDIOUNIT_ISTATE_FLUX_PASSING,
4187 	     ASYS_AUDIOUNIT_ISTATE_FLUX,
4188 	     (int32_t *) &(My->istate)))
4189 	  continue;
4190 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
4191 	break;
4192       case ASYS_AUDIOUNIT_ISTATE_ENGINE:
4193 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
4194 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4195 	  ("\tBad transition - realtime_exit (engine)\n\n");
4196 	break;
4197       case ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING:
4198 	if (!OSAtomicCompareAndSwap32Barrier
4199 	    (ASYS_AUDIOUNIT_ISTATE_ENGINE_PASSING,
4200 	     ASYS_AUDIOUNIT_ISTATE_ENGINE,
4201 	     (int32_t *) &(My->istate)))
4202 	  continue;
4203 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
4204 	break;
4205       case ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER:
4206 	if (!OSAtomicCompareAndSwap32Barrier
4207 	    (ASYS_AUDIOUNIT_ISTATE_ENGINE_RENDER,
4208 	     ASYS_AUDIOUNIT_ISTATE_ENGINE,
4209 	     (int32_t *) &(My->istate)))
4210 	  continue;
4211 	ret = ASYS_AUDIOUNIT_IRESPONSE_COMPLETE;
4212 	break;
4213       default:
4214 	ret = ASYS_AUDIOUNIT_IRESPONSE_ERROR;
4215 	ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4216 	  ("\tBad transition - realtime_exit (default)\n\n");
4217 	break;
4218       }
4219     } while (0);
4220 
4221   return ret;
4222 }
4223 
4224 /*~~~~~~~~~~~~~~~~~~~~~~~~*/
4225 /*~~~~~~~~~~~~~~~~~~~~~~~~*/
4226 /*  The Selector Calls    */
4227 /*~~~~~~~~~~~~~~~~~~~~~~~~*/
4228 /*~~~~~~~~~~~~~~~~~~~~~~~~*/
4229 
4230 /**************************************/
4231 /*          Selector: Open            */
4232 /*                                    */
4233 /*  params[0]: ComponentInstance ci   */
4234 /*                                    */
4235 /**************************************/
4236 
asysn_audiounit_kComponentOpenSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)4237 ComponentResult asysn_audiounit_kComponentOpenSelect(ComponentParameters * p,
4238 						     asysn_audiounit_InstanceState * My)
4239 {
4240   int socket_flags;
4241   int i, msize;
4242 
4243   msize = sizeof(asysn_audiounit_InstanceState);
4244   if (!(My = (asysn_audiounit_InstanceState *) calloc(1, msize)))
4245     return asysn_audiounit_instance_cleanup(p, My);
4246   asysn_audiounit_memstatus(My, msize, MADV_WILLNEED);
4247 
4248   My->component = (ComponentInstance) (p->params[0]);
4249   sprintf(My->componentname, "c%u", (unsigned int) My->component);
4250   My->argv[0] = My->componentname;
4251 
4252   if (asysn_audiounit_initialize_properties(My) != noErr)
4253     return asysn_audiounit_instance_cleanup(p, My);
4254 
4255   if (ASYS_AUDIOUNIT_EFFECT)
4256     {
4257       msize = (sizeof(UInt32) + sizeof(AudioBuffer)*ASYS_AUDIOUNIT_INPUT_MAXCHANNELS);
4258 
4259       if (!(My->AudioBufferCarrier = calloc(msize, 1)))
4260 	return asysn_audiounit_instance_cleanup(p, My);
4261 
4262       if (!(My->AudioBufferTemplate = calloc(msize, 1)))
4263 	return asysn_audiounit_instance_cleanup(p, My);
4264 
4265       asysn_audiounit_memstatus(My->AudioBufferCarrier, msize, MADV_WILLNEED);
4266       asysn_audiounit_memstatus(My->AudioBufferTemplate, msize, MADV_WILLNEED);
4267 
4268       My->AudioBufferTemplate->mNumberBuffers = ASYS_AUDIOUNIT_INPUT_CHANNELS;
4269 
4270       msize = sizeof(Float32)*ASYS_AUDIOUNIT_FRAMES_PER_SLICE;
4271 
4272       for(i = 0; i < ASYS_AUDIOUNIT_INPUT_MAXCHANNELS; i++)
4273 	{
4274 	  My->AudioBufferTemplate->mBuffers[i].mNumberChannels = 1;
4275 
4276 	  if (!(My->AudioBufferTemplate->mBuffers[i].mData = malloc(msize)))
4277 	    return asysn_audiounit_instance_cleanup(p, My);
4278 
4279 	  asysn_audiounit_memstatus(My->AudioBufferTemplate->mBuffers[i].mData,
4280 				    msize, MADV_WILLNEED);
4281 	}
4282     }
4283 
4284   msize = sizeof(Float32)*ASYS_AUDIOUNIT_FRAMES_PER_SLICE;
4285 
4286   for(i = 0; i < ASYS_AUDIOUNIT_OUTPUT_MAXCHANNELS; i++)
4287     {
4288       if (!(My->mData_Output[i] = (Float32 *) malloc(msize)))
4289 	return asysn_audiounit_instance_cleanup(p, My);
4290       asysn_audiounit_memstatus(My->mData_Output[i], msize, MADV_WILLNEED);
4291     }
4292 
4293   if (ASYS_AUDIOUNIT_HAS_AUCONTROL)
4294     {
4295       /*~~~~~~~~~~~~~~~~~~~~*/
4296       /* set up MIDI socket */
4297       /*--------------------*/
4298 
4299       if (socketpair(AF_UNIX, SOCK_DGRAM, 0, My->mpipepair))
4300 	{
4301 	  ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4302 	    ("\n\tIn OpenSelect: Error during MIDI socketpair() call.\n");
4303 	  return asysn_audiounit_instance_cleanup(p, My);
4304 	}
4305 
4306       if ((socket_flags = fcntl(My->mpipepair[0], F_GETFL, 0)) == -1)
4307 	{
4308 	  ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4309 	    ("\n\tIn OpenSelect: Error during mpipepair[0] F_GETFL fcntl() call.\n");
4310 	  return asysn_audiounit_instance_cleanup(p, My);
4311 	}
4312 
4313       if (fcntl(My->mpipepair[0], F_SETFL, socket_flags | O_NONBLOCK) == -1)
4314 	{
4315 	  ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4316 	    ("\n\tIn OpenSelect: Error during mpipepair[0] F_SETFL fcntl() call.\n");
4317 	  return asysn_audiounit_instance_cleanup(p, My);
4318 	}
4319 
4320       /*~~~~~~~~~~~~~~~~~~~~*/
4321       /* set up SASL socket */
4322       /*--------------------*/
4323 
4324       if (socketpair(AF_UNIX, SOCK_DGRAM, 0, My->spipepair))
4325 	{
4326 	  ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4327 	    ("\n\tIn OpenSelect: Error during SASL socketpair() call.\n");
4328 	  return asysn_audiounit_instance_cleanup(p, My);
4329 	}
4330 
4331       if ((socket_flags = fcntl(My->spipepair[0], F_GETFL, 0)) == -1)
4332 	{
4333 	  ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4334 	    ("\n\tIn OpenSelect: Error during spipepair[0] F_GETFL fcntl() call.\n");
4335 	  return asysn_audiounit_instance_cleanup(p, My);
4336 	}
4337 
4338       if (fcntl(My->spipepair[0], F_SETFL, socket_flags | O_NONBLOCK) == -1)
4339 	{
4340 	  ASYS_AUDIOUNIT_WIRETAP_PUTSTRING
4341 	    ("\n\tIn OpenSelect: Error during spipepair[0] F_SETFL fcntl() call.\n");
4342 	  return asysn_audiounit_instance_cleanup(p, My);
4343 	}
4344 
4345       /*~~~~~~~~~~~~~~~~~~~~~~*/
4346       /* set up argc and argv */
4347       /*----------------------*/
4348 
4349       My->argc = 5;
4350 
4351       My->argv[1] = My->mpipeflag;
4352       My->argv[2] = My->mpipevalue;
4353 
4354       sprintf(My->mpipeflag, "-asys_audiounit_mpipe");
4355       sprintf(My->mpipevalue, "%i", My->mpipepair[0]);
4356 
4357       My->argv[3] = My->spipeflag;
4358       My->argv[4] = My->spipevalue;
4359 
4360       sprintf(My->spipeflag, "-asys_audiounit_spipe");
4361       sprintf(My->spipevalue, "%i", My->spipepair[0]);
4362       }
4363   else
4364     {
4365       My->argc = 1;
4366 
4367       My->argv[1] = My->argv[2] = NULL;
4368       My->mpipepair[0] = My->mpipepair[1] = 0;
4369 
4370       My->argv[3] = My->argv[4] = NULL;
4371       My->spipepair[0] = My->spipepair[1] = 0;
4372     }
4373 
4374   if (asysn_audiounit_initialize_parametersystem(My) != noErr)
4375     return asysn_audiounit_instance_cleanup(p, My);
4376 
4377   OSSpinLockLock(&asysn_audiounit_lock_opencount);
4378 
4379   if (!(asysn_audiounit_opencount++))
4380     asysn_audiounit_globalvars_memstatus(MADV_WILLNEED);
4381 
4382   OSSpinLockUnlock(&asysn_audiounit_lock_opencount);
4383 
4384   My->istate = ASYS_AUDIOUNIT_ISTATE_INSTANCE;
4385 
4386   SetComponentInstanceStorage((ComponentInstance) p->params[0], (Handle) My);
4387 
4388   return noErr;
4389 }
4390 
4391 /**************************************/
4392 /*           Selector: Close          */
4393 /*                                    */
4394 /*  params[0]: ComponentInstance ci   */
4395 /*                                    */
4396 /**************************************/
4397 
asysn_audiounit_kComponentCloseSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)4398 ComponentResult asysn_audiounit_kComponentCloseSelect(ComponentParameters * p,
4399 					    asysn_audiounit_InstanceState * My)
4400 {
4401   ENGINE_PTR_DECLARE_SEMICOLON
4402   asysn_audiounit_proplisten * remove;
4403   asysn_audiounit_rendernotify * notify;
4404   int i, k, msize, ret;
4405 
4406   ret = asysn_audiounit_closeselect_enterstate(My);
4407 
4408   SetComponentInstanceStorage((ComponentInstance) p->params[0], (Handle) NULL);
4409 
4410   switch (ret) {
4411   case ASYS_AUDIOUNIT_IRESPONSE_UNINITIALIZE_AND_CLOSE:
4412     ENGINE_PTR_ASSIGNED_TO  MY_ENGINE_PTR;
4413     ENGINE_MEMSTATUS_SEMICOLON(MADV_FREE)
4414     shut_down(ENGINE_PTR);
4415     MY_ENGINE_PTR_ASSIGNED_TO  NULL;
4416     break;
4417   case ASYS_AUDIOUNIT_IRESPONSE_CLOSE:
4418     break;
4419   case ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL:
4420   case ASYS_AUDIOUNIT_IRESPONSE_ERROR:
4421   default:
4422     return noErr;
4423   }
4424 
4425   if (ASYS_AUDIOUNIT_HAS_AUCONTROL)
4426     {
4427       close(My->mpipepair[0]);
4428       close(My->mpipepair[1]);
4429       close(My->spipepair[0]);
4430       close(My->spipepair[1]);
4431 
4432       if (My->num_saolparams)
4433 	{
4434 	  free(My->parameterlist);
4435 	  for (i = 0; i < My->num_saolparams; i++)
4436 	    {
4437 	      if (My->parameterinfo[i].cfNameString)
4438 		CFRelease(My->parameterinfo[i].cfNameString);
4439 	      if (My->parameterinfo[i].unitName)
4440 		CFRelease(My->parameterinfo[i].unitName);
4441 	    }
4442 	  free(My->parameterinfo);
4443 
4444 	  for (i = 0; i < My->num_saolparams; i++)
4445 	    if (My->pvs_size[i])
4446 	      {
4447 		for (k = 0; k < My->pvs_size[i]; k++)
4448 		  free(My->pvs_cstr[i][k]);
4449 		free(My->pvs_cstr[i]);
4450 	      }
4451 	  free(My->pvs_size);
4452 	  free(My->pvs_cstr);
4453 
4454 	  msize = My->num_saolparams*sizeof(asysn_audiounit_saolparam);
4455 	  asysn_audiounit_memstatus(My->saolparam, msize, MADV_FREE);
4456 	  free(My->saolparam);
4457 	}
4458 
4459       if (My->num_factory)
4460 	{
4461 	  for (i = 0; i < My->num_factory; i++)
4462 	    {
4463 	      if (My->factorypreset_values[i])
4464 		{
4465 		  msize = My->num_saolparams*sizeof(Float32);
4466 		  asysn_audiounit_memstatus(My->factorypreset_values[i],
4467 					    msize, MADV_FREE);
4468 		  free(My->factorypreset_values[i]);
4469 		}
4470 
4471 	      if (My->factorypreset_info[i].presetName)
4472 		CFRelease(My->factorypreset_info[i].presetName);
4473 	    }
4474 
4475 	  msize = My->num_factory*sizeof(Float32 *);
4476 	  asysn_audiounit_memstatus(My->factorypreset_values, msize, MADV_FREE);
4477 	  free(My->factorypreset_values);
4478 
4479 	  free(My->factorypreset_info);
4480 	  CFRelease(My->factorypreset_array);
4481 	}
4482     }
4483 
4484 
4485   OSSpinLockLock(&(My->lock_PresentPreset));
4486 
4487   CFRelease(My->PresentPreset.presetName);
4488 
4489   OSSpinLockUnlock(&(My->lock_PresentPreset));
4490 
4491 
4492   OSSpinLockLock(&(My->lock_proplisteners));
4493 
4494   for (i = 0; i < ASYS_AUDIOUNIT_PROPLISTEN_ARRAYSIZE; i++)
4495     while (My->proplisteners[i] != NULL)
4496       {
4497 	remove = My->proplisteners[i];
4498 	My->proplisteners[i] = My->proplisteners[i]->next;
4499 	msize = sizeof(asysn_audiounit_proplisten);
4500 	asysn_audiounit_memstatus(remove, msize, MADV_FREE);
4501 	free(remove);
4502       }
4503 
4504   OSSpinLockUnlock(&(My->lock_proplisteners));
4505 
4506 
4507   OSSpinLockLock(&(My->lock_rendernotify));
4508 
4509   while (My->rendernotify)
4510     {
4511       notify = My->rendernotify;
4512       My->rendernotify = notify->next;
4513       msize = sizeof(asysn_audiounit_rendernotify);
4514       asysn_audiounit_memstatus(notify, msize, MADV_FREE);
4515       free(notify);
4516     }
4517 
4518   OSSpinLockUnlock(&(My->lock_rendernotify));
4519 
4520 
4521   if (ASYS_AUDIOUNIT_EFFECT)
4522     {
4523       msize = (sizeof(UInt32) + sizeof(AudioBuffer)*ASYS_AUDIOUNIT_INPUT_MAXCHANNELS);
4524       asysn_audiounit_memstatus(My->AudioBufferCarrier, msize, MADV_FREE);
4525       free(My->AudioBufferCarrier);
4526 
4527       msize = sizeof(Float32)*ASYS_AUDIOUNIT_FRAMES_PER_SLICE;
4528       for(i = 0; i < ASYS_AUDIOUNIT_INPUT_MAXCHANNELS; i++)
4529 	{
4530 	  asysn_audiounit_memstatus(My->AudioBufferTemplate->mBuffers[i].mData,
4531 				    msize, MADV_FREE);
4532 	  free(My->AudioBufferTemplate->mBuffers[i].mData);
4533 	}
4534 
4535       msize = (sizeof(UInt32) + sizeof(AudioBuffer)*ASYS_AUDIOUNIT_INPUT_MAXCHANNELS);
4536       asysn_audiounit_memstatus(My->AudioBufferTemplate, msize, MADV_FREE);
4537       free(My->AudioBufferTemplate);
4538     }
4539 
4540   for(i = 0; i < ASYS_AUDIOUNIT_OUTPUT_MAXCHANNELS; i++)
4541     {
4542       msize = sizeof(Float32)*ASYS_AUDIOUNIT_FRAMES_PER_SLICE;
4543       asysn_audiounit_memstatus(My->mData_Output[i], msize, MADV_FREE);
4544       free(My->mData_Output[i]);
4545     }
4546 
4547   msize = sizeof(asysn_audiounit_InstanceState);
4548   asysn_audiounit_memstatus(My, msize, MADV_FREE);
4549   free(My);
4550 
4551   OSSpinLockLock(&asysn_audiounit_lock_opencount);
4552 
4553   if (!(--asysn_audiounit_opencount))
4554     asysn_audiounit_globalvars_memstatus(MADV_FREE);
4555 
4556   if (asysn_audiounit_opencount < 0)   /* should never be true */
4557     asysn_audiounit_opencount = 0;
4558 
4559   OSSpinLockUnlock(&asysn_audiounit_lock_opencount);
4560 
4561   return noErr;
4562 }
4563 
4564 /************************/
4565 /* Selector: Initialize */
4566 /*                      */
4567 /************************/
4568 
asysn_audiounit_kAudioUnitInitializeSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)4569 ComponentResult asysn_audiounit_kAudioUnitInitializeSelect(ComponentParameters * p,
4570   					        asysn_audiounit_InstanceState * My)
4571 {
4572   ENGINE_PTR_DECLARE_SEMICOLON
4573 
4574   switch (asysn_audiounit_initializeselect_enterstate(My)) {
4575     case ASYS_AUDIOUNIT_IRESPONSE_INITIALIZE:
4576       break;
4577     case ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL:
4578     case ASYS_AUDIOUNIT_IRESPONSE_REINITIALIZE:
4579     default:
4580       return noErr;
4581     }
4582 
4583   ENGINE_PTR_ASSIGNED_TO  system_init(My->argc, My->argv,
4584 				      My->OutputStreamFormat.mSampleRate);
4585 
4586   MY_ENGINE_PTR_ASSIGNED_TO  ENGINE_PTR;
4587 
4588   if (ENGINE_PTR_IS_NULL)
4589     return kAudioUnitErr_FailedInitialization;
4590 
4591   ENGINE_MEMSTATUS_SEMICOLON(MADV_WILLNEED)
4592 
4593   effects_init(ENGINE_PTR);
4594   main_initpass(ENGINE_PTR);
4595   asysn_audiounit_ksyncinit(My);
4596 
4597   EV(kcycleidx) = EV(kbase);
4598   EV(acycleidx) = EV(ACYCLE) + 1;   /* +1 denotes zero-time condition */
4599   EV(pass) = IPASS;
4600 
4601   My->acycle = EV(ACYCLE);
4602 
4603   OSSpinLockLock(&(My->lock_CPULoad));
4604 
4605   My->krate = EV(KRATE);
4606 
4607   My->ksync_normalize = (Float32) (My->krate/AudioGetHostClockFrequency());
4608   if (My->CPULoad)
4609     My->ksync_normalize = My->ksync_normalize/My->CPULoad;
4610 
4611   OSSpinLockUnlock(&(My->lock_CPULoad));
4612 
4613   My->acycleidx_kcycleidx = 1;     /* acycleidx = 0, kcycleidx = 1 */
4614 
4615   if (ASYS_AUDIOUNIT_HAS_AUCONTROL)
4616     asysn_audiounit_engine_parameter_update(My);
4617 
4618   asysn_audiounit_initializeselect_exitstate(My);
4619 
4620   return noErr;
4621 }
4622 
4623 /**************************/
4624 /* Selector: Uninitialize */
4625 /*                        */
4626 /**************************/
4627 
asysn_audiounit_kAudioUnitUninitializeSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)4628 ComponentResult asysn_audiounit_kAudioUnitUninitializeSelect(ComponentParameters * p,
4629 						   asysn_audiounit_InstanceState * My)
4630 {
4631   int j;
4632   ENGINE_PTR_DECLARE_SEMICOLON
4633 
4634   switch (asysn_audiounit_uninitializeselect_enterstate(My)) {
4635     case ASYS_AUDIOUNIT_IRESPONSE_UNINITIALIZE:
4636       break;
4637     case ASYS_AUDIOUNIT_IRESPONSE_MY_IS_NULL:
4638     case ASYS_AUDIOUNIT_IRESPONSE_REUNINITIALIZE:
4639     default:
4640       return noErr;
4641     }
4642 
4643   ENGINE_PTR_ASSIGNED_TO  MY_ENGINE_PTR;
4644   ENGINE_MEMSTATUS_SEMICOLON(MADV_FREE)
4645   shut_down(ENGINE_PTR);
4646   MY_ENGINE_PTR_ASSIGNED_TO  NULL;
4647 
4648   My->acycle = ((int)(SAOL_SRATE))/((int)(SAOL_KRATE));
4649 
4650   OSSpinLockLock(&(My->lock_CPULoad));
4651 
4652   My->krate = SAOL_KRATE;
4653 
4654   My->ksync_normalize = (Float32) (My->krate/AudioGetHostClockFrequency());
4655   if (My->CPULoad)
4656     My->ksync_normalize = My->ksync_normalize/My->CPULoad;
4657 
4658   OSSpinLockUnlock(&(My->lock_CPULoad));
4659 
4660   My->acycleidx_kcycleidx = 1;   /* acycleidx = 0, kcycleidx = 1 */
4661 
4662   asysn_audiounit_uninitializeselect_exitstate(My);
4663   asysn_audiounit_engine_emptypipes(My);
4664 
4665   return noErr;
4666 }
4667 
4668 /********************************************/
4669 /*        Selector: GetPropertyInfo         */
4670 /*                                          */
4671 /*  params[0]: Boolean * outWritable;       */
4672 /*  params[1]: UInt32 * outDataSize;        */
4673 /*  params[2]: AudioUnitElement inElement;  */
4674 /*  params[3]: AudioUnitScope inScope;      */
4675 /*  params[4]: AudioUnitPropertyID inID;    */
4676 /*                                          */
4677 /********************************************/
4678 
asysn_audiounit_kAudioUnitGetPropertyInfoSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)4679 ComponentResult asysn_audiounit_kAudioUnitGetPropertyInfoSelect
4680 (ComponentParameters * p, asysn_audiounit_InstanceState * My)
4681 
4682 {
4683   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4684   /* return early for invalid properties */
4685   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4686 
4687   if (!asysn_audiounit_supported_property((AudioUnitPropertyID)(p->params[4]),
4688 			  (AudioUnitScope)(p->params[3])))
4689     return kAudioUnitErr_InvalidProperty;
4690 
4691   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4692   /* provide datasize if requested by a non-null pointer */
4693   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4694 
4695   if (p->params[1])
4696     *((UInt32 *)(p->params[1])) = asysn_audiounit_property_size(p->params[4], My);
4697 
4698   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4699   /* provide writable status if requested by a non-null pointer */
4700   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4701 
4702   if (p->params[0])
4703     {
4704       switch (p->params[4] /* property ID */) {
4705       case kAudioUnitProperty_ParameterList: /* 3 */
4706       case kAudioUnitProperty_ParameterInfo: /* 4 */
4707       case kAudioUnitProperty_FastDispatch:  /* 5 */
4708 	*((Boolean *)(p->params[0])) = 0;
4709 	break;
4710       case kAudioUnitProperty_ElementCount: /* 11, also kAudioUnitProperty_BusCount */
4711 	/* for hosts that require AUs to support side-chaining */
4712 	*((Boolean *)(p->params[0])) = (p->params[3] == kAudioUnitScope_Input);
4713 	break;
4714       case kAudioUnitProperty_SupportedNumChannels: /* 13 */
4715       case kAudioUnitProperty_ParameterValueStrings: /* 16 */
4716       case kAudioUnitProperty_FactoryPresets: /* 24 */
4717       case kAudioUnitProperty_CocoaUI: /* 31 */
4718 	*((Boolean *)(p->params[0])) = 0;
4719 	break;
4720       default:
4721 	*((Boolean *)(p->params[0])) = 1;
4722 	break;
4723       }
4724     }
4725 
4726   return noErr;
4727 }
4728 
4729 /********************************************/
4730 /*         Selector: GetProperty            */
4731 /*                                          */
4732 /*  params[0]: UInt32 * ioDataSize;         */
4733 /*  params[1]: void * outData;              */
4734 /*  params[2]: AudioUnitElement inElement;  */
4735 /*  params[3]: AudioUnitScope inScope;      */
4736 /*  params[4]: AudioUnitPropertyID inID;    */
4737 /*                                          */
4738 /********************************************/
4739 
asysn_audiounit_kAudioUnitGetPropertySelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)4740 ComponentResult asysn_audiounit_kAudioUnitGetPropertySelect(ComponentParameters * p,
4741 					       asysn_audiounit_InstanceState * My)
4742 {
4743   ComponentResult result = noErr;
4744   CFBundleRef au_bundle = NULL;
4745   CFURLRef view_bundle_url = NULL;
4746   UInt32 size;
4747 
4748   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4749   /* return early for invalid properties */
4750   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4751 
4752   if (!asysn_audiounit_supported_property((AudioUnitPropertyID)(p->params[4]),
4753 			  (AudioUnitScope)(p->params[3])))
4754     return kAudioUnitErr_InvalidProperty;
4755 
4756   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4757   /* check size of property storage */
4758   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
4759 
4760   if (*((UInt32 *)(p->params[0])) !=
4761       (size = asysn_audiounit_property_size(p->params[4], My)))
4762     if (*((UInt32 *)(p->params[0])) > size)
4763       *((UInt32 *)(p->params[0])) = size;
4764     else
4765       return kAudioUnitErr_InvalidPropertyValue;
4766 
4767   /*~~~~~~~~~~~~~~~~~~~~~~~*/
4768   /* assign property value */
4769   /*~~~~~~~~~~~~~~~~~~~~~~~*/
4770 
4771   switch (p->params[4] /* property ID */) {
4772   case kAudioUnitProperty_ClassInfo: /* 0 */
4773     *((CFPropertyListRef *)((void *)(p->params[1]))) =
4774       asysn_audiounit_classinfo_create(My);
4775     break;
4776   case kAudioUnitProperty_MakeConnection: /* 1 */
4777     if ((p->params[2] >= ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
4778 	(p->params[2] < 0))
4779       {
4780 	result = kAudioUnitErr_InvalidProperty;
4781 	break;
4782       }
4783     OSSpinLockLock(&(My->lock_sampledelivery));
4784     ((AudioUnitConnection *)((void *)(p->params[1])))->sourceAudioUnit
4785       = My->MakeConnection[p->params[2]].sourceAudioUnit;
4786     ((AudioUnitConnection *)((void *)(p->params[1])))->sourceOutputNumber
4787       = My->MakeConnection[p->params[2]].sourceOutputNumber;
4788     ((AudioUnitConnection *)((void *)(p->params[1])))->destInputNumber
4789       = My->MakeConnection[p->params[2]].destInputNumber;
4790     OSSpinLockUnlock(&(My->lock_sampledelivery));
4791     break;
4792   case kAudioUnitProperty_SampleRate: /* 2 */
4793     switch (p->params[3] /* inScope */ ) {
4794     case kAudioUnitScope_Input:
4795     if (!(ASYS_AUDIOUNIT_EFFECT) ||
4796 	(p->params[2] >= ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
4797 	(p->params[2] < 0))
4798       {
4799 	result = kAudioUnitErr_InvalidProperty;
4800 	break;
4801       }
4802     *((Float64 *)((void *)(p->params[1]))) =
4803       My->InputStreamFormat[p->params[2]].mSampleRate;
4804     break;
4805     case kAudioUnitScope_Global:
4806     case kAudioUnitScope_Output:
4807       *((Float64 *)((void *)(p->params[1]))) = My->OutputStreamFormat.mSampleRate;
4808       break;
4809     default:
4810       result = kAudioUnitErr_InvalidProperty;
4811       break;
4812     }
4813     break;
4814   case kAudioUnitProperty_ParameterList: /* 3 */
4815     memcpy(((AudioUnitParameterID *)((void *)(p->params[1]))), My->parameterlist,
4816 	   sizeof(AudioUnitParameterID)*My->num_saolparams);
4817     break;
4818   case kAudioUnitProperty_ParameterInfo: /* 4 */
4819     if (p->params[2] < My->num_saolparams)  /* p->param[2] requests ParameterID. */
4820       {
4821 	if (My->parameterinfo[p->params[2]].cfNameString)
4822 	  CFRetain(My->parameterinfo[p->params[2]].cfNameString);
4823 	if (My->parameterinfo[p->params[2]].unitName)
4824 	  CFRetain(My->parameterinfo[p->params[2]].unitName);
4825 	memcpy(((AudioUnitParameterInfo *)((void *)(p->params[1]))),
4826 	       &(My->parameterinfo[p->params[2]]), sizeof(AudioUnitParameterInfo));
4827       }
4828     else
4829       result = kAudioUnitErr_InvalidProperty;
4830     break;
4831   case kAudioUnitProperty_FastDispatch:  /* 5 */
4832     switch (p->params[2] /* inElement */ )  {
4833     case kAudioUnitRenderSelect:
4834       *((AudioUnitRenderProc *)(p->params[1])) = asysn_audiounit_MyRenderer;
4835       break;
4836     case kMusicDeviceMIDIEventSelect:
4837       if (ASYS_AUDIOUNIT_MIDISUPPORT)
4838 	*((MusicDeviceMIDIEventProc *)(p->params[1])) = asysn_audiounit_MyMIDIEventProc;
4839       else
4840 	result = kAudioUnitErr_InvalidProperty;
4841       break;
4842     case kAudioUnitGetParameterSelect:
4843       *((AudioUnitGetParameterProc *)(p->params[1])) =
4844 	asysn_audiounit_MyGetParameterProc;
4845       break;
4846     case kAudioUnitSetParameterSelect:
4847       *((AudioUnitSetParameterProc *)(p->params[1])) =
4848 	asysn_audiounit_MySetParameterProc;
4849       break;
4850     default:
4851       result = kAudioUnitErr_InvalidProperty;
4852       break;
4853     }
4854     break;
4855   case kAudioUnitProperty_CPULoad: /* 6 */
4856     *((Float32 *)((void *)(p->params[1]))) = My->CPULoad;
4857     break;
4858   case kAudioUnitProperty_StreamFormat: /* 8 */
4859     switch (p->params[3] /* inScope */ ) {
4860     case kAudioUnitScope_Input:
4861     if (!(ASYS_AUDIOUNIT_EFFECT) ||
4862 	(p->params[2] >= ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
4863 	(p->params[2] < 0))
4864       {
4865 	result = kAudioUnitErr_InvalidProperty;
4866 	break;
4867       }
4868     ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mChannelsPerFrame
4869       = My->InputStreamFormat[p->params[2]].mChannelsPerFrame;
4870     ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mSampleRate
4871       = My->InputStreamFormat[p->params[2]].mSampleRate;
4872     ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mFormatID
4873       = My->InputStreamFormat[p->params[2]].mFormatID;
4874     ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mFormatFlags
4875       = My->InputStreamFormat[p->params[2]].mFormatFlags;
4876     ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mBytesPerPacket
4877       = My->InputStreamFormat[p->params[2]].mBytesPerPacket;
4878     ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mBytesPerFrame
4879       = My->InputStreamFormat[p->params[2]].mBytesPerFrame;
4880     ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mFramesPerPacket
4881       = My->InputStreamFormat[p->params[2]].mFramesPerPacket;
4882     ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mBitsPerChannel
4883       = My->InputStreamFormat[p->params[2]].mBitsPerChannel;
4884     ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mReserved
4885       = My->InputStreamFormat[p->params[2]].mReserved;
4886       break;
4887     case kAudioUnitScope_Global:
4888     case kAudioUnitScope_Output:
4889       ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mChannelsPerFrame
4890 	= My->OutputStreamFormat.mChannelsPerFrame;
4891       ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mSampleRate
4892 	= My->OutputStreamFormat.mSampleRate;
4893       ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mFormatID
4894 	= My->OutputStreamFormat.mFormatID;
4895       ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mFormatFlags
4896 	= My->OutputStreamFormat.mFormatFlags;
4897       ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mBytesPerPacket
4898 	= My->OutputStreamFormat.mBytesPerPacket;
4899       ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mBytesPerFrame
4900 	= My->OutputStreamFormat.mBytesPerFrame;
4901       ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mFramesPerPacket
4902 	= My->OutputStreamFormat.mFramesPerPacket;
4903       ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mBitsPerChannel
4904 	= My->OutputStreamFormat.mBitsPerChannel;
4905       ((AudioStreamBasicDescription *)((void *)(p->params[1])))->mReserved
4906 	= My->OutputStreamFormat.mReserved;
4907       break;
4908     default:
4909       result = kAudioUnitErr_InvalidProperty;
4910       break;
4911     }
4912     break;
4913   case kAudioUnitProperty_SRCAlgorithm: /* 9 */
4914     *((OSType *)((void *)(p->params[1]))) = My->SRCAlgorithm;
4915     break;
4916   case kAudioUnitProperty_ElementCount: /* 11, also kAudioUnitProperty_BusCount */
4917     switch (p->params[3] /* inScope */ ) {
4918     case kAudioUnitScope_Input:
4919       *((UInt32 *)((void *)(p->params[1]))) = My->InputElementCount;
4920       break;
4921     case kAudioUnitScope_Global:
4922     case kAudioUnitScope_Output:
4923       *((UInt32 *)((void *)(p->params[1]))) = My->OutputElementCount;
4924       break;
4925     case kAudioUnitScope_Part:
4926     case kAudioUnitScope_Group:
4927       *((UInt32 *)((void *)(p->params[1]))) = 0;
4928       break;
4929     default:
4930       result = kAudioUnitErr_InvalidProperty;
4931       break;
4932     }
4933     break;
4934   case kAudioUnitProperty_Latency: /* 12 */
4935     *((Float64 *)((void *)(p->params[1]))) = My->Latency;
4936     break;
4937   case kAudioUnitProperty_SupportedNumChannels: /* 13 */
4938     memcpy(((AudioUnitParameterID *)((void *)(p->params[1]))), My->SupportedNumChannels,
4939 	   ASYS_AUDIOUNIT_SUPPORTED_FORMATS*sizeof(AUChannelInfo));
4940     break;
4941   case kAudioUnitProperty_MaximumFramesPerSlice: /* 14 */
4942     *((UInt32 *)((void *)(p->params[1]))) = My->MaximumFramesPerSlice;
4943     break;
4944   case kAudioUnitProperty_ParameterValueStrings: /* 16 */
4945     if ((*((CFMutableArrayRef *)((void *)(p->params[1]))) =
4946 	 asysn_audiounit_parametervaluestrings_create(My, p->params[2])) == NULL)
4947       result = kAudioUnitErr_InvalidProperty;
4948     break;
4949   case kAudioUnitProperty_TailTime: /* 20 */
4950     *((Float64 *)((void *)(p->params[1]))) = My->TailTime;
4951     break;
4952   case kAudioUnitProperty_BypassEffect: /* 21 */
4953     *((UInt32 *)((void *)(p->params[1]))) = My->BypassEffect;
4954     break;
4955   case kAudioUnitProperty_LastRenderError: /* 22 */
4956     *((OSStatus *)((void *)(p->params[1]))) = My->LastRenderError;
4957     My->LastRenderError = noErr;
4958     break;
4959   case kAudioUnitProperty_SetRenderCallback:  /* 23 */
4960     if ((p->params[2] >= ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
4961 	(p->params[2] < 0))
4962       {
4963 	result = kAudioUnitErr_InvalidProperty;
4964 	break;
4965       }
4966     OSSpinLockLock(&(My->lock_sampledelivery));
4967     ((AURenderCallbackStruct *)((void *)(p->params[1])))->inputProc
4968       = My->SetRenderCallback[p->params[2]].inputProc;
4969     ((AURenderCallbackStruct *)((void *)(p->params[1])))->inputProcRefCon
4970       = My->SetRenderCallback[p->params[2]].inputProcRefCon;
4971     OSSpinLockUnlock(&(My->lock_sampledelivery));
4972     break;
4973   case kAudioUnitProperty_FactoryPresets: /* 24 */
4974     if (My->num_factory)
4975       {
4976 	CFRetain(My->factorypreset_array);
4977 	*((CFPropertyListRef *)((void *)(p->params[1]))) = My->factorypreset_array;
4978       }
4979     else
4980       result = kAudioUnitErr_InvalidProperty;
4981     break;
4982   case kAudioUnitProperty_RenderQuality: /* 26 */
4983     *((UInt32 *)((void *)(p->params[1]))) = My->RenderQuality;
4984     break;
4985   case kAudioUnitProperty_InPlaceProcessing: /* 29 */
4986     *((UInt32 *)((void *)(p->params[1]))) = My->InPlaceProcessing;
4987     break;
4988   case kAudioUnitProperty_CocoaUI: /* 31 */
4989 #if defined(ASYS_AUDIOUNIT_VIEW_BUNDLECF)
4990 
4991     if ((au_bundle = CFBundleGetBundleWithIdentifier(ASYS_AUDIOUNIT_AU_BUNDLECF)))
4992       CFRetain(au_bundle);
4993     else
4994       {
4995 	result = kAudioUnitErr_InvalidProperty;
4996 	break;
4997       }
4998 
4999     view_bundle_url = CFBundleCopyResourceURL(au_bundle,
5000 					      ASYS_AUDIOUNIT_VIEW_BUNDLECF,
5001 					      CFSTR("bundle"), NULL);
5002     CFRelease(au_bundle);
5003 
5004     if (!view_bundle_url)
5005       {
5006 	result = kAudioUnitErr_InvalidProperty;
5007 	break;
5008       }
5009 
5010     ((AudioUnitCocoaViewInfo *)(p->params[1]))->mCocoaAUViewBundleLocation =
5011       view_bundle_url;
5012 
5013     ((AudioUnitCocoaViewInfo *)(p->params[1]))->mCocoaAUViewClass[0] =
5014       CFStringCreateCopy(NULL, ASYS_AUDIOUNIT_VIEW_BASECLASSCF);
5015 #else
5016     result = kAudioUnitErr_InvalidProperty;
5017 #endif
5018     break;
5019   case kAudioUnitProperty_PresentPreset: /* 36 */
5020     OSSpinLockLock(&(My->lock_PresentPreset));
5021     ((AUPreset *)(p->params[1]))->presetNumber = My->PresentPreset.presetNumber;
5022     ((AUPreset *)(p->params[1]))->presetName = My->PresentPreset.presetName;
5023     CFRetain(My->PresentPreset.presetName);
5024     OSSpinLockUnlock(&(My->lock_PresentPreset));
5025     break;
5026   case kAudioUnitProperty_OfflineRender: /* 37 */
5027     *((UInt32 *)((void *)(p->params[1]))) = My->OfflineRender;
5028     break;
5029   case kAudioUnitProperty_PresentationLatency: /* 40 */
5030     *((Float64 *)((void *)(p->params[1]))) = My->PresentationLatency;
5031     break;
5032   case kMusicDeviceProperty_InstrumentCount: /* 1000 */
5033     if (ASYS_AUDIOUNIT_MUSICDEVICE)
5034       *((UInt32 *)((void *)(p->params[1]))) = My->InstrumentCount;
5035     else
5036       result = kAudioUnitErr_InvalidProperty;
5037     break;
5038   case kMusicDeviceProperty_StreamFromDisk: /* 1011 */
5039     *((UInt32 *)((void *)(p->params[1]))) = My->StreamFromDisk;
5040     break;
5041   default:  /* should never happen */
5042     result = kAudioUnitErr_InvalidProperty;
5043     break;
5044   }
5045 
5046   return result;
5047 }
5048 
5049 /********************************************/
5050 /*         Selector: SetProperty            */
5051 /*                                          */
5052 /*  params[0]: UInt32 inDataSize;           */
5053 /*  params[1]: const void * inData;         */
5054 /*  params[2]: AudioUnitElement inElement;  */
5055 /*  params[3]: AudioUnitScope inScope;      */
5056 /*  params[4]: AudioUnitPropertyID inID;    */
5057 /*                                          */
5058 /********************************************/
5059 
asysn_audiounit_kAudioUnitSetPropertySelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5060 ComponentResult asysn_audiounit_kAudioUnitSetPropertySelect(ComponentParameters * p,
5061 					       asysn_audiounit_InstanceState * My)
5062 {
5063   ComponentResult result = noErr;
5064   CFStringRef key;
5065 
5066   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5067   /* return early for invalid properties */
5068   /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5069 
5070   if (!asysn_audiounit_supported_property((AudioUnitPropertyID)(p->params[4]),
5071 			  (AudioUnitScope)(p->params[3])))
5072     return kAudioUnitErr_InvalidProperty;
5073 
5074   switch (p->params[4] /* property ID */) {
5075   case kAudioUnitProperty_ClassInfo: /* 0 */
5076     asysn_audiounit_classinfo_read(
5077                         My, *((CFMutableDictionaryRef *)((void *)(p->params[1]))));
5078     asysn_audiounit_proplisteners_update(My, kAudioUnitProperty_PresentPreset,
5079 					 kAudioUnitScope_Global, (AudioUnitElement) 0);
5080     asysn_audiounit_proplisteners_update(My, kAudioUnitProperty_RenderQuality,
5081 					 kAudioUnitScope_Global, (AudioUnitElement) 0);
5082     asysn_audiounit_proplisteners_update(My, kAudioUnitProperty_CPULoad,
5083 					 kAudioUnitScope_Global, (AudioUnitElement) 0);
5084     break;
5085   case kAudioUnitProperty_MakeConnection: /* 1 */
5086     if ((p->params[2] >= ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
5087 	(p->params[2] < 0))
5088       {
5089 	result = kAudioUnitErr_InvalidProperty;
5090 	break;
5091       }
5092     OSSpinLockLock(&(My->lock_sampledelivery));
5093     My->MakeConnection[p->params[2]].sourceAudioUnit =
5094       ((AudioUnitConnection *)((void *)(p->params[1])))->sourceAudioUnit;
5095     My->MakeConnection[p->params[2]].sourceOutputNumber =
5096       ((AudioUnitConnection *)((void *)(p->params[1])))->sourceOutputNumber;
5097     My->MakeConnection[p->params[2]].destInputNumber =
5098       ((AudioUnitConnection *)((void *)(p->params[1])))->destInputNumber;
5099     OSSpinLockUnlock(&(My->lock_sampledelivery));
5100     break;
5101   case kAudioUnitProperty_SampleRate: /* 2 */
5102     switch (p->params[3] /* inScope */ ) {
5103     case kAudioUnitScope_Input:
5104       if (!(ASYS_AUDIOUNIT_EFFECT) ||
5105 	  (p->params[2] >= ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
5106 	  (p->params[2] < 0))
5107 	{
5108 	  result = kAudioUnitErr_InvalidProperty;
5109 	  break;
5110 	}
5111 	My->InputStreamFormat[p->params[2]].mSampleRate =
5112 	  *((Float64 *)((void *)(p->params[1])));
5113       break;
5114     case kAudioUnitScope_Output:
5115       My->OutputStreamFormat.mSampleRate = *((Float64 *)((void *)(p->params[1])));
5116       break;
5117     case kAudioUnitScope_Global:
5118       if ((ASYS_AUDIOUNIT_EFFECT) &&
5119 	  (p->params[2] < ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
5120 	  (p->params[2] >= 0))
5121 	My->InputStreamFormat[p->params[2]].mSampleRate =
5122 	  *((Float64 *)((void *)(p->params[1])));
5123       My->OutputStreamFormat.mSampleRate = *((Float64 *)((void *)(p->params[1])));
5124       break;
5125     default:
5126       result = kAudioUnitErr_InvalidProperty;
5127       break;
5128     }
5129     break;
5130   case kAudioUnitProperty_ParameterList: /* 3 */
5131     result = kAudioUnitErr_InvalidProperty;
5132     break;    /* hosts not permitted to change Parameter List */
5133   case kAudioUnitProperty_ParameterInfo: /* 4 */
5134     result = kAudioUnitErr_InvalidProperty;
5135     break;    /* hosts not permitted to change Parameter Info */
5136   case kAudioUnitProperty_FastDispatch:  /* 5 */
5137     result = kAudioUnitErr_InvalidProperty;
5138     break;    /* hosts not permitted to set the dispatch routines */
5139   case kAudioUnitProperty_CPULoad: /* 6 */
5140 
5141     OSSpinLockLock(&(My->lock_CPULoad));
5142 
5143     My->CPULoad = *((Float32 *)((void *)(p->params[1])));
5144     My->ksync_normalize = (Float32) (My->krate/AudioGetHostClockFrequency());
5145     if (My->CPULoad)
5146       My->ksync_normalize = My->ksync_normalize/My->CPULoad;
5147 
5148     OSSpinLockUnlock(&(My->lock_CPULoad));
5149 
5150     asysn_audiounit_proplisteners_update(My, kAudioUnitProperty_CPULoad,
5151 					 kAudioUnitScope_Global, (AudioUnitElement) 0);
5152     break;
5153   case kAudioUnitProperty_StreamFormat: /* 8 */
5154 
5155     /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5156     /* reject non-native endian-ness */
5157     /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5158 
5159     if (ASYS_AUDIOUNIT_FLOAT32_BIGENDIAN !=
5160 	(((((AudioStreamBasicDescription *)((void *)(p->params[1])))->mFormatFlags)
5161 	  & kAudioFormatFlagIsBigEndian) != 0))
5162       {
5163 	result = kAudioUnitErr_InvalidPropertyValue;
5164 	break;
5165       }
5166 
5167     switch (p->params[3] /* inScope */ ) {
5168     case kAudioUnitScope_Input:
5169 
5170       if (!(ASYS_AUDIOUNIT_EFFECT) ||
5171 	  (p->params[2] >= ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
5172 	  (p->params[2] < 0))
5173 	{
5174 	  result = kAudioUnitErr_InvalidProperty;
5175 	  break;
5176 	}
5177 
5178       /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5179       /* if the AU uses an input, accept if it doesn't exceed channel limit */
5180       /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5181 
5182       if (((AudioStreamBasicDescription *)
5183 	   ((void *)(p->params[1])))->mChannelsPerFrame &&
5184 	  (((AudioStreamBasicDescription *)
5185 	    ((void *)(p->params[1])))->mChannelsPerFrame
5186 	   <= ASYS_AUDIOUNIT_INPUT_MAXCHANNELS))
5187 	{
5188 	  if (p->params[2] == 0)
5189 	    My->AudioBufferTemplate->mNumberBuffers =
5190 	      ((AudioStreamBasicDescription *)
5191 	       ((void *)(p->params[1])))->mChannelsPerFrame;
5192 
5193 	  My->InputStreamFormat[p->params[2]].mChannelsPerFrame =
5194 	    ((AudioStreamBasicDescription *)
5195 	     ((void *)(p->params[1])))->mChannelsPerFrame;
5196 	  My->InputStreamFormat[p->params[2]].mSampleRate =
5197 	    ((AudioStreamBasicDescription *)
5198 	     ((void *)(p->params[1])))->mSampleRate;
5199 	  My->InputStreamFormat[p->params[2]].mFormatID =
5200 	    ((AudioStreamBasicDescription *)
5201 	     ((void *)(p->params[1])))->mFormatID;
5202 	  My->InputStreamFormat[p->params[2]].mFormatFlags =
5203 	    ((AudioStreamBasicDescription *)
5204 	     ((void *)(p->params[1])))->mFormatFlags;
5205 	  My->InputStreamFormat[p->params[2]].mBytesPerPacket =
5206 	    ((AudioStreamBasicDescription *)
5207 	     ((void *)(p->params[1])))->mBytesPerPacket;
5208 	  My->InputStreamFormat[p->params[2]].mBytesPerFrame =
5209 	    ((AudioStreamBasicDescription *)
5210 	     ((void *)(p->params[1])))->mBytesPerFrame;
5211 	  My->InputStreamFormat[p->params[2]].mFramesPerPacket =
5212 	    ((AudioStreamBasicDescription *)
5213 	     ((void *)(p->params[1])))->mFramesPerPacket;
5214 	  My->InputStreamFormat[p->params[2]].mBitsPerChannel =
5215 	    ((AudioStreamBasicDescription *)
5216 	     ((void *)(p->params[1])))->mBitsPerChannel;
5217 	  My->InputStreamFormat[p->params[2]].mReserved =
5218 	    ((AudioStreamBasicDescription *)
5219 	     ((void *)(p->params[1])))->mReserved;
5220 	}
5221       else
5222 	result = kAudioUnitErr_InvalidProperty;
5223       break;
5224     case kAudioUnitScope_Output:
5225 
5226       /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5227       /* if number of output channels meet our limits, accept */
5228       /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5229 
5230       if (((AudioStreamBasicDescription *)((void *)(p->params[1])))->mChannelsPerFrame
5231 	  &&
5232 	  (((AudioStreamBasicDescription *)((void *)(p->params[1])))->mChannelsPerFrame
5233 	   <= ASYS_AUDIOUNIT_OUTPUT_MAXCHANNELS))
5234 	{
5235 	  My->OutputStreamFormat.mChannelsPerFrame =
5236 	    ((AudioStreamBasicDescription *)
5237 	     ((void *)(p->params[1])))->mChannelsPerFrame;
5238 	  My->OutputStreamFormat.mSampleRate =
5239 	    ((AudioStreamBasicDescription *)
5240 	     ((void *)(p->params[1])))->mSampleRate;
5241 	  My->OutputStreamFormat.mFormatID =
5242 	    ((AudioStreamBasicDescription *)
5243 	     ((void *)(p->params[1])))->mFormatID;
5244 	  My->OutputStreamFormat.mFormatFlags =
5245 	    ((AudioStreamBasicDescription *)
5246 	     ((void *)(p->params[1])))->mFormatFlags;
5247 	  My->OutputStreamFormat.mBytesPerPacket =
5248 	    ((AudioStreamBasicDescription *)
5249 	     ((void *)(p->params[1])))->mBytesPerPacket;
5250 	  My->OutputStreamFormat.mBytesPerFrame =
5251 	    ((AudioStreamBasicDescription *)
5252 	     ((void *)(p->params[1])))->mBytesPerFrame;
5253 	  My->OutputStreamFormat.mFramesPerPacket =
5254 	    ((AudioStreamBasicDescription *)
5255 	     ((void *)(p->params[1])))->mFramesPerPacket;
5256 	  My->OutputStreamFormat.mBitsPerChannel =
5257 	    ((AudioStreamBasicDescription *)
5258 	     ((void *)(p->params[1])))->mBitsPerChannel;
5259 	  My->OutputStreamFormat.mReserved =
5260 	    ((AudioStreamBasicDescription *)
5261 	     ((void *)(p->params[1])))->mReserved;
5262 	}
5263       else
5264 	result = kAudioUnitErr_InvalidPropertyValue;
5265       break;
5266     case kAudioUnitScope_Global:
5267 
5268       /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5269       /* if number of output channels meet our limits, accept */
5270       /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5271 
5272       if (((AudioStreamBasicDescription *)((void *)(p->params[1])))->mChannelsPerFrame
5273 	  &&
5274 	  (((AudioStreamBasicDescription *)((void *)(p->params[1])))->mChannelsPerFrame
5275 	   <= ASYS_AUDIOUNIT_OUTPUT_MAXCHANNELS))
5276 	{
5277 	  My->OutputStreamFormat.mChannelsPerFrame =
5278 	    ((AudioStreamBasicDescription *)
5279 	     ((void *)(p->params[1])))->mChannelsPerFrame;
5280 	  My->OutputStreamFormat.mSampleRate =
5281 	    ((AudioStreamBasicDescription *)
5282 	     ((void *)(p->params[1])))->mSampleRate;
5283 	  My->OutputStreamFormat.mFormatID =
5284 	    ((AudioStreamBasicDescription *)
5285 	     ((void *)(p->params[1])))->mFormatID;
5286 	  My->OutputStreamFormat.mFormatFlags =
5287 	    ((AudioStreamBasicDescription *)
5288 	     ((void *)(p->params[1])))->mFormatFlags;
5289 	  My->OutputStreamFormat.mBytesPerPacket =
5290 	    ((AudioStreamBasicDescription *)
5291 	     ((void *)(p->params[1])))->mBytesPerPacket;
5292 	  My->OutputStreamFormat.mBytesPerFrame =
5293 	    ((AudioStreamBasicDescription *)
5294 	     ((void *)(p->params[1])))->mBytesPerFrame;
5295 	  My->OutputStreamFormat.mFramesPerPacket =
5296 	    ((AudioStreamBasicDescription *)
5297 	     ((void *)(p->params[1])))->mFramesPerPacket;
5298 	  My->OutputStreamFormat.mBitsPerChannel =
5299 	    ((AudioStreamBasicDescription *)
5300 	     ((void *)(p->params[1])))->mBitsPerChannel;
5301 	  My->OutputStreamFormat.mReserved =
5302 	    ((AudioStreamBasicDescription *)
5303 	     ((void *)(p->params[1])))->mReserved;
5304 	}
5305       else
5306 	{
5307 	  result = kAudioUnitErr_InvalidPropertyValue;
5308 	  break;
5309 	}
5310 
5311       if ((ASYS_AUDIOUNIT_EFFECT) &&
5312 	  (p->params[2] < ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
5313 	  (p->params[2] >= 0))
5314 	{
5315 
5316 	  /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5317 	  /* if the AU uses an input, accept if it doesn't exceed channel limit */
5318 	  /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5319 
5320 	  if (((AudioStreamBasicDescription *)
5321 	       ((void *)(p->params[1])))->mChannelsPerFrame &&
5322 	      (((AudioStreamBasicDescription *)
5323 		((void *)(p->params[1])))->mChannelsPerFrame
5324 	       <= ASYS_AUDIOUNIT_INPUT_MAXCHANNELS))
5325 	    {
5326 	      if (p->params[2] == 0)
5327 		My->AudioBufferTemplate->mNumberBuffers =
5328 		  ((AudioStreamBasicDescription *)
5329 		   ((void *)(p->params[1])))->mChannelsPerFrame;
5330 
5331 	      My->InputStreamFormat[p->params[2]].mChannelsPerFrame =
5332 		((AudioStreamBasicDescription *)
5333 		 ((void *)(p->params[1])))->mChannelsPerFrame;
5334 	      My->InputStreamFormat[p->params[2]].mSampleRate =
5335 		((AudioStreamBasicDescription *)
5336 		 ((void *)(p->params[1])))->mSampleRate;
5337 	      My->InputStreamFormat[p->params[2]].mFormatID =
5338 		((AudioStreamBasicDescription *)
5339 		 ((void *)(p->params[1])))->mFormatID;
5340 	      My->InputStreamFormat[p->params[2]].mFormatFlags =
5341 		((AudioStreamBasicDescription *)
5342 		 ((void *)(p->params[1])))->mFormatFlags;
5343 	      My->InputStreamFormat[p->params[2]].mBytesPerPacket =
5344 		((AudioStreamBasicDescription *)
5345 		 ((void *)(p->params[1])))->mBytesPerPacket;
5346 	      My->InputStreamFormat[p->params[2]].mBytesPerFrame =
5347 		((AudioStreamBasicDescription *)
5348 		 ((void *)(p->params[1])))->mBytesPerFrame;
5349 	      My->InputStreamFormat[p->params[2]].mFramesPerPacket =
5350 		((AudioStreamBasicDescription *)
5351 		 ((void *)(p->params[1])))->mFramesPerPacket;
5352 	      My->InputStreamFormat[p->params[2]].mBitsPerChannel =
5353 		((AudioStreamBasicDescription *)
5354 		 ((void *)(p->params[1])))->mBitsPerChannel;
5355 	      My->InputStreamFormat[p->params[2]].mReserved =
5356 		((AudioStreamBasicDescription *)
5357 		 ((void *)(p->params[1])))->mReserved;
5358 	    }
5359 	  else
5360 	    result = kAudioUnitErr_InvalidProperty;
5361 	}
5362       break;
5363     default:
5364       result = kAudioUnitErr_InvalidProperty;
5365       break;
5366     }
5367     break;
5368   case kAudioUnitProperty_SRCAlgorithm: /* 9 */
5369     My->SRCAlgorithm = *((OSType *)((void *)(p->params[1])));
5370     break;
5371   case kAudioUnitProperty_ElementCount: /* 11, also kAudioUnitProperty_BusCount */
5372     switch (p->params[3] /* inScope */ ) {
5373     case kAudioUnitScope_Input:
5374       if (*((UInt32 *)((void *)(p->params[1]))) <= ASYS_AUDIOUNIT_ELEMENT_INPUTMAX)
5375 	My->InputElementCount = *((UInt32 *)((void *)(p->params[1])));
5376       else
5377 	result = kAudioUnitErr_InvalidPropertyValue;
5378       break;
5379     case kAudioUnitScope_Output:
5380       if (*((UInt32 *)((void *)(p->params[1]))) <= ASYS_AUDIOUNIT_ELEMENT_OUTPUTMAX)
5381 	My->OutputElementCount = *((UInt32 *)((void *)(p->params[1])));
5382       else
5383 	result = kAudioUnitErr_InvalidPropertyValue;
5384       break;
5385     case kAudioUnitScope_Global:
5386       if (*((UInt32 *)((void *)(p->params[1]))) <= ASYS_AUDIOUNIT_ELEMENT_OUTPUTMAX)
5387 	My->OutputElementCount = *((UInt32 *)((void *)(p->params[1])));
5388       else
5389 	result = kAudioUnitErr_InvalidPropertyValue;
5390       if (ASYS_AUDIOUNIT_EFFECT)
5391 	{
5392 	  if (*((UInt32 *)((void *)(p->params[1]))) <= ASYS_AUDIOUNIT_ELEMENT_INPUTMAX)
5393 	    My->InputElementCount = *((UInt32 *)((void *)(p->params[1])));
5394 	  else
5395 	    result = kAudioUnitErr_InvalidPropertyValue;
5396 	}
5397       break;
5398     case kAudioUnitScope_Part:
5399     case kAudioUnitScope_Group:
5400       break;
5401     default:
5402       result = kAudioUnitErr_InvalidProperty;
5403       break;
5404     }
5405     break;
5406   case kAudioUnitProperty_Latency: /* 12 */
5407     My->Latency = *((Float64 *)((void *)(p->params[1])));
5408     asysn_audiounit_proplisteners_update(My, kAudioUnitProperty_Latency,
5409 					 kAudioUnitScope_Global, (AudioUnitElement) 0);
5410     break;
5411   case kAudioUnitProperty_SupportedNumChannels: /* 13 */
5412     result = kAudioUnitErr_InvalidPropertyValue;
5413     break;
5414   case kAudioUnitProperty_MaximumFramesPerSlice: /* 14 */
5415     if (*((UInt32 *)((void *)(p->params[1]))) > ASYS_AUDIOUNIT_FRAMES_PER_SLICE)
5416       result = kAudioUnitErr_InvalidPropertyValue;
5417     else
5418       {
5419 	My->MaximumFramesPerSlice = *((UInt32 *)((void *)(p->params[1])));
5420 	asysn_audiounit_proplisteners_update(My, kAudioUnitProperty_MaximumFramesPerSlice,
5421 					     kAudioUnitScope_Global, (AudioUnitElement) 0);
5422       }
5423     break;
5424   case kAudioUnitProperty_ParameterValueStrings: /* 16 */
5425     result = kAudioUnitErr_InvalidProperty;
5426     break;    /* hosts not permitted to set ParameterValueStrings */
5427   case kAudioUnitProperty_TailTime: /* 20 */
5428     My->TailTime = *((Float64 *)((void *)(p->params[1])));
5429     asysn_audiounit_proplisteners_update(My, kAudioUnitProperty_TailTime,
5430 					 kAudioUnitScope_Global, (AudioUnitElement) 0);
5431     break;
5432   case kAudioUnitProperty_BypassEffect: /* 21 */
5433     My->BypassEffect = *((UInt32 *)((void *)(p->params[1])));
5434     break;
5435   case kAudioUnitProperty_LastRenderError: /* 22 */
5436     My->LastRenderError = *((OSStatus *)((void *)(p->params[1])));
5437     break;
5438   case kAudioUnitProperty_SetRenderCallback:  /* 23 */
5439     if ((p->params[2] >= ASYS_AUDIOUNIT_ELEMENT_ARRAYSIZE) ||
5440 	(p->params[2] < 0))
5441       {
5442 	result = kAudioUnitErr_InvalidProperty;
5443 	break;
5444       }
5445     OSSpinLockLock(&(My->lock_sampledelivery));
5446     memcpy(&(My->SetRenderCallback[p->params[2]]),
5447 	   (AURenderCallbackStruct *)(p->params[1]),
5448 	   sizeof(AURenderCallbackStruct));
5449     OSSpinLockUnlock(&(My->lock_sampledelivery));
5450     break;
5451   case kAudioUnitProperty_FactoryPresets: /* 24 */
5452     result = kAudioUnitErr_InvalidProperty;
5453     break;    /* hosts not permitted to change Factory Presets */
5454   case kAudioUnitProperty_RenderQuality: /* 26 */
5455     My->RenderQuality = *((UInt32 *)((void *)(p->params[1])));
5456     asysn_audiounit_proplisteners_update(My, kAudioUnitProperty_RenderQuality,
5457 					 kAudioUnitScope_Global, (AudioUnitElement) 0);
5458     break;
5459   case kAudioUnitProperty_InPlaceProcessing: /* 29 */
5460     if (*((UInt32 *)((void *)(p->params[1]))) != ASYS_AUDIOUNIT_INPLACE_PROCESSING)
5461       result = kAudioUnitErr_InvalidPropertyValue;
5462     break;
5463   case kAudioUnitProperty_PresentPreset: /* 36 */
5464     OSSpinLockLock(&(My->lock_PresentPreset));
5465     CFRelease(My->PresentPreset.presetName);
5466     My->PresentPreset.presetNumber = ((AUPreset *)(p->params[1]))->presetNumber;
5467     My->PresentPreset.presetName = ((AUPreset *)(p->params[1]))->presetName;
5468     CFRetain(My->PresentPreset.presetName);
5469     OSSpinLockUnlock(&(My->lock_PresentPreset));
5470     asysn_audiounit_presentproperty_setfactory(My);
5471     asysn_audiounit_proplisteners_update(My, kAudioUnitProperty_PresentPreset,
5472 					 kAudioUnitScope_Global, (AudioUnitElement) 0);
5473     break;
5474   case kAudioUnitProperty_OfflineRender: /* 37 */
5475     My->OfflineRender = *((UInt32 *)((void *)(p->params[1])));
5476     break;
5477   case kAudioUnitProperty_PresentationLatency: /* 40 */
5478     My->PresentationLatency = *((Float64 *)((void *)(p->params[1])));
5479     break;
5480   case kMusicDeviceProperty_InstrumentCount: /* 1000 */
5481     if (ASYS_AUDIOUNIT_EFFECT)
5482       result = kAudioUnitErr_InvalidPropertyValue;
5483     else
5484       if (*((UInt32 *)((void *)(p->params[1]))) != ASYS_AUDIOUNIT_INSTRUMENT_COUNT)
5485 	result = kAudioUnitErr_InvalidPropertyValue;
5486     break;
5487   case kMusicDeviceProperty_StreamFromDisk: /* 1011 */
5488     My->StreamFromDisk = *((UInt32 *)((void *)(p->params[1])));
5489     asysn_audiounit_proplisteners_update(My, kMusicDeviceProperty_StreamFromDisk,
5490 					 kAudioUnitScope_Global, (AudioUnitElement) 0);
5491     break;
5492   default:   /* should never happen */
5493     result = kAudioUnitErr_InvalidProperty;
5494     break;
5495   }
5496 
5497   return result;
5498 }
5499 
5500 /**********************************************************/
5501 /*                 Selector: Render                       */
5502 /*                                                        */
5503 /* params[0]: AudioBufferList * ioData;                   */
5504 /* params[1]: UInt32 inNumberFrames;                      */
5505 /* params[2]: UInt32 inOutputBusNumber;                   */
5506 /* params[3]: const AudioTimeStamp * inTimeStamp;         */
5507 /* params[4]: AudioUnitRenderActionFlags * ioActionFlags; */
5508 /*                                                        */
5509 /**********************************************************/
5510 
asysn_audiounit_kAudioUnitRenderSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5511 ComponentResult asysn_audiounit_kAudioUnitRenderSelect(ComponentParameters * p,
5512 					  asysn_audiounit_InstanceState * My)
5513 {
5514   return (asysn_audiounit_MyRenderer((void *) My,
5515 				     (AudioUnitRenderActionFlags *)(p->params[4]),
5516 				     (const AudioTimeStamp *)(p->params[3]),
5517 				     (UInt32)(p->params[2]), (UInt32)(p->params[1]),
5518 				     (AudioBufferList *)(p->params[0])));
5519 }
5520 
5521 /*******************/
5522 /* Selector: Reset */
5523 /*                 */
5524 /*******************/
5525 
asysn_audiounit_kAudioUnitResetSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5526 ComponentResult asysn_audiounit_kAudioUnitResetSelect(ComponentParameters * p,
5527 					 asysn_audiounit_InstanceState * My)
5528 {
5529 
5530 #if (ASYS_AUDIOUNIT_RESET_TYPE == ASYS_AUDIOUNIT_ACTIVE_RESET)
5531   asysn_audiounit_kAudioUnitUninitializeSelect(p, My);
5532   asysn_audiounit_kAudioUnitInitializeSelect(p, My);
5533 #endif
5534 
5535   return noErr;
5536 }
5537 
5538 /*****************************************************/
5539 /* Selector: Add Property Listener                   */
5540 /*                                                   */
5541 /*  params[0]: void * inProcRefCon;                  */
5542 /*  params[1]: AudioUnitPropertyListenerProc inProc; */
5543 /*  params[2]: AudioUnitPropertyID inID;             */
5544 /*                                                   */
5545 /* The caller passes in a function inProc to call    */
5546 /* the AU changes the property, and an object        */
5547 /* inProcRefCon to pass to the function.             */
5548 /*****************************************************/
5549 
asysn_audiounit_kAudioUnitAddPropertyListenerSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5550 ComponentResult asysn_audiounit_kAudioUnitAddPropertyListenerSelect(
5551                                            ComponentParameters * p,
5552 					   asysn_audiounit_InstanceState * My)
5553 {
5554   asysn_audiounit_proplisten * lp;
5555   AudioUnitPropertyListenerProc lproc;
5556   void * lrefcon;
5557   int idx, found, msize;
5558 
5559   if ((idx = asysn_audiounit_proplisteners_index(p->params[2])) < 0)
5560     return noErr;
5561 
5562   lrefcon = (void *)(p->params[0]);
5563   lproc = (AudioUnitPropertyListenerProc)(p->params[1]);
5564 
5565   if (!lproc)
5566     return noErr;
5567 
5568   found = 0;
5569 
5570   OSSpinLockLock(&(My->lock_proplisteners));
5571 
5572   for (lp = My->proplisteners[idx]; lp != NULL; lp = lp->next)
5573     if ((lp->lrefcon == lrefcon) && (lp->lproc == lproc))
5574       {
5575 	found = 1;
5576 	break;
5577       }
5578 
5579   if (!found)
5580     {
5581       msize = sizeof(asysn_audiounit_proplisten);
5582       if (lp = malloc(msize))
5583 	{
5584 	  asysn_audiounit_memstatus(lp, msize, MADV_WILLNEED);
5585 	  lp->lproc = lproc;
5586 	  lp->lrefcon = lrefcon;
5587 	  lp->next = My->proplisteners[idx];
5588 	  My->proplisteners[idx] = lp;
5589 	}
5590     }
5591 
5592   OSSpinLockUnlock(&(My->lock_proplisteners));
5593 
5594   /* end of critical section */
5595 
5596   return noErr;
5597 }
5598 
5599 /*****************************************************/
5600 /* Selector: Remove Property Listener                */
5601 /*                                                   */
5602 /*  params[0]: AudioUnitPropertyListenerProc inProc; */
5603 /*  params[1]: AudioUnitPropertyID inID;             */
5604 /*                                                   */
5605 /* Instructs the AudioUnit to stop calling the       */
5606 /* inProc for the specified property inID.           */
5607 /*****************************************************/
5608 
asysn_audiounit_kAudioUnitRemovePropertyListenerSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5609 ComponentResult asysn_audiounit_kAudioUnitRemovePropertyListenerSelect(
5610                                            ComponentParameters * p,
5611 					   asysn_audiounit_InstanceState * My)
5612 {
5613   asysn_audiounit_proplisten * lp, * remove, ** trailer;
5614   AudioUnitPropertyListenerProc lproc;
5615   int idx, msize;
5616 
5617   if ((idx = asysn_audiounit_proplisteners_index(p->params[1])) < 0)
5618     return noErr;
5619 
5620   lproc = (AudioUnitPropertyListenerProc)(p->params[0]);
5621 
5622   OSSpinLockLock(&(My->lock_proplisteners));
5623 
5624   lp = My->proplisteners[idx];
5625   trailer = &(My->proplisteners[idx]);
5626 
5627   while (lp != NULL)
5628     if (lp->lproc == lproc)
5629       {
5630 	remove = lp;
5631 	lp = (*trailer) = lp->next;
5632 	msize = sizeof(asysn_audiounit_proplisten);
5633 	asysn_audiounit_memstatus(remove, msize, MADV_FREE);
5634  	free(remove);
5635       }
5636     else
5637       {
5638 	trailer = &(lp->next);
5639 	lp = lp->next;
5640       }
5641 
5642   OSSpinLockUnlock(&(My->lock_proplisteners));
5643 
5644   return noErr;
5645 }
5646 
5647 /*****************************************************/
5648 /* Selector: Remove Property Listener With User Data */
5649 /*                                                   */
5650 /*  params[0]: void * inProcRefCon;                  */
5651 /*  params[1]: AudioUnitPropertyListenerProc inProc; */
5652 /*  params[2]: AudioUnitPropertyID inID;             */
5653 /*                                                   */
5654 /* Instructs the AudioUnit to stop calling the       */
5655 /* inProc for the specified property inID.           */
5656 /*****************************************************/
5657 
asysn_audiounit_kAudioUnitRemovePropertyListenerWithUserDataSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5658 ComponentResult asysn_audiounit_kAudioUnitRemovePropertyListenerWithUserDataSelect(
5659                                            ComponentParameters * p,
5660 					   asysn_audiounit_InstanceState * My)
5661 {
5662   asysn_audiounit_proplisten * lp, * remove, ** trailer;
5663   AudioUnitPropertyListenerProc lproc;
5664   void * lrefcon;
5665   int idx, msize;
5666 
5667   if ((idx = asysn_audiounit_proplisteners_index(p->params[2])) < 0)
5668     return noErr;
5669 
5670   lrefcon = (void *)(p->params[0]);
5671   lproc = (AudioUnitPropertyListenerProc)(p->params[1]);
5672 
5673   OSSpinLockLock(&(My->lock_proplisteners));
5674 
5675   lp = My->proplisteners[idx];
5676   trailer = &(My->proplisteners[idx]);
5677 
5678   while (lp != NULL)
5679     if ((lp->lproc == lproc) && (lp->lrefcon == lrefcon))
5680       {
5681 	remove = lp;
5682 	lp = (*trailer) = lp->next;
5683 	msize = sizeof(asysn_audiounit_proplisten);
5684 	asysn_audiounit_memstatus(remove, msize, MADV_FREE);
5685  	free(remove);
5686       }
5687     else
5688       {
5689 	trailer = &(lp->next);
5690 	lp = lp->next;
5691       }
5692 
5693   OSSpinLockUnlock(&(My->lock_proplisteners));
5694 
5695   return noErr;
5696 }
5697 
5698 /*************************************/
5699 /*  Selector: Add Render Notify      */
5700 /*                                   */
5701 /*  params[0]: void * inProcRefCon;  */
5702 /*  params[1]: ProcPtr inProc;       */
5703 /*                                   */
5704 /*************************************/
5705 
asysn_audiounit_kAudioUnitAddRenderNotifySelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5706 ComponentResult asysn_audiounit_kAudioUnitAddRenderNotifySelect
5707 (ComponentParameters * p, asysn_audiounit_InstanceState * My)
5708 {
5709   asysn_audiounit_rendernotify * notify;
5710   int msize;
5711 
5712   msize = sizeof(asysn_audiounit_rendernotify);
5713   if (!(notify = malloc(msize)))
5714     return noErr;
5715   asysn_audiounit_memstatus(notify, msize, MADV_WILLNEED);
5716 
5717   notify->nproc = (AURenderCallback)(p->params[1]);
5718   notify->nrefcon = (void *)(p->params[0]);
5719 
5720   OSSpinLockLock(&(My->lock_rendernotify));
5721 
5722   notify->next = My->rendernotify;
5723   My->rendernotify = notify;
5724 
5725   OSSpinLockUnlock(&(My->lock_rendernotify));
5726 
5727   return noErr;
5728 }
5729 
5730 /*************************************/
5731 /*  Selector: Remove Render Notify   */
5732 /*                                   */
5733 /*  params[0]: void * inProcRefCon;  */
5734 /*  params[1]: ProcPtr inProc;       */
5735 /*                                   */
5736 /*************************************/
5737 
asysn_audiounit_kAudioUnitRemoveRenderNotifySelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5738 ComponentResult asysn_audiounit_kAudioUnitRemoveRenderNotifySelect
5739 (ComponentParameters * p, asysn_audiounit_InstanceState * My)
5740 {
5741   asysn_audiounit_rendernotify * notify, * remove, ** trailer;
5742   int msize;
5743 
5744   OSSpinLockLock(&(My->lock_rendernotify));
5745 
5746   notify = My->rendernotify;
5747   trailer = &(My->rendernotify);
5748 
5749   while (notify != NULL)
5750     if ((notify->nproc == (AURenderCallback)(p->params[1])) &&
5751 	(notify->nrefcon == (void *)(p->params[0])))
5752       {
5753 	remove = notify;
5754 	notify = (*trailer) = notify->next;
5755 
5756 	msize = sizeof(asysn_audiounit_rendernotify);
5757 	asysn_audiounit_memstatus(remove, msize, MADV_FREE);
5758 	free(remove);
5759       }
5760     else
5761       {
5762 	trailer = &(notify->next);
5763 	notify = notify->next;
5764       }
5765 
5766   OSSpinLockUnlock(&(My->lock_rendernotify));
5767 
5768   return noErr;
5769 }
5770 
5771 
5772 /******************************************/
5773 /*     Selector: GetParameterSelect       */
5774 /*                                        */
5775 /* params[0]: Float32 * outValue          */
5776 /* params[1]: AudioUnitElement inElement  */
5777 /* params[2]: AudioUnitScope inScope      */
5778 /* params[3]: AudioUnitParameterID inID   */
5779 /*                                        */
5780 /******************************************/
5781 
asysn_audiounit_kAudioUnitGetParameterSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5782 ComponentResult asysn_audiounit_kAudioUnitGetParameterSelect
5783 (ComponentParameters * p, asysn_audiounit_InstanceState * My)
5784 {
5785   if (((AudioUnitScope)(p->params[2])) != kAudioUnitScope_Global)  /* inScope */
5786     return kAudioUnitErr_InvalidScope;
5787 
5788   return asysn_audiounit_getSASLevent(((AudioUnitParameterID)(p->params[3])) /* inID */,
5789 				      ((Float32 *)(p->params[0])) /* outValue */, My);
5790 }
5791 
5792 
5793 /*********************************************/
5794 /*     Selector: SetParameterSelect          */
5795 /*                                           */
5796 /* params[0]: UInt32 inBufferOffsetInFrames  */
5797 /* params[1]: Float32 inValue                */
5798 /* params[2]: AudioUnitElement inElement     */
5799 /* params[3]: AudioUnitScope inScope;        */
5800 /* params[4]: AudioUnitParameterID inID;     */
5801 /*                                           */
5802 /*********************************************/
5803 
asysn_audiounit_kAudioUnitSetParameterSelect(ComponentParameters * p,asysn_audiounit_InstanceState * My)5804 ComponentResult asysn_audiounit_kAudioUnitSetParameterSelect
5805 (ComponentParameters * p, asysn_audiounit_InstanceState * My)
5806 {
5807   asysn_audiounit_SASLevent SASLevent;
5808   int result;
5809   Float32 inValue;
5810   int inID;
5811 
5812   if (((AudioUnitScope)(p->params[3])) != kAudioUnitScope_Global)  /* inScope */
5813     return kAudioUnitErr_InvalidScope;
5814 
5815   inID = (AudioUnitParameterID)(p->params[4]);
5816 
5817   if ((inID < 0) || (inID >= My->num_saolparams))  /* range-check ID */
5818     return kAudioUnitErr_InvalidParameter;
5819 
5820   inValue = *((Float32 *)((unsigned char *)(&(p->params[1]))));
5821 
5822   if (inValue > My->parameterinfo[inID].maxValue)
5823     inValue = My->parameterinfo[inID].maxValue;
5824 
5825   if (inValue < My->parameterinfo[inID].minValue)
5826     inValue = My->parameterinfo[inID].minValue;
5827 
5828   SASLevent.index = inID;
5829   SASLevent.value = My->saolparam[inID].value = inValue;
5830   SASLevent.kcycleidx = (int)((UInt32)(p->params[0]));
5831 
5832   return asysn_audiounit_sendSASLevent(&SASLevent, My);
5833 }
5834 
5835 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5836 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5837 /* The AudioUnit Entry Function */
5838 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5839 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5840 
5841 /************************************************************/
5842 /*   The function Component Manager calls to access the AU  */
5843 /************************************************************/
5844 
asysn_audiounit_entry(ComponentParameters * p,Handle * obj)5845 extern ComponentResult asysn_audiounit_entry(ComponentParameters * p, Handle * obj)
5846 {
5847   asysn_audiounit_MIDIevent MIDIevent;
5848   ComponentResult result;
5849 
5850   if (obj == NULL)
5851     switch (p->what) {
5852     case kComponentOpenSelect:
5853     case kComponentVersionSelect:
5854     case kComponentCanDoSelect:
5855       break;
5856     default:
5857     return noErr;  /* avoid race condition */
5858     }
5859 
5860   switch (p->what) {
5861   case kComponentOpenSelect:
5862     result = asysn_audiounit_kComponentOpenSelect
5863       (p, (asysn_audiounit_InstanceState *) obj);
5864     break;
5865   case kComponentCloseSelect:
5866     result = asysn_audiounit_kComponentCloseSelect
5867       (p, (asysn_audiounit_InstanceState *) obj);
5868     break;
5869   case kAudioUnitInitializeSelect:
5870     result = asysn_audiounit_kAudioUnitInitializeSelect
5871       (p, (asysn_audiounit_InstanceState *) obj);
5872     break;
5873   case kAudioUnitUninitializeSelect:
5874     result = asysn_audiounit_kAudioUnitUninitializeSelect
5875       (p, (asysn_audiounit_InstanceState *) obj);
5876     break;
5877   case kAudioUnitGetPropertyInfoSelect:
5878     result = asysn_audiounit_kAudioUnitGetPropertyInfoSelect
5879       (p, (asysn_audiounit_InstanceState *) obj);
5880     break;
5881   case kAudioUnitGetPropertySelect:
5882     result = asysn_audiounit_kAudioUnitGetPropertySelect
5883       (p, (asysn_audiounit_InstanceState *) obj);
5884     break;
5885   case kAudioUnitSetPropertySelect:
5886     result = asysn_audiounit_kAudioUnitSetPropertySelect
5887       (p, (asysn_audiounit_InstanceState *) obj);
5888     break;
5889   case kAudioUnitRenderSelect:
5890     result = asysn_audiounit_kAudioUnitRenderSelect
5891       (p, (asysn_audiounit_InstanceState *) obj);
5892     break;
5893   case kAudioUnitResetSelect:
5894     result = asysn_audiounit_kAudioUnitResetSelect
5895       (p, (asysn_audiounit_InstanceState *) obj);
5896     break;
5897   case kAudioUnitAddPropertyListenerSelect:
5898     result = asysn_audiounit_kAudioUnitAddPropertyListenerSelect
5899       (p, (asysn_audiounit_InstanceState *) obj);
5900     break;
5901   case kAudioUnitRemovePropertyListenerSelect:
5902     result = asysn_audiounit_kAudioUnitRemovePropertyListenerSelect
5903       (p, (asysn_audiounit_InstanceState *) obj);
5904     break;
5905   case kAudioUnitRemovePropertyListenerWithUserDataSelect:
5906     result = asysn_audiounit_kAudioUnitRemovePropertyListenerWithUserDataSelect
5907       (p, (asysn_audiounit_InstanceState *) obj);
5908     break;
5909   case kAudioUnitAddRenderNotifySelect:
5910     result = asysn_audiounit_kAudioUnitAddRenderNotifySelect
5911       (p, (asysn_audiounit_InstanceState *) obj);
5912     break;
5913   case kAudioUnitRemoveRenderNotifySelect:
5914     result = asysn_audiounit_kAudioUnitRemoveRenderNotifySelect
5915       (p, (asysn_audiounit_InstanceState *) obj);
5916     break;
5917   case kAudioUnitGetParameterSelect:
5918     result = asysn_audiounit_kAudioUnitGetParameterSelect
5919       (p, (asysn_audiounit_InstanceState *) obj);
5920     break;
5921   case kAudioUnitSetParameterSelect:
5922     result = asysn_audiounit_kAudioUnitSetParameterSelect
5923       (p, (asysn_audiounit_InstanceState *) obj);
5924     break;
5925   case kAudioUnitScheduleParametersSelect:
5926     result = noErr;
5927     break;
5928   case kMusicDeviceMIDIEventSelect:
5929     if (ASYS_AUDIOUNIT_MIDISUPPORT)
5930       {
5931 	MIDIevent.cmd = (unsigned char)((UInt32)(p->params[3]));
5932 	MIDIevent.d0 = (unsigned char)((UInt32)(p->params[2]));
5933 	MIDIevent.d1 = (unsigned char)((UInt32)(p->params[1]));
5934 	MIDIevent.flags = ASYS_AUDIOUNIT_MIDIFLAGS_WAITING;
5935 	MIDIevent.kcycleidx = (int)((UInt32)(p->params[0]));
5936 	result = asysn_audiounit_sendMIDIevent
5937 	  (&MIDIevent, (asysn_audiounit_InstanceState *) obj);
5938       }
5939     else
5940       result = badComponentSelector;
5941     break;
5942   case kMusicDeviceSysExSelect:
5943   case kMusicDevicePrepareInstrumentSelect:
5944   case kMusicDeviceReleaseInstrumentSelect:
5945   case kMusicDeviceStartNoteSelect:
5946   case kMusicDeviceStopNoteSelect:
5947   default:
5948     result = badComponentSelector;
5949     break;
5950   case kComponentVersionSelect:
5951     result = 0x00010000;    /* major version 1, minor version 0 */
5952     break;
5953   case kComponentCanDoSelect:
5954     switch ((int)((SInt16)(p->params[0]))) {
5955     case kComponentOpenSelect:
5956     case kComponentCloseSelect:
5957     case kAudioUnitInitializeSelect:
5958     case kAudioUnitUninitializeSelect:
5959     case kAudioUnitGetPropertyInfoSelect:
5960     case kAudioUnitGetPropertySelect:
5961     case kAudioUnitSetPropertySelect:
5962     case kAudioUnitRenderSelect:
5963     case kAudioUnitResetSelect:
5964     case kAudioUnitAddPropertyListenerSelect:
5965     case kAudioUnitRemovePropertyListenerSelect:
5966     case kAudioUnitRemovePropertyListenerWithUserDataSelect:
5967     case kAudioUnitAddRenderNotifySelect:
5968     case kAudioUnitRemoveRenderNotifySelect:
5969     case kAudioUnitGetParameterSelect:
5970     case kAudioUnitSetParameterSelect:
5971       result = 1;
5972       break;
5973     case kMusicDeviceMIDIEventSelect:
5974       result = ASYS_AUDIOUNIT_MIDISUPPORT;
5975     default:
5976       result = 0;
5977       break;
5978     }
5979     break;
5980   }
5981 
5982   switch (p->what) {
5983   case kAudioUnitRenderSelect:
5984     ASYS_AUDIOUNIT_WIRETAP_R(p, result);
5985     break;
5986   case kMusicDeviceMIDIEventSelect:
5987     ASYS_AUDIOUNIT_WIRETAP_M(p, result);
5988     break;
5989   default:
5990     ASYS_AUDIOUNIT_WIRETAP(p, result);
5991     break;
5992   }
5993 
5994   return result;
5995 }
5996 
5997 /****************************************************************/
5998 /*         End of Part Three (The AudioUnit Component)          */
5999 /****************************************************************/
6000 
6001 /****************************************************************/
6002 /*        End of Apple AudioUnit audio driver for sfront        */
6003 /****************************************************************/
6004 /****************************************************************/
6005 
6006