* Add support for TiVo MPEG-TS files.
This commit is contained in:
parent
ec2beb799d
commit
fa37df8b1f
92
metadata.c
92
metadata.c
@ -255,7 +255,17 @@ parse_nfo(const char *path, metadata_t *m)
|
|||||||
|
|
||||||
val = GetValueFromNameValueList(&xml, "genre");
|
val = GetValueFromNameValueList(&xml, "genre");
|
||||||
if( val )
|
if( val )
|
||||||
|
{
|
||||||
|
free(m->genre);
|
||||||
m->genre = strdup(val);
|
m->genre = strdup(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
val = GetValueFromNameValueList(&xml, "mime");
|
||||||
|
if( val )
|
||||||
|
{
|
||||||
|
free(m->mime);
|
||||||
|
m->mime = strdup(val);
|
||||||
|
}
|
||||||
|
|
||||||
ClearNameValueList(&xml);
|
ClearNameValueList(&xml);
|
||||||
fclose(nfo);
|
fclose(nfo);
|
||||||
@ -758,24 +768,6 @@ GetVideoMetadata(const char *path, char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(nfo, path);
|
|
||||||
ext = strrchr(nfo, '.');
|
|
||||||
if( ext )
|
|
||||||
{
|
|
||||||
strcpy(ext+1, "nfo");
|
|
||||||
if( access(nfo, F_OK) == 0 )
|
|
||||||
{
|
|
||||||
parse_nfo(nfo, &m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !m.date )
|
|
||||||
{
|
|
||||||
m.date = malloc(20);
|
|
||||||
modtime = localtime(&file.st_mtime);
|
|
||||||
strftime(m.date, 20, "%FT%T", modtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ac )
|
if( ac )
|
||||||
{
|
{
|
||||||
aac_object_type_t aac_type = AAC_INVALID;
|
aac_object_type_t aac_type = AAC_INVALID;
|
||||||
@ -1483,26 +1475,6 @@ GetVideoMetadata(const char *path, char *name)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( !m.mime )
|
|
||||||
{
|
|
||||||
if( strcmp(ctx->iformat->name, "avi") == 0 )
|
|
||||||
xasprintf(&m.mime, "video/x-msvideo");
|
|
||||||
else if( strncmp(ctx->iformat->name, "mpeg", 4) == 0 )
|
|
||||||
xasprintf(&m.mime, "video/mpeg");
|
|
||||||
else if( strcmp(ctx->iformat->name, "asf") == 0 )
|
|
||||||
xasprintf(&m.mime, "video/x-ms-wmv");
|
|
||||||
else if( strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
|
|
||||||
if( ends_with(path, ".mov") )
|
|
||||||
xasprintf(&m.mime, "video/quicktime");
|
|
||||||
else
|
|
||||||
xasprintf(&m.mime, "video/mp4");
|
|
||||||
else if( strncmp(ctx->iformat->name, "matroska", 8) == 0 )
|
|
||||||
xasprintf(&m.mime, "video/x-matroska");
|
|
||||||
else if( strcmp(ctx->iformat->name, "flv") == 0 )
|
|
||||||
xasprintf(&m.mime, "video/x-flv");
|
|
||||||
else
|
|
||||||
DPRINTF(E_WARN, L_METADATA, "%s: Unhandled format: %s\n", path, ctx->iformat->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( strcmp(ctx->iformat->name, "asf") == 0 )
|
if( strcmp(ctx->iformat->name, "asf") == 0 )
|
||||||
{
|
{
|
||||||
@ -1557,7 +1529,6 @@ GetVideoMetadata(const char *path, char *name)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
video_no_dlna:
|
video_no_dlna:
|
||||||
lav_close(ctx);
|
|
||||||
|
|
||||||
#ifdef TIVO_SUPPORT
|
#ifdef TIVO_SUPPORT
|
||||||
if( ends_with(path, ".TiVo") && is_tivo_file(path) )
|
if( ends_with(path, ".TiVo") && is_tivo_file(path) )
|
||||||
@ -1567,10 +1538,51 @@ video_no_dlna:
|
|||||||
free(m.dlna_pn);
|
free(m.dlna_pn);
|
||||||
m.dlna_pn = NULL;
|
m.dlna_pn = NULL;
|
||||||
}
|
}
|
||||||
m.mime = realloc(m.mime, 18);
|
m.mime = realloc(m.mime, 21);
|
||||||
strcpy(m.mime, "video/x-tivo-mpeg");
|
strcpy(m.mime, "video/x-tivo-mpeg");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
strcpy(nfo, path);
|
||||||
|
ext = strrchr(nfo, '.');
|
||||||
|
if( ext )
|
||||||
|
{
|
||||||
|
strcpy(ext+1, "nfo");
|
||||||
|
if( access(nfo, F_OK) == 0 )
|
||||||
|
{
|
||||||
|
parse_nfo(nfo, &m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !m.mime )
|
||||||
|
{
|
||||||
|
if( strcmp(ctx->iformat->name, "avi") == 0 )
|
||||||
|
xasprintf(&m.mime, "video/x-msvideo");
|
||||||
|
else if( strncmp(ctx->iformat->name, "mpeg", 4) == 0 )
|
||||||
|
xasprintf(&m.mime, "video/mpeg");
|
||||||
|
else if( strcmp(ctx->iformat->name, "asf") == 0 )
|
||||||
|
xasprintf(&m.mime, "video/x-ms-wmv");
|
||||||
|
else if( strcmp(ctx->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0 )
|
||||||
|
if( ends_with(path, ".mov") )
|
||||||
|
xasprintf(&m.mime, "video/quicktime");
|
||||||
|
else
|
||||||
|
xasprintf(&m.mime, "video/mp4");
|
||||||
|
else if( strncmp(ctx->iformat->name, "matroska", 8) == 0 )
|
||||||
|
xasprintf(&m.mime, "video/x-matroska");
|
||||||
|
else if( strcmp(ctx->iformat->name, "flv") == 0 )
|
||||||
|
xasprintf(&m.mime, "video/x-flv");
|
||||||
|
else
|
||||||
|
DPRINTF(E_WARN, L_METADATA, "%s: Unhandled format: %s\n", path, ctx->iformat->name);
|
||||||
|
}
|
||||||
|
lav_close(ctx);
|
||||||
|
|
||||||
|
if( !m.date )
|
||||||
|
{
|
||||||
|
m.date = malloc(20);
|
||||||
|
modtime = localtime(&file.st_mtime);
|
||||||
|
strftime(m.date, 20, "%FT%T", modtime);
|
||||||
|
}
|
||||||
|
|
||||||
if( !m.title )
|
if( !m.title )
|
||||||
m.title = strdup(name);
|
m.title = strdup(name);
|
||||||
|
|
||||||
|
@ -93,6 +93,28 @@ SendRootContainer(struct upnphttp *h)
|
|||||||
SendResp_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 *
|
static char *
|
||||||
unescape_tag(char *tag)
|
unescape_tag(char *tag)
|
||||||
{
|
{
|
||||||
@ -113,7 +135,7 @@ 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[0], *class = argv[1], *detailID = argv[2], *size = argv[3], *title = argv[4], *duration = argv[5],
|
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],
|
*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;
|
struct string_s *str = passed_args->str;
|
||||||
|
|
||||||
if( strncmp(class, "item", 4) == 0 )
|
if( strncmp(class, "item", 4) == 0 )
|
||||||
@ -124,22 +146,22 @@ callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
{
|
{
|
||||||
flags |= FLAG_NO_PARAMS;
|
flags |= FLAG_NO_PARAMS;
|
||||||
strcatf(str, "<Item><Details>"
|
strcatf(str, "<Item><Details>"
|
||||||
"<ContentType>audio/*</ContentType>"
|
"<ContentType>%s</ContentType>"
|
||||||
"<SourceFormat>%s</SourceFormat>"
|
"<SourceFormat>%s</SourceFormat>"
|
||||||
"<SourceSize>%s</SourceSize>"
|
"<SourceSize>%s</SourceSize>",
|
||||||
"<SongTitle>%s</SongTitle>", mime, size, title);
|
"audio/*", mime, size);
|
||||||
|
strcatf(str, "<SongTitle>%s</SongTitle>", title);
|
||||||
if( date )
|
if( date )
|
||||||
{
|
|
||||||
strcatf(str, "<AlbumYear>%.*s</AlbumYear>", 4, date);
|
strcatf(str, "<AlbumYear>%.*s</AlbumYear>", 4, date);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if( strcmp(mime, "image/jpeg") == 0 )
|
else if( strcmp(mime, "image/jpeg") == 0 )
|
||||||
{
|
{
|
||||||
flags |= FLAG_SEND_RESIZED;
|
flags |= FLAG_SEND_RESIZED;
|
||||||
strcatf(str, "<Item><Details>"
|
strcatf(str, "<Item><Details>"
|
||||||
"<ContentType>image/*</ContentType>"
|
"<ContentType>%s</ContentType>"
|
||||||
"<SourceFormat>image/jpeg</SourceFormat>"
|
"<SourceFormat>%s</SourceFormat>"
|
||||||
"<SourceSize>%s</SourceSize>", size);
|
"<SourceSize>%s</SourceSize>",
|
||||||
|
"image/*", mime, size);
|
||||||
if( date )
|
if( date )
|
||||||
{
|
{
|
||||||
struct tm tm;
|
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));
|
strcatf(str, "<CaptureDate>0x%X</CaptureDate>", (unsigned int)mktime(&tm));
|
||||||
}
|
}
|
||||||
if( comment )
|
if( comment )
|
||||||
{
|
|
||||||
strcatf(str, "<Caption>%s</Caption>", comment);
|
strcatf(str, "<Caption>%s</Caption>", comment);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if( strncmp(mime, "video", 5) == 0 )
|
else if( strncmp(mime, "video", 5) == 0 )
|
||||||
{
|
{
|
||||||
char *episode;
|
char *episode;
|
||||||
flags |= FLAG_NO_PARAMS;
|
|
||||||
flags |= FLAG_VIDEO;
|
flags |= FLAG_VIDEO;
|
||||||
strcatf(str, "<Item><Details>"
|
strcatf(str, "<Item><Details>"
|
||||||
"<ContentType>video/x-tivo-mpeg</ContentType>"
|
"<ContentType>%s</ContentType>"
|
||||||
"<SourceFormat>%s</SourceFormat>"
|
"<SourceFormat>%s</SourceFormat>"
|
||||||
"<SourceSize>%s</SourceSize>", mime, size);
|
"<SourceSize>%s</SourceSize>",
|
||||||
|
mime, mime, size);
|
||||||
episode = strstr(title, " - ");
|
episode = strstr(title, " - ");
|
||||||
if( episode )
|
if( episode )
|
||||||
{
|
{
|
||||||
@ -182,10 +202,8 @@ callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
strcatf(str, "<CaptureDate>0x%X</CaptureDate>", (unsigned int)mktime(&tm));
|
strcatf(str, "<CaptureDate>0x%X</CaptureDate>", (unsigned int)mktime(&tm));
|
||||||
}
|
}
|
||||||
if( comment )
|
if( comment )
|
||||||
{
|
|
||||||
strcatf(str, "<Description>%s</Description>", comment);
|
strcatf(str, "<Description>%s</Description>", comment);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -217,28 +235,24 @@ callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
if( sampleFrequency ) {
|
if( sampleFrequency ) {
|
||||||
strcatf(str, "<SourceSampleRate>%s</SourceSampleRate>", sampleFrequency);
|
strcatf(str, "<SourceSampleRate>%s</SourceSampleRate>", sampleFrequency);
|
||||||
}
|
}
|
||||||
strcatf(str, "</Details><Links><Content>"
|
strcatf(str, "</Details><Links>"
|
||||||
|
"<Content>"
|
||||||
"<ContentType>%s</ContentType>"
|
"<ContentType>%s</ContentType>"
|
||||||
"<Url>/%s/%s.dat</Url>%s</Content>",
|
"<Url>/%s/%s.%s</Url>%s"
|
||||||
|
"</Content>",
|
||||||
mime,
|
mime,
|
||||||
(flags & FLAG_SEND_RESIZED)?"Resized":"MediaItems", detailID,
|
(flags & FLAG_SEND_RESIZED) ? "Resized" : "MediaItems",
|
||||||
(flags & FLAG_NO_PARAMS)?"<AcceptsParams>No</AcceptsParams>":"");
|
detailID, mime_to_ext(mime),
|
||||||
|
(flags & FLAG_NO_PARAMS) ? "<AcceptsParams>No</AcceptsParams>" : "");
|
||||||
if( flags & FLAG_VIDEO )
|
if( flags & FLAG_VIDEO )
|
||||||
{
|
{
|
||||||
char *esc_name = escape_tag(basename(path), 1);
|
|
||||||
strcatf(str, "<CustomIcon>"
|
strcatf(str, "<CustomIcon>"
|
||||||
"<ContentType>video/*</ContentType>"
|
"<ContentType>image/*</ContentType>"
|
||||||
"<Url>urn:tivo:image:save-until-i-delete-recording</Url>"
|
"<Url>urn:tivo:image:save-until-i-delete-recording</Url>"
|
||||||
"</CustomIcon>"
|
"</CustomIcon>");
|
||||||
"<Push><Container>Videos</Container></Push>"
|
|
||||||
"<File>%s</File> </Links>", esc_name);
|
|
||||||
free(esc_name);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
strcatf(str, "</Links>");
|
strcatf(str, "</Links>");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if( strncmp(class, "container", 9) == 0 )
|
else if( strncmp(class, "container", 9) == 0 )
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
@ -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);
|
count = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", id);
|
||||||
#else
|
#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 "
|
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);
|
" or CLASS glob 'container*')", id);
|
||||||
#endif
|
#endif
|
||||||
strcatf(str, "<Item>"
|
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," \
|
#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.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
|
static void
|
||||||
SendItemDetails(struct upnphttp *h, int64_t item)
|
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 )
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -551,7 +565,7 @@ SendContainer(struct upnphttp *h, const char *objectID, int itemStart, int itemC
|
|||||||
}
|
}
|
||||||
else
|
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 )
|
if( anchorItem )
|
||||||
@ -652,7 +666,7 @@ ProcessTiVoCommand(struct upnphttp *h, const char *orig_path)
|
|||||||
char *key, *val;
|
char *key, *val;
|
||||||
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, *sformat = NULL;
|
||||||
int64_t detailItem=0;
|
int64_t 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;
|
||||||
@ -718,6 +732,10 @@ ProcessTiVoCommand(struct upnphttp *h, const char *orig_path)
|
|||||||
if( val )
|
if( val )
|
||||||
detailItem = strtoll(basename(val), NULL, 10);
|
detailItem = strtoll(basename(val), NULL, 10);
|
||||||
}
|
}
|
||||||
|
else if( strcasecmp(key, "SourceFormat") == 0 )
|
||||||
|
{
|
||||||
|
sformat = val;
|
||||||
|
}
|
||||||
else if( strcasecmp(key, "Format") == 0 || // Only send XML
|
else if( strcasecmp(key, "Format") == 0 || // Only send XML
|
||||||
strcasecmp(key, "SerialNum") == 0 || // Unused for now
|
strcasecmp(key, "SerialNum") == 0 || // Unused for now
|
||||||
strcasecmp(key, "DoGenres") == 0 ) // Not sure what this is, so ignore it
|
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);
|
SendItemDetails(h, detailItem);
|
||||||
}
|
}
|
||||||
|
else if( strcmp(command, "QueryFormats") == 0 )
|
||||||
|
{
|
||||||
|
SendFormats(h, sformat);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINTF(E_DEBUG, L_GENERAL, "Unhandled command [%s]\n", command);
|
DPRINTF(E_DEBUG, L_GENERAL, "Unhandled command [%s]\n", command);
|
||||||
|
78
upnpsoap.c
78
upnpsoap.c
@ -292,78 +292,6 @@ GetCurrentConnectionInfo(struct upnphttp * h, const char * action)
|
|||||||
ClearNameValueList(&data);
|
ClearNameValueList(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
mime_to_ext(const char * mime, char * buf)
|
|
||||||
{
|
|
||||||
switch( *mime )
|
|
||||||
{
|
|
||||||
/* Audio extensions */
|
|
||||||
case 'a':
|
|
||||||
if( strcmp(mime+6, "mpeg") == 0 )
|
|
||||||
strcpy(buf, "mp3");
|
|
||||||
else if( strcmp(mime+6, "mp4") == 0 )
|
|
||||||
strcpy(buf, "m4a");
|
|
||||||
else if( strcmp(mime+6, "x-ms-wma") == 0 )
|
|
||||||
strcpy(buf, "wma");
|
|
||||||
else if( strcmp(mime+6, "x-flac") == 0 )
|
|
||||||
strcpy(buf, "flac");
|
|
||||||
else if( strcmp(mime+6, "flac") == 0 )
|
|
||||||
strcpy(buf, "flac");
|
|
||||||
else if( strcmp(mime+6, "x-wav") == 0 )
|
|
||||||
strcpy(buf, "wav");
|
|
||||||
else if( strncmp(mime+6, "L16", 3) == 0 )
|
|
||||||
strcpy(buf, "pcm");
|
|
||||||
else if( strcmp(mime+6, "3gpp") == 0 )
|
|
||||||
strcpy(buf, "3gp");
|
|
||||||
else if( strcmp(mime, "application/ogg") == 0 )
|
|
||||||
strcpy(buf, "ogg");
|
|
||||||
else
|
|
||||||
strcpy(buf, "dat");
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
if( strcmp(mime+6, "avi") == 0 )
|
|
||||||
strcpy(buf, "avi");
|
|
||||||
else if( strcmp(mime+6, "divx") == 0 )
|
|
||||||
strcpy(buf, "avi");
|
|
||||||
else if( strcmp(mime+6, "x-msvideo") == 0 )
|
|
||||||
strcpy(buf, "avi");
|
|
||||||
else if( strcmp(mime+6, "mpeg") == 0 )
|
|
||||||
strcpy(buf, "mpg");
|
|
||||||
else if( strcmp(mime+6, "mp4") == 0 )
|
|
||||||
strcpy(buf, "mp4");
|
|
||||||
else if( strcmp(mime+6, "x-ms-wmv") == 0 )
|
|
||||||
strcpy(buf, "wmv");
|
|
||||||
else if( strcmp(mime+6, "x-matroska") == 0 )
|
|
||||||
strcpy(buf, "mkv");
|
|
||||||
else if( strcmp(mime+6, "x-mkv") == 0 )
|
|
||||||
strcpy(buf, "mkv");
|
|
||||||
else if( strcmp(mime+6, "x-flv") == 0 )
|
|
||||||
strcpy(buf, "flv");
|
|
||||||
else if( strcmp(mime+6, "vnd.dlna.mpeg-tts") == 0 )
|
|
||||||
strcpy(buf, "mpg");
|
|
||||||
else if( strcmp(mime+6, "quicktime") == 0 )
|
|
||||||
strcpy(buf, "mov");
|
|
||||||
else if( strcmp(mime+6, "3gpp") == 0 )
|
|
||||||
strcpy(buf, "3gp");
|
|
||||||
else if( strcmp(mime+6, "x-tivo-mpeg") == 0 )
|
|
||||||
strcpy(buf, "TiVo");
|
|
||||||
else
|
|
||||||
strcpy(buf, "dat");
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
if( strcmp(mime+6, "jpeg") == 0 )
|
|
||||||
strcpy(buf, "jpg");
|
|
||||||
else if( strcmp(mime+6, "png") == 0 )
|
|
||||||
strcpy(buf, "png");
|
|
||||||
else
|
|
||||||
strcpy(buf, "dat");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
strcpy(buf, "dat");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Standard DLNA/UPnP filter flags */
|
/* Standard DLNA/UPnP filter flags */
|
||||||
#define FILTER_CHILDCOUNT 0x00000001
|
#define FILTER_CHILDCOUNT 0x00000001
|
||||||
#define FILTER_DC_CREATOR 0x00000002
|
#define FILTER_DC_CREATOR 0x00000002
|
||||||
@ -671,7 +599,7 @@ add_resized_res(int srcw, int srch, int reqw, int reqh, char *dlna_pn,
|
|||||||
inline static void
|
inline static void
|
||||||
add_res(char *size, char *duration, char *bitrate, char *sampleFrequency,
|
add_res(char *size, char *duration, char *bitrate, char *sampleFrequency,
|
||||||
char *nrAudioChannels, char *resolution, char *dlna_pn, char *mime,
|
char *nrAudioChannels, char *resolution, char *dlna_pn, char *mime,
|
||||||
char *detailID, char *ext, struct Response *args)
|
char *detailID, const char *ext, struct Response *args)
|
||||||
{
|
{
|
||||||
strcatf(args->str, "<res ");
|
strcatf(args->str, "<res ");
|
||||||
if( size && (args->filter & FILTER_RES_SIZE) ) {
|
if( size && (args->filter & FILTER_RES_SIZE) ) {
|
||||||
@ -728,7 +656,7 @@ callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
*genre = argv[12], *comment = argv[13], *nrAudioChannels = argv[14], *track = argv[15], *date = argv[16], *resolution = argv[17],
|
*genre = argv[12], *comment = argv[13], *nrAudioChannels = argv[14], *track = argv[15], *date = argv[16], *resolution = argv[17],
|
||||||
*tn = argv[18], *creator = argv[19], *dlna_pn = argv[20], *mime = argv[21], *album_art = argv[22];
|
*tn = argv[18], *creator = argv[19], *dlna_pn = argv[20], *mime = argv[21], *album_art = argv[22];
|
||||||
char dlna_buf[128];
|
char dlna_buf[128];
|
||||||
char ext[5];
|
const char *ext;
|
||||||
struct string_s *str = passed_args->str;
|
struct string_s *str = passed_args->str;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -938,7 +866,7 @@ callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( passed_args->filter & FILTER_RES ) {
|
if( passed_args->filter & FILTER_RES ) {
|
||||||
mime_to_ext(mime, ext);
|
ext = mime_to_ext(mime);
|
||||||
add_res(size, duration, bitrate, sampleFrequency, nrAudioChannels,
|
add_res(size, duration, bitrate, sampleFrequency, nrAudioChannels,
|
||||||
resolution, dlna_buf, mime, detailID, ext, passed_args);
|
resolution, dlna_buf, mime, detailID, ext, passed_args);
|
||||||
if( *mime == 'i' ) {
|
if( *mime == 'i' ) {
|
||||||
|
66
utils.c
66
utils.c
@ -293,6 +293,72 @@ DJBHash(const char *str, int len)
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
mime_to_ext(const char * mime)
|
||||||
|
{
|
||||||
|
switch( *mime )
|
||||||
|
{
|
||||||
|
/* Audio extensions */
|
||||||
|
case 'a':
|
||||||
|
if( strcmp(mime+6, "mpeg") == 0 )
|
||||||
|
return "mp3";
|
||||||
|
else if( strcmp(mime+6, "mp4") == 0 )
|
||||||
|
return "m4a";
|
||||||
|
else if( strcmp(mime+6, "x-ms-wma") == 0 )
|
||||||
|
return "wma";
|
||||||
|
else if( strcmp(mime+6, "x-flac") == 0 )
|
||||||
|
return "flac";
|
||||||
|
else if( strcmp(mime+6, "flac") == 0 )
|
||||||
|
return "flac";
|
||||||
|
else if( strcmp(mime+6, "x-wav") == 0 )
|
||||||
|
return "wav";
|
||||||
|
else if( strncmp(mime+6, "L16", 3) == 0 )
|
||||||
|
return "pcm";
|
||||||
|
else if( strcmp(mime+6, "3gpp") == 0 )
|
||||||
|
return "3gp";
|
||||||
|
else if( strcmp(mime, "application/ogg") == 0 )
|
||||||
|
return "ogg";
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
if( strcmp(mime+6, "avi") == 0 )
|
||||||
|
return "avi";
|
||||||
|
else if( strcmp(mime+6, "divx") == 0 )
|
||||||
|
return "avi";
|
||||||
|
else if( strcmp(mime+6, "x-msvideo") == 0 )
|
||||||
|
return "avi";
|
||||||
|
else if( strcmp(mime+6, "mpeg") == 0 )
|
||||||
|
return "mpg";
|
||||||
|
else if( strcmp(mime+6, "mp4") == 0 )
|
||||||
|
return "mp4";
|
||||||
|
else if( strcmp(mime+6, "x-ms-wmv") == 0 )
|
||||||
|
return "wmv";
|
||||||
|
else if( strcmp(mime+6, "x-matroska") == 0 )
|
||||||
|
return "mkv";
|
||||||
|
else if( strcmp(mime+6, "x-mkv") == 0 )
|
||||||
|
return "mkv";
|
||||||
|
else if( strcmp(mime+6, "x-flv") == 0 )
|
||||||
|
return "flv";
|
||||||
|
else if( strcmp(mime+6, "vnd.dlna.mpeg-tts") == 0 )
|
||||||
|
return "mpg";
|
||||||
|
else if( strcmp(mime+6, "quicktime") == 0 )
|
||||||
|
return "mov";
|
||||||
|
else if( strcmp(mime+6, "3gpp") == 0 )
|
||||||
|
return "3gp";
|
||||||
|
else if( strncmp(mime+6, "x-tivo-mpeg", 11) == 0 )
|
||||||
|
return "TiVo";
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
if( strcmp(mime+6, "jpeg") == 0 )
|
||||||
|
return "jpg";
|
||||||
|
else if( strcmp(mime+6, "png") == 0 )
|
||||||
|
return "png";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "dat";
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
is_video(const char * file)
|
is_video(const char * file)
|
||||||
{
|
{
|
||||||
|
73
utils.h
73
utils.h
@ -26,58 +26,29 @@
|
|||||||
|
|
||||||
#include "minidlnatypes.h"
|
#include "minidlnatypes.h"
|
||||||
|
|
||||||
int
|
/* String functions */
|
||||||
strcatf(struct string_s *str, char *fmt, ...);
|
int strcatf(struct string_s *str, char *fmt, ...);
|
||||||
|
void strncpyt(char *dst, const char *src, size_t len);
|
||||||
|
inline int xasprintf(char **strp, char *fmt, ...);
|
||||||
|
int ends_with(const char * haystack, const char * needle);
|
||||||
|
char *trim(char *str);
|
||||||
|
char *strstrc(const char *s, const char *p, const char t);
|
||||||
|
char *strcasestrc(const char *s, const char *p, const char t);
|
||||||
|
char *modifyString(char * string, const char * before, const char * after);
|
||||||
|
char *escape_tag(const char *tag, int force_alloc);
|
||||||
|
void strip_ext(char * name);
|
||||||
|
|
||||||
void
|
/* Metadata functions */
|
||||||
strncpyt(char *dst, const char *src, size_t len);
|
int is_video(const char * file);
|
||||||
|
int is_audio(const char * file);
|
||||||
|
int is_image(const char * file);
|
||||||
|
int is_playlist(const char * file);
|
||||||
|
int is_album_art(const char * name);
|
||||||
|
int resolve_unknown_type(const char * path, media_types dir_type);
|
||||||
|
const char *mime_to_ext(const char * mime);
|
||||||
|
|
||||||
inline int
|
/* Others */
|
||||||
xasprintf(char **strp, char *fmt, ...);
|
int make_dir(char * path, mode_t mode);
|
||||||
|
unsigned int DJBHash(const char *str, int len);
|
||||||
int
|
|
||||||
ends_with(const char * haystack, const char * needle);
|
|
||||||
|
|
||||||
char *
|
|
||||||
trim(char *str);
|
|
||||||
|
|
||||||
char *
|
|
||||||
strstrc(const char *s, const char *p, const char t);
|
|
||||||
|
|
||||||
char *
|
|
||||||
strcasestrc(const char *s, const char *p, const char t);
|
|
||||||
|
|
||||||
char *
|
|
||||||
modifyString(char * string, const char * before, const char * after);
|
|
||||||
|
|
||||||
char *
|
|
||||||
escape_tag(const char *tag, int force_alloc);
|
|
||||||
|
|
||||||
void
|
|
||||||
strip_ext(char * name);
|
|
||||||
|
|
||||||
int
|
|
||||||
make_dir(char * path, mode_t mode);
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
DJBHash(const char *str, int len);
|
|
||||||
|
|
||||||
int
|
|
||||||
is_video(const char * file);
|
|
||||||
|
|
||||||
int
|
|
||||||
is_audio(const char * file);
|
|
||||||
|
|
||||||
int
|
|
||||||
is_image(const char * file);
|
|
||||||
|
|
||||||
int
|
|
||||||
is_playlist(const char * file);
|
|
||||||
|
|
||||||
int
|
|
||||||
is_album_art(const char * name);
|
|
||||||
|
|
||||||
int
|
|
||||||
resolve_unknown_type(const char * path, media_types dir_type);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user