* Add support for TiVo MPEG-TS files.

This commit is contained in:
Justin Maggard
2012-11-03 09:45:45 +00:00
parent ec2beb799d
commit fa37df8b1f
5 changed files with 201 additions and 202 deletions

View File

@ -93,6 +93,28 @@ SendRootContainer(struct upnphttp *h)
SendResp_upnphttp(h);
}
static void
SendFormats(struct upnphttp *h, const char *sformat)
{
char *resp;
int len;
len = xasprintf(&resp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<TiVoFormats>"
"<Format>"
"<ContentType>video/x-tivo-mpeg</ContentType>"
"<Description/>"
"</Format>"
"<Format>"
"<ContentType>%s</ContentType>"
"<Description/>"
"</Format>"
"</TiVoFormats>", sformat);
BuildResp_upnphttp(h, resp, len);
free(resp);
SendResp_upnphttp(h);
}
static char *
unescape_tag(char *tag)
{
@ -113,7 +135,7 @@ callback(void *args, int argc, char **argv, char **azColName)
struct Response *passed_args = (struct Response *)args;
char *id = argv[0], *class = argv[1], *detailID = argv[2], *size = argv[3], *title = argv[4], *duration = argv[5],
*bitrate = argv[6], *sampleFrequency = argv[7], *artist = argv[8], *album = argv[9], *genre = argv[10],
*comment = argv[11], *date = argv[12], *resolution = argv[13], *mime = argv[14], *path = argv[15];
*comment = argv[11], *date = argv[12], *resolution = argv[13], *mime = argv[14];
struct string_s *str = passed_args->str;
if( strncmp(class, "item", 4) == 0 )
@ -124,22 +146,22 @@ callback(void *args, int argc, char **argv, char **azColName)
{
flags |= FLAG_NO_PARAMS;
strcatf(str, "<Item><Details>"
"<ContentType>audio/*</ContentType>"
"<ContentType>%s</ContentType>"
"<SourceFormat>%s</SourceFormat>"
"<SourceSize>%s</SourceSize>"
"<SongTitle>%s</SongTitle>", mime, size, title);
"<SourceSize>%s</SourceSize>",
"audio/*", mime, size);
strcatf(str, "<SongTitle>%s</SongTitle>", title);
if( date )
{
strcatf(str, "<AlbumYear>%.*s</AlbumYear>", 4, date);
}
}
else if( strcmp(mime, "image/jpeg") == 0 )
{
flags |= FLAG_SEND_RESIZED;
strcatf(str, "<Item><Details>"
"<ContentType>image/*</ContentType>"
"<SourceFormat>image/jpeg</SourceFormat>"
"<SourceSize>%s</SourceSize>", size);
"<ContentType>%s</ContentType>"
"<SourceFormat>%s</SourceFormat>"
"<SourceSize>%s</SourceSize>",
"image/*", mime, size);
if( date )
{
struct tm tm;
@ -149,19 +171,17 @@ callback(void *args, int argc, char **argv, char **azColName)
strcatf(str, "<CaptureDate>0x%X</CaptureDate>", (unsigned int)mktime(&tm));
}
if( comment )
{
strcatf(str, "<Caption>%s</Caption>", comment);
}
}
else if( strncmp(mime, "video", 5) == 0 )
{
char *episode;
flags |= FLAG_NO_PARAMS;
flags |= FLAG_VIDEO;
strcatf(str, "<Item><Details>"
"<ContentType>video/x-tivo-mpeg</ContentType>"
"<ContentType>%s</ContentType>"
"<SourceFormat>%s</SourceFormat>"
"<SourceSize>%s</SourceSize>", mime, size);
"<SourceSize>%s</SourceSize>",
mime, mime, size);
episode = strstr(title, " - ");
if( episode )
{
@ -182,9 +202,7 @@ callback(void *args, int argc, char **argv, char **azColName)
strcatf(str, "<CaptureDate>0x%X</CaptureDate>", (unsigned int)mktime(&tm));
}
if( comment )
{
strcatf(str, "<Description>%s</Description>", comment);
}
}
else
{
@ -217,27 +235,23 @@ callback(void *args, int argc, char **argv, char **azColName)
if( sampleFrequency ) {
strcatf(str, "<SourceSampleRate>%s</SourceSampleRate>", sampleFrequency);
}
strcatf(str, "</Details><Links><Content>"
"<ContentType>%s</ContentType>"
"<Url>/%s/%s.dat</Url>%s</Content>",
strcatf(str, "</Details><Links>"
"<Content>"
"<ContentType>%s</ContentType>"
"<Url>/%s/%s.%s</Url>%s"
"</Content>",
mime,
(flags & FLAG_SEND_RESIZED)?"Resized":"MediaItems", detailID,
(flags & FLAG_NO_PARAMS)?"<AcceptsParams>No</AcceptsParams>":"");
(flags & FLAG_SEND_RESIZED) ? "Resized" : "MediaItems",
detailID, mime_to_ext(mime),
(flags & FLAG_NO_PARAMS) ? "<AcceptsParams>No</AcceptsParams>" : "");
if( flags & FLAG_VIDEO )
{
char *esc_name = escape_tag(basename(path), 1);
strcatf(str, "<CustomIcon>"
"<ContentType>video/*</ContentType>"
"<ContentType>image/*</ContentType>"
"<Url>urn:tivo:image:save-until-i-delete-recording</Url>"
"</CustomIcon>"
"<Push><Container>Videos</Container></Push>"
"<File>%s</File> </Links>", esc_name);
free(esc_name);
}
else
{
strcatf(str, "</Links>");
"</CustomIcon>");
}
strcatf(str, "</Links>");
}
else if( strncmp(class, "container", 9) == 0 )
{
@ -247,7 +261,7 @@ callback(void *args, int argc, char **argv, char **azColName)
count = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", id);
#else
count = sql_get_int_field(db, "SELECT count(*) from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID) where PARENT_ID = '%s' and "
" (MIME in ('image/jpeg', 'audio/mpeg', 'video/mpeg', 'video/x-tivo-mpeg')"
" (MIME in ('image/jpeg', 'audio/mpeg', 'video/mpeg', 'video/x-tivo-mpeg', 'video/x-tivo-mpeg-ts')"
" or CLASS glob 'container*')", id);
#endif
strcatf(str, "<Item>"
@ -274,7 +288,7 @@ callback(void *args, int argc, char **argv, char **azColName)
#define SELECT_COLUMNS "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, d.PATH, d.DISC, d.TRACK "
" d.COMMENT, d.DATE, d.RESOLUTION, d.MIME, d.DISC, d.TRACK "
static void
SendItemDetails(struct upnphttp *h, int64_t item)
@ -534,7 +548,7 @@ SendContainer(struct upnphttp *h, const char *objectID, int itemStart, int itemC
}
else if( strncasecmp(item, "video", 5) == 0 )
{
strcat(myfilter, "MIME in ('video/mpeg', 'video/x-tivo-mpeg')");
strcat(myfilter, "MIME in ('video/mpeg', 'video/x-tivo-mpeg', 'video/x-tivo-mpeg-ts')");
}
else
{
@ -551,7 +565,7 @@ SendContainer(struct upnphttp *h, const char *objectID, int itemStart, int itemC
}
else
{
strcpy(myfilter, "MIME in ('image/jpeg', 'audio/mpeg', 'video/mpeg', 'video/x-tivo-mpeg') or CLASS glob 'container*'");
strcpy(myfilter, "MIME in ('image/jpeg', 'audio/mpeg', 'video/mpeg', 'video/x-tivo-mpeg', 'video/x-tivo-mpeg-ts') or CLASS glob 'container*'");
}
if( anchorItem )
@ -652,7 +666,7 @@ ProcessTiVoCommand(struct upnphttp *h, const char *orig_path)
char *key, *val;
char *saveptr = NULL, *item;
char *command = NULL, *container = NULL, *anchorItem = NULL;
char *sortOrder = NULL, *filter = NULL;
char *sortOrder = NULL, *filter = NULL, *sformat = NULL;
int64_t detailItem=0;
int itemStart=0, itemCount=-100, anchorOffset=0, recurse=0;
unsigned long int randomSeed=0;
@ -718,6 +732,10 @@ ProcessTiVoCommand(struct upnphttp *h, const char *orig_path)
if( val )
detailItem = strtoll(basename(val), NULL, 10);
}
else if( strcasecmp(key, "SourceFormat") == 0 )
{
sformat = val;
}
else if( strcasecmp(key, "Format") == 0 || // Only send XML
strcasecmp(key, "SerialNum") == 0 || // Unused for now
strcasecmp(key, "DoGenres") == 0 ) // Not sure what this is, so ignore it
@ -752,6 +770,10 @@ ProcessTiVoCommand(struct upnphttp *h, const char *orig_path)
{
SendItemDetails(h, detailItem);
}
else if( strcmp(command, "QueryFormats") == 0 )
{
SendFormats(h, sformat);
}
else
{
DPRINTF(E_DEBUG, L_GENERAL, "Unhandled command [%s]\n", command);