From 1278c67853543a57fb69d635cc26b56ff89cf50b Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Mon, 2 Jan 2023 17:34:24 +0200 Subject: [PATCH 16/16] 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 c44fb65acd..dece14c77b 100644 --- a/client/audio.c +++ b/client/audio.c @@ -47,7 +47,7 @@ #define SOUNDSPEC_CAPSTR "+Freeciv-3.0-soundset" #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; } @@ -339,7 +341,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; } } @@ -618,15 +620,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); @@ -638,6 +647,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 bf33846bcd..8cb378f8b0 100644 --- a/client/audio.h +++ b/client/audio.h @@ -29,8 +29,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); @@ -52,7 +53,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 27ff35ea7a..05b8fa2dee 100644 --- a/client/audio_none.c +++ b/client/audio_none.c @@ -27,8 +27,9 @@ /************************************************************************** Clean up **************************************************************************/ -static void none_audio_shutdown(void) +static void none_audio_shutdown(struct audio_plugin *self) { + self->initialized = FALSE; } /************************************************************************** @@ -61,8 +62,10 @@ static bool none_audio_play(const char *const tag, const char *const fullpath, /************************************************************************** Initialize. **************************************************************************/ -static bool none_audio_init(void) +static bool none_audio_init(struct audio_plugin *self) { + self->initialized = TRUE; + return TRUE; } @@ -75,6 +78,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 575518f994..0a6849291c 100644 --- a/client/audio_sdl.c +++ b/client/audio_sdl.c @@ -154,14 +154,14 @@ static bool sdl_audio_play(const char *const tag, const char *const fullpath, **************************************************************************/ 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) { @@ -207,14 +207,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); @@ -230,7 +232,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; @@ -244,7 +246,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; } @@ -253,8 +256,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; } @@ -268,6 +275,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 57f0e69f1a..9da24140e3 100644 --- a/client/client_main.c +++ b/client/client_main.c @@ -744,6 +744,9 @@ void 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 b7b3970116..fb4f74d253 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; @@ -1337,6 +1339,8 @@ void fc_support_init(void) #ifndef HAVE_LOCALTIME_R fc_init_mutex(&localtime_mutex); #endif /* HAVE_LOCALTIME_R */ + + support_initialized = TRUE; } /***************************************************************** @@ -1344,6 +1348,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); @@ -1358,3 +1364,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 e4335b9fee..082f592fb6 100644 --- a/utility/support.h +++ b/utility/support.h @@ -125,6 +125,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); @@ -214,4 +215,4 @@ int fc_at_quick_exit(void (*func)(void)); } #endif /* __cplusplus */ -#endif /* FC__SUPPORT_H */ +#endif /* FC__SUPPORT_H */ -- 2.39.0