
#import <soundkit/soundkit.h>
#import <sound/sound.h>
#import <appkit/appkit.h>
#import "SoundPlayer.h"


@implementation SoundPlayer

- init
{
	[super init];
	device = [[NXSoundOut alloc] init]; // set up sound out device
	stream = [[NXPlayStream alloc] initOnDevice:device];
	[stream activate]; // set up our output stream
	soundListList = [[List alloc] initCount:NUMTYPES];
	soundType = 0;
	[self loadSounds];
	return self;
}

- loadSounds	// gameBrain calls this in appDidInit method
{
	int i;
	for (i=0; i<NUMTYPES; i++) [self loadSounds:NUMSOUNDS type:i];
	return self;
}

- loadSounds:(int)numSounds type:(int)type
{
	int err, j; id tempSnd, tempList = [[List alloc] initCount:NUMSOUNDS];
	char *slashPos, *appPath = (char *)malloc(1024);
    char *soundFile = (char *)malloc(1024);
    
    strcpy(appPath, NXArgv[0]);
    if (slashPos = strrchr(appPath, '/')) slashPos[1] = '\0';
    else strcpy(appPath, "./");
    
	for (j=0; j<numSounds; j++) {  // load in the the sounds
		sprintf(soundFile, "%sSound%d.%d.snd", appPath, j, type);
		tempSnd = [[Sound alloc] initFromSoundfile:soundFile];
		// Convert to 16 bit linear 22050.0 kHz (idea is that this
		// doesn't require conversion on the fly.  Since we play the
		// sounds so often, why convert each time?  It's a waste of
		// CPU.  This should also provide faster playback response.
		if (err = [tempSnd convertToFormat:SND_FORMAT_LINEAR_16
				samplingRate:SND_RATE_LOW channelCount:2]) {
			fprintf(stderr, "%s:  sound #%d type #%d convert error %s\n",
					[NXApp appName], j, type, SNDSoundError(err));
		}
		[tempList addObject:tempSnd];
    }
	[soundListList addObject:tempList];
    free(appPath); free(soundFile);
	return self;
}

- play0:sender { return [self playNum:0]; }
- play2:sender { return [self playNum:2]; }
- play1:sender { return [self playNum:1]; }
- play:sender { return [self playNum:[sender tag]]; }

- playNum:(int)num
{
	SNDSoundStruct *sound;
	// make sure we have the sound
	if ((num < 0) || (num >= [[soundListList objectAt:0] count])) return nil;
	// get pointer to appropriate sound data
	sound = [[[soundListList objectAt:soundType] objectAt:num] soundStruct];
	// enqueue sound data to be played
	if (sound)
	[stream playBuffer:(char *)sound+sound->dataLocation
		size:sound->dataSize tag:num channelCount:sound->channelCount
		samplingRate:sound->samplingRate];
	return self;
}

- setSoundType:(int)num { soundType = num; return self; }
- (int)soundType { return soundType; }


@end
