diff options
Diffstat (limited to 'src/song_save.c')
-rw-r--r-- | src/song_save.c | 165 |
1 files changed, 69 insertions, 96 deletions
diff --git a/src/song_save.c b/src/song_save.c index 2d6297f3e..a1a573298 100644 --- a/src/song_save.c +++ b/src/song_save.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2009 The Music Player Daemon Project + * Copyright (C) 2003-2010 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,11 +17,13 @@ * 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 <glib.h> @@ -30,136 +32,107 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "song" -#define SONG_KEY "key: " -#define SONG_MTIME "mtime: " +#define SONG_MTIME "mtime" +#define SONG_END "song_end" -static void -song_save_url(FILE *fp, struct song *song) +static GQuark +song_save_quark(void) { - if (song->parent != NULL && song->parent->path != NULL) - fprintf(fp, SONG_FILE "%s/%s\n", - directory_get_path(song->parent), song->url); - else - fprintf(fp, SONG_FILE "%s\n", - song->url); + return g_quark_from_static_string("song_save"); } -static int -song_save(struct song *song, void *data) +void +song_save(FILE *fp, const struct song *song) { - FILE *fp = data; - - fprintf(fp, SONG_KEY "%s\n", song->url); + fprintf(fp, SONG_BEGIN "%s\n", song->uri); - song_save_url(fp, song); + 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); - - return 0; + fprintf(fp, SONG_MTIME ": %li\n", (long)song->mtime); + fprintf(fp, SONG_END "\n"); } -void songvec_save(FILE *fp, struct songvec *sv) +static int +song_save_callback(struct song *song, void *data) { - fprintf(fp, "%s\n", SONG_BEGIN); - songvec_for_each(sv, song_save, fp); - fprintf(fp, "%s\n", SONG_END); + FILE *fp = data; + song_save(fp, song); + return 0; } -static void -insertSongIntoList(struct songvec *sv, struct song *newsong) +void songvec_save(FILE *fp, const struct songvec *sv) { - struct song *existing = songvec_find(sv, newsong->url); - - if (!existing) { - songvec_add(sv, newsong); - if (newsong->tag) - tag_end_add(newsong->tag); - } else { /* prevent dupes, just update the existing song info */ - if (existing->mtime != newsong->mtime) { - if (existing->tag != NULL) - tag_free(existing->tag); - if (newsong->tag) - tag_end_add(newsong->tag); - existing->tag = newsong->tag; - existing->mtime = newsong->mtime; - newsong->tag = NULL; - } - song_free(newsong); - } + songvec_for_each(sv, song_save_callback, fp); } -static char * -matchesAnMpdTagItemKey(char *buffer, enum tag_type *itemType) +struct song * +song_load(FILE *fp, struct directory *parent, const char *uri, + GString *buffer, GError **error_r) { - int i; - - for (i = 0; i < TAG_NUM_OF_ITEM_TYPES; i++) { - size_t len = strlen(tag_item_names[i]); + struct song *song = parent != NULL + ? song_file_new(uri, parent) + : song_remote_new(uri); + char *line, *colon; + enum tag_type type; + const char *value; - if (0 == strncmp(tag_item_names[i], buffer, len) && - buffer[len] == ':') { - *itemType = i; - return g_strchug(buffer + len + 1); + 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; } - } - return NULL; -} + *colon++ = 0; + value = g_strchug(colon); -void readSongInfoIntoList(FILE *fp, struct songvec *sv, - struct directory *parent) -{ - enum { - buffer_size = 32768, - }; - char *buffer = g_malloc(buffer_size); - struct song *song = NULL; - enum tag_type itemType; - const char *value; - - while (fgets(buffer, buffer_size, fp) && - !g_str_has_prefix(buffer, SONG_END)) { - g_strchomp(buffer); - - if (0 == strncmp(SONG_KEY, buffer, strlen(SONG_KEY))) { - if (song) - insertSongIntoList(sv, song); - - song = song_file_new(buffer + strlen(SONG_KEY), - parent); - } else if (*buffer == 0) { - /* ignore empty lines (starting with '\0') */ - } else if (song == NULL) { - g_error("Problems reading song info"); - } else if (0 == strncmp(SONG_FILE, buffer, strlen(SONG_FILE))) { - /* we don't need this info anymore */ - } else if ((value = matchesAnMpdTagItemKey(buffer, - &itemType)) != NULL) { + 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, itemType, value); - } else if (0 == strncmp(SONG_TIME, buffer, strlen(SONG_TIME))) { + 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(&(buffer[strlen(SONG_TIME)])); - } else if (0 == strncmp(SONG_MTIME, buffer, strlen(SONG_MTIME))) { - song->mtime = atoi(&(buffer[strlen(SONG_MTIME)])); + song->tag->time = atoi(value); + } 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; } - else - g_error("unknown line in db: %s", buffer); } - g_free(buffer); + if (song->tag != NULL) + tag_end_add(song->tag); - if (song) - insertSongIntoList(sv, song); + return song; } |