Ejemplo n.º 1
0
enum playlist_result
playlist_move_range(struct playlist *playlist,
		    unsigned start, unsigned end, int to)
{
	const struct song *queued;
	int currentSong;

	if (!queue_valid_position(&playlist->queue, start) ||
		!queue_valid_position(&playlist->queue, end - 1))
		return PLAYLIST_RESULT_BAD_RANGE;

	if ((to >= 0 && to + end - start - 1 >= queue_length(&playlist->queue)) ||
	    (to < 0 && abs(to) > (int)queue_length(&playlist->queue)))
		return PLAYLIST_RESULT_BAD_RANGE;

	if ((int)start == to)
		/* nothing happens */
		return PLAYLIST_RESULT_SUCCESS;

	queued = playlist_get_queued_song(playlist);

	/*
	 * (to < 0) => move to offset from current song
	 * (-playlist.length == to) => move to position BEFORE current song
	 */
	currentSong = playlist->current >= 0
		? (int)queue_order_to_position(&playlist->queue,
					      playlist->current)
		: -1;
	if (to < 0 && playlist->current >= 0) {
		if (start <= (unsigned)currentSong && (unsigned)currentSong <= end)
			/* no-op, can't be moved to offset of itself */
			return PLAYLIST_RESULT_SUCCESS;
		to = (currentSong + abs(to)) % queue_length(&playlist->queue);
		if (start < (unsigned)to)
			to--;
	}

	queue_move_range(&playlist->queue, start, end, to);

	if (!playlist->queue.random) {
		/* update current/queued */
		if ((int)start <= playlist->current &&
		    (unsigned)playlist->current < end)
			playlist->current += to - start;
		else if (playlist->current >= (int)end &&
			 playlist->current <= to) {
			playlist->current -= end - start;
		} else if (playlist->current >= to &&
			   playlist->current < (int)start) {
			playlist->current += end - start;
		}
	}

	playlist_increment_version(playlist);

	playlist_update_queued_song(playlist, queued);

	return PLAYLIST_RESULT_SUCCESS;
}
Ejemplo n.º 2
0
enum playlist_result
playlist_delete_range(struct playlist *playlist, unsigned start, unsigned end)
{
	const struct song *queued;

	if (start >= queue_length(&playlist->queue))
		return PLAYLIST_RESULT_BAD_RANGE;

	if (end > queue_length(&playlist->queue))
		end = queue_length(&playlist->queue);

	if (start >= end)
		return PLAYLIST_RESULT_SUCCESS;

	queued = playlist_get_queued_song(playlist);

	do {
		playlist_delete_internal(playlist, --end, &queued);
	} while (end != start);

	playlist_increment_version(playlist);
	playlist_update_queued_song(playlist, queued);

	return PLAYLIST_RESULT_SUCCESS;
}
Ejemplo n.º 3
0
void
playlist_set_single(struct playlist *playlist, bool status)
{
	if (status == playlist->queue.single)
		return;

	playlist->queue.single = status;

	/* if the last song is currently being played, the "next song"
	   might change when single mode is toggled */
	playlist_update_queued_song(playlist,
				    playlist_get_queued_song(playlist));

	idle_add(IDLE_OPTIONS);
}
Ejemplo n.º 4
0
enum playlist_result
playlist_delete(struct playlist *playlist, unsigned song)
{
	const struct song *queued;

	if (song >= queue_length(&playlist->queue))
		return PLAYLIST_RESULT_BAD_RANGE;

	queued = playlist_get_queued_song(playlist);

	playlist_delete_internal(playlist, song, &queued);

	playlist_increment_version(playlist);
	playlist_update_queued_song(playlist, queued);

	return PLAYLIST_RESULT_SUCCESS;
}
Ejemplo n.º 5
0
void
playlist_shuffle(struct playlist *playlist, struct player_control *pc,
		 unsigned start, unsigned end)
{
	const struct song *queued;

	if (end > queue_length(&playlist->queue))
		/* correct the "end" offset */
		end = queue_length(&playlist->queue);

	if ((start+1) >= end)
		/* needs at least two entries. */
		return;

	queued = playlist_get_queued_song(playlist);
	if (playlist->playing && playlist->current >= 0) {
		unsigned current_position;
		current_position = queue_order_to_position(&playlist->queue,
	                                                   playlist->current);

		if (current_position >= start && current_position < end)
		{
			/* put current playing song first */
			queue_swap(&playlist->queue, start, current_position);

			if (playlist->queue.random) {
				playlist->current =
					queue_position_to_order(&playlist->queue, start);
			} else
				playlist->current = start;

			/* start shuffle after the current song */
			start++;
		}
	} else {
		/* no playback currently: reset playlist->current */

		playlist->current = -1;
	}

	queue_shuffle_range(&playlist->queue, start, end);

	playlist_increment_version(playlist);

	playlist_update_queued_song(playlist, pc, queued);
}
enum playlist_result
playlist_seek_song(struct playlist *playlist, struct player_control *pc,
		   unsigned song, float seek_time)
{
	const struct song *queued;
	unsigned i;
	bool success;

	if (!queue_valid_position(&playlist->queue, song))
		return PLAYLIST_RESULT_BAD_RANGE;

	queued = playlist_get_queued_song(playlist);

	if (playlist->queue.random)
		i = queue_position_to_order(&playlist->queue, song);
	else
		i = song;

	pc_clear_error(pc);
	playlist->stop_on_error = true;
	playlist->error_count = 0;

	if (!playlist->playing || (unsigned)playlist->current != i) {
		/* seeking is not within the current song - prepare
		   song change */

		playlist->playing = true;
		playlist->current = i;

		queued = NULL;
	}

	success = pc_seek(pc, queue_get_order(&playlist->queue, i), seek_time);
	if (!success) {
		playlist_update_queued_song(playlist, pc, queued);

		return PLAYLIST_RESULT_NOT_PLAYING;
	}

	playlist->queued = -1;
	playlist_update_queued_song(playlist, pc, NULL);

	return PLAYLIST_RESULT_SUCCESS;
}
Ejemplo n.º 7
0
void
playlist_set_random(struct playlist *playlist, struct player_control *pc,
		    bool status)
{
	const struct song *queued;

	if (status == playlist->queue.random)
		return;

	queued = playlist_get_queued_song(playlist);

	playlist->queue.random = status;

	if (playlist->queue.random) {
		/* shuffle the queue order, but preserve
		   playlist->current */

		int current_position =
			playlist->playing && playlist->current >= 0
			? (int)queue_order_to_position(&playlist->queue,
						       playlist->current)
			: -1;

		queue_shuffle_order(&playlist->queue);

		if (current_position >= 0) {
			/* make sure the current song is the first in
			   the order list, so the whole rest of the
			   playlist is played after that */
			unsigned current_order =
				queue_position_to_order(&playlist->queue,
							current_position);
			queue_swap_order(&playlist->queue, 0, current_order);
			playlist->current = 0;
		} else
			playlist->current = -1;
	} else
		playlist_order(playlist);

	playlist_update_queued_song(playlist, pc, queued);

	idle_add(IDLE_OPTIONS);
}
Ejemplo n.º 8
0
void
playlist_set_single(struct playlist *playlist, struct player_control *pc,
		    bool status)
{
	if (status == playlist->queue.single)
		return;

	struct queue *queue = &playlist->queue;

	queue->single = status;

	pc_set_border_pause(pc, queue->single && !queue->repeat);

	/* if the last song is currently being played, the "next song"
	   might change when single mode is toggled */
	playlist_update_queued_song(playlist, pc,
				    playlist_get_queued_song(playlist));

	idle_add(IDLE_OPTIONS);
}
Ejemplo n.º 9
0
enum playlist_result
playlist_set_priority(struct playlist *playlist, struct player_control *pc,
		      unsigned start, unsigned end,
		      uint8_t priority)
{
	if (start >= queue_length(&playlist->queue))
		return PLAYLIST_RESULT_BAD_RANGE;

	if (end > queue_length(&playlist->queue))
		end = queue_length(&playlist->queue);

	if (start >= end)
		return PLAYLIST_RESULT_SUCCESS;

	/* remember "current" and "queued" */

	int current_position = playlist->current >= 0
		? (int)queue_order_to_position(&playlist->queue,
					       playlist->current)
		: -1;

	const struct song *queued = playlist_get_queued_song(playlist);

	/* apply the priority changes */

	queue_set_priority_range(&playlist->queue, start, end, priority,
				 playlist->current);

	playlist_increment_version(playlist);

	/* restore "current" and choose a new "queued" */

	if (current_position >= 0)
		playlist->current = queue_position_to_order(&playlist->queue,
							    current_position);

	playlist_update_queued_song(playlist, pc, queued);

	return PLAYLIST_RESULT_SUCCESS;
}
Ejemplo n.º 10
0
enum playlist_result
playlist_swap_songs(struct playlist *playlist, struct player_control *pc,
		    unsigned song1, unsigned song2)
{
	const struct song *queued;

	if (!queue_valid_position(&playlist->queue, song1) ||
	    !queue_valid_position(&playlist->queue, song2))
		return PLAYLIST_RESULT_BAD_RANGE;

	queued = playlist_get_queued_song(playlist);

	queue_swap(&playlist->queue, song1, song2);

	if (playlist->queue.random) {
		/* update the queue order, so that playlist->current
		   still points to the current song order */

		queue_swap_order(&playlist->queue,
				 queue_position_to_order(&playlist->queue,
							 song1),
				 queue_position_to_order(&playlist->queue,
							 song2));
	} else {
		/* correct the "current" song order */

		if (playlist->current == (int)song1)
			playlist->current = song2;
		else if (playlist->current == (int)song2)
			playlist->current = song1;
	}

	playlist_increment_version(playlist);

	playlist_update_queued_song(playlist, pc, queued);

	return PLAYLIST_RESULT_SUCCESS;
}
Ejemplo n.º 11
0
enum playlist_result
playlist_append_song(struct playlist *playlist,
		  struct song *song, unsigned *added_id)
{
	const struct song *queued;
	unsigned id;

	if (queue_is_full(&playlist->queue))
		return PLAYLIST_RESULT_TOO_LARGE;

	queued = playlist_get_queued_song(playlist);

	id = queue_append(&playlist->queue, song);

	if (playlist->queue.random) {
		/* shuffle the new song into the list of remaining
		   songs to play */

		unsigned start;
		if (playlist->queued >= 0)
			start = playlist->queued + 1;
		else
			start = playlist->current + 1;
		if (start < queue_length(&playlist->queue))
			queue_shuffle_order_last(&playlist->queue, start,
						 queue_length(&playlist->queue));
	}

	playlist_increment_version(playlist);

	playlist_update_queued_song(playlist, queued);

	if (added_id)
		*added_id = id;

	return PLAYLIST_RESULT_SUCCESS;
}