/*
===========================================================================

Return to Castle Wolfenstein single player GPL Source Code
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. 

This file is part of the Return to Castle Wolfenstein single player GPL Source Code (RTCW SP Source Code).  

RTCW SP Source Code 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 3 of the License, or
(at your option) any later version.

RTCW SP Source Code 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 RTCW SP Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code.  If not, please request a copy in writing from id Software at the address below.

If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.

===========================================================================
*/


// mac_snddma.c
// all other sound mixing is portable

#include "../client/snd_local.h"
#include <Carbon/Carbon.h>

// For 'ri'
#include "../renderer/tr_local.h"

#import <Foundation/NSZone.h>

// TJW - Different versions of SoundManager have different DMA buffer sizes.  On MacOS X DP2,
// the buffer size is 8K.  On MacOS 9 it is much smaller.  The SoundManager guy at Apple says
// that the size of the buffer will be decreasing for final release to help get rid of latency.
//#define	MAX_MIXED_SAMPLES	(0x8000 * 64)
//#define	SUBMISSION_CHUNK	 (0x100 * 64)

// Original MacOS 9 sizes
//#define	MAX_MIXED_SAMPLES	0x8000
//#define	SUBMISSION_CHUNK	 0x100


static unsigned int submissionChunk;
static unsigned int maxMixedSamples;

static short       *s_mixedSamples;
static int s_chunkCount;                    // number of chunks submitted
static SndChannel      *s_sndChan;
static ExtSoundHeader s_sndHeader;

/*
===============
S_Callback
===============
*/
void S_Callback( SndChannel *sc, SndCommand *cmd ) {
	SndCommand mySndCmd;
	SndCommand mySndCmd2;
	int offset;

	offset = ( s_chunkCount * submissionChunk ) & ( maxMixedSamples - 1 );

	// queue up another sound buffer
	memset( &s_sndHeader, 0, sizeof( s_sndHeader ) );
	s_sndHeader.samplePtr = ( void * )( s_mixedSamples + offset );
	s_sndHeader.numChannels = 2;
	s_sndHeader.sampleRate = rate22khz;
	s_sndHeader.loopStart = 0;
	s_sndHeader.loopEnd = 0;
	s_sndHeader.encode = extSH;
	s_sndHeader.baseFrequency = 1;
	s_sndHeader.numFrames = submissionChunk / 2;
	s_sndHeader.markerChunk = NULL;
	s_sndHeader.instrumentChunks = NULL;
	s_sndHeader.AESRecording = NULL;
	s_sndHeader.sampleSize = 16;

	mySndCmd.cmd = bufferCmd;
	mySndCmd.param1 = 0;
	mySndCmd.param2 = (int)&s_sndHeader;
	SndDoCommand( sc, &mySndCmd, true );

	// and another callback
	mySndCmd2.cmd = callBackCmd;
	mySndCmd2.param1 = 0;
	mySndCmd2.param2 = 0;
	SndDoCommand( sc, &mySndCmd2, true );

	s_chunkCount++;     // this is the next buffer we will submit
}

/*
===============
S_MakeTestPattern
===============
*/
void S_MakeTestPattern( void ) {
	int i;
	float v;
	int sample;

	for ( i = 0 ; i < dma.samples / 2 ; i++ ) {
		v = sin( M_PI * 2 * i / 64 );
		sample = v * 0x4000;
		( (short *)dma.buffer )[i * 2] = sample;
		( (short *)dma.buffer )[i * 2 + 1] = sample;
	}
}

/*
===============
SNDDMA_Init
===============
*/
qboolean SNDDMA_Init( void ) {
	int err;
	cvar_t *bufferSize;
	cvar_t *chunkSize;

	chunkSize = ri.Cvar_Get( "s_chunksize", "8192", CVAR_ARCHIVE );
	bufferSize = ri.Cvar_Get( "s_buffersize", "65536", CVAR_ARCHIVE );

	if ( !chunkSize->integer ) {
		ri.Error( ERR_FATAL, "snd_chunkSize must be non-zero\n" );
	}

	if ( !bufferSize->integer ) {
		ri.Error( ERR_FATAL, "snd_bufferSize must be non-zero\n" );
	}

	if ( chunkSize->integer >= bufferSize->integer ) {
		ri.Error( ERR_FATAL, "snd_chunkSize must be less than snd_bufferSize\n" );
	}

	if ( bufferSize->integer % chunkSize->integer ) {
		ri.Error( ERR_FATAL, "snd_bufferSize must be an even multiple of snd_chunkSize\n" );
	}

	// create a sound channel
	s_sndChan = NULL;
	err = SndNewChannel( &s_sndChan, sampledSynth, initStereo, NewSndCallBackProc( S_Callback ) );
	if ( err ) {
		return false;
	}

	submissionChunk = chunkSize->integer;
	maxMixedSamples = bufferSize->integer;

	s_mixedSamples = NSZoneMalloc( NULL, sizeof( *s_mixedSamples ) * maxMixedSamples );

	dma.channels = 2;
	dma.samples = maxMixedSamples;
	dma.submission_chunk = submissionChunk;
	dma.samplebits = 16;
	dma.speed = 22050;
	dma.buffer = (byte *)s_mixedSamples;

	// que up the first submission-chunk sized buffer
	s_chunkCount = 0;

	S_Callback( s_sndChan, NULL );

	return qtrue;
}

/*
===============
SNDDMA_GetDMAPos
===============
*/
int SNDDMA_GetDMAPos( void ) {
	return s_chunkCount * submissionChunk;
}

/*
===============
SNDDMA_Shutdown
===============
*/
void SNDDMA_Shutdown( void ) {
	if ( s_sndChan ) {
		SndDisposeChannel( s_sndChan, true );
		s_sndChan = NULL;
	}
}

/*
===============
SNDDMA_BeginPainting
===============
*/
void SNDDMA_BeginPainting( void ) {
}

/*
===============
SNDDMA_Submit
===============
*/
void SNDDMA_Submit( void ) {
}
