Commit def21cc8 authored by Max Kellermann's avatar Max Kellermann

Merge branch 'v0.17.x'

Conflicts: src/queue_save.c
parents 488c1eb8 acaa7254
......@@ -12,10 +12,14 @@ ver 0.17.2 (2012/??/??)
* output:
- httpd: use monotonic clock, avoid hiccups after system clock adjustment
- httpd: fix throttling bug after resuming playback
* playlist:
- cue: map "PERFORMER" to "artist" or "album artist"
* mapper: fix non-UTF8 music directory name
* mapper: fix potential crash in file permission check
* playlist: fix use-after-free bug
* playlist: fix memory leak
* state_file: save song priorities
* player: disable cross-fading in "single" mode
ver 0.17.1 (2012/07/31)
......
......@@ -788,7 +788,7 @@ handle_next(G_GNUC_UNUSED struct client *client,
{
/* single mode is not considered when this is user who
* wants to change song. */
int single = g_playlist.queue.single;
const bool single = g_playlist.queue.single;
g_playlist.queue.single = false;
playlist_next(&g_playlist, client->player_control);
......
......@@ -216,9 +216,19 @@ cue_parser_feed2(struct cue_parser *parser, char *p)
if (tag != NULL)
cue_parse_rem(p, tag);
} else if (strcmp(command, "PERFORMER") == 0) {
/* MPD knows a "performer" tag, but it is not a good
match for this CUE tag; from the Hydrogenaudio
Knowledgebase: "At top-level this will specify the
CD artist, while at track-level it specifies the
track artist." */
enum tag_type type = parser->state == TRACK
? TAG_ARTIST
: TAG_ALBUM_ARTIST;
struct tag *tag = cue_current_tag(parser);
if (tag != NULL)
cue_add_tag(tag, TAG_PERFORMER, p);
cue_add_tag(tag, type, p);
} else if (strcmp(command, "TITLE") == 0) {
if (parser->state == HEADER)
cue_add_tag(parser->tag, TAG_ALBUM, p);
......
......@@ -205,6 +205,14 @@ pc_set_pause(struct player_control *pc, bool pause_flag)
}
void
pc_set_border_pause(struct player_control *pc, bool border_pause)
{
player_lock(pc);
pc->border_pause = border_pause;
player_unlock(pc);
}
void
pc_get_status(struct player_control *pc, struct player_status *status)
{
player_lock(pc);
......
......@@ -137,6 +137,15 @@ struct player_control {
float mixramp_db;
float mixramp_delay_seconds;
double total_play_time;
/**
* If this flag is set, then the player will be auto-paused at
* the end of the song, before the next song starts to play.
*
* This is a copy of the queue's "single" flag most of the
* time.
*/
bool border_pause;
};
struct player_control *
......@@ -225,6 +234,12 @@ pc_set_pause(struct player_control *pc, bool pause_flag);
void
pc_pause(struct player_control *pc);
/**
* Set the player's #border_pause flag.
*/
void
pc_set_border_pause(struct player_control *pc, bool border_pause);
void
pc_kill(struct player_control *pc);
......
......@@ -862,6 +862,16 @@ player_song_border(struct player *player)
if (!player_wait_for_decoder(player))
return false;
struct player_control *const pc = player->pc;
player_lock(pc);
if (pc->border_pause) {
player->paused = true;
pc->state = PLAYER_STATE_PAUSE;
}
player_unlock(pc);
return true;
}
......@@ -979,7 +989,10 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
player_dc_start(&player, music_pipe_new());
}
if (player_dc_at_next_song(&player) &&
if (/* no cross-fading if MPD is going to pause at the
end of the current song */
!pc->border_pause &&
player_dc_at_next_song(&player) &&
player.xfade == XFADE_UNKNOWN &&
!decoder_lock_is_starting(dc)) {
/* enable cross fading in this song? if yes,
......
......@@ -110,11 +110,6 @@ playlist_song_started(struct playlist *playlist, struct player_control *pc)
playlist->current = playlist->queued;
playlist->queued = -1;
/* Pause if we are in single mode. */
if(playlist->queue.single && !playlist->queue.repeat) {
pc_set_pause(pc, true);
}
if(playlist->queue.consume)
playlist_delete(playlist, pc,
queue_order_to_position(&playlist->queue,
......@@ -311,7 +306,11 @@ playlist_set_repeat(struct playlist *playlist, struct player_control *pc,
if (status == playlist->queue.repeat)
return;
playlist->queue.repeat = status;
struct queue *queue = &playlist->queue;
queue->repeat = status;
pc_set_border_pause(pc, queue->single && !queue->repeat);
/* if the last song is currently being played, the "next song"
might change when repeat mode is toggled */
......@@ -339,7 +338,11 @@ playlist_set_single(struct playlist *playlist, struct player_control *pc,
if (status == playlist->queue.single)
return;
playlist->queue.single = status;
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 */
......
......@@ -75,7 +75,7 @@ playlist_append_song(struct playlist *playlist, struct player_control *pc,
queued = playlist_get_queued_song(playlist);
id = queue_append(&playlist->queue, song);
id = queue_append(&playlist->queue, song, 0);
if (playlist->queue.random) {
/* shuffle the new song into the list of remaining
......
......@@ -96,7 +96,7 @@ queue_modify_all(struct queue *queue)
}
unsigned
queue_append(struct queue *queue, struct song *song)
queue_append(struct queue *queue, struct song *song, uint8_t priority)
{
unsigned id = queue_generate_id(queue);
......@@ -106,7 +106,7 @@ queue_append(struct queue *queue, struct song *song)
.song = song_dup_detached(song),
.id = id,
.version = queue->version,
.priority = 0,
.priority = priority,
};
queue->order[queue->length] = queue->length;
......
......@@ -280,9 +280,11 @@ queue_modify_all(struct queue *queue);
*
* If a song is not in the database (determined by
* song_in_database()), it is freed when removed from the queue.
*
* @param priority the priority of this new queue item
*/
unsigned
queue_append(struct queue *queue, struct song *song);
queue_append(struct queue *queue, struct song *song, uint8_t priority);
/**
* Swaps two songs, addressed by their position.
......
......@@ -24,9 +24,12 @@
#include "uri.h"
#include "database.h"
#include "song_save.h"
#include "text_file.h"
#include <stdlib.h>
#define PRIO_LABEL "Prio: "
static void
queue_save_database_song(FILE *fp, int idx, const struct song *song)
{
......@@ -54,8 +57,13 @@ queue_save_song(FILE *fp, int idx, const struct song *song)
void
queue_save(FILE *fp, const struct queue *queue)
{
for (unsigned i = 0; i < queue_length(queue); i++)
for (unsigned i = 0; i < queue_length(queue); i++) {
uint8_t prio = queue_get_priority_at_position(queue, i);
if (prio != 0)
fprintf(fp, PRIO_LABEL "%u\n", prio);
queue_save_song(fp, i, queue_get(queue, i));
}
}
static struct song *
......@@ -75,6 +83,15 @@ queue_load_song(FILE *fp, GString *buffer, const char *line,
if (queue_is_full(queue))
return;
uint8_t priority = 0;
if (g_str_has_prefix(line, PRIO_LABEL)) {
priority = strtoul(line + sizeof(PRIO_LABEL) - 1, NULL, 10);
line = read_text_line(fp, buffer);
if (line == NULL)
return;
}
if (g_str_has_prefix(line, SONG_BEGIN)) {
const char *uri = line + sizeof(SONG_BEGIN) - 1;
if (!uri_has_scheme(uri) && !g_path_is_absolute(uri))
......@@ -102,7 +119,7 @@ queue_load_song(FILE *fp, GString *buffer, const char *line,
return;
}
queue_append(queue, song);
queue_append(queue, song, priority);
if (song_in_database(song))
db_return_song(song);
......
......@@ -56,7 +56,7 @@ main(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
queue_init(&queue, 32);
for (unsigned i = 0; i < G_N_ELEMENTS(songs); ++i)
queue_append(&queue, &songs[i]);
queue_append(&queue, &songs[i], 0);
assert(queue_length(&queue) == G_N_ELEMENTS(songs));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment