mirror of
https://github.com/dborth/vbagx.git
synced 2024-11-23 02:59:17 +01:00
fix long-standing menu "random" lockup/crashing bug. caused by Hermes' oggplayer threading. oggplayer rewritten.
This commit is contained in:
parent
00e80c3f32
commit
1a5885f0ce
@ -104,18 +104,17 @@ SwitchAudioMode(int mode)
|
|||||||
{
|
{
|
||||||
#ifndef NO_SOUND
|
#ifndef NO_SOUND
|
||||||
ASND_Pause(1);
|
ASND_Pause(1);
|
||||||
ASND_End();
|
|
||||||
#endif
|
#endif
|
||||||
|
AUDIO_StopDMA();
|
||||||
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
|
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
|
||||||
AUDIO_RegisterDMACallback(AudioPlayer);
|
AUDIO_RegisterDMACallback(AudioPlayer);
|
||||||
}
|
}
|
||||||
else // menu
|
else // menu
|
||||||
{
|
{
|
||||||
AUDIO_StopDMA();
|
|
||||||
AUDIO_RegisterDMACallback(NULL);
|
|
||||||
IsPlaying = 0;
|
IsPlaying = 0;
|
||||||
|
AUDIO_StopDMA();
|
||||||
#ifndef NO_SOUND
|
#ifndef NO_SOUND
|
||||||
ASND_Init();
|
ASND_SetDMACallback();
|
||||||
ASND_Pause(0);
|
ASND_Pause(0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -127,7 +126,11 @@ SwitchAudioMode(int mode)
|
|||||||
|
|
||||||
void InitialiseSound()
|
void InitialiseSound()
|
||||||
{
|
{
|
||||||
AUDIO_Init(NULL); // Start audio subsystem
|
#ifdef NO_SOUND
|
||||||
|
AUDIO_Init (NULL);
|
||||||
|
#else
|
||||||
|
ASND_Init();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net>
|
Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net>
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
Threading modifications/corrections by Tantric, 2009
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are
|
Redistribution and use in source and binary forms, with or without modification, are
|
||||||
permitted provided that the following conditions are met:
|
permitted provided that the following conditions are met:
|
||||||
|
|
||||||
@ -61,15 +63,15 @@ static private_data_ogg private_ogg;
|
|||||||
#define STACKSIZE 8192
|
#define STACKSIZE 8192
|
||||||
|
|
||||||
static u8 oggplayer_stack[STACKSIZE];
|
static u8 oggplayer_stack[STACKSIZE];
|
||||||
static lwpq_t oggplayer_queue;
|
static lwpq_t oggplayer_queue = LWP_TQUEUE_NULL;
|
||||||
static lwp_t h_oggplayer;
|
static lwp_t h_oggplayer = LWP_THREAD_NULL;
|
||||||
static int ogg_thread_running = 0;
|
static int ogg_thread_running = 0;
|
||||||
|
|
||||||
static void ogg_add_callback(int voice)
|
static void ogg_add_callback(int voice)
|
||||||
{
|
{
|
||||||
if (ogg_thread_running <= 0)
|
if (!ogg_thread_running)
|
||||||
{
|
{
|
||||||
SND_StopVoice(0);
|
ASND_StopVoice(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +80,7 @@ static void ogg_add_callback(int voice)
|
|||||||
|
|
||||||
if (private_ogg.pcm_indx >= READ_SAMPLES)
|
if (private_ogg.pcm_indx >= READ_SAMPLES)
|
||||||
{
|
{
|
||||||
if (SND_AddVoice(0,
|
if (ASND_AddVoice(0,
|
||||||
(void *) private_ogg.pcmout[private_ogg.pcmout_pos],
|
(void *) private_ogg.pcmout[private_ogg.pcmout_pos],
|
||||||
private_ogg.pcm_indx << 1) == 0)
|
private_ogg.pcm_indx << 1) == 0)
|
||||||
{
|
{
|
||||||
@ -101,14 +103,14 @@ static void ogg_add_callback(int voice)
|
|||||||
static void * ogg_player_thread(private_data_ogg * priv)
|
static void * ogg_player_thread(private_data_ogg * priv)
|
||||||
{
|
{
|
||||||
int first_time = 1;
|
int first_time = 1;
|
||||||
|
long ret;
|
||||||
|
|
||||||
ogg_thread_running = 0;
|
|
||||||
//init
|
//init
|
||||||
LWP_InitQueue(&oggplayer_queue);
|
LWP_InitQueue(&oggplayer_queue);
|
||||||
|
|
||||||
priv[0].vi = ov_info(&priv[0].vf, -1);
|
priv[0].vi = ov_info(&priv[0].vf, -1);
|
||||||
|
|
||||||
SND_Pause(0);
|
ASND_Pause(0);
|
||||||
|
|
||||||
priv[0].pcm_indx = 0;
|
priv[0].pcm_indx = 0;
|
||||||
priv[0].pcmout_pos = 0;
|
priv[0].pcmout_pos = 0;
|
||||||
@ -118,22 +120,15 @@ static void * ogg_player_thread(private_data_ogg * priv)
|
|||||||
|
|
||||||
ogg_thread_running = 1;
|
ogg_thread_running = 1;
|
||||||
|
|
||||||
while (!priv[0].eof)
|
while (!priv[0].eof && ogg_thread_running)
|
||||||
{
|
{
|
||||||
long ret;
|
|
||||||
if (ogg_thread_running <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (priv[0].flag)
|
if (priv[0].flag)
|
||||||
LWP_ThreadSleep(oggplayer_queue); // wait only when i have samples to send
|
LWP_ThreadSleep(oggplayer_queue); // wait only when i have samples to send
|
||||||
|
|
||||||
if (ogg_thread_running <= 0)
|
if (priv[0].flag == 0) // wait to all samples are sent
|
||||||
break;
|
|
||||||
|
|
||||||
if (priv[0].flag == 0) // wait to all samples are sended
|
|
||||||
{
|
{
|
||||||
if (SND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos])
|
if (ASND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos])
|
||||||
&& SND_StatusVoice(0) != SND_UNUSED)
|
&& ASND_StatusVoice(0) != SND_UNUSED)
|
||||||
{
|
{
|
||||||
priv[0].flag |= 64;
|
priv[0].flag |= 64;
|
||||||
continue;
|
continue;
|
||||||
@ -161,7 +156,6 @@ static void * ogg_player_thread(private_data_ogg * priv)
|
|||||||
ov_time_seek(&priv[0].vf, 0); // repeat
|
ov_time_seek(&priv[0].vf, 0); // repeat
|
||||||
else
|
else
|
||||||
priv[0].eof = 1; // stops
|
priv[0].eof = 1; // stops
|
||||||
//
|
|
||||||
}
|
}
|
||||||
else if (ret < 0)
|
else if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -188,12 +182,12 @@ static void * ogg_player_thread(private_data_ogg * priv)
|
|||||||
|
|
||||||
if (priv[0].flag == 1)
|
if (priv[0].flag == 1)
|
||||||
{
|
{
|
||||||
if (SND_StatusVoice(0) == SND_UNUSED || first_time)
|
if (ASND_StatusVoice(0) == SND_UNUSED || first_time)
|
||||||
{
|
{
|
||||||
first_time = 0;
|
first_time = 0;
|
||||||
if (priv[0].vi->channels == 2)
|
if (priv[0].vi->channels == 2)
|
||||||
{
|
{
|
||||||
SND_SetVoice(0, VOICE_STEREO_16BIT, priv[0].vi->rate, 0,
|
ASND_SetVoice(0, VOICE_STEREO_16BIT, priv[0].vi->rate, 0,
|
||||||
(void *) priv[0].pcmout[priv[0].pcmout_pos],
|
(void *) priv[0].pcmout[priv[0].pcmout_pos],
|
||||||
priv[0].pcm_indx << 1, priv[0].volume,
|
priv[0].pcm_indx << 1, priv[0].volume,
|
||||||
priv[0].volume, ogg_add_callback);
|
priv[0].volume, ogg_add_callback);
|
||||||
@ -203,7 +197,7 @@ static void * ogg_player_thread(private_data_ogg * priv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SND_SetVoice(0, VOICE_MONO_16BIT, priv[0].vi->rate, 0,
|
ASND_SetVoice(0, VOICE_MONO_16BIT, priv[0].vi->rate, 0,
|
||||||
(void *) priv[0].pcmout[priv[0].pcmout_pos],
|
(void *) priv[0].pcmout[priv[0].pcmout_pos],
|
||||||
priv[0].pcm_indx << 1, priv[0].volume,
|
priv[0].pcm_indx << 1, priv[0].volume,
|
||||||
priv[0].volume, ogg_add_callback);
|
priv[0].volume, ogg_add_callback);
|
||||||
@ -212,35 +206,32 @@ static void * ogg_player_thread(private_data_ogg * priv)
|
|||||||
priv[0].flag = 0;
|
priv[0].flag = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// if(priv[0].pcm_indx==0) priv[0].flag=0; // all samples sended
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
usleep(100);
|
||||||
}
|
}
|
||||||
ov_clear(&priv[0].vf);
|
ov_clear(&priv[0].vf);
|
||||||
priv[0].fd = -1;
|
priv[0].fd = -1;
|
||||||
priv[0].pcm_indx = 0;
|
priv[0].pcm_indx = 0;
|
||||||
ogg_thread_running = 0;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopOgg()
|
void StopOgg()
|
||||||
{
|
{
|
||||||
SND_StopVoice(0);
|
ASND_StopVoice(0);
|
||||||
if (ogg_thread_running > 0)
|
ogg_thread_running = 0;
|
||||||
{
|
|
||||||
ogg_thread_running = -2;
|
|
||||||
LWP_ThreadSignal(oggplayer_queue);
|
|
||||||
LWP_JoinThread(h_oggplayer, NULL);
|
|
||||||
|
|
||||||
while (((volatile int) ogg_thread_running) != 0)
|
if(h_oggplayer != LWP_THREAD_NULL)
|
||||||
{
|
{
|
||||||
;;;
|
if(oggplayer_queue != LWP_TQUEUE_NULL)
|
||||||
}
|
LWP_ThreadSignal(oggplayer_queue);
|
||||||
|
LWP_JoinThread(h_oggplayer, NULL);
|
||||||
|
h_oggplayer = LWP_THREAD_NULL;
|
||||||
|
}
|
||||||
|
if(oggplayer_queue != LWP_TQUEUE_NULL)
|
||||||
|
{
|
||||||
|
LWP_CloseQueue(oggplayer_queue);
|
||||||
|
oggplayer_queue = LWP_TQUEUE_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,8 +239,6 @@ int PlayOgg(int fd, int time_pos, int mode)
|
|||||||
{
|
{
|
||||||
StopOgg();
|
StopOgg();
|
||||||
|
|
||||||
ogg_thread_running = 0;
|
|
||||||
|
|
||||||
private_ogg.fd = fd;
|
private_ogg.fd = fd;
|
||||||
private_ogg.mode = mode;
|
private_ogg.mode = mode;
|
||||||
private_ogg.eof = 0;
|
private_ogg.eof = 0;
|
||||||
@ -269,23 +258,18 @@ int PlayOgg(int fd, int time_pos, int mode)
|
|||||||
{
|
{
|
||||||
mem_close(private_ogg.fd); // mem_close() can too close files from devices
|
mem_close(private_ogg.fd); // mem_close() can too close files from devices
|
||||||
private_ogg.fd = -1;
|
private_ogg.fd = -1;
|
||||||
ogg_thread_running = -1;
|
ogg_thread_running = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LWP_CreateThread(&h_oggplayer, (void *) ogg_player_thread,
|
if (LWP_CreateThread(&h_oggplayer, (void *) ogg_player_thread,
|
||||||
&private_ogg, oggplayer_stack, STACKSIZE, 80) == -1)
|
&private_ogg, oggplayer_stack, STACKSIZE, 80) == -1)
|
||||||
{
|
{
|
||||||
ogg_thread_running = -1;
|
ogg_thread_running = 0;
|
||||||
ov_clear(&private_ogg.vf);
|
ov_clear(&private_ogg.vf);
|
||||||
private_ogg.fd = -1;
|
private_ogg.fd = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
LWP_ThreadSignal(oggplayer_queue);
|
|
||||||
while (((volatile int) ogg_thread_running) == 0)
|
|
||||||
{
|
|
||||||
;;;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,39 +288,33 @@ void PauseOgg(int pause)
|
|||||||
if (ogg_thread_running > 0)
|
if (ogg_thread_running > 0)
|
||||||
{
|
{
|
||||||
LWP_ThreadSignal(oggplayer_queue);
|
LWP_ThreadSignal(oggplayer_queue);
|
||||||
// while(((volatile int )private_ogg.flag)!=1 && ((volatile int )ogg_thread_running)>0) {;;;}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int StatusOgg()
|
int StatusOgg()
|
||||||
{
|
{
|
||||||
if (ogg_thread_running <= 0)
|
if (ogg_thread_running == 0)
|
||||||
return -1; // Error
|
return -1; // Error
|
||||||
|
else if (private_ogg.eof)
|
||||||
if (private_ogg.eof)
|
|
||||||
return 255; // EOF
|
return 255; // EOF
|
||||||
|
else if (private_ogg.flag & 128)
|
||||||
if (private_ogg.flag & 128)
|
|
||||||
return 2; // paused
|
return 2; // paused
|
||||||
return 1; // running
|
else
|
||||||
|
return 1; // running
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetVolumeOgg(int volume)
|
void SetVolumeOgg(int volume)
|
||||||
{
|
{
|
||||||
private_ogg.volume = volume;
|
private_ogg.volume = volume;
|
||||||
|
ASND_ChangeVolumeVoice(0, volume, volume);
|
||||||
SND_ChangeVolumeVoice(0, volume, volume);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 GetTimeOgg()
|
s32 GetTimeOgg()
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
if (ogg_thread_running <= 0)
|
if (ogg_thread_running == 0 || private_ogg.fd < 0)
|
||||||
return 0;
|
|
||||||
if (private_ogg.fd < 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
ret = ((s32) ov_time_tell(&private_ogg.vf));
|
ret = ((s32) ov_time_tell(&private_ogg.vf));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -90,7 +90,6 @@ static camera cam = { {0.0F, 0.0F, 0.0F},
|
|||||||
* VideoThreading
|
* VideoThreading
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#define TSTACK 16384
|
#define TSTACK 16384
|
||||||
static lwpq_t videoblankqueue;
|
|
||||||
static lwp_t vbthread;
|
static lwp_t vbthread;
|
||||||
static unsigned char vbstack[TSTACK];
|
static unsigned char vbstack[TSTACK];
|
||||||
|
|
||||||
@ -116,18 +115,11 @@ vbgetback (void *arg)
|
|||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* InitVideoThread
|
* InitVideoThread
|
||||||
*
|
|
||||||
* libOGC provides a nice wrapper for LWP access.
|
|
||||||
* This function sets up a new local queue and attaches the thread to it.
|
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
void
|
void
|
||||||
InitVideoThread ()
|
InitVideoThread ()
|
||||||
{
|
{
|
||||||
/*** Initialise a new queue ***/
|
LWP_CreateThread (&vbthread, vbgetback, NULL, vbstack, TSTACK, 100);
|
||||||
LWP_InitQueue (&videoblankqueue);
|
|
||||||
|
|
||||||
/*** Create the thread on this queue ***/
|
|
||||||
LWP_CreateThread (&vbthread, vbgetback, NULL, vbstack, TSTACK, 150);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
Loading…
Reference in New Issue
Block a user