1
2#include "FaustAU_CustomView.h"
3#include "FaustAU.h"
4
5@implementation FaustAU_CustomView
6
7// This listener responds to parameter changes, gestures, and property notifications
8void eventListenerDispatcher (void *inRefCon, void *inObject, const AudioUnitEvent *inEvent, UInt64 inHostTime, Float32 inValue)
9{
10	FaustAU_CustomView *SELF = (FaustAU_CustomView *)inRefCon;
11	[SELF eventListener:inObject event: inEvent value: inValue];
12}
13
14void addParamListener (AUEventListenerRef listener, void* refCon, AudioUnitEvent *inEvent)
15{
16	inEvent->mEventType = kAudioUnitEvent_BeginParameterChangeGesture;
17	verify_noerr ( AUEventListenerAddEventType(	listener, refCon, inEvent));
18
19	inEvent->mEventType = kAudioUnitEvent_EndParameterChangeGesture;
20	verify_noerr ( AUEventListenerAddEventType(	listener, refCon, inEvent));
21
22	inEvent->mEventType = kAudioUnitEvent_ParameterValueChange;
23	verify_noerr ( AUEventListenerAddEventType(	listener, refCon, inEvent));
24}
25
26- (void)addListeners
27{
28    auUI* dspUI;
29
30    if (mAU) {
31		verify_noerr( AUEventListenerCreate(eventListenerDispatcher, self,
32											CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0.05, 0.05,
33											&mAUEventListener));
34        dspUI = [self dspUI];
35
36		//add listeners
37        AudioUnitEvent auEvent;
38        for (int i = 0; i < dspUI->fUITable.size(); i++)
39            if (dspUI->fUITable[i] && dspUI->fUITable[i]->fZone)
40            {
41                if (dynamic_cast<auButton*>(dspUI->fUITable[i])) {
42                }
43                else if (dynamic_cast<auToggleButton*>(dspUI->fUITable[i])) {
44                }
45                else if (dynamic_cast<auCheckButton*>(dspUI->fUITable[i])) {
46                }
47                else {
48                    AudioUnitParameter parameter =
49                    {
50                        mAU,
51                        i,
52                        kAudioUnitScope_Global,
53                        0 // mElement
54                    };
55                    auEvent.mArgument.mParameter = parameter;
56                    addParamListener (mAUEventListener, self, &auEvent);                }
57            }
58
59		/* Add a listener for the changes in our custom property */
60		/* The Audio unit will send a property change when the unit is intialized */
61		auEvent.mEventType = kAudioUnitEvent_PropertyChange;
62		auEvent.mArgument.mProperty.mAudioUnit = mAU;
63		auEvent.mArgument.mProperty.mPropertyID = kAudioUnitCustomProperty_dspUI;
64		auEvent.mArgument.mProperty.mScope = kAudioUnitScope_Global;
65		auEvent.mArgument.mProperty.mElement = 0;
66		verify_noerr (AUEventListenerAddEventType (mAUEventListener, self, &auEvent));
67	}
68
69}
70
71- (void)removeListeners
72{
73	if (mAUEventListener) verify_noerr (AUListenerDispose(mAUEventListener));
74	mAUEventListener = NULL;
75	mAU = NULL;
76}
77
78- (auUI*) dspUI
79{
80    auUI* dspUI;
81    UInt32 dataSize = sizeof(auUI*);
82    ComponentResult result = AudioUnitGetProperty(mAU,
83                                                  (AudioUnitPropertyID)kAudioUnitCustomProperty_dspUI,
84                                                  kAudioUnitScope_Global,
85                                                  (AudioUnitElement)0, //inElement
86                                                  (void*)&dspUI,
87                                                  &dataSize);
88    return dspUI;
89}
90
91/*
92 - (BOOL)isFlipped {
93     return YES;
94 }
95*/
96
97- (void)dealloc
98{
99     [self unsetTimer];
100     [self removeListeners];
101     [[NSNotificationCenter defaultCenter] removeObserver: self];
102     [super dealloc];
103}
104
105- (NSButton*)addButton:(NSBox*) nsBox :(auButton*)fButton :(int)controlId :(NSPoint&) origin :(NSSize&) size :(bool)isVerticalBox
106{
107    int width = 100;
108    int height = 35;
109
110    FaustAU_Button* button = [[FaustAU_Button alloc] init :NSMakeRect(origin.x, origin.y, width, height) :fButton :controlId];
111
112    button->delegate = self;
113
114    [nsBox addSubview:button];
115
116    if (isVerticalBox)
117    {
118        origin.y += height;
119        size.height += height;
120        if (size.width < width)
121            size.width = width;
122    }
123    else
124    {
125        origin.x += width;
126        size.width += width;
127        if (size.height < height)
128            size.height = height;
129    }
130
131    return button;
132}
133
134- (NSButton*)addCheckButton:(NSBox*) nsBox :(auCheckButton*)fButton :(int)controlId :(NSPoint&) origin :(NSSize&) size :(bool)isVerticalBox
135{
136    int width = 100;
137    int height = 35;
138
139    NSRect frame = NSMakeRect(origin.x, origin.y, width, height);
140
141    NSButton* button = [[NSButton alloc] initWithFrame:frame ];
142
143    [button setTitle:[[NSString alloc] initWithCString:fButton->fLabel.c_str() encoding:NSUTF8StringEncoding]];
144
145    [button setButtonType:NSSwitchButton];
146    [button setBezelStyle:NSRoundedBezelStyle];
147
148    NSString *identifier = [NSString stringWithFormat:@"%d",controlId];
149    [button setIdentifier: identifier];
150
151    [button setTarget:self];
152    [button setAction:@selector(paramChanged:)];
153
154    [nsBox addSubview:button];
155
156    if (isVerticalBox)
157    {
158        origin.y += height;
159        size.height += height;
160        if (size.width < width)
161            size.width = width;
162    }
163    else
164    {
165        origin.x += width;
166        size.width += width;
167        if (size.height < height)
168            size.height = height;
169    }
170
171    return button;
172}
173
174- (NSTextField*)addTextField:(NSBox*) nsBox :(const char*)label :(int)controlId :(NSPoint&) origin :(bool)isVerticalBox
175{
176    int width = 100;
177    int height = 35;
178
179    NSTextField* textField;
180
181    textField = [[NSTextField alloc] initWithFrame:NSMakeRect(origin.x, origin.y + 2 , width, height)];
182
183    [textField setBezeled:NO];
184    [textField setDrawsBackground:NO];
185    [textField setEditable:NO];
186    [textField setSelectable:NO];
187    [textField setIdentifier: @"200"]; //TODO
188    [textField setStringValue:[[NSString alloc] initWithCString:label encoding:NSUTF8StringEncoding]];
189
190    [nsBox addSubview:textField];
191
192    return textField;
193}
194
195- (FaustAU_Slider*)addSlider:(NSBox*) nsBox :(auSlider*)fSlider :(int)controlId :(NSPoint&) origin :(NSSize&) size :(bool)isVerticalBox
196{
197    int labelWidth = 0;
198
199    NSTextField* labelTextField = NULL;
200
201    if (strcmp(fSlider->fLabel.c_str(), "")) {
202        labelTextField = [self addTextField :nsBox :fSlider->fLabel.c_str() :200 :origin :isVerticalBox];
203        [labelTextField setAlignment: NSRightTextAlignment];
204        labelWidth = 100;
205    }
206
207    int width;
208    int height;
209    float value;
210
211    if (fSlider->fIsVertical) {
212        width = 15;
213        height = 100;
214    } else {
215        width = 300;
216        height = 45;
217    }
218
219    FaustAU_Slider* slider;
220    slider = [[FaustAU_Slider alloc] initWithFrame:NSMakeRect(origin.x + labelWidth, origin.y, width, height)];
221    [slider setMinValue:fSlider->fMin];
222    [slider setMaxValue:fSlider->fMax];
223
224    AudioUnitGetParameter(mAU, controlId, kAudioUnitScope_Global, 0, &value);
225    [slider setDoubleValue:value];
226
227    //TODO [slider setNumberOfTickMarks: (fSlider->fMax - fSlider->fMin) / fSlider->fStep];
228    NSString *identifier = [NSString stringWithFormat:@"%d",controlId];
229    [slider setIdentifier: identifier];
230
231    [slider setContinuous:YES];
232
233    [slider setAction:@selector(paramChanged:)];
234    [slider setTarget:self];
235
236    [nsBox addSubview:slider];
237
238    AudioUnitGetParameter(mAU, controlId, kAudioUnitScope_Global, 0, &value);
239    char valueString[100];
240    sprintf(valueString, "%9.2f", value);
241
242    NSPoint org;
243    org.x = origin.x + labelWidth + width - 12;
244    org.y = origin.y;
245    NSTextField* valueTextField = [self addTextField :nsBox :valueString :-1 :org :isVerticalBox];
246    [valueTextField setAlignment: NSLeftTextAlignment];
247
248    if (isVerticalBox)
249    {
250        origin.y += height;
251        size.height += height;
252        if (size.width < width+labelWidth+100)
253            size.width = width+labelWidth+100;
254    }
255    else
256    {
257        origin.x += width+labelWidth+100;
258        size.width += width+labelWidth+100;
259        if (size.height < height)
260            size.height = height;
261    }
262
263    paramValues[controlId] = valueTextField;
264
265    if (labelTextField)
266        [slider setLabelTextField: labelTextField];
267
268    [slider setValueTextField: valueTextField];
269    return slider;
270}
271
272- (NSArray*)generateArrayFrom:(float)start to:(float)stop step:(float)step
273{
274    NSMutableArray *a = [[NSMutableArray alloc] init];
275    float v = start;
276
277    while (v <= stop)
278    {
279        [a addObject:@(v)];
280        v += step;
281
282    }
283    return a;
284}
285
286- (FaustAU_Knob*)addKnob:(NSBox*) nsBox :(auSlider*)fSlider :(int)controlId :(NSPoint&) origin :(NSSize&) size :(bool)isVerticalBox
287{
288    NSTextField* labelTextField;
289    int labelWidth = 0;
290
291    if (strcmp(fSlider->fLabel.c_str(), "")) {
292        labelTextField = [self addTextField :nsBox :fSlider->fLabel.c_str() :200 :origin :isVerticalBox];
293        [labelTextField setAlignment: NSRightTextAlignment];
294        labelWidth = 100;
295    }
296
297    labelTextField = [self addTextField :nsBox :fSlider->fLabel.c_str() :200 :origin :isVerticalBox];
298    [labelTextField setAlignment: NSRightTextAlignment];
299
300    int width = 50;
301    int height = 50;
302    float value;
303
304    AudioUnitGetParameter(mAU, controlId, kAudioUnitScope_Global, 0, &value);
305    int initAngle =  225.0 - 270.0 * (value - fSlider->fMin) / (fSlider->fMax - fSlider->fMin);
306
307    FaustAU_Knob *knob = [[FaustAU_Knob alloc] initWithFrame:NSMakeRect(origin.x + labelWidth, origin.y, width, height)
308                                                  withInsets:10
309                                    withControlPointDiameter:2
310                                       withControlPointColor:[NSColor darkGrayColor]
311                                               withKnobColor:[NSColor whiteColor]
312                                         withBackgroundColor:[NSColor clearColor]
313                                            withCurrentAngle:initAngle];
314
315
316    knob->control = controlId;
317    knob->controlPoint->delegate = self;
318    knob->controlPoint->data = [self generateArrayFrom:fSlider->fMin to:fSlider->fMax step:fSlider->fStep]; //TODO step
319
320    NSString *identifier = [NSString stringWithFormat:@"%d",controlId];
321    [knob setIdentifier: identifier];
322
323    [nsBox addSubview:knob];
324
325    AudioUnitGetParameter(mAU, controlId, kAudioUnitScope_Global, 0, &value);
326    char valueString[100];
327    sprintf(valueString, "%9.2f", value);
328
329    NSPoint org;
330    org.x = origin.x + labelWidth + 28;
331    org.y = origin.y;
332    NSTextField* valueTextField = [self addTextField :nsBox :valueString :-1 :org :isVerticalBox];
333    [valueTextField setAlignment: NSLeftTextAlignment];
334
335    if (isVerticalBox)
336    {
337        origin.y += height;
338        size.height += height;
339        if (size.width < width+labelWidth + 30)
340            size.width = width+labelWidth + 30;
341    }
342    else
343    {
344        origin.x += width+labelWidth + 30;
345        size.width += width + labelWidth + 30;
346        if (size.height < height)
347            size.height = height;
348    }
349
350    paramValues[controlId] = valueTextField;
351
352    if (labelTextField)
353        [knob setLabelTextField: labelTextField];
354
355    [knob setValueTextField: valueTextField];
356    return knob;
357}
358
359- (FaustAU_Bargraph*)addBargraph:(NSBox*) nsBox :(auBargraph*)fBargraph :(int)controlId :(NSPoint&) origin :(NSSize&) size :(bool)isVerticalBox
360{
361    NSTextField* labelTextField = NULL;
362    int labelWidth = 0;
363
364    if (strcmp(fBargraph->fLabel.c_str(), "")) {
365        labelTextField = [self addTextField :nsBox :fBargraph->fLabel.c_str() :200 :origin :isVerticalBox];
366        [labelTextField setAlignment: NSRightTextAlignment];
367        labelWidth = 100;
368    }
369
370    int width;
371    int height;
372    float value;
373
374    if (fBargraph->fIsVertical) {
375        width = 35;
376        height = 100;
377    } else {
378        width = 300;
379        height = 55;
380    }
381
382    FaustAU_Bargraph* bargraph;
383    bargraph = [[FaustAU_Bargraph alloc] initWithFrame:NSMakeRect(origin.x + labelWidth, origin.y, width, height)];
384    [bargraph setMinValue:fBargraph->fMin];
385    [bargraph setMaxValue:fBargraph->fMax];
386
387    AudioUnitGetParameter(mAU, controlId, kAudioUnitScope_Global, 0, &value);
388    [bargraph setDoubleValue:value];
389
390    //TODO [barGraph setNumberOfTickMarks: (fBargraph->fMax - fBargraph->fMin) / fBargraph->fStep];
391    NSString *identifier = [NSString stringWithFormat:@"%d",controlId];
392    [bargraph setIdentifier: identifier];
393
394    [bargraph setContinuous:YES];
395
396    [bargraph setAction:@selector(paramChanged:)];
397    [bargraph setTarget:self];
398
399    [nsBox addSubview:bargraph];
400
401    AudioUnitGetParameter(mAU, controlId, kAudioUnitScope_Global, 0, &value);
402    char valueString[100];
403    sprintf(valueString, "%9.2f", value);
404
405    NSPoint org;
406    org.x = origin.x + labelWidth + width - 12;
407    org.y = origin.y;
408    NSTextField* valueTextField = [self addTextField :nsBox :valueString :-1 :org :isVerticalBox];
409    [valueTextField setAlignment: NSLeftTextAlignment];
410
411    if (isVerticalBox)
412    {
413        origin.y += height;
414        size.height += height;
415        if (size.width < width+labelWidth+100)
416            size.width = width+labelWidth+100;
417    }
418    else
419    {
420        origin.x += width+labelWidth+100;
421        size.width += width+labelWidth+100;
422        if (size.height < height)
423            size.height = height;
424    }
425
426    paramValues[controlId] = valueTextField;
427
428    if (labelTextField)
429        [bargraph setLabelTextField: labelTextField];
430
431    [bargraph setValueTextField: valueTextField];
432
433    return bargraph;
434}
435
436- (NSBox*)addBox:(NSBox*) nsParentBox :(auBox*)fThisBox :(NSPoint&) parentBoxOrigin :(NSSize&) parentBoxSize :(bool)isParentVerticalBox {
437
438    auUIObject* childUIObject;
439
440    NSBox* nsThisBox = [[NSBox alloc] init];
441    NSPoint thisBoxOrigin;
442    NSSize thisBoxSize;
443
444    thisBoxOrigin.x = thisBoxOrigin.y = 0;
445    thisBoxSize.width = thisBoxSize.height = 0;
446
447    [nsThisBox setTitle:[[NSString alloc] initWithCString:fThisBox->fLabel.c_str() encoding:NSUTF8StringEncoding]];
448
449    auUI* dspUI = [self dspUI];
450
451    int controlId;
452    NSView* childView = NULL;
453
454    bool hasChildView = false;
455
456      for (int i = 0; i < fThisBox->fChildren.size(); i++) {
457        if (fThisBox->fIsVertical)
458            childUIObject = fThisBox->fChildren[fThisBox->fChildren.size() - i - 1]; //not isFlipped
459        else
460            childUIObject = fThisBox->fChildren[i];
461
462        for (int j = 0; j < dspUI->fUITable.size(); j++)
463        {
464            if (dspUI->fUITable[j] == childUIObject)
465                controlId = j;
466        }
467
468        if (dynamic_cast<auBox*>(childUIObject)) {
469            [self addBox :nsThisBox :(auBox*)childUIObject :thisBoxOrigin :thisBoxSize :fThisBox->fIsVertical];
470        }
471        else
472        {
473            if (dynamic_cast<auButton*>(childUIObject)) {
474                childView = [self addButton :nsThisBox :(auButton*)childUIObject :controlId :thisBoxOrigin :thisBoxSize :fThisBox->fIsVertical];
475            }
476            else if (dynamic_cast<auCheckButton*>(childUIObject)) {
477                childView = [self addCheckButton :nsThisBox :(auCheckButton*)childUIObject :controlId :thisBoxOrigin :thisBoxSize :fThisBox->fIsVertical];
478            }
479
480            else if (dynamic_cast<auSlider*>(childUIObject)) {
481                if (dspUI->isKnob(childUIObject->fZone)) { //isKnob
482                    childView = [self addKnob :nsThisBox :(auSlider*)childUIObject :controlId :thisBoxOrigin :thisBoxSize :fThisBox->fIsVertical];
483                }
484                else {
485                    childView = [self addSlider :nsThisBox :(auSlider*)childUIObject :controlId :thisBoxOrigin :thisBoxSize :fThisBox->fIsVertical];
486                }
487
488            }
489            else if (dynamic_cast<auBargraph*>(childUIObject)) {
490                childView = [self addBargraph :nsThisBox :(auBargraph*)childUIObject :controlId :thisBoxOrigin :thisBoxSize :fThisBox->fIsVertical];
491            }
492
493            hasChildView = true;
494
495            if (childView)
496                viewMap[controlId] = childView;
497        }
498    }
499
500    /* if (hasChildView)
501     {
502
503     auButton showHideAUButton(fThisBox->fLabel.c_str(), NULL);
504
505     NSButton* showHideButton = [self addButton :nsThisBox :&showHideAUButton :-100 :thisBoxOrigin :thisBoxSize :fThisBox->fIsVertical]; //TODO -100
506     /*
507
508     // NSButton* showHideBtton = [[NSButton alloc] initWithFrame:NSMakeRect(0 //*thisBoxOrigin.x//, frame.size.//height - 30,  35, 70 )];
509
510     [showHideButton setTarget:self];
511     [showHideButton setAction:@selector(showHide:)];
512
513     [nsThisBox addSubview:showHideButton];
514     showHideMap[showHideButton] = nsThisBox;
515     }*/
516
517
518    NSRect frame;
519    frame.origin.x = parentBoxOrigin.x;
520    frame.origin.y = parentBoxOrigin.y;
521    frame.size.width  = thisBoxSize.width + 25;
522    frame.size.height = thisBoxSize.height + 25;
523    [nsThisBox setFrame:frame];
524
525    [nsThisBox setNeedsDisplay:YES];
526
527    [nsParentBox addSubview:nsThisBox];
528
529    if (isParentVerticalBox)
530    {
531        parentBoxOrigin.x = 0;
532        parentBoxOrigin.y += thisBoxSize.height + 25;
533
534        parentBoxSize.height += thisBoxSize.height + 25;
535        if (parentBoxSize.width < thisBoxSize.width)
536            parentBoxSize.width = thisBoxSize.width;
537    }
538    else
539    {
540        parentBoxOrigin.x += thisBoxSize.width + 25;
541        parentBoxSize.width += thisBoxSize.width + 25;
542
543        if (parentBoxSize.height < thisBoxSize.height)
544            parentBoxSize.height = thisBoxSize.height;
545        parentBoxOrigin.y = 0;
546    }
547
548    return nsThisBox;
549}
550
551-(void)repaint
552{
553    auUI* dspUI = [self dspUI];
554    NSRect frame;
555
556    NSPoint origin;
557    origin.x = origin.y = 0;
558
559    NSSize size;
560    size.width = size.height = 0;
561
562    NSBox* nsCustomViewBox = [[NSBox alloc] init];
563    [nsCustomViewBox setTitle:@"FaustAU CustomView"];
564    [self addBox :nsCustomViewBox :dspUI->boundingBox :origin :size :true];
565
566    frame.origin.x  = 0;
567    frame.origin.y = 0;
568    frame.size.width  = size.width + 25;
569    frame.size.height = size.height + 25;
570    [nsCustomViewBox setFrame:frame];
571    [nsCustomViewBox setNeedsDisplay:YES];
572    [self addSubview:nsCustomViewBox];
573
574    //xml button
575    NSButton* button;
576    NSRect monitorFrame = NSMakeRect(size.width - 32, 6, 55, 24);
577    button = [[NSButton alloc] initWithFrame:monitorFrame ];
578    [button setTitle:@"XML"];
579    [button setButtonType:NSMomentaryPushInButton];
580    [button setBezelStyle:NSRoundedBezelStyle];
581    [button setTarget:self];
582    [button setAction:@selector(xmlButtonPushed:)];
583    [button setState:TRUE];
584    [self addSubview:button];
585
586    if (usesBargraphs)
587    {
588        NSRect monitorFrame = NSMakeRect(10, 10, 60, 15);
589        button = [[NSButton alloc] initWithFrame:monitorFrame ];
590        [button setTitle:@"MON"];
591        [button setButtonType:NSSwitchButton];
592        [button setBezelStyle:NSRoundedBezelStyle];
593        [button setTarget:self];
594        [button setAction:@selector(monitorButtonPushed:)];
595        [button setState:TRUE];
596        [self addSubview:button];
597    }
598
599    [self setFrame:frame];
600    [self setNeedsDisplay:YES];
601}
602
603- (void)setAU:(AudioUnit)inAU
604{
605	if (mAU)
606		[self removeListeners];
607
608    mAU = inAU;
609    [self addListeners];
610    [self synchronizeUIWithParameterValues];
611
612    auUI* dspUI = [self dspUI];
613
614    usesBargraphs = false;
615    for (int i = 0; i < dspUI->fUITable.size(); i++)
616    {
617        if (dspUI->fUITable[i] && dspUI->fUITable[i]->fZone)
618        {
619            if (dynamic_cast<auBargraph*>(dspUI->fUITable[i]))
620                usesBargraphs = true;
621            break;
622        }
623    }
624
625    if (usesBargraphs)
626    {
627        monitor = true;
628        [self setTimer];
629    }
630
631    [self repaint];
632}
633
634-(void)setTimer
635{
636    if (!timer)
637    {
638        timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(update) userInfo:nil repeats:YES];
639    }
640}
641
642-(void)unsetTimer
643{
644    if (timer)
645    {
646        [timer invalidate];
647        timer = nil;
648    }
649}
650
651- (void)update
652{
653    [self synchronizeUIWithParameterValues];
654    [self setNeedsDisplay:YES];
655}
656
657// Called upon a knob update
658- (void)knobUpdatedWithIndex:(int)index
659                   withValue:(double)value
660                  withObject:(id)object
661{
662    [ (FaustAU_Knob*)object setDoubleValue :value ];
663    int paramId = [[object identifier] intValue];
664    ComponentResult result = AudioUnitSetParameter(mAU,
665                                                   paramId, //AudioUnitParameterID
666                                                   kAudioUnitScope_Global,
667                                                   (AudioUnitElement)0, //inElement
668                                                   value, //inValue
669                                                   0); //inBufferOffsetInFrames
670
671    NSString *string = [NSString stringWithFormat:@"%9.2f", value];
672    [paramValues[paramId] setStringValue: string];
673
674	AudioUnitParameter parameter = {mAU,
675        paramId, //paramId
676        kAudioUnitScope_Global,
677        0 }; //mElement
678
679	NSAssert(	AUParameterSet(mAUEventListener, object, &parameter, (Float32)value, 0) == noErr,
680             @"[FaustAU_CustomView paramChanged:] AUParameterSet()");
681
682    [object setNeedsDisplay:TRUE];
683}
684
685- (void)showHide:(id)sender
686{
687
688    int intValue = [sender intValue];
689
690    if (intValue)
691    {
692        [sender setTitle: @"-"];
693        [sender setIntValue: 1];
694
695        NSBox* box = showHideMap[sender];
696
697        [box setHidden:FALSE];
698        [box setNeedsDisplay:YES];
699    }
700    else
701    {
702        [sender setTitle: @"+"];
703        [sender setIntValue: 0];
704
705        NSBox* box = showHideMap[sender];
706
707        [box setHidden:TRUE];
708        [box setNeedsDisplay:YES];
709    }
710
711    //[self repaint];
712}
713
714- (void)buttonPushed:(id)sender
715{
716    int state =  ((FaustAU_Button*)sender)->buttonState;
717    int paramId = [[sender identifier] intValue];
718
719    ComponentResult result = AudioUnitSetParameter(mAU,
720                                                   paramId, //AudioUnitParameterID
721                                                   kAudioUnitScope_Global,
722                                                   (AudioUnitElement)0, //inElement
723                                                   state, //inValue
724                                                   0); //inBufferOffsetInFrames
725 	AudioUnitParameter parameter = {mAU,
726        paramId, //paramId
727        kAudioUnitScope_Global,
728        0 }; //mElement
729
730	NSAssert(	AUParameterSet(mAUEventListener, sender, &parameter, (Float32)state, 0) == noErr,
731             @"[FaustAU_CustomView paramChanged:] AUParameterSet()");
732}
733
734- (void)xmlButtonPushed:(id)sender
735{
736    NSData *data;
737    NSString* dataString;
738    NSString *oldString, *newString;
739
740    auUI* dspUI = [self dspUI];
741    NSFileManager *filemgr = [NSFileManager defaultManager];
742
743    NSString* path = [NSHomeDirectory() stringByAppendingString: @"/Library/Audio/Plug-Ins/Components/_FILENAME_.component/Contents/Resources/au-output.xml"];
744
745    NSSavePanel *savePanel = [NSSavePanel savePanel];
746    NSString *outputFileName = NULL;
747    int result = [savePanel runModal];
748
749    if (result == NSOKButton){
750        outputFileName = [[savePanel URL] path];
751    }
752
753    data = [filemgr contentsAtPath: path ];
754
755    dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
756
757    for (int i = 0; i < dspUI->fUITable.size(); i++)
758    {
759        if (dspUI->fUITable[i] && dspUI->fUITable[i]->fZone)
760        {
761            oldString = [NSString stringWithFormat:@"id=\"%i\"", i + 1];
762            newString = [NSString stringWithFormat:@"id=\"%i\" value=\"%f\"", i + 1, *dspUI->fUITable[i]->fZone];
763
764            dataString = [dataString stringByReplacingOccurrencesOfString: oldString withString:newString];
765        }
766    }
767
768    data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
769    [filemgr createFileAtPath: outputFileName contents: data attributes: nil];
770}
771
772- (void)monitorButtonPushed:(id)sender
773{
774    monitor = [(NSButton*)sender state];
775
776    if (monitor)
777        [self setTimer];
778    else
779        [self unsetTimer];
780}
781
782- (void)paramChanged:(id)sender
783{
784    float value =  [sender doubleValue]; //TODO
785    int paramId = [[sender identifier] intValue];
786
787    ComponentResult result = AudioUnitSetParameter(mAU,
788                                                   paramId, //AudioUnitParameterID
789                                                   kAudioUnitScope_Global,
790                                                   (AudioUnitElement)0, //inElement
791                                                   value, //inValue
792                                                   0); //inBufferOffsetInFrames
793
794    NSString *string = [NSString stringWithFormat:@"%9.2f", value];
795    [paramValues[paramId] setStringValue: string];
796
797	AudioUnitParameter parameter = { mAU,
798        paramId, //paramId
799        kAudioUnitScope_Global,
800        0 }; //mElement
801
802	NSAssert(	AUParameterSet(mAUEventListener, sender, &parameter, (Float32)value, 0) == noErr,
803             @"[FaustAU_CustomView paramChanged:] AUParameterSet()");
804}
805
806- (void)synchronizeUIWithParameterValues
807{
808    auUI* dspUI = [self dspUI];
809
810    NSView* subView = NULL;
811    int paramId;
812    Float32 value;
813
814    for (int i = 0; i < dspUI->fUITable.size(); i++)
815    {
816        if (dspUI->fUITable[i] && dspUI->fUITable[i]->fZone)
817        {
818            subView = viewMap[i]; //TODO can be used for other cases
819
820            if (subView)
821            {
822                if (dynamic_cast<auBargraph*>(dspUI->fUITable[i])) {
823                    value = *(dspUI->fUITable[i]->fZone);
824                    [subView setDoubleValue:value];
825                }
826            }
827        }
828    }
829}
830
831- (void)eventListener:(void *) inObject event:(const AudioUnitEvent *)inEvent value:(Float32)inValue
832{}
833
834@end
835