From 0cefd158d9afa2c4994f403ad1d1f5c41e64ed55 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Fri, 12 Aug 2016 11:14:51 -0400 Subject: [PATCH] core/tags/album: Add artist and genre information to saved data And perform an upgrade when reading back in. After track tags are read, we can save the database in the new format and remove the old tags. Signed-off-by: Anna Schumaker --- core/tags/album.c | 58 +++++++++++++++++++++++++++++++++++---- core/tags/tags.c | 12 +++++++- include/core/tags/album.h | 13 +++++---- tests/core/tags/album.c | 38 +++++++++++-------------- 4 files changed, 87 insertions(+), 34 deletions(-) diff --git a/core/tags/album.c b/core/tags/album.c index 887774d6..c0b24ea3 100644 --- a/core/tags/album.c +++ b/core/tags/album.c @@ -15,7 +15,10 @@ #define OCARINA_AGENT OCARINA_NAME #endif +#define ALBUM_DB_MIN 0 /* Ocarina 6.0 */ +#define ALBUM_DB_CUR 1 /* Ocarina 6.5 */ static struct database album_db; +static bool album_db_upgraded = false; static inline void __album_init_file(struct album *al, struct cache_file *f) @@ -185,7 +188,7 @@ static struct album *__album_alloc(struct artist *artist, struct genre *genre, album->al_artist = artist; album->al_genre = genre; - if (!album_artwork_exists(album)) + if (!album_artwork_exists(album) && artist && genre) idle_schedule(IDLE_ASYNC, IDLE_FUNC(__album_fetch_artwork), album); return album; } @@ -229,22 +232,49 @@ static gchar *album_key(struct db_entry *dbe) ALBUM(dbe)->al_name, ALBUM(dbe)->al_year); } -static struct db_entry *album_read(struct file *file) +static struct album *__album_parse_v0(gchar *line) { unsigned int year; + gchar *name; + + if (sscanf(line, "%u %m[^\n]", &year, &name) == 1) + name = g_strdup(""); + return __album_alloc(NULL, NULL, name, year); +} + +static struct db_entry *album_read(struct file *file) +{ + unsigned int year, artist_id, genre_id, n; + struct album *album; gchar *line, *name; line = file_readl(file); - if (sscanf(line, "%u %m[^\n]", &year, &name) == 1) + if (file_version(file) == 0) { + album = __album_parse_v0(line); + album_db_upgraded = true; + goto out; + } + + n = sscanf(line, "%u %u %u %m[^\n]", &artist_id, &genre_id, &year, &name); + if (n == 3) name = g_strdup(""); + album = __album_alloc(artist_get(artist_id), + genre_get(genre_id), name, year); +out: g_free(line); - return &__album_alloc(NULL, NULL, name, year)->al_dbe; + return &album->al_dbe; } static void album_write(struct file *file, struct db_entry *dbe) { - file_writef(file, "%u %s", ALBUM(dbe)->al_year, ALBUM(dbe)->al_name); + struct album *album = ALBUM(dbe); + struct artist *artist = album->al_artist; + struct genre *genre = album->al_genre; + + file_writef(file, "%u %u %u %s", artist ? artist_index(artist) : 0, + genre ? genre_index(genre) : 0, + album->al_year, album->al_name); } @@ -260,7 +290,8 @@ static const struct db_ops album_ops = { void album_db_init() { - db_init(&album_db, "album.db", true, &album_ops, 0, 0); + db_init(&album_db, "album.db", true, &album_ops, ALBUM_DB_MIN, + ALBUM_DB_CUR); db_load_idle(&album_db); } @@ -269,6 +300,21 @@ void album_db_deinit() db_deinit(&album_db); } +bool album_db_upgrade_done() +{ + struct db_entry *dbe, *next; + + if (album_db_upgraded == false) + return false; + + db_for_each(dbe, next, &album_db) { + if (!ALBUM(dbe)->al_artist && !ALBUM(dbe)->al_genre) + db_remove(&album_db, dbe); + } + + return true; +} + struct album *album_find(struct artist *artist, struct genre *genre, const gchar *name, unsigned int year) { diff --git a/core/tags/tags.c b/core/tags/tags.c index 9c7e38bb..112d7ace 100644 --- a/core/tags/tags.c +++ b/core/tags/tags.c @@ -1,6 +1,7 @@ /* * Copyright 2014 (c) Anna Schumaker. */ +#include #include #include #include @@ -8,13 +9,22 @@ #include #include +static bool tags_upgrade_done(void *data) +{ + if (album_db_upgrade_done()) + track_db_commit(); + return true; +} + void tags_init() { artist_db_init(); - album_db_init(); genre_db_init(); + album_db_init(); library_db_init(); track_db_init(); + + idle_schedule(IDLE_SYNC, tags_upgrade_done, NULL); } void tags_deinit() diff --git a/include/core/tags/album.h b/include/core/tags/album.h index 7409496f..ec411ac7 100644 --- a/include/core/tags/album.h +++ b/include/core/tags/album.h @@ -4,12 +4,12 @@ * The album tag is used to store the name and year of albums * added to the tag database. * - * When writing an album tag to disk, write out the album_year field - * followed by the album_name on the same line: + * When writing an album tag to disk, write out the album_artist, album_genre, + * and album_year fields followed by the album_name on the same line: * - * ... 1998 Hyrule Symphony - * ... 2006 Twilight Princess - * ... 2011 Skyward Sword + * ...0 0 1998 Hyrule Symphony + * ...0 0 2006 Twilight Princess + * ...0 0 2011 Skyward Sword */ #ifndef OCARINA_CORE_TAGS_ALBUM_H #define OCARINA_CORE_TAGS_ALBUM_H @@ -36,6 +36,9 @@ void album_db_init(); /* Called to clean up the album database. */ void album_db_deinit(); +/* Called to clean up the album database after an upgrade. */ +bool album_db_upgrade_done(); + /* Called to find an album tag by artist, name and year. */ struct album *album_find(struct artist *, struct genre *, const gchar *, unsigned int); diff --git a/tests/core/tags/album.c b/tests/core/tags/album.c index d00b1081..687c4bf1 100644 --- a/tests/core/tags/album.c +++ b/tests/core/tags/album.c @@ -12,9 +12,10 @@ static void test_verify_empty(struct album *album) g_assert_cmpstr(album->al_name, ==, ""); g_assert_null(album->al_tokens[0]); g_assert_null(album->al_alts[0]); - g_assert_null(album->al_artist); + g_assert(album->al_artist == artist_get(0)); + g_assert(album->al_genre == genre_get(0)); g_assert_cmpuint(album->al_year, ==, 0); - g_assert_cmpstr_free(album_ops->dbe_key(&album->al_dbe), ==, "0/"); + g_assert_cmpstr_free(album_ops->dbe_key(&album->al_dbe), ==, "0/0/0/"); } static void test_verify_hyrule(struct album *album, struct artist *artist, @@ -51,16 +52,15 @@ static void test_album() koji = artist_find("Koji Kondo"); genre = genre_find("Video Game Music"); - album = ALBUM(album_ops->dbe_alloc("0/0/1998/Hyrule Symphony")); test_verify_hyrule(album, koji, genre); g_assert_true( album_match_token(album, "hyrule")); g_assert_true( album_match_token(album, "symphony")); g_assert_false(album_match_token(album, "skyward")); - file_init(&f, "album_tag", 0, 0); + file_init(&f, "album_tag", 1, 1); file_open(&f, OPEN_WRITE); - file_writef(&f, "0 \n"); + file_writef(&f, "0 0 0 \n"); album_ops->dbe_write(&f, &album->al_dbe); file_close(&f); album_ops->dbe_free(&album->al_dbe); @@ -72,7 +72,7 @@ static void test_album() album = ALBUM(album_ops->dbe_read(&f)); file_close(&f); - test_verify_hyrule(album, NULL, NULL); + test_verify_hyrule(album, koji, genre); album_ops->dbe_free(&album->al_dbe); } @@ -109,25 +109,17 @@ static void test_album_db() struct genre *genre; struct album *album; - album = album_find(NULL, NULL, "Hyrule Symphony", 1998); - test_verify_hyrule(album, NULL, NULL); - g_assert(album_find(NULL, NULL, "Hyrule Symphony", 1998) == album); - g_assert(album_get(0) == album); - g_assert_null(album_get(1)); - koji = artist_find("Koji Kondo"); genre = genre_find("Video Game Music"); album = album_find(koji, genre, "Hyrule Symphony", 1998); test_verify_hyrule(album, koji, genre); - g_assert(album_find(NULL, NULL, "Hyrule Symphony", 1998) != album); g_assert(album_find(koji, genre, "Hyrule Symphony", 1998) == album); - g_assert(album_get(0) != album); - g_assert(album_get(1) == album); - g_assert_null(album_get(2)); + g_assert(album_get(0) == album); + g_assert_null(album_get(1)); - db_init(&album_db, "album.db", false, album_ops, 0, 0); + db_init(&album_db, "album.db", false, album_ops, 1, 1); db_load(&album_db); - g_assert_cmpuint(album_db.db_size, ==, 2); + g_assert_cmpuint(album_db.db_size, ==, 1); db_deinit(&album_db); } @@ -138,6 +130,7 @@ static void test_album_artwork() struct album *ocarina, *majora, *wind, *ocarina_3d; gchar *o_path, *m_path, *w_path; struct artist *koji; + struct genre *genre; const gchar *cache; idle_deinit(); @@ -149,9 +142,10 @@ static void test_album_artwork() w_path = g_build_filename(cache, "ocarina-test", "core", "tags", "album", "0", "Wind Waker.jpg", NULL); koji = artist_find("Koji Kondo"); - ocarina = album_find(koji, NULL, "Ocarina of Time", 1998); - majora = album_find(NULL, NULL, "Majora's Mask", 2000); - wind = album_find(NULL, NULL, "Wind Waker", 0); + genre = genre_find("Video Game Music"); + ocarina = album_find(koji, genre, "Ocarina of Time", 1998); + majora = album_find(koji, genre, "Majora's Mask", 2000); + wind = album_find(koji, genre, "Wind Waker", 0); ocarina->al_artist = koji; g_assert_false(album_artwork_exists(ocarina)); @@ -171,7 +165,7 @@ static void test_album_artwork() g_assert_cmpstr_free(album_artwork_path(wind), ==, w_path); /* Import the original Ocarina of Time album art. */ - ocarina_3d = album_find(NULL, NULL, "Ocarina of Time 3D", 2011); + ocarina_3d = album_find(koji, genre, "Ocarina of Time 3D", 2011); g_assert_false(album_artwork_exists(ocarina_3d)); album_artwork_import(ocarina_3d, NULL); g_assert_false(album_artwork_exists(ocarina_3d));