Merge pull request #309 from chme/persistentqueue3

Persistent queue
This commit is contained in:
ejurgensen 2016-12-08 21:06:17 +01:00 committed by GitHub
commit 9ba512a340
18 changed files with 2515 additions and 2742 deletions

View File

@ -105,7 +105,6 @@ forked_daapd_SOURCES = main.c \
rsp_query.c rsp_query.h \
daap_query.c daap_query.h \
player.c player.h \
queue.c queue.h \
worker.c worker.h \
outputs.h outputs.c \
outputs/raop.c outputs/streaming.c outputs/dummy.c outputs/fifo.c \

1494
src/db.c

File diff suppressed because it is too large Load Diff

136
src/db.h
View File

@ -28,6 +28,8 @@ enum sort_type {
S_DISC,
S_TRACK,
S_VPATH,
S_POS,
S_SHUFFLE_POS,
};
#define Q_F_BROWSE (1 << 15)
@ -374,6 +376,49 @@ struct directory_enum {
sqlite3_stmt *stmt;
};
struct db_queue_item
{
/* A unique id for this queue item. If the same item appears multiple
times in the queue each corresponding queue item has its own id. */
uint32_t id;
/* Id of the file/item in the files database */
uint32_t file_id;
/* Length of the item in ms */
uint32_t song_length;
/* Data type of the item */
enum data_kind data_kind;
/* Media type of the item */
enum media_kind media_kind;
uint32_t seek;
uint32_t pos;
uint32_t shuffle_pos;
char *path;
char *virtual_path;
char *title;
char *artist;
char *album_artist;
char *album;
char *genre;
int64_t songalbumid;
uint32_t time_modified;
char *artist_sort;
char *album_sort;
char *album_artist_sort;
uint32_t year;
uint32_t track;
uint32_t disc;
};
char *
db_escape_string(const char *str);
@ -392,6 +437,9 @@ free_pli(struct playlist_info *pli, int content_only);
void
free_di(struct directory_info *di, int content_only);
void
free_queue_item(struct db_queue_item *queue_item, int content_only);
/* Maintenance and DB hygiene */
void
db_hook_post_scan(void);
@ -409,6 +457,9 @@ db_transaction_begin(void);
void
db_transaction_end(void);
void
db_transaction_rollback(void);
/* Queries */
int
db_query_start(struct query_params *qp);
@ -498,9 +549,6 @@ db_file_add(struct media_file_info *mfi);
int
db_file_update(struct media_file_info *mfi);
void
db_file_update_icy(int id, char *artist, char *album);
void
db_file_save_seek(int id, uint32_t seek);
@ -646,6 +694,88 @@ db_speaker_get(uint64_t id, int *selected, int *volume);
void
db_speaker_clear_all(void);
/* Queue */
int
db_queue_get_version();
void
db_queue_update_icymetadata(int id, char *artist, char *album);
int
db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id);
int
db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id);
int
db_queue_add_by_playlistid(int plid, char reshuffle, uint32_t item_id);
int
db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id);
int
db_queue_enum_start(struct query_params *query_params);
void
db_queue_enum_end(struct query_params *query_params);
int
db_queue_enum_fetch(struct query_params *query_params, struct db_queue_item *queue_item);
struct db_queue_item *
db_queue_fetch_byitemid(uint32_t item_id);
struct db_queue_item *
db_queue_fetch_byfileid(uint32_t file_id);
struct db_queue_item *
db_queue_fetch_bypos(uint32_t pos, char shuffle);
struct db_queue_item *
db_queue_fetch_byposrelativetoitem(int pos, uint32_t item_id, char shuffle);
struct db_queue_item *
db_queue_fetch_next(uint32_t item_id, char shuffle);
struct db_queue_item *
db_queue_fetch_prev(uint32_t item_id, char shuffle);
int
db_queue_cleanup();
int
db_queue_clear();
int
db_queue_delete_byitemid(uint32_t item_id);
int
db_queue_delete_bypos(uint32_t pos, int count);
int
db_queue_delete_byposrelativetoitem(uint32_t pos, uint32_t item_id, char shuffle);
int
db_queue_move_byitemid(uint32_t item_id, int pos_to);
int
db_queue_move_bypos(int pos_from, int pos_to);
int
db_queue_move_byposrelativetoitem(uint32_t from_pos, uint32_t to_offset, uint32_t item_id, char shuffle);
int
db_queue_reshuffle(uint32_t item_id);
int
db_queue_get_count();
int
db_queue_get_pos(uint32_t item_id, char shuffle);
int
db_queue_get_pos_byfileid(uint32_t file_id, char shuffle);
/* Inotify */
int
db_watch_clear(void);

View File

@ -158,6 +158,32 @@
" parent_id INTEGER DEFAULT 0" \
");"
#define T_QUEUE \
"CREATE TABLE IF NOT EXISTS queue (" \
" id INTEGER PRIMARY KEY NOT NULL," \
" file_id INTEGER NOT NULL," \
" pos INTEGER NOT NULL," \
" shuffle_pos INTEGER NOT NULL," \
" data_kind INTEGER NOT NULL," \
" media_kind INTEGER NOT NULL," \
" song_length INTEGER NOT NULL," \
" path VARCHAR(4096) NOT NULL," \
" virtual_path VARCHAR(4096) NOT NULL," \
" title VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" artist VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" album_artist VARCHAR(1024) NOT NULL COLLATE DAAP," \
" album VARCHAR(1024) NOT NULL COLLATE DAAP," \
" genre VARCHAR(255) DEFAULT NULL COLLATE DAAP," \
" songalbumid INTEGER NOT NULL," \
" time_modified INTEGER DEFAULT 0," \
" artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" album_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" album_artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" year INTEGER DEFAULT 0," \
" track INTEGER DEFAULT 0," \
" disc INTEGER DEFAULT 0" \
");"
#define TRG_GROUPS_INSERT_FILES \
"CREATE TRIGGER update_groups_new_file AFTER INSERT ON files FOR EACH ROW" \
" BEGIN" \
@ -216,6 +242,9 @@
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
" VALUES (4, '/spotify:', 0, 4294967296, 1);"
#define Q_QUEUE_VERSION \
"INSERT INTO admin (key, value) VALUES ('queue_version', '0');"
#define Q_SCVER_MAJOR \
"INSERT INTO admin (key, value) VALUES ('schema_version_major', '%d');"
#define Q_SCVER_MINOR \
@ -237,6 +266,7 @@ static const struct db_init_query db_init_table_queries[] =
{ T_SPEAKERS, "create table speakers" },
{ T_INOTIFY, "create table inotify" },
{ T_DIRECTORIES, "create table directories" },
{ T_QUEUE, "create table queue" },
{ TRG_GROUPS_INSERT_FILES, "create trigger update_groups_new_file" },
{ TRG_GROUPS_UPDATE_FILES, "create trigger update_groups_update_file" },
@ -251,6 +281,7 @@ static const struct db_init_query db_init_table_queries[] =
{ Q_DIR2, "create default base directory '/file:'" },
{ Q_DIR3, "create default base directory '/http:'" },
{ Q_DIR4, "create default base directory '/spotify:'" },
{ Q_QUEUE_VERSION, "initialize queue version" },
};
@ -327,6 +358,12 @@ static const struct db_init_query db_init_table_queries[] =
#define I_DIR_PARENT \
"CREATE INDEX IF NOT EXISTS idx_dir_parentid ON directories(parent_id);"
#define I_QUEUE_POS \
"CREATE INDEX IF NOT EXISTS idx_queue_pos ON queue(pos);"
#define I_QUEUE_SHUFFLEPOS \
"CREATE INDEX IF NOT EXISTS idx_queue_shufflepos ON queue(shuffle_pos);"
static const struct db_init_query db_init_index_queries[] =
{
{ I_RESCAN, "create rescan index" },
@ -357,6 +394,9 @@ static const struct db_init_query db_init_index_queries[] =
{ I_DIR_VPATH, "create directories disabled_virtualpath index" },
{ I_DIR_PARENT, "create directories parentid index" },
{ I_QUEUE_POS, "create queue pos index" },
{ I_QUEUE_SHUFFLEPOS, "create queue shuffle pos index" },
};
int

View File

@ -26,7 +26,7 @@
* is a major upgrade. In other words minor version upgrades permit downgrading
* forked-daapd after the database was upgraded. */
#define SCHEMA_VERSION_MAJOR 19
#define SCHEMA_VERSION_MINOR 00
#define SCHEMA_VERSION_MINOR 01
int
db_init_indices(sqlite3 *hdl);

View File

@ -1441,6 +1441,54 @@ db_upgrade_v19(sqlite3 *hdl)
return 0;
}
/* Upgrade from schema v19.00 to v20.00 */
/* Create new table queue for persistent playqueue
*/
#define U_V2000_CREATE_TABLE_QUEUE \
"CREATE TABLE IF NOT EXISTS queue (" \
" id INTEGER PRIMARY KEY NOT NULL," \
" file_id INTEGER NOT NULL," \
" pos INTEGER NOT NULL," \
" shuffle_pos INTEGER NOT NULL," \
" data_kind INTEGER NOT NULL," \
" media_kind INTEGER NOT NULL," \
" song_length INTEGER NOT NULL," \
" path VARCHAR(4096) NOT NULL," \
" virtual_path VARCHAR(4096) NOT NULL," \
" title VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" artist VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" album_artist VARCHAR(1024) NOT NULL COLLATE DAAP," \
" album VARCHAR(1024) NOT NULL COLLATE DAAP," \
" genre VARCHAR(255) DEFAULT NULL COLLATE DAAP," \
" songalbumid INTEGER NOT NULL," \
" time_modified INTEGER DEFAULT 0," \
" artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" album_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" album_artist_sort VARCHAR(1024) DEFAULT NULL COLLATE DAAP," \
" year INTEGER DEFAULT 0," \
" track INTEGER DEFAULT 0," \
" disc INTEGER DEFAULT 0" \
");"
#define U_V2000_QUEUE_VERSION \
"INSERT INTO admin (key, value) VALUES ('queue_version', '0');"
#define U_V2000_SCVER_MAJOR \
"UPDATE admin SET value = '20' WHERE key = 'schema_version_major';"
#define U_V2000_SCVER_MINOR \
"UPDATE admin SET value = '00' WHERE key = 'schema_version_minor';"
static const struct db_upgrade_query db_upgrade_v1901_queries[] =
{
{ U_V2000_CREATE_TABLE_QUEUE, "create table directories" },
{ U_V2000_QUEUE_VERSION, "insert queue version" },
{ U_V2000_SCVER_MAJOR, "set schema_version_major to 19" },
{ U_V2000_SCVER_MINOR, "set schema_version_minor to 01" },
};
int
db_upgrade(sqlite3 *hdl, int db_ver)
{
@ -1551,6 +1599,13 @@ db_upgrade(sqlite3 *hdl, int db_ver)
if (ret < 0)
return -1;
/* FALLTHROUGH */
case 1900:
ret = db_generic_upgrade(hdl, db_upgrade_v1901_queries, sizeof(db_upgrade_v1901_queries) / sizeof(db_upgrade_v1901_queries[0]));
if (ret < 0)
return -1;
break;
default:

View File

@ -559,3 +559,78 @@ dmap_encode_file_metadata(struct evbuffer *songlist, struct evbuffer *song, stru
return 0;
}
int
dmap_encode_queue_metadata(struct evbuffer *songlist, struct evbuffer *song, struct db_queue_item *queue_item)
{
int32_t val;
int want_mikd;
int want_asdk;
int want_ased;
int ret;
dmap_add_int(song, "miid", queue_item->file_id);
dmap_add_string(song, "minm", queue_item->title);
dmap_add_long(song, "mper", queue_item->file_id);
dmap_add_int(song, "mcti", queue_item->file_id);
dmap_add_string(song, "asal", queue_item->album);
dmap_add_long(song, "asai", queue_item->songalbumid);
dmap_add_string(song, "asaa", queue_item->album_artist);
dmap_add_string(song, "asar", queue_item->artist);
dmap_add_int(song, "asdm", queue_item->time_modified);
dmap_add_short(song, "asdn", queue_item->disc);
dmap_add_string(song, "asgn", queue_item->genre);
dmap_add_int(song, "astm", queue_item->song_length);
dmap_add_short(song, "astn", queue_item->track);
dmap_add_short(song, "asyr", queue_item->year);
dmap_add_int(song, "aeMK", queue_item->media_kind);
dmap_add_char(song, "aeMk", queue_item->media_kind);
dmap_add_string(song, "asfm", "wav");
dmap_add_short(song, "asbr", 1411);
dmap_add_string(song, "asdt", "wav audio file");
want_mikd = 1;/* Will be prepended to the list *//* item kind */
want_asdk = 1;/* Will be prepended to the list *//* data kind */
want_ased = 1;/* Extradata not in media_file_info but flag for reply */
/* Required for artwork in iTunes, set songartworkcount (asac) = 1 */
if (want_ased)
{
dmap_add_short(song, "ased", 1);
dmap_add_short(song, "asac", 1);
}
val = 0;
if (want_mikd)
val += 9;
if (want_asdk)
val += 9;
dmap_add_container(songlist, "mlit", evbuffer_get_length(song) + val);
/* Prepend mikd & asdk if needed */
if (want_mikd)
{
/* dmap.itemkind must come first */
val = 2; /* music by default */
dmap_add_char(songlist, "mikd", val);
}
if (want_asdk)
{
ret = queue_item->data_kind;
if (ret < 0)
val = 0;
dmap_add_char(songlist, "asdk", val);
}
ret = evbuffer_add_buffer(songlist, song);
if (ret < 0)
{
DPRINTF(E_LOG, L_DAAP, "Could not add song to song list\n");
return -1;
}
return 0;
}

View File

@ -84,4 +84,7 @@ dmap_send_error(struct evhttp_request *req, const char *container, const char *e
int
dmap_encode_file_metadata(struct evbuffer *songlist, struct evbuffer *song, struct db_media_file_info *dbmfi, const struct dmap_field **meta, int nmeta, int sort_tags, int force_wav);
int
dmap_encode_queue_metadata(struct evbuffer *songlist, struct evbuffer *song, struct db_queue_item *queue_item);
#endif /* !__DMAP_HELPERS_H__ */

View File

@ -1227,6 +1227,7 @@ bulk_scan(int flags)
DPRINTF(E_DBG, L_SCAN, "Purging old database content\n");
db_purge_cruft(start);
db_queue_cleanup();
cache_artwork_purge_cruft(start);
DPRINTF(E_LOG, L_SCAN, "Bulk library scan completed in %.f sec\n", difftime(end, start));
@ -1244,6 +1245,7 @@ bulk_scan(int flags)
static void *
filescanner(void *arg)
{
int clear_queue_on_stop_disabled;
int ret;
#if defined(__linux__)
struct sched_param param;
@ -1284,6 +1286,19 @@ filescanner(void *arg)
pthread_exit(NULL);
}
// Only clear the queue if enabled (default) in config
clear_queue_on_stop_disabled = cfg_getbool(cfg_getsec(cfg, "mpd"), "clear_queue_on_stop_disable");
if (!clear_queue_on_stop_disabled)
{
ret = db_queue_clear();
if (ret < 0)
{
DPRINTF(E_LOG, L_SCAN, "Error: could not clear queue from DB\n");
pthread_exit(NULL);
}
}
/* Recompute all songartistids and songalbumids, in case the SQLite DB got transferred
* to a different host; the hash is not portable.
* It will also rebuild the groups we just cleared.
@ -1937,7 +1952,7 @@ filescanner_fullrescan(void *arg, int *retval)
DPRINTF(E_LOG, L_SCAN, "Full rescan triggered\n");
player_playback_stop();
player_queue_clear();
db_queue_clear();
inofd_event_unset(); // Clears all inotify watches
db_purge_all(); // Clears files, playlists, playlistitems, inotify and groups

File diff suppressed because it is too large Load Diff

427
src/mpd.c
View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2010 Julien BLACHE <jb@jblache.org>
* Copyright (C) 2016 Christian Meffert <christian.meffert@googlemail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -61,7 +61,6 @@
#include "artwork.h"
#include "player.h"
#include "queue.h"
#include "filescanner.h"
#include "commands.h"
@ -396,18 +395,16 @@ mpd_parse_args(char *args, int *argc, char **argv)
* Id: 1
*
* @param evbuf the response event buffer
* @param mfi media information
* @param item_id queue-item id
* @param pos_pl position in the playqueue, if -1 the position is ignored
* @param queue_item queue item information
* @return the number of bytes added if successful, or -1 if an error occurred.
*/
static int
mpd_add_mediainfo(struct evbuffer *evbuf, struct media_file_info *mfi, unsigned int item_id, int pos_pl)
mpd_add_db_queue_item(struct evbuffer *evbuf, struct db_queue_item *queue_item)
{
char modified[32];
int ret;
mpd_time(modified, sizeof(modified), mfi->time_modified);
mpd_time(modified, sizeof(modified), queue_item->time_modified);
ret = evbuffer_add_printf(evbuf,
"file: %s\n"
@ -422,65 +419,28 @@ mpd_add_mediainfo(struct evbuffer *evbuf, struct media_file_info *mfi, unsigned
"Track: %d\n"
"Date: %d\n"
"Genre: %s\n"
"Disc: %d\n",
(mfi->virtual_path + 1),
"Disc: %d\n"
"Pos: %d\n"
"Id: %d\n",
(queue_item->virtual_path + 1),
modified,
(mfi->song_length / 1000),
mfi->artist,
mfi->album_artist,
mfi->artist_sort,
mfi->album_artist_sort,
mfi->album,
mfi->title,
mfi->track,
mfi->year,
mfi->genre,
mfi->disc);
if (ret >= 0 && pos_pl >= 0)
{
ret = evbuffer_add_printf(evbuf,
"Pos: %d\n",
pos_pl);
if (ret >= 0)
{
ret = evbuffer_add_printf(evbuf,
"Id: %d\n",
item_id);
}
}
(queue_item->song_length / 1000),
queue_item->artist,
queue_item->album_artist,
queue_item->artist_sort,
queue_item->album_artist_sort,
queue_item->album,
queue_item->title,
queue_item->track,
queue_item->year,
queue_item->genre,
queue_item->disc,
queue_item->pos,
queue_item->id);
return ret;
}
static int
mpd_add_mediainfo_byid(struct evbuffer *evbuf, int id, unsigned int item_id, int pos_pl)
{
struct media_file_info *mfi;
int ret;
mfi = db_file_fetch_byid(id);
if (!mfi)
{
DPRINTF(E_LOG, L_MPD, "Error fetching file by id: %d\n", id);
return -1;
}
ret = mpd_add_mediainfo(evbuf, mfi, item_id, pos_pl);
if (ret < 0)
{
DPRINTF(E_LOG, L_MPD, "Error adding media info for file with id: %d\n", id);
free_mfi(mfi, 0);
return -1;
}
free_mfi(mfi, 0);
return 0;
}
/*
* Adds the informations (path, id, tags, etc.) for the given song to the given buffer.
*
@ -568,6 +528,7 @@ mpd_command_currentsong(struct evbuffer *evbuf, int argc, char **argv, char **er
{
struct player_status status;
struct db_queue_item *queue_item;
int ret;
player_get_status(&status);
@ -578,7 +539,20 @@ mpd_command_currentsong(struct evbuffer *evbuf, int argc, char **argv, char **er
return 0;
}
ret = mpd_add_mediainfo_byid(evbuf, status.id, status.item_id, status.pos_pl);
queue_item = db_queue_fetch_byitemid(status.item_id);
if (!queue_item)
{
ret = asprintf(errmsg, "Error adding queue item info for file with id: %d", status.item_id);
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_UNKNOWN;
}
ret = mpd_add_db_queue_item(evbuf, queue_item);
free_queue_item(queue_item, 0);
if (ret < 0)
{
ret = asprintf(errmsg, "Error adding media info for file with id: %d", status.id);
@ -717,7 +691,11 @@ static int
mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct player_status status;
int queue_length;
int queue_version;
char *state;
int pos_pl;
struct db_queue_item *next_item;
player_get_status(&status);
@ -736,6 +714,9 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
break;
}
queue_version = db_queue_get_version();
queue_length = db_queue_get_count();
evbuffer_add_printf(evbuf,
"volume: %d\n"
"repeat: %d\n"
@ -751,12 +732,14 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
status.shuffle,
(status.repeat == REPEAT_SONG ? 1 : 0),
0 /* consume: not supported by forked-daapd, always return 'off' */,
status.plversion,
status.playlistlength,
queue_version,
queue_length,
state);
if (status.status != PLAY_STOPPED)
{
pos_pl = db_queue_get_pos(status.item_id, 0);
evbuffer_add_printf(evbuf,
"song: %d\n"
"songid: %d\n"
@ -764,7 +747,7 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
"elapsed: %#.3f\n"
"bitrate: 128\n"
"audio: 44100:16:2\n",
status.pos_pl,
pos_pl,
status.item_id,
(status.pos_ms / 1000), (status.len_ms / 1000),
(status.pos_ms / 1000.0));
@ -777,11 +760,17 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
if (status.status != PLAY_STOPPED)
{
next_item = db_queue_fetch_next(status.item_id, status.shuffle);
if (next_item)
{
evbuffer_add_printf(evbuf,
"nextsong: %d\n"
"nextsongid: %d\n",
status.next_pos_pl,
status.next_item_id);
next_item->id,
next_item->pos);
free_queue_item(next_item, 0);
}
}
return 0;
@ -1074,7 +1063,7 @@ mpd_command_next(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
return ACK_ERROR_UNKNOWN;
}
ret = player_playback_start(NULL);
ret = player_playback_start();
if (ret < 0)
{
ret = asprintf(errmsg, "Player returned an error for start after nextitem");
@ -1122,7 +1111,7 @@ mpd_command_pause(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
if (pause == 1)
ret = player_playback_pause();
else
ret = player_playback_start(NULL);
ret = player_playback_start();
if (ret < 0)
{
@ -1145,10 +1134,9 @@ mpd_command_play(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
int songpos;
struct player_status status;
struct db_queue_item *queue_item;
int ret;
player_get_status(&status);
songpos = 0;
if (argc > 1)
{
@ -1162,6 +1150,8 @@ mpd_command_play(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
}
}
player_get_status(&status);
if (status.status == PLAY_PLAYING && songpos < 0)
{
DPRINTF(E_DBG, L_MPD, "Ignoring play command with parameter '%s', player is already playing.\n", argv[1]);
@ -1175,9 +1165,21 @@ mpd_command_play(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
}
if (songpos > 0)
ret = player_playback_start_byindex(songpos, NULL);
{
queue_item = db_queue_fetch_bypos(songpos, 0);
if (!queue_item)
{
ret = asprintf(errmsg, "Failed to start playback");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_UNKNOWN;
}
ret = player_playback_start_byitem(queue_item);
free_queue_item(queue_item, 0);
}
else
ret = player_playback_start(NULL);
ret = player_playback_start();
if (ret < 0)
{
@ -1200,6 +1202,7 @@ mpd_command_playid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
uint32_t id;
struct player_status status;
struct db_queue_item *queue_item;
int ret;
player_get_status(&status);
@ -1225,9 +1228,21 @@ mpd_command_playid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
}
if (id > 0)
ret = player_playback_start_byitemid(id, NULL);
{
queue_item = db_queue_fetch_byitemid(id);
if (!queue_item)
{
ret = asprintf(errmsg, "Failed to start playback");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_UNKNOWN;
}
ret = player_playback_start_byitem(queue_item);
free_queue_item(queue_item, 0);
}
else
ret = player_playback_start(NULL);
ret = player_playback_start();
if (ret < 0)
{
@ -1259,7 +1274,7 @@ mpd_command_previous(struct evbuffer *evbuf, int argc, char **argv, char **errms
return ACK_ERROR_UNKNOWN;
}
ret = player_playback_start(NULL);
ret = player_playback_start();
if (ret < 0)
{
ret = asprintf(errmsg, "Player returned an error for start after previtem");
@ -1279,7 +1294,6 @@ mpd_command_previous(struct evbuffer *evbuf, int argc, char **argv, char **errms
static int
mpd_command_seek(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct player_status status;
uint32_t songpos;
float seek_target_sec;
int seek_target_msec;
@ -1303,14 +1317,6 @@ mpd_command_seek(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
}
//TODO Allow seeking in songs not currently playing
player_get_status(&status);
if (status.pos_pl != songpos)
{
ret = asprintf(errmsg, "Given song is not the current playing one, seeking is not supported");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_UNKNOWN;
}
seek_target_sec = strtof(argv[2], NULL);
seek_target_msec = seek_target_sec * 1000;
@ -1325,7 +1331,7 @@ mpd_command_seek(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
return ACK_ERROR_UNKNOWN;
}
ret = player_playback_start(NULL);
ret = player_playback_start();
if (ret < 0)
{
ret = asprintf(errmsg, "Player returned an error for start after seekcur");
@ -1391,7 +1397,7 @@ mpd_command_seekid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
return ACK_ERROR_UNKNOWN;
}
ret = player_playback_start(NULL);
ret = player_playback_start();
if (ret < 0)
{
ret = asprintf(errmsg, "Player returned an error for start after seekcur");
@ -1436,7 +1442,7 @@ mpd_command_seekcur(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
return ACK_ERROR_UNKNOWN;
}
ret = player_playback_start(NULL);
ret = player_playback_start();
if (ret < 0)
{
ret = asprintf(errmsg, "Player returned an error for start after seekcur");
@ -1470,11 +1476,12 @@ mpd_command_stop(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
return 0;
}
static struct queue_item *
mpd_queueitem_make(char *path, int recursive)
static int
mpd_queue_add(char *path, int recursive)
{
struct query_params qp;
struct queue_item *items;
struct player_status status;
int ret;
memset(&qp, 0, sizeof(struct query_params));
@ -1495,10 +1502,12 @@ mpd_queueitem_make(char *path, int recursive)
DPRINTF(E_DBG, L_PLAYER, "Out of memory\n");
}
items = queueitem_make_byquery(&qp);
player_get_status(&status);
ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id);
sqlite3_free(qp.filter);
return items;
return ret;
}
/*
@ -1509,7 +1518,6 @@ mpd_queueitem_make(char *path, int recursive)
static int
mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct queue_item *items;
int ret;
if (argc < 2)
@ -1520,9 +1528,9 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
return ACK_ERROR_ARG;
}
items = mpd_queueitem_make(argv[1], 1);
ret = mpd_queue_add(argv[1], 1);
if (!items)
if (ret < 0)
{
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
if (ret < 0)
@ -1530,8 +1538,6 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
return ACK_ERROR_UNKNOWN;
}
player_queue_add(items, NULL);
return 0;
}
@ -1544,8 +1550,6 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
static int
mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct queue_item *items;
uint32_t item_id;
int ret;
if (argc < 2)
@ -1562,9 +1566,9 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
DPRINTF(E_LOG, L_MPD, "Adding at a specified position not supported for 'addid', adding songs at end of queue.\n");
}
items = mpd_queueitem_make(argv[1], 0);
ret = mpd_queue_add(argv[1], 0);
if (!items)
if (ret < 0)
{
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
if (ret < 0)
@ -1572,12 +1576,9 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
return ACK_ERROR_UNKNOWN;
}
player_queue_add(items, &item_id);
evbuffer_add_printf(evbuf,
"Id: %d\n",
item_id);
ret); // mpd_queue_add returns the item_id of the last inserted queue item
return 0;
}
@ -1597,7 +1598,7 @@ mpd_command_clear(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
DPRINTF(E_DBG, L_MPD, "Failed to stop playback\n");
}
player_queue_clear();
db_queue_clear();
return 0;
}
@ -1616,10 +1617,10 @@ mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
int count;
int ret;
// If argv[1] is ommited clear the whole queue except the current playing one
// If argv[1] is ommited clear the whole queue
if (argc < 2)
{
player_queue_clear();
db_queue_clear();
return 0;
}
@ -1635,7 +1636,7 @@ mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
count = end_pos - start_pos;
ret = player_queue_remove_byindex(start_pos, count);
ret = db_queue_delete_bypos(start_pos, count);
if (ret < 0)
{
ret = asprintf(errmsg, "Failed to remove %d songs starting at position %d", count, start_pos);
@ -1674,7 +1675,7 @@ mpd_command_deleteid(struct evbuffer *evbuf, int argc, char **argv, char **errms
return ACK_ERROR_ARG;
}
ret = player_queue_remove_byitemid(songid);
ret = db_queue_delete_byitemid(songid);
if (ret < 0)
{
ret = asprintf(errmsg, "Failed to remove song with id '%s'", argv[1]);
@ -1726,7 +1727,7 @@ mpd_command_move(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
return ACK_ERROR_ARG;
}
ret = player_queue_move_byindex(start_pos, to_pos);
ret = db_queue_move_bypos(start_pos, to_pos);
if (ret < 0)
{
ret = asprintf(errmsg, "Failed to move song at position %d to %d", start_pos, to_pos);
@ -1771,7 +1772,7 @@ mpd_command_moveid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
return ACK_ERROR_ARG;
}
ret = player_queue_move_byitemid(songid, to_pos);
ret = db_queue_move_byitemid(songid, to_pos);
if (ret < 0)
{
ret = asprintf(errmsg, "Failed to move song with id '%s' to index '%s'", argv[1], argv[2]);
@ -1793,12 +1794,9 @@ mpd_command_moveid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
static int
mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct queue *queue;
struct queue_item *item;
struct query_params query_params;
struct db_queue_item queue_item;
uint32_t songid;
int pos_pl;
int count;
int i;
int ret;
songid = 0;
@ -1815,39 +1813,38 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
}
}
// Get the whole queue (start_pos = 0, end_pos = -1)
queue = player_queue_get_byindex(0, 0);
memset(&query_params, 0, sizeof(struct query_params));
if (!queue)
if (songid > 0)
query_params.filter = sqlite3_mprintf("id = %d", songid);
ret = db_queue_enum_start(&query_params);
if (ret < 0)
{
// Queue is emtpy
return 0;
sqlite3_free(query_params.filter);
ret = asprintf(errmsg, "Failed to start queue enum for command playlistid: '%s'", argv[1]);
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_ARG;
}
pos_pl = 0;
count = queue_count(queue);
for (i = 0; i < count; i++)
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
{
item = queue_get_byindex(queue, i, 0);
if (songid == 0 || songid == queueitem_item_id(item))
{
ret = mpd_add_mediainfo_byid(evbuf, queueitem_id(item), queueitem_item_id(item), pos_pl);
ret = mpd_add_db_queue_item(evbuf, &queue_item);
if (ret < 0)
{
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queueitem_id(item));
queue_free(queue);
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue_item.file_id);
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
db_queue_enum_end(&query_params);
sqlite3_free(query_params.filter);
return ACK_ERROR_UNKNOWN;
}
}
pos_pl++;
}
queue_free(queue);
db_queue_enum_end(&query_params);
sqlite3_free(query_params.filter);
return 0;
}
@ -1863,17 +1860,15 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
static int
mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct queue *queue;
struct queue_item *item;
struct query_params query_params;
struct db_queue_item queue_item;
int start_pos;
int end_pos;
int count;
int pos_pl;
int i;
int ret;
start_pos = 0;
end_pos = 0;
memset(&query_params, 0, sizeof(struct query_params));
if (argc > 1)
{
@ -1885,46 +1880,41 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_ARG;
}
}
count = end_pos - start_pos;
if (start_pos < 0)
{
DPRINTF(E_DBG, L_MPD, "Command 'playlistinfo' called with pos < 0 (arg = '%s'), ignore arguments and return whole queue\n", argv[1]);
start_pos = 0;
count = 0;
else
query_params.filter = sqlite3_mprintf("pos >= %d AND pos < %d", start_pos, end_pos);
}
queue = player_queue_get_byindex(start_pos, count);
if (!queue)
ret = db_queue_enum_start(&query_params);
if (ret < 0)
{
// Queue is emtpy
return 0;
sqlite3_free(query_params.filter);
ret = asprintf(errmsg, "Failed to start queue enum for command playlistinfo: '%s'", argv[1]);
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_ARG;
}
pos_pl = start_pos;
count = queue_count(queue);
for (i = 0; i < count; i++)
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
{
item = queue_get_byindex(queue, i, 0);
ret = mpd_add_mediainfo_byid(evbuf, queueitem_id(item), queueitem_item_id(item), pos_pl);
ret = mpd_add_db_queue_item(evbuf, &queue_item);
if (ret < 0)
{
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queueitem_id(item));
queue_free(queue);
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue_item.file_id);
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
db_queue_enum_end(&query_params);
sqlite3_free(query_params.filter);
return ACK_ERROR_UNKNOWN;
}
pos_pl++;
}
queue_free(queue);
db_queue_enum_end(&query_params);
sqlite3_free(query_params.filter);
return 0;
}
@ -1936,46 +1926,42 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
static int
mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct queue *queue;
struct queue_item *item;
int pos_pl;
int count;
int i;
struct query_params query_params;
struct db_queue_item queue_item;
int ret;
/*
* forked-daapd does not keep track of changes in the queue based on the playlist version,
* therefor plchanges returns all songs in the queue as changed ignoring the given version.
*/
queue = player_queue_get_byindex(0, 0);
memset(&query_params, 0, sizeof(struct query_params));
if (!queue)
ret = db_queue_enum_start(&query_params);
if (ret < 0)
{
// Queue is emtpy
return 0;
ret = asprintf(errmsg, "Failed to start queue enum for command plchanges");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_ARG;
}
pos_pl = 0;
count = queue_count(queue);
for (i = 0; i < count; i++)
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
{
item = queue_get_byindex(queue, i, 0);
ret = mpd_add_mediainfo_byid(evbuf, queueitem_id(item), queueitem_item_id(item), pos_pl);
ret = mpd_add_db_queue_item(evbuf, &queue_item);
if (ret < 0)
{
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queueitem_id(item));
queue_free(queue);
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue_item.file_id);
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
db_queue_enum_end(&query_params);
return ACK_ERROR_UNKNOWN;
}
pos_pl++;
}
queue_free(queue);
db_queue_enum_end(&query_params);
return 0;
}
@ -1986,36 +1972,36 @@ mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errm
static int
mpd_command_plchangesposid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct queue *queue;
struct queue_item *item;
int count;
int i;
struct query_params query_params;
struct db_queue_item queue_item;
int ret;
/*
* forked-daapd does not keep track of changes in the queue based on the playlist version,
* therefor plchangesposid returns all songs in the queue as changed ignoring the given version.
*/
queue = player_queue_get_byindex(0, 0);
memset(&query_params, 0, sizeof(struct query_params));
if (!queue)
ret = db_queue_enum_start(&query_params);
if (ret < 0)
{
// Queue is emtpy
return 0;
ret = asprintf(errmsg, "Failed to start queue enum for command plchangesposid");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_ARG;
}
count = queue_count(queue);
for (i = 0; i < count; i++)
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
{
item = queue_get_byindex(queue, i, 0);
evbuffer_add_printf(evbuf,
"cpos: %d\n"
"Id: %d\n",
i,
queueitem_item_id(item));
queue_item.pos,
queue_item.id);
}
queue_free(queue);
db_queue_enum_end(&query_params);
return 0;
}
@ -2239,7 +2225,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
char path[PATH_MAX];
struct playlist_info *pli;
struct queue_item *items;
struct player_status status;
int ret;
if (argc < 2)
@ -2274,20 +2260,18 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
//TODO If a second parameter is given only add the specified range of songs to the playqueue
items = queueitem_make_byplid(pli->id);
player_get_status(&status);
if (!items)
ret = db_queue_add_by_playlistid(pli->id, status.shuffle, status.item_id);
free_pli(pli, 0);
if (ret < 0)
{
free_pli(pli, 0);
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_UNKNOWN;
}
player_queue_add(items, NULL);
return 0;
}
@ -2436,6 +2420,7 @@ mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
if (ret < 0)
{
db_query_end(&qp);
sqlite3_free(qp.filter);
ret = asprintf(errmsg, "Could not start query");
if (ret < 0)
@ -2447,6 +2432,7 @@ mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
if (ret < 0)
{
db_query_end(&qp);
sqlite3_free(qp.filter);
ret = asprintf(errmsg, "Could not fetch query count");
if (ret < 0)
@ -2461,6 +2447,7 @@ mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
(fci.length / 1000));
db_query_end(&qp);
sqlite3_free(qp.filter);
return 0;
}
@ -2492,6 +2479,7 @@ mpd_command_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
if (ret < 0)
{
db_query_end(&qp);
sqlite3_free(qp.filter);
ret = asprintf(errmsg, "Could not start query");
if (ret < 0)
@ -2509,6 +2497,7 @@ mpd_command_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
}
db_query_end(&qp);
sqlite3_free(qp.filter);
return 0;
}
@ -2517,7 +2506,7 @@ static int
mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct query_params qp;
struct queue_item *items;
struct player_status status;
int ret;
if (argc < 3 || ((argc - 1) % 2) != 0)
@ -2536,9 +2525,11 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
mpd_get_query_params_find(argc - 1, argv + 1, &qp);
items = queueitem_make_byquery(&qp);
player_get_status(&status);
if (!items)
ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id);
sqlite3_free(qp.filter);
if (ret < 0)
{
ret = asprintf(errmsg, "Failed to add songs to playlist");
if (ret < 0)
@ -2546,8 +2537,6 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
return ACK_ERROR_UNKNOWN;
}
player_queue_add(items, NULL);
return 0;
}
@ -2639,6 +2628,7 @@ mpd_command_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
if (ret < 0)
{
db_query_end(&qp);
sqlite3_free(qp.filter);
ret = asprintf(errmsg, "Could not start query");
if (ret < 0)
@ -2682,6 +2672,7 @@ mpd_command_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
}
db_query_end(&qp);
sqlite3_free(qp.filter);
return 0;
}
@ -3121,6 +3112,7 @@ mpd_command_search(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
if (ret < 0)
{
db_query_end(&qp);
sqlite3_free(qp.filter);
ret = asprintf(errmsg, "Could not start query");
if (ret < 0)
@ -3138,6 +3130,7 @@ mpd_command_search(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
}
db_query_end(&qp);
sqlite3_free(qp.filter);
return 0;
}
@ -3146,7 +3139,7 @@ static int
mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct query_params qp;
struct queue_item *items;
struct player_status status;
int ret;
if (argc < 3 || ((argc - 1) % 2) != 0)
@ -3165,9 +3158,11 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm
mpd_get_query_params_search(argc - 1, argv + 1, &qp);
items = queueitem_make_byquery(&qp);
player_get_status(&status);
if (!items)
ret = db_queue_add_by_query(&qp, status.shuffle, status.item_id);
sqlite3_free(qp.filter);
if (ret < 0)
{
ret = asprintf(errmsg, "Failed to add songs to playlist");
if (ret < 0)
@ -3175,8 +3170,6 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm
return ACK_ERROR_UNKNOWN;
}
player_queue_add(items, NULL);
return 0;
}

View File

@ -821,12 +821,9 @@ raop_metadata_prune(uint64_t rtptime)
static void *
raop_metadata_prepare(int id)
{
struct query_params qp;
struct db_media_file_info dbmfi;
char filter[32];
struct db_queue_item *queue_item;
struct raop_metadata *rmd;
struct evbuffer *tmp;
uint64_t duration;
int ret;
rmd = (struct raop_metadata *)malloc(sizeof(struct raop_metadata));
@ -839,6 +836,14 @@ raop_metadata_prepare(int id)
memset(rmd, 0, sizeof(struct raop_metadata));
queue_item = db_queue_fetch_byitemid(id);
if (!queue_item)
{
DPRINTF(E_LOG, L_RAOP, "Out of memory for queue item\n");
goto out_rmd;
}
/* Get artwork */
rmd->artwork = evbuffer_new();
if (!rmd->artwork)
@ -848,7 +853,7 @@ raop_metadata_prepare(int id)
goto skip_artwork;
}
ret = artwork_get_item(rmd->artwork, id, 600, 600);
ret = artwork_get_item(rmd->artwork, queue_item->file_id, 600, 600);
if (ret < 0)
{
DPRINTF(E_INFO, L_RAOP, "Failed to retrieve artwork for file id %d; no artwork will be sent\n", id);
@ -861,44 +866,13 @@ raop_metadata_prepare(int id)
skip_artwork:
/* Get dbmfi */
memset(&qp, 0, sizeof(struct query_params));
qp.type = Q_ITEMS;
qp.idx_type = I_NONE;
qp.sort = S_NONE;
qp.filter = filter;
ret = snprintf(filter, sizeof(filter), "id = %d", id);
if ((ret < 0) || (ret >= sizeof(filter)))
{
DPRINTF(E_LOG, L_RAOP, "Could not build filter for file id %d; metadata will not be sent\n", id);
goto out_rmd;
}
ret = db_query_start(&qp);
if (ret < 0)
{
DPRINTF(E_LOG, L_RAOP, "Couldn't start query; no metadata will be sent\n");
goto out_rmd;
}
ret = db_query_fetch_file(&qp, &dbmfi);
if (ret < 0)
{
DPRINTF(E_LOG, L_RAOP, "Couldn't fetch file id %d; metadata will not be sent\n", id);
goto out_query;
}
/* Turn it into DAAP metadata */
tmp = evbuffer_new();
if (!tmp)
{
DPRINTF(E_LOG, L_RAOP, "Out of memory for temporary metadata evbuffer; metadata will not be sent\n");
goto out_query;
goto out_qi;
}
rmd->metadata = evbuffer_new();
@ -907,10 +881,10 @@ raop_metadata_prepare(int id)
DPRINTF(E_LOG, L_RAOP, "Out of memory for metadata evbuffer; metadata will not be sent\n");
evbuffer_free(tmp);
goto out_query;
goto out_qi;
}
ret = dmap_encode_file_metadata(rmd->metadata, tmp, &dbmfi, NULL, 0, 0, 1);
ret = dmap_encode_queue_metadata(rmd->metadata, tmp, queue_item);
evbuffer_free(tmp);
if (ret < 0)
{
@ -919,27 +893,18 @@ raop_metadata_prepare(int id)
goto out_metadata;
}
/* Progress */
ret = safe_atou64(dbmfi.song_length, &duration);
if (ret < 0)
{
DPRINTF(E_LOG, L_RAOP, "Failed to convert song_length to integer; no metadata will be sent\n");
goto out_metadata;
}
db_query_end(&qp);
/* raop_metadata_send() will add rtptime to these */
/* Progress - raop_metadata_send() will add rtptime to these */
rmd->start = 0;
rmd->end = (duration * 44100UL) / 1000UL;
rmd->end = (queue_item->song_length * 44100UL) / 1000UL;
free_queue_item(queue_item, 0);
return rmd;
out_metadata:
evbuffer_free(rmd->metadata);
out_query:
db_query_end(&qp);
out_qi:
free_queue_item(queue_item, 0);
out_rmd:
free(rmd);

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,6 @@
#include <stdint.h>
#include "db.h"
#include "queue.h"
/* AirTunes v2 packet interval in ns */
/* (352 samples/packet * 1e9 ns/s) / 44100 samples/s = 7981859 ns/packet */
@ -28,6 +27,12 @@ enum play_status {
PLAY_PLAYING = 4,
};
enum repeat_mode {
REPEAT_OFF = 0,
REPEAT_SONG = 1,
REPEAT_ALL = 2,
};
struct spk_flags {
unsigned selected:1;
unsigned has_password:1;
@ -44,13 +49,6 @@ struct player_status {
/* Playlist id */
uint32_t plid;
/* Playlist version
After startup plversion is 0 and gets incremented after each change of the playlist
(e. g. after adding/moving/removing items). It is used by mpd clients to recognize if
they need to update the current playlist. */
uint32_t plversion;
/* Playlist length */
uint32_t playlistlength;
/* Id of the playing file/item in the files database */
uint32_t id;
/* Item-Id of the playing file/item in the queue */
@ -59,14 +57,6 @@ struct player_status {
uint32_t pos_ms;
/* Length in ms of playing item */
uint32_t len_ms;
/* Playlist position of playing item*/
int pos_pl;
/* Item id of next item in playlist */
uint32_t next_id;
/* Item-Id of the next file/item in the queue */
uint32_t next_item_id;
/* Playlist position of next item */
int next_pos_pl;
};
typedef void (*spk_enum_cb)(uint64_t id, const char *name, int relvol, int absvol, struct spk_flags flags, void *arg);
@ -104,16 +94,10 @@ int
player_speaker_set(uint64_t *ids);
int
player_playback_start(uint32_t *id);
player_playback_start();
int
player_playback_start_byindex(int pos, uint32_t *id);
int
player_playback_start_bypos(int pos, uint32_t *id);
int
player_playback_start_byitemid(uint32_t item_id, uint32_t *id);
player_playback_start_byitem(struct db_queue_item *queue_item);
int
player_playback_stop(void);
@ -147,39 +131,6 @@ int
player_shuffle_set(int enable);
struct queue *
player_queue_get_bypos(int count);
struct queue *
player_queue_get_byindex(int pos, int count);
int
player_queue_add(struct queue_item *items, uint32_t *item_id);
int
player_queue_add_next(struct queue_item *items);
int
player_queue_move_bypos(int ps_pos_from, int ps_pos_to);
int
player_queue_move_byindex(int pos_from, int pos_to);
int
player_queue_move_byitemid(uint32_t item_id, int pos_to);
int
player_queue_remove_bypos(int pos);
int
player_queue_remove_byindex(int pos, int count);
int
player_queue_remove_byitemid(uint32_t id);
void
player_queue_clear(void);
void
player_queue_clear_history(void);

File diff suppressed because it is too large Load Diff

View File

@ -1,116 +0,0 @@
#ifndef SRC_QUEUE_H_
#define SRC_QUEUE_H_
#include "db.h"
enum repeat_mode {
REPEAT_OFF = 0,
REPEAT_SONG = 1,
REPEAT_ALL = 2,
};
/*
* Internal representation of a queue
*/
struct queue;
/*
* Internal representation of a list of queue items
*/
struct queue_item;
struct queue *
queue_new();
void
queue_free(struct queue *queue);
unsigned int
queue_count(struct queue *queue);
int
queueitem_pos(struct queue_item *item, uint32_t id);
uint32_t
queueitem_id(struct queue_item *item);
unsigned int
queueitem_item_id(struct queue_item *item);
unsigned int
queueitem_len(struct queue_item *item);
enum data_kind
queueitem_data_kind(struct queue_item *item);
enum media_kind
queueitem_media_kind(struct queue_item *item);
struct queue_item *
queue_get_byitemid(struct queue *queue, unsigned int item_id);
struct queue_item *
queue_get_byindex(struct queue *queue, unsigned int index, char shuffle);
struct queue_item *
queue_get_bypos(struct queue *queue, unsigned int item_id, unsigned int pos, char shuffle);
int
queue_index_byitemid(struct queue *queue, unsigned int item_id, char shuffle);
struct queue_item *
queue_next(struct queue *queue, unsigned int item_id, char shuffle, enum repeat_mode r_mode, int reshuffle);
struct queue_item *
queue_prev(struct queue *queue, unsigned int item_id, char shuffle, enum repeat_mode r_mode);
struct queue *
queue_new_byindex(struct queue *queue, unsigned int index, unsigned int count, char shuffle);
struct queue *
queue_new_bypos(struct queue *queue, unsigned int item_id, unsigned int count, char shuffle);
void
queue_add(struct queue *queue, struct queue_item *item);
void
queue_add_after(struct queue *queue, struct queue_item *item, unsigned int item_id);
void
queue_move_bypos(struct queue *queue, unsigned int item_id, unsigned int from_pos, unsigned int to_offset, char shuffle);
void
queue_move_byindex(struct queue *queue, unsigned int from_pos, unsigned int to_pos, char shuffle);
void
queue_move_byitemid(struct queue *queue, unsigned int item_id, unsigned int to_pos, char shuffle);
void
queue_remove_byitemid(struct queue *queue, unsigned int item_id);
void
queue_remove_byindex(struct queue *queue, unsigned int index, char shuffle);
void
queue_remove_bypos(struct queue *queue, unsigned int item_id, unsigned int pos, char shuffle);
void
queue_clear(struct queue *queue);
void
queue_shuffle(struct queue *queue, unsigned int item_id);
struct queue_item *
queueitem_make_byquery(struct query_params *qp);
struct queue_item *
queueitem_make_byplid(int plid);
struct queue_item *
queueitem_make_byid(uint32_t id);
#endif /* SRC_QUEUE_H_ */

View File

@ -128,11 +128,11 @@ rng_rand_range(struct rng_ctx *ctx, int32_t min, int32_t max)
* Durstenfeld in-place shuffling variant
*/
void
shuffle_ptr(struct rng_ctx *ctx, void **values, int len)
shuffle_int(struct rng_ctx *ctx, int *values, int len)
{
int i;
int32_t j;
void *tmp;
int tmp;
for (i = len - 1; i > 0; i--)
{
@ -143,4 +143,3 @@ shuffle_ptr(struct rng_ctx *ctx, void **values, int len)
values[j] = tmp;
}
}

View File

@ -19,7 +19,7 @@ int32_t
rng_rand_range(struct rng_ctx *ctx, int32_t min, int32_t max);
void
shuffle_ptr(struct rng_ctx *ctx, void **values, int len);
shuffle_int(struct rng_ctx *ctx, int *values, int len);
#endif /* !__RNG_H__ */