2013-05-13 23:13:54 -04:00
|
|
|
===============================================================================
|
|
|
|
= =
|
|
|
|
= 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.
|
|
|
|
|
2013-05-26 11:08:41 -04:00
|
|
|
I will also create unit tests as I add features so bugs can be found faster.
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-13 23:13:54 -04:00
|
|
|
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
|
|
|
|
|
2013-05-26 11:08:41 -04:00
|
|
|
|
|
|
|
|
2013-05-13 23:13:54 -04:00
|
|
|
Files:
|
2013-05-26 11:08:41 -04:00
|
|
|
ocarina/
|
|
|
|
design.txt
|
|
|
|
ocarina/gui/
|
|
|
|
ocarina/include/
|
|
|
|
library.h
|
|
|
|
playlist.h
|
|
|
|
ocarina/lib/
|
|
|
|
library.cpp
|
|
|
|
playlist.cpp
|
|
|
|
ocarina/tests/
|
|
|
|
|
2013-05-13 23:13:54 -04:00
|
|
|
$HOME/.ocarina{-debug}/ocarina.db
|
|
|
|
|
2013-05-26 11:08:41 -04:00
|
|
|
|
|
|
|
|
2013-05-13 23:13:54 -04:00
|
|
|
Database: (ocarina.db)
|
|
|
|
Paths -
|
|
|
|
create table if not exists paths(
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
2013-05-26 11:08:41 -04:00
|
|
|
dirpath TEXT UNIQUE, /* root path of library */
|
2013-05-13 23:13:54 -04:00
|
|
|
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 */
|
|
|
|
);
|
|
|
|
|
2013-05-26 11:08:41 -04:00
|
|
|
<Research FTS tables and inverted indexes for filtering>
|
2013-05-13 23:13:54 -04:00
|
|
|
|
2013-05-26 11:08:41 -04:00
|
|
|
Tags index -
|
|
|
|
<another FTS table>
|
|
|
|
Tag Name -> song ids
|
2013-05-13 23:13:54 -04:00
|
|
|
|
|
|
|
User settings -
|
|
|
|
create table if not exists config(
|
|
|
|
name PRIMARY KEY,
|
|
|
|
value INT,
|
|
|
|
);
|
|
|
|
|
2013-05-26 11:08:41 -04:00
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
2013-05-13 23:13:54 -04:00
|
|
|
Archlinux packages:
|
|
|
|
extra/sqlite
|