245 lines
4.7 KiB
C++
245 lines
4.7 KiB
C++
/**
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
*/
|
|
extern "C" {
|
|
#include <core/idle.h>
|
|
}
|
|
#include <core/library.h>
|
|
#include <core/print.h>
|
|
|
|
#include <glib.h>
|
|
|
|
|
|
class LibraryQueue : public queue {
|
|
private:
|
|
file f;
|
|
|
|
public:
|
|
|
|
LibraryQueue()
|
|
{
|
|
file_init(&f, "library.q", 0);
|
|
}
|
|
|
|
void save()
|
|
{
|
|
GSList *cur = q_sort;
|
|
int field;
|
|
|
|
if (!file_open(&f, OPEN_WRITE))
|
|
return;
|
|
|
|
file_writef(&f, "%u %u", q_flags, g_slist_length(q_sort));
|
|
while (cur) {
|
|
field = GPOINTER_TO_INT(cur->data);
|
|
file_writef(&f, " %u %d", abs(field) - 1, field > 0);
|
|
cur = g_slist_next(cur);
|
|
}
|
|
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", &q_flags, &n);
|
|
for (unsigned int i = 0; i < n; i++) {
|
|
file_readf(&f, "%u %d", &field, &ascending);
|
|
queue_sort(this, (compare_t)(field + 1), (i == 0) ? true : false);
|
|
if (ascending == false)
|
|
queue_sort(this, (compare_t)(field + 1), false);
|
|
}
|
|
file_close(&f);
|
|
}
|
|
};
|
|
|
|
static LibraryQueue library_q;
|
|
|
|
struct scan_info {
|
|
struct library *library;
|
|
std :: string path;
|
|
};
|
|
|
|
static void scan_path(void *);
|
|
|
|
|
|
|
|
/*
|
|
* Scanning functions are here
|
|
*/
|
|
static void tag_track(struct library *library, const std::string &filepath)
|
|
{
|
|
struct track *track = track_add(library, filepath.c_str());
|
|
if (track)
|
|
queue_add(&library_q, track);
|
|
}
|
|
|
|
static void process_path(struct library *library, const std :: string &dir,
|
|
const std :: string &name)
|
|
{
|
|
struct scan_info *scan = new struct scan_info;
|
|
scan->library = library;
|
|
scan->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);
|
|
delete scan;
|
|
}
|
|
}
|
|
|
|
static void scan_path(void *data)
|
|
{
|
|
GDir *dir;
|
|
const char *name;
|
|
struct scan_info *scan = (struct scan_info *)data;
|
|
|
|
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();
|
|
g_dir_close(dir);
|
|
delete scan;
|
|
}
|
|
|
|
static void validate_library(void *data)
|
|
{
|
|
struct library *library = (struct library *)data;
|
|
struct db_entry *dbe, *next;
|
|
struct track *track;
|
|
gchar *path;
|
|
|
|
db_for_each(dbe, next, track_db_get()) {
|
|
track = TRACK(dbe);
|
|
if (track->tr_library != library)
|
|
continue;
|
|
|
|
path = track_path(track);
|
|
if (g_file_test(path, G_FILE_TEST_EXISTS) == false) {
|
|
queue_remove_all(&library_q, track);
|
|
track_remove(track);
|
|
}
|
|
g_free(path);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* External API begins here
|
|
*/
|
|
|
|
void collection_init(struct queue_ops *ops)
|
|
{
|
|
struct db_entry *track, *next;
|
|
|
|
queue_init(&library_q, Q_ENABLED | Q_REPEAT | Q_ADD_FRONT, ops);
|
|
|
|
db_for_each(track, next, track_db_get()) {
|
|
if (TRACK(track)->tr_library->li_enabled)
|
|
queue_add(&library_q, TRACK(track));
|
|
}
|
|
queue_unset_flag(&library_q, Q_ADD_FRONT);
|
|
|
|
library_q.load();
|
|
if (!library_q.q_sort) {
|
|
queue_sort(&library_q, COMPARE_ARTIST, true);
|
|
queue_sort(&library_q, COMPARE_YEAR, false);
|
|
queue_sort(&library_q, COMPARE_TRACK, false);
|
|
}
|
|
|
|
queue_set_flag(&library_q, Q_SAVE_SORT);
|
|
queue_set_flag(&library_q, Q_SAVE_FLAGS);
|
|
}
|
|
|
|
void collection :: save(struct queue *queue, enum queue_flags flag)
|
|
{
|
|
library_q.save();
|
|
}
|
|
|
|
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.c_str());
|
|
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 = new struct scan_info;
|
|
scan->library = library;
|
|
|
|
if (library) {
|
|
scan->path = library->li_path;
|
|
idle_schedule(validate_library, library);
|
|
idle_schedule(scan_path, scan);
|
|
}
|
|
}
|
|
|
|
void collection :: update_all()
|
|
{
|
|
struct db_entry *library, *next;
|
|
|
|
db_for_each(library, next, library_db_get())
|
|
update(LIBRARY(library));
|
|
}
|
|
|
|
void collection :: set_enabled(struct library *library, bool enabled)
|
|
{
|
|
struct db_entry *dbe, *next;
|
|
struct track *track;
|
|
|
|
if (!library || (library->li_enabled == enabled))
|
|
return;
|
|
|
|
library_set_enabled(library, enabled);
|
|
queue_set_flag(&library_q, Q_ADD_FRONT);
|
|
|
|
db_for_each(dbe, next, track_db_get()) {
|
|
track = TRACK(dbe);
|
|
if (track->tr_library == library) {
|
|
if (enabled)
|
|
queue_add(&library_q, track);
|
|
else
|
|
queue_remove_all(&library_q, track);
|
|
}
|
|
}
|
|
|
|
queue_unset_flag(&library_q, Q_ADD_FRONT);
|
|
queue_resort(&library_q);
|
|
}
|
|
|
|
queue *collection :: get_queue()
|
|
{
|
|
return &library_q;
|
|
}
|