fix long-standing menu "random" lockup/crashing bug. caused by Hermes' oggplayer threading. oggplayer rewritten.

This commit is contained in:
dborth 2009-06-13 08:41:35 +00:00
parent 00e80c3f32
commit 1a5885f0ce
3 changed files with 48 additions and 75 deletions

View File

@ -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
} }
/**************************************************************************** /****************************************************************************

View File

@ -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)

View File

@ -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);
} }
/**************************************************************************** /****************************************************************************