/*
 * You may freely copy, distribute and reuse the code in this example.  
 * NeXT disclaims any warranty of any kind, expressed or implied, as to 
 * its fitness for any particular use.
 */


#import "SoundController.h"
#import "SaveToController.h"
#import "SoundDocument.h"
#import <soundkit/soundkit.h>
#import <appkit/Application.h>
#import <appkit/OpenPanel.h>
#import <appkit/Cursor.h>
#import <appkit/Button.h>
#import <appkit/Panel.h>
#import <appkit/publicWraps.h>	/* for NXBeep() */
#import <sys/param.h> 		/* for MAXPATHLEN */
#import <string.h>
#import <objc/NXStringTable.h>

static char pathname[1024];

static BOOL getOpenPath(char *buf, char const *theType)
{
    static id openPanel = nil;
    char const *fileTypes[2] = {0,0};
    int opr;

    if (!openPanel)
        openPanel = [OpenPanel new];
    if (theType && *theType)
	fileTypes[0] = theType;
    [NXApp setAutoupdate:NO];
    
    if (*buf)
      opr = [openPanel runModalForDirectory:buf
		 file:NULL types:fileTypes];
    else
      opr = [openPanel runModalForDirectory:"/NextLibrary/Sounds" 
	 file:"Basso.snd" types:fileTypes];
    if (opr) {
	strcpy(buf,[openPanel filename]);
	[NXApp setAutoupdate:YES];
	return YES;
    } else {
	[NXApp setAutoupdate:YES];
	return NO;
    }
}


static BOOL getSavePath(char *buf, char const *defaultPath, View *accessory)
{
    static id	savePanel = nil;
    BOOL	ok;
    char	dirName[1024], fileName[256];

    if (!savePanel) {
        const char *const types[2] = {"snd", NULL};
        savePanel = [SavePanel new];
        [savePanel setRequiredFileType:types[0]];
    }
    [savePanel setAccessoryView:accessory];
    [NXApp setAutoupdate:NO];
    if (defaultPath &&faultPath) {
	char *p;
	strcpy(dirName,defaultPath);
	if (p = rindex(dirName,'/')) {
	    strcpy(fileName, p+1);
	    *p = '\0';
	} else {
	    strcpy(fileName,defaultPath);
	    fileName[0] = '\0';
	}
	ok = [savePanel runModalForDirectory:dirName file:fileName];
    } else 
	ok = [savePanel runModal];
    [NXApp setAutoupdate:YES];
    if (ok) {
	strcpy(buf,[savePanel filename]);
	return YES;
    } else 
	return NO;
}


@implementation SoundController

- init
{
    [super init];
    [controlPanel removeFromEventMask:(NX_KEYDOWNMASK|NX_KEYUPMASK)];
    [controlPanel setFloatingPanel:YES];
    return self;
}

- appDidInit:sender
{
    [self newSoundDoc:self];   /* User Interface guidelines recommend opening 
				a new document at launch time.  We do this in
				appDidInit: rather than init to make sure that
				the stringTable has been unarchived */ 
    return self;
}

- info:sender
{
    if (!infoPanel)
	[NXApp loadNibSection:"InfoPanel.nib" owner:self];
    [infoPanel orderFront:self];
    return self;	
}

- newSoundDoc:sender
{
    static char filenamebuf[MAXPATHLEN+1];
    strcpy(filenamebuf, [[OpenPanel new] directory]);
				/* doesn't instantiate a new OpenPanel 
				   if one already exists */
    strcat(filenamebuf,[stringTable valueForStringKey:"/UNTITLED"]);
    [self setDocument:[[SoundDocument alloc] init]];
    [currentDocument setFileName:filenamebuf];
    return self;
}


- setDocument:aDocument
{
    [self stop:nil];
    currentDocument = aDocument;
    [recordButton setEnabled:([currentDocument isRecordable]? YES : NO)];
    [playButton setEnabled:YES];
    [currentDocument setDelegate:self];
    return self;
}

- document
{
    return currentDocument;
}

- openFile:(char *)fileName
{
    id newDocument;
    newDocument = [[SoundDocument alloc] init];
    [newDocument setFileName:fileName];
    [newDocument load:nil];
    [self setDocument:newDocument];
    return self;
}

- open:sender
{
    if (getOpenPath(pathname,"snd"))
	[self openFile:pathname];
    return self;
}

- saveAs:sender withAccessory:accessory
{
    char pathname[1024];
    id doc = currentDocument;
    if (accessory)
	[saveToController setSound:[doc sound]];
    if (doc && getSavePath(pathname,[doc fileName],accessory)) {
	if (accessory)
	    [doc saveToFormat:[saveToController soundTemplate]
	         fileName: pathname];se {
	    [doc setFileName:pathname];
	    [doc save:sender];
	}
    }
    return self;
}

- saveAs:sender
{
    return [self saveAs:sender withAccessory:nil];
}

- saveTo:sender
{
    return [self saveAs:sender withAccessory:saveToAccessoryView];
}

- save:sender
{
    if (currentDocument) {
	if ([currentDocument fileName]
	        && strcmp(strrchr([currentDocument fileName],'/'),"/UNTITLED"))
	    [currentDocument save:sender];
	else
	    [self saveAs:sender];
    }
    return self;
}

- revertToSaved:sender
{
    if (currentDocument)
	[currentDocument revertToSaved:sender];
    return self;
}

- play:sender
{
    if (![currentDocument isPlayable]) {
	NXBeep();
	return nil;
    }
    if (currentDocument) {
	[playButton setEnabled:NO];
	[recordButton setEnabled:NO];
	[stopButton setEnabled:YES];
	[pauseButton setState:0];
	[currentDocument play:sender];
    }
    return self;
}

- willPlay:sender
{
    [meter setSound:[sender soundBeingProcessed]];
    [meter run:self];
    return self;
}

- didPlay:sender
{
    [playButton setState:0];
    [playButton setEnabled:YES];
    [recordButton setState:0];
    [recordButton setEnabled:YES];
    [pauseButton setState:0];
    [meter stop:self];
    return self;
}

- stop:sender
{
    if (currentDocument)
	[currentDocument stop:sender];
    [playButton setState:0];
    [playButton setEnabled:YES];
    [recordButton setState:0];
    [recordButton setEnabled:YES];
    [pauseButton setState:0];
    return self;
}

- pause:sender
{
    if (!currentDocument || (![playButton state] && ![recordButton state])) {
	[pauseButton setState:0];
	return self;
    } else if ([pauseButton state])
	[currentDocument pause:self];
    else
	[currentDocument resume:self];
    return self;
}

- record:sender
{
    if (currentDocument) {
	[recordButton setEnabled:NO];
	[playButton setEnabled:NO];
	[stopButton setEnabled:YES];
	[currentDocument record:sender];
    }
    return self;
}

- willRecord:sender
{
    [meter setSound:[sender soundBeingProcessed]];
    [meter run:self];
    return self;
}

- didRecord:sender
{
    [playButton setState:0];
    [playButton setEnabled:YES];
    [recordButton setState:0];
    [recordButton setEnabled:YES];
    [pauseButton setState:0];
    [meter stop:self];
    return self;
}

- soundDidChange:sender
{
    if (currentDocument)
    	[currentDocument t];
    return self;
}

- hadError:sender
{
    int err = [[sender soundBeingProcessed] processingError];

    if ([playButton state])
	NXRunAlertPanel([stringTable valueForStringKey:"Play error"],
	    SNDSoundError(err),
	    [stringTable valueForStringKey:"OK"],
	    NULL,NULL);
    else if ([recordButton state])
	NXRunAlertPanel([stringTable valueForStringKey:"Record error"],
	    SNDSoundError(err),
	    [stringTable valueForStringKey:"OK"],
	    NULL,NULL);
    return [self stop:self];
}

- appDidHide:sender
{
    [self stop:nil];
    return self;
}

- appDidBecomeActive:sender
{
    [controlPanel orderFront:nil];
    return self;
}

- stringTable
{
    return stringTable;	
}

@end
