ocarina/core/deck.cpp

243 lines
4.7 KiB
C++

/**
* Copyright 2013 (c) Anna Schumaker.
*/
extern "C" {
#include <core/collection.h>
}
#include <core/deck.h>
#include <core/file.h>
static std::list<TempQueue> queue_deck;
static struct queue recent_queue;
static struct file deck_file;
TempQueue :: TempQueue()
{
queue_init(this, 0, NULL);
}
TempQueue :: TempQueue(bool random, struct queue_ops *ops)
{
unsigned int flags = Q_ENABLED | Q_SAVE_FLAGS | Q_SAVE_SORT;
queue_init(this, flags | (random ? Q_RANDOM : 0), ops);
}
void TempQueue :: write(file &file)
{
file_writef(&file, "%u %zu", q_flags, queue_size(this));
for (unsigned int i = 0; i < queue_size(this); i++)
file_writef(&file, " %u", queue_at(this, i)->tr_dbe.dbe_index);
}
void TempQueue :: read(file &file)
{
unsigned int n, id;
file_readf(&file, "%u %u", &q_flags, &n);
for (unsigned int i = 0; i < n; i++) {
file_readf(&file, "%u", &id);
queue_add(this, track_get(id));
}
}
unsigned int TempQueue :: add(struct track *track)
{
unsigned int res = queue_add(this, track);
deck :: write();
return res;
}
void TempQueue :: del(struct track *track)
{
queue_remove_all(this, track);
deck :: write();
}
void TempQueue :: del(unsigned int id)
{
queue_remove(this, id);
deck :: write();
}
static void upgrade_v0()
{
int random, ascending;
unsigned int num, field;
queue *library = collection_get_queue();
file_readf(&deck_file, "%d %u", &random, &num);
if (random)
queue_set_flag(library, Q_RANDOM);
for (unsigned int i = 0; i < num; i++) {
file_readf(&deck_file, "%u %d", &field, &ascending);
queue_sort(library, (compare_t)field, (i == 0) ? true : false);
if (!ascending)
queue_sort(library, (compare_t)field, false);
}
}
void deck :: init(struct queue_ops *history_ops, struct queue_ops *temp_ops)
{
unsigned int num;
bool upgraded = false;
std::list<TempQueue>::iterator it;
queue_init(&recent_queue, Q_ENABLED | Q_REPEAT | Q_NO_SORT | Q_ADD_FRONT, history_ops);
file_init(&deck_file, "deck", 1);
if (!file_open(&deck_file, OPEN_READ))
return;
if (file_version(&deck_file) == 0) {
upgrade_v0();
upgraded = true;
}
file_readf(&deck_file, "%u", &num);
queue_deck.resize(num);
for (it = queue_deck.begin(); it != queue_deck.end(); it++) {
it->read(deck_file);
it->q_ops = temp_ops;
}
file_close(&deck_file);
if (upgraded)
deck :: write();
}
void deck :: write()
{
std::list<TempQueue>::iterator it;
if (!file_open(&deck_file, OPEN_WRITE))
return;
file_writef(&deck_file, "%zu\n", queue_deck.size());
for (it = queue_deck.begin(); it != queue_deck.end(); it++) {
it->write(deck_file);
file_writef(&deck_file, "\n");
}
file_close(&deck_file);
}
void deck :: save(struct queue *queue, enum queue_flags flag)
{
deck :: write();
}
queue *deck :: create(bool random, struct queue_ops *ops)
{
queue_deck.push_back(TempQueue(random, ops));
return &queue_deck.back();
}
static void _destroy(std::list<TempQueue>::iterator &it)
{
queue_deck.erase(it);
deck :: write();
}
void deck :: destroy(queue *queue)
{
std::list<TempQueue>::iterator it;
for (it = queue_deck.begin(); it != queue_deck.end(); it++) {
if (&(*it) == queue) {
_destroy(it);
return;
}
}
}
void deck :: move(queue *queue, unsigned int index)
{
unsigned int old_pos = deck :: index(queue);
std::list<TempQueue>::iterator it_old = queue_deck.begin();
std::list<TempQueue>::iterator it_new = queue_deck.begin();
for (unsigned int i = 0; i < queue_deck.size(); i++) {
if (i < old_pos)
it_old++;
if (i < index)
it_new++;
}
if (index > old_pos)
it_new++;
queue_deck.splice(it_new, queue_deck, it_old);
write();
}
unsigned int deck :: index(queue *queue)
{
unsigned int i = 0;
std::list<TempQueue>::iterator it;
for (it = queue_deck.begin(); it != queue_deck.end(); it++) {
if (&(*it) == queue)
return i;
i++;
}
return queue_deck.size();
}
queue *deck :: get(unsigned int index)
{
std::list<TempQueue>::iterator it;
for (it = queue_deck.begin(); it != queue_deck.end(); it++) {
if (index == 0)
return &(*it);
index--;
}
return NULL;
}
struct track *deck :: next()
{
struct track *track = NULL;
std::list<TempQueue>::iterator it;
for (it = queue_deck.begin(); it != queue_deck.end(); it++) {
if (queue_has_flag(&(*it), Q_ENABLED) == false)
continue;
track = queue_next(&(*it));
if (queue_size(&(*it)) == 0)
_destroy(it);
break;
}
if (!track)
track = queue_next(collection_get_queue());
if (track) {
queue_remove_all(&recent_queue, track);
queue_add(&recent_queue, track);
_q_iter_set(&recent_queue.q_tracks, &recent_queue.q_cur, 0);
}
return track;
}
struct track *deck :: prev()
{
return queue_next(&recent_queue);
}
std::list<TempQueue> &deck :: get_queues()
{
return queue_deck;
}
queue *deck :: get_queue()
{
return &recent_queue;
}