int 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]; char str_buf[4096]; int ret = 0, flags = 0, count; if( strncmp(class, "item", 4) == 0 ) { unescape_tag(title); if( strncmp(mime, "audio", 5) == 0 ) { flags |= FLAG_NO_PARAMS; ret = sprintf(str_buf, "<Item><Details>" "<ContentType>audio/*</ContentType>" "<SourceFormat>%s</SourceFormat>" "<SourceSize>%s</SourceSize>" "<SongTitle>%s</SongTitle>", mime, size, title); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; if( date ) { ret = sprintf(str_buf, "<AlbumYear>%.*s</AlbumYear>", 4, date); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } } else if( strcmp(mime, "image/jpeg") == 0 ) { flags |= FLAG_SEND_RESIZED; ret = sprintf(str_buf, "<Item><Details>" "<ContentType>image/*</ContentType>" "<SourceFormat>image/jpeg</SourceFormat>" "<SourceSize>%s</SourceSize>", size); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; if( date ) { struct tm tm; memset(&tm, 0, sizeof(tm)); strptime(date, "%Y-%m-%dT%H:%M:%S", &tm); ret = sprintf(str_buf, "<CaptureDate>0x%X</CaptureDate>", (unsigned int)mktime(&tm)); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } if( comment ) { ret = sprintf(str_buf, "<Caption>%s</Caption>", comment); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } } else if( strncmp(mime, "video", 5) == 0 ) { flags |= FLAG_NO_PARAMS; flags |= FLAG_VIDEO; ret = sprintf(str_buf, "<Item><Details>" "<ContentType>video/x-tivo-mpeg</ContentType>" "<SourceFormat>%s</SourceFormat>" "<SourceSize>%s</SourceSize>" "<EpisodeTitle>%s</EpisodeTitle>", mime, size, title); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; if( date ) { struct tm tm; memset(&tm, 0, sizeof(tm)); strptime(date, "%Y-%m-%dT%H:%M:%S", &tm); ret = sprintf(str_buf, "<CaptureDate>0x%X</CaptureDate>", (unsigned int)mktime(&tm)); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } } else { return 0; } ret = sprintf(str_buf, "<Title>%s</Title>", unescape_tag(title)); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; if( artist ) { ret = sprintf(str_buf, "<ArtistName>%s</ArtistName>", unescape_tag(artist)); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } if( album ) { ret = sprintf(str_buf, "<AlbumTitle>%s</AlbumTitle>", unescape_tag(album)); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } if( genre ) { ret = sprintf(str_buf, "<MusicGenre>%s</MusicGenre>", unescape_tag(genre)); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } if( resolution ) { char *width = strsep(&resolution, "x"); ret = sprintf(str_buf, "<SourceWidth>%s</SourceWidth>" "<SourceHeight>%s</SourceHeight>", width, resolution); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } if( duration ) { ret = sprintf(str_buf, "<Duration>%d</Duration>", atoi(rindex(duration, '.')+1) + (1000*atoi(rindex(duration, ':')+1)) + (60000*atoi(rindex(duration, ':')-2)) + (3600000*atoi(duration))); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } if( bitrate ) { ret = sprintf(str_buf, "<SourceBitRate>%s</SourceBitRate>", bitrate); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } if( sampleFrequency ) { ret = sprintf(str_buf, "<SourceSampleRate>%s</SourceSampleRate>", sampleFrequency); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; } ret = sprintf(str_buf, "</Details><Links><Content>" "<ContentType>%s</ContentType>" "<Url>/%s/%s.dat</Url>%s</Content>", mime, (flags & FLAG_SEND_RESIZED)?"Resized":"MediaItems", detailID, (flags & FLAG_NO_PARAMS)?"<AcceptsParams>No</AcceptsParams>":""); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; if( flags & FLAG_VIDEO ) { char *name = basename(path); char *esc_name = escape_tag(name); ret = sprintf(str_buf, "<CustomIcon>" "<ContentType>video/*</ContentType>" "<Url>urn:tivo:image:save-until-i-delete-recording</Url>" "</CustomIcon>" "<Push><Container>Videos</Container></Push>" "<File>%s</File> </Links>", esc_name?esc_name:name); if( esc_name ) free(esc_name); } else { ret = sprintf(str_buf, "</Links>"); } } else if( strncmp(class, "container", 9) == 0 )
void parse_nfo(const char *path, metadata_t *m) { FILE *nfo; char buf[65536]; struct NameValueParserData xml; struct stat file; size_t nread; char *val, *val2; if( stat(path, &file) != 0 || file.st_size > 65536 ) { DPRINTF(E_INFO, L_METADATA, "Not parsing very large .nfo file %s\n", path); return; } DPRINTF(E_DEBUG, L_METADATA, "Parsing .nfo file: %s\n", path); nfo = fopen(path, "r"); if( !nfo ) return; nread = fread(&buf, 1, sizeof(buf), nfo); ParseNameValue(buf, nread, &xml, 0); //printf("\ttype: %s\n", GetValueFromNameValueList(&xml, "rootElement")); val = GetValueFromNameValueList(&xml, "title"); if( val ) { char *esc_tag = unescape_tag(val, 1); val2 = GetValueFromNameValueList(&xml, "episodetitle"); if( val2 ) { char *esc_tag2 = unescape_tag(val2, 1); xasprintf(&m->title, "%s - %s", esc_tag, esc_tag2); free(esc_tag2); } else { m->title = escape_tag(esc_tag, 1); } free(esc_tag); } val = GetValueFromNameValueList(&xml, "plot"); if( val ) { char *esc_tag = unescape_tag(val, 1); m->comment = escape_tag(esc_tag, 1); free(esc_tag); } val = GetValueFromNameValueList(&xml, "capturedate"); if( val ) { char *esc_tag = unescape_tag(val, 1); m->date = escape_tag(esc_tag, 1); free(esc_tag); } val = GetValueFromNameValueList(&xml, "genre"); if( val ) { free(m->genre); char *esc_tag = unescape_tag(val, 1); m->genre = escape_tag(esc_tag, 1); free(esc_tag); } val = GetValueFromNameValueList(&xml, "mime"); if( val ) { free(m->mime); char *esc_tag = unescape_tag(val, 1); m->mime = escape_tag(esc_tag, 1); free(esc_tag); } ClearNameValueList(&xml); fclose(nfo); }
" or CLASS glob 'container*')", id); #endif ret = sprintf(str_buf, "<Item>" "<Details>" "<ContentType>x-container/folder</ContentType>" "<SourceFormat>x-container/folder</SourceFormat>" "<Title>%s</Title>" "<TotalItems>%d</TotalItems>" "</Details>" "<Links>" "<Content>" "<Url>/TiVoConnect?Command=QueryContainer&Container=%s</Url>" "<ContentType>x-tivo-container/folder</ContentType>" "</Content>" "</Links>", unescape_tag(title), count, id); } memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; ret = sprintf(str_buf, "</Item>"); memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1); passed_args->size += ret; passed_args->returned++; return 0; } void SendItemDetails(struct upnphttp * h, sqlite_int64 item) {