Merge branch 'v0.17.x'
Conflicts: src/queue_save.c
This commit is contained in:
commit
def21cc87e
4
NEWS
4
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)
|
||||
|
@ -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);
|
||||
|
@ -204,6 +204,14 @@ pc_set_pause(struct player_control *pc, bool pause_flag)
|
||||
player_unlock(pc);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user