make audio safer

- centralized stop function
- freeing the struct not from the thread while waiting on handle in it
- thread not detached
- maybe fixes hang on exit from HM in ndsp status check loop
This commit is contained in:
LiquidFenrir
2022-06-14 12:54:02 +02:00
parent 9ebfe387a0
commit 4a56a883fa
5 changed files with 26 additions and 30 deletions

View File

@@ -46,9 +46,10 @@ typedef struct {
u32 filesize; u32 filesize;
volatile bool stop; volatile bool stop;
Handle finished; Thread playing_thread;
} audio_s; } audio_s;
void play_audio(audio_s *); void play_audio(audio_s *);
void stop_audio(audio_s**);
#endif #endif

View File

@@ -608,7 +608,6 @@ Result load_audio(Entry_s entry, audio_s *audio)
} }
audio->mix[0] = audio->mix[1] = 1.0f; // Determines volume for the 12 (?) different outputs. See http://smealum.github.io/ctrulib/channel_8h.html#a30eb26f1972cc3ec28370263796c0444 audio->mix[0] = audio->mix[1] = 1.0f; // Determines volume for the 12 (?) different outputs. See http://smealum.github.io/ctrulib/channel_8h.html#a30eb26f1972cc3ec28370263796c0444
svcCreateEvent(&audio->finished, RESET_STICKY);
ndspChnSetInterp(0, NDSP_INTERP_LINEAR); ndspChnSetInterp(0, NDSP_INTERP_LINEAR);
ndspChnSetMix(0, audio->mix); // See mix comment above ndspChnSetMix(0, audio->mix); // See mix comment above

View File

@@ -37,7 +37,7 @@
bool quit = false; bool quit = false;
bool dspfirm = false; bool dspfirm = false;
audio_s * audio = NULL; static audio_s * audio = NULL;
static bool homebrew = false; static bool homebrew = false;
static bool installed_themes = false; static bool installed_themes = false;
@@ -165,8 +165,7 @@ void exit_function(bool power_pressed)
{ {
if(audio) if(audio)
{ {
audio->stop = true; stop_audio(&audio);
svcWaitSynchronization(audio->finished, U64_MAX);
} }
free_lists(); free_lists();
svcCloseHandle(update_icons_mutex); svcCloseHandle(update_icons_mutex);
@@ -512,9 +511,7 @@ int main(void)
preview_mode = false; preview_mode = false;
if(current_mode == MODE_THEMES && audio) if(current_mode == MODE_THEMES && audio)
{ {
audio->stop = true; stop_audio(&audio);
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
} }
} }
continue; continue;
@@ -524,9 +521,7 @@ int main(void)
preview_mode = false; preview_mode = false;
if(current_mode == MODE_THEMES && audio) if(current_mode == MODE_THEMES && audio)
{ {
audio->stop = true; stop_audio(&audio);
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
} }
continue; continue;
} }

View File

@@ -69,17 +69,26 @@ void thread_audio(void* data) {
while(!audio->stop) { while(!audio->stop) {
update_audio(audio); update_audio(audio);
} }
free(audio->filebuf); ndspChnWaveBufClear(0);
ndspChnReset(0);
ov_clear(&audio->vf); ov_clear(&audio->vf);
free(audio->filebuf);
linearFree((void*)audio->wave_buf[0].data_vaddr); linearFree((void*)audio->wave_buf[0].data_vaddr);
linearFree((void*)audio->wave_buf[1].data_vaddr); linearFree((void*)audio->wave_buf[1].data_vaddr);
while (audio->wave_buf[0].status != NDSP_WBUF_DONE || audio->wave_buf[1].status != NDSP_WBUF_DONE) svcSleepThread(1e7);
svcSignalEvent(audio->finished);
svcSleepThread(1e8);
svcCloseHandle(audio->finished);
free(audio);
} }
void play_audio(audio_s *audio) { void play_audio(audio_s *audio) {
threadCreate(thread_audio, audio, 0x1000, 0x3F, 1, true); audio->playing_thread = threadCreate(thread_audio, audio, 0x1000, 0x3F, 1, false);
}
void stop_audio(audio_s** audio_ptr) {
audio_s* audio = *audio_ptr;
if(audio->playing_thread)
{
audio->stop = true;
threadJoin(audio->playing_thread, U64_MAX);
threadFree(audio->playing_thread);
}
free(audio);
*audio_ptr = NULL;
} }

View File

@@ -569,9 +569,7 @@ bool themeplaza_browser(EntryMode mode)
preview_mode = false; preview_mode = false;
if (mode == MODE_THEMES && audio != NULL) if (mode == MODE_THEMES && audio != NULL)
{ {
audio->stop = true; stop_audio(&audio);
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
} }
} }
} }
@@ -582,9 +580,7 @@ bool themeplaza_browser(EntryMode mode)
preview_mode = false; preview_mode = false;
if (mode == MODE_THEMES && audio != NULL) if (mode == MODE_THEMES && audio != NULL)
{ {
audio->stop = true; stop_audio(&audio);
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
} }
} }
else else
@@ -650,9 +646,7 @@ bool themeplaza_browser(EntryMode mode)
preview_mode = false; preview_mode = false;
if (mode == MODE_THEMES && audio) if (mode == MODE_THEMES && audio)
{ {
audio->stop = true; stop_audio(&audio);
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
} }
continue; continue;
} }
@@ -721,9 +715,7 @@ bool themeplaza_browser(EntryMode mode)
if (audio) if (audio)
{ {
audio->stop = true; stop_audio(&audio);
svcWaitSynchronization(audio->finished, U64_MAX);
audio = NULL;
} }
free_preview(preview); free_preview(preview);