mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-27 06:33:21 -05:00
commit
9ba512a340
@ -105,7 +105,6 @@ forked_daapd_SOURCES = main.c \
|
|||||||
rsp_query.c rsp_query.h \
|
rsp_query.c rsp_query.h \
|
||||||
daap_query.c daap_query.h \
|
daap_query.c daap_query.h \
|
||||||
player.c player.h \
|
player.c player.h \
|
||||||
queue.c queue.h \
|
|
||||||
worker.c worker.h \
|
worker.c worker.h \
|
||||||
outputs.h outputs.c \
|
outputs.h outputs.c \
|
||||||
outputs/raop.c outputs/streaming.c outputs/dummy.c outputs/fifo.c \
|
outputs/raop.c outputs/streaming.c outputs/dummy.c outputs/fifo.c \
|
||||||
|
136
src/db.h
136
src/db.h
@ -28,6 +28,8 @@ enum sort_type {
|
|||||||
S_DISC,
|
S_DISC,
|
||||||
S_TRACK,
|
S_TRACK,
|
||||||
S_VPATH,
|
S_VPATH,
|
||||||
|
S_POS,
|
||||||
|
S_SHUFFLE_POS,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define Q_F_BROWSE (1 << 15)
|
#define Q_F_BROWSE (1 << 15)
|
||||||
@ -374,6 +376,49 @@ struct directory_enum {
|
|||||||
sqlite3_stmt *stmt;
|
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 *
|
char *
|
||||||
db_escape_string(const char *str);
|
db_escape_string(const char *str);
|
||||||
|
|
||||||
@ -392,6 +437,9 @@ free_pli(struct playlist_info *pli, int content_only);
|
|||||||
void
|
void
|
||||||
free_di(struct directory_info *di, int content_only);
|
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 */
|
/* Maintenance and DB hygiene */
|
||||||
void
|
void
|
||||||
db_hook_post_scan(void);
|
db_hook_post_scan(void);
|
||||||
@ -409,6 +457,9 @@ db_transaction_begin(void);
|
|||||||
void
|
void
|
||||||
db_transaction_end(void);
|
db_transaction_end(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
db_transaction_rollback(void);
|
||||||
|
|
||||||
/* Queries */
|
/* Queries */
|
||||||
int
|
int
|
||||||
db_query_start(struct query_params *qp);
|
db_query_start(struct query_params *qp);
|
||||||
@ -498,9 +549,6 @@ db_file_add(struct media_file_info *mfi);
|
|||||||
int
|
int
|
||||||
db_file_update(struct media_file_info *mfi);
|
db_file_update(struct media_file_info *mfi);
|
||||||
|
|
||||||
void
|
|
||||||
db_file_update_icy(int id, char *artist, char *album);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
db_file_save_seek(int id, uint32_t seek);
|
db_file_save_seek(int id, uint32_t seek);
|
||||||
|
|
||||||
@ -646,6 +694,88 @@ db_speaker_get(uint64_t id, int *selected, int *volume);
|
|||||||
void
|
void
|
||||||
db_speaker_clear_all(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 */
|
/* Inotify */
|
||||||
int
|
int
|
||||||
db_watch_clear(void);
|
db_watch_clear(void);
|
||||||
|
@ -158,6 +158,32 @@
|
|||||||
" parent_id INTEGER DEFAULT 0" \
|
" 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 \
|
#define TRG_GROUPS_INSERT_FILES \
|
||||||
"CREATE TRIGGER update_groups_new_file AFTER INSERT ON files FOR EACH ROW" \
|
"CREATE TRIGGER update_groups_new_file AFTER INSERT ON files FOR EACH ROW" \
|
||||||
" BEGIN" \
|
" BEGIN" \
|
||||||
@ -216,6 +242,9 @@
|
|||||||
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
"INSERT INTO directories (id, virtual_path, db_timestamp, disabled, parent_id)" \
|
||||||
" VALUES (4, '/spotify:', 0, 4294967296, 1);"
|
" VALUES (4, '/spotify:', 0, 4294967296, 1);"
|
||||||
|
|
||||||
|
#define Q_QUEUE_VERSION \
|
||||||
|
"INSERT INTO admin (key, value) VALUES ('queue_version', '0');"
|
||||||
|
|
||||||
#define Q_SCVER_MAJOR \
|
#define Q_SCVER_MAJOR \
|
||||||
"INSERT INTO admin (key, value) VALUES ('schema_version_major', '%d');"
|
"INSERT INTO admin (key, value) VALUES ('schema_version_major', '%d');"
|
||||||
#define Q_SCVER_MINOR \
|
#define Q_SCVER_MINOR \
|
||||||
@ -237,6 +266,7 @@ static const struct db_init_query db_init_table_queries[] =
|
|||||||
{ T_SPEAKERS, "create table speakers" },
|
{ T_SPEAKERS, "create table speakers" },
|
||||||
{ T_INOTIFY, "create table inotify" },
|
{ T_INOTIFY, "create table inotify" },
|
||||||
{ T_DIRECTORIES, "create table directories" },
|
{ T_DIRECTORIES, "create table directories" },
|
||||||
|
{ T_QUEUE, "create table queue" },
|
||||||
|
|
||||||
{ TRG_GROUPS_INSERT_FILES, "create trigger update_groups_new_file" },
|
{ TRG_GROUPS_INSERT_FILES, "create trigger update_groups_new_file" },
|
||||||
{ TRG_GROUPS_UPDATE_FILES, "create trigger update_groups_update_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_DIR2, "create default base directory '/file:'" },
|
||||||
{ Q_DIR3, "create default base directory '/http:'" },
|
{ Q_DIR3, "create default base directory '/http:'" },
|
||||||
{ Q_DIR4, "create default base directory '/spotify:'" },
|
{ 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 \
|
#define I_DIR_PARENT \
|
||||||
"CREATE INDEX IF NOT EXISTS idx_dir_parentid ON directories(parent_id);"
|
"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[] =
|
static const struct db_init_query db_init_index_queries[] =
|
||||||
{
|
{
|
||||||
{ I_RESCAN, "create rescan index" },
|
{ 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_VPATH, "create directories disabled_virtualpath index" },
|
||||||
{ I_DIR_PARENT, "create directories parentid index" },
|
{ I_DIR_PARENT, "create directories parentid index" },
|
||||||
|
|
||||||
|
{ I_QUEUE_POS, "create queue pos index" },
|
||||||
|
{ I_QUEUE_SHUFFLEPOS, "create queue shuffle pos index" },
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* is a major upgrade. In other words minor version upgrades permit downgrading
|
* is a major upgrade. In other words minor version upgrades permit downgrading
|
||||||
* forked-daapd after the database was upgraded. */
|
* forked-daapd after the database was upgraded. */
|
||||||
#define SCHEMA_VERSION_MAJOR 19
|
#define SCHEMA_VERSION_MAJOR 19
|
||||||
#define SCHEMA_VERSION_MINOR 00
|
#define SCHEMA_VERSION_MINOR 01
|
||||||
|
|
||||||
int
|
int
|
||||||
db_init_indices(sqlite3 *hdl);
|
db_init_indices(sqlite3 *hdl);
|
||||||
|
@ -1441,6 +1441,54 @@ db_upgrade_v19(sqlite3 *hdl)
|
|||||||
return 0;
|
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
|
int
|
||||||
db_upgrade(sqlite3 *hdl, int db_ver)
|
db_upgrade(sqlite3 *hdl, int db_ver)
|
||||||
{
|
{
|
||||||
@ -1551,6 +1599,13 @@ db_upgrade(sqlite3 *hdl, int db_ver)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -1;
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -559,3 +559,78 @@ dmap_encode_file_metadata(struct evbuffer *songlist, struct evbuffer *song, stru
|
|||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
@ -84,4 +84,7 @@ dmap_send_error(struct evhttp_request *req, const char *container, const char *e
|
|||||||
int
|
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);
|
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__ */
|
#endif /* !__DMAP_HELPERS_H__ */
|
||||||
|
@ -1227,6 +1227,7 @@ bulk_scan(int flags)
|
|||||||
|
|
||||||
DPRINTF(E_DBG, L_SCAN, "Purging old database content\n");
|
DPRINTF(E_DBG, L_SCAN, "Purging old database content\n");
|
||||||
db_purge_cruft(start);
|
db_purge_cruft(start);
|
||||||
|
db_queue_cleanup();
|
||||||
cache_artwork_purge_cruft(start);
|
cache_artwork_purge_cruft(start);
|
||||||
|
|
||||||
DPRINTF(E_LOG, L_SCAN, "Bulk library scan completed in %.f sec\n", difftime(end, 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 *
|
static void *
|
||||||
filescanner(void *arg)
|
filescanner(void *arg)
|
||||||
{
|
{
|
||||||
|
int clear_queue_on_stop_disabled;
|
||||||
int ret;
|
int ret;
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
struct sched_param param;
|
struct sched_param param;
|
||||||
@ -1284,6 +1286,19 @@ filescanner(void *arg)
|
|||||||
pthread_exit(NULL);
|
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
|
/* Recompute all songartistids and songalbumids, in case the SQLite DB got transferred
|
||||||
* to a different host; the hash is not portable.
|
* to a different host; the hash is not portable.
|
||||||
* It will also rebuild the groups we just cleared.
|
* 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");
|
DPRINTF(E_LOG, L_SCAN, "Full rescan triggered\n");
|
||||||
|
|
||||||
player_playback_stop();
|
player_playback_stop();
|
||||||
player_queue_clear();
|
db_queue_clear();
|
||||||
inofd_event_unset(); // Clears all inotify watches
|
inofd_event_unset(); // Clears all inotify watches
|
||||||
db_purge_all(); // Clears files, playlists, playlistitems, inotify and groups
|
db_purge_all(); // Clears files, playlists, playlistitems, inotify and groups
|
||||||
|
|
||||||
|
480
src/httpd_dacp.c
480
src/httpd_dacp.c
File diff suppressed because it is too large
Load Diff
427
src/mpd.c
427
src/mpd.c
@ -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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -61,7 +61,6 @@
|
|||||||
#include "artwork.h"
|
#include "artwork.h"
|
||||||
|
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "queue.h"
|
|
||||||
#include "filescanner.h"
|
#include "filescanner.h"
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
|
|
||||||
@ -396,18 +395,16 @@ mpd_parse_args(char *args, int *argc, char **argv)
|
|||||||
* Id: 1
|
* Id: 1
|
||||||
*
|
*
|
||||||
* @param evbuf the response event buffer
|
* @param evbuf the response event buffer
|
||||||
* @param mfi media information
|
* @param queue_item queue item information
|
||||||
* @param item_id queue-item id
|
|
||||||
* @param pos_pl position in the playqueue, if -1 the position is ignored
|
|
||||||
* @return the number of bytes added if successful, or -1 if an error occurred.
|
* @return the number of bytes added if successful, or -1 if an error occurred.
|
||||||
*/
|
*/
|
||||||
static int
|
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];
|
char modified[32];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mpd_time(modified, sizeof(modified), mfi->time_modified);
|
mpd_time(modified, sizeof(modified), queue_item->time_modified);
|
||||||
|
|
||||||
ret = evbuffer_add_printf(evbuf,
|
ret = evbuffer_add_printf(evbuf,
|
||||||
"file: %s\n"
|
"file: %s\n"
|
||||||
@ -422,65 +419,28 @@ mpd_add_mediainfo(struct evbuffer *evbuf, struct media_file_info *mfi, unsigned
|
|||||||
"Track: %d\n"
|
"Track: %d\n"
|
||||||
"Date: %d\n"
|
"Date: %d\n"
|
||||||
"Genre: %s\n"
|
"Genre: %s\n"
|
||||||
"Disc: %d\n",
|
"Disc: %d\n"
|
||||||
(mfi->virtual_path + 1),
|
"Pos: %d\n"
|
||||||
|
"Id: %d\n",
|
||||||
|
(queue_item->virtual_path + 1),
|
||||||
modified,
|
modified,
|
||||||
(mfi->song_length / 1000),
|
(queue_item->song_length / 1000),
|
||||||
mfi->artist,
|
queue_item->artist,
|
||||||
mfi->album_artist,
|
queue_item->album_artist,
|
||||||
mfi->artist_sort,
|
queue_item->artist_sort,
|
||||||
mfi->album_artist_sort,
|
queue_item->album_artist_sort,
|
||||||
mfi->album,
|
queue_item->album,
|
||||||
mfi->title,
|
queue_item->title,
|
||||||
mfi->track,
|
queue_item->track,
|
||||||
mfi->year,
|
queue_item->year,
|
||||||
mfi->genre,
|
queue_item->genre,
|
||||||
mfi->disc);
|
queue_item->disc,
|
||||||
|
queue_item->pos,
|
||||||
if (ret >= 0 && pos_pl >= 0)
|
queue_item->id);
|
||||||
{
|
|
||||||
ret = evbuffer_add_printf(evbuf,
|
|
||||||
"Pos: %d\n",
|
|
||||||
pos_pl);
|
|
||||||
|
|
||||||
if (ret >= 0)
|
|
||||||
{
|
|
||||||
ret = evbuffer_add_printf(evbuf,
|
|
||||||
"Id: %d\n",
|
|
||||||
item_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
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.
|
* 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 player_status status;
|
||||||
|
struct db_queue_item *queue_item;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
player_get_status(&status);
|
player_get_status(&status);
|
||||||
@ -578,7 +539,20 @@ mpd_command_currentsong(struct evbuffer *evbuf, int argc, char **argv, char **er
|
|||||||
return 0;
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", status.id);
|
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)
|
mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct player_status status;
|
struct player_status status;
|
||||||
|
int queue_length;
|
||||||
|
int queue_version;
|
||||||
char *state;
|
char *state;
|
||||||
|
int pos_pl;
|
||||||
|
struct db_queue_item *next_item;
|
||||||
|
|
||||||
player_get_status(&status);
|
player_get_status(&status);
|
||||||
|
|
||||||
@ -736,6 +714,9 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queue_version = db_queue_get_version();
|
||||||
|
queue_length = db_queue_get_count();
|
||||||
|
|
||||||
evbuffer_add_printf(evbuf,
|
evbuffer_add_printf(evbuf,
|
||||||
"volume: %d\n"
|
"volume: %d\n"
|
||||||
"repeat: %d\n"
|
"repeat: %d\n"
|
||||||
@ -751,12 +732,14 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
status.shuffle,
|
status.shuffle,
|
||||||
(status.repeat == REPEAT_SONG ? 1 : 0),
|
(status.repeat == REPEAT_SONG ? 1 : 0),
|
||||||
0 /* consume: not supported by forked-daapd, always return 'off' */,
|
0 /* consume: not supported by forked-daapd, always return 'off' */,
|
||||||
status.plversion,
|
queue_version,
|
||||||
status.playlistlength,
|
queue_length,
|
||||||
state);
|
state);
|
||||||
|
|
||||||
if (status.status != PLAY_STOPPED)
|
if (status.status != PLAY_STOPPED)
|
||||||
{
|
{
|
||||||
|
pos_pl = db_queue_get_pos(status.item_id, 0);
|
||||||
|
|
||||||
evbuffer_add_printf(evbuf,
|
evbuffer_add_printf(evbuf,
|
||||||
"song: %d\n"
|
"song: %d\n"
|
||||||
"songid: %d\n"
|
"songid: %d\n"
|
||||||
@ -764,7 +747,7 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
"elapsed: %#.3f\n"
|
"elapsed: %#.3f\n"
|
||||||
"bitrate: 128\n"
|
"bitrate: 128\n"
|
||||||
"audio: 44100:16:2\n",
|
"audio: 44100:16:2\n",
|
||||||
status.pos_pl,
|
pos_pl,
|
||||||
status.item_id,
|
status.item_id,
|
||||||
(status.pos_ms / 1000), (status.len_ms / 1000),
|
(status.pos_ms / 1000), (status.len_ms / 1000),
|
||||||
(status.pos_ms / 1000.0));
|
(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)
|
if (status.status != PLAY_STOPPED)
|
||||||
{
|
{
|
||||||
|
next_item = db_queue_fetch_next(status.item_id, status.shuffle);
|
||||||
|
if (next_item)
|
||||||
|
{
|
||||||
evbuffer_add_printf(evbuf,
|
evbuffer_add_printf(evbuf,
|
||||||
"nextsong: %d\n"
|
"nextsong: %d\n"
|
||||||
"nextsongid: %d\n",
|
"nextsongid: %d\n",
|
||||||
status.next_pos_pl,
|
next_item->id,
|
||||||
status.next_item_id);
|
next_item->pos);
|
||||||
|
|
||||||
|
free_queue_item(next_item, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1074,7 +1063,7 @@ mpd_command_next(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Player returned an error for start after nextitem");
|
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)
|
if (pause == 1)
|
||||||
ret = player_playback_pause();
|
ret = player_playback_pause();
|
||||||
else
|
else
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start();
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -1145,10 +1134,9 @@ mpd_command_play(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
{
|
{
|
||||||
int songpos;
|
int songpos;
|
||||||
struct player_status status;
|
struct player_status status;
|
||||||
|
struct db_queue_item *queue_item;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
player_get_status(&status);
|
|
||||||
|
|
||||||
songpos = 0;
|
songpos = 0;
|
||||||
if (argc > 1)
|
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)
|
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]);
|
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)
|
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
|
else
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start();
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -1200,6 +1202,7 @@ mpd_command_playid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
{
|
{
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
struct player_status status;
|
struct player_status status;
|
||||||
|
struct db_queue_item *queue_item;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
player_get_status(&status);
|
player_get_status(&status);
|
||||||
@ -1225,9 +1228,21 @@ mpd_command_playid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id > 0)
|
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
|
else
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start();
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -1259,7 +1274,7 @@ mpd_command_previous(struct evbuffer *evbuf, int argc, char **argv, char **errms
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Player returned an error for start after previtem");
|
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
|
static int
|
||||||
mpd_command_seek(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_seek(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct player_status status;
|
|
||||||
uint32_t songpos;
|
uint32_t songpos;
|
||||||
float seek_target_sec;
|
float seek_target_sec;
|
||||||
int seek_target_msec;
|
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
|
//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_sec = strtof(argv[2], NULL);
|
||||||
seek_target_msec = seek_target_sec * 1000;
|
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;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Player returned an error for start after seekcur");
|
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;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Player returned an error for start after seekcur");
|
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;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_playback_start(NULL);
|
ret = player_playback_start();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Player returned an error for start after seekcur");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct queue_item *
|
static int
|
||||||
mpd_queueitem_make(char *path, int recursive)
|
mpd_queue_add(char *path, int recursive)
|
||||||
{
|
{
|
||||||
struct query_params qp;
|
struct query_params qp;
|
||||||
struct queue_item *items;
|
struct player_status status;
|
||||||
|
int ret;
|
||||||
|
|
||||||
memset(&qp, 0, sizeof(struct query_params));
|
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");
|
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);
|
sqlite3_free(qp.filter);
|
||||||
return items;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1509,7 +1518,6 @@ mpd_queueitem_make(char *path, int recursive)
|
|||||||
static int
|
static int
|
||||||
mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct queue_item *items;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
@ -1520,9 +1528,9 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
return ACK_ERROR_ARG;
|
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]);
|
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1530,8 +1538,6 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_add(items, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1544,8 +1550,6 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
static int
|
static int
|
||||||
mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct queue_item *items;
|
|
||||||
uint32_t item_id;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 2)
|
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");
|
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]);
|
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1572,12 +1576,9 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
player_queue_add(items, &item_id);
|
|
||||||
|
|
||||||
evbuffer_add_printf(evbuf,
|
evbuffer_add_printf(evbuf,
|
||||||
"Id: %d\n",
|
"Id: %d\n",
|
||||||
item_id);
|
ret); // mpd_queue_add returns the item_id of the last inserted queue item
|
||||||
|
|
||||||
return 0;
|
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");
|
DPRINTF(E_DBG, L_MPD, "Failed to stop playback\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_clear();
|
db_queue_clear();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1616,10 +1617,10 @@ mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
int count;
|
int count;
|
||||||
int ret;
|
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)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
player_queue_clear();
|
db_queue_clear();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1635,7 +1636,7 @@ mpd_command_delete(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
|
|
||||||
count = end_pos - start_pos;
|
count = end_pos - start_pos;
|
||||||
|
|
||||||
ret = player_queue_remove_byindex(start_pos, count);
|
ret = db_queue_delete_bypos(start_pos, count);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Failed to remove %d songs starting at position %d", count, start_pos);
|
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;
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_queue_remove_byitemid(songid);
|
ret = db_queue_delete_byitemid(songid);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Failed to remove song with id '%s'", argv[1]);
|
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;
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Failed to move song at position %d to %d", start_pos, to_pos);
|
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;
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = player_queue_move_byitemid(songid, to_pos);
|
ret = db_queue_move_byitemid(songid, to_pos);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Failed to move song with id '%s' to index '%s'", argv[1], argv[2]);
|
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
|
static int
|
||||||
mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct queue *queue;
|
struct query_params query_params;
|
||||||
struct queue_item *item;
|
struct db_queue_item queue_item;
|
||||||
uint32_t songid;
|
uint32_t songid;
|
||||||
int pos_pl;
|
|
||||||
int count;
|
|
||||||
int i;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
songid = 0;
|
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)
|
memset(&query_params, 0, sizeof(struct query_params));
|
||||||
queue = player_queue_get_byindex(0, 0);
|
|
||||||
|
|
||||||
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
|
sqlite3_free(query_params.filter);
|
||||||
return 0;
|
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;
|
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
|
||||||
count = queue_count(queue);
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
item = queue_get_byindex(queue, i, 0);
|
ret = mpd_add_db_queue_item(evbuf, &queue_item);
|
||||||
if (songid == 0 || songid == queueitem_item_id(item))
|
|
||||||
{
|
|
||||||
ret = mpd_add_mediainfo_byid(evbuf, queueitem_id(item), queueitem_item_id(item), pos_pl);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queueitem_id(item));
|
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue_item.file_id);
|
||||||
|
|
||||||
queue_free(queue);
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
|
||||||
|
db_queue_enum_end(&query_params);
|
||||||
|
sqlite3_free(query_params.filter);
|
||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_pl++;
|
db_queue_enum_end(&query_params);
|
||||||
}
|
sqlite3_free(query_params.filter);
|
||||||
|
|
||||||
queue_free(queue);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1863,17 +1860,15 @@ mpd_command_playlistid(struct evbuffer *evbuf, int argc, char **argv, char **err
|
|||||||
static int
|
static int
|
||||||
mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct queue *queue;
|
struct query_params query_params;
|
||||||
struct queue_item *item;
|
struct db_queue_item queue_item;
|
||||||
int start_pos;
|
int start_pos;
|
||||||
int end_pos;
|
int end_pos;
|
||||||
int count;
|
|
||||||
int pos_pl;
|
|
||||||
int i;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
start_pos = 0;
|
start_pos = 0;
|
||||||
end_pos = 0;
|
end_pos = 0;
|
||||||
|
memset(&query_params, 0, sizeof(struct query_params));
|
||||||
|
|
||||||
if (argc > 1)
|
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");
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
return ACK_ERROR_ARG;
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
count = end_pos - start_pos;
|
|
||||||
|
|
||||||
if (start_pos < 0)
|
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]);
|
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;
|
else
|
||||||
count = 0;
|
query_params.filter = sqlite3_mprintf("pos >= %d AND pos < %d", start_pos, end_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
queue = player_queue_get_byindex(start_pos, count);
|
ret = db_queue_enum_start(&query_params);
|
||||||
|
if (ret < 0)
|
||||||
if (!queue)
|
|
||||||
{
|
{
|
||||||
// Queue is emtpy
|
sqlite3_free(query_params.filter);
|
||||||
return 0;
|
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;
|
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
|
||||||
count = queue_count(queue);
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
item = queue_get_byindex(queue, i, 0);
|
ret = mpd_add_db_queue_item(evbuf, &queue_item);
|
||||||
ret = mpd_add_mediainfo_byid(evbuf, queueitem_id(item), queueitem_item_id(item), pos_pl);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queueitem_id(item));
|
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue_item.file_id);
|
||||||
|
|
||||||
queue_free(queue);
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
|
||||||
|
db_queue_enum_end(&query_params);
|
||||||
|
sqlite3_free(query_params.filter);
|
||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_pl++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_free(queue);
|
db_queue_enum_end(&query_params);
|
||||||
|
sqlite3_free(query_params.filter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1936,46 +1926,42 @@ mpd_command_playlistinfo(struct evbuffer *evbuf, int argc, char **argv, char **e
|
|||||||
static int
|
static int
|
||||||
mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct queue *queue;
|
struct query_params query_params;
|
||||||
struct queue_item *item;
|
struct db_queue_item queue_item;
|
||||||
int pos_pl;
|
|
||||||
int count;
|
|
||||||
int i;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* forked-daapd does not keep track of changes in the queue based on the playlist version,
|
* 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.
|
* 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
|
ret = asprintf(errmsg, "Failed to start queue enum for command plchanges");
|
||||||
return 0;
|
if (ret < 0)
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_pl = 0;
|
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
|
||||||
count = queue_count(queue);
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
item = queue_get_byindex(queue, i, 0);
|
ret = mpd_add_db_queue_item(evbuf, &queue_item);
|
||||||
ret = mpd_add_mediainfo_byid(evbuf, queueitem_id(item), queueitem_item_id(item), pos_pl);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queueitem_id(item));
|
ret = asprintf(errmsg, "Error adding media info for file with id: %d", queue_item.file_id);
|
||||||
|
|
||||||
queue_free(queue);
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
|
||||||
|
db_queue_enum_end(&query_params);
|
||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_pl++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_free(queue);
|
db_queue_enum_end(&query_params);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1986,36 +1972,36 @@ mpd_command_plchanges(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
|||||||
static int
|
static int
|
||||||
mpd_command_plchangesposid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_plchangesposid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct queue *queue;
|
struct query_params query_params;
|
||||||
struct queue_item *item;
|
struct db_queue_item queue_item;
|
||||||
int count;
|
int ret;
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* forked-daapd does not keep track of changes in the queue based on the playlist version,
|
* 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.
|
* 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
|
ret = asprintf(errmsg, "Failed to start queue enum for command plchangesposid");
|
||||||
return 0;
|
if (ret < 0)
|
||||||
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
|
return ACK_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = queue_count(queue);
|
while ((ret = db_queue_enum_fetch(&query_params, &queue_item)) == 0 && queue_item.id > 0)
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
item = queue_get_byindex(queue, i, 0);
|
|
||||||
|
|
||||||
evbuffer_add_printf(evbuf,
|
evbuffer_add_printf(evbuf,
|
||||||
"cpos: %d\n"
|
"cpos: %d\n"
|
||||||
"Id: %d\n",
|
"Id: %d\n",
|
||||||
i,
|
queue_item.pos,
|
||||||
queueitem_item_id(item));
|
queue_item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_free(queue);
|
db_queue_enum_end(&query_params);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2239,7 +2225,7 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
struct playlist_info *pli;
|
struct playlist_info *pli;
|
||||||
struct queue_item *items;
|
struct player_status status;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 2)
|
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
|
//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]);
|
ret = asprintf(errmsg, "Failed to add song '%s' to playlist", argv[1]);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
|
||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_add(items, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2436,6 +2420,7 @@ mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
sqlite3_free(qp.filter);
|
||||||
|
|
||||||
ret = asprintf(errmsg, "Could not start query");
|
ret = asprintf(errmsg, "Could not start query");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -2447,6 +2432,7 @@ mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
sqlite3_free(qp.filter);
|
||||||
|
|
||||||
ret = asprintf(errmsg, "Could not fetch query count");
|
ret = asprintf(errmsg, "Could not fetch query count");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -2461,6 +2447,7 @@ mpd_command_count(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
(fci.length / 1000));
|
(fci.length / 1000));
|
||||||
|
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
sqlite3_free(qp.filter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2492,6 +2479,7 @@ mpd_command_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
sqlite3_free(qp.filter);
|
||||||
|
|
||||||
ret = asprintf(errmsg, "Could not start query");
|
ret = asprintf(errmsg, "Could not start query");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -2509,6 +2497,7 @@ mpd_command_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
sqlite3_free(qp.filter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2517,7 +2506,7 @@ static int
|
|||||||
mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct query_params qp;
|
struct query_params qp;
|
||||||
struct queue_item *items;
|
struct player_status status;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 3 || ((argc - 1) % 2) != 0)
|
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);
|
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");
|
ret = asprintf(errmsg, "Failed to add songs to playlist");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -2546,8 +2537,6 @@ mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_add(items, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2639,6 +2628,7 @@ mpd_command_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
sqlite3_free(qp.filter);
|
||||||
|
|
||||||
ret = asprintf(errmsg, "Could not start query");
|
ret = asprintf(errmsg, "Could not start query");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -2682,6 +2672,7 @@ mpd_command_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
sqlite3_free(qp.filter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3121,6 +3112,7 @@ mpd_command_search(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
sqlite3_free(qp.filter);
|
||||||
|
|
||||||
ret = asprintf(errmsg, "Could not start query");
|
ret = asprintf(errmsg, "Could not start query");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -3138,6 +3130,7 @@ mpd_command_search(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
db_query_end(&qp);
|
db_query_end(&qp);
|
||||||
|
sqlite3_free(qp.filter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3146,7 +3139,7 @@ static int
|
|||||||
mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
|
||||||
{
|
{
|
||||||
struct query_params qp;
|
struct query_params qp;
|
||||||
struct queue_item *items;
|
struct player_status status;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (argc < 3 || ((argc - 1) % 2) != 0)
|
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);
|
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");
|
ret = asprintf(errmsg, "Failed to add songs to playlist");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -3175,8 +3170,6 @@ mpd_command_searchadd(struct evbuffer *evbuf, int argc, char **argv, char **errm
|
|||||||
return ACK_ERROR_UNKNOWN;
|
return ACK_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
player_queue_add(items, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,12 +821,9 @@ raop_metadata_prune(uint64_t rtptime)
|
|||||||
static void *
|
static void *
|
||||||
raop_metadata_prepare(int id)
|
raop_metadata_prepare(int id)
|
||||||
{
|
{
|
||||||
struct query_params qp;
|
struct db_queue_item *queue_item;
|
||||||
struct db_media_file_info dbmfi;
|
|
||||||
char filter[32];
|
|
||||||
struct raop_metadata *rmd;
|
struct raop_metadata *rmd;
|
||||||
struct evbuffer *tmp;
|
struct evbuffer *tmp;
|
||||||
uint64_t duration;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
rmd = (struct raop_metadata *)malloc(sizeof(struct raop_metadata));
|
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));
|
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 */
|
/* Get artwork */
|
||||||
rmd->artwork = evbuffer_new();
|
rmd->artwork = evbuffer_new();
|
||||||
if (!rmd->artwork)
|
if (!rmd->artwork)
|
||||||
@ -848,7 +853,7 @@ raop_metadata_prepare(int id)
|
|||||||
goto skip_artwork;
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_INFO, L_RAOP, "Failed to retrieve artwork for file id %d; no artwork will be sent\n", id);
|
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:
|
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 */
|
/* Turn it into DAAP metadata */
|
||||||
tmp = evbuffer_new();
|
tmp = evbuffer_new();
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_RAOP, "Out of memory for temporary metadata evbuffer; metadata will not be sent\n");
|
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();
|
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");
|
DPRINTF(E_LOG, L_RAOP, "Out of memory for metadata evbuffer; metadata will not be sent\n");
|
||||||
|
|
||||||
evbuffer_free(tmp);
|
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);
|
evbuffer_free(tmp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -919,27 +893,18 @@ raop_metadata_prepare(int id)
|
|||||||
goto out_metadata;
|
goto out_metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Progress */
|
/* Progress - raop_metadata_send() will add rtptime to these */
|
||||||
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 */
|
|
||||||
rmd->start = 0;
|
rmd->start = 0;
|
||||||
rmd->end = (duration * 44100UL) / 1000UL;
|
rmd->end = (queue_item->song_length * 44100UL) / 1000UL;
|
||||||
|
|
||||||
|
free_queue_item(queue_item, 0);
|
||||||
|
|
||||||
return rmd;
|
return rmd;
|
||||||
|
|
||||||
out_metadata:
|
out_metadata:
|
||||||
evbuffer_free(rmd->metadata);
|
evbuffer_free(rmd->metadata);
|
||||||
out_query:
|
out_qi:
|
||||||
db_query_end(&qp);
|
free_queue_item(queue_item, 0);
|
||||||
out_rmd:
|
out_rmd:
|
||||||
free(rmd);
|
free(rmd);
|
||||||
|
|
||||||
|
994
src/player.c
994
src/player.c
File diff suppressed because it is too large
Load Diff
65
src/player.h
65
src/player.h
@ -5,7 +5,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "queue.h"
|
|
||||||
|
|
||||||
/* AirTunes v2 packet interval in ns */
|
/* AirTunes v2 packet interval in ns */
|
||||||
/* (352 samples/packet * 1e9 ns/s) / 44100 samples/s = 7981859 ns/packet */
|
/* (352 samples/packet * 1e9 ns/s) / 44100 samples/s = 7981859 ns/packet */
|
||||||
@ -28,6 +27,12 @@ enum play_status {
|
|||||||
PLAY_PLAYING = 4,
|
PLAY_PLAYING = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum repeat_mode {
|
||||||
|
REPEAT_OFF = 0,
|
||||||
|
REPEAT_SONG = 1,
|
||||||
|
REPEAT_ALL = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct spk_flags {
|
struct spk_flags {
|
||||||
unsigned selected:1;
|
unsigned selected:1;
|
||||||
unsigned has_password:1;
|
unsigned has_password:1;
|
||||||
@ -44,13 +49,6 @@ struct player_status {
|
|||||||
|
|
||||||
/* Playlist id */
|
/* Playlist id */
|
||||||
uint32_t plid;
|
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 */
|
/* Id of the playing file/item in the files database */
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
/* Item-Id of the playing file/item in the queue */
|
/* Item-Id of the playing file/item in the queue */
|
||||||
@ -59,14 +57,6 @@ struct player_status {
|
|||||||
uint32_t pos_ms;
|
uint32_t pos_ms;
|
||||||
/* Length in ms of playing item */
|
/* Length in ms of playing item */
|
||||||
uint32_t len_ms;
|
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);
|
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);
|
player_speaker_set(uint64_t *ids);
|
||||||
|
|
||||||
int
|
int
|
||||||
player_playback_start(uint32_t *id);
|
player_playback_start();
|
||||||
|
|
||||||
int
|
int
|
||||||
player_playback_start_byindex(int pos, uint32_t *id);
|
player_playback_start_byitem(struct db_queue_item *queue_item);
|
||||||
|
|
||||||
int
|
|
||||||
player_playback_start_bypos(int pos, uint32_t *id);
|
|
||||||
|
|
||||||
int
|
|
||||||
player_playback_start_byitemid(uint32_t item_id, uint32_t *id);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
player_playback_stop(void);
|
player_playback_stop(void);
|
||||||
@ -147,39 +131,6 @@ int
|
|||||||
player_shuffle_set(int enable);
|
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
|
void
|
||||||
player_queue_clear_history(void);
|
player_queue_clear_history(void);
|
||||||
|
|
||||||
|
1272
src/queue.c
1272
src/queue.c
File diff suppressed because it is too large
Load Diff
116
src/queue.h
116
src/queue.h
@ -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_ */
|
|
@ -128,11 +128,11 @@ rng_rand_range(struct rng_ctx *ctx, int32_t min, int32_t max)
|
|||||||
* Durstenfeld in-place shuffling variant
|
* Durstenfeld in-place shuffling variant
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
shuffle_ptr(struct rng_ctx *ctx, void **values, int len)
|
shuffle_int(struct rng_ctx *ctx, int *values, int len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int32_t j;
|
int32_t j;
|
||||||
void *tmp;
|
int tmp;
|
||||||
|
|
||||||
for (i = len - 1; i > 0; i--)
|
for (i = len - 1; i > 0; i--)
|
||||||
{
|
{
|
||||||
@ -143,4 +143,3 @@ shuffle_ptr(struct rng_ctx *ctx, void **values, int len)
|
|||||||
values[j] = tmp;
|
values[j] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ int32_t
|
|||||||
rng_rand_range(struct rng_ctx *ctx, int32_t min, int32_t max);
|
rng_rand_range(struct rng_ctx *ctx, int32_t min, int32_t max);
|
||||||
|
|
||||||
void
|
void
|
||||||
shuffle_ptr(struct rng_ctx *ctx, void **values, int len);
|
shuffle_int(struct rng_ctx *ctx, int *values, int len);
|
||||||
|
|
||||||
#endif /* !__RNG_H__ */
|
#endif /* !__RNG_H__ */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user