core/tags/track: Clean up constructors

I replace the standard and copy constructors with one that tags a track
during construction.  This lets me clean up a lot of code, and keep
tagging functions internal to the track class.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2015-10-31 10:53:40 -04:00
parent 33e20989fa
commit 92806c5201
7 changed files with 89 additions and 143 deletions

View File

@ -1,7 +1,7 @@
#!/usr/bin/python
Import("env")
env.UsePackage("taglib")
env.UsePackage("taglib_c")
res = Glob("*.cpp") + Glob("*.c") + SConscript("tags/Sconscript")
Return("res")

View File

@ -6,8 +6,6 @@
#include <core/print.h>
#include <glib.h>
#include <taglib/tag.h>
#include <taglib/fileref.h>
class LibraryQueue : public Queue {
@ -82,28 +80,7 @@ static void scan_path(struct scan_info &);
*/
static void tag_track(struct library *library, const std::string &filepath)
{
struct track *track;
TagLib :: Tag *tag;
TagLib :: AudioProperties *audio;
TagLib :: FileRef ref(filepath.c_str(), true, TagLib::AudioProperties::Fast);
if (ref.isNull()) {
print("WARNING: Could not read tags for file %s\n", filepath.c_str());
return;
}
tag = ref.tag();
audio = ref.audioProperties();
track = track_add(
album_find(tag->album().stripWhiteSpace().to8Bit(true), tag->year()),
artist_find(tag->artist().stripWhiteSpace().to8Bit(true)),
genre_find(tag->genre().stripWhiteSpace().to8Bit(true)),
library, filepath,
tag->title().stripWhiteSpace().to8Bit(true),
audio->length(), tag->track()
);
struct track *track = track_add(library, filepath);
if (track)
library_q.add(track);
}

View File

@ -4,6 +4,7 @@
#include <core/filter.h>
extern "C" {
#include <core/string.h>
#include <taglib/tag_c.h>
}
#include <core/tags/track.h>
@ -12,7 +13,7 @@ extern "C" {
static database<struct track> track_db;
static const std::string make_key(struct library *library, const std::string &path)
static const std::string __track_key(struct library *library, const std::string &path)
{
std :: string res;
@ -31,33 +32,54 @@ track :: track()
tr_count(0), tr_length(0), tr_track(0)
{}
track :: track(struct album *album, struct artist *artist, struct genre *genre,
struct library *library, const std::string &filepath,
const std::string &name, unsigned int length, unsigned int track)
: tr_album(album), tr_artist(artist), tr_genre(genre),
tr_library(library), tr_count(0), tr_length(length), tr_track(track),
tr_path(filepath), tr_title(name)
track :: track(const std::string &key)
{
gchar *lower = string_lowercase(name.c_str());
tr_lower = lower;
g_free(lower);
const TagLib_AudioProperties *audio;
struct library *library;
unsigned int lib_id;
TagLib_File *file;
TagLib_Tag *tag;
std::string full;
char *path, *lower;
sscanf(key.c_str(), "%u/%m[^\n]", &lib_id, &path);
library = library_get(lib_id);
full = library_file(library, path);
file = taglib_file_new(full.c_str());
if (!file || !taglib_file_is_valid(file)) {
printf("WARNING: Could not read tags for: %s\n", full.c_str());
goto out;
}
tag = taglib_file_tag(file);
audio = taglib_file_audioproperties(file);
tr_album = album_find(taglib_tag_album(tag), taglib_tag_year(tag));
tr_artist = artist_find(taglib_tag_artist(tag));
tr_genre = genre_find(taglib_tag_genre(tag));
tr_library = library;
tr_library->li_size++;
date_set(&tr_date, 0, 0, 0);
filter :: add(this->tr_title, index());
tr_count = 0;
tr_length = taglib_audioproperties_length(audio);
tr_track = taglib_tag_track(tag);
tr_path = path;
tr_title = taglib_tag_title(tag);
lower = string_lowercase(tr_title.c_str());
tr_lower = lower;
date_set(&tr_date, 0, 0, 0);
filter :: add(tr_title, index());
filter :: add(tr_artist->ar_name, index());
filter :: add(tr_album->al_name, index());
tr_library->li_size++;
}
track :: track(const struct track &track)
: tr_album(track.tr_album), tr_artist(track.tr_artist),
tr_genre(track.tr_genre), tr_library(track.tr_library),
tr_count(track.tr_count), tr_length(track.tr_length),
tr_track(track.tr_track), tr_date(track.tr_date),
tr_path(track.tr_path), tr_title(track.tr_title),
tr_lower(track.tr_lower)
{
tr_library->li_size++;
taglib_tag_free_strings();
taglib_file_free(file);
g_free(lower);
out:
g_free(path);
}
track :: ~track()
@ -68,7 +90,7 @@ track :: ~track()
const std::string track :: primary_key() const
{
return make_key(tr_library, tr_path);
return __track_key(tr_library, tr_path);
}
void track :: read(file &file)
@ -134,16 +156,13 @@ const database<struct track> *track_db_get()
return &track_db;
}
struct track *track_add(struct album *album, struct artist *artist,
struct genre *genre, struct library *library,
const std::string &filepath, const std::string &name,
unsigned int length, unsigned int track)
struct track *track_add(struct library *library, const std::string &filepath)
{
std::string path = filepath.substr(library->primary_key().size() + 1);
if (db_get(&track_db, make_key(library, path).c_str()))
std::string key = __track_key(library, path);
if (db_get(&track_db, key.c_str()))
return NULL;
return db_insert(&track_db, new struct track(album, artist, genre, library,
path, name, length, track));
return db_insert(&track_db, new struct track(key));
}
void track_remove(struct track *track)

View File

@ -33,29 +33,7 @@ struct track : public DatabaseEntry {
std::string tr_title; /* This track's title. */
std::string tr_lower; /* This track's title (lowercased). */
/**
* Track constructor
*
* @param album The album containing this track.
* @param artist The artist performing this track.
* @param genre The genre describing this track.
* @param library The library containing this track.
* @param filepath The path of this track, relative to the library root.
* @param name The name (title) of this track.
* @param length The length of this track (in seconds).
* @param track The track number of this track.
*/
track(struct album *, struct artist *, struct genre *, struct library *,
const std::string &, const std::string &, unsigned int,
unsigned int);
/**
* Track copy constructor
*
* @param track The Track tag that should be copied.
*/
track(const struct track &);
track(const std::string &);
track(); /**< Track constructor. */
~track(); /**< Track destructor. */
@ -98,9 +76,7 @@ void track_db_commit();
const database<struct track> *track_db_get();
/* Called to add a track tag to the database. */
struct track *track_add(struct album *, struct artist *, struct genre *,
struct library *, const std::string &,
const std::string &, unsigned int, unsigned int);
struct track *track_add(struct library *, const std::string &);
/* Called to remove a specific track tag. */
void track_remove(struct track *);

View File

@ -26,8 +26,6 @@ res += [ CoreTest("idle", "idle.cpp") ]
res += SConscript("tags/Sconscript")
res += [ CoreTest("queue", "queue.cpp") ]
env.UsePackage("taglib")
res += [ CoreTest("library", "library.cpp") ]
res += [ CoreTest("playlist", "playlist.cpp") ]
res += [ CoreTest("deck", "deck.cpp") ]

View File

@ -17,6 +17,7 @@ res += [ TagTest("album", "album.cpp") ]
res += [ TagTest("genre", "genre.cpp") ]
res += [ TagTest("library", "library.cpp") ]
env.UsePackage("taglib_c")
core_objs += [ env.Object("../../../core/tags/tags.cpp") ]
res += [ TagTest("track", "track.cpp") ]

View File

@ -13,13 +13,6 @@ extern "C" {
#include <sstream>
static struct artist *artist = NULL;
static struct album *album = NULL;
static struct genre *genre = NULL;
static struct library *library = NULL;
const std::string MUSIC_DIR = "/home/Zelda/Music";
static void test_track_tag_default()
{
struct track track;
@ -42,72 +35,63 @@ static void test_track_tag_default()
static void verify_track_tag(struct track *track, unsigned int size)
{
test_equal(track->tr_album, album);
test_equal(track->tr_artist, artist);
test_equal(track->tr_genre, genre);
test_equal(track->tr_library, library);
test_equal(track->tr_artist->ar_name, "Artist");
test_equal(track->tr_album->al_year, 2014);
test_equal(track->tr_album->al_name, "Album");
test_equal(track->tr_genre->ge_name, "Silence");
test_equal(track->tr_title, (std::string)"Legend of Zelda Medley");
test_equal(track->tr_lower, (std::string)"legend of zelda medley");
test_equal(track_last_play(track), (std::string)"Never");
test_equal(track_path(track), (std::string)MUSIC_DIR + "/Hyrule Symphony/13 - Legend of Zelda Medley.mp3");
test_equal(track->primary_key(), (std::string)"0/Hyrule Symphony/13 - Legend of Zelda Medley.mp3");
test_equal(track->tr_count, 0);
test_equal(track->tr_length, 1);
test_equal(track->tr_track, 1);
test_equal(track->tr_track, (unsigned)13);
test_equal(track->tr_length, (unsigned)288);
test_equal(track->tr_count, (unsigned)0);
test_equal(library->li_size, size);
test_equal(track->tr_path, "1.ogg");
test_equal(track->tr_title, "One");
test_equal(track->tr_lower, "one");
test_equal(track->tr_library->li_size, size);
}
static void test_track_tag_constructor()
{
struct set search = SET_INIT();
struct library *library;
struct track *track;
file f;
filter_init();
tags :: init();
album = album_find("Hyrule Symphony", 1998);
artist = artist_find("Koji Kondo");
genre = genre_find("Video Game Music");
library = library_find(MUSIC_DIR);
library = library_find("tests/Music");
struct track a(album, artist, genre, library,
"Hyrule Symphony/13 - Legend of Zelda Medley.mp3",
"Legend of Zelda Medley", 288, 13);
struct set search = SET_INIT();
struct track b;
verify_track_tag(&a, 1);
track = new struct track("0/1.ogg");
verify_track_tag(track, 1);
file_init(&f, "track_tag", 0);
file_open(&f, OPEN_WRITE);
a.write(f);
track->write(f);
file_close(&f);
delete track;
test_equal(library->li_size, 0);
track = new struct track;
file_open(&f, OPEN_READ);
b.read(f);
track->read(f);
file_close(&f);
verify_track_tag(track, 1);
delete track;
verify_track_tag(&b, 2);
filter :: search("Legend of Zelda Medley", &search);
filter :: search("One", &search);
test_equal(set_size(&search), (size_t)1);
test_equal(set_has(&search, 0), true);
filter :: search("Koji Kondo", &search);
filter :: search("Artist", &search);
test_equal(set_size(&search), (size_t)1);
test_equal(set_has(&search, 0), true);
filter :: search("Hyrule Symphony", &search);
filter :: search("Album", &search);
test_equal(set_size(&search), (size_t)1);
test_equal(set_has(&search, 0), true);
}
static void test_track_tag_destructor()
{
test_equal(library->li_size, (unsigned)0);
}
static void test_track_tag_load_db(unsigned int size)
{
database<struct track> track_db;
@ -121,21 +105,16 @@ static void test_track_tag_lookup()
{
unsigned int index;
struct track *a, *b;
struct library *library = library_find("tests/Music");
a = track_add(album, artist, genre, library,
MUSIC_DIR + "/Hyrule Symphony/13 - Legend of Zelda Medley.mp3",
"Legend of Zelda Medley", 288, 13);
a = track_add(library, "tests/Music/1.ogg");
test_not_equal(a, (struct track *)NULL);
verify_track_tag(a, 1);
b = track_add(album, artist, genre, library,
MUSIC_DIR + "/Hyrule Symphony/13 - Legend of Zelda Medley.mp3",
"Legend of Zelda Medley", 288, 13);
b = track_add(library, "tests/Music/1.ogg");
test_equal(b, (struct track *)NULL);
b = track_add(album, artist, genre, library,
MUSIC_DIR + "/Hyrule Symphony/12 - Ocarina Medley.mp3",
"Ocarina Medley", 232, 12);
b = track_add(library, "tests/Music/10.ogg");
test_not_equal(b, a);
test_equal(library->li_size, (unsigned)2);
test_equal(track_db_get()->db_size, b->index() + 1);
@ -160,9 +139,7 @@ static void test_track_tag_lookup()
test_equal(db_actual_size(track_db_get()), b->index() + 1);
a = track_add(album, artist, genre, library,
MUSIC_DIR + "/Hyrule Symphony/13 - Legend of Zelda Medley.mp3",
"Legend of Zelda Medley", 288, 13);
a = track_add(library, "tests/Music/1.ogg");
test_not_equal(a, (struct track *)NULL);
verify_track_tag(a, 2);
test_equal(db_actual_size(track_db_get()), a->index() + 1);
@ -176,9 +153,8 @@ static void test_track_tag_locale()
{
time_t rawtime = time(NULL);
struct tm *now = localtime(&rawtime);
struct track *track = track_add(album, artist, genre, library,
MUSIC_DIR + "/Hyrule Symphony/6 - Kakariko Village.mp3",
"Kakariko Village", 186, 6);
struct library *library = library_find("tests/Music");
struct track *track = track_add(library, "tests/Music/1.ogg");
gchar *date;
std::setlocale(LC_TIME, "C");
@ -196,7 +172,6 @@ static void test_track_tag_locale()
DECLARE_UNIT_TESTS(
UNIT_TEST("Track Tag Default Constructor", test_track_tag_default),
UNIT_TEST("Track Tag Constructor", test_track_tag_constructor),
UNIT_TEST("Track Tag Destructor Test", test_track_tag_destructor),
UNIT_TEST("Track Tag Lookup Test", test_track_tag_lookup),
UNIT_TEST("Track Tag Date Test", test_track_tag_locale),
);