2009-10-01 01:10:58 +02:00
|
|
|
|
/****************************************************************************
|
|
|
|
|
* libwiigui
|
|
|
|
|
*
|
|
|
|
|
* Tantric 2009
|
|
|
|
|
*
|
|
|
|
|
* gui_sound.cpp
|
|
|
|
|
*
|
2009-11-10 00:03:13 +01:00
|
|
|
|
* decoder modification by ardi 2009
|
|
|
|
|
*
|
2009-10-01 01:10:58 +02:00
|
|
|
|
* GUI class definitions
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "gui.h"
|
2009-11-10 00:03:13 +01:00
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include "gecko.h"
|
|
|
|
|
|
|
|
|
|
#include "gui_sound_decoder.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define BUFFER_SIZE 8192
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
|
*
|
|
|
|
|
* D E C O D E R <EFBFBD> L I S T
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
***************************************************************/
|
2009-10-01 01:10:58 +02:00
|
|
|
|
|
2009-11-10 00:03:13 +01:00
|
|
|
|
GuiSoundDecoder::DecoderListEntry *GuiSoundDecoder::DecoderList = NULL;
|
2010-09-19 01:16:05 +02:00
|
|
|
|
GuiSoundDecoder::DecoderListEntry &GuiSoundDecoder::RegisterDecoder( DecoderListEntry &Decoder, GuiSoundDecoderCreate fnc )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( Decoder.fnc != fnc )
|
|
|
|
|
{
|
|
|
|
|
Decoder.fnc = fnc;
|
|
|
|
|
Decoder.next = DecoderList;
|
|
|
|
|
DecoderList = &Decoder;
|
|
|
|
|
}
|
|
|
|
|
return Decoder;
|
2009-11-10 00:03:13 +01:00
|
|
|
|
}
|
2010-09-19 01:16:05 +02:00
|
|
|
|
GuiSoundDecoder *GuiSoundDecoder::GetDecoder( const u8 * snd, u32 len, bool snd_is_allocated )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
for ( DecoderListEntry *de = DecoderList; de; de = de->next )
|
|
|
|
|
{
|
|
|
|
|
GuiSoundDecoder *d = NULL;
|
|
|
|
|
try { d = de->fnc( snd, len, snd_is_allocated ); }
|
|
|
|
|
catch ( const char *error )
|
|
|
|
|
{
|
|
|
|
|
gprintf( "%s", error );
|
|
|
|
|
}
|
|
|
|
|
catch ( ... ) {}
|
|
|
|
|
if ( d ) return d;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
2009-11-10 00:03:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2010-05-29 17:43:19 +02:00
|
|
|
|
|
2009-11-10 00:03:13 +01:00
|
|
|
|
/***************************************************************
|
|
|
|
|
*
|
|
|
|
|
* D E C O D E R <EFBFBD> T H R E A D
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
***************************************************************/
|
|
|
|
|
|
|
|
|
|
static GuiSound *GuiSoundPlayer[16] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
static lwp_t GuiSoundDecoderThreadHandle = LWP_THREAD_NULL;
|
|
|
|
|
static bool GuiSoundDecoderThreadRunning = false;
|
|
|
|
|
static bool GuiSoundDecoderDataRquested = false;
|
2009-11-10 00:03:13 +01:00
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
void *GuiSoundDecoderThread( void *args )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
GuiSoundDecoderThreadRunning = true;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if ( GuiSoundDecoderDataRquested )
|
|
|
|
|
{
|
|
|
|
|
GuiSoundDecoderDataRquested = false;
|
|
|
|
|
GuiSound **players = GuiSoundPlayer;
|
|
|
|
|
for ( int i = 0; i < 16; ++i , ++players )
|
|
|
|
|
{
|
|
|
|
|
GuiSound *player = *players;
|
|
|
|
|
if ( player )
|
|
|
|
|
player->DecoderCallback();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( !GuiSoundDecoderDataRquested )
|
|
|
|
|
usleep( 50 );
|
|
|
|
|
}
|
|
|
|
|
while ( GuiSoundDecoderThreadRunning );
|
|
|
|
|
return 0;
|
2009-11-10 00:03:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
|
*
|
|
|
|
|
* A S N D <EFBFBD> C A L L B A C K
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
***************************************************************/
|
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
void GuiSoundPlayerCallback( s32 Voice )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( Voice >= 0 && Voice < 16 && GuiSoundPlayer[Voice] )
|
|
|
|
|
{
|
|
|
|
|
GuiSoundPlayer[Voice]->PlayerCallback();
|
|
|
|
|
GuiSoundDecoderDataRquested = true;
|
|
|
|
|
}
|
2009-11-10 00:03:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
|
*
|
|
|
|
|
* R A W - D E C O D E R
|
|
|
|
|
* Decoder for Raw-PCM-Datas (16bit Stereo 48kHz)
|
|
|
|
|
*
|
|
|
|
|
***************************************************************/
|
2010-02-09 11:59:55 +01:00
|
|
|
|
class GuiSoundDecoderRAW : public GuiSoundDecoder
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
protected:
|
|
|
|
|
GuiSoundDecoderRAW( const u8 * snd, u32 len, bool snd_is_allocated )
|
|
|
|
|
{
|
|
|
|
|
pcm_start = snd;
|
|
|
|
|
is_allocated = snd_is_allocated;
|
|
|
|
|
pcm_end = pcm_start + len;
|
|
|
|
|
pos = pcm_start;
|
|
|
|
|
is_running = false;
|
2009-11-10 00:03:13 +01:00
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
~GuiSoundDecoderRAW()
|
|
|
|
|
{
|
|
|
|
|
while ( is_running ) usleep( 50 );
|
|
|
|
|
if ( is_allocated ) delete [] pcm_start;
|
|
|
|
|
}
|
|
|
|
|
static GuiSoundDecoder *Create( const u8 * snd, u32 len, bool snd_is_allocated )
|
|
|
|
|
{
|
|
|
|
|
try { return new GuiSoundDecoderRAW( snd, len, snd_is_allocated ); }
|
|
|
|
|
catch ( ... ) {}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
s32 GetFormat()
|
|
|
|
|
{
|
|
|
|
|
return VOICE_STEREO_16BIT;
|
|
|
|
|
}
|
|
|
|
|
s32 GetSampleRate()
|
|
|
|
|
{
|
|
|
|
|
return 48000;
|
|
|
|
|
}
|
|
|
|
|
/* Read reads data from stream to buffer
|
|
|
|
|
return: >0 = readed bytes;
|
|
|
|
|
0 = EOF;
|
|
|
|
|
<0 = Error;
|
|
|
|
|
*/
|
|
|
|
|
int Read( u8 * buffer, int buffer_size )
|
|
|
|
|
{
|
|
|
|
|
if ( pos >= pcm_end )
|
|
|
|
|
return 0; // EOF
|
2009-11-10 00:03:13 +01:00
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
is_running = true;
|
|
|
|
|
if ( pos + buffer_size > pcm_end )
|
|
|
|
|
buffer_size = pcm_end - pos;
|
|
|
|
|
memcpy( buffer, pos, buffer_size );
|
|
|
|
|
pos += buffer_size;
|
|
|
|
|
is_running = false;
|
|
|
|
|
return buffer_size;
|
|
|
|
|
}
|
|
|
|
|
int Rewind()
|
|
|
|
|
{
|
|
|
|
|
pos = pcm_start;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
const u8 *pcm_start;
|
|
|
|
|
const u8 *pcm_end;
|
|
|
|
|
bool is_allocated;
|
|
|
|
|
const u8 *pos;
|
|
|
|
|
bool is_running;
|
2009-11-10 00:03:13 +01:00
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
|
*
|
|
|
|
|
* G u i S o u n d
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
***************************************************************/
|
2010-09-19 01:16:05 +02:00
|
|
|
|
#define GuiSoundBufferReady 0x01
|
|
|
|
|
#define GuiSoundBufferEOF 0x02
|
|
|
|
|
#define GuiSoundFinish 0x04
|
2009-11-10 00:03:13 +01:00
|
|
|
|
static int GuiSoundCount = 0;
|
2009-10-01 01:10:58 +02:00
|
|
|
|
/**
|
|
|
|
|
* Constructor for the GuiSound class.
|
|
|
|
|
*/
|
2010-09-19 01:16:05 +02:00
|
|
|
|
GuiSound::GuiSound( const u8 *s, int l, int v/*=100*/, bool r/*=true*/, bool a/*=false*/ )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( GuiSoundCount++ == 0 || GuiSoundDecoderThreadHandle == LWP_THREAD_NULL )
|
|
|
|
|
{
|
|
|
|
|
LWP_CreateThread( &GuiSoundDecoderThreadHandle, GuiSoundDecoderThread, NULL, NULL, 32768, 80 );
|
|
|
|
|
}
|
|
|
|
|
voice = -1;
|
|
|
|
|
play_buffer[0] = ( u8* )memalign( 32, BUFFER_SIZE * 3 ); // tripple-buffer first is played
|
|
|
|
|
play_buffer[1] = play_buffer[0] + BUFFER_SIZE; // second is waiting
|
|
|
|
|
play_buffer[2] = play_buffer[1] + BUFFER_SIZE; // third is decoding
|
|
|
|
|
buffer_nr = 0; // current playbuffer
|
|
|
|
|
buffer_pos = 0; // current idx to write in buffer
|
|
|
|
|
buffer_ready = false;
|
|
|
|
|
buffer_eof = false;
|
|
|
|
|
loop = false; // play looped
|
|
|
|
|
volume = v; // volume
|
|
|
|
|
decoder = NULL;
|
|
|
|
|
if ( play_buffer[0] ) // playbuffer ok
|
|
|
|
|
Load( s, l, r, a );
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
2010-09-19 01:16:05 +02:00
|
|
|
|
bool GuiSound::Load( const u8 *s, int l, bool r/*=false*/, bool a/*=false*/ )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
Stop();
|
|
|
|
|
if ( !play_buffer[0] ) return false;
|
|
|
|
|
GuiSoundDecoder *newDecoder = GuiSoundDecoder::GetDecoder( s, l, a );
|
|
|
|
|
if ( !newDecoder && r ) newDecoder = GuiSoundDecoderRAW::Create( s, l, a );
|
|
|
|
|
if ( newDecoder )
|
|
|
|
|
{
|
|
|
|
|
delete decoder;
|
|
|
|
|
decoder = newDecoder;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if ( a )
|
|
|
|
|
delete [] s;
|
|
|
|
|
return false;
|
2009-11-10 00:03:13 +01:00
|
|
|
|
}
|
2010-09-19 01:16:05 +02:00
|
|
|
|
GuiSound::GuiSound( const char *p, int v/*=100*/ )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( GuiSoundCount++ == 0 || GuiSoundDecoderThreadHandle == LWP_THREAD_NULL )
|
|
|
|
|
{
|
|
|
|
|
LWP_CreateThread( &GuiSoundDecoderThreadHandle, GuiSoundDecoderThread, NULL, NULL, 32*1024, 80 );
|
|
|
|
|
}
|
|
|
|
|
voice = -1;
|
|
|
|
|
play_buffer[0] = ( u8* )memalign( 32, BUFFER_SIZE * 3 ); // tripple-buffer first is played
|
|
|
|
|
play_buffer[1] = play_buffer[0] + BUFFER_SIZE; // second is waiting
|
|
|
|
|
play_buffer[2] = play_buffer[1] + BUFFER_SIZE; // third is decoding
|
|
|
|
|
buffer_nr = 0; // current playbuffer
|
|
|
|
|
buffer_pos = 0; // current idx to write in buffer
|
|
|
|
|
buffer_ready = false;
|
|
|
|
|
buffer_eof = false;
|
|
|
|
|
loop = false; // play looped
|
|
|
|
|
volume = v; // volume
|
|
|
|
|
decoder = NULL;
|
|
|
|
|
if ( play_buffer[0] ) // playbuffer ok
|
|
|
|
|
Load( p );
|
2009-11-10 00:03:13 +01:00
|
|
|
|
}
|
2010-09-19 01:16:05 +02:00
|
|
|
|
bool GuiSound::Load( const char *p )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
Stop(); // stop playing
|
|
|
|
|
if ( !play_buffer[0] ) return false;
|
2010-05-29 17:43:19 +02:00
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
bool ret = false;
|
|
|
|
|
voice = -2; // -2 marks loading from file
|
|
|
|
|
u32 filesize = 0;
|
|
|
|
|
u8 *buffer = NULL;
|
|
|
|
|
size_t result;
|
2009-11-10 00:03:13 +01:00
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
FILE * pFile = fopen ( p, "rb" );
|
|
|
|
|
if ( pFile )
|
|
|
|
|
{
|
|
|
|
|
// get file size:
|
|
|
|
|
fseek ( pFile , 0 , SEEK_END );
|
|
|
|
|
filesize = ftell ( pFile );
|
|
|
|
|
fseek ( pFile , 0 , SEEK_SET );
|
2009-11-10 00:03:13 +01:00
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
// allocate memory to contain the whole file:
|
|
|
|
|
buffer = new( std::nothrow ) u8[filesize];
|
|
|
|
|
if ( buffer )
|
|
|
|
|
{
|
|
|
|
|
// copy the file into the buffer:
|
|
|
|
|
result = fread ( buffer, 1, filesize, pFile );
|
|
|
|
|
if ( result == filesize )
|
|
|
|
|
ret = Load( buffer, filesize, false, true );
|
|
|
|
|
else
|
|
|
|
|
delete [] buffer;
|
|
|
|
|
}
|
|
|
|
|
fclose ( pFile );
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Destructor for the GuiSound class.
|
|
|
|
|
*/
|
2010-02-09 11:59:55 +01:00
|
|
|
|
GuiSound::~GuiSound()
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( !loop ) while ( voice >= 0 ) usleep( 50 );
|
|
|
|
|
Stop();
|
|
|
|
|
if ( --GuiSoundCount == 0 && GuiSoundDecoderThreadHandle != LWP_THREAD_NULL )
|
|
|
|
|
{
|
|
|
|
|
GuiSoundDecoderThreadRunning = false;
|
|
|
|
|
LWP_JoinThread( GuiSoundDecoderThreadHandle, NULL );
|
|
|
|
|
GuiSoundDecoderThreadHandle = LWP_THREAD_NULL;
|
|
|
|
|
}
|
|
|
|
|
delete decoder;
|
|
|
|
|
free( play_buffer[0] );
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-09 11:59:55 +01:00
|
|
|
|
void GuiSound::Play()
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
Stop(); // stop playing if it played
|
|
|
|
|
if ( !play_buffer[0] ) return;
|
|
|
|
|
if ( !decoder ) return; // no decoder or no play_buffer -> no playing
|
|
|
|
|
// initialize the buffer
|
|
|
|
|
buffer_nr = 0; // allways starts with buffer 0
|
|
|
|
|
buffer_pos = 0; // reset position
|
|
|
|
|
buffer_ready = false;
|
|
|
|
|
buffer_eof = false;
|
|
|
|
|
decoder->Rewind(); // play from begin
|
|
|
|
|
DecoderCallback(); // fill first buffer;
|
|
|
|
|
if ( !buffer_ready || buffer_eof ) // if first buffer not ready -> no play
|
|
|
|
|
return;
|
|
|
|
|
voice = ASND_GetFirstUnusedVoice();
|
|
|
|
|
if ( voice >= 0 )
|
|
|
|
|
{
|
|
|
|
|
s32 vol = ( 255 * volume ) / 100;
|
|
|
|
|
s32 format = decoder->GetFormat();
|
|
|
|
|
s32 samplerate = decoder->GetSampleRate();
|
|
|
|
|
s32 first_pos = buffer_pos;
|
|
|
|
|
// switch to next buffer
|
|
|
|
|
buffer_nr = 1;
|
|
|
|
|
buffer_pos = 0;
|
|
|
|
|
buffer_ready = false;
|
|
|
|
|
buffer_eof = false;
|
|
|
|
|
DecoderCallback(); // fill second buffer;
|
|
|
|
|
GuiSoundPlayer[voice] = this; // activate Callbacks for this voice
|
|
|
|
|
// Play the voice
|
|
|
|
|
ASND_SetVoice( voice, format, samplerate, 0, play_buffer[0], first_pos, vol, vol, GuiSoundPlayerCallback );
|
|
|
|
|
}
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
2009-11-10 00:03:13 +01:00
|
|
|
|
/*
|
|
|
|
|
int GuiSound::PlayOggFile(char * path)
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if(Load(path))
|
|
|
|
|
Play();
|
|
|
|
|
return 1;
|
2009-11-10 00:03:13 +01:00
|
|
|
|
}
|
|
|
|
|
*/
|
2010-02-09 11:59:55 +01:00
|
|
|
|
void GuiSound::Stop()
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( voice < 0 ) return ;
|
|
|
|
|
GuiSoundPlayer[voice] = NULL; // disable Callbacks
|
|
|
|
|
SND_StopVoice( voice );
|
|
|
|
|
voice = -1;
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-09 11:59:55 +01:00
|
|
|
|
void GuiSound::Pause()
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( voice < 0 ) return ;
|
|
|
|
|
ASND_PauseVoice( voice, 1 );
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-09 11:59:55 +01:00
|
|
|
|
void GuiSound::Resume()
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( voice < 0 ) return ;
|
|
|
|
|
ASND_PauseVoice( voice, 0 );
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-09 11:59:55 +01:00
|
|
|
|
bool GuiSound::IsPlaying()
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
return voice >= 0;
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
void GuiSound::SetVolume( int vol )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
volume = vol;
|
|
|
|
|
if ( voice < 0 ) return ;
|
|
|
|
|
int newvol = 255 * ( volume / 100.0 );
|
|
|
|
|
ASND_ChangeVolumeVoice( voice, newvol, newvol );
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
|
void GuiSound::SetLoop( bool l )
|
2010-02-09 11:59:55 +01:00
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
loop = l;
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-09 11:59:55 +01:00
|
|
|
|
void GuiSound::DecoderCallback()
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( buffer_ready || buffer_eof ) // if buffer ready or EOF -> nothing
|
|
|
|
|
return;
|
|
|
|
|
bool error = false;
|
|
|
|
|
while ( buffer_pos < BUFFER_SIZE )
|
|
|
|
|
{
|
|
|
|
|
int ret = decoder->Read( &play_buffer[buffer_nr][buffer_pos], BUFFER_SIZE - buffer_pos );
|
|
|
|
|
if ( ret > 0 )
|
|
|
|
|
buffer_pos += ret; // ok -> fill the buffer more
|
|
|
|
|
else if ( ret == 0 ) // EOF from decoder
|
|
|
|
|
{
|
|
|
|
|
if ( loop )
|
|
|
|
|
decoder->Rewind(); // if loop -> rewind and fill the buffer more
|
|
|
|
|
else if ( buffer_pos )
|
|
|
|
|
break; // has data in buffer -> play the buffer
|
|
|
|
|
else
|
|
|
|
|
buffer_eof = true; // no data in buffer -> return EOF
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if ( ret < 0 ) // an ERROR
|
|
|
|
|
{
|
|
|
|
|
if ( buffer_pos )
|
|
|
|
|
break; // has data in buffer -> play the buffer
|
|
|
|
|
else if ( loop )
|
|
|
|
|
{
|
|
|
|
|
if ( !error ) // if no prev error
|
|
|
|
|
{
|
|
|
|
|
decoder->Rewind(); // if loop -> rewind
|
|
|
|
|
error = true; // set error-state
|
|
|
|
|
continue; // and fill the buffer more
|
|
|
|
|
}
|
|
|
|
|
buffer_eof = true; // has prev error -> error in first block -> return EOF
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
buffer_eof = true; // no loop -> return EOF
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
error = false; // clear error-state
|
|
|
|
|
}
|
|
|
|
|
buffer_ready = true;
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
2010-02-09 11:59:55 +01:00
|
|
|
|
void GuiSound::PlayerCallback()
|
|
|
|
|
{
|
2010-09-19 01:16:05 +02:00
|
|
|
|
if ( buffer_eof ) // if EOF
|
|
|
|
|
{
|
|
|
|
|
if ( ASND_TestPointer( voice, play_buffer[( buffer_nr+2 )%3] ) == 0 ) // test prev. Buffer
|
|
|
|
|
Stop();
|
|
|
|
|
}
|
|
|
|
|
else if ( buffer_ready ) // if buffer ready
|
|
|
|
|
{
|
|
|
|
|
if ( ASND_AddVoice( voice, play_buffer[buffer_nr], buffer_pos ) == SND_OK ) // add buffer
|
|
|
|
|
{
|
|
|
|
|
// next buffer
|
|
|
|
|
buffer_nr = ( buffer_nr + 1 ) % 3;
|
|
|
|
|
buffer_pos = 0;
|
|
|
|
|
buffer_ready = false;
|
|
|
|
|
buffer_eof = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-01 01:10:58 +02:00
|
|
|
|
}
|
2009-11-10 00:03:13 +01:00
|
|
|
|
|