/** * Copyright 2013 (c) Anna Schumaker. */ #include #include #include static std::list 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::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::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::iterator &it) { queue_deck.erase(it); deck :: write(); } void deck :: destroy(queue *queue) { std::list::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::iterator it_old = queue_deck.begin(); std::list::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::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::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::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 &deck :: get_queues() { return queue_deck; } queue *deck :: get_queue() { return &recent_queue; }