home *** CD-ROM | disk | FTP | other *** search
- /* ----------------------------------------------------------------------------------- */
- /* 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
-