* Implement the QueryItem command.

* Add error handling/reporting for unknown commands.
This commit is contained in:
Justin Maggard 2009-03-30 07:43:10 +00:00
parent 3aea5d6f07
commit 2e3a4f1dde
3 changed files with 77 additions and 39 deletions

View File

@ -80,9 +80,9 @@ SendRootContainer(struct upnphttp * h)
int callback(void *args, int argc, char **argv, char **azColName) int callback(void *args, int argc, char **argv, char **azColName)
{ {
struct Response *passed_args = (struct Response *)args; struct Response *passed_args = (struct Response *)args;
char *id = argv[1], *class = argv[4], *detailID = argv[5], *size = argv[9], *title = argv[10], *duration = argv[11], char *id = argv[0], *class = argv[1], *detailID = argv[2], *size = argv[3], *title = argv[4], *duration = argv[5],
*bitrate = argv[12], *sampleFrequency = argv[13], *artist = argv[14], *album = argv[15], *genre = argv[16], *bitrate = argv[6], *sampleFrequency = argv[7], *artist = argv[8], *album = argv[9], *genre = argv[10],
*comment = argv[17], *date = argv[20], *resolution = argv[21], *mime = argv[25]; *comment = argv[11], *date = argv[12], *resolution = argv[13], *mime = argv[14];
char str_buf[4096]; char str_buf[4096];
char **result; char **result;
int is_audio = 0; int is_audio = 0;
@ -96,13 +96,13 @@ int callback(void *args, int argc, char **argv, char **azColName)
if( strncmp(class, "item", 4) == 0 ) if( strncmp(class, "item", 4) == 0 )
{ {
if( strcmp(mime, "audio/mpeg") == 0 ) if( strncmp(mime, "audio", 5) == 0 )
{ {
sprintf(str_buf, "<Item><Details>" sprintf(str_buf, "<Item><Details>"
"<ContentType>audio/*</ContentType>" "<ContentType>audio/*</ContentType>"
"<SourceFormat>audio/mpeg</SourceFormat>" "<SourceFormat>%s</SourceFormat>"
"<SourceSize>%s</SourceSize>" "<SourceSize>%s</SourceSize>"
"<SongTitle>%s</SongTitle>", size, title); "<SongTitle>%s</SongTitle>", mime, size, title);
strcat(passed_args->resp, str_buf); strcat(passed_args->resp, str_buf);
if( date ) if( date )
{ {
@ -138,15 +138,15 @@ int callback(void *args, int argc, char **argv, char **azColName)
sprintf(str_buf, "<Title>%s</Title>", modifyString(title, "&amp;amp;", "&amp;", 0)); sprintf(str_buf, "<Title>%s</Title>", modifyString(title, "&amp;amp;", "&amp;", 0));
strcat(passed_args->resp, str_buf); strcat(passed_args->resp, str_buf);
if( artist ) { if( artist ) {
sprintf(str_buf, "<ArtistName>%s</ArtistName>", artist); sprintf(str_buf, "<ArtistName>%s</ArtistName>", modifyString(artist, "&amp;amp;", "&amp;", 0));
strcat(passed_args->resp, str_buf); strcat(passed_args->resp, str_buf);
} }
if( album ) { if( album ) {
sprintf(str_buf, "<AlbumTitle>%s</AlbumTitle>", album); sprintf(str_buf, "<AlbumTitle>%s</AlbumTitle>", modifyString(album, "&amp;amp;", "&amp;", 0));
strcat(passed_args->resp, str_buf); strcat(passed_args->resp, str_buf);
} }
if( genre ) { if( genre ) {
sprintf(str_buf, "<MusicGenre>%s</MusicGenre>", genre); sprintf(str_buf, "<MusicGenre>%s</MusicGenre>", modifyString(genre, "&amp;amp;", "&amp;", 0));
strcat(passed_args->resp, str_buf); strcat(passed_args->resp, str_buf);
} }
if( resolution ) { if( resolution ) {
@ -196,6 +196,39 @@ int callback(void *args, int argc, char **argv, char **azColName)
return 0; return 0;
} }
void
SendItemDetails(struct upnphttp * h, sqlite_int64 item)
{
char * resp = malloc(32768);
char *sql;
char *zErrMsg = NULL;
struct Response args;
int ret;
memset(&args, 0, sizeof(args));
sprintf(resp, "<?xml version='1.0' encoding='UTF-8' ?>\n<TiVoItem>");
args.resp = resp;
args.requested = 1;
asprintf(&sql, "SELECT o.OBJECT_ID, o.CLASS, o.DETAIL_ID, d.SIZE, d.TITLE,"
" d.DURATION, d.BITRATE, d.SAMPLERATE, d.ARTIST, d.ALBUM,"
" d.GENRE, d.COMMENT, d.DATE, d.RESOLUTION, d.MIME "
"from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
" where o.DETAIL_ID = %lld", item);
DPRINTF(E_DEBUG, L_TIVO, "%s\n", sql);
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
free(sql);
if( ret != SQLITE_OK )
{
DPRINTF(E_ERROR, L_HTTP, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
strcat(resp, "</TiVoItem>");
BuildResp_upnphttp(h, resp, strlen(resp));
free(resp);
SendResp_upnphttp(h);
}
void void
SendContainer(struct upnphttp * h, const char * objectID, int itemStart, int itemCount, char * anchorItem, SendContainer(struct upnphttp * h, const char * objectID, int itemStart, int itemCount, char * anchorItem,
int anchorOffset, int recurse, char * sortOrder, char * filter, unsigned long int randomSeed) int anchorOffset, int recurse, char * sortOrder, char * filter, unsigned long int randomSeed)
@ -206,14 +239,11 @@ SendContainer(struct upnphttp * h, const char * objectID, int itemStart, int ite
char *zErrMsg = NULL; char *zErrMsg = NULL;
char **result; char **result;
char *title; char *title;
char what[10], order[64], order2[64], myfilter[128]; char what[10], order[64]={0}, order2[64]={0}, myfilter[128]={0};
char *which; char *which;
struct Response args; struct Response args;
int i, ret; int i, ret;
*items = '\0'; *items = '\0';
order[0] = '\0';
order2[0] = '\0';
myfilter[0] = '\0';
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.resp = items; args.resp = items;
@ -222,25 +252,19 @@ SendContainer(struct upnphttp * h, const char * objectID, int itemStart, int ite
if( strlen(objectID) == 1 ) if( strlen(objectID) == 1 )
{ {
if( *objectID == '1' ) if( *objectID == '1' )
{
asprintf(&title, "Music on %s", friendly_name); asprintf(&title, "Music on %s", friendly_name);
}
else if( *objectID == '3' ) else if( *objectID == '3' )
{
asprintf(&title, "Pictures on %s", friendly_name); asprintf(&title, "Pictures on %s", friendly_name);
} else
asprintf(&title, "Unknown on %s", friendly_name);
} }
else else
{ {
sql = sqlite3_mprintf("SELECT NAME from OBJECTS where OBJECT_ID = '%s'", objectID); sql = sqlite3_mprintf("SELECT NAME from OBJECTS where OBJECT_ID = '%s'", objectID);
if( (sql_get_table(db, sql, &result, &ret, NULL) == SQLITE_OK) && ret ) if( (sql_get_table(db, sql, &result, &ret, NULL) == SQLITE_OK) && ret )
{
title = strdup(result[1]); title = strdup(result[1]);
}
else else
{
title = strdup("UNKNOWN"); title = strdup("UNKNOWN");
}
sqlite3_free(sql); sqlite3_free(sql);
sqlite3_free_table(result); sqlite3_free_table(result);
} }
@ -297,25 +321,17 @@ SendContainer(struct upnphttp * h, const char * objectID, int itemStart, int ite
{ {
strcat(order, " DESC"); strcat(order, " DESC");
if( itemCount >= 0 ) if( itemCount >= 0 )
{
strcat(order2, " DESC"); strcat(order2, " DESC");
}
else else
{
strcat(order2, " ASC"); strcat(order2, " ASC");
}
} }
else else
{ {
strcat(order, " ASC"); strcat(order, " ASC");
if( itemCount >= 0 ) if( itemCount >= 0 )
{
strcat(order2, " ASC"); strcat(order2, " ASC");
}
else else
{
strcat(order2, " DESC"); strcat(order2, " DESC");
}
} }
strcat(order, ", "); strcat(order, ", ");
strcat(order2, ", "); strcat(order2, ", ");
@ -324,13 +340,9 @@ SendContainer(struct upnphttp * h, const char * objectID, int itemStart, int ite
} }
strcat(order, "DETAIL_ID ASC"); strcat(order, "DETAIL_ID ASC");
if( itemCount >= 0 ) if( itemCount >= 0 )
{
strcat(order2, "DETAIL_ID ASC"); strcat(order2, "DETAIL_ID ASC");
}
else else
{
strcat(order2, "DETAIL_ID DESC"); strcat(order2, "DETAIL_ID DESC");
}
} }
} }
else else
@ -390,6 +402,7 @@ SendContainer(struct upnphttp * h, const char * objectID, int itemStart, int ite
sqlite3Prng.isInit = 0; sqlite3Prng.isInit = 0;
sql = sqlite3_mprintf("SELECT %s from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)" sql = sqlite3_mprintf("SELECT %s from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
" where %s and (%s)" " where %s and (%s)"
" group by DETAIL_ID"
" order by %s", what, which, myfilter, order2); " order by %s", what, which, myfilter, order2);
if( itemCount < 0 ) if( itemCount < 0 )
{ {
@ -415,8 +428,12 @@ SendContainer(struct upnphttp * h, const char * objectID, int itemStart, int ite
} }
args.start = itemStart+anchorOffset; args.start = itemStart+anchorOffset;
sqlite3Prng.isInit = 0; sqlite3Prng.isInit = 0;
sql = sqlite3_mprintf("SELECT * from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)" sql = sqlite3_mprintf("SELECT o.OBJECT_ID, o.CLASS, o.DETAIL_ID, d.SIZE, d.TITLE,"
" d.DURATION, d.BITRATE, d.SAMPLERATE, d.ARTIST, d.ALBUM,"
" d.GENRE, d.COMMENT, d.DATE, d.RESOLUTION, d.MIME "
"from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID)"
" where %s and (%s)" " where %s and (%s)"
" group by DETAIL_ID"
" order by %s", which, myfilter, order); " order by %s", which, myfilter, order);
DPRINTF(E_DEBUG, L_TIVO, "%s\n", sql); DPRINTF(E_DEBUG, L_TIVO, "%s\n", sql);
ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg); ret = sqlite3_exec(db, sql, callback, (void *) &args, &zErrMsg);
@ -459,6 +476,7 @@ ProcessTiVoCommand(struct upnphttp * h, const char * orig_path)
char *saveptr = NULL, *item; char *saveptr = NULL, *item;
char *command = NULL, *container = NULL, *anchorItem = NULL; char *command = NULL, *container = NULL, *anchorItem = NULL;
char *sortOrder = NULL, *filter = NULL; char *sortOrder = NULL, *filter = NULL;
sqlite_int64 detailItem=0;
int itemStart=0, itemCount=-100, anchorOffset=0, recurse=0; int itemStart=0, itemCount=-100, anchorOffset=0, recurse=0;
unsigned long int randomSeed=0; unsigned long int randomSeed=0;
@ -518,6 +536,10 @@ ProcessTiVoCommand(struct upnphttp * h, const char * orig_path)
{ {
randomSeed = strtoul(val, NULL, 10); randomSeed = strtoul(val, NULL, 10);
} }
else if( strcasecmp(key, "Url") == 0 )
{
detailItem = strtoll(basename(val), NULL, 10);
}
else if( strcasecmp(key, "Format") == 0 ) else if( strcasecmp(key, "Format") == 0 )
{ {
// Only send XML // Only send XML
@ -533,15 +555,27 @@ ProcessTiVoCommand(struct upnphttp * h, const char * orig_path)
strip_ext(anchorItem); strip_ext(anchorItem);
} }
if( command && strcmp(command, "QueryContainer") == 0 ) if( command )
{ {
if( !container || (strcmp(container, "/") == 0) ) if( strcmp(command, "QueryContainer") == 0 )
{ {
SendRootContainer(h); if( !container || (strcmp(container, "/") == 0) )
{
SendRootContainer(h);
}
else
{
SendContainer(h, container, itemStart, itemCount, anchorItem, anchorOffset, recurse, sortOrder, filter, randomSeed);
}
}
else if( strcmp(command, "QueryItem") == 0 )
{
SendItemDetails(h, detailItem);
} }
else else
{ {
SendContainer(h, container, itemStart, itemCount, anchorItem, anchorOffset, recurse, sortOrder, filter, randomSeed); DPRINTF(E_DEBUG, L_GENERAL, "Unhandled command [%s]\n", command);
Send501(h);
} }
} }
free(path); free(path);

View File

@ -336,7 +336,7 @@ Send500(struct upnphttp * h)
} }
/* very minimalistic 501 error message */ /* very minimalistic 501 error message */
static void void
Send501(struct upnphttp * h) Send501(struct upnphttp * h)
{ {
static const char body501[] = static const char body501[] =

View File

@ -120,6 +120,10 @@ BuildResp2_upnphttp(struct upnphttp * h, int respcode,
const char * respmsg, const char * respmsg,
const char * body, int bodylen); const char * body, int bodylen);
/* Error messages */
void
Send501(struct upnphttp *);
/* SendResp_upnphttp() */ /* SendResp_upnphttp() */
void void
SendResp_upnphttp(struct upnphttp *); SendResp_upnphttp(struct upnphttp *);