From 24bf24015e9baa4c558e24e5a53a89886e5621c7 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Mon, 2 Jan 2023 17:27:35 +0200 Subject: [PATCH 42/42] Client: Play quit sound while we still can On normal shutdown, play the quit sound before closing support for construcing its tag. Atexit handler still used in case of other kind of shutdown. See osdn #46426 Signed-off-by: Marko Lindqvist --- client/audio.c | 36 +++++++++++++++++++++++++++--------- client/audio.h | 7 ++++--- client/audio_none.c | 8 ++++++-- client/audio_sdl.c | 22 +++++++++++++++------- client/client_main.c | 3 +++ utility/support.c | 14 ++++++++++++++ utility/support.h | 3 ++- 7 files changed, 71 insertions(+), 22 deletions(-) diff --git a/client/audio.c b/client/audio.c index 935dc7e800..dc52d5f1d4 100644 --- a/client/audio.c +++ b/client/audio.c @@ -47,7 +47,7 @@ #define SOUNDSPEC_CAPSTR "+Freeciv-soundset-Devel-2022-07-03" #define MUSICSPEC_CAPSTR "+Freeciv-2.6-musicset" -/* keep it open throughout */ +/* Keep them open throughout */ static struct section_file *ss_tagfile = NULL; static struct section_file *ms_tagfile = NULL; @@ -69,6 +69,8 @@ static int audio_play_tag(struct section_file *sfile, const char *tag, bool repeat, int exclude, bool keep_old_style); +static void audio_shutdown_atexit(void); + /**********************************************************************//** Returns a static string vector of all sound plugins available on the system. This function is unfortunately similar to @@ -156,7 +158,7 @@ bool audio_select_plugin(const char *const name) log_debug("Shutting down %s", plugins[selected_plugin].name); plugins[selected_plugin].stop(); plugins[selected_plugin].wait(); - plugins[selected_plugin].shutdown(); + plugins[selected_plugin].shutdown(&(plugins[selected_plugin])); } if (!found) { @@ -165,7 +167,7 @@ bool audio_select_plugin(const char *const name) exit(EXIT_FAILURE); } - if (!plugins[i].init()) { + if (!plugins[i].init(&(plugins[i]))) { log_error("Plugin %s found, but can't be initialized.", name); return FALSE; } @@ -342,7 +344,7 @@ void audio_real_init(const char *const soundset_name, static bool atexit_set = FALSE; if (!atexit_set) { - atexit(audio_shutdown); + atexit(audio_shutdown_atexit); atexit_set = TRUE; } } @@ -637,15 +639,22 @@ void audio_set_volume(double volume) /**********************************************************************//** Call this at end of program only. + + @param play_quit_tag Play exit sound **************************************************************************/ -void audio_shutdown(void) +void audio_shutdown(bool play_quit_tag) { - /* avoid infinite loop at end of game */ + /* Avoid infinite loop at end of game */ audio_stop(); - audio_play_sound("e_game_quit", NULL); - plugins[selected_plugin].wait(); - plugins[selected_plugin].shutdown(); + if (play_quit_tag) { + audio_play_sound("e_game_quit", NULL); + } + + if (plugins[selected_plugin].initialized) { + plugins[selected_plugin].wait(); + plugins[selected_plugin].shutdown(&(plugins[selected_plugin])); + } if (NULL != ss_tagfile) { secfile_destroy(ss_tagfile); @@ -657,6 +666,15 @@ void audio_shutdown(void) } } +/**********************************************************************//** + Called as atexit handler. +**************************************************************************/ +static void audio_shutdown_atexit(void) +{ + /* If support has already been shut down, can't handle audio tags. */ + audio_shutdown(are_support_services_available()); +} + /**********************************************************************//** Returns a string which list all available plugins. You don't have to free the string. diff --git a/client/audio.h b/client/audio.h index 102f066d4e..813897cbd2 100644 --- a/client/audio.h +++ b/client/audio.h @@ -30,8 +30,9 @@ typedef void (*audio_finished_callback)(void); struct audio_plugin { char name[MAX_AUDIO_NAME_LEN]; char descr[MAX_AUDIO_DESCR_LEN]; - bool (*init) (void); - void (*shutdown) (void); + bool initialized; + bool (*init) (struct audio_plugin *self); + void (*shutdown) (struct audio_plugin *self); void (*stop) (void); void (*wait) (void); double (*get_volume) (void); @@ -55,7 +56,7 @@ void audio_real_init(const char *const soundspec_name, const char *const musicset_name, const char *const preferred_plugin_name); void audio_add_plugin(struct audio_plugin *p); -void audio_shutdown(void); +void audio_shutdown(bool play_quit_tag); void audio_stop(void); void audio_stop_usage(void); void audio_restart(const char *soundset_name, const char *musicset_name); diff --git a/client/audio_none.c b/client/audio_none.c index 30ad9740aa..86dd0fc75a 100644 --- a/client/audio_none.c +++ b/client/audio_none.c @@ -29,8 +29,9 @@ /**********************************************************************//** Clean up **************************************************************************/ -static void none_audio_shutdown(void) +static void none_audio_shutdown(struct audio_plugin *self) { + self->initialized = FALSE; } /**********************************************************************//** @@ -77,8 +78,10 @@ static void none_audio_resume(void) /**********************************************************************//** Initialize. **************************************************************************/ -static bool none_audio_init(void) +static bool none_audio_init(struct audio_plugin *self) { + self->initialized = TRUE; + return TRUE; } @@ -91,6 +94,7 @@ void audio_none_init(void) sz_strlcpy(self.name, "none"); sz_strlcpy(self.descr, "/dev/null plugin"); + self.initialized = FALSE; self.init = none_audio_init; self.shutdown = none_audio_shutdown; self.stop = none_audio_stop; diff --git a/client/audio_sdl.c b/client/audio_sdl.c index 7b49176dbf..51571d8f01 100644 --- a/client/audio_sdl.c +++ b/client/audio_sdl.c @@ -165,14 +165,14 @@ static void sdl_audio_resume(void) **************************************************************************/ static void sdl_audio_stop(void) { - /* fade out over 2 sec */ + /* Fade out over 2 sec */ Mix_FadeOutMusic(2000); } /**********************************************************************//** Wait for audio to die on all channels. WARNING: If a channel is looping, it will NEVER exit! Always call - music_stop() first! + stop_style_music() first! **************************************************************************/ static void sdl_audio_wait(void) { @@ -216,14 +216,16 @@ static int init_sdl_audio(void) /**********************************************************************//** Clean up. **************************************************************************/ -static void sdl_audio_shutdown(void) +static void sdl_audio_shutdown(struct audio_plugin *self) { int i; + self->initialized = FALSE; + sdl_audio_stop(); sdl_audio_wait(); - /* remove all buffers */ + /* Remove all buffers */ for (i = 0; i < MIX_CHANNELS; i++) { if (samples[i].wave) { Mix_FreeChunk(samples[i].wave); @@ -239,7 +241,7 @@ static void sdl_audio_shutdown(void) /**********************************************************************//** Initialize. **************************************************************************/ -static bool sdl_audio_init(void) +static bool sdl_audio_init(struct audio_plugin *self) { /* Initialize variables */ const int audio_rate = MIX_DEFAULT_FREQUENCY; @@ -253,7 +255,8 @@ static bool sdl_audio_init(void) if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, buf_size) < 0) { log_error("Error calling Mix_OpenAudio"); - /* try something else */ + + /* Try something else */ quit_sdl_audio(); return FALSE; } @@ -262,8 +265,12 @@ static bool sdl_audio_init(void) for (i = 0; i < MIX_CHANNELS; i++) { samples[i].wave = NULL; } - /* sanity check, for now; add volume controls later */ + + /* Sanity check, for now; add volume controls later */ sdl_audio_set_volume(sdl_audio_volume); + + self->initialized = TRUE; + return TRUE; } @@ -277,6 +284,7 @@ void audio_sdl_init(void) sz_strlcpy(self.name, "sdl"); sz_strlcpy(self.descr, "Simple DirectMedia Library (SDL) mixer plugin"); + self.initialized = FALSE; self.init = sdl_audio_init; self.shutdown = sdl_audio_shutdown; self.stop = sdl_audio_stop; diff --git a/client/client_main.c b/client/client_main.c index 95f3bda671..cdb2665ded 100644 --- a/client/client_main.c +++ b/client/client_main.c @@ -734,6 +734,9 @@ void fc__noreturn client_exit(int return_value) ui_exit(); + /* Play the exit sound while audio system dependencies still up. */ + audio_shutdown(TRUE); + script_client_free(); editor_free(); diff --git a/utility/support.c b/utility/support.c index 17e3970e25..a8e237d08c 100644 --- a/utility/support.c +++ b/utility/support.c @@ -111,6 +111,8 @@ #include "support.h" +static bool support_initialized = FALSE; + static int icu_buffer_uchars = 0; static UChar *icu_buffer1 = NULL; static UChar *icu_buffer2 = NULL; @@ -1343,6 +1345,8 @@ void fc_support_init(void) #ifndef HAVE_LOCALTIME_R fc_init_mutex(&localtime_mutex); #endif /* HAVE_LOCALTIME_R */ + + support_initialized = TRUE; } /************************************************************************//** @@ -1350,6 +1354,8 @@ void fc_support_init(void) ****************************************************************************/ void fc_support_free(void) { + support_initialized = FALSE; + #ifndef HAVE_WORKING_VSNPRINTF if (vsnprintf_buf != NULL) { free(vsnprintf_buf); @@ -1364,3 +1370,11 @@ void fc_support_free(void) fc_strAPI_free(); } + +/************************************************************************//** + Is the support module currently in usable state? +****************************************************************************/ +bool are_support_services_available(void) +{ + return support_initialized; +} diff --git a/utility/support.h b/utility/support.h index cdfa042c9a..b112ad93d8 100644 --- a/utility/support.h +++ b/utility/support.h @@ -141,6 +141,7 @@ int fc_strncasequotecmp(const char *str0, const char *str1, size_t n); void fc_support_init(void); void fc_support_free(void); +bool are_support_services_available(void); size_t effectivestrlenquote(const char *str); @@ -230,4 +231,4 @@ int fc_at_quick_exit(void (*func)(void)); } #endif /* __cplusplus */ -#endif /* FC__SUPPORT_H */ +#endif /* FC__SUPPORT_H */ -- 2.39.0