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.