This is MKCodeGen.m in view mode; [Download] [Up]
/************************************************** * SynthBuilder * Copyright 1993 Nick Porcaro All Rights Reserved **************************************************/ /* * MKCodeGen.m * Music Kit Code generator object (split off from FakeSynthPatch) */ #import <stdio.h> #import <stdlib.h> #import <string.h> #import <ctype.h> #import <appkit/Application.h> #import <dpsclient/event.h> #import <appkit/Matrix.h> #import <appkit/OpenPanel.h> #import <appkit/SavePanel.h> #import "NodeView.h" #import "FakeSynthPatch.h" #import "FakePatchPoint.h" #import "FakeUG.h" #import "UGDef.h" #import "MKCodeGen.h" #import "Controller.h" #import "Utilities.h" #define EOS '\0' static char TempString[1024]; extern id savePanel; extern id openPanel; extern char *getSavePath(char *banner); extern char *getOpenPath(char *banner); extern char *getAppName(); double atod(STR s) { double x; sscanf(s, "%lf", &x); return x; } @implementation MKCodeGen - init { [super init]; [NXApp loadNibSection:"MKCodeGen.nib" owner:self withNames:YES]; return self; } - displayInspector:sender { theSP = [theMainController theSP]; fakeUGs = [theSP getFakeUGs]; fakePatchPoints = [theSP getFakePatchPoints]; if (theSP && [fakeUGs count] && [fakePatchPoints count]) { [theInspector makeKeyAndOrderFront:self]; } else { NXRunAlertPanel(getAppName(), "Nothing to generate code for", NULL, NULL, NULL); } return self; } - emitCode:sender { char *file_name; char *path_leaf; int comments; int dest; int len; [theInspector performClose:self]; comments = [generateComments intValue]; dest = [[patchDest selectedCell] tag]; /* Get the file name from the user and make sure it is * a cool name for the code generator */ sprintf(TempString, "%s Generate Code", getAppName()); if (! (file_name = getSavePath(TempString))) { return self; } path_leaf = [utilities getPathLeaf:file_name]; len = strlen(path_leaf); if (len > 2 && path_leaf[len-2] == '.') { path_leaf[len-2] = EOS; } if (! [utilities checkName:path_leaf]) { return self; } [self emitCodeTo:file_name genComments:comments ToDest:dest]; return self; } - emitCodeTo:(char *) file genComments:(int) comments ToDest: (int) aDest { int len; static char header_file[512], code_file[512]; char *newFileName; /* Turn off the sound in case the user generates code * to an app that * needs the dsp */ theSP = [theMainController theSP]; fakeUGs = [theSP getFakeUGs]; fakePatchPoints = [theSP getFakePatchPoints]; strcpy(code_file, file); [theSP deallocatePatch:self]; newFileName = [self makeObjCCode:code_file:comments]; if (! newFileName) { NXRunAlertPanel(getAppName(), "Could not process file: %s", NULL, NULL, NULL, code_file); return self; } strcpy(code_file, newFileName); /* Get the header file name from the * code file name -- assume code file ends in .m and * header file ends in .h */ strcpy(header_file, code_file); len = strlen(header_file); header_file[len-2] = '\0'; strcat(header_file, ".h"); newFileName = [self makeHeaderFile:header_file]; if (! newFileName) { NXRunAlertPanel(getAppName(), "Could not process file: %s", NULL, NULL, NULL, header_file); } strcpy(header_file, newFileName); /* Now do the right thing with the file */ switch (aDest) { case(0): { sprintf(TempString, "open %s %s", code_file, header_file); system(TempString); break; } case(1): /* Standard test script */ { sprintf(TempString, "%s/mk-tester -mfile %s -sb_dir %s&", [utilities getAppDir], code_file, [utilities getAppDir]); printf("Shell command: %s\n", TempString); system(TempString); break; } case(2): /* Custom test script */ { sprintf(TempString, "%s -mfile %s -sb_dir %s &", [testerScript stringValue], code_file, [utilities getAppDir]); printf("Shell command: %s\n", TempString); system(TempString); break; } case(3): /* Future -- make it go to the paste board */ { break; } case(4): /* Just create the file silently */ { break; } } return self; } - (char *) makeHeaderFile:(char *)fileName { char *theFileName; FILE *f; theFileName = [self setClassNameFromFileName: 'h' : (char *)fileName]; if (!theFileName) { NXRunAlertPanel(getAppName(), "%s could not be processed as a file name.", NULL, NULL, NULL, fileName); return NULL; } f = fopen(theFileName, "w"); if (!f) { NXRunAlertPanel(getAppName(), "Could not open: %s", NULL, NULL, NULL, theFileName); return NULL; } fprintf(f, "#import <musickit/SynthPatch.h>\n"); fprintf(f, "#import <musickit/WaveTable.h>\n"); fprintf(f, "#import <musickit/Envelope.h>\n\n"); fprintf(f, "@interface %s:SynthPatch\n{\n",[theSP getName]); fprintf(f, " /*** ADD INSTANCE VARIABLES HERE ***/\n"); fprintf(f, "}\n\n"); fprintf(f, "+patchTemplateFor:currentNote;\n"); fprintf(f, "-init;\n"); fprintf(f, "-testNote;\n"); fprintf(f, "-noteOnSelf:aNote;\n"); fprintf(f, "-preemptFor:aNote;\n"); fprintf(f, "-noteUpdateSelf:aNote;\n"); fprintf(f, "-(double)noteOffSelf:aNote;\n"); fprintf(f, "-noteEndSelf;\n\n"); // fprintf(f, "-_setDefaults;\n"); // fprintf(f, "-_updateParameters:aNote;\n\n"); fprintf(f, "@end\n"); fclose(f); return theFileName; } - (char *) makeObjCCode:(char *)fileName:(int)doComments { int i, j, k, l; BOOL first; id patchPoint, theUG, aFakeUG, fromFakeUG; BOOL isDataElement, isSineRom, isConstantpp, isEnvelope, declareThem, hasEnvelope; char *ug_name, *ug_type, *inst_name, *arg_val, *arg_name, *type_str, *cast_str; char *thing; int arg_type; int arg_count = 0; int pointCount=0, stickPoint = -1; int envelopes_processed = 0; double *xArray, *yArray, *smoothingArray; char first_part[256], curr_env[256], x_array[20], y_array[20], smooth_array[20]; FILE *f; extern char *getenv(); char *theFileName; theFileName = [self setClassNameFromFileName: 'm' : fileName]; if (!theFileName) { NXRunAlertPanel(getAppName(), "%s could not be processed as a file name.", NULL, NULL, NULL, fileName); return NULL; } f = fopen(theFileName, "w"); if (!f) { NXRunAlertPanel(getAppName(), "Could not open: %s", NULL, NULL, NULL, theFileName); return NULL; } fprintf(f, "#import <appkit/appkit.h>\n"); /*** Added by Nick ***/ fprintf(f, "#import <musickit/unitgenerators/unitgenerators.h>\n"); fprintf(f, "#import <musickit/PatchTemplate.h>\n"); fprintf(f, "#import \"%s.h\"\n\n", [theSP getName]); fprintf(f, "#define SE NX_ADDRESS(synthElements)\n\n"); fprintf(f, "@implementation %s:SynthPatch\n\n",[theSP getName]); fprintf(f, "static int "); first=YES; for (i=0; i<[fakeUGs count]; i++) { aFakeUG = [fakeUGs objectAt:i]; if ([aFakeUG isSoundMaker]) { if (![aFakeUG isData]) { if (first) { fprintf(f, "%s", [aFakeUG getName]); first=NO; } else { fprintf(f, ", %s", [aFakeUG getName]); } } } } for (i=0; i<[fakePatchPoints count]; i++) { fromFakeUG = [[[fakePatchPoints objectAt:i] getFromNode] superview]; if ([fromFakeUG isSoundMaker]) { if (![fromFakeUG isSineROM]) { if (first) { fprintf(f, "%s",[[fakePatchPoints objectAt:i] getName]); first=NO; } else { fprintf(f, ", %s",[[fakePatchPoints objectAt:i] getName]); } } } } fprintf(f, ";\n\n"); fprintf(f, "+patchTemplateFor:currentNote\n"); fprintf(f, "{\n static PatchTemplate *template = nil;\n"); fprintf(f, " if (template)\n return template;\n"); fprintf(f, " [UnitGenerator enableErrorChecking:YES]; /*** Comment this out once your patch is working. ***/\n"); fprintf(f, " template = [[PatchTemplate alloc] init];\n"); for (i=0; i<[fakeUGs count]; i++) { aFakeUG = [fakeUGs objectAt:i]; if ([aFakeUG isSoundMaker]) { if (![aFakeUG isData]) { ug_name = [self checkForUnconnectedPins: i ]; fprintf(f, " %s = [template addUnitGenerator:[%s class]];\n", [aFakeUG getName], ug_name); } } } #define KARPLUS_STRONG_WORKS1 1 /* This causes Karplus Strong to go higher pitched */ #ifdef KARPLUS_STRONG_WORKS1 for (i=0; i<[fakePatchPoints count]; i++) { fromFakeUG = [[[fakePatchPoints objectAt:i] getFromNode] superview]; if ([fromFakeUG isSoundMaker]) { if ([fromFakeUG isData]) { if ([[fakePatchPoints objectAt:i] getXMemory]) { theUG = [[[fakePatchPoints objectAt:i] getFromNode] superview]; if ( [ theUG hasConstant] && ! [theUG isStorage]) { fprintf(f, " %s = [template addPatchpoint:MK_xData];\n", [[fakePatchPoints objectAt:i] getName]); } else { fprintf(f, " %s = [template addSynthData:MK_xData length:%i];\n", [[fakePatchPoints objectAt:i] getName], [[[[fakePatchPoints objectAt:i] getFromNode] superview] getLength]); } } else { if (![[[[fakePatchPoints objectAt:i] getFromNode] superview] isSineROM]) { fprintf(f, " %s = [template addSynthData:MK_yData length:%i];\n", [[fakePatchPoints objectAt:i] getName], [[[[fakePatchPoints objectAt:i] getFromNode] superview] getLength]); } } } else { if ([[fakePatchPoints objectAt:i] getXMemory]) { fprintf(f, " %s = [template addPatchpoint:MK_xPatch];\n", [[fakePatchPoints objectAt:i] getName]); } else { fprintf(f, " %s = [template addPatchpoint:MK_yPatch];\n", [[fakePatchPoints objectAt:i] getName]); } } } } fprintf(f, " return template;\n}"); fprintf(f, "\n\n-_setDefaults\n{\n"); fprintf(f, " /*** ADD ANY INITIALIZATION CODE HERE. ***/\n"); fprintf(f, " return self;\n}\n\n"); #else for (i=0; i<[fakePatchPoints count]; i++) { fromFakeUG = [[[fakePatchPoints objectAt:i] getFromNode] superview]; if ([fromFakeUG isSoundMaker]) { if ([fromFakeUG isData]) if ([[fakePatchPoints objectAt:i] getXMemory]) fprintf(f, " %s = [template addSynthData:MK_xData length:%i];\n", [[fakePatchPoints objectAt:i] getName], [[[[fakePatchPoints objectAt:i] getFromNode] superview] getLength]); else { if (![fromFakeUG isSineROM]) fprintf(f, " %s = [template addSynthData:MK_yData length:%i];\n", [[fakePatchPoints objectAt:i] getName], [[[[fakePatchPoints objectAt:i] getFromNode] superview] getLength]); } else if ([[fakePatchPoints objectAt:i] getXMemory]) fprintf(f, " %s = [template addPatchpoint:MK_xPatch];\n", [[fakePatchPoints objectAt:i] getName]); else fprintf(f, " %s = [template addPatchpoint:MK_yPatch];\n", [[fakePatchPoints objectAt:i] getName]); } } fprintf(f, " return template;\n}"); fprintf(f, "\n\n-_setDefaults\n{\n"); fprintf(f, " /*** ADD ANY INITIALIZATION CODE HERE. ***/\n"); fprintf(f, " return self;\n}\n\n"); #endif KARPLUS_STRONG_WORKS1 // Declare static id variables for the envelopes (Nick) envelopes_processed = 0; for (i=0; i<[fakeUGs count]; i++) { aFakeUG = [fakeUGs objectAt:i]; if ([aFakeUG isSoundMaker]) { if ([[fakeUGs objectAt:i] isEnvelopeHandler]) { ug_name = [[fakeUGs objectAt:i] getName]; envelopes_processed++; fprintf(f, "static id envelope%d = nil;\n", envelopes_processed); } } } fprintf(f, "\n\n"); // Put the envelope code in _updateParameters (Nick) fprintf(f, "-_updateParameters:aNote\n{\n\n"); fprintf(f, "\n"); fprintf(f, " if ([self phraseStatus] <= MK_phraseRearticulate) {\n"); envelopes_processed = 0; for (i=0; i<[fakeUGs count]; i++) { aFakeUG = [fakeUGs objectAt:i]; if ([aFakeUG isSoundMaker]) { if ([[fakeUGs objectAt:i] isEnvelopeHandler]) { ug_name = [[fakeUGs objectAt:i] getName]; envelopes_processed++; sprintf(curr_env, "envelope%d", envelopes_processed); fprintf(f, " MKUpdateAsymp(SE[%s], %s, 0.0, 1.0,\n", ug_name, curr_env); fprintf(f, " MK_NODVAL, MK_NODVAL, MK_NODVAL,\n"); fprintf(f, " [self phraseStatus]);\n"); } } } fprintf(f, " }\n"); fprintf(f, " return self;\n}\n\n"); fprintf(f, "-init\n{\n"); // Figure out if we need to declare freqs, amps, partials declareThem = NO; for (i=0; i<[fakePatchPoints count]; i++) { int k; fromFakeUG = [[fakePatchPoints objectAt:i] getFromFakeUG]; if ([fromFakeUG isSoundMaker]) { if ([fromFakeUG isData]) { if (![fromFakeUG hasConstant]) { for (k=0; k<MAXNOTEPARAMETERS; k++) { if ([fromFakeUG getArgType:k] == PARTIALS) { declareThem = YES; break; } } } } } } if (declareThem) { fprintf(f, " double *freqs, *amps;\n id partials;\n"); } for (i=0; i<[fakePatchPoints count]; i++) { int k; patchPoint = [fakePatchPoints objectAt:i]; fromFakeUG = [patchPoint getFromFakeUG]; if (! [fromFakeUG isSoundMaker]) { goto end_of_loop0; } if (![fromFakeUG isData]) fprintf(f, " [SE[%s] %sSE[%s]];\n", [fromFakeUG getName], [fromFakeUG getConnectionName:[patchPoint getFromConnectionNumber]], [patchPoint getName]); else if ([fromFakeUG hasConstant]) { fprintf(f, " [SE[%s]",[patchPoint getName]); /** Fixed by Nick **/ fprintf(f, " setToConstant:DSPDoubleToFix24(%f)];\n", atod([fromFakeUG getConstant])); } else { for (k=0; k<MAXNOTEPARAMETERS; k++) { if (([fromFakeUG getArgType:k])==PARTIALS) { int l; for (l=0; l<[[patchPoint getToNodes] count]; l++) { double *freqs, *amps; char *scoreString; int p, q, pointCount=0; scoreString = [fromFakeUG getArgName:k]; for (p=0; scoreString[p]!='\0'; p++) if (scoreString[p]=='{') pointCount++; freqs = (double *) NXZoneCalloc([self zone], pointCount, sizeof(double)); amps = (double *) NXZoneCalloc([self zone], pointCount, sizeof(double)); q=0; for (p=0; p<pointCount; p++) { freqs[p] = amps[p] = 0.0; while (scoreString[q]!='{') q++; sscanf(scoreString+q, "{%lf,%lf}", &freqs[p], &s[p]); q++; } fprintf(f, " partials=[[Partials alloc]"); fprintf(f, " init];\n freqs=(double *)"); fprintf(f, " calloc(%i, sizeof(*freqs));\n", pointCount); fprintf(f, " amps=(double *) calloc(%i,", pointCount); fprintf(f, " sizeof(*amps));\n"); for (p=0; p<pointCount; p++) fprintf(f, " freqs[%i]=%f;\n", p, freqs[p]); for (p=0; p<pointCount; p++) fprintf(f, " amps[%i]=%f;\n", p, amps[p]); fprintf(f, " [partials setPartialCount:%i", pointCount); fprintf(f, " freqRatios:freqs ampRatios:amps"); fprintf(f, " phases:NULL orDefaultPhase:0.0];\n"); fprintf(f, " [SE[%s]", [patchPoint getName]); fprintf(f, " setData:[partials dataDSPLength:%i]];\n", [fromFakeUG getLength]); } } } } /* A UG is an output if it has no output nodes. */ for (k=0; k<[[patchPoint getToNodes] count]; k++) { id toFakeUG = [[[patchPoint getToNodes] objectAt:k] superview]; if ([toFakeUG getConnectionName:0]!=NULL) { if (([fromFakeUG isData] && ([fromFakeUG isSineROM]) && ([toFakeUG isOscg]))) { fprintf(f, " [SE[%s]", [toFakeUG getName]); fprintf(f, " setTableToSineROM];\n"); } else fprintf(f, " [SE[%s] %sSE[%s]];\n", [toFakeUG getName], [toFakeUG getConnectionName:[[[patchPoint getToNodes] objectAt:k] getTag]], [patchPoint getName]); } } end_of_loop0: ; } fprintf(f, " [self _setDefaults]; \n"); fprintf(f, " return self;\n}\n\n"); // **************************************** // start testNote method (Nick) // **************************************** fprintf(f, "// ** Added by Nick **\n"); fprintf(f, "-testNote\n"); fprintf(f, "{\n\n"); envelopes_processed = 0; for (i=0; i<[fakeUGs count]; i++) { aFakeUG = [fakeUGs objectAt:i]; if (! [aFakeUG isSoundMaker]) { goto end_of_loop; } isDataElement = [aFakeUG isData]; isSineRom = [aFakeUG isSineROM]; isEnvelope = [aFakeUG isEnvelopeHandler]; ug_name = [aFakeUG getName]; ug_type = [aFakeUG getTypeString]; inst_name = [aFakeUG getName]; arg_count = [aFakeUG getArgCount]; /* I think this line is flawed */ isConstantpp = [[[[fakePatchPoints objectAt:i] getFromNode] superview] hasConstant]; if (doComments) { /* Generate the comments */ if (isConstantpp || isDataElement) { thing = "Synth Data"; } else { thing = "Unit Generator"; } fprintf(f, "\n//\n"); fprintf(f, "// *** %s (graph instance number %d) ***\n", thing, i); fprintf(f, "// Instance name: %s\n", inst_name); fprintf(f, "// Type: %s", ug_type); if ( (isDataElement) && (! isSineRom) && (!isConstantpp)) { fprintf(f, " (data element of length: %d)\n", [aFakeUG getLength]); } else if (isEnvelope) { fprintf(f, "\n// Envelope!\n"); } else { fprintf(f, "\n"); } fprintf(f, "// Number of arguments: %d\n", arg_count); for (j=0; j<arg_count; j++) { arg_val = [aFakeUG getArg:j]; if (! arg_val || (strcmp(arg_val, "") == 0) ) { arg_val = "UNSET"; } arg_type = [aFakeUG getArgType:j]; arg_name = [aFakeUG getArgName:j]; if ( (!arg_name) || (strcmp(arg_name, "") == 0) ) { break; } type_str = [aFakeUG getArgTypeStr:arg_type]; if (!type_str) { cast_str = ""; } if (arg_type == PARTIALS) { fprintf(f, "// *** WARNING cannot generate code for UG of type %s\n", type_str); } fprintf(f, "// %s %s %s\n", arg_name, type_str, arg_val); } fprintf(f, " \n"); } // Generate the code if ( (arg_count > 0) && (! isDataElement)) { for (j=0; j<arg_count; j++) { /* Make sure we can even do it */ isEnvelope = NO; arg_type = [aFakeUG getArgType:j]; type_str = [aFakeUG getArgTypeStr:arg_type]; pointCount = 0; if (arg_type == ENV) { isEnvelope = YES; envelopes_processed++; sprintf(curr_env, "envelope%d", envelopes_processed); sprintf(x_array, "xArray%d", envelopes_processed); sprintf(y_array, "yArray%d", envelopes_processed); sprintf(smooth_array, "smoothArray%d", envelopes_processed); arg_val = [aFakeUG getArg:j]; for (k=0; arg_val[k] != '\0'; k++) { if (arg_val[k]=='|') { stickPoint = pointCount-1; } if (arg_val[k]=='(') pointCount++; } xArray = (double *) NXZoneCalloc([self zone], pointCount, sizeof(double)); yArray = (double *) NXZoneCalloc([self zone], pointCount, sizeof(double)); smoothingArray = (double *) NXZoneCalloc([self zone], pointCount, sizeof(double)); l=0; for (k=0; k<pointCount; k++) { xArray[k] = yArray[k] = 0.0; smoothingArray[k] = 1.0; while (arg_val[l]!='(') { l++; } sscanf(arg_val+l, "(%lf,%lf,%lf)", &xArray[k], &yArray[k], &smoothingArray[k]); l++; } fprintf(f, " if (! %s) {\n", curr_env); fprintf(f, " double %s[] = {", x_array); for (k=0; k<pointCount; k++) { if (k == pointCount -1) { fprintf(f, "%f};\n", xArray[k]); } else { fprintf(f, "%f, ", xArray[k]); } } fprintf(f, " double %s[] = {", y_array); for (k=0; k<pointCount; k++) { if (k == pointCount - 1) { fprintf(f, "%f};\n", yArray[k]); } else { fprintf(f, "%f, ", yArray[k]); } } fprintf(f, " double %s[] = {", smooth_array); for (k=0; k<pointCount; k++) { if (k == pointCount - 1) { fprintf(f, "%f};\n", smoothingArray[k]); } else { fprintf(f, "%f, ", smoothingArray[k]); } } fprintf(f, " %s = [[Envelope alloc] init];\n", curr_env); // I added orSamplingPeriod:0 per DAJ mail of 12/20/92 fprintf(f, " [%s setPointCount: %d xArray:%s orSamplingPeriod:0 yArray:%s smoothingArray:%s orDefaultSmoothing:1.0];\n", curr_env, pointCount, x_array, y_array, smooth_array); if (stickPoint!=-1) { fprintf(f, " [%s setStickPoint: %d];\n", curr_env, stickPoint); } fprintf(f, " [SE[%s] setEnvelope:%s yScale:1.0 yOffset:0.0 xScale:1.0 releaseXScale:1.0 funcPtr:NULL];\n",ug_name, curr_env); fprintf(f, " }\n"); NXZoneFree([self zone], xArray); NXZoneFree([self zone], smoothingArray); NXZoneFree([self zone], yArray); xArray = NULL; smoothingArray = NULL; yArray = NULL; } else if (arg_type == PARTIALS) { fprintf(f, "// *** ERROR cannot generate code for UG of type %s\n", type_str); break; } else /* All other argument types */ { /* Write out the first part */ sprintf(first_part, " [SE[%s] ", ug_name); /* Write code for paramter method setting */ arg_val = [aFakeUG getArg:j]; arg_name = [aFakeUG getArgName:j]; cast_str = [aFakeUG getArgCast:arg_type]; if ( (!cast_str) || (strcmp(cast_str, "") == 0)) { fprintf(stderr, "Warning: NULL cast on method %s for UG %s\n", arg_name, type_str); cast_str = ""; } /* Only generate the code for non-NULL arg_val's * This corresponds to David Jaffe's request not to * generate code for "unset" values */ if (arg_val && (strcmp(arg_val, "") != 0) ) { // fprintf(f, "%s %s %s %s];\n", first_part, arg_name, cast_str, arg_val); // Took out cast per daj request of 3-5-93 (nick) fprintf(f, "%s %s %s];\n", first_part, arg_name, arg_val); } } } } end_of_loop: ; } // **************************************** // end testNote method (Nick) // **************************************** fprintf(f, " return self;\n}\n"); fprintf(f, "-noteOnSelf:aNote\n"); fprintf(f, "{\n"); fprintf(f, "// This produces the sound designed in %s.\n", getAppName()); fprintf(f, "// For further control, remove the testNote method and add\n"); fprintf(f, "// parmeter-setting code to _updateParameters:\n"); fprintf(f, " [self testNote];\n"); /** (added by Nick) **/ fprintf(f, " [self _updateParameters:aNote];\n"); for (i=0; i<[fakePatchPoints count]; i++) { int k; id patchPoint = [fakePatchPoints objectAt:i]; for (k=0; k<[[patchPoint getToNodes] count]; k++) { id toFakeUG = [[[patchPoint getToNodes] objectAt:k] superview]; if ([toFakeUG isSoundMaker]) { if ([toFakeUG getConnectionName:0]==NULL) fprintf(f, " [SE[%s] %sSE[%s]];\n", [toFakeUG getName], [toFakeUG getConnectionName:[[[patchPoint getToNodes] objectAt:k] getTag]], [patchPoint getName]); } } } fprintf(f, " [synthElements makeObjectsPerform:@selector(run)];\n"); fprintf(f, " return self;\n}\n\n"); fprintf(f, "-noteUpdateSelf:aNote\n"); fprintf(f, "{\n [self _updateParameters:aNote];\n"); fprintf(f, " return self;\n}\n\n"); fprintf(f, "-(double)noteOffSelf:aNote\n"); fprintf(f, "{\n double t=0;\n"); hasEnvelope = NO; for (i=0; i<[fakeUGs count]; i++) { aFakeUG = [fakeUGs objectAt:i]; if ([aFakeUG isSoundMaker]) { if ([[fakeUGs objectAt:i] isEnvelopeHandler]) { hasEnvelope = YES; break; } } } if (hasEnvelope) { fprintf(f, " double u;\n"); } fprintf(f, " [self _updateParameters:aNote];\n"); for (i=0; i<[fakeUGs count]; i++) { aFakeUG = [fakeUGs objectAt:i]; if ([aFakeUG isSoundMaker]) { if ([aFakeUG isEnvelopeHandler]) { fprintf(f, " u = [SE[%s] finish];\n t=(u>t)?u:t;\n", [aFakeUG getName]); } } } fprintf(f, " return t;\n}\n\n"); fprintf(f, "-noteEndSelf\n{\n"); for (i=0; i<[fakePatchPoints count]; i++) { id patchPoint = [fakePatchPoints objectAt:i]; int k; id toFakeUG; for (k=0; k<[[patchPoint getToNodes] count]; k++) { toFakeUG = [[[patchPoint getToNodes] objectAt:k] superview]; if ([toFakeUG isSoundMaker]) { if ([toFakeUG getConnectionName:0] == NULL) /*** The following change made by DAJ. July 26, 1992 ***/ fprintf(f, " [SE[%s] idle];\n", [[[[patchPoint getToNodes] objectAt:0] superview] getName]); } } } for (i=0; i<[fakeUGs count]; i++) if ([[fakeUGs objectAt:i] isEnvelopeHandler]) fprintf(f, " [SE[%s] abortEnvelope];\n", [[fakeUGs objectAt:i] getName]); fprintf(f, " return self;\n}\n\n"); fprintf(f, "-preemptFor:aNote\n{\n"); for (i=0; i<[fakeUGs count]; i++) if ([[fakeUGs objectAt:i] isEnvelopeHandler]) fprintf(f, " [SE[%s] preemptEnvelope];\n", [[fakeUGs objectAt:i] getName]); fprintf(f, " return self;\n}\n\n@end\n"); fclose(f); return theFileName; } - (char *)setClassNameFromFileName:(char) suff : (char *) fileName /* Utilitity function for setting class name from a filename. * The suffix suff is ignored in setting the class name. * The fileName is returned with suff appended if it didn't already exist * If something bizzare happens, NULL is returned. */ { int l; static char name_buf[1024]; char *path_leaf; if (! fileName) { return(NULL); } /* Change the patch name to reflect the "root" name of the file * (that is, the name with no suffix). * We assume the name is legit from an earlier check */ strcpy(name_buf, fileName); l = strlen(name_buf); if ( l > 2 && (name_buf[l-1] == suff) && (name_buf[l-2] == '.')) { /* Get rid of the suffix */ name_buf[l-2] = EOS; } path_leaf = [utilities getPathLeaf:name_buf]; if (! path_leaf) { return NULL; } [theSP changeName:path_leaf]; /* Add in the suffix again and return it */ l = strlen(name_buf); name_buf[l] = '.'; name_buf[l+1] = suff; name_buf[l+2] = EOS; return(name_buf); } - (char *)checkForUnconnectedPins: (int) index /* Function to check connections. Eventually add code * to check all the connections. */ { static char ug_name_out[256]; char *ug_name; ug_name = [[fakeUGs objectAt:index] getTypeString]; if (strcmp([[fakeUGs objectAt:index] getTypeString], "Add2UGxx") == 0) { NXRunAlertPanel(getAppName(), "%s may have unconnected pins. Naming it Add2UGxxx", NULL, NULL, NULL, ug_name); ug_name = "Add2UGxxx"; } strcpy(ug_name_out, ug_name); return (ug_name_out); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.