diff options
-rw-r--r-- | src/Main.cxx | 22 | ||||
-rw-r--r-- | src/StateFile.cxx | 98 | ||||
-rw-r--r-- | src/StateFile.hxx | 35 |
3 files changed, 80 insertions, 75 deletions
diff --git a/src/Main.cxx b/src/Main.cxx index f9062cccb..e0083bff7 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -101,6 +101,8 @@ EventLoop *main_loop; Partition *global_partition; +static StateFile *state_file; + static bool glue_daemonize_init(const struct options *options, GError **error_r) { @@ -225,14 +227,18 @@ glue_state_file_init(GError **error_r) GError *error = NULL; char *path = config_dup_path(CONF_STATE_FILE, &error); - if (path == NULL && error != NULL) { - g_propagate_error(error_r, error); - return false; + if (path == nullptr) { + if (error != nullptr) { + g_propagate_error(error_r, error); + return false; + } + + return true; } - state_file_init(path, *global_partition); + state_file = new StateFile(path, *global_partition, *main_loop); g_free(path); - + state_file->Read(); return true; } @@ -519,7 +525,11 @@ int mpd_main(int argc, char *argv[]) mpd_inotify_finish(); #endif - state_file_finish(*global_partition); + if (state_file != nullptr) { + state_file->Write(); + delete state_file; + } + pc_kill(&global_partition->pc); finishZeroconf(); client_manager_deinit(); diff --git a/src/StateFile.cxx b/src/StateFile.cxx index a153a6263..a19eac55c 100644 --- a/src/StateFile.cxx +++ b/src/StateFile.cxx @@ -24,7 +24,6 @@ #include "TextFile.hxx" #include "Partition.hxx" #include "Volume.hxx" -#include "Main.hxx" #include "event/Loop.hxx" #include <glib.h> @@ -35,31 +34,29 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "state_file" -static char *state_file_path; - -/** the GLib source id for the save timer */ -static guint save_state_source_id; - -/** - * These version numbers determine whether we need to save the state - * file. If nothing has changed, we won't let the hard drive spin up. - */ -static unsigned prev_volume_version, prev_output_version, - prev_playlist_version; - -static void -state_file_write(Partition &partition) +StateFile::StateFile(const char *_path, Partition &_partition, EventLoop &_loop) + :path(_path), partition(_partition), loop(_loop), + source_id(0), + prev_volume_version(0), prev_output_version(0), + prev_playlist_version(0) { - FILE *fp; + source_id = loop.AddTimeoutSeconds(5 * 60, TimerCallback, this); +} - assert(state_file_path != NULL); +StateFile::~StateFile() +{ + g_source_remove(source_id); +} - g_debug("Saving state file %s", state_file_path); +void +StateFile::Write() +{ + g_debug("Saving state file %s", path.c_str()); - fp = fopen(state_file_path, "w"); + FILE *fp = fopen(path.c_str(), "w"); if (G_UNLIKELY(!fp)) { g_warning("failed to create %s: %s", - state_file_path, g_strerror(errno)); + path.c_str(), g_strerror(errno)); return; } @@ -75,19 +72,17 @@ state_file_write(Partition &partition) &partition.pc); } -static void -state_file_read(Partition &partition) +void +StateFile::Read() { bool success; - assert(state_file_path != NULL); + g_debug("Loading state file %s", path.c_str()); - g_debug("Loading state file %s", state_file_path); - - TextFile file(state_file_path); + TextFile file(path.c_str()); if (file.HasFailed()) { g_warning("failed to open %s: %s", - state_file_path, g_strerror(errno)); + path.c_str(), g_strerror(errno)); return; } @@ -107,54 +102,29 @@ state_file_read(Partition &partition) &partition.pc); } -/** - * This function is called every 5 minutes by the GLib main loop, and - * saves the state file. - */ -static gboolean -timer_save_state_file(gpointer data) +inline void +StateFile::AutoWrite() { - Partition &partition = *(Partition *)data; - if (prev_volume_version == sw_volume_state_get_hash() && prev_output_version == audio_output_state_get_version() && prev_playlist_version == playlist_state_get_hash(&partition.playlist, &partition.pc)) /* nothing has changed - don't save the state file, don't spin up the hard disk */ - return true; - - state_file_write(partition); - return true; -} - -void -state_file_init(const char *path, Partition &partition) -{ - assert(state_file_path == NULL); - - if (path == NULL) return; - state_file_path = g_strdup(path); - state_file_read(partition); - - save_state_source_id = - main_loop->AddTimeoutSeconds(5 * 60, timer_save_state_file, - &partition); + Write(); } -void -state_file_finish(Partition &partition) +/** + * This function is called every 5 minutes by the GLib main loop, and + * saves the state file. + */ +gboolean +StateFile::TimerCallback(gpointer data) { - if (state_file_path == NULL) - /* no state file configured, no cleanup required */ - return; - - if (save_state_source_id != 0) - g_source_remove(save_state_source_id); + StateFile &state_file = *(StateFile *)data; - state_file_write(partition); - - g_free(state_file_path); + state_file.AutoWrite(); + return true; } diff --git a/src/StateFile.hxx b/src/StateFile.hxx index 35269fe40..0888b25ad 100644 --- a/src/StateFile.hxx +++ b/src/StateFile.hxx @@ -20,14 +20,39 @@ #ifndef MPD_STATE_FILE_HXX #define MPD_STATE_FILE_HXX +#include <glib.h> + +#include <string> + struct Partition; +class EventLoop; + +class StateFile { + std::string path; + + Partition &partition; + EventLoop &loop; + + /** the GLib source id for the save timer */ + guint source_id; + + /** + * These version numbers determine whether we need to save the state + * file. If nothing has changed, we won't let the hard drive spin up. + */ + unsigned prev_volume_version, prev_output_version, + prev_playlist_version; -void -state_file_init(const char *path, Partition &partition); +public: + StateFile(const char *path, Partition &partition, EventLoop &loop); + ~StateFile(); -void -state_file_finish(Partition &partition); + void Read(); + void Write(); + void AutoWrite(); -void write_state_file(void); +private: + static gboolean TimerCallback(gpointer data); +}; #endif /* STATE_FILE_H */ |