207 lines
5.4 KiB
Plaintext
207 lines
5.4 KiB
Plaintext
== Files ==
|
|
ocarina/include/
|
|
library.h
|
|
ocarina/lib/
|
|
library.cpp
|
|
$HOME/.ocarina{-debug}/
|
|
album.db
|
|
artist.db
|
|
genre.db
|
|
library.db
|
|
track.db
|
|
|
|
== Depends ==
|
|
idle database playlist filter
|
|
|
|
Library: (lib/library.cpp)
|
|
The library manages databases containing track information added by the
|
|
user. Ocarina 6 splits the library into multiple database tables for
|
|
storing content. The library will exist in a library namespace to
|
|
to make functions and classes more unique.
|
|
|
|
When a library : Track is created, it should be added to the "Library"
|
|
group if it is NOT a member of the banned songs group.
|
|
|
|
- Databases:
|
|
enum DB_Type {
|
|
DB_ALBUM,
|
|
DB_ARTIST,
|
|
DB_GENRE,
|
|
DB_LIBRARY,
|
|
DB_TRACK,
|
|
};
|
|
|
|
- Album:
|
|
class library :: Album : public DatabaseEntry {
|
|
public:
|
|
string name;
|
|
string name_lc;
|
|
unsigned int year;
|
|
unsigned int artist_id;
|
|
};
|
|
|
|
File << artist_id << year << name
|
|
|
|
- Artist:
|
|
class library :: Artist : public DatabaseEntry {
|
|
public:
|
|
string name;
|
|
string name_lc;
|
|
};
|
|
|
|
File << name
|
|
|
|
- Genre:
|
|
class library :: Genre : public DatabaseEntry {
|
|
public:
|
|
string name;
|
|
string name_lc;
|
|
};
|
|
|
|
File << name
|
|
|
|
- Library:
|
|
class library :: Library : public DatabaseEntry {
|
|
public:
|
|
string root_path;
|
|
unsigned int count;
|
|
bool enabled;
|
|
};
|
|
|
|
File << enabled << root_path
|
|
|
|
- Track:
|
|
The primary key for a track is the full filepath (library.root_path +
|
|
track.filepath)
|
|
|
|
class library :: Track : public DatabaseEntry {
|
|
public:
|
|
unsigned int library_id;
|
|
unsigned int artist_id;
|
|
unsigned int album_id;
|
|
unsigned int genre_id;
|
|
|
|
unsigned int track;
|
|
unsigned int last_year;
|
|
unsigned int last_month;
|
|
unsigned int last_day;
|
|
unsigned int play_count;
|
|
unsigned int length;
|
|
|
|
bool banned;
|
|
string title;
|
|
string title_lc;
|
|
string length_str;
|
|
string filepath;
|
|
};
|
|
|
|
File << library_id << artist_id << album_id << genre_id << track << last_year
|
|
File << last_month << last_day << play_count << length << banned << endl
|
|
File << title << endl;
|
|
File << filepath << endl;
|
|
|
|
- Song:
|
|
struct Song {
|
|
library :: Album *album;
|
|
library :: Artist *artist;
|
|
library :: Genre *genre;
|
|
library :: Library *library;
|
|
library :: Track *track;
|
|
};
|
|
|
|
- Databases:
|
|
Database<library :: Album> album_db(album.db);
|
|
Database<library :: Artist> artist_db(artist.db);
|
|
Database<library :: Genre> genre_db(genre.db);
|
|
Database<library :: Library> library_db(library.db);
|
|
Database<library :: Track> track_db(track.db);
|
|
|
|
- Updating algorithm:
|
|
1) For each track currently in the library, check if the track exists
|
|
in the filesystem and mark the track invalid if it does not.
|
|
2) For each file in the scan directory, check if the track exists in
|
|
the track is already in the track_db.
|
|
2a) If the file is in the db, do nothing.
|
|
2b) Else, add track to the library and the filter index.
|
|
3) Save all databases
|
|
|
|
The taglib library should be used for finding artist, album, etc. tags
|
|
for each track.
|
|
|
|
Use idle tasks for step 2 to break up tagging new files into chunks.
|
|
This way the user will still be able to use Ocarina and scanning can
|
|
happen while idle.
|
|
|
|
- Importing
|
|
Ocarina 5.11 stores library files in ~/.ocarina/library/. Importing
|
|
involves reading each file and adding them to the database. If the file
|
|
describes a path already in the database then DO NOT overwrite the
|
|
current path and instead move on to the next file. If version != 2 then
|
|
move on to the next file.
|
|
|
|
File format:
|
|
File << version << endl; /* version == 2 */
|
|
File << path << endl;
|
|
File << id << enabled << next_track_id << size << endl;
|
|
File << <track list>
|
|
|
|
Track format:
|
|
File << filepath << endl;
|
|
File << title << endl;
|
|
File << artist << endl;
|
|
File << album << endl;
|
|
File << comment << endl;
|
|
File << genre << endl;
|
|
File << lenstr << endl;
|
|
File << id << year << track << count;
|
|
File << last_day << last_month << last_year;
|
|
File << length << bitrate << sample << channels << banned << endl;
|
|
|
|
- Testing:
|
|
The script tests/library/gen_library.sh will create a sample library
|
|
in the /tmp/ directory for testing purposes. All the track files are
|
|
complete silence, but the script will fake up tags for each file.
|
|
|
|
To test importing, create several mock library files and copy them to
|
|
~/.ocarina-test/library/ and attempt to read them in.
|
|
|
|
- API
|
|
void library :: init();
|
|
Initialize databases and read files from disk. While reading
|
|
the library:
|
|
- Update the count of treacks in each library path
|
|
- Find the lowercase text of artist, album, genre, track
|
|
|
|
void library :: add_path(string dir);
|
|
If dir is not a directory:
|
|
throw -EINVAL
|
|
|
|
Add new row to the library_db table, begin an update only
|
|
on the new path.
|
|
|
|
void library :: del_path(unsigned int lib_id);
|
|
Invalidate a library_db row and all tracks owned by that path
|
|
|
|
void library :: update_path(lib_id);
|
|
Update the given library_db row, if valid.
|
|
|
|
struct Song library :: lookup(track_id);
|
|
Fill out a Song structure for the provided track_id. Throw
|
|
-EEXIST if there is no track mapping to track_id.
|
|
|
|
struct library :: Library *library :: get_path_info(unsigned int id);
|
|
Return the library path with index id. Throw -EEXIST if there
|
|
is no such path.
|
|
|
|
void library :: import();
|
|
Call this function to import an Ocarina 5.11 style library,
|
|
following the "Importing" section above.
|
|
|
|
#ifdef CONFIG_DEBUG
|
|
void library :: print_db(DB_Type);
|
|
Print the database corresponding to DB_Type
|
|
|
|
void library :: reset();
|
|
Clear all databases, returning the library to an empty state.
|
|
endif /* CONFIG_DEBUG */
|