ocarina/core/library.cpp

219 lines
4.0 KiB
C++

/**
* Copyright 2013 (c) Anna Schumaker.
*/
#include <core/idle.h>
#include <core/library.h>
#include <core/print.h>
#include <glib.h>
class LibraryQueue : public Queue {
private:
file f;
public:
LibraryQueue() : Queue(Q_ENABLED | Q_REPEAT)
{
file_init(&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;
file_open(&f, OPEN_WRITE);
file_writef(&f, "%u %u", _flags, _sort_order.size());
for (it = _sort_order.begin(); it != _sort_order.end(); it++)
file_writef(&f, " %u %d", it->field, it->ascending);
file_writef(&f, "\n");
file_close(&f);
}
void load()
{
unsigned int field;
int ascending;
unsigned int n;
if (!file_open(&f, OPEN_READ))
return;
file_readf(&f, "%u %u", &_flags, &n);
for (unsigned int i = 0; i < n; i++) {
file_readf(&f, "%u %d", &field, &ascending);
Queue :: sort((sort_t)field, (i == 0) ? true : false);
if (ascending == false)
Queue :: sort((sort_t)field, false);
}
file_close(&f);
}
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 {
struct library *library;
std :: string path;
};
static void scan_path(struct scan_info &);
/*
* Scanning functions are here
*/
static void tag_track(struct library *library, const std::string &filepath)
{
struct track *track = track_add(library, filepath);
if (track)
library_q.add(track);
}
static void process_path(struct 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
tag_track(library, scan.path);
}
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);
}
track_db_commit();
}
static void validate_library(struct library *&library)
{
struct track *track, *next;
db_for_each(track, next, track_db_get()) {
if (track->tr_library != library)
continue;
if (g_file_test(track_path(track).c_str(), G_FILE_TEST_EXISTS) == false) {
library_q.del(track);
track_remove(track);
}
}
}
/*
* External API begins here
*/
void collection :: init()
{
struct track *track, *next;
library_q.load();
db_for_each(track, next, track_db_get()) {
if (track->tr_library->li_enabled)
library_q.add(track);
}
}
struct library *collection :: add(const std::string &dir)
{
struct library *library = NULL;
if (g_file_test(dir.c_str(), G_FILE_TEST_IS_DIR) == false)
return library;
library = library_find(dir);
if (library)
update(library);
return library;
}
void collection :: remove(struct library *library)
{
if (library) {
set_enabled(library, false);
track_remove_all(library);
library_remove(library);
}
}
void collection :: update(struct library *library)
{
struct scan_info scan = {
.library = library,
};
if (library) {
scan.path = library->primary_key();
idle :: schedule(validate_library, library);
idle :: schedule(scan_path, scan);
}
}
void collection :: update_all()
{
struct library *library, *next;
db_for_each(library, next, library_db_get())
update(library);
}
void collection :: set_enabled(struct library *library, bool enabled)
{
struct track *track, *next;
if (!library || (library->li_enabled == enabled))
return;
library_set_enabled(library, enabled);
db_for_each(track, next, track_db_get()) {
if (track->tr_library == library) {
if (enabled)
library_q.add(track);
else
library_q.del(track);
}
}
}
Queue *collection :: get_queue()
{
return &library_q;
}