This is FrontEnd.m in view mode; [Download] [Up]
/* ----------------------------------------------------------------------------------- */ /* FrontEnd.m -- Copyright (c) 1990 Ed Hill */ /* */ /* This program is free software; you can redistribute it and/or modify it under the */ /* terms of the GNU General Public License as published by the Free Software */ /* Foundation; either version 1, or (at your option) any later option. */ /* */ /* This program is distributed in the hope that it will be useful, but WITHOUT ANY */ /* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A */ /* PARTICULAR PURPOSE. See the GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License along with this */ /* this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, */ /* Cambridge, MA 02139, USA, or send electronic mail to the author. */ /* ------------------------------------------------------------------------------------ */ /* */ /* ------------------------------------------------------------------------------------ */ /* I am aware that this program does nothing that hasn't been done before. I simply */ /* wanted to see how easy it was to add a simple user interface to an existing non-user */ /* friendly program. I would like to add functionality to this program in the future */ /* If you have suggestions or ideas that would be useful in future releases plese feel */ /* to write me at edhill@shumun.weeg.uiowa.edu (NeXT). I also welcome any programming */ /* advice (I would have done this different, etc...). */ /* ------------------------------------------------------------------------------------ */ #import "GNULicense.h" #import "FrontEnd.h" #import <appkit/appkit.h> #import <appkit/publicWraps.h> #import <appkit/nextstd.h> #import <soundkit/soundkit.h> #import <sound/sound.h> #import <string.h> #import <stdio.h> @implementation FrontEnd /* ------------------------------------------------------------------------------------ */ /* The following methods set up the necessary outlets. */ /* Which are connected via the Interface Builder. */ /* ------------------------------------------------------------------------------------ */ -setFrontEndWindow:anObject { FrontEndWindow = anObject; return self; } -setNameView:anObject { NameView = anObject; return self; } -setNameView2:anObject { NameView2 = anObject; return self; } -setIconBox:anObject { IconBox = anObject; return self; } -setIconBox2:anObject { IconBox2 = anObject; return self; } -setSampleButton:anObject { SampleButton = anObject; popup = [PopUpList new]; [popup addItem:"Sample Rate = 22 KHz"]; [popup addItem:"Sample Rate = 11 KHz"]; [[popup setTarget:self] setAction:@selector(changeSampleRate:)]; NXAttachPopUpList (SampleButton, popup); return self; } -setConvertButton:anObject { ConvertButton = anObject; return self; } -setErrorText:anObject { ErrorText = anObject; [ErrorText setStringValue:""]; return self; } /* ------------------------------------------------------------------------------------ */ /* The following four methods are delegate methods that add functionality to the */ /* existing methods are already defined by the Application class. I believe that I */ /* am doing something wrong because I have been told that I shouldn't have to redefine */ /* the -unhide method. If you can tell what I am doing wrong I would greatly */ /* appreciate it. */ /* ------------------------------------------------------------------------------------ */ - appDidInit:sender { id theListener; id theSpeaker; unsigned int windowNum; theSpeaker = [NXApp appSpeaker]; NXConvertWinNumToGlobal([FrontEndWindow windowNum], &windowNum); theListener = [NXApp appListener]; [theListener setDelegate:self]; [theListener privatePort]; [theListener addPort]; [theSpeaker setSendPort: NXPortFromName(NX_WORKSPACEREQUEST, NULL)]; [theSpeaker registerWindow: windowNum toPort:[theListener listenPort]]; isPaused = FALSE; sampleRate = 1; NX_FREE( nextSoundName ); NX_MALLOC( nextSoundName, char, strlen( "" ) + 1 ); strcpy( nextSoundName, "" ); NX_FREE( macSoundName ); NX_MALLOC( macSoundName, char, strlen( "" ) + 1 ); strcpy( macSoundName, "" ); NX_FREE( iconPath ); NX_MALLOC( iconPath, char, strlen( "" ) + 1 ); strcpy( iconPath, "" ); NothingHere = TRUE; [ConvertButton setEnabled:NO]; return self; } - (int)iconEntered:(int)windowNum at:(double)x :(double)y iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY iconWidth:(double)iconWidth iconHeight:(double)iconHeight pathList:(const char *)pathList { NX_FREE( iconPath ); NX_MALLOC( iconPath, char, strlen( pathList ) + 1 ); strcpy( iconPath, pathList ); return 0; } - unhide:sender { [NXApp unhide:self]; return self; } - (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag { NXPoint iconViewOrigin; id currentIcon; BOOL OKflag; char *fileName; iconViewOrigin.x = iconViewOrigin.y = 0.0; NX_FREE( nextSoundName ); NX_MALLOC( nextSoundName, char, strlen( "" ) + 1 ); strcpy( nextSoundName, "" ); OKflag = [self setUpDraggedInFiles:self]; if( OKflag ) { NothingHere = FALSE; [NXApp activateSelf:YES]; [FrontEndWindow makeKeyAndOrderFront:self]; *flag = 1; [ErrorText setStringValue:""]; [ConvertButton setEnabled:YES]; [IconBox lockFocus]; currentIcon = [Bitmap findBitmapFor:"Macsnd"]; [currentIcon composite:NX_COPY toPoint:&iconViewOrigin]; [IconBox unlockFocus]; fileName = strrchr(macSoundName, '/'); fileName++; [NameView setStringValue:fileName]; /* This is probably a stupid way to do this but its quick */ [IconBox2 lockFocus]; currentIcon = [Bitmap findBitmapFor:"Blank"]; [currentIcon composite:NX_COPY toPoint:&iconViewOrigin]; [IconBox2 unlockFocus]; [NameView2 setStringValue:""]; } else { /* This is probably a stupid way to do this but its quick */ NothingHere = TRUE; [IconBox lockFocus]; currentIcon = [Bitmap findBitmapFor:"Blank"]; [currentIcon composite:NX_COPY toPoint:&iconViewOrigin]; [IconBox unlockFocus]; [NameView setStringValue:""]; [IconBox2 lockFocus]; currentIcon = [Bitmap findBitmapFor:"Blank"]; [currentIcon composite:NX_COPY toPoint:&iconViewOrigin]; [IconBox2 unlockFocus]; [NameView2 setStringValue:""]; [ConvertButton setEnabled:NO]; NX_FREE( macSoundName ); NX_MALLOC( macSoundName, char, strlen( "" ) + 1 ); strcpy( macSoundName, "" ); *flag = 0; } return 0; } /* ------------------------------------------------------------------------------------ */ /* This method checks to make sure that the file that has been dragged from the */ /* workspace is the proper type (ending with a ".macsnd" suffix). */ /* ------------------------------------------------------------------------------------ */ -setUpDraggedInFiles:sender { char *tab; char *extension; BOOL hadInvalid; hadInvalid = FALSE; if( iconPath ) { tab = strchr(iconPath,'\t'); if (tab) *tab = '\0'; extension = strrchr(iconPath,'.'); if (extension) { if (!strcmp(extension,".macsnd")) { NX_FREE( macSoundName ); NX_MALLOC( macSoundName, char, strlen( iconPath ) + 1 ); strcpy( macSoundName, iconPath ); } else { hadInvalid = TRUE; [ErrorText setStringValue:"NOT '.macsnd' Extension"]; } } else { hadInvalid = TRUE; [ErrorText setStringValue:"NOT '.macsnd' Extension"]; } } else [ErrorText setStringValue:"Workspace Error"]; if( hadInvalid ) return FALSE; else return TRUE; } /* ------------------------------------------------------------------------------------ */ /* The following three methods perform functions on the converted sound. I added this */ /* functionality so that the user can instantly tell if the conversion was completed */ /* succesfully. */ /* ------------------------------------------------------------------------------------ */ -playsound:sender { if( strcmp( nextSoundName, "" ) ) { if( currentSound ) [currentSound play]; else [ErrorText setStringValue:"Sound Not Initialized"]; } else [ErrorText setStringValue:"No NeXT Sound to Play"]; return self; } -stopsound:sender { if( strcmp( nextSoundName, "" ) ) { if( currentSound ) [currentSound stop]; else [ErrorText setStringValue:"Sound Not Initialized"]; } else [ErrorText setStringValue:"No NeXT Sound to Stop"]; return self; } -pausesound:sender { if( strcmp( nextSoundName, "" ) ) { if( currentSound ) { if( isPaused ) { isPaused = FALSE; [currentSound resume:self]; } else { isPaused = TRUE; [currentSound pause:self]; } } else [ErrorText setStringValue:"Sound Not Initialized"]; } else [ErrorText setStringValue:"No NeXT Sound to Pause"]; return self; } /* ------------------------------------------------------------------------------------ */ /* This method is activated when the user activates the PopUpList. It simply sets */ /* the sampleing rate for the user. */ /* ------------------------------------------------------------------------------------ */ -changeSampleRate:sender; { if( NothingHere ) [ConvertButton setEnabled:NO]; else [ConvertButton setEnabled:YES]; if( strcmp( [[sender selectedCell] title], "Sample Rate = 22 KHz" ) ) sampleRate = 0; else sampleRate = 1; return self; } /* ------------------------------------------------------------------------------------ */ /* This function takes care of most of the error checking and visual effects that take */ /* take place before the sound is converted. It changes the name of the original file */ /* and places the NeXT Sound icon in its respective dock. */ /* ------------------------------------------------------------------------------------ */ -convertMactoNeXT:sender { NXPoint iconViewOrigin; id currentIcon; char *fileName; char *tempName; iconViewOrigin.x = iconViewOrigin.y = 0.0; if( strcmp( macSoundName, "" ) ) { [IconBox2 lockFocus]; currentIcon = [Bitmap findBitmapFor:"Sound"]; [currentIcon composite:NX_COPY toPoint:&iconViewOrigin]; [IconBox2 unlockFocus]; NX_FREE( nextSoundName ); NX_MALLOC( nextSoundName, char, strlen( macSoundName ) + 1 ); strcpy( nextSoundName, macSoundName ); fileName = strrchr(nextSoundName, '/'); fileName++; tempName = fileName; while( *tempName++ != '.' ); strcpy( tempName, "snd\0" ); [NameView2 setStringValue:fileName]; [self _actualMactoNeXTcode:sampleRate]; currentSound = [Sound newFromSoundfile:nextSoundName]; [ErrorText setStringValue:""]; [ConvertButton setEnabled:NO]; return self; } else [ErrorText setStringValue:"No Sound to Convert"]; } /* ------------------------------------------------------------------------------------ */ /* This is the actual code that converts the Macintosh sound to a NeXT sound. I did */ /* not write this code it was written by Robert Hood. I honestly haven't even looked */ /* at this code. I hope to rewrite this function in a future release so that I can fix */ /* a known bug in it. */ /* ------------------------------------------------------------------------------------ */ -_actualMactoNeXTcode:(int)theSampleRate { FILE *input, *output; char filename [256], outname [256]; int temp,last; int fast; char temp2; unsigned char ch; strcpy (filename, macSoundName); fast = theSampleRate; if ((input = fopen (filename, "rb")) == 0) { perror (filename); exit (-1); } strcpy (outname, nextSoundName); if ((output = fopen (outname, "wb")) == 0) { perror (outname); exit (-1); } temp = 0x2E736E64; /* magic */ fwrite (&temp, 4, 1, output); temp = 0x0000001C; /* start of sound */ fwrite (&temp, 4, 1, output); temp = 0x98 + 1; /* end of sound...doesn't seem to matter */ fwrite (&temp, 4, 1, output); temp = 0x00000003; /* ?? */ fwrite (&temp, 4, 1, output); temp = 0x00005622; /* sample frequency */ fwrite (&temp, 4, 1, output); temp = 0x00000001; /* ?? */ fwrite (&temp, 4, 1, output); temp = 0x00000000; /* space filler? */ fwrite (&temp, 4, 1, output); temp = 0x00000000; /* space filler? */ fwrite (&temp, 4, 1, output); last = 0; while (!feof (input)) { ch = getc (input); temp = ch; temp = (128 - temp) * (int)64; if (!fast) /* 11 kHz is simulated by averaging the input */ { last = (last + temp) / 2; putc ((last >> 8) & 0xFF, output); putc ((last) & 0xFF, output); last = temp; } putc ((temp >> 8) & 0xFF, output); putc ((temp) & 0xFF, output); } fclose (input); fclose (output); } /* ------------------------------------------------------------------------------------ */ /* This brings up the GNU Panel which shows the Public GNU License. */ /* ------------------------------------------------------------------------------------ */ -showGNULicense:sender { if (myGNULicense == nil) myGNULicense = [GNULicense new]; /* Not really necessary, but kinda cutesy. */ if ([sender isKindOf:[Control class]] == YES) { [sender setTarget:myGNULicense]; [sender setAction:@selector (showLicense:)]; } [myGNULicense showLicense:self]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.