2008-10-21 13:22:46 UTC
previous
next
/* Echo Media Player
* Copyright (C) 2008 Shane O'Connell
*
* [ The original file includes a copyright header in this location describing
* the file as being released under the terms of the GNU General Public
* License. It has been removed in order to display the file as part of the
* archive. ]
*/
#include "Database.h"
#include <sys/stat.h>
#include <giomm.h>
#include <cstdlib>
#include <cassert>
#include <iostream>
using namespace std;
Database* Database::m_instance = 0;
void Database::init()
{
assert(!m_instance);
m_instance = new Database();
SQLstmt stmt;
m_instance->db.prepare(stmt,
"SELECT LibraryID, LibraryName, LibraryIcon "
"FROM Libraries ORDER BY LibraryID");
while (stmt.step()) {
m_instance->m_libraries.push_back(LibraryRef(new Library(
stmt.get_column_int(0),
stmt.get_column_text(1),
stmt.get_column_text(2))));
}
}
Database::Database()
{
// TODO handle various Gio errors
Glib::RefPtr<Gio::File> db_file;
char* xdg_config_dir_env = getenv("XDG_CONFIG_HOME");
if (xdg_config_dir_env)
db_file = Gio::File::create_for_path(xdg_config_dir_env);
if (!xdg_config_dir_env || !db_file->query_exists() || !db_file->is_native()) {
char* home_dir_env = getenv("HOME");
assert(home_dir_env != NULL); // TODO show a friendly error message instead of this
db_file = Gio::File::create_for_path(home_dir_env);
assert(db_file->query_exists() && db_file->is_native()); // TODO show a better error message
db_file = db_file->get_child(".config");
}
if (!db_file->query_exists()) {
db_file->make_directory();
chmod(db_file->get_path().c_str(), 0700);
}
db_file = db_file->get_child("echo");
if (!db_file->query_exists()) {
db_file->make_directory();
chmod(db_file->get_path().c_str(), 0700);
}
db_file = db_file->get_child("echo.db");
bool new_db = !db_file->query_exists();
db.open(db_file->get_path());
if (new_db)
chmod(db_file->get_path().c_str(), 0600);
db.run("CREATE TEMPORARY TABLE MemoryPlaylists ("
" PlaylistID INTEGER PRIMARY KEY,"
" PlaylistName TEXT"
")");
db.run("CREATE TEMPORARY TABLE MemoryPlaylistTracks ("
" PlaylistID INTEGER,"
" PlaylistIndex INTEGER,"
" ArtistName TEXT,"
" AlbumName TEXT,"
" AlbumReleaseDate INTEGER,"
" TrackName TEXT,"
" TrackNumber INTEGER,"
" TrackURI TEXT UNIQUE"
")");
db.run("CREATE TABLE IF NOT EXISTS Config ("
" Name TEXT,"
" Value TEXT"
")");
db.run("CREATE TABLE IF NOT EXISTS Artists ("
" ArtistID INTEGER PRIMARY KEY,"
" ArtistName TEXT UNIQUE"
")");
db.prepare(m_get_artist_id_stmt, "SELECT ArtistID FROM Artists WHERE ArtistName = ?");
db.prepare(m_add_artist_id_stmt, "INSERT INTO Artists (ArtistName) VALUES(?)");
db.run("CREATE TABLE IF NOT EXISTS Albums ("
" AlbumID INTEGER PRIMARY KEY,"
" ArtistID INTEGER,"
" AlbumName TEXT,"
" AlbumReleaseDate INTEGER"
")");
db.prepare(m_get_album_id_stmt, "SELECT AlbumID FROM Albums WHERE ArtistID = ? AND AlbumName = ?");
db.prepare(m_add_album_id_stmt, "INSERT INTO Albums (ArtistID, AlbumName) VALUES(?,?)");
db.run("CREATE TABLE IF NOT EXISTS Tracks ("
" TrackID INTEGER PRIMARY KEY,"
" AlbumID INTEGER,"
" TrackName TEXT,"
" TrackNumber INTEGER,"
" TrackRating INTEGER,"
" TrackURI TEXT UNIQUE ON CONFLICT REPLACE"
")");
db.prepare(m_get_track_id_stmt, "SELECT TrackID FROM Tracks WHERE TrackURI = ?");
//m_add_track_id_stmt = m_db.prepare("INSERT INTO Albums (ArtistID, AlbumName) VALUES(?,?)");
db.run("CREATE TABLE IF NOT EXISTS Libraries ("
" LibraryID INTEGER PRIMARY KEY,"
" LibraryName TEXT,"
" LibraryIcon TEXT,"
" LibraryURI TEXT"
")");
if (get_row_count("Libraries") == 0) {
db.run("INSERT INTO Libraries (LibraryName, LibraryIcon, LibraryURI) "
"VALUES('Music Library', 'audio-x-generic', 'file:/home/shane/library/music/albums')");
db.run("INSERT INTO Libraries (LibraryName, LibraryIcon, LibraryURI) "
"VALUES('Video Library', 'video-x-generic', 'file:/home/shane/library/television')");
}
db.run("CREATE TABLE IF NOT EXISTS LibraryTracks ("
" LibraryID INTEGER,"
" TrackID INTEGER,"
" UNIQUE(LibraryID, TrackID) ON CONFLICT REPLACE"
")");
db.run("CREATE TABLE IF NOT EXISTS Playlists ("
" PlaylistID INTEGER PRIMARY KEY,"
" PlaylistName TEXT"
")");
db.run("CREATE TABLE IF NOT EXISTS PlaylistTracks ("
" PlaylistID INTEGER,"
" TrackID INTEGER,"
" PlaylistOrder INTEGER"
")");
SQLstmt stmt;
db.prepare(stmt, "SELECT ArtistID, ArtistName FROM Artists");
while (stmt.step())
m_artist_id_lookup[stmt.get_column_int(0)] = StringRef(
new Glib::ustring(stmt.get_column_text(1)));
db.prepare(stmt, "SELECT AlbumID, AlbumName FROM Albums");
while (stmt.step())
m_album_id_lookup[stmt.get_column_int(0)] = StringRef(
new Glib::ustring(stmt.get_column_text(1)));
}
int Database::get_row_count(const Glib::ustring& table)
{
SQLstmt stmt;
db.prepare(stmt, Glib::ustring::compose("SELECT COUNT(*) FROM %1", table));
bool is_row = stmt.step();
assert(is_row);
return stmt.get_column_int(0);
}
long long Database::get_artist_id(const Glib::ustring& artist_name)
{
m_get_artist_id_stmt.bind(1, artist_name);
if (m_get_artist_id_stmt.step()) {
long long artist_id = m_get_artist_id_stmt.get_column_int(0);
m_get_artist_id_stmt.reset();
return artist_id;
}
else {
m_get_artist_id_stmt.reset();
m_add_artist_id_stmt.bind(1, artist_name);
m_add_artist_id_stmt.step();
m_add_artist_id_stmt.reset();
return db.last_rowid();
}
}
long long Database::get_album_id(long long artist_id, const Glib::ustring& album_name)
{
m_get_album_id_stmt.bind(1, artist_id);
m_get_album_id_stmt.bind(2, album_name);
if (m_get_album_id_stmt.step()) {
long long album_id = m_get_album_id_stmt.get_column_int(0);
m_get_album_id_stmt.reset();
return album_id;
}
else {
m_get_album_id_stmt.reset();
m_add_album_id_stmt.bind(1, artist_id);
m_add_album_id_stmt.bind(2, album_name);
m_add_album_id_stmt.step();
m_add_album_id_stmt.reset();
return db.last_rowid();
}
}
long long Database::get_track_id(const Glib::ustring& uri)
{
m_get_track_id_stmt.bind(1, uri);
if (m_get_track_id_stmt.step()) {
long long track_id = m_get_track_id_stmt.get_column_int(0);
m_get_track_id_stmt.reset();
return track_id;
}
else {
m_get_track_id_stmt.reset();
return -1;
}
}