ocarina/core/library.cpp

219 lines
4.0 KiB
C++

/*
* Copyright 2013 (c) Anna Schumaker.
*/
#include <core/idle.h>
#include <core/library.h>
#include <glib.h>
class LibraryQueue : public Queue {
private:
File f;
public:
LibraryQueue() : Queue(Q_ENABLED | Q_REPEAT), f("library.q", 0)
{
Queue :: sort(SORT_ARTIST, true);
Queue :: sort(SORT_YEAR, false);
Queue :: sort(SORT_TRACK, false);
}
void save()
{
std::vector<struct sort_info>::iterator it;
f.open(OPEN_WRITE);
f << _flags << " " << _sort_order.size();
for (it = _sort_order.begin(); it != _sort_order.end(); it++)
f << " " << it->field << " " << it->ascending;
f << std::endl;
f.close();
}
void load()
{
unsigned int field;
bool ascending;
unsigned int n;
if (!f.open(OPEN_READ))
return;
f >> _flags >> n;
for (unsigned int i = 0; i < n; i++) {
f >> field >> ascending;
Queue :: sort((sort_t)field, (i == 0) ? true : false);
if (ascending == false)
Queue :: sort((sort_t)field, false);
}
}
void set_flag(queue_flags f) { Queue :: set_flag(f); save(); }
void unset_flag(queue_flags f) { Queue :: unset_flag(f); save(); }
void sort(sort_t field, bool ascending)
{
Queue :: sort(field, ascending);
save();
};
};
static LibraryQueue library_q;
struct scan_info {
Library *library;
std :: string path;
};
static void scan_path(struct scan_info &);
/*
* Scanning functions are here
*/
static void process_path(Library *library, const std :: string &dir,
const std :: string &name)
{
struct scan_info scan = {
.library = library,
.path = dir + "/" + name,
};
if (g_file_test(scan.path.c_str(), G_FILE_TEST_IS_DIR) == true)
idle :: schedule (scan_path, scan);
else {
Track *track = tagdb :: add_track(scan.path, library);
if (track)
library_q.add(track);
}
}
static void scan_path(struct scan_info &scan)
{
GDir *dir;
const char *name;
dir = g_dir_open(scan.path.c_str(), 0, NULL);
if (dir == NULL)
return;
name = g_dir_read_name(dir);
while (name != NULL) {
process_path(scan.library, scan.path, name);
name = g_dir_read_name(dir);
}
tagdb :: commit();
}
static void validate_library(Library *&library)
{
Track *track;
Database<Track>::iterator it;
Database<Track> *db = &tagdb :: get_track_db();
for (it = db->begin(); it != db->end(); it = db->next(it)) {
track = *it;
if (track->library != library)
continue;
if (g_file_test(track->path().c_str(), G_FILE_TEST_EXISTS) == false) {
library_q.del(track);
tagdb :: remove_track(track->id);
}
}
}
/*
* External API begins here
*/
void library :: init()
{
Database<Track>::iterator it;
Database<Track> *db = &tagdb :: get_track_db();
library_q.load();
for (it = db->begin(); it != db->end(); it = db->next(it)) {
if ((*it)->library->enabled)
library_q.add(*it);
}
}
Library *library :: add(const std::string &dir)
{
Library *library = NULL;
if (g_file_test(dir.c_str(), G_FILE_TEST_IS_DIR) == false)
return library;
library = tagdb :: add_library(dir);
if (library)
update(library);
return library;
}
void library :: remove(Library *library)
{
if (library) {
set_enabled(library, false);
tagdb :: remove_library(library->id);
}
}
void library :: update(Library *library)
{
struct scan_info scan = {
.library = library,
};
if (library) {
scan.path = library->root_path;
idle :: schedule(validate_library, library);
idle :: schedule(scan_path, scan);
}
}
void library :: update_all()
{
Database<Library>::iterator it;
Database<Library> *db = &tagdb :: get_library_db();
for (it = db->begin(); it != db->end(); it = db->next(it))
update(*it);
}
void library :: set_enabled(Library *library, bool enabled)
{
Database<Track>::iterator it;
Database<Track> *db = &(tagdb :: get_track_db());
if (!library || (library->enabled == enabled))
return;
library->enabled = enabled;
tagdb :: commit_library();
for (it = db->begin(); it != db->end(); it = db->next(it)) {
if ((*it)->library == library) {
if (enabled)
library_q.add(*it);
else
library_q.del(*it);
}
}
}
Queue *library :: get_queue()
{
return &library_q;
}