This is FakeUG.m in view mode; [Download] [Up]
/************************************************** * SynthBuilder * Copyright 1993 Nick Porcaro All Rights Reserved **************************************************/ /* #define DEBUG_BACKWARD 1 */ /* #define DEBUG_ERASE 1 */ /* * FakeUG.m * Eric Jordan, independent work, Spring, 1992 * * Nick Porcaro, independent work, Summer 1993 * * - Added new inspector. * * --> Arguments are updated when the user enters return * (left as an excersise for later to do correctly) * * --> The buttons next to each field either open a slider * or an envelope editor */ #import <stdlib.h> #import <stdio.h> #import <sys/file.h> #import <appkit/Application.h> #import <appkit/Matrix.h> #import <ctype.h> #import <dpsclient/psops.h> #import <dpsclient/wraps.h> #import <appkit/publicWraps.h> #import <strings.h> #import <musickit/musickit.h> #import <musickit/unitgenerators/AsympUG.h> #import <appkit/TextField.h> #import "FakeSynthPatch.h" #import "FakePatchPoint.h" #import "Controller.h" #import "UGDef.h" #import "UGArgDef.h" #import "UGMethodDef.h" #import "PatchParam.h" #import "Clavier.h" #import "UGArgSlider.h" #import "EnvDelegate.h" #import "EnvController.h" #import "FakeUG.h" #import "Utilities.h" #import "ElementController.h" #import "Controller.h" static char ErrorMsg[1024]; extern char *getAppName(); #define NODESIZE 10 @implementation FakeUG static char TempString[1024]; static int uniquename = 0; + initialize /* Set the version. This can be used in a later version to distinguish older * formats when unarchiving documents. */ { [FakeUG setVersion:5]; return self; } - awakeFromNib { clavInit = NO; clickCount = 0; return self; } - init { int i; [super init]; allocOrder = 1; for (i=0;i<MAXCONNECTIONS;i++) { connections[i]=nil; } for (i=0;i<MAXNOTEPARAMETERS;i++) { arg[i] = NULL; envDelegate[i] = nil; argEnvelope[i] = nil; argEnabled[i] = YES; slider[i] = nil; } isAllocated = NO; strcpy(theName, ""); clavier = nil; midi = nil; noteFilter = nil; patchParam = nil; clickCount = 0; useInspectorRect = NO; inspectorRectJustLoaded = NO; return self; } - takeArgEnableFrom:sender { argEnabled[currArg] = ([sender intValue] ? YES : NO); return self; } - (BOOL) isArgEnabled:(int) num { BOOL rval; if ((num >=0) && (num < MAXNOTEPARAMETERS)) { rval = argEnabled[num]; } else { /* Request was out of bounds */ rval = NO; } return rval; } - takeAllocOrderFrom:sender { int button, order, ival, maxOrder; maxOrder = [[theSP getFakeUGs] count]; order = [self getAllocOrder]; if ([sender isKindOfClassNamed: "TextField"]) { ival = [sender intValue]; if ((ival <= maxOrder) && (ival >=1)) { [self setAllocOrder:order]; [theSP sortFakeUGsByAllocOrder]; [self updateAllocOrder]; } else { NXRunAlertPanel(getAppName(), "Invalid order: %d Must be between 1 and %d", NULL, NULL, NULL, ival, maxOrder); [sender setIntValue:order]; return self; } } else { /* Get order from switcher */ /* button = -1 for top, 1 for bottom */ button = [[sender selectedCell] tag]; order += button; /* Only set a new order if it's within range */ if ((order <= maxOrder) && (order >= 1)) { [self setAllocOrder:order]; [theSP sortFakeUGsByAllocOrder]; [self updateAllocOrder]; } } return self; } - setAllocOrder:(int) order { allocOrder = order; return self; } - (int) getAllocOrder { return allocOrder; } - updateAllocOrder { if (argCount > 0) { [allocOrderField setIntValue:allocOrder]; } else { [allocOrderField2 setIntValue:allocOrder]; } return self; } - setSP:aSP { theSP = aSP; return self; } - getSP { return theSP; } - initWithDef: aUGDef WithPatch:aSP { [self setSP: aSP]; [self initUGDef: aUGDef]; [self initSubviews]; [self setDefaultValues]; [self validate]; return self; } - initUGDef: aUGDef { theUGDef = aUGDef; theMethods = [theUGDef methods]; methodCount = [theMethods count]; theArgs = [theUGDef arguments]; argCount = [theArgs count]; sprintf(theName, "%c%s%i", tolower([self getTypeString][0]), [self getTypeString]+1, uniquename++); theImage = [NXImage findImageNamed:[theUGDef getIconFile]]; if (!theImage) { sprintf(TempString, "Cannot find image for: %s", [theUGDef getName]); NXRunAlertPanel(getAppName(), TempString, NULL, NULL, NULL); return nil; } return self; } - setDefaultValues /* This assumes you called initUGDef first */ { int i; int len; char *aStr; UGArgDef *anArg; if (! [theSP useDefaultArgValues]) { return self; } /* Set the default parameter values * and the right stuff in the inspector */ for (i=0; i<argCount; i++) { anArg = [theArgs objectAt:i]; aStr = [anArg defaultValue]; if (aStr) { len = strlen(aStr); len += 1; if (arg[i]) { NXZoneFree([self zone], arg[i]); } /*ME* Observed malloc error here on load: old save new, load old */ if (NXMallocCheck()) { printf("malloc error!!!!\n"); } arg[i] = (char *) NXZoneCalloc([self zone], len, sizeof(char)); strcpy(arg[i], aStr); } } return self; } - initSubviews /* This assumes you called initUGDef first */ { int i; UGMethodDef *aMethod; for (i=0; i<methodCount; i++) { NXRect *newrect = (NXRect *) NXZoneMalloc([self zone], sizeof (*newrect)); id newnode = [[NodeView alloc] init]; [newnode setPatch:[self thePatch]]; aMethod = [theMethods objectAt:i]; [newnode setTag:i]; [self addSubview:newnode]; NXSetRect(newrect, [aMethod xCoord] - NODESIZE/2, [aMethod yCoord] - NODESIZE/2, NODESIZE,NODESIZE); #ifdef DEBUG_PARAM DEBUG_PRINT("fakeUG %s: Created node with tag %d at x: %d y: %d\n", [self getTypeString], [newnode getTag], [aMethod xCoord], [aMethod yCoord]); #endif DEBUG_PARAM [newnode setFrame:newrect]; [newnode display]; } return self; } - checkSubviews /* This ensures the subview indices are equal to the NodeView tags * This was a problem with old files */ { int i; int nodeViewCount; id nodeView; nodeViewCount = [subviews count]; if (nodeViewCount != methodCount) { sprintf(TempString, "Internal error file: %s line: %d", __FILE__, __LINE__); NXRunAlertPanel(getAppName(), TempString, NULL, NULL, NULL); return self; } for (i=0; i<nodeViewCount; i++) { nodeView = [subviews objectAt:i]; if ( ![nodeView isKindOfClassNamed: "NodeView"]) { sprintf(TempString, "Internal error file: %s line: %d", __FILE__, __LINE__); NXRunAlertPanel(getAppName(), TempString, NULL, NULL, NULL); return self; } [nodeView setTag:i]; } return self; } - displayArg:(int) i { [argName setStringValue:[[[theUGDef arguments] objectAt:i] getName]]; if ([self getArgType:i] == PARTIALS) { /* Can't inspect partials yet */ [argButton setEnabled:NO]; } else { [argButton setEnabled:YES]; } if ([self getArgType:i] == ENV) { /* Don't let the user futs with the envelope field */ [argVal setEditable:NO]; [argVal setSelectable:YES]; } else { [argVal setEnabled:YES]; [argVal setEditable:YES]; } if (! arg[i]) { [argVal setStringValue: ""]; } else { [argVal setStringValue: arg[i]]; } if (argCount > 0) { [argIndexField setIntValue:i+1]; } if (slider[i]) { [slider[i] takeSliderValueFrom:argVal]; } if (argEnabled[i]) { [argEnabledSwitch setIntValue:1]; } else { [argEnabledSwitch setIntValue:0]; } return self; } - checkConnections { int i, j, k; id temp_connections[MAXCONNECTIONS]; id theToNodes; /* Older versions allowed connections[0] * to be non-nil, and the newer versions * don't. Deal with this by re-organizing * the connections array so it has no empty slots * before non-empty slots */ for (i=0; i<MAXCONNECTIONS; i++) { temp_connections[i] = nil; } j = 0; for (i=0; i<MAXCONNECTIONS; i++) { if (connections[i]) { temp_connections[j++] = connections[i]; } } if (j > 0) { #ifdef DEBUG_BACKWARD printf("** Reprocessing %d connections for: %s\n\n", j, [self getName]); #endif DEBUG_BACKWARD for (i=0; i<j; i++) { connections[i] = temp_connections[i]; theToNodes = [connections[i] getToNodes]; #ifdef DEBUG_BACKWARD printf("$$ Set connection[%d] = temp_connection[%d]: %s ToNode ct: %d\n", i, i, [connections[i] getName], (int) [theToNodes count]); #endif DEBUG_BACKWARD for (k=0; k<[theToNodes count]; k++) { #ifdef DEBUG_BACKWARD printf(">> Node: %d tag: %d FakeUG: %s\n", k, [[theToNodes objectAt:k] getTag], [[[theToNodes objectAt:k] superview] getName]); #endif DEBUG_BACKWARD } } for (i=j; i<MAXCONNECTIONS; i++) { connections[i] = nil; #ifdef DEBUG_BACKWARD printf("nilling connection: %d\n", i); #endif DEBUG_BACKWARD } } [self checkSubviews]; #ifdef DEBUG_BACKWARD [self printConnections]; #endif DEBUG_BACKWARD return self; } - printConnections { int i, j; id theToNodes, toFakeUG; for (i=0; i<MAXCONNECTIONS; i++) { if (connections[i]) { printf("%s: Connection: %d from: %s (tag %d) to:", [self getName], i, [[connections[i] getFromFakeUG] getName], [[connections[i] getFromNode] getTag]); theToNodes = [connections[i] getToNodes]; for (j=0; j<[theToNodes count]; j++) { toFakeUG = [[theToNodes objectAt:j] superview]; printf(" %s tag: %d", [toFakeUG getName], [ [theToNodes objectAt:j] getTag]); } printf("\n"); } } return self; } - validate /* Make sure we are together * This is useful to do if we have * just loaded an existing file that may * be out of date, and in the case where the fakeUG * is a Clavier or PatchParameter */ { int aType; isSoundMaker = NO; if (!theUGDef || ![theUGDef isKindOfClassNamed: "UGDef"]) { sprintf(TempString, "Internal error file: %s line: %d", __FILE__, __LINE__); NXRunAlertPanel(getAppName(), TempString, NULL, NULL, NULL); return self; } aType = [theUGDef getMetaType]; /* Check for consistency */ if ( (aType != PP_UG) && (aType != CLAV_UG) && (aType != MIDI_UG)) { /* A little paranoia from a previous bug */ if (!theUGDef || ![theUGDef isKindOfClassNamed: "UGDef"]) { sprintf(TempString, "Internal error file: %s line: %d", __FILE__, __LINE__); NXRunAlertPanel(getAppName(), "Internal error file: %s line: %d", NULL, NULL, NULL); return self; } } theMethods = [theUGDef methods]; methodCount = [theMethods count]; theArgs = [theUGDef arguments]; argCount = [theArgs count]; switch (aType) { case (MK_UG): { isSoundMaker = YES; if (argCount > 0) { currArg = 0; } break; /* Just a regular audio UG */ } case (CLM_UG): { NXRunAlertPanel(getAppName(), "Sorry I cannot deal with CLM UGs yet", NULL, NULL, NULL); break; } case (PP_UG): { /* Allocate a PatchParameter if necessary * When the user double clicks on the icon * the editor scene will "just happen" because * we allocate all the cool stuff here. */ if (! patchParam) { /* New PP */ patchParam = [[PatchParam alloc] init]; [patchParam setPatch:[self thePatch]]; [patchParam setViewFakeUG:self]; [patchParam setPatchParamName:theName]; } else { /* PP just read from file */ [patchParam setPatch:[self thePatch]]; [patchParam setViewFakeUG:self]; } break; } case (CLAV_UG): { if (! clavier) { clavier = [[Clavier alloc] init]; [clavier initConnectionWithPatch:[self thePatch] WithFakeUG: self]; [clavier setClavierName:theName]; } break; } case (MIDI_UG): { midi = [theSP midi]; inspector = nil; noArgInspector = nil; break; } default: { break; } } return self; } - getImage { return theImage; } - (BOOL)getErasing { return erasing; } - (char *)getName { return theName; } - changeName:(char *)aName { int len; if (! [[theSP utilities] checkName:aName]) { [fakeUGName setStringValue:theName]; return nil; } len = strlen(aName) + 1; strcpy(theName, aName); [self setInspectorName:theName]; return self; } - takeNameFrom:sender { [self changeName: (char *)[sender stringValue]]; return self; } - (char *)getTypeString /* This returns a string that indentifies * the unit generator class used to make sound for this FakeUG * The name of the class is based on the root class name * plus "x" if its connections (other than data connections) * are from x memory, and "y" if they are in y-memory. */ { int i; static char s[1024]; /* There is a special case for Biquads. They're output * must be y memory, and they only have leaf classes * with a single x or y. Hence, the only issue * is what memory location the input of the Biquad uses. * If it uses x memory, return BiquadUGx, else return BiquadUGy. */ strcpy(s, [theUGDef getType]); if (strcmp(s, "BiquadUG") == 0) { if (! connections[0] && ! connections[1]) { /* This means the biquad is unconnected */ return "BiquadUG"; } else if ([connections[0] getXMemory] || [connections[1] getXMemory]) { return "BiquadUGx"; } else { return "BiquadUGy"; } } for (i=0; i<[theMethods count]; i++) { if ((connections[i] != nil) && ![self isData]) { if ([connections[i] getXMemory]) { sprintf(s,"%sx",s); } else { sprintf(s,"%sy",s); } } } if ([theUGDef isADSwitch] && connections[1] && connections[2]) { s[strlen(s)-1]='\0'; } return s; } - (char *)getGenericTypeString { return [theUGDef getType]; } - (BOOL)isAFakeUG { /* We have to tell the recepient of a message that uses * a FakeUG object that the object is in fact a FakeUG (late binding in action!) */ return YES; } - (BOOL)isAFakePatchPoint { return NO; } - (char *)getConnectionName:(int)connectionNumber { UGMethodDef *aMethod; aMethod = [theMethods objectAt:connectionNumber]; return [aMethod getName]; } - setConnection:(int)connectionNumber toFakePatchPoint:fakePatchPoint { connections[connectionNumber] = fakePatchPoint; return self; } - getConnection:(int)connectionNumber { return connections[connectionNumber]; } - getUG { return ug; } - (int)getArgType:(int)i { return [[theArgs objectAt:i] argType]; } - allocateUGMK { if (isAllocated) { #ifdef DEBUG_PARAM DEBUG_PRINT("ug: %s already allocated\n", [self getName]); #endif DEBUG_PARAM return self; } if (![self isPatchParameter] && ![self isMidi] && ![self isClavier] && ![self isData]) { ug = [[superview getOrch] allocUnitGenerator:objc_getClass([self getTypeString])]; if (! ug) { sprintf(ErrorMsg, "Is DSP being used by another app? Could not allocate %s", [self getName]); NXRunAlertPanel(getAppName(), ErrorMsg, NULL, NULL, NULL); return nil; } #ifdef DEBUG_PARAM DEBUG_PRINT("*** ug: %s allocated\n", [self getName]); #endif DEBUG_PARAM isAllocated = YES; } return self; } - runMK { if (isSoundMaker) { [ug run]; } return self; } - deallocUGMK { if (isSoundMaker) { [ug finish]; [ug dealloc]; ug = nil; isAllocated = NO; } return self; } - (BOOL)isEnvelopeHandler { return [theUGDef isEnvelopeHandler]; } - (BOOL)isDSwitch { return [theUGDef isADSwitch]; } - (BOOL)isData { return [theUGDef isData]; } - (BOOL)isStorage { return [theUGDef isStorage]; } - (BOOL)isOscg { return [theUGDef isOscg]; } - (BOOL)isSineROM { return [theUGDef isSineROM]; } - (int)getLength { return ([theUGDef hasLength] ? ((arg[0]==NULL) ? 0 : atoi(arg[0])) : 16); } - (BOOL)hasLength { return [theUGDef hasLength]; } - (BOOL)hasConstant { if (! [theUGDef hasConstant]) return NO; if (![self getConstant]) return NO; return YES; } - (char *)getConstant { if ([theUGDef hasLength]) return arg[1]; else return arg[0]; } - setConstantPP:(double) value { int i; id aPP; /* Set the constant for each connection to this * constant PP to value */ for (i=0; i<MAXCONNECTIONS; i++) { if (connections[i]) { aPP = [connections[i] getpp]; if (aPP) { [aPP setToConstant: DSPDoubleToFix24(value)]; } } } return self; } - (BOOL)isComplete /* Returns YES if the fakeUG has all its connections made */ { int i; BOOL rval = YES; if (isSoundMaker) { for (i=0; i<methodCount; i++) { if (!connections[i]) { rval = NO; } } } else { rval = NO; } return rval; } - (BOOL)acceptsFirstMouse { return YES; } - (BOOL)acceptsFirstResponder { return NO; } - drawSelf:(BOOL)instance { NXPoint *thePoint = (NXPoint *)NXZoneMalloc([self zone], sizeof(*thePoint)); int i; thePoint->x = thePoint->y = 0.0; if ([superview getSelected]==self) [theImage composite:NX_COPY toPoint:thePoint]; else [theImage composite:NX_SOVER toPoint:thePoint]; [self unlockFocus]; for (i=0; i<MAXCONNECTIONS; i++) if (connections[i]!=nil) { [connections[i] lockFocus]; if (instance) PSsetinstance(YES); [connections[i] drawSelf:NULL :0]; if (instance) PSsetinstance(NO); [connections[i] unlockFocus]; } [self lockFocus]; return self; } - eraseSelf { int i; NXRect *rect = (NXRect *)NXZoneMalloc ([self zone], sizeof (*rect)); rect->origin.x = frame.origin.x; rect->origin.y = frame.origin.y; rect->size.width = frame.size.width; rect->size.height = frame.size.height; [self convertRectFromSuperview:rect]; PSsetgray(NX_LTGRAY); NXRectFill(rect); for (i=0; i<MAXCONNECTIONS; i++) if (connections[i]!=nil) { [self unlockFocus]; [connections[i] lockFocus]; [connections[i] eraseSelf]; #ifdef DEBUG_ERASE printf("(FakeUG %s - eraseSelf) Erased connection %d pp: %s\n", [self getName], i, [connections[i] getName]); #endif DEBUG_ERASE [connections[i] unlockFocus]; [self lockFocus]; } erasing = YES; [self unlockFocus]; [superview display]; [self lockFocus]; erasing = NO; return self; } - closeInspector { int i; for (i=0; i<MAXNOTEPARAMETERS; i++) { if (slider[i]) { [slider[i] closeInspector]; } if (envDelegate[i]) { [envDelegate[i] closeInspector]; } } if ( (argCount > 0) && inspector) { [inspector performClose:self]; } else if (noArgInspector) { [noArgInspector performClose:self]; } if ([self isPatchParameter]) { [patchParam closeInspector]; } if ([self isClavier]) { [clavier closeInspector]; } inspectorDisplayed = NO; return self; } - removeSelf { int i; [self lockFocus]; [self closeInspector]; [self eraseSelf]; [self unlockFocus]; for (i=0; i<MAXCONNECTIONS; i++) if (connections[i]!=nil) { id temp = connections[i]; [temp removeSelf]; [temp free]; } /* Now fix the envelopes * The next time an envelope inspector comes * up it will use the new envelope we * just read in with a new envDelegate */ for (i=0; i<MAXNOTEPARAMETERS; i++) { if (envDelegate[i]) { [envDelegate[i] free]; envDelegate[i] = nil; } if (argEnvelope[i]) { [argEnvelope[i] free]; argEnvelope[i] = nil; } } if (patchParam) { [patchParam free]; } if ([theUGDef isMidi]) { [theSP setHaveMidi:NO]; } [superview remFakeUGFromList:self]; return self; } - remConnection:(int)i { connections[i]=nil; #ifdef DEBUG_ERASE printf("(FakeUG %s - remConnection) Nilled connection %d\n", [self getName], i); #endif DEBUG_ERASE return self; } - nilConnectionsWithId:aFakePatchPoint { int i; for (i=0; i<MAXCONNECTIONS; i++) { if (connections[i] && (connections[i] == aFakePatchPoint)) { connections[i] = nil; } } return self; } - drawSelf:(const NXRect *)rects :(int)rectCount { if (!erasing) { [self drawSelf:NO]; NXPing(); } return self; } - mouseDown:(NXEvent *)theEvent { mouseUpRespond = YES; [window addToEventMask:NX_LMOUSEDRAGGEDMASK]; noMovement = YES; whereGrabbed = theEvent->location; [self convertPoint:&whereGrabbed fromView:nil]; return self; } - mouseDragged:(NXEvent *)theEvent { NXPoint *location = (NXPoint *) NXZoneMalloc([self zone], sizeof (*location)); NXRect *rect = (NXRect *)NXZoneMalloc ([self zone], sizeof (*rect)); NXRect limits; /* When the user drags on a FakeUG this method gets called twice * the first time it's called noMovement = YES, the second time it gets * set to NO */ if (noMovement) { /* This code just draws the fake UG in the same place it was before * the drag */ noMovement = NO; [self lockFocus]; [self eraseSelf]; PSnewinstance(); PSsetinstance(YES); [self drawSelf:YES]; PSsetinstance(NO); [self unlockFocus]; } location->x = theEvent->location.x; location->y = theEvent->location.y; [superview convertPoint:location fromView:nil]; [superview getBounds:&limits]; if ((location->x >= limits.origin.x) && (location->y >= limits.origin.y) && (location->x <= limits.size.width+limits.origin.x) && (location->y <= limits.size.height+limits.origin.y)) { [self convertPoint:location fromView:superview]; location->x = location->x-whereGrabbed.x; location->y = location->y-whereGrabbed.y; [superview convertPoint:location fromView:self]; [self moveTo:location->x :location->y]; [self lockFocus]; PSnewinstance(); PSsetinstance(YES); /* After this line gets done the terd get's left over */ [self drawSelf:YES]; PSsetinstance(NO); [self unlockFocus]; NXPing(); [window flushWindow]; } return self; } - mouseUp:(NXEvent *)theEvent { NXPoint *location = (NXPoint *) NXZoneMalloc ([self zone], sizeof (*location)); NXRect *rect = (NXRect *)NXZoneMalloc ([self zone], sizeof (*rect)); NXRect limits; if (mouseUpRespond) { mouseUpRespond = NO; if (noMovement) [superview setSelected:self]; else { NXPing(); location->x = theEvent->location.x; location->y = theEvent->location.y; [superview convertPoint:location fromView:nil]; [superview getBounds:&limits]; if ((location->x>=limits.origin.x) && (location->y>=limits.origin.y) && (location->x<=limits.size.width+limits.origin.x) && (location->y<=limits.size.height+limits.origin.y)) { [self convertPoint:location fromView:superview]; location->x = location->x-whereGrabbed.x; location->y = location->y-whereGrabbed.y; [superview convertPoint:location fromView:self]; [self moveTo:location->x :location->y]; } [self lockFocus]; [self drawSelf:NO]; PSnewinstance(); [self unlockFocus]; NXPing(); } [window removeFromEventMask:NX_LMOUSEDRAGGEDMASK]; [window flushWindow]; [superview display]; } return self; } - getInspectorRect:anInspector { if (anInspector) { useInspectorRect = YES; [anInspector getFrame:&inspectorRect]; } else { useInspectorRect = NO; inspectorRect.origin.x = -1; inspectorRect.origin.y = -1; inspectorRect.size.width = -1; inspectorRect.size.height = -1; } return self; } - write:(NXTypedStream *) stream { char *aName; int i; [super write:stream]; NXWriteTypes(stream, "i", &allocOrder); NXWriteTypes(stream, "@", &theUGDef); NXWriteArray(stream, "@", MAXCONNECTIONS, &connections); NXWriteArray(stream, "*", MAXNOTEPARAMETERS, &arg); NXWriteArray(stream, "c", MAXNOTEPARAMETERS, &argEnabled); NXWriteTypes(stream, "@", &theImage); aName = theName; NXWriteTypes(stream, "*", &aName); NXWriteTypes(stream, "@", &patchParam); NXWriteTypes(stream, "@", &clavier); /* Make sure we have the latest envelope happening */ for (i=0; i<MAXNOTEPARAMETERS; i++) { if ([self getArgType:i] == ENV) { [self syncEnvelope:i]; argEnvelope[i] = [envDelegate[i] envelope]; } } NXWriteArray(stream, "@", MAXNOTEPARAMETERS, &argEnvelope); NXWriteArray(stream, "@", MAXNOTEPARAMETERS, &slider); if (argCount > 0) { [self getInspectorRect:inspector]; } else { [self getInspectorRect:noArgInspector]; } NXWriteTypes(stream, "d", &inspectorRect.origin.x); NXWriteTypes(stream, "d", &inspectorRect.origin.y); NXWriteTypes(stream, "d", &inspectorRect.size.width); NXWriteTypes(stream, "d", &inspectorRect.size.height); NXWriteTypes(stream, "c", &useInspectorRect); NXWriteTypes(stream, "c", &inspectorDisplayed); return self; } - read:(NXTypedStream *) stream { int version, old_ug_type, i, len; char *old_arg[9], *old_name; id elementController; [super read:stream]; isAllocated = NO; clavier = nil; midi = nil; allocOrder = 1; if (! theSP) { theSP = [[Controller theController] theSP]; } version = NXTypedStreamClassVersion(stream, "FakeUG"); useInspectorRect = NO; inspectorRectJustLoaded = NO; switch (version) { case(5): { NXReadTypes(stream, "i", &allocOrder); NXReadTypes(stream, "@", &theUGDef); NXReadArray(stream, "@", MAXCONNECTIONS, &connections); NXReadArray(stream, "*", MAXNOTEPARAMETERS, &arg); NXReadArray(stream, "c", MAXNOTEPARAMETERS, &argEnabled); NXReadTypes(stream, "@", &theImage); NXReadTypes(stream, "*", &old_name); NXReadTypes(stream, "@", &patchParam); NXReadTypes(stream, "@", &clavier); NXReadArray(stream, "@", MAXNOTEPARAMETERS, &argEnvelope); NXReadArray(stream, "@", MAXNOTEPARAMETERS, &slider); NXReadTypes(stream, "d", &inspectorRect.origin.x); NXReadTypes(stream, "d", &inspectorRect.origin.y); NXReadTypes(stream, "d", &inspectorRect.size.width); NXReadTypes(stream, "d", &inspectorRect.size.height); NXReadTypes(stream, "c", &useInspectorRect); NXReadTypes(stream, "c", &inspectorDisplayed); inspectorRectJustLoaded = YES; if (old_name) { strcpy(theName, old_name); } else { strcpy(theName, ""); } // [self validate]; break; } case(4): { NXReadTypes(stream, "i", &allocOrder); NXReadTypes(stream, "@", &theUGDef); NXReadArray(stream, "@", MAXCONNECTIONS, &connections); NXReadArray(stream, "*", MAXNOTEPARAMETERS, &arg); NXReadArray(stream, "c", MAXNOTEPARAMETERS, &argEnabled); NXReadTypes(stream, "@", &theImage); NXReadTypes(stream, "*", &old_name); NXReadTypes(stream, "@", &patchParam); NXReadTypes(stream, "@", &clavier); NXReadArray(stream, "@", MAXNOTEPARAMETERS, &argEnvelope); NXReadTypes(stream, "d", &inspectorRect.origin.x); NXReadTypes(stream, "d", &inspectorRect.origin.y); NXReadTypes(stream, "d", &inspectorRect.size.width); NXReadTypes(stream, "d", &inspectorRect.size.height); NXReadTypes(stream, "c", &useInspectorRect); NXReadTypes(stream, "c", &inspectorDisplayed); inspectorRectJustLoaded = YES; if (old_name) { strcpy(theName, old_name); } else { strcpy(theName, ""); } // [self validate]; break; } case(3): { NXReadTypes(stream, "i", &allocOrder); NXReadTypes(stream, "@", &theUGDef); NXReadArray(stream, "@", MAXCONNECTIONS, &connections); NXReadArray(stream, "*", MAXNOTEPARAMETERS, &arg); NXReadArray(stream, "c", MAXNOTEPARAMETERS, &argEnabled); NXReadTypes(stream, "@", &theImage); NXReadTypes(stream, "*", &old_name); NXReadTypes(stream, "@", &patchParam); NXReadTypes(stream, "@", &clavier); NXReadArray(stream, "@", MAXNOTEPARAMETERS, &argEnvelope); if (old_name) { strcpy(theName, old_name); } else { strcpy(theName, ""); } // [self validate]; break; } case(2): { NXReadTypes(stream, "i", &allocOrder); NXReadTypes(stream, "@", &theUGDef); NXReadArray(stream, "@", MAXCONNECTIONS, &connections); NXReadArray(stream, "*", MAXNOTEPARAMETERS, &arg); NXReadTypes(stream, "@", &theImage); NXReadTypes(stream, "*", &old_name); NXReadTypes(stream, "@", &patchParam); NXReadTypes(stream, "@", &clavier); NXReadArray(stream, "@", MAXNOTEPARAMETERS, &argEnvelope); if (old_name) { strcpy(theName, old_name); } else { strcpy(theName, ""); } for (i=0; i<MAXNOTEPARAMETERS; i++) { argEnabled[i] = YES; } // [self validate]; break; } default: { /* Old versions didn't have versioning */ NXReadArray(stream, "@", 5, &connections); for (i=0; i<9; i++) { old_arg[i] = NULL; } NXReadArray(stream, "*", 9, &old_arg); NXReadTypes(stream, "@i*ccc", &theImage, &old_ug_type, &old_name, &noMovement, &erasing, &mouseUpRespond); if (old_name) { strcpy(theName, old_name); } else { strcpy(theName, ""); } /* Convert typeOfFakeUG to a UGDef * This will set all the default values in theUGDef */ elementController = [[theSP theController] elementController]; [self initUGDef: [elementController oldUGTypeToUGDef: old_ug_type]]; [self setDefaultValues]; for (i=0; i<MAXNOTEPARAMETERS; i++) { argEnabled[i] = YES; } // [self validate]; /* Now set the old argument values into the new arg */ for (i=0; i<9; i++) { if (old_arg[i]) { len = strlen(old_arg[i]); if (len > 0) { len += 10; /* for good measure */ if (arg[i]) { NXZoneFree([self zone], arg[i]); } arg[i] = (char *) NXZoneCalloc([self zone], len, sizeof(char)); strcpy(arg[i], old_arg[i]); } else { /* Pathological */ len = 2; if (arg[i]) { NXZoneFree([self zone], arg[i]); } arg[i] = (char *) NXZoneCalloc([self zone], len, sizeof(char)); strcpy(arg[i], ""); } } } } } /* Make sure all the envelopes are synced */ for (i=0; i<MAXNOTEPARAMETERS; i++) { if (envDelegate[i]) { [envDelegate[i] free]; envDelegate[i] = nil; } [self syncEnvelope:i]; } return self; } - (STR)getArgCast:(int)type; { char *cast; switch (type) { case(INT): { cast = "(int)"; break; } case(DOUBLE): { cast = "(double)"; break; } case(BOOLEAN): { cast = "(BOOL)"; break; } default: { cast = NULL; } } return(cast); } - (STR)getArgTypeStr:(int)type; { char *cast; switch (type) { case(INT): { cast = "int"; break; } case(DOUBLE): { cast = "double"; break; } case(BOOLEAN): { cast = "BOOL"; break; } case(ENV): { cast = "ENV"; break; } case(DSPDATUM): { cast = "DSPDATUM"; break; } case(PARTIALS): { cast = "PARTIALS"; break; } default: { cast = NULL; } } return(cast); } - (int)getUGTarget { return [theUGDef getMetaType]; } - (BOOL)isPatchParameter { return [theUGDef isPatchParameter]; } - (BOOL)isClavier { return [theUGDef isClavier]; } - (BOOL)isMidi { return [theUGDef isMidi]; } - (BOOL)isNoteFilter { return [theUGDef isNoteFilter]; } - thePatch { return theSP; } - clavier /* Called by FakeSynthPatch when a clavier icon is clicked on */ { if ([self isClavier]) { if (clavier) { /* From an archived object */ if (! clavInit) { [clavier initConnectionWithPatch:[self thePatch] WithFakeUG: self]; clavInit = YES; } } else { /* A new one */ clavier = [[Clavier alloc] init]; [clavier initConnectionWithPatch:[self thePatch] WithFakeUG: self]; [clavier setClavierName:theName]; } return clavier; } else { return nil; } } - midi { return midi; } - noteFilter { return noteFilter; } - patchParam { return patchParam; } - (BOOL) isSoundMaker { return isSoundMaker; } - setInspectorName:(char *) aName { int i; if (argCount > 0) { [inspector setTitle: aName]; } else { [noArgInspector setTitle: aName]; } for (i=0;i<MAXNOTEPARAMETERS;i++) { [slider[i] updateInspectorTitle]; } return self; } - switchArg:sender /* Change the argument being displayed on the inspector */ { int button; /* button = -1 for top, 1 for bottom */ button = [[sender selectedCell] tag]; currArg += button; if (currArg < 0) { currArg = argCount - 1; } else if (currArg == argCount) { currArg = 0; } [self displayArg:currArg]; return self; } - displayInspector { char *nibFile; if ([self isPatchParameter]) { [[self patchParam] displayInspector]; } else if ([self isClavier]) { [clavier displayInspector]; } else { if (! inspector) { nibFile = [theUGDef getNibFile]; if (! nibFile) { if (! [self isMidi]) { NXRunAlertPanel(getAppName(), "No nib file defined for: %s", NULL, NULL, NULL, [theUGDef getName]); } return nil; } [NXApp loadNibSection:nibFile owner:self withNames:NO]; [self displayArg:currArg]; [argIndexField setIntValue:argCount]; } if (argCount > 0) { [self updateAllocOrder]; [fakeUGName setStringValue: theName]; [fakeUGType setStringValue:[self getTypeString]]; [argCountField setIntValue:[self getArgCount]]; [argIndexField setIntValue:currArg+1]; [self setInspectorName:theName]; [self bringUpInspector:inspector]; } else { [self updateAllocOrder]; [fakeUGNameNoArg setStringValue: theName]; [fakeUGTypeNoArg setStringValue:[self getTypeString]]; [self setInspectorName:theName]; [self bringUpInspector:noArgInspector]; } } inspectorDisplayed = YES; return self; } - displayInspectorIfWasActive { if ([self isPatchParameter]) { [[self patchParam] displayInspectorIfWasActive]; } else if ([self isClavier]) { [clavier displayInspectorIfWasActive]; } else { if (inspectorDisplayed) { [self displayInspector]; } } return self; } - inspectorClosed /* Called by the inspector's delegate */ { inspectorDisplayed = NO; return self; } - bringUpInspector:anInspector { int i; if (inspectorRectJustLoaded) { if (useInspectorRect) { [anInspector placeWindowAndDisplay:&inspectorRect]; useInspectorRect = NO; } inspectorRectJustLoaded = NO; for (i=0; i<MAXNOTEPARAMETERS; i++) { if (slider[i]) { [slider [i] initFromFakeUG: self ArgNum: i ArgField: argVal ArgType: [[theArgs objectAt:i] argType] ]; [slider[i] displayInspector]; } } } /* doHighlight toggle prevents the instance * from being highlighted twice */ doHighlight = NO; [anInspector makeKeyAndOrderFront:self]; doHighlight = YES; return self; } - takeArgFromInspector:sender /* This is called when a return is hit in a cell in argVal */ { [self setArgWithIndex: currArg To: (char *) [sender stringValue]]; if (slider[currArg]) { [slider[currArg] takeSliderValueFrom:argVal]; } return self; } - inspectArg:sender { if ([[theArgs objectAt:currArg] argType] == ENV) { [self displayEnvelope:currArg]; [self displayArg:currArg]; } else { if (! slider[currArg]) { slider[currArg] = [[UGArgSlider alloc] init]; [slider [currArg] initFromFakeUG: self ArgNum: currArg ArgField: argVal ArgType: [[theArgs objectAt:currArg] argType] ]; } [slider[currArg] displayInspector]; } return self; } - syncEnvelope:(int) i { if ([self getArgType:i] != ENV) { return nil; } if (! envDelegate[i]) { envDelegate[i] = [[EnvDelegate alloc] init]; } [envDelegate[i] setFakeUG:self ArgNum: i]; [envDelegate[i] setPatchParameter:nil]; if (! argEnvelope[i] && arg[i]) { /* The argument was set but the Envelope object was * never initialized */ argEnvelope[i] = [envDelegate[i] textToEnvelope:arg[i]]; } return self; } - createDefaultEnvelope:(int) i { static double x[3]; static double y[3]; static double s[3]; int pointCount = 3; int stickPoint = 1; double orSamplingPeriod = 1.0; double orDefaultSmoothing = 1.0; Envelope *anEnv; /* Create the default Envelope */ x[0] = 0; y[0] = 0; x[1] = .5; y[1] = 1.0; x[2] = 1; y[2] = 0; s[0] = 1.0; s[1] = 1.0; s[2] = 1.0; anEnv = [[Envelope alloc] init]; [anEnv setPointCount: pointCount xArray: x orSamplingPeriod: orSamplingPeriod yArray: y smoothingArray: s orDefaultSmoothing: orDefaultSmoothing]; [anEnv setStickPoint:stickPoint]; argEnvelope[i] = anEnv; return self; } - displayEnvelope:(int) i { id envController; char *ptr; int val; [self syncEnvelope:i]; if (argEnvelope[i]) { envController = [envDelegate[i] envController]; [envController setNewEnvelope:argEnvelope[i]]; [envController reScaleLimits:self]; [envController makeGraphType:1]; [envController reScaleLimits:self]; } else { val = NXRunAlertPanel(getAppName(), "No envelope defined. Create default envelope?", "YES", /* default */ "NO", /* alt */ "Cancel"); /* other */ switch (val) { case(NX_ALERTDEFAULT): { [self createDefaultEnvelope:i]; envController = [envDelegate[i] envController]; [envController setNewEnvelope:argEnvelope[i]]; [envController reScaleLimits:self]; [envController makeGraphType:1]; [envController reScaleLimits:self]; break; } case(NX_ALERTALTERNATE): { break; } default: { return self; } } } sprintf(ErrorMsg, "%s %s", theName, [self getArgName:i]); [envDelegate[i] displayWindow:ErrorMsg]; if (arg[i]) { NXZoneFree([self zone], arg[i]); arg[i] = NULL; } if (argEnvelope[i]) { ptr = [[theSP utilities] envelopeToText:argEnvelope[i]]; if (ptr) { arg[i] = (char *) NXZoneCalloc ([self zone], 1+strlen(ptr), sizeof(char)); strcpy(arg[i], ptr); } } [self displayArg:i]; return self; } - inspector { return inspector; } - setArg: (int) argnum To:(char *) value /* This gets called when the inspector field is touched * directly */ { currArg = argnum; [self setArgWithIndex: currArg To:value]; /* Update the inspector */ [self displayArg:argnum]; return self; } - setArgWithIndex:(int) argnum To:(char*) value { #ifdef DEBUG_PARAM DEBUG_PRINT("FakeUG:setArgWithIndex:%d To:%s\n", argnum, value); #endif DEBUG_PARAM if (! value) { if (arg[argnum]) { NXZoneFree([self zone], arg[argnum]); } arg[argnum] = NULL; } else { const char *temp = value; if (arg[argnum]) { NXZoneFree([self zone], arg[argnum]); } arg[argnum] = (char *) NXZoneCalloc ([self zone], 1+strlen(temp), sizeof(char)); strcpy(arg[argnum], temp); } [self syncEnvelope:argnum]; #ifdef DEBUG_PARAM DEBUG_PRINT("setArgWithIndex:To: Sending %s to arg %d and updating inspector\n", arg[argnum], argnum); #endif DEBUG_PARAM [self sendArg:argnum]; return self; } - setArg:(int)i WithEnvelope:anEnv { char *ptr; if ([self getArgType:i] == ENV) { argEnvelope[i] = anEnv; } if (arg[i]) { NXZoneFree([self zone], arg[i]); arg[i] = NULL; } ptr = [[theSP utilities] envelopeToText:argEnvelope[i]]; if (ptr) { arg[i] = (char *) NXZoneCalloc ([self zone], 1+strlen(ptr), sizeof(char)); strcpy(arg[i], ptr); } [self displayArg:i]; [self sendArg:i]; return self; } - sendArg:(int) num { if (isSoundMaker) { if (argEnabled[num]) { [theSP setUGParameterFromFakeUG:self argNum:num]; } else { if ([self getArgType:num] == ENV) { /* Dis-associate the current envelope from the asymp */ if (ug) { [ug abortEnvelope]; } } } } return self; } - (STR)getArg:(int)i { return arg[i]; } - getArgEnvelope:(int)i { id envCopy; if ([self getArgType:i] == ENV) { /* Return a copy of the latest envelope */ if (argEnvelope[i]) { envCopy = [argEnvelope[i] copy]; } else { envCopy = nil; } return envCopy; } return nil; } - clearArgEnvelope:(int)i { argEnvelope[i] = nil; if (arg[i]) { NXZoneFree([self zone], arg[i]); arg[i] = NULL; } [self displayArg:i]; return self; } - willAddEnvelope:(int)i { if ( !([self getArgType:i] == ENV)) { return self; } if (ug) { [ug abortEnvelope]; [theSP enableNoteOff:NO]; } return self; } - willRemoveEnvelope:(int)i { if ( !([self getArgType:i] == ENV)) { return self; } if (ug) { [ug abortEnvelope]; [theSP enableNoteOff:NO]; } return self; } - (int) methodCount { return methodCount; } - (int) getArgCount { return argCount; } - (char *)getMethod:(int)i { return [[theMethods objectAt:i] getName]; } - (char *)getArgName:(int)i { return [[theArgs objectAt:i] getName]; } - (BOOL) isMethodAnOutput:(int)i { return [[theMethods objectAt:i] isOutput]; } - printSelf { int i; int connectionCount = 0; for (i=0; i<MAXCONNECTIONS; i++) { if (connections[i]!=nil) { connectionCount++; } } printf("+++++++++++++++++++++++++++++++++++++++++++++\n\n"); printf("- (FakeUG %s) connections: %d\n", [self getName], connectionCount); for (i=0; i<methodCount; i++) { printf("method %d: %s\n", i, [self getMethod:i]); } for (i=0; i<argCount; i++) { printf("arg %d %s: %s\n", i, [self getArgName:i], arg[i]); } for (i=0; i<connectionCount; i++) { [connections[i] printSelf]; } return self; } - displayIfDoubleClick { if ([self isPatchParameter]) { [[self patchParam] displayIfDoubleClick]; } else if ([self isClavier]) { [[self clavier] displayIfDoubleClick]; } else { clickCount++; if (clickCount >= 2) { clickCount = 0; [self displayInspector]; } } return self; } - highlightSelf { if ( (![theSP windowMiniaturized]) && doHighlight) { [theSP setSelected:self]; [window removeFromEventMask:NX_LMOUSEDRAGGEDMASK]; [window flushWindow]; [theSP display]; } return self; } - setDoHighlight:(BOOL) flag { doHighlight = flag; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.