This is PatchParam.m in view mode; [Download] [Up]
/************************************************** * SynthBuilder * Copyright 1993 Nick Porcaro All Rights Reserved **************************************************/ #define DEBUG_PRINT printf /* * PatchParam.m * Nick Porcaro Summer 1993 */ #import <stdlib.h> #import <sys/param.h> #import <dsp/dsp.h> #import <strings.h> #import <appkit/Application.h> #import <appkit/View.h> #import <appkit/Panel.h> #import <appkit/PopUpList.h> #import <appkit/Control.h> #import <appkit/Slider.h> #import <appkit/Matrix.h> #import <appkit/TextField.h> #import <musickit/Midi.h> #import <musickit/Conductor.h> #import <musickit/Envelope.h> #import "PatchParam.h" #import "FakeSynthPatch.h" #import "FakeUG.h" #import "EnvDelegate.h" #import "EnvController.h" #import "ParamInterface.h" /* #import "EnvelopeGraphView.h" */ #import "Utilities.h" extern char *getAppName(); @implementation PatchParam static char ErrorMsg[1024]; + initialize /* Set the version. This can be used in a later version to distinguish older * formats when unarchiving documents. */ { [PatchParam setVersion:5]; return self; } - awakeFromNib { ugSelectorPop = [ugSelector target]; [inputInterface setMode:CONTROLS]; [ugSelectorPop setTarget:self]; [ugSelectorPop setAutoupdate:YES]; [ugSelectorPop changeButtonTitle:YES]; [ugSelectorPop setAction:@selector(selectFakeUG:)]; argSelectorPop = [argSelector target]; [argSelectorPop setTarget:self]; [argSelectorPop setAction:@selector(selectArg:)]; [argSelectorPop setAutoupdate:YES]; [argSelectorPop changeButtonTitle:YES]; clickCount = 0; currNoteCount = 0; return self; } - init /* This reads in the nib file for dealing with a PatchParam * Make sure you call setPatch after this or the mapper will not work * So here's an example of how you create one of these objects * (in this example self is a FakeUG): * * patchParam = [[PatchParam alloc] init]; * [patchParam setPatch:[self thePatch]]; * [patchParam setPatchParamName:name]; */ { [super init]; [self addNoteReceiver:[[NoteReceiver alloc] init]]; /* Create a new patch param inspector * for the patchParam in this FakeUG. * We load the nib section each time so * we can get multiple patchParamInspector panels */ [NXApp loadNibSection:"PatchParam.nib" owner:self withNames:YES]; /* The correct values are set in the nib file fields to * reflect the following: */ midiController = 0; strcpy(midiControllerName,"Off"); midiCtrlScaleVal = 1.0; minMidiCtrlScaleVal = 0.0; maxMidiCtrlScaleVal = 2.0; midiCtrlOffsetVal = 0.0; minMidiCtrlOffsetVal = 0.0; maxMidiCtrlOffsetVal = 127.0; noteTypeToControl = MK_noteOn; [offsetSlider setDoubleValue:midiCtrlOffsetVal]; [offsetSlider setMinValue:minMidiCtrlOffsetVal]; [offsetSlider setMaxValue:maxMidiCtrlOffsetVal]; [scaleSlider setDoubleValue:midiCtrlScaleVal]; [scaleSlider setMinValue:minMidiCtrlScaleVal]; [scaleSlider setMaxValue:maxMidiCtrlScaleVal]; mapEnvelope = nil; envDelegate = nil; theFakeUG = nil; clickCount = 0; [self syncMapEnvelope]; paramEnabled = YES; useInspectorRect = NO; inspectorRectJustLoaded = NO; currNoteCount = 0; thinEnabled = NO; thinFactor = 1; // No thinning return self; } - takeParamEnabled:sender { paramEnabled = ([sender intValue] ? YES : NO); return self; } - takeThinFactor:sender { thinFactor = [sender intValue]; return self; } - takeThinEnable:sender { thinEnabled = ([sender intValue] ? YES : NO); return self; } - free /* Usually called by the FakeUG associated with this PatchParam */ { if (envDelegate) { [envDelegate free]; envDelegate = nil; } if (mapEnvelope) { [mapEnvelope free]; mapEnvelope = nil; } return self; } - setPatchParamName: (char *) aName { if (! [[thePatch utilities] checkName:aName]) { if (thePPName) { [thePPName setStringValue:theName]; } return nil; } strcpy(theName, aName); return self; } - (char *) getName; { return theName; } - setPatch:aPatch { thePatch = aPatch; fakeUGs = [thePatch getFakeUGs]; return self; } - setViewFakeUG:aFakeUG { theViewFakeUG = aFakeUG; return self; } - thePatch { return thePatch; } - setInspectorTitles { if (inspector) { [inspector setTitle:""]; [inspector setTitle:theName]; [thePPName setStringValue:theName]; } return self; } - takeNameFrom:sender { if (![sender stringValue]) { NXRunAlertPanel(getAppName(), "Invalid name", NULL, NULL, NULL); return self; } [self setPatchParamName: (char *) [sender stringValue]]; [self setInspectorTitles]; return self; } - takeMidiCtrlFrom:sender { char *sys_str, *user_str; int num; if ([sender isKindOfClassNamed: "TextField"]) { /* This came from the user. so be paranoid */ user_str = (char *) [sender stringValue]; sys_str = [paramInterface validControlName: user_str Number: &num]; if (sys_str) { midiController = num; [sender setStringValue:sys_str]; /* Make the case correct */ strcpy(midiControllerName, sys_str); } else { NXRunAlertPanel(getAppName(), "Invalid controller", NULL, NULL, NULL); } } else { /* a "trusted" source */ midiController = [sender intValue]; strcpy(midiControllerName, (char *)[midiCtrlField stringValue]); } midiControllerAsMKParm = [paramInterface MidiParamAsMK:midiController]; return self; } - takeScaleFrom:sender { midiCtrlScaleVal = [sender doubleValue]; [sender setDoubleValue:midiCtrlScaleVal]; [scaleSlider setDoubleValue:midiCtrlScaleVal]; [midiCtrlScale setDoubleValue:midiCtrlScaleVal]; if (midiCtrlScaleVal > maxMidiCtrlScaleVal) { maxMidiCtrlScaleVal = midiCtrlScaleVal; [maxMidiCtrlScale setDoubleValue:maxMidiCtrlScaleVal]; [scaleSlider setMaxValue:maxMidiCtrlScaleVal]; } else if (midiCtrlScaleVal < minMidiCtrlScaleVal) { minMidiCtrlScaleVal = midiCtrlScaleVal; [minMidiCtrlScale setDoubleValue:minMidiCtrlScaleVal]; [scaleSlider setMinValue:minMidiCtrlScaleVal]; } return self; } - takeMinScaleFrom:sender { minMidiCtrlScaleVal = [sender doubleValue]; if (midiCtrlScaleVal < minMidiCtrlScaleVal) { midiCtrlScaleVal = minMidiCtrlScaleVal; [midiCtrlScale setDoubleValue:midiCtrlScaleVal]; [scaleSlider setDoubleValue:midiCtrlScaleVal]; } [scaleSlider setMinValue:minMidiCtrlScaleVal]; [sender setDoubleValue:minMidiCtrlScaleVal]; return self; } - takeMaxScaleFrom:sender { maxMidiCtrlScaleVal = [sender doubleValue]; if (midiCtrlScaleVal > maxMidiCtrlScaleVal) { midiCtrlScaleVal = maxMidiCtrlScaleVal; [midiCtrlScale setDoubleValue:midiCtrlScaleVal]; [scaleSlider setDoubleValue:midiCtrlScaleVal]; } [scaleSlider setMaxValue:maxMidiCtrlScaleVal]; [sender setDoubleValue:maxMidiCtrlScaleVal]; return self; } - takeOffsetFrom:sender { midiCtrlOffsetVal = [sender doubleValue]; [sender setDoubleValue:midiCtrlOffsetVal]; [offsetSlider setDoubleValue:midiCtrlOffsetVal]; [midiCtrlOffset setDoubleValue:midiCtrlOffsetVal]; if (midiCtrlOffsetVal > maxMidiCtrlOffsetVal) { maxMidiCtrlOffsetVal = midiCtrlOffsetVal; [maxMidiCtrlOffset setDoubleValue:maxMidiCtrlOffsetVal]; [offsetSlider setMaxValue:maxMidiCtrlOffsetVal]; } else if (midiCtrlOffsetVal < minMidiCtrlOffsetVal) { minMidiCtrlOffsetVal = midiCtrlOffsetVal; [minMidiCtrlOffset setDoubleValue:minMidiCtrlOffsetVal]; [offsetSlider setMinValue:minMidiCtrlOffsetVal]; } return self; } - takeMinOffsetFrom:sender { minMidiCtrlOffsetVal = [sender doubleValue]; if (midiCtrlOffsetVal < minMidiCtrlOffsetVal) { midiCtrlOffsetVal = minMidiCtrlOffsetVal; [midiCtrlOffset setDoubleValue:midiCtrlOffsetVal]; [offsetSlider setDoubleValue:midiCtrlOffsetVal]; } [offsetSlider setMinValue:minMidiCtrlOffsetVal]; [sender setDoubleValue:minMidiCtrlOffsetVal]; return self; } - takeMaxOffsetFrom:sender { maxMidiCtrlOffsetVal = [sender doubleValue]; if (midiCtrlOffsetVal > maxMidiCtrlOffsetVal) { midiCtrlOffsetVal = maxMidiCtrlOffsetVal; [midiCtrlOffset setDoubleValue:midiCtrlOffsetVal]; [offsetSlider setDoubleValue:midiCtrlOffsetVal]; } [offsetSlider setMaxValue:maxMidiCtrlOffsetVal]; [sender setDoubleValue:maxMidiCtrlOffsetVal]; return self; } - takeMapEnableFrom:sender { if ([sender intValue]) { mapEnabled = YES; } else { mapEnabled = NO; } return self; } - displayInspector { NXRect virginRect; if ([thePatch hasControllableSoundMakers]) { if (! inspector) { [NXApp loadNibSection:"PatchParam.nib" owner:self withNames:YES]; [inspector getFrame:&virginRect]; } if (inspectorRectJustLoaded) { if (useInspectorRect) { [inspector placeWindowAndDisplay:&inspectorRect]; useInspectorRect = NO; } inspectorRectJustLoaded = NO; } else { inspectorRect = virginRect; } [self updateUgSelector]; [self updateArgSelector]; if (midiController) { [midiCtrlField setStringValue:midiControllerName]; } [midiCtrlField setStringValue:midiControllerName]; [midiCtrlScale setDoubleValue:midiCtrlScaleVal]; [minMidiCtrlScale setDoubleValue:minMidiCtrlScaleVal]; [maxMidiCtrlScale setDoubleValue:maxMidiCtrlScaleVal]; [midiCtrlOffset setDoubleValue:midiCtrlOffsetVal]; [minMidiCtrlOffset setDoubleValue:minMidiCtrlOffsetVal]; [maxMidiCtrlOffset setDoubleValue:maxMidiCtrlOffsetVal]; [offsetSlider setDoubleValue:midiCtrlOffsetVal]; [offsetSlider setMaxValue:maxMidiCtrlOffsetVal]; [offsetSlider setMinValue:minMidiCtrlOffsetVal]; [scaleSlider setDoubleValue:midiCtrlScaleVal]; [scaleSlider setMaxValue:maxMidiCtrlScaleVal]; [scaleSlider setMinValue:minMidiCtrlScaleVal]; if (mapEnabled) { [enableSwitch setIntValue:1]; } else { [enableSwitch setIntValue:0]; } if (paramEnabled) { [paramEnabledSwitch setIntValue:1]; } else { [paramEnabledSwitch setIntValue:0]; } [thinField setIntValue:thinFactor]; if (thinEnabled) { [thinSwitch setIntValue:1]; } else { [thinSwitch setIntValue:0]; } [self setInspectorTitles]; /* This line adds the PatchParam panel to the WindowsMenu * This happens automatically for FakePatchPoints and FakeUGs * (maybe because they are separate Views?). * When the user closes the PatchParam inspector, this * item is automatically removed from the WindowsMenu * (presumably by NXApp) */ [NXApp addWindowsItem: inspector title:[self getName] filename:NO]; /* doHighlight toggle prevents the instance * from being highlighted twice */ doHighlight = NO; [theViewFakeUG setDoHighlight:NO]; [inspector makeKeyAndOrderFront:self]; inspectorDisplayed = YES; doHighlight = YES; [theViewFakeUG setDoHighlight:YES]; } else { NXRunAlertPanel(getAppName(), "This patch has no controllable unit generators", NULL, NULL, NULL); } return self; } - selectFakeUG:sender /* This sets the theFakeUG * based on the selection from the ugSelectorPop */ { char *name; name = (char *) [ugSelectorPop selectedItem]; [self setFakeUG:name]; [self perform:@selector(updateUgSelector) with:nil afterDelay:0 cancelPrevious:NO]; [self perform:@selector(updateArgSelector) with:nil afterDelay:0 cancelPrevious:NO]; return self; } - selectArg:sender /* This sets the theArg * based on the selection from the argSelectorPop */ { char *name; name = (char *) [argSelectorPop selectedItem]; [self setArg:name]; return self; } - takeNoteType:sender { switch ([[sender selectedCell] tag]) { case (0): { noteTypeToControl = MK_noteOn; break; } case (1): { noteTypeToControl = MK_noteOff; break; } case (2): { noteTypeToControl = MK_noteUpdate; break; } default: { noteTypeToControl = MK_noteOn; break; } } return self; } - setFakeUG:(char *) name /* This sets theFakeUG */ { theFakeUG = [self getFakeUG:name]; return self; } - getFakeUG:(char *) name /* This returns the id named FakeUG * in the List fakeUGs */ { int count, i; char *old_name; /* Yeah, I could do this with a Hash, but there * are typically less than 20 FakeUGs in a patch * so a cheezy linear search doesn't hurt us. */ count = [fakeUGs count]; for (i=0; i<count; i++) { old_name = [ [fakeUGs objectAt:i] getName]; if (old_name) { if (strcmp(old_name, name) == 0) { #ifdef DEBUG_PARAM DEBUG_PRINT("found %s in list of existing fakeUGs\n", old_name); #endif DEBUG_PARAM return [fakeUGs objectAt:i]; break; } } } return nil; } - updateUgSelector /* * Update the list of available FakeUGs that * can be controlled by the this parameter */ { int count, i, availUG = -1; char *name; id aFakeUG; count = [ugSelectorPop count]; for (i = count-1; i >= 0; i--) { [[ugSelectorPop removeItemAt:i] free]; } fakeUGs = [thePatch getFakeUGs]; count = [fakeUGs count]; for (i=0; i<count; i++) { aFakeUG = [fakeUGs objectAt:i]; if ([aFakeUG isSoundMaker] && [aFakeUG getArgCount]) { name = [[fakeUGs objectAt:i] getName]; availUG = i; [ugSelectorPop addItem:name]; } } if (! theFakeUG && (availUG >= 0)) { /* If we got this far, we are assured object 0 exists and * is legit */ theFakeUG = [fakeUGs objectAt:availUG]; } if (theFakeUG) { [ugSelector setTitle:[theFakeUG getName]]; } else { /* Should never ever happen */ theFakeUG = nil; [ugSelector setTitle:""]; } return self; } - inspectorClosed /* Called by the inspector's delegate */ { inspectorDisplayed = NO; return self; } - closeInspector { [inspector performClose:self]; if (envDelegate) { [envDelegate closeInspector]; } return self; } - highlightSelf { if ( (![thePatch windowMiniaturized]) && doHighlight) { [theViewFakeUG highlightSelf]; } return self; } - setArg:(char *) name /* This sets theArg */ { /* The theArg cannot be set unless the * theFakeUG is set */ if (! theFakeUG) { NXRunAlertPanel(getAppName(), "Select UG to control first", NULL, NULL, NULL); return self; } theArg = [self getIndexForArg:name FromFakeUG:theFakeUG]; if (theArg < 0) { /* snafu */ sprintf(ErrorMsg, "Unexpected theArg file: %s line: %d\n", __FILE__, __LINE__); NXRunAlertPanel(getAppName(), ErrorMsg, NULL, NULL, NULL); return self; } return self; } - (int) getIndexForArg:(char *) name FromFakeUG:aFakeUG /* This returns the index of the arg named "name" * in aFakeUG */ { int i; char *aName; for (i=0; i<[aFakeUG getArgCount]; i++) { aName = [aFakeUG getArgName:i]; if (strcmp(aName, name) == 0) { #ifdef DEBUG_PARAM DEBUG_PRINT("Found arg: %s (index %d)\n", aName, i); #endif DEBUG_PARAM return i; break; } } return -1; } - updateArgSelector /* Update the list of args for theFakeUG */ { int count, i; count = [argSelectorPop count]; for (i = count-1; i >= 0; i--) { [[argSelectorPop removeItemAt:i] free]; } if (! theFakeUG) { return self; } for (i=0; i<[theFakeUG getArgCount]; i++) { [argSelectorPop addItem:[theFakeUG getArgName:i]]; } [argSelector setTitle:[theFakeUG getArgName:theArg]]; return self; } - createDefaultMapEnvelope { static double x[150], y[150], s[150]; int i, npoints; npoints = 0; for (i=0; i<127; i++) { if ((i % 5) == 0) { x[npoints] = (double) i; y[npoints] = (double) i; s[npoints] = 1.0; npoints++; } } x[0] = 0; y[0] = 0; s[0] = 1.0; x[npoints-1] = 127; y[npoints-1] = 127; s[npoints-1] = 1.0; mapEnvelope = [[[Envelope alloc] init] setPointCount: npoints xArray: x orSamplingPeriod: 1.0 yArray: y smoothingArray: s orDefaultSmoothing: 1.0 ]; return self; } - syncMapEnvelope { if (! envDelegate) { envDelegate = [[EnvDelegate alloc] init]; } [envDelegate setPatchParameter:self]; [envDelegate setFakeUG:nil ArgNum:-1]; return self; } - clearMapEnvelope { mapEnvelope = nil; return self; } - setMapEnvelope:anEnv { mapEnvelope = anEnv; return self; } - displayMapEnvelope:sender { id envController; int val; [self syncMapEnvelope]; if (mapEnvelope) { envController = [envDelegate envController]; [envController setNewEnvelope:mapEnvelope]; [envController reScaleLimits:self]; [envController makeGraphType:0]; } else { val = NXRunAlertPanel(getAppName(), "No lookup table defined. Create default lookup table?", "YES", /* default */ "NO", /* alt */ "Cancel"); /* other */ switch (val) { case(NX_ALERTDEFAULT): { [self createDefaultMapEnvelope]; envController = [envDelegate envController]; [envController setNewEnvelope:mapEnvelope]; [envController reScaleLimits:self]; [envController makeGraphType:0]; [envController reScaleLimits:self]; break; } case(NX_ALERTALTERNATE): { break; } default: { return self; } } } sprintf(ErrorMsg, "%s - lookup table", theName); [envDelegate displayWindow:ErrorMsg]; return self; } - setParamValue:(double) ctrl_val /* Send the float value to our controlled arg(s) */ { static char value[512]; /* May have caused delays [Conductor lockPerformance]; */ sprintf(value, "%f", ctrl_val); #ifdef DEBUG_PARAM DEBUG_PRINT("setParamValue %s sending %s to fakeUG: %s arg %s (index=%d)\n", theName, value, [theFakeUG getName], [theFakeUG getArgName:theArg], theArg); #endif DEBUG_PARAM [theFakeUG setArgWithIndex: theArg To:value]; if ([thePatch allowPPInspectorUpdate] || [thePatch alwaysUpdate]) { [theFakeUG displayArg: theArg]; [thePatch setAllowPPInspectorUpdate:NO]; } /* May have caused delays [Conductor unlockPerformance]; */ return self; } - (double) applyMap:(double) val { double newVal; if ( (mapEnvelope) && (mapEnabled) ) { newVal = [mapEnvelope lookupYForX:val]; } else if ( ! (mapEnvelope) && (mapEnabled) ) { newVal = 0.0; } else { newVal = val; } return newVal; } // #define DEBUG_PARAM 0 - realizeNote:aNote fromNoteReceiver:aNR { double controlVal; double fval; double pbSensitivity; double bend; double pitchBend; double frequency; static double lastFreq = 0.0; static double pitchbendSensitivity = 2.0; /* Do we even send it ?*/ if ( !(([aNote noteType] == noteTypeToControl) && paramEnabled && [theFakeUG isArgEnabled:theArg])) { return self; } #ifdef DEBUG_PARAM DEBUG_PRINT("- **** PatchParam/realizeNote Looking for midiController: %s (%d)\n", [paramInterface getControlName:midiController], midiController); #endif DEBUG_PARAM /* Make sure the Note isn't being "thinned=out" */ if (thinEnabled) { currNoteCount++; if ((currNoteCount % thinFactor) != 0) { return self; } else { currNoteCount = 0; } } // printf ("**** Processing note: %d\n", [aNote noteType]); /* Deal with some common MusicKit parameters */ if (midiControllerAsMKParm == MK_freq) { /* Convert the keyNum to freq */ if (MKIsNoteParPresent(aNote, MK_keyNum)) { frequency = MKKeyNumToFreq([aNote keyNum]); [aNote setPar:MK_freq toDouble:frequency]; } } if (isControlPresent(aNote, midiController)) { if (MKIsNoteParPresent(aNote, MK_pitchBend) && (midiControllerAsMKParm == MK_pitchBend)) { if (lastFreq > 0) { #ifdef DEBUG_PARAM DEBUG_PRINT("- !bend! **** PatchParam/realizeNote Have midiController: %s (%d)\n", [paramInterface getControlName:midiController], midiController); #endif DEBUG_PARAM if (MKIsNoteParPresent(aNote, MK_pitchBendSensitivity)) { pitchbendSensitivity = MKGetNoteParAsDouble(aNote, MK_pitchBendSensitivity); } else { pitchbendSensitivity = 2.0; // Pick something "reasonable" } pbSensitivity = (pitchbendSensitivity / 12.0) / 8192.0; bend = MKGetNoteParAsDouble(aNote, MK_pitchBend); pitchBend = pow(2.0, (bend - 8192.0) * pbSensitivity); #ifdef DEBUG_PARAM DEBUG_PRINT("pitchbendSensitivity: %f pbSensitivity: %f bend: %f pitchBend: %f\n", pitchbendSensitivity, pbSensitivity, bend, pitchBend); #endif DEBUG_PARAM fval = lastFreq * pitchBend; #ifdef DEBUG_PARAM DEBUG_PRINT("PatchParam realizeNote: Have pitchBend %f\n", fval); #endif DEBUG_PARAM fval = [self applyMap:fval]; fval = (fval * midiCtrlScaleVal) + midiCtrlOffsetVal; [self setParamValue:fval]; } } else { #ifdef DEBUG_PARAM DEBUG_PRINT("- **** PatchParam/realizeNote Have midiController: %s (%d)\n", [paramInterface getControlName:midiController], midiController); #endif DEBUG_PARAM controlVal = getControlValAsDouble(aNote, midiController); controlVal = [self applyMap:controlVal]; controlVal = (controlVal * midiCtrlScaleVal) + midiCtrlOffsetVal; #ifdef DEBUG_PARAM DEBUG_PRINT("PatchParam realizeNote: Have controller %d val: %f\n", midiController, controlVal); #endif DEBUG_PARAM [self setParamValue:controlVal]; } } /* Hack for pitch bend */ if (MKIsNoteParPresent(aNote, MK_freq) || MKIsNoteParPresent(aNote, MK_keyNum)) { lastFreq = [self applyMap:[aNote freq]]; } return self; } /* Stuff that came from Mike's mapper ********************** > > - free > { > [[envelopeView window] close]; > [[envelopeView window] free]; > return [super free]; > } > > - editEnvelope:sender > { > if (! mapEnvelope) > { > double x[2], y[2]; > mapEnvelope = [[Envelope allocFromZone:[self zone]] init]; > x[0] = y[0] = 0.0; > x[1] = y[1] = 127.0; > [mapEnvelope setPointCount:2 xArray:x yArray:y]; > } > > [envelopeView setEnvelope:mapEnvelope]; > [[envelopeView window] setTitle:[self getName]]; > [[envelopeView window] orderFront:sender]; > return self; > } > > - windowDidBecomeKey:sender > { > if ([[envelopeView window] isVisible]) > [[envelopeView window] orderWindow:NX_BELOW > relativeTo:[inspector windowNum]]; > return self; > } > > **************************************************/ - write:(NXTypedStream *) stream { char *aName; [super write:stream]; aName = midiControllerName; NXWriteTypes(stream, "*", &aName); aName = theName; NXWriteTypes(stream, "*", &aName); NXWriteTypes(stream, "d", &midiCtrlScaleVal); NXWriteTypes(stream, "d", &minMidiCtrlScaleVal); NXWriteTypes(stream, "d", &maxMidiCtrlScaleVal); NXWriteTypes(stream, "d", &midiCtrlOffsetVal); NXWriteTypes(stream, "d", &minMidiCtrlOffsetVal); NXWriteTypes(stream, "d", &maxMidiCtrlOffsetVal); NXWriteTypes(stream, "i", ¬eTypeToControl); NXWriteTypes(stream, "@", &theFakeUG); NXWriteTypes(stream, "i", &theArg); NXWriteTypes(stream, "i", &midiController); NXWriteTypes(stream, "i", &midiControllerAsMKParm); [self syncMapEnvelope]; NXWriteTypes(stream, "@", &mapEnvelope); NXWriteTypes(stream, "c", &mapEnabled); NXWriteTypes(stream, "c", ¶mEnabled); NXWriteTypes(stream, "c", &thinEnabled); NXWriteTypes(stream, "i", &thinFactor); if (inspector) { useInspectorRect = YES; [inspector getFrame:&inspectorRect]; } else { useInspectorRect = NO; inspectorRect.origin.x = -1; inspectorRect.origin.y = -1; inspectorRect.size.width = -1; inspectorRect.size.height = -1; } 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; char *aName; [super read:stream]; thinEnabled = NO; thinFactor = 1; paramEnabled = YES; mapEnabled = NO; version = NXTypedStreamClassVersion(stream, "PatchParam"); switch (version) { case(5): { NXReadTypes(stream, "*", &aName); strcpy(midiControllerName, aName); NXReadTypes(stream, "*", &aName); strcpy(theName, aName); NXReadTypes(stream, "d", &midiCtrlScaleVal); NXReadTypes(stream, "d", &minMidiCtrlScaleVal); NXReadTypes(stream, "d", &maxMidiCtrlScaleVal); NXReadTypes(stream, "d", &midiCtrlOffsetVal); NXReadTypes(stream, "d", &minMidiCtrlOffsetVal); NXReadTypes(stream, "d", &maxMidiCtrlOffsetVal); NXReadTypes(stream, "i", ¬eTypeToControl); NXReadTypes(stream, "@", &theFakeUG); NXReadTypes(stream, "i", &theArg); NXReadTypes(stream, "i", &midiController); NXReadTypes(stream, "i", &midiControllerAsMKParm); NXReadTypes(stream, "@", &mapEnvelope); NXReadTypes(stream, "c", &mapEnabled); NXReadTypes(stream, "c", ¶mEnabled); NXReadTypes(stream, "c", &thinEnabled); NXReadTypes(stream, "i", &thinFactor); 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; break; } case(4): { NXReadTypes(stream, "*", &aName); strcpy(midiControllerName, aName); NXReadTypes(stream, "*", &aName); strcpy(theName, aName); NXReadTypes(stream, "d", &midiCtrlScaleVal); NXReadTypes(stream, "d", &minMidiCtrlScaleVal); NXReadTypes(stream, "d", &maxMidiCtrlScaleVal); NXReadTypes(stream, "d", &midiCtrlOffsetVal); NXReadTypes(stream, "d", &minMidiCtrlOffsetVal); NXReadTypes(stream, "d", &maxMidiCtrlOffsetVal); NXReadTypes(stream, "i", ¬eTypeToControl); NXReadTypes(stream, "@", &theFakeUG); NXReadTypes(stream, "i", &theArg); NXReadTypes(stream, "i", &midiController); NXReadTypes(stream, "i", &midiControllerAsMKParm); NXReadTypes(stream, "@", &mapEnvelope); NXReadTypes(stream, "c", &mapEnabled); NXReadTypes(stream, "c", ¶mEnabled); 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; break; } case(3): { NXReadTypes(stream, "*", &aName); strcpy(midiControllerName, aName); NXReadTypes(stream, "*", &aName); strcpy(theName, aName); NXReadTypes(stream, "d", &midiCtrlScaleVal); NXReadTypes(stream, "d", &minMidiCtrlScaleVal); NXReadTypes(stream, "d", &maxMidiCtrlScaleVal); NXReadTypes(stream, "d", &midiCtrlOffsetVal); NXReadTypes(stream, "d", &minMidiCtrlOffsetVal); NXReadTypes(stream, "d", &maxMidiCtrlOffsetVal); NXReadTypes(stream, "i", ¬eTypeToControl); NXReadTypes(stream, "@", &theFakeUG); NXReadTypes(stream, "i", &theArg); NXReadTypes(stream, "i", &midiController); NXReadTypes(stream, "i", &midiControllerAsMKParm); NXReadTypes(stream, "@", &mapEnvelope); NXReadTypes(stream, "c", &mapEnabled); NXReadTypes(stream, "c", ¶mEnabled); break; } case(2): { NXReadTypes(stream, "*", &aName); strcpy(midiControllerName, aName); NXReadTypes(stream, "*", &aName); strcpy(theName, aName); NXReadTypes(stream, "d", &midiCtrlScaleVal); NXReadTypes(stream, "d", &minMidiCtrlScaleVal); NXReadTypes(stream, "d", &maxMidiCtrlScaleVal); NXReadTypes(stream, "d", &midiCtrlOffsetVal); NXReadTypes(stream, "d", &minMidiCtrlOffsetVal); NXReadTypes(stream, "d", &maxMidiCtrlOffsetVal); NXReadTypes(stream, "i", ¬eTypeToControl); NXReadTypes(stream, "@", &theFakeUG); NXReadTypes(stream, "i", &theArg); NXReadTypes(stream, "i", &midiController); NXReadTypes(stream, "i", &midiControllerAsMKParm); NXReadTypes(stream, "@", &mapEnvelope); NXReadTypes(stream, "c", &mapEnabled); paramEnabled = YES; break; } default: { sprintf(ErrorMsg, "Unexpected document version: %d reading a PatchParam: File: %s Line: %d\n", version, __FILE__, __LINE__); NXRunAlertPanel(getAppName(), ErrorMsg, NULL, NULL, NULL); } } /* Make sure the map envelope is synced */ if (envDelegate) { [envDelegate free]; envDelegate = nil; } [self syncMapEnvelope]; return self; } - displayIfDoubleClick { clickCount++; if (clickCount >= 2) { clickCount = 0; [self displayInspector]; } return self; } - displayInspectorIfWasActive { if (inspectorDisplayed) { [self displayInspector]; } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.