
/* Generated by Interface Builder */

#import "Manager.h"
#import <strings.h>
#import <math.h>
#import <defaults/defaults.h>
#import <bsd/libc.h>
#import <streams/streams.h>



int tagToChan[5] = {4,2,0,1,3};
int chanToTag[5] = {2,3,1,4,0};

@implementation Manager

- (int)app:sender openFile:(const char *)path type:(const char *)type
{
int i;

    files = (char**)malloc(10*sizeof(char*));
    for(i=1;i<10;i++)
	files[1]=NULL;
    files[0]=(char*)rindex(path,'/')+1;
    files[0][-1]=(char)0;
    direct=(char*)path;
    fprintf(stderr,"Dir: %s File %s\n", direct, files[0]);
    [self doOpenSound:1];
    return 1;
}

/* appAcceptsAnotherFile -- our app accepts to open files from the workspace
 */
- (BOOL)appAcceptsAnotherFile:sender
{
    return YES;
}


/* regDefaults: -- To register default values */

- regDefaults:sender
{
const char temp[128];

    defSrate = samplingRate[currentSound];
    [loadForm setIntValue:defSrate];
    defLength = lengthplayed[currentSound];
    sprintf((char*) temp,"%d", defSrate);
    NXWriteDefault((const char*)"Niveaux",(const char*)"SRate",temp);
    sprintf((char*) temp,"%d",[[outputMatrix selectedCell] tag]);
    NXWriteDefault((const char*)"Niveaux",(const char*)"Output",temp);
    return self;
}

- useDefaults:sender
{
    samplingRate[currentSound] = defSrate;
    lengthplayed[currentSound] = defLength;
    [sampRateForm setIntValue:defSrate];
    return self;
}

// The following method is necessary because when you click on the
// Inspector Panel, it becomes Key (and first Responder) and Manager
// no longer responds to key events! Since Manager is the Inspector's
// delegate, it will receive the following message each time the
// Inspector becomes key, and make Manager the Inspector's first
// responder.
- windowDidBecomeKey:sender	 
{
    [sender makeFirstResponder:self];
    return self;
}

- appWillInit:sender
{
int i;
const char *defOutput, *defSRateTmp;

    defOutput=NXGetDefaultValue((const char*)"Niveaux",(const char*)"Output");
    defSRateTmp=NXGetDefaultValue((const char*)"Niveaux",(const char*)"SRate");

    fprintf(stderr,"defOutput %s defSRateTmp %s\n", defOutput, defSRateTmp);
    if(defOutput == 0 || defSRateTmp == 0)
    {
	NXWriteDefault((const char*)"Niveaux",(const char*)"Output",
		(const char*)"0");
	NXWriteDefault((const char*)"Niveaux",(const char*)"SRate",
		(const char*)"16000");
	defSrate = 16000;
    }
    else
    {
	defSrate = atoi(defSRateTmp);
	i=atoi(defOutput);
	[outputMatrix selectCellWithTag:i];
	[playObject setOutput:i];
    }
	
    for(i=0;i<10;i++)
	scaleFactor[i] = 1.0;
    openPanel = [OpenPanel new];
    [openPanel allowMultipleFiles:YES];
    [openPanel setDelegate:self];
    [openPanel setAccessoryView:loadView];
    [loadForm setIntValue:defSrate];
    [playObject setMonoMode:MONO];
    [playObject setDelegate:self];
    firstTime = 1;
    Nmax = 0;
    defLength = 0;
    ALL_PLAY = 0;
    silence = 0;
    generalVol = 1;
    return self;
}

- saveSound:sender
{
static int firstTimeSave=1;
int i=0,j,file_numb,ans;
short *stemp;
char temp[200];
    
    if(Nmax == 0 || Nmax == -1) return self;
    if(firstTimeSave)
    {
	strcpy(saveDir,direct);
	firstTimeSave = 0;
    }	
    [saveDirCell setStringValue:saveDir at:0];
    ans = 1;
    while(ans != 0)
    {
	ans = [NXApp runModalFor:savePanel];
	[messageForm setStringValue:" "];
fprintf(stderr,"End of runModal! ans= %d directory %s\n", ans,saveDir);
	if(ans) for(i=0;i<Nmax;i++)
	{
	    SNDGetDataPointer(sounds[i], (char**) &stemp, &j, &j);
	    strcpy(temp, saveDir);
	    strcat(temp, "/");
	    strcat(temp, filenames[i]);
	    file_numb = open(temp,O_RDWR|O_CREAT,0644);
	    if(file_numb == -1) 
	    {
	    fprintf(stderr,"Can't write!! %s\n", temp);
		break;
	    }
	    else write(file_numb, stemp, N[i]*sizeof(short));
	}
	if(i == Nmax) ans = 0;
	else [messageForm setStringValue:"Invalid Directory"];
    }
    [messageForm setStringValue:" "];
    return self;
}

- adjustAmp:sender
{
int i;

    i = [[sender selectedCell] tag];
    scaleFactor[i] = [sender floatValue];
    [ampForm selectCellWithTag:i];
    [[ampForm selectedCell] setFloatValue:scaleFactor[i]];
    currentSound = i;
    return self;
}

- rescaleAmp:sender
{
int i,j;
float scalefactor;
short *stemp;

    for(i=0;i<Nmax;i++)
    {
	if(fabs(scaleFactor[i] - 1) < 0.0001) continue;
	SNDGetDataPointer(sounds[i], (char**) &stemp, &j, &j);
	scalefactor = scaleFactor[i];
	for(j=0;j<N[i];j++)
	    *stemp++ *= scalefactor;
	scaleFactor[i] = 1;
	[sliderMatrix selectCellWithTag:i];
	[[sliderMatrix selectedCell] setFloatValue:1];
	[ampForm selectCellWithTag:i];
	[[ampForm selectedCell] setStringValue:"1.00"];
    }
    return self;
}

- openSound:sender
{
int i;
const char *foo;

    [openPanel setAccessoryView:loadView];
    [openPanel setTitle:(const char *)"Close Sounds and Open"];
    if(firstTime)
    {
	foo = ((Nmax) ? directories[Nmax-1] : NXHomeDirectory());
	i=[openPanel runModalForDirectory:foo file:""];
    }
    else
	i=[openPanel runModalForDirectory:[openPanel directory] file:""];
    firstTime = 0;
    files = (char**) [openPanel filenames];
    direct = (char*) [openPanel directory];
    if(i) [self doOpenSound:0];
    return self;
}

- openMoreSound:sender
{
int i;
const char *foo;

    [openPanel setAccessoryView:loadView];
    [openPanel setTitle:(const char *)"Open                  "];
    if(firstTime)
    {
	foo = ((Nmax) ? directories[Nmax-1] : NXHomeDirectory());
	i=[openPanel runModalForDirectory:foo file:""];
    }
    else
	i=[openPanel runModalForDirectory:[openPanel directory] file:""];
    firstTime = 0;
    files = (char**) [openPanel filenames];
    direct = (char*) [openPanel directory];
    if(i) [self doOpenSound:1];
    return self;
}

- (int) doOpenSound:(int)more
{
int i,j;

    if(!more) [self closeSound:self];
    i=((more) ? Nmax : 0);
    for(j=0; files != NULL && files[j] != NULL && i<10 && j<10; i++,j++)
	[self doOpenOneSound:files[j]:direct:[loadForm intValue]];
    Nmax = i;
    for(i=Nmax;i<10;i++)
    {
	[buttonMatrix selectCellWithTag:i];
	[sliderMatrix selectCellWithTag:i];
	[openMatrix selectCellWithTag:i];
	[inspectMatrix selectCellWithTag:i];
	[[buttonMatrix selectedCell]  setEnabled:NO];
	[[sliderMatrix selectedCell]  setEnabled:NO];
	[[openMatrix selectedCell]  setEnabled:NO];
	[[inspectMatrix selectedCell]  setEnabled:NO];
	[fieldMatrix setStringValue:" " at:i];
    }
    [generalVolSlider  setEnabled:(Nmax != 0)];
    [[NXApp keyWindow] addToEventMask:NX_KEYDOWNMASK|NX_KEYUPMASK];
    [[NXApp keyWindow] makeFirstResponder:self];
    return 0;
}

- (int) doOpenOneSound:(char*)filename:(char*)directory:(int)tempSrate
{
int i,trash;
char temp[200];
short *stemp;

    i = Nmax;
    if(filename != NULL && i < 10)
    {
	strcpy(temp, directory);
	strcat(temp, "/");
	strcat(temp, filename);
	mapfile[i] = NXMapFile((const char*) temp, NX_READWRITE);
	if(mapfile[i] == 0) 
	{
	    NXRunAlertPanel("Open","Cannot open %s\n","OK",NULL,NULL, temp);
	    return -1;
	}
	else
	{
	    NXGetMemoryBuffer(mapfile[i], (char**) &stemp, &N[i], &trash);
	    trash=SNDAlloc(&sounds[i],20, SND_FORMAT_LINEAR_16,0, 1,4);
	    sounds[i]->dataSize = N[i] - sizeof(SNDSoundStruct);
	    bcopy((char*)sounds[i],(char*)stemp,sizeof(SNDSoundStruct));
	    N[i]/=sizeof(short); sounds[i] = (SNDSoundStruct*) stemp;

// A Word of explanation: In order to be able to play a sound using
// the Play object, you have to have a SNDSoundStruct to pass to the
// object, with at least the correct value of the datalocation. When
// the opened sound is not a soundfile, it doesn't have a header so
// we copy a SNDSoundStruct on the first samples or the sound. When
// the sound is saved, remember that the first 14 samples have been
// destroyed and replaced by the SNDSoundStruct.


	}
	[buttonMatrix selectCellWithTag:i];
	[sliderMatrix selectCellWithTag:i];
	[openMatrix selectCellWithTag:i];
	[inspectMatrix selectCellWithTag:i];
	[[buttonMatrix selectedCell]  setEnabled:YES];
	[[sliderMatrix selectedCell]  setEnabled:YES];
	[[openMatrix selectedCell]  setEnabled:YES];
	[[inspectMatrix selectedCell]  setEnabled:YES];
	[fieldMatrix setStringValue:filename at:i];
	strcpy(filenames[i], filename);
	strcpy(directories[i],directory);
	samplingRate[i]=tempSrate;
	lengthplayed[i]=defLength;
	stereo[i]=4;		// Mono mode default.
    }
    else return -1;
    Nmax++;
    [[NXApp keyWindow] addToEventMask:NX_KEYDOWNMASK|NX_KEYUPMASK];
    [[NXApp keyWindow] makeFirstResponder:self];
    return 0;
}

- play:sender
{
int i;
char toto[128];

    [self inspect:sender];
    i = [[sender selectedCell] tag];
    if(i>=Nmax) return self;
    fprintf(stderr,"Playing file: %d soundfile%d\n",i,(int)sounds[i]);
    if(!ALL_PLAY) [(Play *) playObject stop];
    else if(i) usleep((unsigned) (silence*1000000));
    [playObject setOutput:[[outputMatrix selectedCell] tag]];
    [playObject setGain:scaleFactor[i]];
    [playObject setSamplingRate:samplingRate[i]];
    [playObject setMonoMode:stereo[i]];
    if(!lengthplayed[i])
	[playObject playSound:sounds[i]:0:N[i]];
    else
    	[playObject playSound:sounds[i]:0:MIN(N[i],lengthplayed[i])];
    currentSound = playingSound = i;
    sprintf(toto,"%d", playingSound+1);
    [numberForm setStringValue:toto];
    return self;
}

- setSampRate:sender
{
    samplingRate[currentSound] = [sender intValueAt:0];
    [[NXApp keyWindow] makeFirstResponder:self];
    return self;
}

- setStereo:sender
{
    stereo[currentSound] = tagToChan[[[sender selectedCell] tag]];
    [[NXApp keyWindow] makeFirstResponder:self];
    return self;
}

-keyDown:(NXEvent *) anEvent
{
int tempCurrent;
NXEvent *nextEvent;

    nextEvent = [NXApp getNextEvent:(NX_KEYDOWNMASK|NX_KEYUPMASK)];	
    tempCurrent = (nextEvent->data).key.charCode - 49;
//    fprintf(stderr,"currentSound %d\n", currentSound);
    if(tempCurrent == -1) tempCurrent = 9;
    if(tempCurrent >= Nmax || tempCurrent < 0)
    { 
	if(tempCurrent >= 10 || tempCurrent < 0)
	    [self stop:self];
	return self;
    }
    if(ALL_PLAY) return self;
    currentSound = tempCurrent;
    if(nextEvent->flags & NX_COMMANDMASK) //Command 1 opens inspector 1 
    {
	[inspectMatrix selectCellWithTag:currentSound];
	[[inspectMatrix selectedCell] performClick:[inspectMatrix selectedCell]]; return self;
    }
    [buttonMatrix selectCellWithTag:currentSound];
    [[buttonMatrix selectedCell] performClick:[buttonMatrix selectedCell]];
    return self;
}

-okSave:sender
{
int i;

    i = [[sender selectedCell] tag];
fprintf(stderr,"Stop modal! Tag %d\n",i);
    strcpy(saveDir,[saveDirCell stringValueAt:0]);
    [NXApp stopModal:i];
    [savePanel close];
    return self;
}

- willPlay:sender
{
fprintf(stderr,"WILLPLAY nomn de dieu! current playing sound %d\n", currentSound);
    return self;
}

- stop:sender
{
    ALL_PLAY = 0;
    [(Play *) playObject stop];
    return self;
}

- setLength:sender
{
    lengthplayed[currentSound] = [sender intValueAt:0];
    [[NXApp keyWindow] makeFirstResponder:self];
    return self;
}

- closeSound:sender
{
int i,Size,trash;
short *stemp;

    for(i=0;i<Nmax;i++)
    {
	NXGetMemoryBuffer(mapfile[i],(char**)&stemp, &trash, &Size);
	vm_deallocate(task_self(),(pointer_t)stemp,Size);
	NXClose(mapfile[i]);
    }
    Nmax = 0;
    [generalVolSlider  setEnabled:NO];
    return self;
}

- openEdsndP:sender
{
char temp[128];
int i;

    i = [[sender selectedCell] tag];
    strcpy(temp, directories[i]);
    strcat(temp, "/");
    strcat(temp, filenames[i]);
    [[Application workspace] openFile:temp withApplication:"edsndP"];
    return self;
}

- saveConfiguration:sender
{
static int first = 1;
int i;
static char *saveConfigName;
FILE *fopen(),*fp;

    if(first == 1)
    {
	saveConfigPanel = [SavePanel new];
	[saveConfigPanel setDelegate:self];
	[saveConfigPanel setTitle:(const char *)"Save Configuration"];
	i=[saveConfigPanel runModalForDirectory:NXHomeDirectory() file:""];
    }
    else
    {
	[saveConfigPanel setTitle:(const char *)"Save Configuration"];
	i=[saveConfigPanel runModalForDirectory:
		[saveConfigPanel directory] file:""];
    }
    first = 0;
    if(!i) return self;
    saveConfigName = (char*) [saveConfigPanel filename];
    fp = fopen(saveConfigName,"w");
    if(fp == NULL)
    {
	NXRunAlertPanel("Save Config","%s\n","OK",NULL,NULL,"Can't write into file... Check permission");
	return self;
    }
    fprintf(fp,"%d \n",Nmax);
    for(i=0;i<Nmax;i++)
	fprintf(fp,"%s %s %f %d %d %d\n", directories[i], filenames[i], scaleFactor[i], samplingRate[i], lengthplayed[i], stereo[i]);
    fprintf(fp,"%f \n",silence);
    for(i=0;i<Nmax;i++)
	fprintf(fp,"%s@",info[i]);
    fclose(fp);
    return self;
}

- readConfiguration:sender
{
static int first = 1;
int i,NNmax;
char *saveConfigName;
FILE *fopen(),*fp;
char foo;

    if(first) readConfigPanel = [OpenPanel new];
    [readConfigPanel setAccessoryView:nil];
    [readConfigPanel setDelegate:self];
    [readConfigPanel setTitle:(const char *)"Read Configuration"];
    if(first)
	i=[readConfigPanel runModalForDirectory:NXHomeDirectory() file:""];
    else i=[readConfigPanel runModalForDirectory:
    	[readConfigPanel directory] file:""];
    first = 0;
    if(!i) return self;
    saveConfigName = (char*) [readConfigPanel filename];
    fp = fopen(saveConfigName,"r");
    if(fp == NULL) return self;
    fscanf(fp,"%d",&NNmax);
    if(NNmax < 0 || NNmax > 10) return self;
    [self closeSound:self];
    for(i=0;i<NNmax;i++)
    {
	fscanf(fp,"%s %s %f %d",
		directories[i],filenames[i],&scaleFactor[i],&samplingRate[i]);
	[self doOpenOneSound:filenames[i]:directories[i]:samplingRate[i]];
	fscanf(fp," %d %d",&lengthplayed[i],&stereo[i]);
	[sliderMatrix selectCellWithTag:i];
	[[sliderMatrix selectedCell]  setFloatValue:scaleFactor[i]];
	[ampForm selectCellWithTag:i];
	[[ampForm selectedCell] setFloatValue:scaleFactor[i]];
// Careful! The doOpenSound method will alter Nmax, so we need to have
// a local copy, hence the NNmax!
    }
    fscanf(fp,"%f ",&silence);
    for(i=0;i<NNmax;i++)
    {
	fscanf(fp,"%[^@]",info[i]);
	fscanf(fp,"%c",&foo);
    }
    [silenceForm setFloatValue:silence];
    for(i=Nmax;i<10;i++)
    {
	[buttonMatrix selectCellWithTag:i];
	[sliderMatrix selectCellWithTag:i];
	[openMatrix selectCellWithTag:i];
	[inspectMatrix selectCellWithTag:i];
	[[buttonMatrix selectedCell]  setEnabled:NO];
	[[sliderMatrix selectedCell]  setEnabled:NO];
	[[openMatrix selectedCell]  setEnabled:NO];
	[[inspectMatrix selectedCell]  setEnabled:NO];
	[fieldMatrix setStringValue:" " at:i];
    }
    fclose(fp);
    [generalVolSlider  setEnabled:(Nmax != 0)];
    return self;
}

- inspect:sender
{
char toto[128];
char *aux;
int temp;

    strcpy(toto,"Sound ");
    currentSound = [[sender selectedCell] tag];
    sprintf(toto+60,"%d", currentSound+1);
    strcat(toto,toto+60);
    [inspectorPanel orderFront:self];
    [inspectorPanel setTitle:toto];
    [sampRateForm setIntValue:samplingRate[currentSound]];
    [lengthForm setIntValue:lengthplayed[currentSound]];
    [stereoForm selectCellWithTag:chanToTag[stereo[currentSound]]];
    [iPanelSoundName setTitle:toto at:0];
    [iPanelSoundName setStringValue:filenames[currentSound] at:0];
    temp=strlen(directories[currentSound]);
    if(temp > 25)
    {
    int i;
	strcpy(toto,"...");
	aux = index(directories[currentSound],'/');
	for(i=1;strlen(aux)>23;i++)
	    aux = index((char*)(aux+1),'/');
//	strcat(toto,(char*)(directories[currentSound]+temp-22));
	strcat(toto,aux);
	aux = toto;
    }
    else aux = directories[currentSound];
    [iPanelSoundName setStringValue:aux at:1];
    [[NXApp keyWindow] makeFirstResponder:self];
    [infoText setStringValue:info[currentSound]];
    NXPing();
    return self;
}

- delete:sender
{
int i;
//int Size,toto;
//char **stemp;
    
    for(i=currentSound;i<Nmax-1;i++)
    {
	
	sounds[i] = sounds[i+1];
	strcpy(filenames[i], filenames[i+1]);
	strcpy(directories[i], directories[i+1]);
	samplingRate[i] = samplingRate[i+1];
	scaleFactor[i] = scaleFactor[i+1];
	lengthplayed[i] = lengthplayed[i+1];
	stereo[i] = stereo[i+1];
	mapfile[i] = mapfile[i+1];
	N[i] = N[i+1];
	[sliderMatrix selectCellWithTag:i];
	[[sliderMatrix selectedCell]  setFloatValue:scaleFactor[i]];
	[fieldMatrix setStringValue:filenames[i] at:i];
	[ampForm selectCellWithTag:i];
	[[ampForm selectedCell] setFloatValue:scaleFactor[i]];
    }
    [sliderMatrix selectCellWithTag:Nmax-1];
    [[sliderMatrix selectedCell]  setFloatValue:1];
    [[sliderMatrix selectedCell]  setEnabled:NO];
    [fieldMatrix setStringValue:" " at:Nmax-1];
    [ampForm selectCellWithTag:Nmax-1];
    [[ampForm selectedCell] setFloatValue:1.0];
    [buttonMatrix selectCellWithTag:Nmax-1];
    [openMatrix selectCellWithTag:Nmax-1];
    [inspectMatrix selectCellWithTag:Nmax-1];
    [[buttonMatrix selectedCell]  setEnabled:NO];
    [[openMatrix selectedCell]  setEnabled:NO];
    [[inspectMatrix selectedCell]  setEnabled:NO];
//     NXGetMemoryBuffer(mapfile[currentSound],(char**)&stemp, &toto,
//     &Size); vm_deallocate(task_self(),(pointer_t)stemp,Size);
//     NXClose(mapfile[currentSound]);
    Nmax--;
    if(currentSound == Nmax) currentSound--;
    if(currentSound >= 0)
    {
	[inspectMatrix selectCellWithTag:currentSound];
	[[inspectMatrix selectedCell] 
		performClick:[inspectMatrix selectedCell]];
    }
    else
    {
	[inspectorPanel performClose:self];
	[numberForm setStringValue:" "];
    }
    [generalVolSlider  setEnabled:(Nmax != 0)];
    return self;
}

- error:(char*)aString
{
    NXRunAlertPanel("Play","%s\n","OK",NULL,NULL, aString);
    return self;
}

- reload:sender
{
int Nmax_temp, trash, Size, DefLengthTemp;
char *stemp;
    
    NXGetMemoryBuffer(mapfile[currentSound],(char**)&stemp, &trash, &Size);
    vm_deallocate(task_self(),(pointer_t)stemp,Size);
    NXClose(mapfile[currentSound]);
    Nmax_temp = Nmax;
    DefLengthTemp = defLength;
    defLength = lengthplayed[currentSound];
    Nmax = currentSound;
    [self doOpenOneSound:filenames[currentSound]:directories[currentSound]
	:samplingRate[currentSound]];
    Nmax = Nmax_temp;
    defLength = DefLengthTemp;
    return self;
}

- didPlay:sender
{
    if(ALL_PLAY) [self playAll:nil];
    return self;
}

- playAll:sender
{
static int currentplayed = 0;

    if(sender != nil)
    {
	ALL_PLAY = 1;
	currentplayed = 0;
    }
    if(currentplayed >= Nmax)
    {
	ALL_PLAY = 0;
	return self;
    }
    [inspectMatrix selectCellWithTag:currentplayed];
    [[inspectMatrix selectedCell] performClick:[inspectMatrix selectedCell]];
    [self play:inspectMatrix];
    currentplayed ++;
    return self;
}

- setSilence:sender
{
    silence = [sender floatValue];
    if(silence > 10)
    {
	[sender setFloatValue:10.0]; 
	silence = 10;
    }
    return self;
}

- setGeneralVol:sender
{
float newVol, deltaVol;
int i;

    newVol = 0.04*floor([sender floatValue]*25);
    deltaVol = (generalVol - newVol);
    if(deltaVol < 0.04 && deltaVol > -0.04) return self;
    generalVol = newVol;
    for(i=0;i<Nmax;i++)
    {
	scaleFactor[i] -= deltaVol;
	[ampForm selectCellWithTag:i];
	[[ampForm selectedCell] setFloatValue:scaleFactor[i]];
	[sliderMatrix selectCellWithTag:i];
	[[sliderMatrix selectedCell] setFloatValue:scaleFactor[i]];
    }
    return self;
}

- soundAnimate:(int)samples
{
float percent;

    if(stereo[playingSound] != 4) samples *= 2;
    if(samples < 100) samples = 0;
    if(lengthplayed[playingSound])
    percent = (float)samples / MIN(N[playingSound],lengthplayed[playingSound]);
    else percent = (float)samples / N[playingSound] ;
    [percentView displayPercent:percent];
    return self;
}

- textDidEnd:sender endChar:(unsigned short)whyEnd
{
    [sender getSubstring:info[currentSound] start:0 length:TEXTLENGTH];
    fprintf(stderr,"%d\n", whyEnd);
    fprintf(stderr,"%s\n", info[currentSound]);
    if(whyEnd) [bigWindow makeKeyAndOrderFront:self];
    return self;
}  

@end
