library: Implement importing old libraries

This adds backwards-compatibility for Ocarina 5.11 libraries.

Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
Anna Schumaker 2014-01-01 20:26:18 -05:00 committed by Anna Schumaker
parent 94fdfda9fb
commit a2665d4e41
8 changed files with 3777 additions and 3 deletions

View File

@ -10,6 +10,8 @@
#include <taglib/tag.h>
#include <taglib/fileref.h>
struct ImportData;
namespace library
{
@ -29,6 +31,7 @@ namespace library
AGInfo();
AGInfo(DB_Type, TagLib :: Tag *);
AGInfo(DB_Type, const std::string &);
void read(File &);
void write(File &);
#ifdef CONFIG_DEBUG
@ -46,6 +49,7 @@ namespace library
Album();
Album(TagLib :: Tag *, unsigned int);
Album(const std::string &, unsigned int, unsigned int);
void read(File &);
void write(File &);
#ifdef CONFIG_DEBUG
@ -83,7 +87,6 @@ namespace library
unsigned int play_count;
unsigned int length;
bool banned;
std :: string title;
std :: string title_lower;
std :: string length_str;
@ -93,6 +96,8 @@ namespace library
Track(TagLib :: Tag *, TagLib :: AudioProperties *,
unsigned int, unsigned int, unsigned int,
unsigned int, const std :: string &);
Track(ImportData *, unsigned int, unsigned int,
unsigned int, unsigned int);
void read(File &);
void write(File &);
#ifdef CONFIG_DEBUG
@ -116,6 +121,7 @@ namespace library
void update_path(unsigned int);
void update_all();
void lookup(unsigned int, library :: Song *);
void import();
#ifdef CONFIG_DEBUG
void print_db(DB_Type);
void reset();

View File

@ -16,6 +16,17 @@ static Database<library :: Track> track_db("track.db");
static Database<library :: Library> library_db("library.db");
struct ImportData {
std::string filepath;
std::string title;
unsigned int track;
unsigned int last_day;
unsigned int last_month;
unsigned int last_year;
unsigned int length;
unsigned int count;
};
/*
@ -39,6 +50,17 @@ library :: AGInfo :: AGInfo(DB_Type type, TagLib :: Tag *tag)
key_lower = filter :: to_lowercase(primary_key);
}
library :: AGInfo :: AGInfo(DB_Type type, const std::string &str)
: db_type(type)
{
if ((db_type == DB_ARTIST) || (db_type == DB_GENRE)) {
primary_key = str;
key_lower = filter :: to_lowercase(primary_key);
} else
throw -EINVAL;
}
void library :: AGInfo :: read(File &f)
{
primary_key = f.getline();
@ -80,6 +102,15 @@ library :: Album :: Album(TagLib :: Tag *tag, unsigned int artist)
name_lower = filter :: to_lowercase(name);
}
library :: Album :: Album(const std::string &str, unsigned int yr, unsigned int artist)
: name(str), year(yr), artist_id(artist)
{
std::stringstream ss;
ss << artist_id << "." << name << "." << year;
primary_key = ss.str();
name_lower = filter :: to_lowercase(name);
}
void library :: Album :: read(File &f)
{
f >> artist_id >> year;
@ -153,7 +184,7 @@ library :: Track :: Track(TagLib :: Tag *tag, TagLib :: AudioProperties *audio,
unsigned int genre, const std :: string &path)
: library_id(lib), artist_id(artist), album_id(album), genre_id(genre),
track(tag->track()), last_year(0), last_month(0), last_day(0),
play_count(0), length(audio->length()), banned(false),
play_count(0), length(audio->length()),
title(tag->title().stripWhiteSpace().to8Bit(true))
{
std::stringstream ss;
@ -172,11 +203,36 @@ library :: Track :: Track(TagLib :: Tag *tag, TagLib :: AudioProperties *audio,
length_str = ss.str();
}
library :: Track :: Track(struct ImportData *data, unsigned int lib,
unsigned int artist, unsigned int album,
unsigned int genre)
: library_id(lib), artist_id(artist), album_id(album), genre_id(genre),
track(data->track), last_year(data->last_year), last_month(data->last_month),
last_day(data->last_day), play_count(data->count), length(data->length),
title(data->title)
{
std::stringstream ss;
unsigned int minutes, seconds;
primary_key = data->filepath;
filepath = primary_key.substr(library_db[library_id].root_path.size() + 1);
title_lower = filter :: to_lowercase(title);
minutes = length / 60;
seconds = length % 60;
ss << minutes << ":";
if (seconds < 10)
ss << "0";
ss << seconds;
length_str = ss.str();
}
void library :: Track :: read(File &f)
{
f >> library_id >> artist_id >> album_id >> genre_id;
f >> track >> last_year >> last_month >> last_day;
f >> play_count >> length >> banned;
f >> play_count >> length;
length_str = f.getline();
title = f.getline();
filepath = f.getline();
}
@ -303,6 +359,66 @@ static void do_update_library(unsigned int lib_id)
idle :: schedule(do_scan_path, scan);
}
static void do_import_track(File &f, unsigned int lib_id)
{
struct ImportData data;
std::string artist, album, genre;
unsigned int artist_id, album_id, genre_id, year, tmp;
data.filepath = f.getline();
data.title = f.getline();
artist = f.getline();
album = f.getline();
f.getline(); /* comment */
genre = f.getline();
f.getline(); /* lenstr */
f >> tmp /* id */ >> year >> data.track >> data.count;
f >> data.last_day >> data.last_month >> data.last_year >> data.length;
f >> tmp >> tmp >>tmp >> tmp; /* bitrate, sample, channels, banned */
f.getline(); /* get rest of line */
artist_id = artist_db.insert(library :: AGInfo(library :: DB_ARTIST, artist));
album_id = album_db.insert(library :: Album(album, year, artist_id));
genre_id = genre_db.insert(library :: AGInfo(library :: DB_GENRE, genre));
track_db.insert(library :: Track(&data, lib_id, artist_id, album_id, genre_id));
}
static void do_import_library(std::string &s)
{
unsigned int id, next_id, size;
std::string path;
bool enabled;
File f(s, FILE_TYPE_LEGACY);
print("Importing: %s\n", f.get_filepath());
f.open(OPEN_READ);
if (f.get_version() != 2) {
print("Version mismatch: %u != 2\n", f.get_version());
return;
}
path = f.getline();
f >> id >> enabled >> next_id >> size;
/* Assign this path a new id */
if (library_db.has_key(path)) {
print("Library already contains path: %s, skipping\n", path.c_str());
return;
}
print("Adding path: %s\n", path.c_str());
id = library_db.insert(library :: Library(path, enabled));
library_db.save();
f.getline(); /* Get rest of line */
for (unsigned int i = 0; i < size; i++)
do_import_track(f, id);
save_all_dbs();
library :: update_path(id);
}
/*
@ -355,6 +471,27 @@ void library :: lookup(unsigned int id, library :: Song *song)
song->library = &library_db[song->track->library_id];
}
void library :: import()
{
unsigned int i = 0;
std::string name;
do {
std::stringstream ss;
ss << i;
name = ss.str();
File f(name, FILE_TYPE_LEGACY);
if (f.exists() == false)
break;
idle :: schedule(do_import_library, name);
ss.clear();
i++;
} while (true);
}
#ifdef CONFIG_DEBUG
void library :: print_db(DB_Type type)
{

1
tests/library/0 Normal file
View File

@ -0,0 +1 @@
1

1203
tests/library/1 Normal file

File diff suppressed because it is too large Load Diff

1203
tests/library/2 Normal file

File diff suppressed because it is too large Load Diff

1203
tests/library/3 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -78,3 +78,9 @@ for i in $(seq 0 4); do
done
touch /tmp/library/file
##
# Set up legacy library files
#
mkdir -p $HOME/.ocarina-test/library/
cp tests/library/0 tests/library/1 tests/library/2 tests/library/3 $HOME/.ocarina-test/library/

View File

@ -204,6 +204,20 @@ void test_6()
library :: update_path(0);
run_idle_tasks();
library :: print_db(library :: DB_TRACK);
print("\n");
}
/* Test importing Ocarina 5.11 libraries */
void test_7()
{
library :: reset();
test_add_dir("7a", "/tmp/library/2", true);
print("\n");
library :: import();
run_idle_tasks();
library :: print_db(library :: DB_LIBRARY);
}
int main(int argc, char **argv)
@ -217,5 +231,6 @@ int main(int argc, char **argv)
test_4();
test_5();
test_6();
test_7();
return 0;
}