2014-10-17 09:42:45 -04:00
|
|
|
/**
|
2013-12-31 15:44:44 -05:00
|
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
|
|
*/
|
2014-06-05 10:19:22 -04:00
|
|
|
#include <core/queue.h>
|
2015-09-09 09:00:17 -04:00
|
|
|
extern "C" {
|
2014-06-05 10:19:22 -04:00
|
|
|
#include <core/random.h>
|
2015-09-09 09:00:17 -04:00
|
|
|
}
|
2015-01-29 08:27:25 -05:00
|
|
|
#include <core/string.h>
|
2014-01-22 21:17:51 -05:00
|
|
|
|
2014-01-26 13:44:25 -05:00
|
|
|
#include <algorithm>
|
2014-01-22 21:17:51 -05:00
|
|
|
#include <sstream>
|
|
|
|
|
2013-12-31 15:44:44 -05:00
|
|
|
|
2015-04-03 10:30:46 -04:00
|
|
|
static class DefaultNotifier : public QNotifier {
|
|
|
|
public:
|
|
|
|
DefaultNotifier() {};
|
2015-04-03 12:24:26 -04:00
|
|
|
void on_track_added(unsigned int pos) {};
|
|
|
|
void on_track_removed(unsigned int pos) {};
|
2015-04-03 20:54:45 -04:00
|
|
|
void on_track_updated(unsigned int pos) {};
|
2015-04-03 10:30:46 -04:00
|
|
|
} def_notify;
|
|
|
|
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
queue :: queue(unsigned int flags)
|
|
|
|
: q_cur(-1), q_flags(flags), q_length(0), q_notify(&def_notify)
|
2014-12-09 08:39:04 -05:00
|
|
|
{}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
queue :: queue()
|
|
|
|
: q_cur(-1), q_flags(0), q_length(0), q_notify(&def_notify)
|
2014-12-09 08:39:04 -05:00
|
|
|
{}
|
2013-12-31 15:44:44 -05:00
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
queue :: ~queue()
|
2015-04-09 09:15:06 -04:00
|
|
|
{}
|
2013-12-31 15:44:44 -05:00
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
void queue :: write(file &file)
|
2013-12-31 15:44:44 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
file_writef(&file, "%u %zu", q_flags, q_tracks.size());
|
|
|
|
for (unsigned int i = 0; i < q_tracks.size(); i++)
|
|
|
|
file_writef(&file, " %u", q_tracks[i]->tr_dbe.dbe_index);
|
2013-12-31 15:44:44 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
void queue :: read(file &file)
|
2013-12-31 15:44:44 -05:00
|
|
|
{
|
2014-04-13 12:26:32 -04:00
|
|
|
unsigned int n, id;
|
2015-11-16 09:12:15 -05:00
|
|
|
file_readf(&file, "%u %u", &q_flags, &n);
|
|
|
|
q_tracks.resize(n);
|
2014-04-13 12:26:32 -04:00
|
|
|
for (unsigned int i = 0; i < n; i++) {
|
2015-10-08 11:16:38 -04:00
|
|
|
file_readf(&file, "%u", &id);
|
2015-11-16 09:12:15 -05:00
|
|
|
q_tracks[i] = track_get(id);
|
|
|
|
q_length += q_tracks[i]->tr_length;
|
2014-04-13 12:26:32 -04:00
|
|
|
}
|
2013-12-31 15:44:44 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
void queue :: set_flag(queue_flags flag)
|
2013-12-31 15:44:44 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
q_flags |= flag;
|
2013-12-31 15:44:44 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
void queue :: unset_flag(queue_flags flag)
|
2013-12-31 15:44:44 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
q_flags &= ~flag;
|
2013-12-31 15:44:44 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
bool queue :: has_flag(queue_flags flag)
|
2014-01-02 21:58:18 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
return (q_flags & flag) == (unsigned int)flag;
|
2014-01-02 21:58:18 -05:00
|
|
|
}
|
|
|
|
|
2015-10-24 19:34:45 -04:00
|
|
|
static bool track_less_than(struct track *lhs, struct track *rhs,
|
2014-05-18 14:11:21 -04:00
|
|
|
std::vector<struct sort_info> &order)
|
2014-01-26 12:12:01 -05:00
|
|
|
{
|
|
|
|
int res;
|
2014-01-25 14:43:51 -05:00
|
|
|
|
2014-05-18 14:11:21 -04:00
|
|
|
for (unsigned int i = 0; i < order.size(); i++) {
|
|
|
|
if (order[i].ascending == true)
|
2014-11-28 10:28:15 -05:00
|
|
|
res = track_compare(lhs, rhs, order[i].field);
|
2014-01-26 14:44:56 -05:00
|
|
|
else
|
2014-11-28 10:28:15 -05:00
|
|
|
res = track_compare(rhs, lhs, order[i].field);
|
2014-05-18 14:11:21 -04:00
|
|
|
if (res == 0)
|
|
|
|
continue;
|
|
|
|
break;
|
2014-01-26 12:12:01 -05:00
|
|
|
}
|
2014-05-18 14:11:21 -04:00
|
|
|
return res < 0;
|
2014-01-25 14:43:51 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
unsigned int queue :: find_sorted_id(struct track *rhs)
|
2014-01-25 14:43:51 -05:00
|
|
|
{
|
2015-10-24 19:34:45 -04:00
|
|
|
struct track *lhs;
|
2015-11-16 09:12:15 -05:00
|
|
|
unsigned int begin = 0, end = (q_tracks.size() - 1), mid;
|
2014-01-25 14:43:51 -05:00
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
if (q_tracks.size() == 0)
|
2014-01-27 11:22:35 -05:00
|
|
|
return 0;
|
2014-01-26 10:41:13 -05:00
|
|
|
|
2014-01-28 09:42:38 -05:00
|
|
|
while (end > begin) {
|
|
|
|
mid = begin + ((end - begin) / 2);
|
2015-11-16 09:12:15 -05:00
|
|
|
lhs = q_tracks[mid];
|
|
|
|
if (track_less_than(lhs, rhs, q_sort))
|
2014-01-28 09:42:38 -05:00
|
|
|
begin = mid + 1;
|
|
|
|
else {
|
|
|
|
if (mid == begin)
|
|
|
|
return begin;
|
|
|
|
else
|
|
|
|
end = mid - 1;
|
2014-01-27 11:22:35 -05:00
|
|
|
}
|
2014-01-27 10:23:22 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
lhs = q_tracks[begin];
|
|
|
|
if (track_less_than(lhs, rhs, q_sort))
|
2014-01-28 09:42:38 -05:00
|
|
|
return begin + 1;
|
|
|
|
return begin;
|
2014-01-25 14:43:51 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
unsigned int queue :: _add_at(struct track *track, unsigned int pos)
|
2013-12-31 15:44:44 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
q_tracks.insert(q_tracks.begin() + pos, track);
|
|
|
|
q_length += track->tr_length;
|
|
|
|
q_notify->on_track_added(pos);
|
2014-05-11 10:53:48 -04:00
|
|
|
return pos;
|
2013-12-31 15:44:44 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
unsigned int queue :: add(struct track *track)
|
2014-01-02 21:58:18 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
unsigned int id = q_tracks.size();
|
|
|
|
if (q_sort.size() > 0)
|
2014-05-11 10:53:48 -04:00
|
|
|
id = find_sorted_id(track);
|
|
|
|
return _add_at(track, id);
|
2014-01-02 21:58:18 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
void queue :: del(unsigned int index)
|
2013-12-31 15:44:44 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
q_length -= q_tracks[index]->tr_length;
|
|
|
|
q_tracks.erase(q_tracks.begin() + index);
|
|
|
|
q_notify->on_track_removed(index);
|
2015-11-19 08:08:14 -05:00
|
|
|
|
|
|
|
if (q_cur == index)
|
|
|
|
q_cur--;
|
2013-12-31 15:44:44 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
void queue :: del(struct track *track)
|
2014-01-16 22:05:36 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
for (unsigned int i = 0; i < q_tracks.size(); i++) {
|
|
|
|
while ((i < q_tracks.size()) && (q_tracks[i] == track))
|
2014-12-09 08:48:27 -05:00
|
|
|
del(i);
|
|
|
|
}
|
2014-01-16 22:05:36 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
void queue :: updated(struct track *track)
|
2014-01-29 22:45:01 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
for (unsigned int i = 0; i < q_tracks.size(); i++) {
|
|
|
|
if (q_tracks[i] == track)
|
|
|
|
q_notify->on_track_updated(i);
|
2014-01-29 22:45:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-19 08:08:14 -05:00
|
|
|
void queue_selected(struct queue *queue, unsigned int index)
|
|
|
|
{
|
|
|
|
queue->q_cur = index;
|
|
|
|
if (queue->has_flag(Q_REPEAT) == false)
|
|
|
|
queue->del(index);
|
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
struct track *queue :: next()
|
2014-05-18 11:08:58 -04:00
|
|
|
{
|
2015-10-24 19:34:45 -04:00
|
|
|
struct track *res;
|
2014-05-18 11:08:58 -04:00
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
if (!(q_flags & Q_ENABLED))
|
2015-11-13 11:14:40 -05:00
|
|
|
return NULL;
|
2015-11-16 09:12:15 -05:00
|
|
|
else if (q_tracks.size() == 0)
|
2014-05-18 11:08:58 -04:00
|
|
|
return NULL;
|
2015-11-16 09:12:15 -05:00
|
|
|
else if (q_tracks.size() == 1)
|
|
|
|
q_cur = 0;
|
|
|
|
else if (q_flags & Q_RANDOM)
|
|
|
|
q_cur += random_range(1, q_tracks.size() / 2);
|
2014-05-18 11:08:58 -04:00
|
|
|
else
|
2015-11-16 09:12:15 -05:00
|
|
|
q_cur++;
|
2014-05-18 11:08:58 -04:00
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
q_cur %= q_tracks.size();
|
|
|
|
res = q_tracks[q_cur];
|
2015-11-19 08:08:14 -05:00
|
|
|
queue_selected(this, q_cur);
|
2014-05-18 11:08:58 -04:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
unsigned int queue :: size()
|
2013-12-31 15:44:44 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
return q_tracks.size();
|
2013-12-31 15:44:44 -05:00
|
|
|
}
|
|
|
|
|
2014-01-26 13:44:25 -05:00
|
|
|
class SortTracks {
|
|
|
|
public:
|
2014-05-18 14:11:21 -04:00
|
|
|
std::vector<struct sort_info> fields;
|
|
|
|
SortTracks(std::vector<sort_info> f) : fields(f) {}
|
2015-10-24 19:34:45 -04:00
|
|
|
bool operator()(struct track *lhs, struct track *rhs)
|
2014-01-26 13:44:25 -05:00
|
|
|
{
|
|
|
|
return track_less_than(lhs, rhs, fields);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
void queue :: sort(compare_t field, bool reset)
|
2014-01-26 12:12:01 -05:00
|
|
|
{
|
2014-05-18 14:11:21 -04:00
|
|
|
bool found = false;
|
|
|
|
struct sort_info info = { field, true };
|
2014-01-26 14:44:56 -05:00
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
if (q_flags & Q_NO_SORT)
|
2014-01-26 14:49:07 -05:00
|
|
|
return;
|
2014-05-18 14:11:21 -04:00
|
|
|
if (reset)
|
2015-11-16 09:12:15 -05:00
|
|
|
q_sort.clear();
|
2014-05-18 14:11:21 -04:00
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
for (unsigned int i = 0; i < q_sort.size(); i++) {
|
|
|
|
if (q_sort[i].field == info.field) {
|
|
|
|
q_sort[i].ascending = !q_sort[i].ascending;
|
2014-05-18 14:11:21 -04:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found)
|
2015-11-16 09:12:15 -05:00
|
|
|
q_sort.push_back(info);
|
2014-01-26 14:49:07 -05:00
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
std::stable_sort(q_tracks.begin(), q_tracks.end(), SortTracks(q_sort));
|
2014-01-26 14:44:56 -05:00
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
for (unsigned int i = 0; i < q_tracks.size(); i++)
|
|
|
|
q_notify->on_track_updated(i);
|
2014-01-26 12:12:01 -05:00
|
|
|
}
|
|
|
|
|
2015-11-16 09:12:15 -05:00
|
|
|
struct track *queue :: operator[](unsigned int index)
|
2014-01-20 19:06:52 -05:00
|
|
|
{
|
2015-11-16 09:12:15 -05:00
|
|
|
return q_tracks[index];
|
2014-01-20 19:06:52 -05:00
|
|
|
}
|