aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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