diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | src/command.c | 2 | ||||
-rw-r--r-- | src/cue/cue_parser.c | 12 | ||||
-rw-r--r-- | src/player_control.c | 8 | ||||
-rw-r--r-- | src/player_control.h | 15 | ||||
-rw-r--r-- | src/player_thread.c | 15 | ||||
-rw-r--r-- | src/playlist.c | 17 | ||||
-rw-r--r-- | src/playlist_edit.c | 2 | ||||
-rw-r--r-- | src/queue.c | 4 | ||||
-rw-r--r-- | src/queue.h | 4 | ||||
-rw-r--r-- | src/queue_save.c | 21 | ||||
-rw-r--r-- | test/test_queue_priority.c | 2 |
12 files changed, 89 insertions, 17 deletions
@@ -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) diff --git a/src/command.c b/src/command.c index b4f8e7039..2c76a75ba 100644 --- a/src/command.c +++ b/src/command.c @@ -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); diff --git a/src/cue/cue_parser.c b/src/cue/cue_parser.c index 868aed094..2b0733f00 100644 --- a/src/cue/cue_parser.c +++ b/src/cue/cue_parser.c @@ -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); diff --git a/src/player_control.c b/src/player_control.c index 28134ccdc..d9aa2b94c 100644 --- a/src/player_control.c +++ b/src/player_control.c @@ -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); diff --git a/src/player_control.h b/src/player_control.h index c16dbcb9f..3b536b8ba 100644 --- a/src/player_control.h +++ b/src/player_control.h @@ -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); diff --git a/src/player_thread.c b/src/player_thread.c index d410984f6..d2682f513 100644 --- a/src/player_thread.c +++ b/src/player_thread.c @@ -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, diff --git a/src/playlist.c b/src/playlist.c index 4d4f0c1f6..71abcb692 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -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 */ diff --git a/src/playlist_edit.c b/src/playlist_edit.c index 3cd737705..2b7cdd8ae 100644 --- a/src/playlist_edit.c +++ b/src/playlist_edit.c @@ -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 diff --git a/src/queue.c b/src/queue.c index 2a489242c..098cbcce9 100644 --- a/src/queue.c +++ b/src/queue.c @@ -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; diff --git a/src/queue.h b/src/queue.h index 5cb5c196b..e4bfcdffa 100644 --- a/src/queue.h +++ b/src/queue.h @@ -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. diff --git a/src/queue_save.c b/src/queue_save.c index 0025e26f9..00b5ecbb1 100644 --- a/src/queue_save.c +++ b/src/queue_save.c @@ -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); diff --git a/test/test_queue_priority.c b/test/test_queue_priority.c index 2fc1a3706..b4a7366e9 100644 --- a/test/test_queue_priority.c +++ b/test/test_queue_priority.c @@ -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)); |