//////////
//
//	File:		MyObject.m
//
//	Contains:	Implementation file for the MyObject class.
//
//	Written by:	Apple Developer Technical Support
//
//	Copyright:	© 2002 by Apple Computer, Inc., all rights reserved.
//
//	Change History (most recent first):
//	   
//	   <1>	 	5/20/02	srk		first file
//
//////////

/*
 IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. ("Apple")
 in consideration of your agreement to the following terms, and your use,
 installation, modification or redistribution of this Apple software constitutes
 acceptance of these terms.  If you do not agree with these terms, please do not use,
 install, modify or redistribute this Apple software.
 
 In consideration of your agreement to abide by the following terms, and subject to
 these terms, Apple grants you a personal, non-exclusive license, under Apple's
 copyrights in this original Apple software (the "Apple Software"), to use,
 reproduce, modify and redistribute the Apple Software, with or without
 modifications, in source and/or binary forms; provided that if you redistribute the
 Apple Software in its entirety and without modifications, you must retain this
 notice and the following text and disclaimers in all such redistributions of the
 Apple Software.  Neither the name, trademarks, service marks or logos of Apple
 Computer, Inc. may be used to endorse or promote products derived from the Apple
 Software without specific prior written permission from Apple. Except as expressly
 stated in this notice, no other rights or licenses, express or implied, are granted
 by Apple herein, including but not limited to any patent rights that may be
 infringed by your derivative works or by other works in which the Apple Software
 may be incorporated.
 
 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES
 OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
 THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR
 PRODUCTS.
 
 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING
 IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
 APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#import <QuickTime/QuickTime.h>
#import <Carbon/Carbon.h>

#import "MyObject.h"
#import "MyQuickDrawView.h"

@implementation MyObject

#define BailErr(x) {err = x; if(err != noErr) goto bail;}


/////////////////////////////////////////////////////////////////////////////////////
//
// Used by record mode only
//
/////////////////////////////////////////////////////////////////////////////////////

-(IBAction)inputText: (id)sender
{
    // Shouldn't record text if not recording!!!!!
    //NSTimeInterval pauseDuration;
    //static NSDate *lastInsertTime = gRecStartTime;
    
    NSString *inputStr = [textInput stringValue];
    if (![inputStr isEqualToString:@""])
    {
		//[gTextInputDict setObject:[textInput stringValue] forKey:[NSDate date]];
		NSTimeInterval pauseDuration;
		UserText *textData;
		// lastInsertTime will always be earlier than current time
		// we take the absolute value because the result of timeIntervalSinceNow
		// will always be negative
		
		NSLog(@"gLastTime = %@", [gLastInsertTime description]);
		pauseDuration = fabs([gLastInsertTime timeIntervalSinceNow]);
		NSLog(@"pauseDuration = %f", pauseDuration);
		
		// Create a UserText object and add it to the gCaption array
		textData = [[UserText alloc] init];
		if (textData)
		{
			[textData setDuration:pauseDuration];
			[textData setText:inputStr];
			[gCaption addObject:textData];
			[textData release];
		}
		
		[gLastInsertTime release];
		gLastInsertTime = [[NSDate date] retain];   // Set lastInsertTime to now
		NSLog(@"gLastTime 2 = %@", [gLastInsertTime description]);
    }
    else
    {
		NSLog(@"input string is empty");
    }
    
    // Make the text field active again after user hitting Enter
    [window makeFirstResponder: textInput];
}

-(OSErr)addTextToMovie
{
    MyMovieText *movieText = nil;
    OSErr err = noErr;
    
	/*
	int i;
	for (i = 0; i < [gCaption count]; i++)
	{
		UserText *textData = (UserText *)[gCaption objectAtIndex:i];
		//NSLog(@"duration = %f", [textData duration]);
		NSLog(@"duration = %f, text = %@", [textData duration], [textData text]);
	}
	 */
	
	movieText = [[MyMovieText alloc] init];
	NSAssert(movieText, @"movieText couldn't not be created");
	
	err = [movieText addCaptionToMovie:gCaption filename:gMovieFilename];
	if (err != noErr)
	{
		NSRunAlertPanel(@"Error", @"addCaptionToMovie failed", @"OK", nil, nil);
		return err;
	}
	
	return err;
}

-(IBAction)record: (id)sender
{
    OSErr err = noErr;
    
    // Create and initialise gCaption
    gCaption = [[NSMutableArray alloc] init];

    if (!gCaption)
        BailErr(kMyErrorCode);
    
    // Create and initialise gMyVideo
    gMyVideo = [[MyVideo alloc] init];

    if (!gMyVideo)
        BailErr(kMyErrorCode);
    
    // Pass gMyVideo object to MyQuickDrawViewClass because
    // we need to use the same MyVideo object over there for recording
    [view setMyMovie:gMyVideo];
    
    // Get the filename from user, but we must first relinquish the old one
    [gMovieFilename release];					
    gMovieFilename = [[gMyVideo promptMovieFilename] retain];   

    if (!gMovieFilename)
        BailErr(kMyErrorCode);
    
    // Create the movie file
    err = [gMyVideo createMovie:[view boundsRect] gWorld:[view gworld] 
		    filename:gMovieFilename];
    BailErr(err);
    
    // Configure the user interface accordingly
    [recordButton setEnabled:NO];   // disable record button
    [pauseButton setEnabled:YES];   // enable pause button
    [stopButton setEnabled:YES];    // enable stop button
    [textInput setEnabled:YES];	    // enable text input
    [view setRecording:YES];        // start recording
    [self sizeIndicatorInit];       // initialise and start
                                    // the movie size indicator
    
    // start time of recording, used in addTextToMovie()
    gLastInsertTime = [[NSDate date] retain];

    if (!gLastInsertTime)
        BailErr(kMyErrorCode);
	
    NSLog(@"time in str = %@", [gLastInsertTime description]);

    bail:
    // Cleanup code if something goes wrong
    if (err != noErr)
    {
        if (gCaption)
        [gCaption release];
		
        if (gMyVideo)
        {
            [gMyVideo closeMovie];
            [gMyVideo release];
            NSRunAlertPanel(@"Error", @"Record failed", @"OK", nil, nil);
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////////
//
// Used by both record and playback modes
//
/////////////////////////////////////////////////////////////////////////////////////

-(IBAction)pause: (id)sender
{
    // if in recording mode
    // else in playback mode
    if (!gPlaybackMode)
    {   
        BOOL recording;

        recording = [view recording];
        [view setRecording:!recording];
    }

    else
    {
        [movieView setEditable:YES];
        [movieView stop:sender]; // Stops movieview at current position
                                 // It can resume playback from
                                 // this position, not beginning

        [closeMovieMenuItem setEnabled:YES];
			 
        [pauseButton setEnabled:NO];
        [playButton setEnabled:YES];
    }
}

-(IBAction)stop: (id)sender
{
    if (!gPlaybackMode) // if in recording mode
    {
        [view setRecording:NO];	  // stop recording
        [gMyVideo closeMovie];	  // close movie file
        [gMyVideo release];       // free resources used by gMyVideo

        [gSizeIndicatorTimer invalidate];   // stop size indicator timer
        [gSizeIndicatorTimer release];      // release timer resource

        [stopButton setEnabled:NO];     // disable stop button
        [recordButton setEnabled:YES];  // enable record button
        [pauseButton setEnabled:NO];    // disable pause button

        gStopTime = [NSDate date];      // stop time of recording
        NSLog(@"before stop");
	
        // Add caption to movie (if we have any)
        if ([gCaption count] > 0)
            [self addTextToMovie];

        [gCaption release];
        NSLog(@"after stop");
    }

    else // it is in playback mode
    {
        [movieView setEditable:YES];
        [movieView stop:sender];            // stop movie at current spot
        [movieView gotoBeginning:sender];   // reset position to the beginning

        [closeMovieMenuItem setEnabled:YES];
	
        [pauseButton setEnabled:NO];
        [playButton setEnabled:YES];
        [stopButton setEnabled:NO];

        [gPlaybackTimer invalidate];   // stop playback timer
        [gPlaybackTimer release];      // release timer resource
    }
}



/////////////////////////////////////////////////////////////////////////////////////
//
// Used by playback only - buttons
//
/////////////////////////////////////////////////////////////////////////////////////

//////////
//
// play
// 
// plays the opened movie
//
//////////

-(IBAction)play : (id)sender
{
    [movieView start:sender];
    [movieView setEditable:NO];

    [pauseButton setEnabled:YES];
    [playButton setEnabled:NO];
    [stopButton setEnabled:YES];

    [closeMovieMenuItem setEnabled:NO];
    
    gPlaybackTimer = 
       [[NSTimer scheduledTimerWithTimeInterval:kTimeSliderUpdateInterval
                                         target:self
                                       selector:@selector(updatePlaybackTimedUIObjects:)
                                       userInfo:nil
                                        repeats:YES] retain];
}

-(IBAction)gotoBeginning : (id)sender
{
    [movieView gotoBeginning:sender];
}

// movie autoloops when end is reaches so basically redundant unless
// loop is turned off
-(IBAction)gotoEnd : (id)sender
{
    [movieView gotoEnd:sender];
}

-(IBAction)setSelectBeginning : (id)sender
{
    gSelectBeginningTime = GetMovieTime([gOpenedMovie QTMovie], nil);

    NSLog(@"Beginning select time is %d secs", (long)gSelectBeginningTime);
}


// only sets duration on setSelectEnd
// if beginning time changes after that, duration is still the previous
// if selectend is selected first, the duration is from the start of movie
-(IBAction)setSelectEnd : (id)sender
{
    gSelectEndTime = GetMovieTime([gOpenedMovie QTMovie], nil);

    // Duration of selection is time between beginning and end
    // Doesn't matter if end is before beginning, accounts for it
    gDuration = abs(gSelectEndTime - gSelectBeginningTime);

    if (gSelectEndTime < gSelectBeginningTime)
        gSelectBeginningTime = gSelectEndTime;

    NSLog(@"Selection duration is %d secs", (long)gDuration);
}

/////////////////////////////////////////////////////////////////////////////////////
//
// Used by playback only - menu items
//
/////////////////////////////////////////////////////////////////////////////////////

//////////
//
// openMovie
// 
// Opens a dialog box allowing the user to select a movie file to open for playback
//
//////////

-(IBAction)openMovie : (id)sender
{
    int result;
    TimeValue movieDuration;

    NSArray *fileTypes = [NSArray arrayWithObject:@"mov"];
    NSOpenPanel *op = [NSOpenPanel openPanel];
    [op setAllowsMultipleSelection:NO];
    [op setCanChooseFiles:YES];
    [op setCanChooseDirectories:NO];

    result = [op runModalForDirectory:NSHomeDirectory() file:nil types:fileTypes];

    if (result == NSOKButton)
    {
        NSArray *movieToOpen = [op URLs];
        NSURL *movieURL = [movieToOpen objectAtIndex:0];
        gOpenedMovie = [[NSMovie alloc] initWithURL:movieURL byReference:NO];
        [movieView setMovie:gOpenedMovie];
        [movieView showController:NO adjustingSize:NO];
        [movieView setLoopMode:NSQTMovieLoopingPlayback];

        movieDuration = GetMovieDuration([gOpenedMovie QTMovie]);
        [timeSlider setEnabled:YES];
        [timeSlider setMaxValue: (double)movieDuration];

        BOOL opened = YES;
        [self openGUIUpdate:opened];
    }
}

-(IBAction)closeMovie : (id)sender
{
    BOOL opened = NO;
    [self openGUIUpdate:opened];

    [gOpenedMovie release];
}

-(IBAction)saveMovie : (id)sender
{
    OSErr err = noErr;
    int runResult;

    NSSavePanel *sp = [NSSavePanel savePanel];

    [sp setRequiredFileType:@"mov"]; // must have extension .mov


    // display the NSSavePanel
    // if successful, save file under designated name
    runResult = [sp runModalForDirectory:NSHomeDirectory() file:nil];

    // run if save button is pressed
    if (runResult == NSOKButton)
    {
        FSSpec myFSSpec;
        Movie aMovie;
        NSString *filename;
        NSString *filenameWithExtension;
        NSRange range;

	filename = [sp filename];   // get filename entered from save panel

        // search for extension .mov
	range = [filename rangeOfString:@".mov"
                                options:(NSCaseInsensitiveSearch|NSBackwardsSearch)];

        // if .mov extension not found in filename entered by user, add extension
	// else .mov extension found so leave filename entered as is
	if ((range.location == NSNotFound) && (range.length == 0))
            filenameWithExtension = [filename stringByAppendingString:@".mov"];
        else
            filenameWithExtension = [filename copy];

        err = [MyVideo myMakeFSSpec:&myFSSpec fromPath:filenameWithExtension];

	// save movie to filename specified by user in save panel
        aMovie = FlattenMovieData([gOpenedMovie QTMovie], flattenAddMovieToDataFork,
                                    &myFSSpec, FOUR_CHAR_CODE('TVOD'),
                                    smSystemScript,
                                    createMovieFileDeleteCurFile |
				    createMovieFileDontCreateResFile); 

        DisposeMovie(aMovie);
    }
}

-(IBAction)deleteSelection : (id)sender
{
    SetMovieSelection([gOpenedMovie QTMovie], gSelectBeginningTime, gDuration);

    ClearMovieSelection([gOpenedMovie QTMovie]);

    NSLog(@"Selection deleted");
}

/////////////////////////////////////////////////////////////////////////////////////

-(IBAction)playbackModeChanged : (id)sender
{
    int radioButtonMode = [[sender selectedCell] tag]; 
    BOOL playbackMode;

    switch(radioButtonMode)
    {
        case PLAYBACK:
        {
            playbackMode = TRUE;
            [recordButton setEnabled:NO];
            [textInput setEnabled:NO];
        }
        break;

        case RECORD:
        {
            playbackMode = FALSE;
            [recordButton setEnabled:YES];
            [textInput setEnabled:YES];
        }
        break;
    }

    gPlaybackMode = playbackMode;

    [self playbackModeMenuUpdate:playbackMode];
    [self openGUIUpdate:NO];
}

//////////
//
// timeSliderMoved
// 
// updates the current movie time when the time slider is moved manually
//
//////////

-(IBAction)timeSliderMoved : (id)sender
{
    double currentSliderValue;
    currentSliderValue = [sender doubleValue]; // get the value from the slider
    SetMovieTimeValue([gOpenedMovie QTMovie], currentSliderValue);
}

-(IBAction)contrastCheckBoxChanged : (id)sender
{
    BOOL boolValue;

    // if checkbox is not ticked, contrast not enabled
    // else checkbox is ticked, contrast enabled
    if ([sender state] == NSOffState)
        boolValue = NO;
    else
        boolValue = YES;

    // if contrast is not enabled, disable the color wells and threshold
    [lightColorWell setEnabled:boolValue];
    [darkColorWell setEnabled:boolValue];
    [thresholdField setEnabled:boolValue];
}

//////////
//
// contrastApply
// 
// Sets the user selected contrast colors and the
// threshold value when the OK button is pressed
//
//////////

-(IBAction)contrastApply : (id)sender
{
    // Allow the contrast function to process each frame
    if ([contrastCheckBox state] == NSOnState)
        [view setContrastEnable:YES];
    else
        [view setContrastEnable:NO];

    [view setThreshold:[thresholdField intValue]];

    [view setThresholdColors:[lightColorWell color]:[darkColorWell color]];
}

/////////////////////////////////////////////////////////////////////////////////////
//
// Initialise GUI components
//
/////////////////////////////////////////////////////////////////////////////////////

-(void)contrastSettingsInit
{
    // Initialise contrast settings
    [contrastCheckBox setState:NSOffState];
    [contrastCheckBox setAllowsMixedState:NO]; // only on/off state
    [self thresholdFieldInit];
}

-(void)thresholdFieldInit
{
    NSDecimalNumber *dNumMin = [[[NSDecimalNumber alloc] init] autorelease];
    NSDecimalNumber *dNumMax = [[[NSDecimalNumber alloc] init] autorelease];
    NSNumberFormatter *thresholdNumberFormatter = [[[NSNumberFormatter alloc] init] autorelease];

    dNumMin = [NSDecimalNumber decimalNumberWithString:@"0"];
    dNumMax = [NSDecimalNumber decimalNumberWithString:@"100"];

    [thresholdNumberFormatter setAllowsFloats:NO];
    [thresholdNumberFormatter setMinimum:dNumMin];
    [thresholdNumberFormatter setMaximum:dNumMax];

    [[thresholdField cell] setFormatter:thresholdNumberFormatter];

    [thresholdField setStringValue:@"50"];
}

//////////
//
// sizeIndicatorInit
// 
// Initialises the settings of the filesize progress indicator ready for display
//
//////////

-(void)sizeIndicatorInit
{
    [sizeIndicator setStyle:NSProgressIndicatorBarStyle];
    [sizeIndicator setIndeterminate:FALSE];
    [sizeIndicator setDisplayedWhenStopped:YES];
    [sizeIndicator setControlSize:NSSmallControlSize];
    [sizeIndicator setControlTint:NSClearControlTint];
    [sizeIndicator setBezeled:YES];

    // Set the limits of the indicator
    [sizeIndicator setMinValue:kSizeIndicatorMin];
    [sizeIndicator setMaxValue:kSizeIndicatorMax];

    gSizeIndicatorTimer =
       [[NSTimer scheduledTimerWithTimeInterval:kSizeIndicatorInterval
                                         target:self
                                       selector:@selector(sizeIndicatorUpdate:)
                                       userInfo:nil
                                        repeats:YES] retain];
}



/////////////////////////////////////////////////////////////////////////////////////
//
// Update various GUI components
//
/////////////////////////////////////////////////////////////////////////////////////

-(void)openGUIUpdate : (BOOL)opened
{
    BOOL closed = !opened;

    [pauseButton setEnabled:opened];
    [playButton setEnabled:opened];
    [stopButton setEnabled:opened];
    
    [gotoBeginningButton setEnabled:opened];
    [gotoEndButton setEnabled:opened];
    [setSelectBeginningButton setEnabled:opened];
    [setSelectEndButton setEnabled:opened];

    [openMovieMenuItem setEnabled:closed];
    [closeMovieMenuItem setEnabled:opened];
    [saveAsMenuItem setEnabled:opened];
    [deleteSelectionMenuItem setEnabled:opened];
}


//////////
//
// updatePlaybackTimedUIObjects
// 
// updates the time slider and the time display at set time intervals
//
//////////

-(void)playbackModeMenuUpdate : (BOOL)playbackMode
{
    BOOL recordMode = !playbackMode;

    [openMovieMenuItem setEnabled:playbackMode];
    [closeMovieMenuItem setEnabled:NO];
    [saveAsMenuItem setEnabled:NO];
    
    [contrastMenuItem setEnabled:recordMode];
}

//////////
//
// sizeIndicatorUpdate
// 
// Updates the filesize indicator display every time the timer reaches its update interval
//
//////////

-(void)sizeIndicatorUpdate : (id)sender
{
    // if movie size has reached limit
    // else movie size still within limit so just update progres indicator
    if ([sizeIndicator doubleValue] >= kSizeIndicatorMax)
    {
        NSRunAlertPanel(@"Error", @"Maximum movie filesize reached", @"OK", nil, nil);
        [gSizeIndicatorTimer invalidate];
    }
    else
    {
        // change colour to warn user they are at 90% movie capacity
        if (([sizeIndicator doubleValue] / kSizeIndicatorMax) >= 0.9)
            [sizeIndicator setControlTint:NSDefaultControlTint];

        // set size indicator value so it can display the current movie size
        [sizeIndicator setDoubleValue:[gMyVideo myGetMovieSize:gMovieFilename]];
    }
}


-(void)updatePlaybackTimedUIObjects : (id)sender
{
    double currentMovieTime;

    // if movie is at end of file while playing
    // else movie is not at end of file
    if (IsMovieDone([gOpenedMovie QTMovie]))
    {
        [movieView setEditable:YES];
        [movieView stop:sender];          // stop movie at current spot
        [movieView gotoBeginning:sender]; // reset position to the beginning

        [gPlaybackTimer invalidate]; // stop playback timer
        [gPlaybackTimer release];    // release timer resource
    }
    else
    {
        currentMovieTime = [self getCurrentMovieTime];

        // update slider
	[timeSlider setDoubleValue:(currentMovieTime)]; // update slider
        // update time display
	[timeDisplay setStringValue:[self timeStringCreate:currentMovieTime]];
    }
}



/////////////////////////////////////////////////////////////////////////////////////
//
// User functions
//
/////////////////////////////////////////////////////////////////////////////////////

//////////
//
// getCurrentMovieTime
// 
// returns the current movie time in terms of milliseconds instead of seconds
//
//////////

-(double)getCurrentMovieTime
{
    TimeValue currentTime;
    TimeRecord timeRecord;

    timeRecord.scale = kScale;
    timeRecord.base = nil;

    currentTime = (double)GetMovieTime([gOpenedMovie QTMovie], nil);

    return (currentTime);
}


//////////
//
// timeStringCreate
// 
// returns the current movie time as a string of the format
// "hours:mins:secs.millisecs"
//
//////////

-(NSString *)timeStringCreate : (double)timeIn
{
    NSString *timeString;
    int hours, mins, secs, millis, numSecs;

    numSecs = (int)floor(timeIn/kScale);
    hours = (int)(numSecs/3600);
    mins = (int)((numSecs - (hours * 3600))/60);
    secs = numSecs % 60;
    millis = (int)(((timeIn/kScale) - numSecs) * kScale);

    timeString = [NSString stringWithFormat:@"%02d:%02d:%02d.%03d",
                           hours, mins, secs, millis];

    return timeString;
}




// delegate for threshold field, to keep the values between 0 and 100
-(BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error
{
    if(control == thresholdField)
    {
        NSRunAlertPanel(@"Error", @"Threshold value not within range", @"OK", nil, nil);
        return NO;
    }

    return YES;
}

/////////////////////////////////////////////////////////////////////////////////////
//
// NSObject subclass overrides
//
/////////////////////////////////////////////////////////////////////////////////////

//////////
//
// init
//
// Our controller's initialization method. Well
// add our self as an observer for application
// termination notifications, so we can perform
// cleanup when the application quits.
//
//////////

- (id)init
{
    /* we'll want to be called when the application
     quits so we can do any cleanup */
     
    [[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(applicationWillTerminate:)
        name:@"NSApplicationWillTerminateNotification" object:NSApp];

    //gTextInputDict = [[NSMutableDictionary alloc] init];
    
    return self;
}


//////////
//
// awakeFromNib
//
// Called after all our objects are unarchived and
// connected but just before the interface is made visible
// to the user. We will do custom initialization of our
// objects here.
//
//////////

- (void)awakeFromNib
{
    NSString 		*windowTitle;
    OSErr 			err;

    /* set the window title */
    windowTitle = @"iView";
    [window setTitle:windowTitle];
    
    /* pass our view object to our MyQuickDrawView class so we can access methods
        in this class from our C code routines */
    saveQDViewObjectForCallback(view);

    [view setContrastEnable:NO];

    /* now lets create a window and display the video data passed to us by the sequence grabber */
    err = [view doSeqGrab:[view bounds]];

    // Initialise view object
    //[view myInit];
    
    /* put up an error dialog to display any errors */
    if (err != noErr)
    {
        NSString *errorStr = [[NSString alloc] initWithFormat:@"%d" , err];
        int choice;

        /* now display error dialog and quit */
        choice = NSRunAlertPanel(@"Error", errorStr, @"OK", nil, nil);
        [errorStr release];
    }
    
    // disable stop button, pause button and text field
    [pauseButton setEnabled:NO];
    [stopButton setEnabled:NO];
    [textInput setEnabled:NO];

    gPlaybackMode = NO; // when app first starts, start in recording mode, not playback
    [self playbackModeMenuUpdate:gPlaybackMode];

    BOOL opened = NO;
    [self openGUIUpdate:opened];

    [openMovieMenuItem setEnabled:NO];
    [closeMovieMenuItem setEnabled:NO];
    [saveAsMenuItem setEnabled:NO];
    [deleteSelectionMenuItem setEnabled:NO];
    [contrastMenuItem setEnabled:YES];

    [self contrastSettingsInit];
}


//////////
//
// applicationWillTerminate
//
// We'll release any objects we initialised
// in our init method.
//
//////////

- (void)applicationWillTerminate:(NSNotification *)notification
{
    [view endGrab];
	[gLastInsertTime release];
    //[gTextInputDict release];
    [gMovieFilename release];
}

@end

