aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-10-08 15:22:39 +0200
committerMax Kellermann <max@duempel.org>2009-10-08 15:22:39 +0200
commitecb118f1edab572a904890eddafd3b11c0a79a79 (patch)
tree4e273cd64778fcff80250b3b33ffb050a257c981
parent1e663b186998ffdeef9b3b9775558e9378bad342 (diff)
downloadmpd-ecb118f1edab572a904890eddafd3b11c0a79a79.tar.gz
mpd-ecb118f1edab572a904890eddafd3b11c0a79a79.tar.xz
mpd-ecb118f1edab572a904890eddafd3b11c0a79a79.zip
state_file: save only if something has changed
If nothing has changed since the last save, don't save the state file. Saving will spin up the hard drive, which is undesirable on hosts where MPD is idling in background.
-rw-r--r--NEWS1
-rw-r--r--src/output_command.c6
-rw-r--r--src/output_state.c8
-rw-r--r--src/output_state.h8
-rw-r--r--src/playlist_state.c18
-rw-r--r--src/playlist_state.h9
-rw-r--r--src/state_file.c22
-rw-r--r--src/volume.c6
-rw-r--r--src/volume.h9
9 files changed, 87 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index a33879be7..64666d2ff 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,7 @@ ver 0.16 (20??/??/??)
* renamed option "--stdout" to "--stderr"
* removed options --create-db and --no-create-db
* automatically update the database with Linux inotify
+* state_file: save only if something has changed
* obey $(sysconfdir) for default mpd.conf location
diff --git a/src/output_command.c b/src/output_command.c
index 5da176dde..9d948c8cc 100644
--- a/src/output_command.c
+++ b/src/output_command.c
@@ -31,6 +31,8 @@
#include "mixer_control.h"
#include "idle.h"
+extern unsigned audio_output_state_version;
+
bool
audio_output_enable_index(unsigned idx)
{
@@ -44,6 +46,8 @@ audio_output_enable_index(unsigned idx)
ao->enabled = true;
idle_add(IDLE_OUTPUT);
+ ++audio_output_state_version;
+
return true;
}
@@ -67,5 +71,7 @@ audio_output_disable_index(unsigned idx)
idle_add(IDLE_MIXER);
}
+ ++audio_output_state_version;
+
return true;
}
diff --git a/src/output_state.c b/src/output_state.c
index 7fc60518c..be135f6d0 100644
--- a/src/output_state.c
+++ b/src/output_state.c
@@ -34,6 +34,8 @@
#define AUDIO_DEVICE_STATE "audio_device_state:"
+unsigned audio_output_state_version;
+
void
audio_output_state_save(FILE *fp)
{
@@ -80,3 +82,9 @@ audio_output_state_read(const char *line)
ao->enabled = false;
return true;
}
+
+unsigned
+audio_output_state_get_version(void)
+{
+ return audio_output_state_version;
+}
diff --git a/src/output_state.h b/src/output_state.h
index 1efae94a1..3b865f5fe 100644
--- a/src/output_state.h
+++ b/src/output_state.h
@@ -34,4 +34,12 @@ audio_output_state_read(const char *line);
void
audio_output_state_save(FILE *fp);
+/**
+ * Generates a version number for the current state of the audio
+ * outputs. This is used by timer_save_state_file() to determine
+ * whether the state has changed and the state file should be saved.
+ */
+unsigned
+audio_output_state_get_version(void);
+
#endif
diff --git a/src/playlist_state.c b/src/playlist_state.c
index f288a5738..5d18cc339 100644
--- a/src/playlist_state.c
+++ b/src/playlist_state.c
@@ -200,3 +200,21 @@ playlist_state_restore(const char *line, FILE *fp, struct playlist *playlist)
return true;
}
+
+unsigned
+playlist_state_get_hash(const struct playlist *playlist)
+{
+ return playlist->queue.version ^
+ (getPlayerElapsedTime() << 8) ^
+ (playlist->current >= 0
+ ? (queue_order_to_position(&playlist->queue,
+ playlist->current) << 16)
+ : 0) ^
+ ((int)getPlayerCrossFade() << 20) ^
+ (getPlayerState() << 24) ^
+ (playlist->queue.random << 27) ^
+ (playlist->queue.repeat << 28) ^
+ (playlist->queue.single << 29) ^
+ (playlist->queue.consume << 30) ^
+ (playlist->queue.random << 31);
+}
diff --git a/src/playlist_state.h b/src/playlist_state.h
index 7ed7e8c8e..d116aaeb1 100644
--- a/src/playlist_state.h
+++ b/src/playlist_state.h
@@ -36,4 +36,13 @@ playlist_state_save(FILE *fp, const struct playlist *playlist);
bool
playlist_state_restore(const char *line, FILE *fp, struct playlist *playlist);
+/**
+ * Generates a hash number for the current state of the playlist and
+ * the playback options. This is used by timer_save_state_file() to
+ * determine whether the state has changed and the state file should
+ * be saved.
+ */
+unsigned
+playlist_state_get_hash(const struct playlist *playlist);
+
#endif
diff --git a/src/state_file.c b/src/state_file.c
index 14c76d739..4ba157b14 100644
--- a/src/state_file.c
+++ b/src/state_file.c
@@ -36,6 +36,13 @@ 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(void)
{
@@ -57,6 +64,10 @@ state_file_write(void)
playlist_state_save(fp, &g_playlist);
while(fclose(fp) && errno == EINTR) /* nothing */;
+
+ prev_volume_version = sw_volume_state_get_hash();
+ prev_output_version = audio_output_state_get_version();
+ prev_playlist_version = playlist_state_get_hash(&g_playlist);
}
static void
@@ -88,6 +99,10 @@ state_file_read(void)
}
while(fclose(fp) && errno == EINTR) /* nothing */;
+
+ prev_volume_version = sw_volume_state_get_hash();
+ prev_output_version = audio_output_state_get_version();
+ prev_playlist_version = playlist_state_get_hash(&g_playlist);
}
/**
@@ -97,6 +112,13 @@ state_file_read(void)
static gboolean
timer_save_state_file(G_GNUC_UNUSED gpointer 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(&g_playlist))
+ /* nothing has changed - don't save the state file,
+ don't spin up the hard disk */
+ return true;
+
state_file_write();
return true;
}
diff --git a/src/volume.c b/src/volume.c
index 5f4a66837..8b33f592d 100644
--- a/src/volume.c
+++ b/src/volume.c
@@ -122,3 +122,9 @@ void save_sw_volume_state(FILE *fp)
{
fprintf(fp, SW_VOLUME_STATE "%u\n", volume_software_set);
}
+
+unsigned
+sw_volume_state_get_hash(void)
+{
+ return volume_software_set;
+}
diff --git a/src/volume.h b/src/volume.h
index 0db231ef6..66e7c43f0 100644
--- a/src/volume.h
+++ b/src/volume.h
@@ -36,4 +36,13 @@ read_sw_volume_state(const char *line);
void save_sw_volume_state(FILE *fp);
+/**
+ * Generates a hash number for the current state of the software
+ * volume control. This is used by timer_save_state_file() to
+ * determine whether the state has changed and the state file should
+ * be saved.
+ */
+unsigned
+sw_volume_state_get_hash(void);
+
#endif