From b715e522cff7109c370e66d29ba22340c9259c52 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 2 Jan 2013 19:52:57 +0100 Subject: db_save, state_file: convert to C++ --- src/DatabaseGlue.cxx | 2 +- src/DatabaseSave.cxx | 182 +++++++++++++++++++++++++++++ src/DatabaseSave.hxx | 35 ++++++ src/DirectorySave.cxx | 188 ++++++++++++++++++++++++++++++ src/DirectorySave.hxx | 36 ++++++ src/Main.cxx | 2 +- src/OutputState.cxx | 94 +++++++++++++++ src/OutputState.hxx | 44 +++++++ src/PlaylistDatabase.cxx | 82 +++++++++++++ src/PlaylistDatabase.hxx | 39 +++++++ src/PlaylistSave.hxx | 1 - src/PlaylistState.cxx | 252 ++++++++++++++++++++++++++++++++++++++++ src/PlaylistState.hxx | 52 +++++++++ src/QueueSave.cxx | 129 ++++++++++++++++++++ src/QueueSave.hxx | 43 +++++++ src/SongSave.cxx | 136 ++++++++++++++++++++++ src/SongSave.hxx | 47 ++++++++ src/StateFile.cxx | 165 ++++++++++++++++++++++++++ src/StateFile.hxx | 33 ++++++ src/TagSave.cxx | 38 ++++++ src/TagSave.hxx | 29 +++++ src/db/SimpleDatabasePlugin.cxx | 2 +- src/db_save.c | 179 ---------------------------- src/db_save.h | 36 ------ src/directory_save.c | 185 ----------------------------- src/directory_save.h | 37 ------ src/output_state.c | 91 --------------- src/output_state.h | 45 ------- src/playlist_database.c | 79 ------------- src/playlist_database.h | 40 ------- src/playlist_global.c | 1 - src/playlist_state.c | 250 --------------------------------------- src/playlist_state.h | 53 --------- src/queue_save.c | 126 -------------------- src/queue_save.h | 43 ------- src/song_save.c | 133 --------------------- src/song_save.h | 47 -------- src/state_file.c | 162 -------------------------- src/state_file.h | 33 ------ src/tag_save.c | 38 ------ src/tag_save.h | 29 ----- 41 files changed, 1627 insertions(+), 1611 deletions(-) create mode 100644 src/DatabaseSave.cxx create mode 100644 src/DatabaseSave.hxx create mode 100644 src/DirectorySave.cxx create mode 100644 src/DirectorySave.hxx create mode 100644 src/OutputState.cxx create mode 100644 src/OutputState.hxx create mode 100644 src/PlaylistDatabase.cxx create mode 100644 src/PlaylistDatabase.hxx create mode 100644 src/PlaylistState.cxx create mode 100644 src/PlaylistState.hxx create mode 100644 src/QueueSave.cxx create mode 100644 src/QueueSave.hxx create mode 100644 src/SongSave.cxx create mode 100644 src/SongSave.hxx create mode 100644 src/StateFile.cxx create mode 100644 src/StateFile.hxx create mode 100644 src/TagSave.cxx create mode 100644 src/TagSave.hxx delete mode 100644 src/db_save.c delete mode 100644 src/db_save.h delete mode 100644 src/directory_save.c delete mode 100644 src/directory_save.h delete mode 100644 src/output_state.c delete mode 100644 src/output_state.h delete mode 100644 src/playlist_database.c delete mode 100644 src/playlist_database.h delete mode 100644 src/playlist_state.c delete mode 100644 src/playlist_state.h delete mode 100644 src/queue_save.c delete mode 100644 src/queue_save.h delete mode 100644 src/song_save.c delete mode 100644 src/song_save.h delete mode 100644 src/state_file.c delete mode 100644 src/state_file.h delete mode 100644 src/tag_save.c delete mode 100644 src/tag_save.h (limited to 'src') diff --git a/src/DatabaseGlue.cxx b/src/DatabaseGlue.cxx index 03a717cb2..88791879e 100644 --- a/src/DatabaseGlue.cxx +++ b/src/DatabaseGlue.cxx @@ -20,11 +20,11 @@ #include "config.h" #include "DatabaseGlue.hxx" #include "DatabaseRegistry.hxx" +#include "DatabaseSave.hxx" extern "C" { #include "database.h" #include "db_error.h" -#include "db_save.h" #include "stats.h" #include "conf.h" #include "glib_compat.h" diff --git a/src/DatabaseSave.cxx b/src/DatabaseSave.cxx new file mode 100644 index 000000000..711d5b2f3 --- /dev/null +++ b/src/DatabaseSave.cxx @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2003-2011 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "DatabaseSave.hxx" +#include "db_lock.h" +#include "directory.h" +#include "DirectorySave.hxx" +#include "song.h" + +extern "C" { +#include "path.h" +#include "text_file.h" +#include "tag.h" +#include "tag_internal.h" +} + +#include + +#include +#include + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "database" + +#define DIRECTORY_INFO_BEGIN "info_begin" +#define DIRECTORY_INFO_END "info_end" +#define DB_FORMAT_PREFIX "format: " +#define DIRECTORY_MPD_VERSION "mpd_version: " +#define DIRECTORY_FS_CHARSET "fs_charset: " +#define DB_TAG_PREFIX "tag: " + +enum { + DB_FORMAT = 1, +}; + +G_GNUC_CONST +static GQuark +db_quark(void) +{ + return g_quark_from_static_string("database"); +} + +void +db_save_internal(FILE *fp, const struct directory *music_root) +{ + assert(music_root != NULL); + + fprintf(fp, "%s\n", DIRECTORY_INFO_BEGIN); + fprintf(fp, DB_FORMAT_PREFIX "%u\n", DB_FORMAT); + fprintf(fp, "%s%s\n", DIRECTORY_MPD_VERSION, VERSION); + fprintf(fp, "%s%s\n", DIRECTORY_FS_CHARSET, path_get_fs_charset()); + + for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) + if (!ignore_tag_items[i]) + fprintf(fp, DB_TAG_PREFIX "%s\n", tag_item_names[i]); + + fprintf(fp, "%s\n", DIRECTORY_INFO_END); + + directory_save(fp, music_root); +} + +bool +db_load_internal(FILE *fp, struct directory *music_root, GError **error) +{ + GString *buffer = g_string_sized_new(1024); + char *line; + int format = 0; + bool found_charset = false, found_version = false; + bool success; + bool tags[TAG_NUM_OF_ITEM_TYPES]; + + assert(music_root != NULL); + + /* get initial info */ + line = read_text_line(fp, buffer); + if (line == NULL || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) { + g_set_error(error, db_quark(), 0, "Database corrupted"); + g_string_free(buffer, true); + return false; + } + + memset(tags, false, sizeof(tags)); + + while ((line = read_text_line(fp, buffer)) != NULL && + strcmp(line, DIRECTORY_INFO_END) != 0) { + if (g_str_has_prefix(line, DB_FORMAT_PREFIX)) { + format = atoi(line + sizeof(DB_FORMAT_PREFIX) - 1); + } else if (g_str_has_prefix(line, DIRECTORY_MPD_VERSION)) { + if (found_version) { + g_set_error(error, db_quark(), 0, + "Duplicate version line"); + g_string_free(buffer, true); + return false; + } + + found_version = true; + } else if (g_str_has_prefix(line, DIRECTORY_FS_CHARSET)) { + const char *new_charset, *old_charset; + + if (found_charset) { + g_set_error(error, db_quark(), 0, + "Duplicate charset line"); + g_string_free(buffer, true); + return false; + } + + found_charset = true; + + new_charset = line + sizeof(DIRECTORY_FS_CHARSET) - 1; + old_charset = path_get_fs_charset(); + if (old_charset != NULL + && strcmp(new_charset, old_charset)) { + g_set_error(error, db_quark(), 0, + "Existing database has charset " + "\"%s\" instead of \"%s\"; " + "discarding database file", + new_charset, old_charset); + g_string_free(buffer, true); + return false; + } + } else if (g_str_has_prefix(line, DB_TAG_PREFIX)) { + const char *name = line + sizeof(DB_TAG_PREFIX) - 1; + enum tag_type tag = tag_name_parse(name); + if (tag == TAG_NUM_OF_ITEM_TYPES) { + g_set_error(error, db_quark(), 0, + "Unrecognized tag '%s', " + "discarding database file", + name); + return false; + } + + tags[tag] = true; + } else { + g_set_error(error, db_quark(), 0, + "Malformed line: %s", line); + g_string_free(buffer, true); + return false; + } + } + + if (format != DB_FORMAT) { + g_set_error(error, db_quark(), 0, + "Database format mismatch, " + "discarding database file"); + return false; + } + + for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) { + if (!ignore_tag_items[i] && !tags[i]) { + g_set_error(error, db_quark(), 0, + "Tag list mismatch, " + "discarding database file"); + return false; + } + } + + g_debug("reading DB"); + + db_lock(); + success = directory_load(fp, music_root, buffer, error); + db_unlock(); + g_string_free(buffer, true); + + return success; +} diff --git a/src/DatabaseSave.hxx b/src/DatabaseSave.hxx new file mode 100644 index 000000000..f96bf5e21 --- /dev/null +++ b/src/DatabaseSave.hxx @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_DATABASE_SAVE_HXX +#define MPD_DATABASE_SAVE_HXX + +#include "gerror.h" + +#include + +struct directory; + +void +db_save_internal(FILE *file, const struct directory *root); + +bool +db_load_internal(FILE *file, struct directory *root, GError **error); + +#endif diff --git a/src/DirectorySave.cxx b/src/DirectorySave.cxx new file mode 100644 index 000000000..83a1ffd5a --- /dev/null +++ b/src/DirectorySave.cxx @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "DirectorySave.hxx" +#include "directory.h" +#include "song.h" +#include "SongSave.hxx" +#include "PlaylistDatabase.hxx" + +extern "C" { +#include "text_file.h" +} + +#include +#include + +#define DIRECTORY_DIR "directory: " +#define DIRECTORY_MTIME "mtime: " +#define DIRECTORY_BEGIN "begin: " +#define DIRECTORY_END "end: " + +/** + * The quark used for GError.domain. + */ +static inline GQuark +directory_quark(void) +{ + return g_quark_from_static_string("directory"); +} + +void +directory_save(FILE *fp, const struct directory *directory) +{ + if (!directory_is_root(directory)) { + fprintf(fp, DIRECTORY_MTIME "%lu\n", + (unsigned long)directory->mtime); + + fprintf(fp, "%s%s\n", DIRECTORY_BEGIN, + directory_get_path(directory)); + } + + struct directory *cur; + directory_for_each_child(cur, directory) { + char *base = g_path_get_basename(cur->path); + + fprintf(fp, DIRECTORY_DIR "%s\n", base); + g_free(base); + + directory_save(fp, cur); + + if (ferror(fp)) + return; + } + + struct song *song; + directory_for_each_song(song, directory) + song_save(fp, song); + + playlist_vector_save(fp, &directory->playlists); + + if (!directory_is_root(directory)) + fprintf(fp, DIRECTORY_END "%s\n", + directory_get_path(directory)); +} + +static struct directory * +directory_load_subdir(FILE *fp, struct directory *parent, const char *name, + GString *buffer, GError **error_r) +{ + const char *line; + bool success; + + if (directory_get_child(parent, name) != NULL) { + g_set_error(error_r, directory_quark(), 0, + "Duplicate subdirectory '%s'", name); + return NULL; + } + + struct directory *directory = directory_new_child(parent, name); + + line = read_text_line(fp, buffer); + if (line == NULL) { + g_set_error(error_r, directory_quark(), 0, + "Unexpected end of file"); + directory_delete(directory); + return NULL; + } + + if (g_str_has_prefix(line, DIRECTORY_MTIME)) { + directory->mtime = + g_ascii_strtoull(line + sizeof(DIRECTORY_MTIME) - 1, + NULL, 10); + + line = read_text_line(fp, buffer); + if (line == NULL) { + g_set_error(error_r, directory_quark(), 0, + "Unexpected end of file"); + directory_delete(directory); + return NULL; + } + } + + if (!g_str_has_prefix(line, DIRECTORY_BEGIN)) { + g_set_error(error_r, directory_quark(), 0, + "Malformed line: %s", line); + directory_delete(directory); + return NULL; + } + + success = directory_load(fp, directory, buffer, error_r); + if (!success) { + directory_delete(directory); + return NULL; + } + + return directory; +} + +bool +directory_load(FILE *fp, struct directory *directory, + GString *buffer, GError **error) +{ + const char *line; + + while ((line = read_text_line(fp, buffer)) != NULL && + !g_str_has_prefix(line, DIRECTORY_END)) { + if (g_str_has_prefix(line, DIRECTORY_DIR)) { + struct directory *subdir = + directory_load_subdir(fp, directory, + line + sizeof(DIRECTORY_DIR) - 1, + buffer, error); + if (subdir == NULL) + return false; + } else if (g_str_has_prefix(line, SONG_BEGIN)) { + const char *name = line + sizeof(SONG_BEGIN) - 1; + struct song *song; + + if (directory_get_song(directory, name) != NULL) { + g_set_error(error, directory_quark(), 0, + "Duplicate song '%s'", name); + return false; + } + + song = song_load(fp, directory, name, + buffer, error); + if (song == NULL) + return false; + + directory_add_song(directory, song); + } else if (g_str_has_prefix(line, PLAYLIST_META_BEGIN)) { + /* duplicate the name, because + playlist_metadata_load() will overwrite the + buffer */ + char *name = g_strdup(line + sizeof(PLAYLIST_META_BEGIN) - 1); + + if (!playlist_metadata_load(fp, &directory->playlists, + name, buffer, error)) { + g_free(name); + return false; + } + + g_free(name); + } else { + g_set_error(error, directory_quark(), 0, + "Malformed line: %s", line); + return false; + } + } + + return true; +} diff --git a/src/DirectorySave.hxx b/src/DirectorySave.hxx new file mode 100644 index 000000000..18c3bf64e --- /dev/null +++ b/src/DirectorySave.hxx @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_DIRECTORY_SAVE_HXX +#define MPD_DIRECTORY_SAVE_HXX + +#include + +#include + +struct directory; + +void +directory_save(FILE *fp, const struct directory *directory); + +bool +directory_load(FILE *fp, struct directory *directory, + GString *buffer, GError **error); + +#endif diff --git a/src/Main.cxx b/src/Main.cxx index 44042d8ca..9a5fa1cd9 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -22,6 +22,7 @@ #include "PlaylistFile.hxx" #include "UpdateGlue.hxx" #include "chunk.h" +#include "StateFile.hxx" extern "C" { #include "daemon.h" @@ -51,7 +52,6 @@ extern "C" { #include "decoder_list.h" #include "input_init.h" #include "playlist_list.h" -#include "state_file.h" #include "tag.h" #include "zeroconf.h" #include "event_pipe.h" diff --git a/src/OutputState.cxx b/src/OutputState.cxx new file mode 100644 index 000000000..95aeacbca --- /dev/null +++ b/src/OutputState.cxx @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Saving and loading the audio output states to/from the state file. + * + */ + +#include "config.h" +#include "OutputState.hxx" +#include "output_internal.h" + +extern "C" { +#include "output_all.h" +} + +#include + +#include +#include +#include + +#define AUDIO_DEVICE_STATE "audio_device_state:" + +unsigned audio_output_state_version; + +void +audio_output_state_save(FILE *fp) +{ + unsigned n = audio_output_count(); + + assert(n > 0); + + for (unsigned i = 0; i < n; ++i) { + const struct audio_output *ao = audio_output_get(i); + + fprintf(fp, AUDIO_DEVICE_STATE "%d:%s\n", + ao->enabled, ao->name); + } +} + +bool +audio_output_state_read(const char *line) +{ + long value; + char *endptr; + const char *name; + struct audio_output *ao; + + if (!g_str_has_prefix(line, AUDIO_DEVICE_STATE)) + return false; + + line += sizeof(AUDIO_DEVICE_STATE) - 1; + + value = strtol(line, &endptr, 10); + if (*endptr != ':' || (value != 0 && value != 1)) + return false; + + if (value != 0) + /* state is "enabled": no-op */ + return true; + + 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; +} + +unsigned +audio_output_state_get_version(void) +{ + return audio_output_state_version; +} diff --git a/src/OutputState.hxx b/src/OutputState.hxx new file mode 100644 index 000000000..5ab765ba8 --- /dev/null +++ b/src/OutputState.hxx @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Saving and loading the audio output states to/from the state file. + * + */ + +#ifndef MPD_OUTPUT_STATE_HXX +#define MPD_OUTPUT_STATE_HXX + +#include + +bool +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/PlaylistDatabase.cxx b/src/PlaylistDatabase.cxx new file mode 100644 index 000000000..b88ebbd6b --- /dev/null +++ b/src/PlaylistDatabase.cxx @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "PlaylistDatabase.hxx" + +extern "C" { +#include "playlist_vector.h" +#include "text_file.h" +#include "string_util.h" +} + +#include +#include + +static GQuark +playlist_database_quark(void) +{ + return g_quark_from_static_string("playlist_database"); +} + +void +playlist_vector_save(FILE *fp, const struct list_head *pv) +{ + struct playlist_metadata *pm; + playlist_vector_for_each(pm, pv) + fprintf(fp, PLAYLIST_META_BEGIN "%s\n" + "mtime: %li\n" + "playlist_end\n", + pm->name, (long)pm->mtime); +} + +bool +playlist_metadata_load(FILE *fp, struct list_head *pv, const char *name, + GString *buffer, GError **error_r) +{ + struct playlist_metadata pm; + pm.mtime = 0; + + char *line, *colon; + const char *value; + + while ((line = read_text_line(fp, buffer)) != NULL && + strcmp(line, "playlist_end") != 0) { + colon = strchr(line, ':'); + if (colon == NULL || colon == line) { + g_set_error(error_r, playlist_database_quark(), 0, + "unknown line in db: %s", line); + return false; + } + + *colon++ = 0; + value = strchug_fast_c(colon); + + if (strcmp(line, "mtime") == 0) + pm.mtime = strtol(value, NULL, 10); + else { + g_set_error(error_r, playlist_database_quark(), 0, + "unknown line in db: %s", line); + return false; + } + } + + playlist_vector_update_or_add(pv, name, pm.mtime); + return true; +} diff --git a/src/PlaylistDatabase.hxx b/src/PlaylistDatabase.hxx new file mode 100644 index 000000000..0b4cd3f3a --- /dev/null +++ b/src/PlaylistDatabase.hxx @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_PLAYLIST_DATABASE_HXX +#define MPD_PLAYLIST_DATABASE_HXX + +#include "check.h" + +#include +#include + +#define PLAYLIST_META_BEGIN "playlist_begin: " + +struct list_head; + +void +playlist_vector_save(FILE *fp, const struct list_head *pv); + +bool +playlist_metadata_load(FILE *fp, struct list_head *pv, const char *name, + GString *buffer, GError **error_r); + +#endif diff --git a/src/PlaylistSave.hxx b/src/PlaylistSave.hxx index 20b2ca425..ff5f0c494 100644 --- a/src/PlaylistSave.hxx +++ b/src/PlaylistSave.hxx @@ -22,7 +22,6 @@ #include "playlist_error.h" -#include #include struct song; diff --git a/src/PlaylistState.cxx b/src/PlaylistState.cxx new file mode 100644 index 000000000..0cfd32723 --- /dev/null +++ b/src/PlaylistState.cxx @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2003-2011 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Saving and loading the playlist to/from the state file. + * + */ + +#include "config.h" +#include "PlaylistState.hxx" +#include "QueueSave.hxx" + +extern "C" { +#include "playlist.h" +#include "player_control.h" +#include "text_file.h" +#include "conf.h" +} + +#include +#include + +#define PLAYLIST_STATE_FILE_STATE "state: " +#define PLAYLIST_STATE_FILE_RANDOM "random: " +#define PLAYLIST_STATE_FILE_REPEAT "repeat: " +#define PLAYLIST_STATE_FILE_SINGLE "single: " +#define PLAYLIST_STATE_FILE_CONSUME "consume: " +#define PLAYLIST_STATE_FILE_CURRENT "current: " +#define PLAYLIST_STATE_FILE_TIME "time: " +#define PLAYLIST_STATE_FILE_CROSSFADE "crossfade: " +#define PLAYLIST_STATE_FILE_MIXRAMPDB "mixrampdb: " +#define PLAYLIST_STATE_FILE_MIXRAMPDELAY "mixrampdelay: " +#define PLAYLIST_STATE_FILE_PLAYLIST_BEGIN "playlist_begin" +#define PLAYLIST_STATE_FILE_PLAYLIST_END "playlist_end" + +#define PLAYLIST_STATE_FILE_STATE_PLAY "play" +#define PLAYLIST_STATE_FILE_STATE_PAUSE "pause" +#define PLAYLIST_STATE_FILE_STATE_STOP "stop" + +#define PLAYLIST_BUFFER_SIZE 2*MPD_PATH_MAX + +void +playlist_state_save(FILE *fp, const struct playlist *playlist, + struct player_control *pc) +{ + struct player_status player_status; + + pc_get_status(pc, &player_status); + + fputs(PLAYLIST_STATE_FILE_STATE, fp); + + if (playlist->playing) { + switch (player_status.state) { + case PLAYER_STATE_PAUSE: + fputs(PLAYLIST_STATE_FILE_STATE_PAUSE "\n", fp); + break; + default: + fputs(PLAYLIST_STATE_FILE_STATE_PLAY "\n", fp); + } + fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", + queue_order_to_position(&playlist->queue, + playlist->current)); + fprintf(fp, PLAYLIST_STATE_FILE_TIME "%i\n", + (int)player_status.elapsed_time); + } else { + fputs(PLAYLIST_STATE_FILE_STATE_STOP "\n", fp); + + if (playlist->current >= 0) + fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", + queue_order_to_position(&playlist->queue, + playlist->current)); + } + + fprintf(fp, PLAYLIST_STATE_FILE_RANDOM "%i\n", playlist->queue.random); + fprintf(fp, PLAYLIST_STATE_FILE_REPEAT "%i\n", playlist->queue.repeat); + fprintf(fp, PLAYLIST_STATE_FILE_SINGLE "%i\n", playlist->queue.single); + fprintf(fp, PLAYLIST_STATE_FILE_CONSUME "%i\n", + playlist->queue.consume); + fprintf(fp, PLAYLIST_STATE_FILE_CROSSFADE "%i\n", + (int)(pc_get_cross_fade(pc))); + fprintf(fp, PLAYLIST_STATE_FILE_MIXRAMPDB "%f\n", + pc_get_mixramp_db(pc)); + fprintf(fp, PLAYLIST_STATE_FILE_MIXRAMPDELAY "%f\n", + pc_get_mixramp_delay(pc)); + fputs(PLAYLIST_STATE_FILE_PLAYLIST_BEGIN "\n", fp); + queue_save(fp, &playlist->queue); + fputs(PLAYLIST_STATE_FILE_PLAYLIST_END "\n", fp); +} + +static void +playlist_state_load(FILE *fp, GString *buffer, struct playlist *playlist) +{ + const char *line = read_text_line(fp, buffer); + if (line == NULL) { + g_warning("No playlist in state file"); + return; + } + + while (!g_str_has_prefix(line, PLAYLIST_STATE_FILE_PLAYLIST_END)) { + queue_load_song(fp, buffer, line, &playlist->queue); + + line = read_text_line(fp, buffer); + if (line == NULL) { + g_warning("'" PLAYLIST_STATE_FILE_PLAYLIST_END + "' not found in state file"); + break; + } + } + + queue_increment_version(&playlist->queue); +} + +bool +playlist_state_restore(const char *line, FILE *fp, GString *buffer, + struct playlist *playlist, struct player_control *pc) +{ + int current = -1; + int seek_time = 0; + enum player_state state = PLAYER_STATE_STOP; + 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 ((line = read_text_line(fp, buffer)) != NULL) { + if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_TIME)) { + seek_time = + atoi(&(line[strlen(PLAYLIST_STATE_FILE_TIME)])); + } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_REPEAT)) { + if (strcmp + (&(line[strlen(PLAYLIST_STATE_FILE_REPEAT)]), + "1") == 0) { + playlist_set_repeat(playlist, pc, true); + } else + playlist_set_repeat(playlist, pc, false); + } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_SINGLE)) { + if (strcmp + (&(line[strlen(PLAYLIST_STATE_FILE_SINGLE)]), + "1") == 0) { + playlist_set_single(playlist, pc, true); + } else + playlist_set_single(playlist, pc, false); + } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_CONSUME)) { + if (strcmp + (&(line[strlen(PLAYLIST_STATE_FILE_CONSUME)]), + "1") == 0) { + playlist_set_consume(playlist, true); + } else + playlist_set_consume(playlist, false); + } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_CROSSFADE)) { + pc_set_cross_fade(pc, + atoi(line + strlen(PLAYLIST_STATE_FILE_CROSSFADE))); + } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_MIXRAMPDB)) { + pc_set_mixramp_db(pc, + atof(line + strlen(PLAYLIST_STATE_FILE_MIXRAMPDB))); + } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_MIXRAMPDELAY)) { + pc_set_mixramp_delay(pc, + atof(line + strlen(PLAYLIST_STATE_FILE_MIXRAMPDELAY))); + } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_RANDOM)) { + random_mode = + strcmp(line + strlen(PLAYLIST_STATE_FILE_RANDOM), + "1") == 0; + } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_CURRENT)) { + current = atoi(&(line + [strlen + (PLAYLIST_STATE_FILE_CURRENT)])); + } else if (g_str_has_prefix(line, + PLAYLIST_STATE_FILE_PLAYLIST_BEGIN)) { + playlist_state_load(fp, buffer, playlist); + } + } + + playlist_set_random(playlist, pc, random_mode); + + if (!queue_is_empty(&playlist->queue)) { + if (!queue_valid_position(&playlist->queue, current)) + current = 0; + + if (state == PLAYER_STATE_PLAY && + config_get_bool("restore_paused", false)) + /* the user doesn't want MPD to auto-start + playback after startup; fall back to + "pause" */ + state = PLAYER_STATE_PAUSE; + + /* enable all devices for the first time; this must be + called here, after the audio output states were + restored, before playback begins */ + if (state != PLAYER_STATE_STOP) + pc_update_audio(pc); + + if (state == PLAYER_STATE_STOP /* && config_option */) + playlist->current = current; + else if (seek_time == 0) + playlist_play(playlist, pc, current); + else + playlist_seek_song(playlist, pc, current, seek_time); + + if (state == PLAYER_STATE_PAUSE) + pc_pause(pc); + } + + return true; +} + +unsigned +playlist_state_get_hash(const struct playlist *playlist, + struct player_control *pc) +{ + struct player_status player_status; + + pc_get_status(pc, &player_status); + + return playlist->queue.version ^ + (player_status.state != PLAYER_STATE_STOP + ? ((int)player_status.elapsed_time << 8) + : 0) ^ + (playlist->current >= 0 + ? (queue_order_to_position(&playlist->queue, + playlist->current) << 16) + : 0) ^ + ((int)pc_get_cross_fade(pc) << 20) ^ + (player_status.state << 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/PlaylistState.hxx b/src/PlaylistState.hxx new file mode 100644 index 000000000..d38fe9d12 --- /dev/null +++ b/src/PlaylistState.hxx @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Saving and loading the playlist to/from the state file. + * + */ + +#ifndef MPD_PLAYLIST_STATE_HXX +#define MPD_PLAYLIST_STATE_HXX + +#include +#include + +struct playlist; +struct player_control; + +void +playlist_state_save(FILE *fp, const struct playlist *playlist, + struct player_control *pc); + +bool +playlist_state_restore(const char *line, FILE *fp, GString *buffer, + struct playlist *playlist, struct player_control *pc); + +/** + * 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, + struct player_control *pc); + +#endif diff --git a/src/QueueSave.cxx b/src/QueueSave.cxx new file mode 100644 index 000000000..96713c700 --- /dev/null +++ b/src/QueueSave.cxx @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "QueueSave.hxx" +#include "song.h" +#include "SongSave.hxx" + +extern "C" { +#include "queue.h" +#include "uri.h" +#include "database.h" +#include "text_file.h" +} + +#include + +#define PRIO_LABEL "Prio: " + +static void +queue_save_database_song(FILE *fp, int idx, const struct song *song) +{ + char *uri = song_get_uri(song); + + fprintf(fp, "%i:%s\n", idx, uri); + g_free(uri); +} + +static void +queue_save_full_song(FILE *fp, const struct song *song) +{ + song_save(fp, song); +} + +static void +queue_save_song(FILE *fp, int idx, const struct song *song) +{ + if (song_in_database(song)) + queue_save_database_song(fp, idx, song); + else + queue_save_full_song(fp, song); +} + +void +queue_save(FILE *fp, const struct queue *queue) +{ + for (unsigned i = 0; i < queue_length(queue); i++) { + uint8_t prio = queue_get_priority_at_position(queue, i); + if (prio != 0) + fprintf(fp, PRIO_LABEL "%u\n", prio); + + queue_save_song(fp, i, queue_get(queue, i)); + } +} + +static struct song * +get_song(const char *uri) +{ + return uri_has_scheme(uri) + ? song_remote_new(uri) + : db_get_song(uri); +} + +void +queue_load_song(FILE *fp, GString *buffer, const char *line, + struct queue *queue) +{ + struct song *song; + + if (queue_is_full(queue)) + return; + + uint8_t priority = 0; + if (g_str_has_prefix(line, PRIO_LABEL)) { + priority = strtoul(line + sizeof(PRIO_LABEL) - 1, NULL, 10); + + line = read_text_line(fp, buffer); + if (line == NULL) + return; + } + + if (g_str_has_prefix(line, SONG_BEGIN)) { + const char *uri = line + sizeof(SONG_BEGIN) - 1; + if (!uri_has_scheme(uri) && !g_path_is_absolute(uri)) + return; + + GError *error = NULL; + song = song_load(fp, NULL, uri, buffer, &error); + if (song == NULL) { + g_warning("%s", error->message); + g_error_free(error); + return; + } + } else { + char *endptr; + long ret = strtol(line, &endptr, 10); + if (ret < 0 || *endptr != ':' || endptr[1] == 0) { + g_warning("Malformed playlist line in state file"); + return; + } + + line = endptr + 1; + + song = get_song(line); + if (song == NULL) + return; + } + + queue_append(queue, song, priority); + + if (song_in_database(song)) + db_return_song(song); +} diff --git a/src/QueueSave.hxx b/src/QueueSave.hxx new file mode 100644 index 000000000..d6b09329b --- /dev/null +++ b/src/QueueSave.hxx @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * This library saves the queue into the state file, and also loads it + * back into memory. + */ + +#ifndef MPD_QUEUE_SAVE_HXX +#define MPD_QUEUE_SAVE_HXX + +#include +#include + +struct queue; + +void +queue_save(FILE *fp, const struct queue *queue); + +/** + * Loads one song from the state file and appends it to the queue. + */ +void +queue_load_song(FILE *fp, GString *buffer, const char *line, + struct queue *queue); + +#endif diff --git a/src/SongSave.cxx b/src/SongSave.cxx new file mode 100644 index 000000000..21d073b86 --- /dev/null +++ b/src/SongSave.cxx @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "SongSave.hxx" +#include "song.h" +#include "TagSave.hxx" +#include "directory.h" + +extern "C" { +#include "tag.h" +#include "text_file.h" +#include "string_util.h" +} + +#include + +#include + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "song" + +#define SONG_MTIME "mtime" +#define SONG_END "song_end" + +static GQuark +song_save_quark(void) +{ + return g_quark_from_static_string("song_save"); +} + +void +song_save(FILE *fp, const struct song *song) +{ + fprintf(fp, SONG_BEGIN "%s\n", song->uri); + + if (song->end_ms > 0) + fprintf(fp, "Range: %u-%u\n", song->start_ms, song->end_ms); + else if (song->start_ms > 0) + fprintf(fp, "Range: %u-\n", song->start_ms); + + if (song->tag != NULL) + tag_save(fp, song->tag); + + fprintf(fp, SONG_MTIME ": %li\n", (long)song->mtime); + fprintf(fp, SONG_END "\n"); +} + +struct song * +song_load(FILE *fp, struct directory *parent, const char *uri, + GString *buffer, GError **error_r) +{ + struct song *song = parent != NULL + ? song_file_new(uri, parent) + : song_remote_new(uri); + char *line, *colon; + enum tag_type type; + const char *value; + + while ((line = read_text_line(fp, buffer)) != NULL && + strcmp(line, SONG_END) != 0) { + colon = strchr(line, ':'); + if (colon == NULL || colon == line) { + if (song->tag != NULL) + tag_end_add(song->tag); + song_free(song); + + g_set_error(error_r, song_save_quark(), 0, + "unknown line in db: %s", line); + return NULL; + } + + *colon++ = 0; + value = strchug_fast_c(colon); + + if ((type = tag_name_parse(line)) != TAG_NUM_OF_ITEM_TYPES) { + if (!song->tag) { + song->tag = tag_new(); + tag_begin_add(song->tag); + } + + tag_add_item(song->tag, type, value); + } else if (strcmp(line, "Time") == 0) { + if (!song->tag) { + song->tag = tag_new(); + tag_begin_add(song->tag); + } + + song->tag->time = atoi(value); + } else if (strcmp(line, "Playlist") == 0) { + if (!song->tag) { + song->tag = tag_new(); + tag_begin_add(song->tag); + } + + song->tag->has_playlist = strcmp(value, "yes") == 0; + } else if (strcmp(line, SONG_MTIME) == 0) { + song->mtime = atoi(value); + } else if (strcmp(line, "Range") == 0) { + char *endptr; + + song->start_ms = strtoul(value, &endptr, 10); + if (*endptr == '-') + song->end_ms = strtoul(endptr + 1, NULL, 10); + } else { + if (song->tag != NULL) + tag_end_add(song->tag); + song_free(song); + + g_set_error(error_r, song_save_quark(), 0, + "unknown line in db: %s", line); + return NULL; + } + } + + if (song->tag != NULL) + tag_end_add(song->tag); + + return song; +} diff --git a/src/SongSave.hxx b/src/SongSave.hxx new file mode 100644 index 000000000..d8805acd7 --- /dev/null +++ b/src/SongSave.hxx @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_SONG_SAVE_HXX +#define MPD_SONG_SAVE_HXX + +#include + +#include + +#define SONG_BEGIN "song_begin: " + +struct song; +struct directory; + +void +song_save(FILE *fp, const struct song *song); + +/** + * Loads a song from the input file. Reading stops after the + * "song_end" line. + * + * @param error_r location to store the error occurring, or NULL to + * ignore errors + * @return true on success, false on error + */ +struct song * +song_load(FILE *fp, struct directory *parent, const char *uri, + GString *buffer, GError **error_r); + +#endif diff --git a/src/StateFile.cxx b/src/StateFile.cxx new file mode 100644 index 000000000..6635d9f9d --- /dev/null +++ b/src/StateFile.cxx @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "StateFile.hxx" +#include "OutputState.hxx" +#include "playlist.h" +#include "PlaylistState.hxx" + +extern "C" { +#include "volume.h" +#include "text_file.h" +} + +#include +#include +#include +#include + +#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(struct player_control *pc) +{ + FILE *fp; + + assert(state_file_path != NULL); + + g_debug("Saving state file %s", state_file_path); + + fp = fopen(state_file_path, "w"); + if (G_UNLIKELY(!fp)) { + g_warning("failed to create %s: %s", + state_file_path, g_strerror(errno)); + return; + } + + save_sw_volume_state(fp); + audio_output_state_save(fp); + playlist_state_save(fp, &g_playlist, pc); + + fclose(fp); + + 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, pc); +} + +static void +state_file_read(struct player_control *pc) +{ + FILE *fp; + bool success; + + assert(state_file_path != NULL); + + g_debug("Loading state file %s", state_file_path); + + fp = fopen(state_file_path, "r"); + if (G_UNLIKELY(!fp)) { + g_warning("failed to open %s: %s", + state_file_path, g_strerror(errno)); + return; + } + + GString *buffer = g_string_sized_new(1024); + const char *line; + while ((line = read_text_line(fp, buffer)) != NULL) { + success = read_sw_volume_state(line) || + audio_output_state_read(line) || + playlist_state_restore(line, fp, buffer, + &g_playlist, pc); + if (!success) + g_warning("Unrecognized line in state file: %s", line); + } + + fclose(fp); + + 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, pc); + + + g_string_free(buffer, true); +} + +/** + * 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) +{ + struct player_control *pc = (struct player_control *)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, pc)) + /* nothing has changed - don't save the state file, + don't spin up the hard disk */ + return true; + + state_file_write(pc); + return true; +} + +void +state_file_init(const char *path, struct player_control *pc) +{ + assert(state_file_path == NULL); + + if (path == NULL) + return; + + state_file_path = g_strdup(path); + state_file_read(pc); + + save_state_source_id = g_timeout_add_seconds(5 * 60, + timer_save_state_file, + pc); +} + +void +state_file_finish(struct player_control *pc) +{ + 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); + + state_file_write(pc); + + g_free(state_file_path); +} diff --git a/src/StateFile.hxx b/src/StateFile.hxx new file mode 100644 index 000000000..77629aba9 --- /dev/null +++ b/src/StateFile.hxx @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_STATE_FILE_HXX +#define MPD_STATE_FILE_HXX + +struct player_control; + +void +state_file_init(const char *path, struct player_control *pc); + +void +state_file_finish(struct player_control *pc); + +void write_state_file(void); + +#endif /* STATE_FILE_H */ diff --git a/src/TagSave.cxx b/src/TagSave.cxx new file mode 100644 index 000000000..639dc2d97 --- /dev/null +++ b/src/TagSave.cxx @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "TagSave.hxx" +#include "tag.h" +#include "tag_internal.h" +#include "song.h" + +void tag_save(FILE *file, const struct tag *tag) +{ + if (tag->time >= 0) + fprintf(file, SONG_TIME "%i\n", tag->time); + + if (tag->has_playlist) + fprintf(file, "Playlist: yes\n"); + + for (unsigned i = 0; i < tag->num_items; i++) + fprintf(file, "%s: %s\n", + tag_item_names[tag->items[i]->type], + tag->items[i]->value); +} diff --git a/src/TagSave.hxx b/src/TagSave.hxx new file mode 100644 index 000000000..a7ccfa613 --- /dev/null +++ b/src/TagSave.hxx @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_TAG_SAVE_HXX +#define MPD_TAG_SAVE_HXX + +#include + +struct tag; + +void tag_save(FILE *file, const struct tag *tag); + +#endif diff --git a/src/db/SimpleDatabasePlugin.cxx b/src/db/SimpleDatabasePlugin.cxx index d83c1ca73..4b92da6cf 100644 --- a/src/db/SimpleDatabasePlugin.cxx +++ b/src/db/SimpleDatabasePlugin.cxx @@ -22,10 +22,10 @@ #include "DatabaseSelection.hxx" #include "DatabaseHelpers.hxx" #include "SongFilter.hxx" +#include "DatabaseSave.hxx" extern "C" { #include "db_error.h" -#include "db_save.h" #include "db_lock.h" #include "conf.h" } diff --git a/src/db_save.c b/src/db_save.c deleted file mode 100644 index 4af9d58b8..000000000 --- a/src/db_save.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "db_save.h" -#include "db_lock.h" -#include "directory.h" -#include "directory_save.h" -#include "song.h" -#include "path.h" -#include "text_file.h" -#include "tag.h" -#include "tag_internal.h" - -#include - -#include -#include - -#undef G_LOG_DOMAIN -#define G_LOG_DOMAIN "database" - -#define DIRECTORY_INFO_BEGIN "info_begin" -#define DIRECTORY_INFO_END "info_end" -#define DB_FORMAT_PREFIX "format: " -#define DIRECTORY_MPD_VERSION "mpd_version: " -#define DIRECTORY_FS_CHARSET "fs_charset: " -#define DB_TAG_PREFIX "tag: " - -enum { - DB_FORMAT = 1, -}; - -G_GNUC_CONST -static GQuark -db_quark(void) -{ - return g_quark_from_static_string("database"); -} - -void -db_save_internal(FILE *fp, const struct directory *music_root) -{ - assert(music_root != NULL); - - fprintf(fp, "%s\n", DIRECTORY_INFO_BEGIN); - fprintf(fp, DB_FORMAT_PREFIX "%u\n", DB_FORMAT); - fprintf(fp, "%s%s\n", DIRECTORY_MPD_VERSION, VERSION); - fprintf(fp, "%s%s\n", DIRECTORY_FS_CHARSET, path_get_fs_charset()); - - for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) - if (!ignore_tag_items[i]) - fprintf(fp, DB_TAG_PREFIX "%s\n", tag_item_names[i]); - - fprintf(fp, "%s\n", DIRECTORY_INFO_END); - - directory_save(fp, music_root); -} - -bool -db_load_internal(FILE *fp, struct directory *music_root, GError **error) -{ - GString *buffer = g_string_sized_new(1024); - char *line; - int format = 0; - bool found_charset = false, found_version = false; - bool success; - bool tags[TAG_NUM_OF_ITEM_TYPES]; - - assert(music_root != NULL); - - /* get initial info */ - line = read_text_line(fp, buffer); - if (line == NULL || strcmp(DIRECTORY_INFO_BEGIN, line) != 0) { - g_set_error(error, db_quark(), 0, "Database corrupted"); - g_string_free(buffer, true); - return false; - } - - memset(tags, false, sizeof(tags)); - - while ((line = read_text_line(fp, buffer)) != NULL && - strcmp(line, DIRECTORY_INFO_END) != 0) { - if (g_str_has_prefix(line, DB_FORMAT_PREFIX)) { - format = atoi(line + sizeof(DB_FORMAT_PREFIX) - 1); - } else if (g_str_has_prefix(line, DIRECTORY_MPD_VERSION)) { - if (found_version) { - g_set_error(error, db_quark(), 0, - "Duplicate version line"); - g_string_free(buffer, true); - return false; - } - - found_version = true; - } else if (g_str_has_prefix(line, DIRECTORY_FS_CHARSET)) { - const char *new_charset, *old_charset; - - if (found_charset) { - g_set_error(error, db_quark(), 0, - "Duplicate charset line"); - g_string_free(buffer, true); - return false; - } - - found_charset = true; - - new_charset = line + sizeof(DIRECTORY_FS_CHARSET) - 1; - old_charset = path_get_fs_charset(); - if (old_charset != NULL - && strcmp(new_charset, old_charset)) { - g_set_error(error, db_quark(), 0, - "Existing database has charset " - "\"%s\" instead of \"%s\"; " - "discarding database file", - new_charset, old_charset); - g_string_free(buffer, true); - return false; - } - } else if (g_str_has_prefix(line, DB_TAG_PREFIX)) { - const char *name = line + sizeof(DB_TAG_PREFIX) - 1; - enum tag_type tag = tag_name_parse(name); - if (tag == TAG_NUM_OF_ITEM_TYPES) { - g_set_error(error, db_quark(), 0, - "Unrecognized tag '%s', " - "discarding database file", - name); - return false; - } - - tags[tag] = true; - } else { - g_set_error(error, db_quark(), 0, - "Malformed line: %s", line); - g_string_free(buffer, true); - return false; - } - } - - if (format != DB_FORMAT) { - g_set_error(error, db_quark(), 0, - "Database format mismatch, " - "discarding database file"); - return false; - } - - for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) { - if (!ignore_tag_items[i] && !tags[i]) { - g_set_error(error, db_quark(), 0, - "Tag list mismatch, " - "discarding database file"); - return false; - } - } - - g_debug("reading DB"); - - db_lock(); - success = directory_load(fp, music_root, buffer, error); - db_unlock(); - g_string_free(buffer, true); - - return success; -} diff --git a/src/db_save.h b/src/db_save.h deleted file mode 100644 index d232d7331..000000000 --- a/src/db_save.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_DB_SAVE_H -#define MPD_DB_SAVE_H - -#include "gerror.h" - -#include -#include - -struct directory; - -void -db_save_internal(FILE *file, const struct directory *root); - -bool -db_load_internal(FILE *file, struct directory *root, GError **error); - -#endif diff --git a/src/directory_save.c b/src/directory_save.c deleted file mode 100644 index de1df050a..000000000 --- a/src/directory_save.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "directory_save.h" -#include "directory.h" -#include "song.h" -#include "text_file.h" -#include "song_save.h" -#include "playlist_database.h" - -#include -#include - -#define DIRECTORY_DIR "directory: " -#define DIRECTORY_MTIME "mtime: " -#define DIRECTORY_BEGIN "begin: " -#define DIRECTORY_END "end: " - -/** - * The quark used for GError.domain. - */ -static inline GQuark -directory_quark(void) -{ - return g_quark_from_static_string("directory"); -} - -void -directory_save(FILE *fp, const struct directory *directory) -{ - if (!directory_is_root(directory)) { - fprintf(fp, DIRECTORY_MTIME "%lu\n", - (unsigned long)directory->mtime); - - fprintf(fp, "%s%s\n", DIRECTORY_BEGIN, - directory_get_path(directory)); - } - - struct directory *cur; - directory_for_each_child(cur, directory) { - char *base = g_path_get_basename(cur->path); - - fprintf(fp, DIRECTORY_DIR "%s\n", base); - g_free(base); - - directory_save(fp, cur); - - if (ferror(fp)) - return; - } - - struct song *song; - directory_for_each_song(song, directory) - song_save(fp, song); - - playlist_vector_save(fp, &directory->playlists); - - if (!directory_is_root(directory)) - fprintf(fp, DIRECTORY_END "%s\n", - directory_get_path(directory)); -} - -static struct directory * -directory_load_subdir(FILE *fp, struct directory *parent, const char *name, - GString *buffer, GError **error_r) -{ - const char *line; - bool success; - - if (directory_get_child(parent, name) != NULL) { - g_set_error(error_r, directory_quark(), 0, - "Duplicate subdirectory '%s'", name); - return NULL; - } - - struct directory *directory = directory_new_child(parent, name); - - line = read_text_line(fp, buffer); - if (line == NULL) { - g_set_error(error_r, directory_quark(), 0, - "Unexpected end of file"); - directory_delete(directory); - return NULL; - } - - if (g_str_has_prefix(line, DIRECTORY_MTIME)) { - directory->mtime = - g_ascii_strtoull(line + sizeof(DIRECTORY_MTIME) - 1, - NULL, 10); - - line = read_text_line(fp, buffer); - if (line == NULL) { - g_set_error(error_r, directory_quark(), 0, - "Unexpected end of file"); - directory_delete(directory); - return NULL; - } - } - - if (!g_str_has_prefix(line, DIRECTORY_BEGIN)) { - g_set_error(error_r, directory_quark(), 0, - "Malformed line: %s", line); - directory_delete(directory); - return NULL; - } - - success = directory_load(fp, directory, buffer, error_r); - if (!success) { - directory_delete(directory); - return NULL; - } - - return directory; -} - -bool -directory_load(FILE *fp, struct directory *directory, - GString *buffer, GError **error) -{ - const char *line; - - while ((line = read_text_line(fp, buffer)) != NULL && - !g_str_has_prefix(line, DIRECTORY_END)) { - if (g_str_has_prefix(line, DIRECTORY_DIR)) { - struct directory *subdir = - directory_load_subdir(fp, directory, - line + sizeof(DIRECTORY_DIR) - 1, - buffer, error); - if (subdir == NULL) - return false; - } else if (g_str_has_prefix(line, SONG_BEGIN)) { - const char *name = line + sizeof(SONG_BEGIN) - 1; - struct song *song; - - if (directory_get_song(directory, name) != NULL) { - g_set_error(error, directory_quark(), 0, - "Duplicate song '%s'", name); - return NULL; - } - - song = song_load(fp, directory, name, - buffer, error); - if (song == NULL) - return false; - - directory_add_song(directory, song); - } else if (g_str_has_prefix(line, PLAYLIST_META_BEGIN)) { - /* duplicate the name, because - playlist_metadata_load() will overwrite the - buffer */ - char *name = g_strdup(line + sizeof(PLAYLIST_META_BEGIN) - 1); - - if (!playlist_metadata_load(fp, &directory->playlists, - name, buffer, error)) { - g_free(name); - return false; - } - - g_free(name); - } else { - g_set_error(error, directory_quark(), 0, - "Malformed line: %s", line); - return false; - } - } - - return true; -} diff --git a/src/directory_save.h b/src/directory_save.h deleted file mode 100644 index 2d0056830..000000000 --- a/src/directory_save.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_DIRECTORY_SAVE_H -#define MPD_DIRECTORY_SAVE_H - -#include - -#include -#include - -struct directory; - -void -directory_save(FILE *fp, const struct directory *directory); - -bool -directory_load(FILE *fp, struct directory *directory, - GString *buffer, GError **error); - -#endif diff --git a/src/output_state.c b/src/output_state.c deleted file mode 100644 index 7bcafb36b..000000000 --- a/src/output_state.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* - * Saving and loading the audio output states to/from the state file. - * - */ - -#include "config.h" -#include "output_state.h" -#include "output_internal.h" -#include "output_all.h" - -#include - -#include -#include -#include - -#define AUDIO_DEVICE_STATE "audio_device_state:" - -unsigned audio_output_state_version; - -void -audio_output_state_save(FILE *fp) -{ - unsigned n = audio_output_count(); - - assert(n > 0); - - for (unsigned i = 0; i < n; ++i) { - const struct audio_output *ao = audio_output_get(i); - - fprintf(fp, AUDIO_DEVICE_STATE "%d:%s\n", - ao->enabled, ao->name); - } -} - -bool -audio_output_state_read(const char *line) -{ - long value; - char *endptr; - const char *name; - struct audio_output *ao; - - if (!g_str_has_prefix(line, AUDIO_DEVICE_STATE)) - return false; - - line += sizeof(AUDIO_DEVICE_STATE) - 1; - - value = strtol(line, &endptr, 10); - if (*endptr != ':' || (value != 0 && value != 1)) - return false; - - if (value != 0) - /* state is "enabled": no-op */ - return true; - - 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; -} - -unsigned -audio_output_state_get_version(void) -{ - return audio_output_state_version; -} diff --git a/src/output_state.h b/src/output_state.h deleted file mode 100644 index 320a3520a..000000000 --- a/src/output_state.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* - * Saving and loading the audio output states to/from the state file. - * - */ - -#ifndef OUTPUT_STATE_H -#define OUTPUT_STATE_H - -#include -#include - -bool -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_database.c b/src/playlist_database.c deleted file mode 100644 index 6b9d87155..000000000 --- a/src/playlist_database.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "playlist_database.h" -#include "playlist_vector.h" -#include "text_file.h" -#include "string_util.h" - -#include -#include - -static GQuark -playlist_database_quark(void) -{ - return g_quark_from_static_string("playlist_database"); -} - -void -playlist_vector_save(FILE *fp, const struct list_head *pv) -{ - struct playlist_metadata *pm; - playlist_vector_for_each(pm, pv) - fprintf(fp, PLAYLIST_META_BEGIN "%s\n" - "mtime: %li\n" - "playlist_end\n", - pm->name, (long)pm->mtime); -} - -bool -playlist_metadata_load(FILE *fp, struct list_head *pv, const char *name, - GString *buffer, GError **error_r) -{ - struct playlist_metadata pm = { - .mtime = 0, - }; - char *line, *colon; - const char *value; - - while ((line = read_text_line(fp, buffer)) != NULL && - strcmp(line, "playlist_end") != 0) { - colon = strchr(line, ':'); - if (colon == NULL || colon == line) { - g_set_error(error_r, playlist_database_quark(), 0, - "unknown line in db: %s", line); - return false; - } - - *colon++ = 0; - value = strchug_fast_c(colon); - - if (strcmp(line, "mtime") == 0) - pm.mtime = strtol(value, NULL, 10); - else { - g_set_error(error_r, playlist_database_quark(), 0, - "unknown line in db: %s", line); - return false; - } - } - - playlist_vector_update_or_add(pv, name, pm.mtime); - return true; -} diff --git a/src/playlist_database.h b/src/playlist_database.h deleted file mode 100644 index 3238fa06b..000000000 --- a/src/playlist_database.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_PLAYLIST_DATABASE_H -#define MPD_PLAYLIST_DATABASE_H - -#include "check.h" - -#include -#include -#include - -#define PLAYLIST_META_BEGIN "playlist_begin: " - -struct list_head; - -void -playlist_vector_save(FILE *fp, const struct list_head *pv); - -bool -playlist_metadata_load(FILE *fp, struct list_head *pv, const char *name, - GString *buffer, GError **error_r); - -#endif diff --git a/src/playlist_global.c b/src/playlist_global.c index 43bf26755..e66febce0 100644 --- a/src/playlist_global.c +++ b/src/playlist_global.c @@ -24,7 +24,6 @@ #include "config.h" #include "playlist.h" -#include "playlist_state.h" #include "event_pipe.h" #include "Main.hxx" diff --git a/src/playlist_state.c b/src/playlist_state.c deleted file mode 100644 index 4aa2c2c92..000000000 --- a/src/playlist_state.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* - * Saving and loading the playlist to/from the state file. - * - */ - -#include "config.h" -#include "playlist_state.h" -#include "playlist.h" -#include "player_control.h" -#include "queue_save.h" -#include "path.h" -#include "text_file.h" -#include "conf.h" - -#include -#include - -#define PLAYLIST_STATE_FILE_STATE "state: " -#define PLAYLIST_STATE_FILE_RANDOM "random: " -#define PLAYLIST_STATE_FILE_REPEAT "repeat: " -#define PLAYLIST_STATE_FILE_SINGLE "single: " -#define PLAYLIST_STATE_FILE_CONSUME "consume: " -#define PLAYLIST_STATE_FILE_CURRENT "current: " -#define PLAYLIST_STATE_FILE_TIME "time: " -#define PLAYLIST_STATE_FILE_CROSSFADE "crossfade: " -#define PLAYLIST_STATE_FILE_MIXRAMPDB "mixrampdb: " -#define PLAYLIST_STATE_FILE_MIXRAMPDELAY "mixrampdelay: " -#define PLAYLIST_STATE_FILE_PLAYLIST_BEGIN "playlist_begin" -#define PLAYLIST_STATE_FILE_PLAYLIST_END "playlist_end" - -#define PLAYLIST_STATE_FILE_STATE_PLAY "play" -#define PLAYLIST_STATE_FILE_STATE_PAUSE "pause" -#define PLAYLIST_STATE_FILE_STATE_STOP "stop" - -#define PLAYLIST_BUFFER_SIZE 2*MPD_PATH_MAX - -void -playlist_state_save(FILE *fp, const struct playlist *playlist, - struct player_control *pc) -{ - struct player_status player_status; - - pc_get_status(pc, &player_status); - - fputs(PLAYLIST_STATE_FILE_STATE, fp); - - if (playlist->playing) { - switch (player_status.state) { - case PLAYER_STATE_PAUSE: - fputs(PLAYLIST_STATE_FILE_STATE_PAUSE "\n", fp); - break; - default: - fputs(PLAYLIST_STATE_FILE_STATE_PLAY "\n", fp); - } - fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", - queue_order_to_position(&playlist->queue, - playlist->current)); - fprintf(fp, PLAYLIST_STATE_FILE_TIME "%i\n", - (int)player_status.elapsed_time); - } else { - fputs(PLAYLIST_STATE_FILE_STATE_STOP "\n", fp); - - if (playlist->current >= 0) - fprintf(fp, PLAYLIST_STATE_FILE_CURRENT "%i\n", - queue_order_to_position(&playlist->queue, - playlist->current)); - } - - fprintf(fp, PLAYLIST_STATE_FILE_RANDOM "%i\n", playlist->queue.random); - fprintf(fp, PLAYLIST_STATE_FILE_REPEAT "%i\n", playlist->queue.repeat); - fprintf(fp, PLAYLIST_STATE_FILE_SINGLE "%i\n", playlist->queue.single); - fprintf(fp, PLAYLIST_STATE_FILE_CONSUME "%i\n", - playlist->queue.consume); - fprintf(fp, PLAYLIST_STATE_FILE_CROSSFADE "%i\n", - (int)(pc_get_cross_fade(pc))); - fprintf(fp, PLAYLIST_STATE_FILE_MIXRAMPDB "%f\n", - pc_get_mixramp_db(pc)); - fprintf(fp, PLAYLIST_STATE_FILE_MIXRAMPDELAY "%f\n", - pc_get_mixramp_delay(pc)); - fputs(PLAYLIST_STATE_FILE_PLAYLIST_BEGIN "\n", fp); - queue_save(fp, &playlist->queue); - fputs(PLAYLIST_STATE_FILE_PLAYLIST_END "\n", fp); -} - -static void -playlist_state_load(FILE *fp, GString *buffer, struct playlist *playlist) -{ - const char *line = read_text_line(fp, buffer); - if (line == NULL) { - g_warning("No playlist in state file"); - return; - } - - while (!g_str_has_prefix(line, PLAYLIST_STATE_FILE_PLAYLIST_END)) { - queue_load_song(fp, buffer, line, &playlist->queue); - - line = read_text_line(fp, buffer); - if (line == NULL) { - g_warning("'" PLAYLIST_STATE_FILE_PLAYLIST_END - "' not found in state file"); - break; - } - } - - queue_increment_version(&playlist->queue); -} - -bool -playlist_state_restore(const char *line, FILE *fp, GString *buffer, - struct playlist *playlist, struct player_control *pc) -{ - int current = -1; - int seek_time = 0; - enum player_state state = PLAYER_STATE_STOP; - 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 ((line = read_text_line(fp, buffer)) != NULL) { - if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_TIME)) { - seek_time = - atoi(&(line[strlen(PLAYLIST_STATE_FILE_TIME)])); - } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_REPEAT)) { - if (strcmp - (&(line[strlen(PLAYLIST_STATE_FILE_REPEAT)]), - "1") == 0) { - playlist_set_repeat(playlist, pc, true); - } else - playlist_set_repeat(playlist, pc, false); - } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_SINGLE)) { - if (strcmp - (&(line[strlen(PLAYLIST_STATE_FILE_SINGLE)]), - "1") == 0) { - playlist_set_single(playlist, pc, true); - } else - playlist_set_single(playlist, pc, false); - } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_CONSUME)) { - if (strcmp - (&(line[strlen(PLAYLIST_STATE_FILE_CONSUME)]), - "1") == 0) { - playlist_set_consume(playlist, true); - } else - playlist_set_consume(playlist, false); - } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_CROSSFADE)) { - pc_set_cross_fade(pc, - atoi(line + strlen(PLAYLIST_STATE_FILE_CROSSFADE))); - } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_MIXRAMPDB)) { - pc_set_mixramp_db(pc, - atof(line + strlen(PLAYLIST_STATE_FILE_MIXRAMPDB))); - } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_MIXRAMPDELAY)) { - pc_set_mixramp_delay(pc, - atof(line + strlen(PLAYLIST_STATE_FILE_MIXRAMPDELAY))); - } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_RANDOM)) { - random_mode = - strcmp(line + strlen(PLAYLIST_STATE_FILE_RANDOM), - "1") == 0; - } else if (g_str_has_prefix(line, PLAYLIST_STATE_FILE_CURRENT)) { - current = atoi(&(line - [strlen - (PLAYLIST_STATE_FILE_CURRENT)])); - } else if (g_str_has_prefix(line, - PLAYLIST_STATE_FILE_PLAYLIST_BEGIN)) { - playlist_state_load(fp, buffer, playlist); - } - } - - playlist_set_random(playlist, pc, random_mode); - - if (!queue_is_empty(&playlist->queue)) { - if (!queue_valid_position(&playlist->queue, current)) - current = 0; - - if (state == PLAYER_STATE_PLAY && - config_get_bool("restore_paused", false)) - /* the user doesn't want MPD to auto-start - playback after startup; fall back to - "pause" */ - state = PLAYER_STATE_PAUSE; - - /* enable all devices for the first time; this must be - called here, after the audio output states were - restored, before playback begins */ - if (state != PLAYER_STATE_STOP) - pc_update_audio(pc); - - if (state == PLAYER_STATE_STOP /* && config_option */) - playlist->current = current; - else if (seek_time == 0) - playlist_play(playlist, pc, current); - else - playlist_seek_song(playlist, pc, current, seek_time); - - if (state == PLAYER_STATE_PAUSE) - pc_pause(pc); - } - - return true; -} - -unsigned -playlist_state_get_hash(const struct playlist *playlist, - struct player_control *pc) -{ - struct player_status player_status; - - pc_get_status(pc, &player_status); - - return playlist->queue.version ^ - (player_status.state != PLAYER_STATE_STOP - ? ((int)player_status.elapsed_time << 8) - : 0) ^ - (playlist->current >= 0 - ? (queue_order_to_position(&playlist->queue, - playlist->current) << 16) - : 0) ^ - ((int)pc_get_cross_fade(pc) << 20) ^ - (player_status.state << 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 deleted file mode 100644 index f67d01d2c..000000000 --- a/src/playlist_state.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* - * Saving and loading the playlist to/from the state file. - * - */ - -#ifndef PLAYLIST_STATE_H -#define PLAYLIST_STATE_H - -#include -#include -#include - -struct playlist; -struct player_control; - -void -playlist_state_save(FILE *fp, const struct playlist *playlist, - struct player_control *pc); - -bool -playlist_state_restore(const char *line, FILE *fp, GString *buffer, - struct playlist *playlist, struct player_control *pc); - -/** - * 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, - struct player_control *pc); - -#endif diff --git a/src/queue_save.c b/src/queue_save.c deleted file mode 100644 index 00b5ecbb1..000000000 --- a/src/queue_save.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "queue_save.h" -#include "queue.h" -#include "song.h" -#include "uri.h" -#include "database.h" -#include "song_save.h" -#include "text_file.h" - -#include - -#define PRIO_LABEL "Prio: " - -static void -queue_save_database_song(FILE *fp, int idx, const struct song *song) -{ - char *uri = song_get_uri(song); - - fprintf(fp, "%i:%s\n", idx, uri); - g_free(uri); -} - -static void -queue_save_full_song(FILE *fp, const struct song *song) -{ - song_save(fp, song); -} - -static void -queue_save_song(FILE *fp, int idx, const struct song *song) -{ - if (song_in_database(song)) - queue_save_database_song(fp, idx, song); - else - queue_save_full_song(fp, song); -} - -void -queue_save(FILE *fp, const struct queue *queue) -{ - for (unsigned i = 0; i < queue_length(queue); i++) { - uint8_t prio = queue_get_priority_at_position(queue, i); - if (prio != 0) - fprintf(fp, PRIO_LABEL "%u\n", prio); - - queue_save_song(fp, i, queue_get(queue, i)); - } -} - -static struct song * -get_song(const char *uri) -{ - return uri_has_scheme(uri) - ? song_remote_new(uri) - : db_get_song(uri); -} - -void -queue_load_song(FILE *fp, GString *buffer, const char *line, - struct queue *queue) -{ - struct song *song; - - if (queue_is_full(queue)) - return; - - uint8_t priority = 0; - if (g_str_has_prefix(line, PRIO_LABEL)) { - priority = strtoul(line + sizeof(PRIO_LABEL) - 1, NULL, 10); - - line = read_text_line(fp, buffer); - if (line == NULL) - return; - } - - if (g_str_has_prefix(line, SONG_BEGIN)) { - const char *uri = line + sizeof(SONG_BEGIN) - 1; - if (!uri_has_scheme(uri) && !g_path_is_absolute(uri)) - return; - - GError *error = NULL; - song = song_load(fp, NULL, uri, buffer, &error); - if (song == NULL) { - g_warning("%s", error->message); - g_error_free(error); - return; - } - } else { - char *endptr; - long ret = strtol(line, &endptr, 10); - if (ret < 0 || *endptr != ':' || endptr[1] == 0) { - g_warning("Malformed playlist line in state file"); - return; - } - - line = endptr + 1; - - song = get_song(line); - if (song == NULL) - return; - } - - queue_append(queue, song, priority); - - if (song_in_database(song)) - db_return_song(song); -} diff --git a/src/queue_save.h b/src/queue_save.h deleted file mode 100644 index 5526d615d..000000000 --- a/src/queue_save.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -/* - * This library saves the queue into the state file, and also loads it - * back into memory. - */ - -#ifndef QUEUE_SAVE_H -#define QUEUE_SAVE_H - -#include -#include - -struct queue; - -void -queue_save(FILE *fp, const struct queue *queue); - -/** - * Loads one song from the state file and appends it to the queue. - */ -void -queue_load_song(FILE *fp, GString *buffer, const char *line, - struct queue *queue); - -#endif diff --git a/src/song_save.c b/src/song_save.c deleted file mode 100644 index 4fcb46e22..000000000 --- a/src/song_save.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "song_save.h" -#include "song.h" -#include "tag_save.h" -#include "directory.h" -#include "tag.h" -#include "text_file.h" -#include "string_util.h" - -#include - -#include - -#undef G_LOG_DOMAIN -#define G_LOG_DOMAIN "song" - -#define SONG_MTIME "mtime" -#define SONG_END "song_end" - -static GQuark -song_save_quark(void) -{ - return g_quark_from_static_string("song_save"); -} - -void -song_save(FILE *fp, const struct song *song) -{ - fprintf(fp, SONG_BEGIN "%s\n", song->uri); - - if (song->end_ms > 0) - fprintf(fp, "Range: %u-%u\n", song->start_ms, song->end_ms); - else if (song->start_ms > 0) - fprintf(fp, "Range: %u-\n", song->start_ms); - - if (song->tag != NULL) - tag_save(fp, song->tag); - - fprintf(fp, SONG_MTIME ": %li\n", (long)song->mtime); - fprintf(fp, SONG_END "\n"); -} - -struct song * -song_load(FILE *fp, struct directory *parent, const char *uri, - GString *buffer, GError **error_r) -{ - struct song *song = parent != NULL - ? song_file_new(uri, parent) - : song_remote_new(uri); - char *line, *colon; - enum tag_type type; - const char *value; - - while ((line = read_text_line(fp, buffer)) != NULL && - strcmp(line, SONG_END) != 0) { - colon = strchr(line, ':'); - if (colon == NULL || colon == line) { - if (song->tag != NULL) - tag_end_add(song->tag); - song_free(song); - - g_set_error(error_r, song_save_quark(), 0, - "unknown line in db: %s", line); - return NULL; - } - - *colon++ = 0; - value = strchug_fast_c(colon); - - if ((type = tag_name_parse(line)) != TAG_NUM_OF_ITEM_TYPES) { - if (!song->tag) { - song->tag = tag_new(); - tag_begin_add(song->tag); - } - - tag_add_item(song->tag, type, value); - } else if (strcmp(line, "Time") == 0) { - if (!song->tag) { - song->tag = tag_new(); - tag_begin_add(song->tag); - } - - song->tag->time = atoi(value); - } else if (strcmp(line, "Playlist") == 0) { - if (!song->tag) { - song->tag = tag_new(); - tag_begin_add(song->tag); - } - - song->tag->has_playlist = strcmp(value, "yes") == 0; - } else if (strcmp(line, SONG_MTIME) == 0) { - song->mtime = atoi(value); - } else if (strcmp(line, "Range") == 0) { - char *endptr; - - song->start_ms = strtoul(value, &endptr, 10); - if (*endptr == '-') - song->end_ms = strtoul(endptr + 1, NULL, 10); - } else { - if (song->tag != NULL) - tag_end_add(song->tag); - song_free(song); - - g_set_error(error_r, song_save_quark(), 0, - "unknown line in db: %s", line); - return NULL; - } - } - - if (song->tag != NULL) - tag_end_add(song->tag); - - return song; -} diff --git a/src/song_save.h b/src/song_save.h deleted file mode 100644 index f6ecbbfeb..000000000 --- a/src/song_save.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_SONG_SAVE_H -#define MPD_SONG_SAVE_H - -#include - -#include - -#define SONG_BEGIN "song_begin: " - -struct song; -struct directory; - -void -song_save(FILE *fp, const struct song *song); - -/** - * Loads a song from the input file. Reading stops after the - * "song_end" line. - * - * @param error_r location to store the error occurring, or NULL to - * ignore errors - * @return true on success, false on error - */ -struct song * -song_load(FILE *fp, struct directory *parent, const char *uri, - GString *buffer, GError **error_r); - -#endif diff --git a/src/state_file.c b/src/state_file.c deleted file mode 100644 index de0e70538..000000000 --- a/src/state_file.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "state_file.h" -#include "output_state.h" -#include "playlist.h" -#include "playlist_state.h" -#include "volume.h" -#include "text_file.h" - -#include -#include -#include -#include - -#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(struct player_control *pc) -{ - FILE *fp; - - assert(state_file_path != NULL); - - g_debug("Saving state file %s", state_file_path); - - fp = fopen(state_file_path, "w"); - if (G_UNLIKELY(!fp)) { - g_warning("failed to create %s: %s", - state_file_path, g_strerror(errno)); - return; - } - - save_sw_volume_state(fp); - audio_output_state_save(fp); - playlist_state_save(fp, &g_playlist, pc); - - fclose(fp); - - 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, pc); -} - -static void -state_file_read(struct player_control *pc) -{ - FILE *fp; - bool success; - - assert(state_file_path != NULL); - - g_debug("Loading state file %s", state_file_path); - - fp = fopen(state_file_path, "r"); - if (G_UNLIKELY(!fp)) { - g_warning("failed to open %s: %s", - state_file_path, g_strerror(errno)); - return; - } - - GString *buffer = g_string_sized_new(1024); - const char *line; - while ((line = read_text_line(fp, buffer)) != NULL) { - success = read_sw_volume_state(line) || - audio_output_state_read(line) || - playlist_state_restore(line, fp, buffer, - &g_playlist, pc); - if (!success) - g_warning("Unrecognized line in state file: %s", line); - } - - fclose(fp); - - 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, pc); - - - g_string_free(buffer, true); -} - -/** - * 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) -{ - struct player_control *pc = 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, pc)) - /* nothing has changed - don't save the state file, - don't spin up the hard disk */ - return true; - - state_file_write(pc); - return true; -} - -void -state_file_init(const char *path, struct player_control *pc) -{ - assert(state_file_path == NULL); - - if (path == NULL) - return; - - state_file_path = g_strdup(path); - state_file_read(pc); - - save_state_source_id = g_timeout_add_seconds(5 * 60, - timer_save_state_file, - pc); -} - -void -state_file_finish(struct player_control *pc) -{ - 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); - - state_file_write(pc); - - g_free(state_file_path); -} diff --git a/src/state_file.h b/src/state_file.h deleted file mode 100644 index 4c4f881cc..000000000 --- a/src/state_file.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_STATE_FILE_H -#define MPD_STATE_FILE_H - -struct player_control; - -void -state_file_init(const char *path, struct player_control *pc); - -void -state_file_finish(struct player_control *pc); - -void write_state_file(void); - -#endif /* STATE_FILE_H */ diff --git a/src/tag_save.c b/src/tag_save.c deleted file mode 100644 index 2fdaef56c..000000000 --- a/src/tag_save.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "tag_save.h" -#include "tag.h" -#include "tag_internal.h" -#include "song.h" - -void tag_save(FILE *file, const struct tag *tag) -{ - if (tag->time >= 0) - fprintf(file, SONG_TIME "%i\n", tag->time); - - if (tag->has_playlist) - fprintf(file, "Playlist: yes\n"); - - for (unsigned i = 0; i < tag->num_items; i++) - fprintf(file, "%s: %s\n", - tag_item_names[tag->items[i]->type], - tag->items[i]->value); -} diff --git a/src/tag_save.h b/src/tag_save.h deleted file mode 100644 index 9f6a580c8..000000000 --- a/src/tag_save.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2003-2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_TAG_SAVE_H -#define MPD_TAG_SAVE_H - -#include - -struct tag; - -void tag_save(FILE *file, const struct tag *tag); - -#endif -- cgit v1.2.3