From 108242042e684b9d6147aeb97351b823e0a1ed0b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 6 Jan 2013 21:33:58 +0100 Subject: queue: convert all functions to methods --- src/Queue.cxx | 342 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 163 insertions(+), 179 deletions(-) (limited to 'src/Queue.cxx') diff --git a/src/Queue.cxx b/src/Queue.cxx index a8a737540..f64bbf5c9 100644 --- a/src/Queue.cxx +++ b/src/Queue.cxx @@ -23,6 +23,34 @@ #include +queue::queue(unsigned _max_length) + :max_length(_max_length), length(0), + version(1), + items(g_new(struct queue_item, max_length)), + order((unsigned *)g_malloc(sizeof(order[0]) * max_length)), + id_to_position((int *)g_malloc(sizeof(id_to_position[0]) * + max_length * QUEUE_HASH_MULT)), + repeat(false), + single(false), + consume(false), + random(false), + rand(g_rand_new()) +{ + for (unsigned i = 0; i < max_length * QUEUE_HASH_MULT; ++i) + id_to_position[i] = -1; +} + +queue::~queue() +{ + Clear(); + + g_free(items); + g_free(order); + g_free(id_to_position); + + g_rand_free(rand); +} + /** * Generate a non-existing id number. */ @@ -42,15 +70,15 @@ queue_generate_id(const struct queue *queue) } int -queue_next_order(const struct queue *queue, unsigned order) +queue::GetNextOrder(unsigned _order) const { - assert(order < queue->length); + assert(_order < length); - if (queue->single && queue->repeat && !queue->consume) - return order; - else if (order + 1 < queue->length) - return order + 1; - else if (queue->repeat && (order > 0 || !queue->consume)) + if (single && repeat && !consume) + return _order; + else if (_order + 1 < length) + return _order + 1; + else if (repeat && (_order > 0 || !consume)) /* restart at first song */ return 0; else @@ -59,79 +87,77 @@ queue_next_order(const struct queue *queue, unsigned order) } void -queue_increment_version(struct queue *queue) +queue::IncrementVersion() { static unsigned long max = ((uint32_t) 1 << 31) - 1; - queue->version++; + version++; - if (queue->version >= max) { - for (unsigned i = 0; i < queue->length; i++) - queue->items[i].version = 0; + if (version >= max) { + for (unsigned i = 0; i < length; i++) + items[i].version = 0; - queue->version = 1; + version = 1; } } void -queue_modify(struct queue *queue, unsigned order) +queue::ModifyAtOrder(unsigned _order) { - unsigned position; - - assert(order < queue->length); + assert(_order < length); - position = queue->order[order]; - queue->items[position].version = queue->version; + unsigned position = order[_order]; + items[position].version = version; - queue_increment_version(queue); + IncrementVersion(); } void -queue_modify_all(struct queue *queue) +queue::ModifyAll() { - for (unsigned i = 0; i < queue->length; i++) - queue->items[i].version = queue->version; + for (unsigned i = 0; i < length; i++) + items[i].version = version; - queue_increment_version(queue); + IncrementVersion(); } unsigned -queue_append(struct queue *queue, struct song *song, uint8_t priority) +queue::Append(struct song *song, uint8_t priority) { - unsigned id = queue_generate_id(queue); + unsigned id = queue_generate_id(this); - assert(!queue_is_full(queue)); + assert(!IsFull()); - auto &item = queue->items[queue->length]; + auto &item = items[length]; item.song = song_dup_detached(song); item.id = id; - item.version = queue->version; + item.version = version; item.priority = priority; - queue->order[queue->length] = queue->length; - queue->id_to_position[id] = queue->length; + order[length] = length; + id_to_position[id] = length; - ++queue->length; + ++length; return id; } void -queue_swap(struct queue *queue, unsigned position1, unsigned position2) +queue::SwapPositions(unsigned position1, unsigned position2) { struct queue_item tmp; - unsigned id1 = queue->items[position1].id; - unsigned id2 = queue->items[position2].id; + unsigned id1 = items[position1].id; + unsigned id2 = items[position2].id; - tmp = queue->items[position1]; - queue->items[position1] = queue->items[position2]; - queue->items[position2] = tmp; + tmp = items[position1]; + items[position1] = items[position2]; + items[position2] = tmp; - queue->items[position1].version = queue->version; - queue->items[position2].version = queue->version; + items[position1].version = version; + items[position2].version = version; - queue->id_to_position[id1] = position2; - queue->id_to_position[id2] = position1; + id_to_position[id1] = position2; + id_to_position[id2] = position1; } static void @@ -145,79 +171,79 @@ queue_move_song_to(struct queue *queue, unsigned from, unsigned to) } void -queue_move(struct queue *queue, unsigned from, unsigned to) +queue::MovePostion(unsigned from, unsigned to) { - struct queue_item item = queue->items[from]; + struct queue_item item = items[from]; /* move songs to one less in from->to */ for (unsigned i = from; i < to; i++) - queue_move_song_to(queue, i + 1, i); + queue_move_song_to(this, i + 1, i); /* move songs to one more in to->from */ for (unsigned i = from; i > to; i--) - queue_move_song_to(queue, i - 1, i); + queue_move_song_to(this, i - 1, i); /* put song at _to_ */ - queue->id_to_position[item.id] = to; - queue->items[to] = item; - queue->items[to].version = queue->version; + id_to_position[item.id] = to; + items[to] = item; + items[to].version = version; /* now deal with order */ - if (queue->random) { - for (unsigned i = 0; i < queue->length; i++) { - if (queue->order[i] > from && queue->order[i] <= to) - queue->order[i]--; - else if (queue->order[i] < from && - queue->order[i] >= to) - queue->order[i]++; - else if (from == queue->order[i]) - queue->order[i] = to; + if (random) { + for (unsigned i = 0; i < length; i++) { + if (order[i] > from && order[i] <= to) + order[i]--; + else if (order[i] < from && + order[i] >= to) + order[i]++; + else if (from == order[i]) + order[i] = to; } } } void -queue_move_range(struct queue *queue, unsigned start, unsigned end, unsigned to) +queue::MoveRange(unsigned start, unsigned end, unsigned to) { - struct queue_item items[end - start]; + struct queue_item tmp[end - start]; // Copy the original block [start,end-1] for (unsigned i = start; i < end; i++) - items[i - start] = queue->items[i]; + tmp[i - start] = items[i]; // If to > start, we need to move to-start items to start, starting from end for (unsigned i = end; i < end + to - start; i++) - queue_move_song_to(queue, i, start + i - end); + queue_move_song_to(this, i, start + i - end); // If to < start, we need to move start-to items to newend (= end + to - start), starting from to // This is the same as moving items from start-1 to to (decreasing), with start-1 going to end-1 // We have to iterate in this order to avoid writing over something we haven't yet moved for (unsigned i = start - 1; i >= to && i != G_MAXUINT; i--) - queue_move_song_to(queue, i, i + end - start); + queue_move_song_to(this, i, i + end - start); // Copy the original block back in, starting at to. for (unsigned i = start; i< end; i++) { - queue->id_to_position[items[i-start].id] = to + i - start; - queue->items[to + i - start] = items[i-start]; - queue->items[to + i - start].version = queue->version; + id_to_position[tmp[i-start].id] = to + i - start; + items[to + i - start] = tmp[i-start]; + items[to + i - start].version = version; } - if (queue->random) { + if (random) { // Update the positions in the queue. // Note that the ranges for these cases are the same as the ranges of // the loops above. - for (unsigned i = 0; i < queue->length; i++) { - if (queue->order[i] >= end && queue->order[i] < to + end - start) - queue->order[i] -= end - start; - else if (queue->order[i] < start && - queue->order[i] >= to) - queue->order[i] += end - start; - else if (start <= queue->order[i] && queue->order[i] < end) - queue->order[i] += to - start; + for (unsigned i = 0; i < length; i++) { + if (order[i] >= end && order[i] < to + end - start) + order[i] -= end - start; + else if (order[i] < start && + order[i] >= to) + order[i] += end - start; + else if (start <= order[i] && order[i] < end) + order[i] += to - start; } } } @@ -232,8 +258,7 @@ queue_move_order(struct queue *queue, unsigned from_order, unsigned to_order) assert(from_order < queue->length); assert(to_order <= queue->length); - const unsigned from_position = - queue_order_to_position(queue, from_order); + const unsigned from_position = queue->OrderToPosition(from_order); if (from_order < to_order) { for (unsigned i = from_order; i < to_order; ++i) @@ -247,85 +272,54 @@ queue_move_order(struct queue *queue, unsigned from_order, unsigned to_order) } void -queue_delete(struct queue *queue, unsigned position) +queue::DeletePosition(unsigned position) { - struct song *song; - unsigned id, order; + assert(position < length); - assert(position < queue->length); - - song = queue_get(queue, position); + struct song *song = Get(position); assert(!song_in_database(song) || song_is_detached(song)); song_free(song); - id = queue_position_to_id(queue, position); - order = queue_position_to_order(queue, position); + const unsigned id = PositionToId(position); + const unsigned _order = PositionToOrder(position); - --queue->length; + --length; /* release the song id */ - queue->id_to_position[id] = -1; + id_to_position[id] = -1; /* delete song from songs array */ - for (unsigned i = position; i < queue->length; i++) - queue_move_song_to(queue, i + 1, i); + for (unsigned i = position; i < length; i++) + queue_move_song_to(this, i + 1, i); /* delete the entry from the order array */ - for (unsigned i = order; i < queue->length; i++) - queue->order[i] = queue->order[i + 1]; + for (unsigned i = _order; i < length; i++) + order[i] = order[i + 1]; /* readjust values in the order array */ - for (unsigned i = 0; i < queue->length; i++) - if (queue->order[i] > position) - --queue->order[i]; + for (unsigned i = 0; i < length; i++) + if (order[i] > position) + --order[i]; } void -queue_clear(struct queue *queue) +queue::Clear() { - for (unsigned i = 0; i < queue->length; i++) { - struct queue_item *item = &queue->items[i]; + for (unsigned i = 0; i < length; i++) { + struct queue_item *item = &items[i]; assert(!song_in_database(item->song) || song_is_detached(item->song)); song_free(item->song); - queue->id_to_position[item->id] = -1; + id_to_position[item->id] = -1; } - queue->length = 0; -} - -queue::queue(unsigned _max_length) - :max_length(_max_length), length(0), - version(1), - items(g_new(struct queue_item, max_length)), - order((unsigned *)g_malloc(sizeof(order[0]) * max_length)), - id_to_position((int *)g_malloc(sizeof(id_to_position[0]) * - max_length * QUEUE_HASH_MULT)), - repeat(false), - single(false), - consume(false), - random(false), - rand(g_rand_new()) -{ - for (unsigned i = 0; i < max_length * QUEUE_HASH_MULT; ++i) - id_to_position[i] = -1; -} - -queue::~queue() -{ - queue_clear(this); - - g_free(items); - g_free(order); - g_free(id_to_position); - - g_rand_free(rand); + length = 0; } static const struct queue_item * @@ -390,8 +384,7 @@ queue_shuffle_order_range(struct queue *queue, unsigned start, unsigned end) assert(end <= queue->length); for (unsigned i = start; i < end; ++i) - queue_swap_order(queue, i, - g_rand_int_range(queue->rand, i, end)); + queue->SwapOrders(i, g_rand_int_range(queue->rand, i, end)); } /** @@ -399,70 +392,66 @@ queue_shuffle_order_range(struct queue *queue, unsigned start, unsigned end) * priority group. */ void -queue_shuffle_order_range_with_priority(struct queue *queue, - unsigned start, unsigned end) +queue::ShuffleOrderRangeWithPriority(unsigned start, unsigned end) { - assert(queue != NULL); - assert(queue->random); + assert(random); assert(start <= end); - assert(end <= queue->length); + assert(end <= length); if (start == end) return; /* first group the range by priority */ - queue_sort_order_by_priority(queue, start, end); + queue_sort_order_by_priority(this, start, end); /* now shuffle each priority group */ unsigned group_start = start; - uint8_t group_priority = queue_get_order_priority(queue, start); + uint8_t group_priority = queue_get_order_priority(this, start); for (unsigned i = start + 1; i < end; ++i) { - uint8_t priority = queue_get_order_priority(queue, i); + uint8_t priority = queue_get_order_priority(this, i); assert(priority <= group_priority); if (priority != group_priority) { /* start of a new group - shuffle the one that has just ended */ - queue_shuffle_order_range(queue, group_start, i); + queue_shuffle_order_range(this, group_start, i); group_start = i; group_priority = priority; } } /* shuffle the last group */ - queue_shuffle_order_range(queue, group_start, end); + queue_shuffle_order_range(this, group_start, end); } void -queue_shuffle_order(struct queue *queue) +queue::ShuffleOrder() { - queue_shuffle_order_range_with_priority(queue, 0, queue->length); + ShuffleOrderRangeWithPriority(0, length); } static void queue_shuffle_order_first(struct queue *queue, unsigned start, unsigned end) { - queue_swap_order(queue, start, - g_rand_int_range(queue->rand, start, end)); + queue->SwapOrders(start, g_rand_int_range(queue->rand, start, end)); } void -queue_shuffle_order_last(struct queue *queue, unsigned start, unsigned end) +queue::ShuffleOrderLast(unsigned start, unsigned end) { - queue_swap_order(queue, end - 1, - g_rand_int_range(queue->rand, start, end)); + SwapOrders(end - 1, g_rand_int_range(rand, start, end)); } void -queue_shuffle_range(struct queue *queue, unsigned start, unsigned end) +queue::ShuffleRange(unsigned start, unsigned end) { assert(start <= end); - assert(end <= queue->length); + assert(end <= length); for (unsigned i = start; i < end; i++) { - unsigned ri = g_rand_int_range(queue->rand, i, end); - queue_swap(queue, i, ri); + unsigned ri = g_rand_int_range(rand, i, end); + SwapPositions(i, ri); } } @@ -479,7 +468,7 @@ queue_find_priority_order(const struct queue *queue, unsigned start_order, assert(start_order <= queue->length); for (unsigned order = start_order; order < queue->length; ++order) { - const unsigned position = queue_order_to_position(queue, order); + const unsigned position = queue->OrderToPosition(order); const struct queue_item *item = &queue->items[position]; if (item->priority <= priority && order != exclude_order) return order; @@ -498,7 +487,7 @@ queue_count_same_priority(const struct queue *queue, unsigned start_order, assert(start_order <= queue->length); for (unsigned order = start_order; order < queue->length; ++order) { - const unsigned position = queue_order_to_position(queue, order); + const unsigned position = queue->OrderToPosition(order); const struct queue_item *item = &queue->items[position]; if (item->priority != priority) return order - start_order; @@ -508,39 +497,37 @@ queue_count_same_priority(const struct queue *queue, unsigned start_order, } bool -queue_set_priority(struct queue *queue, unsigned position, uint8_t priority, - int after_order) +queue::SetPriority(unsigned position, uint8_t priority, int after_order) { - assert(queue != NULL); - assert(position < queue->length); + assert(position < length); - struct queue_item *item = &queue->items[position]; + struct queue_item *item = &items[position]; uint8_t old_priority = item->priority; if (old_priority == priority) return false; - item->version = queue->version; + item->version = version; item->priority = priority; - if (!queue->random) + if (!random) /* don't reorder if not in random mode */ return true; - unsigned order = queue_position_to_order(queue, position); + unsigned _order = PositionToOrder(position); if (after_order >= 0) { - if (order == (unsigned)after_order) + if (_order == (unsigned)after_order) /* don't reorder the current song */ return true; - if (order < (unsigned)after_order) { + if (_order < (unsigned)after_order) { /* the specified song has been played already - enqueue it only if its priority has just become bigger than the current one's */ const unsigned after_position = - queue_order_to_position(queue, after_order); + OrderToPosition(after_order); const struct queue_item *after_item = - &queue->items[after_position]; + &items[after_position]; if (old_priority > after_item->priority || priority <= after_item->priority) /* priority hasn't become bigger */ @@ -552,44 +539,41 @@ queue_set_priority(struct queue *queue, unsigned position, uint8_t priority, create a new priority group) */ const unsigned before_order = - queue_find_priority_order(queue, after_order + 1, priority, - order); - const unsigned new_order = before_order > order + queue_find_priority_order(this, after_order + 1, priority, + _order); + const unsigned new_order = before_order > _order ? before_order - 1 : before_order; - queue_move_order(queue, order, new_order); + queue_move_order(this, _order, new_order); /* shuffle the song within that priority group */ const unsigned priority_count = - queue_count_same_priority(queue, new_order, priority); + queue_count_same_priority(this, new_order, priority); assert(priority_count >= 1); - queue_shuffle_order_first(queue, new_order, + queue_shuffle_order_first(this, new_order, new_order + priority_count); return true; } bool -queue_set_priority_range(struct queue *queue, - unsigned start_position, unsigned end_position, - uint8_t priority, int after_order) +queue::SetPriorityRange(unsigned start_position, unsigned end_position, + uint8_t priority, int after_order) { - assert(queue != NULL); assert(start_position <= end_position); - assert(end_position <= queue->length); + assert(end_position <= length); bool modified = false; int after_position = after_order >= 0 - ? (int)queue_order_to_position(queue, after_order) + ? (int)OrderToPosition(after_order) : -1; for (unsigned i = start_position; i < end_position; ++i) { after_order = after_position >= 0 - ? (int)queue_position_to_order(queue, after_position) + ? (int)PositionToOrder(after_position) : -1; - modified |= queue_set_priority(queue, i, priority, - after_order); + modified |= SetPriority(i, priority, after_order); } return modified; -- cgit v1.2.3