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.
This commit is contained in:
		| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -25,10 +25,11 @@ | ||||
| #ifndef OUTPUT_STATE_H | ||||
| #define OUTPUT_STATE_H | ||||
|  | ||||
| #include <stdbool.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| void | ||||
| readAudioDevicesState(FILE *fp); | ||||
| bool | ||||
| readAudioDevicesState(const char *line); | ||||
|  | ||||
| void | ||||
| saveAudioDevicesState(FILE *fp); | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -25,6 +25,7 @@ | ||||
| #ifndef PLAYLIST_STATE_H | ||||
| #define PLAYLIST_STATE_H | ||||
|  | ||||
| #include <stdbool.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| 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 | ||||
|   | ||||
| @@ -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 */; | ||||
| } | ||||
|   | ||||
							
								
								
									
										24
									
								
								src/volume.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								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) | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann