ocarina/design.txt

171 lines
4.5 KiB
Plaintext
Raw Normal View History

===============================================================================
= =
= Ocarina 6.0 =
= =
===============================================================================
My main goal for Ocarina 6.x is to stop writing my own solutions to problems
that have already been solved. For example, this means using SQL to store
a library rather than developing my own file format. This should help with
future maintenance because I'll have less code to navigate.
I will also create unit tests as I add features so bugs can be found faster.
SQLite:
I plan on using SQLite for data storage as much as possible. I had
been using my own custom file formats for storing preferences or
libraries, but this is turning into a hassle as I have more code that
needs to be maintained. Try to use an SQLite prepared statement
whenever possible.
#include <sqlite3.h>
$ pkg-config --cflags --libs sqlite3
Files:
ocarina/
design.txt
ocarina/gui/
ocarina/include/
library.h
playlist.h
ocarina/lib/
library.cpp
playlist.cpp
ocarina/tests/
$HOME/.ocarina{-debug}/ocarina.db
Database: (ocarina.db)
Paths -
create table if not exists paths(
id INTEGER PRIMARY KEY AUTOINCREMENT,
dirpath TEXT UNIQUE, /* root path of library */
enabled INTEGER, /* 0 = false, 1 = true */
);
Artist -
create table if not exists artists(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE
);
Album -
create table if not exists albums(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE,
year SHORT INTEGER,
);
Tracks -
create table if not exists tracks(
id INTEGER PRIMARY KEY AUTOINCREMENT,
FOREIGN KEY(path_id) REFERENCES paths(id),
FOREIGN KEY(artist_id) REFERENCES artists(id),
FOREIGN KEY(album_id) REFERENCES albums(id),
filepath TEXT UNIQUE, /* full path - libary root */
title TEXT,
comment TEXT,
genre TEXT,
lenstr TEXT,
track UNSIGNED INT,
count UNSIGNED INT DEFAULT 0,
last_day UNSIGNED INT DEFAULT 0,
last_month UNSIGNED INT DEFAULT 0,
last_year UNSIGNED INT DEFAULT 0,
length INT,
bitrate INT,
sample INT,
channels INT,
banned INT, /* 0 = false, 1 = true */
);
<Research FTS tables and inverted indexes for filtering>
Tags index -
<another FTS table>
Tag Name -> song ids
User settings -
create table if not exists config(
name PRIMARY KEY,
value INT,
);
Library: (lib/library.cpp)
The purpose of library.cpp is to control access to the library tables
in the SQLite database. This file will set up prepared statements and
wrapper functions to make it really easy for the Ocarina gui to affect
the library.
- API
/* Path management */
add_path_to_library(dir);
Add new row to paths table, update
rm_path_from_library(dir);
Remove row from paths table
update_path(dir);
Scan tracks table, remove paths that don't exist
Scan dir, add new files to database
Consider having SQLite create an index on tracks.filepath
update_all();
Call update_path() for each paths.dirpath
list_paths(list<>);
Tell the caller basic information about library paths
(dir, enabled, size,...)
Playlist: (lib/playlist.cpp)
A playlist is a simple list of songs that can be played either randomly
or in a user-defined order. It would probably be best to use a linked
list or vector to represent playlists, rather than creating a SQLite
table. I will be able to easily rearrange tracks in the playlist this
way. This will also make it easier to deal with playlist renames and
reordering by the user.
- API
/* Playlist management */
new_playlist();
del_playlist(playlist);
add_to_playlist(playlist, songid);
rm_from_playlist(playlist, songid);
playlist_size(playlist)
set_flag(playlist, flag)
- Flags
PL_ENABLED (1 << 0)
PL_RANDOM (1 << 1)
PL_DRAIN (1 << 2)
Tags:
Tags will be a new feature in Ocarina 6 and will be a more generic way
of implementing a banned-songs playlist. Users will be able to create
new tags on the fly and add songs to and from them. I can also use
an SQLite trigger to manage automatic tags.
The following tags will be created by default and will not be
deletable by the user: Artist, Album, Unplayed Songs, Genre
- API
new_tag(name);
del_tag(name);
tag_song(name, songid);
untag_song(name, songid);
set_tag_visible(name, visible);
Archlinux packages:
extra/sqlite