(basic) support for mpd commands 'find' and 'list'

This commit is contained in:
chme 2015-02-15 13:55:24 +01:00
parent 911b982815
commit 7024f2f3e7

217
src/mpd.c
View File

@ -1680,8 +1680,213 @@ mpd_command_load(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
}
static int
mpd_command_list()
mpd_get_query_params_find(int argc, char **argv, struct query_params *qp)
{
char *c1;
char *c2;
int start_pos;
int end_pos;
int i;
int ret;
c1 = NULL;
c2 = NULL;
for (i = 0; i < argc; i += 2)
{
if (0 == strcasecmp(argv[i], "any"))
{
c1 = sqlite3_mprintf("(f.artist LIKE '%%%q%%' OR f.album LIKE '%%%q%%' OR f.title LIKE '%%%q%%')", argv[i + 1], argv[i + 1], argv[i + 1]);
}
else if (0 == strcasecmp(argv[i], "file"))
{
c1 = sqlite3_mprintf("(f.virtual_path = '/%q')", argv[i + 1]);
}
else if (0 == strcasecmp(argv[i], "base"))
{
c1 = sqlite3_mprintf("(f.virtual_path LIKE '/%q%%')", argv[i + 1]);
}
else if (0 == strcasecmp(argv[i], "modified-since"))
{
DPRINTF(E_WARN, L_MPD, "Special parameter 'modified-since' is not supported by forked-daapd and will be ignored\n");
}
else if (0 == strcasecmp(argv[i], "window"))
{
ret = mpd_pars_range_arg(argv[i + 1], &start_pos, &end_pos);
if (ret == 0)
{
qp->idx_type = I_SUB;
qp->limit = end_pos - start_pos;
qp->offset = start_pos;
}
else
{
DPRINTF(E_LOG, L_MPD, "Window argument doesn't convert to integer or range: '%s'\n", argv[i + 1]);
}
}
else if (0 == strcasecmp(argv[i], "artist"))
{
c1 = sqlite3_mprintf("(f.artist = '%q')", argv[i + 1]);
}
else if (0 == strcasecmp(argv[i], "albumartist"))
{
c1 = sqlite3_mprintf("(f.album_artist = '%q')", argv[i + 1]);
}
else if (0 == strcasecmp(argv[i], "album"))
{
c1 = sqlite3_mprintf("(f.album = '%q')", argv[i + 1]);
}
else if (0 == strcasecmp(argv[i], "title"))
{
c1 = sqlite3_mprintf("(f.title = '%q')", argv[i + 1]);
}
else
{
DPRINTF(E_WARN, L_MPD, "Parameter '%s' is not supported by forked-daapd and will be ignored\n", argv[i]);
}
if (c1)
{
if (qp->filter)
c2 = sqlite3_mprintf("%s AND %s", qp->filter, c1);
else
c2 = sqlite3_mprintf("%s", c1);
if (qp->filter)
sqlite3_free(qp->filter);
qp->filter = c2;
c2 = NULL;
sqlite3_free(c1);
c1 = NULL;
}
}
return 0;
}
static int
mpd_command_find(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct query_params qp;
struct db_media_file_info dbmfi;
int ret;
if (argc < 3 || ((argc - 1) % 2) != 0)
{
DPRINTF(E_LOG, L_MPD, "Missing argument(s) for command 'find'\n");
ret = asprintf(errmsg, "Missing argument(s) for command 'find'");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_ARG;
}
memset(&qp, 0, sizeof(struct query_params));
qp.type = Q_ITEMS;
qp.sort = S_NAME;
qp.idx_type = I_NONE;
mpd_get_query_params_find(argc - 1, argv + 1, &qp);
ret = db_query_start(&qp);
if (ret < 0)
{
db_query_end(&qp);
DPRINTF(E_LOG, L_MPD, "Could not start query\n");
ret = asprintf(errmsg, "Could not start query");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_UNKNOWN;
}
while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
{
ret = mpd_add_db_media_file_info(evbuf, &dbmfi);
if (ret < 0)
{
DPRINTF(E_LOG, L_MPD, "Error adding song to the evbuffer, song id: %s\n", dbmfi.id);
}
}
db_query_end(&qp);
return 0;
}
static int
mpd_command_findadd(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
return 0;
}
static int
mpd_command_list(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
{
struct query_params qp;
struct db_group_info dbgri;
char *type;
int ret;
if (argc < 2 || (argc % 2) != 0)
{
DPRINTF(E_LOG, L_MPD, "Missing argument(s) for command 'list'\n");
ret = asprintf(errmsg, "Missing argument(s) for command 'list'");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_ARG;
}
memset(&qp, 0, sizeof(struct query_params));
if (0 == strcasecmp(argv[1], "artist")
|| 0 == strcasecmp(argv[1], "albumartist"))
{
qp.type = Q_GROUP_ARTISTS;
qp.sort = S_ARTIST;
type = "Artist: ";
}
else if (0 == strcasecmp(argv[1], "album"))
{
qp.type = Q_GROUP_ALBUMS;
qp.sort = S_ALBUM;
type = "Album: ";
}
else
{
DPRINTF(E_WARN, L_MPD, "Unsupported type argument for command 'list': %s\n", argv[1]);
return 0;
}
qp.idx_type = I_NONE;
if (argc > 2)
{
mpd_get_query_params_find(argc - 2, argv + 2, &qp);
}
ret = db_query_start(&qp);
if (ret < 0)
{
db_query_end(&qp);
DPRINTF(E_LOG, L_MPD, "Could not start query\n");
ret = asprintf(errmsg, "Could not start query");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_UNKNOWN;
}
while ((ret = db_query_fetch_group(&qp, &dbgri)) == 0)
{
evbuffer_add_printf(evbuf,
"%s%s\n",
type,
dbgri.itemname);
}
db_query_end(&qp);
return 0;
}
@ -1781,7 +1986,7 @@ mpd_command_lsinfo(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
}
static int
mpd_get_query_params(int argc, char **argv, struct query_params *qp)
mpd_get_query_params_search(int argc, char **argv, struct query_params *qp)
{
char *c1;
char *c2;
@ -1889,8 +2094,8 @@ mpd_command_search(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
if (argc < 3 || ((argc - 1) % 2) != 0)
{
DPRINTF(E_LOG, L_MPD, "Missing argument(s) for command 'update'\n");
ret = asprintf(errmsg, "Missing argument(s) for command 'update'");
DPRINTF(E_LOG, L_MPD, "Missing argument(s) for command 'search'\n");
ret = asprintf(errmsg, "Missing argument(s) for command 'search'");
if (ret < 0)
DPRINTF(E_LOG, L_MPD, "Out of memory\n");
return ACK_ERROR_ARG;
@ -1902,7 +2107,7 @@ mpd_command_search(struct evbuffer *evbuf, int argc, char **argv, char **errmsg)
qp.sort = S_NAME;
qp.idx_type = I_NONE;
mpd_get_query_params(argc - 1, argv + 1, &qp);
mpd_get_query_params_search(argc - 1, argv + 1, &qp);
ret = db_query_start(&qp);
if (ret < 0)
@ -2321,6 +2526,7 @@ static struct command mpd_handlers[] =
.mpdcommand = "count",
.handler = mpd_command_count
},
*/
{
.mpdcommand = "find",
.handler = mpd_command_find
@ -2329,7 +2535,6 @@ static struct command mpd_handlers[] =
.mpdcommand = "findadd",
.handler = mpd_command_findadd
},
*/
{
.mpdcommand = "list",
.handler = mpd_command_list