From f7cc5b2efddece7cdc4fc5b7fc5324d33b7dfa8f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 15 Jul 2009 16:57:37 +0200 Subject: [PATCH] state_file: don't rewind the stream while reading the state file Parse the state file line by line, let each subsystem probe a line. Only the playlist_state code gets the FILE pointer to read the following lines. --- src/output_state.c | 47 ++++++++++++++++++++++---------------------- src/output_state.h | 5 +++-- src/playlist_state.c | 29 ++++++++++++++------------- src/playlist_state.h | 5 +++-- src/state_file.c | 16 ++++++++++----- src/volume.c | 24 +++++++++++----------- src/volume.h | 3 ++- 7 files changed, 68 insertions(+), 61 deletions(-) diff --git a/src/output_state.c b/src/output_state.c index c7e6c8579..5efae3626 100644 --- a/src/output_state.c +++ b/src/output_state.c @@ -49,35 +49,34 @@ saveAudioDevicesState(FILE *fp) } } -void -readAudioDevicesState(FILE *fp) +bool +readAudioDevicesState(const char *line) { - char buffer[1024]; + long value; + char *endptr; + const char *name; + struct audio_output *ao; - while (fgets(buffer, sizeof(buffer), fp)) { - char *c, *name; - struct audio_output *ao; + if (!g_str_has_prefix(line, AUDIO_DEVICE_STATE)) + return false; - g_strchomp(buffer); + line += sizeof(AUDIO_DEVICE_STATE) - 1; - if (!g_str_has_prefix(buffer, AUDIO_DEVICE_STATE)) - continue; + value = strtol(line, &endptr, 10); + if (*endptr != ':' || (value != 0 && value != 1)) + return false; - c = strchr(buffer, ':'); - if (!c || !(++c)) - goto errline; + if (value != 0) + /* state is "enabled": no-op */ + return true; - name = strchr(c, ':'); - if (!name || !(++name)) - goto errline; - - ao = audio_output_find(name); - if (ao != NULL && atoi(c) == 0) - ao->enabled = false; - - continue; -errline: - /* nonfatal */ - g_warning("invalid line in state_file: %s\n", buffer); + name = endptr + 1; + ao = audio_output_find(name); + if (ao == NULL) { + g_debug("Ignoring device state for '%s'", name); + return true; } + + ao->enabled = false; + return true; } diff --git a/src/output_state.h b/src/output_state.h index 8592574ab..b171fed18 100644 --- a/src/output_state.h +++ b/src/output_state.h @@ -25,10 +25,11 @@ #ifndef OUTPUT_STATE_H #define OUTPUT_STATE_H +#include #include -void -readAudioDevicesState(FILE *fp); +bool +readAudioDevicesState(const char *line); void saveAudioDevicesState(FILE *fp); diff --git a/src/playlist_state.c b/src/playlist_state.c index c9d3303ac..cbf77813e 100644 --- a/src/playlist_state.c +++ b/src/playlist_state.c @@ -115,8 +115,8 @@ playlist_state_load(FILE *fp, struct playlist *playlist, char *buffer) queue_increment_version(&playlist->queue); } -void -playlist_state_restore(FILE *fp, struct playlist *playlist) +bool +playlist_state_restore(const char *line, FILE *fp, struct playlist *playlist) { int current = -1; int seek_time = 0; @@ -124,21 +124,20 @@ playlist_state_restore(FILE *fp, struct playlist *playlist) char buffer[PLAYLIST_BUFFER_SIZE]; bool random_mode = false; + if (!g_str_has_prefix(line, PLAYLIST_STATE_FILE_STATE)) + return false; + + line += sizeof(PLAYLIST_STATE_FILE_STATE) - 1; + + if (strcmp(line, PLAYLIST_STATE_FILE_STATE_PLAY) == 0) + state = PLAYER_STATE_PLAY; + else if (strcmp(line, PLAYLIST_STATE_FILE_STATE_PAUSE) == 0) + state = PLAYER_STATE_PAUSE; + while (fgets(buffer, sizeof(buffer), fp)) { g_strchomp(buffer); - if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_STATE)) { - if (strcmp(&(buffer[strlen(PLAYLIST_STATE_FILE_STATE)]), - PLAYLIST_STATE_FILE_STATE_PLAY) == 0) { - state = PLAYER_STATE_PLAY; - } else - if (strcmp - (&(buffer[strlen(PLAYLIST_STATE_FILE_STATE)]), - PLAYLIST_STATE_FILE_STATE_PAUSE) - == 0) { - state = PLAYER_STATE_PAUSE; - } - } else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_TIME)) { + if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_TIME)) { seek_time = atoi(&(buffer[strlen(PLAYLIST_STATE_FILE_TIME)])); } else if (g_str_has_prefix(buffer, PLAYLIST_STATE_FILE_REPEAT)) { @@ -198,4 +197,6 @@ playlist_state_restore(FILE *fp, struct playlist *playlist) if (state == PLAYER_STATE_PAUSE) playerPause(); } + + return true; } diff --git a/src/playlist_state.h b/src/playlist_state.h index 989430264..7ed7e8c8e 100644 --- a/src/playlist_state.h +++ b/src/playlist_state.h @@ -25,6 +25,7 @@ #ifndef PLAYLIST_STATE_H #define PLAYLIST_STATE_H +#include #include struct playlist; @@ -32,7 +33,7 @@ struct playlist; void playlist_state_save(FILE *fp, const struct playlist *playlist); -void -playlist_state_restore(FILE *fp, struct playlist *playlist); +bool +playlist_state_restore(const char *line, FILE *fp, struct playlist *playlist); #endif diff --git a/src/state_file.c b/src/state_file.c index 3791c057d..18548d03c 100644 --- a/src/state_file.c +++ b/src/state_file.c @@ -63,6 +63,8 @@ static void state_file_read(void) { FILE *fp; + char line[1024]; + bool success; assert(state_file_path != NULL); @@ -75,11 +77,15 @@ state_file_read(void) return; } - read_sw_volume_state(fp); - rewind(fp); - readAudioDevicesState(fp); - rewind(fp); - playlist_state_restore(fp, &g_playlist); + while (fgets(line, sizeof(line), fp) != NULL) { + g_strchomp(line); + + success = read_sw_volume_state(line) || + readAudioDevicesState(line) || + playlist_state_restore(line, fp, &g_playlist); + if (!success) + g_warning("Unrecognized line in state file: %s", line); + } while(fclose(fp) && errno == EINTR) /* nothing */; } diff --git a/src/volume.c b/src/volume.c index 3e6079cd6..5f4a66837 100644 --- a/src/volume.c +++ b/src/volume.c @@ -100,24 +100,22 @@ bool volume_level_change(unsigned volume) return hardware_volume_change(volume); } -void read_sw_volume_state(FILE *fp) +bool +read_sw_volume_state(const char *line) { - char buf[sizeof(SW_VOLUME_STATE) + sizeof("100") - 1]; char *end = NULL; long int sv; - while (fgets(buf, sizeof(buf), fp)) { - if (!g_str_has_prefix(buf, SW_VOLUME_STATE)) - continue; + if (!g_str_has_prefix(line, SW_VOLUME_STATE)) + return false; - g_strchomp(buf); - sv = strtol(buf + strlen(SW_VOLUME_STATE), &end, 10); - if (G_LIKELY(!*end) && sv >= 0 && sv <= 100) - software_volume_change(sv); - else - g_warning("Can't parse software volume: %s\n", buf); - return; - } + line += sizeof(SW_VOLUME_STATE) - 1; + sv = strtol(line, &end, 10); + if (*end == 0 && sv >= 0 && sv <= 100) + software_volume_change(sv); + else + g_warning("Can't parse software volume: %s\n", line); + return true; } void save_sw_volume_state(FILE *fp) diff --git a/src/volume.h b/src/volume.h index 352d36168..0db231ef6 100644 --- a/src/volume.h +++ b/src/volume.h @@ -31,7 +31,8 @@ int volume_level_get(void); bool volume_level_change(unsigned volume); -void read_sw_volume_state(FILE *fp); +bool +read_sw_volume_state(const char *line); void save_sw_volume_state(FILE *fp);