aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--src/command.c2
-rw-r--r--src/cue/cue_parser.c12
-rw-r--r--src/player_control.c8
-rw-r--r--src/player_control.h15
-rw-r--r--src/player_thread.c15
-rw-r--r--src/playlist.c17
-rw-r--r--src/playlist_edit.c2
-rw-r--r--src/queue.c4
-rw-r--r--src/queue.h4
-rw-r--r--src/queue_save.c21
-rw-r--r--test/test_queue_priority.c2
12 files changed, 89 insertions, 17 deletions
diff --git a/NEWS b/NEWS
index d71fba2bb..873c91762 100644
--- a/NEWS
+++ b/NEWS
@@ -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));