From dee22896a815ccf77ffb4901cdb0739033f1839e Mon Sep 17 00:00:00 2001 From: Ron Pedde Date: Fri, 11 Nov 2005 23:52:42 +0000 Subject: [PATCH] codectype transcoding --- admin-root/hdr.html | 3 +- contrib/mt-daapd.conf | 22 ++++-- src/configfile.c | 14 ++-- src/daapd.h | 2 +- src/dbs-sqlite.c | 4 +- src/dispatch.c | 4 +- src/ssc.c | 155 +++++++++++++----------------------------- src/ssc.h | 2 +- src/xml-rpc.c | 15 ++++ 9 files changed, 98 insertions(+), 123 deletions(-) diff --git a/admin-root/hdr.html b/admin-root/hdr.html index 480b0571..15513742 100644 --- a/admin-root/hdr.html +++ b/admin-root/hdr.html @@ -1,5 +1,4 @@ - + .: m t - d a a p d :. diff --git a/contrib/mt-daapd.conf b/contrib/mt-daapd.conf index 7c5e6c7e..2d24bdad 100644 --- a/contrib/mt-daapd.conf +++ b/contrib/mt-daapd.conf @@ -128,16 +128,28 @@ playlist /etc/mt-daapd.playlist extensions .mp3,.m4a,.m4p,.ogg # -# ssc_extensions (optional) +# ssc_codectypes (optional) # -# List of file extensions belonging to the files daap server -# performs internal format conversion and present to clients -# as WAV files. Extensions must also be present in 'extensions' +# List of codectypes for files that the daap server should +# perform internal format conversion and present to clients +# as WAV files. The file extensions that these codectypes correspond +# to must also be present in 'extensions' # configuration value, or files are not probed in the first # place. # +# Valid codectypes: +# +# mp4a - for AAC (.aac, .mp4, .m4a, .m4p) +# mpeg - for mp3 +# wav - for wav +# wma - for wma +# ogg - for ogg +# flac - for flac (.flac, .fla) +# mpc for musepack (.mpc, .mpp, .mp+) +# alac for alac (.m4a) +# -ssc_extensions .ogg +ssc_codectypes ogg,flac,alac # # ssc_prog (optional) diff --git a/src/configfile.c b/src/configfile.c index 73898ee4..7dc8fc69 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -132,7 +132,7 @@ CONFIGELEMENT config_elements[] = { { 1,0,0,CONFIG_TYPE_STRING,"playlist",(void*)&config.playlist,config_emit_string }, { 1,0,0,CONFIG_TYPE_STRING,"extensions",(void*)&config.extensions,config_emit_string }, { 1,0,0,CONFIG_TYPE_STRING,"interface",(void*)&config.iface,config_emit_string }, - { 1,0,0,CONFIG_TYPE_STRING,"ssc_extensions",(void*)&config.ssc_extensions,config_emit_string }, + { 1,0,0,CONFIG_TYPE_STRING,"ssc_codectypes",(void*)&config.ssc_codectypes,config_emit_string }, { 1,0,0,CONFIG_TYPE_STRING,"ssc_prog",(void*)&config.ssc_prog,config_emit_string }, { 1,0,0,CONFIG_TYPE_STRING,"password",(void*)&config.readpassword, config_emit_string }, { 1,0,0,CONFIG_TYPE_STRING,"compdirs",(void*)&config.compdirs, config_emit_string }, @@ -307,7 +307,7 @@ int config_read(char *file) { /* DWB: use alloced space so it can be freed without errors */ config.extensions=strdup(".mp3"); - config.ssc_extensions=strdup(""); + config.ssc_codectypes=strdup(""); config.ssc_prog=strdup(""); /* DWB: use alloced space so it can be freed without errors */ @@ -564,7 +564,7 @@ int config_write(WS_CONNINFO *pwsc) { if(ws_getvar(pwsc,"password") && strlen(ws_getvar(pwsc,"password"))) fprintf(configfile,"password\t%s\n",ws_getvar(pwsc,"password")); fprintf(configfile,"extensions\t%s\n",ws_getvar(pwsc,"extensions")); - fprintf(configfile,"ssc_extensions\t%s\n",ws_getvar(pwsc,"ssc_extensions")); + fprintf(configfile,"ssc_codectypes\t%s\n",ws_getvar(pwsc,"ssc_codectypes")); fprintf(configfile,"ssc_prog\t%s\n",ws_getvar(pwsc,"ssc_prog")); fprintf(configfile,"db_dir\t\t%s\n",ws_getvar(pwsc,"db_dir")); fprintf(configfile,"rescan_interval\t%s\n",ws_getvar(pwsc,"rescan_interval")); @@ -1085,9 +1085,13 @@ void config_emit_ispage(WS_CONNINFO *pwsc, void *value, char *arg) { if((strlen(page) > strlen(pwsc->uri)) || (strcasecmp(page,(char*)&pwsc->uri[strlen(pwsc->uri) - strlen(page)]) != 0)) { - ws_writefd(pwsc,"%s",false); + if(false) { + ws_writefd(pwsc,"%s",false); + } } else { - ws_writefd(pwsc,"%s",true); + if(true) { + ws_writefd(pwsc,"%s",true); + } } diff --git a/src/daapd.h b/src/daapd.h index 31450a78..cd30e387 100644 --- a/src/daapd.h +++ b/src/daapd.h @@ -68,7 +68,7 @@ typedef struct tag_config { char *runas; /**< Who to drop privs to (if run as root) */ char *dbdir; /**< Where to put the db file */ char *extensions; /**< What music file extentions to process */ - char *ssc_extensions; /**< What extensions are converted in server */ + char *ssc_codectypes; /**< What codectypes are converted in server */ char *ssc_prog; /**< Server side music format converter prog */ char *artfilename; /**< What filename to merge coverart with */ char *logfile; /**< What file to use as a logfile */ diff --git a/src/dbs-sqlite.c b/src/dbs-sqlite.c index 5ec61515..1d443578 100644 --- a/src/dbs-sqlite.c +++ b/src/dbs-sqlite.c @@ -1104,7 +1104,7 @@ int db_sqlite_get_size(DBQUERYINFO *pinfo, char **valarray) { case queryTypeItems: case queryTypePlaylistItems: /* essentially the same query */ /* see if this is going to be transcoded */ - transcode = server_side_convert(valarray[2]); + transcode = server_side_convert(valarray[37]); /* Items that get changed by transcode: * @@ -1271,7 +1271,7 @@ int db_sqlite_build_dmap(DBQUERYINFO *pinfo, char **valarray, unsigned char *pre case queryTypeItems: case queryTypePlaylistItems: /* essentially the same query */ /* see if this is going to be transcoded */ - transcode = server_side_convert(valarray[2]); + transcode = server_side_convert(valarray[37]); /* Items that get changed by transcode: * diff --git a/src/dispatch.c b/src/dispatch.c index 299dcb00..1bd7b57f 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -143,6 +143,8 @@ void daap_handler(WS_CONNINFO *pwsc) { ws_addresponseheader(pwsc,"Accept-Ranges","bytes"); ws_addresponseheader(pwsc,"DAAP-Server","mt-daapd/" VERSION); ws_addresponseheader(pwsc,"Content-Type","application/x-dmap-tagged"); + ws_addresponseheader(pwsc,"Cache-Control","no-cache"); /* anti-ie defense */ + ws_addresponseheader(pwsc,"Expires","-1"); if(ws_getvar(pwsc,"session-id")) pqi->session_id = atoi(ws_getvar(pwsc,"session-id")); @@ -626,7 +628,7 @@ void dispatch_stream(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { if(!pmp3) { DPRINTF(E_LOG,L_DAAP|L_WS|L_DB,"Could not find requested item %lu\n",item); ws_returnerror(pwsc,404,"File Not Found"); - } else if (server_side_convert(pmp3->fname)) { + } else if (server_side_convert(pmp3->codectype)) { /************************ * Server side conversion ************************/ diff --git a/src/ssc.c b/src/ssc.c index fa64e9fc..7c016579 100644 --- a/src/ssc.c +++ b/src/ssc.c @@ -48,120 +48,31 @@ # include "strcasestr.h" #endif -/** - * If path is server side convertable, return the path to real file. - * - * @param path char * to the path in the database. - */ -char *server_side_convert_path(char *path) -{ - char *r = NULL; - - if (path && - (strlen(path) > strlen(SERVER_SIDE_CONVERT_SUFFIX)) && - (strcmp(path + strlen(path) - strlen(SERVER_SIDE_CONVERT_SUFFIX), - SERVER_SIDE_CONVERT_SUFFIX) == 0)) { - /* Lose the artificial suffix. Could use strndup here.*/ - r = strdup(path); - r[strlen(path) - strlen(SERVER_SIDE_CONVERT_SUFFIX)] = '\0'; - } - - return r; -} - - /** * Check if the file specified by fname should be converted in * server to wav. Currently it does this by file extension, but * could in the future decided to transcode based on user agent. * - * @param fname file name of file to check for conversion + * @param codectype codec type of the file we are checking for conversion * @returns 1 if should be converted. 0 if not */ -int server_side_convert(char *fname) { - char *ext; - - DPRINTF(E_SPAM,L_SCAN,"Checking for ssc: %s\n",fname); - - if ((!config.ssc_extensions) || - (!config.ssc_extensions[0]) || - (!config.ssc_prog) || - (!config.ssc_prog[0]) || - (!fname)) { - DPRINTF(E_DBG,L_SCAN,"Nope\n"); - return 0; +int server_side_convert(char *codectype) { + if ((!config.ssc_codectypes) || + (!config.ssc_codectypes[0]) || + (!config.ssc_prog) || + (!config.ssc_prog[0]) || + (!codectype)) { + DPRINTF(E_DBG,L_SCAN,"Nope\n"); + return 0; } - if(((ext = strrchr(fname, '.')) != NULL) && - (strcasestr(config.ssc_extensions, ext))) { - DPRINTF(E_SPAM,L_SCAN,"Yup\n"); - return 1; + if(strcasestr(config.ssc_codectypes, codectype)) { + return 1; } - DPRINTF(E_SPAM,L_SCAN,"Nope\n"); return 0; } -/** - * Check if the file entry (otherwise complete) is such that - * file should be converted in server end to wav-format. - * If so, the info is modified accordingly and non-zero return - * value is returned. - * - * @param song MP3FILE of the file to possibly set to server side conversion - */ -int server_side_convert_set(MP3FILE *pmp3) -{ - char *fname, *path, *description, *ext; - DPRINTF(E_SPAM,L_SCAN,"Checking for ssc: %s\n",pmp3->fname); - if ((!config.ssc_extensions) || - (!config.ssc_extensions[0]) || - (!config.ssc_prog) || - (!config.ssc_prog[0]) || - (!pmp3->fname) || - (!pmp3->path) || - (!pmp3->type) || - ((strlen(pmp3->fname) > strlen(SERVER_SIDE_CONVERT_SUFFIX)) && - (strcmp(pmp3->fname + - strlen(pmp3->fname) - - strlen(SERVER_SIDE_CONVERT_SUFFIX), - SERVER_SIDE_CONVERT_SUFFIX) == 0))) { - DPRINTF(E_SPAM,L_SCAN,"Nope\n"); - return 0; - } - - DPRINTF(E_SPAM,L_SCAN,"Yup\n"); - if (((ext = strrchr(pmp3->path, '.')) != NULL) && - (strcasestr(config.ssc_extensions, ext))) { - fname = (char *)malloc(strlen(pmp3->fname) + - strlen(SERVER_SIDE_CONVERT_SUFFIX) + 1); - path = (char *)malloc(strlen(pmp3->path) + - strlen(SERVER_SIDE_CONVERT_SUFFIX) + 1); - description = (char *)malloc(strlen(pmp3->description) + - strlen(SERVER_SIDE_CONVERT_DESCR) + 1); - strcpy(fname, pmp3->fname); - strcat(fname, SERVER_SIDE_CONVERT_SUFFIX); - free(pmp3->fname); - pmp3->fname = fname; - strcpy(path, pmp3->path); - strcat(path, SERVER_SIDE_CONVERT_SUFFIX); - free(pmp3->path); - pmp3->path = path; - strcpy(description, pmp3->description); - strcat(description, SERVER_SIDE_CONVERT_DESCR); - free(pmp3->description); - pmp3->description = description; - free(pmp3->type); - pmp3->type = strdup("wav"); - if (pmp3->samplerate > 0) { - // Here we guess that it's always 16 bit stereo samples, - // which is accurate enough for now. - pmp3->bitrate = (pmp3->samplerate * 4 * 8) / 1000; - } - return 1; - } - return 0; -} /** * Open the source file with convert fiter. @@ -169,17 +80,49 @@ int server_side_convert_set(MP3FILE *pmp3) * @param path char * to the real filename. * @param offset off_t to the point in file where the streaming starts. */ -FILE *server_side_convert_open(char *path, off_t offset, unsigned long len_ms) -{ +FILE *server_side_convert_open(char *path, off_t offset, unsigned long len_ms) { char *cmd; FILE *f; + char *newpath; + char *metachars = "\"();"; /* More?? */ + char metacount = 0; + char *src,*dst; + + src=path; + while(*src) { + if(strchr(metachars,*src)) + metacount++; + src++; + } + + if(metachars) { + newpath = (char*)malloc(strlen(path) + metacount + 1); + if(!newpath) { + DPRINTF(E_FATAL,L_SCAN,"Malloc error.\n"); + } + src=path; + dst=newpath; + + while(*src) { + if(strchr(metachars,*src)) + *dst++='\\'; + *dst++=*src++; + } + *dst='\0'; + } else { + newpath = strdup(path); /* becuase it will be freed... */ + } + /* FIXME: is 64 enough? is there a better way to determine this? */ cmd=(char *)malloc(strlen(config.ssc_prog) + - strlen(path) + - 64); + strlen(path) + + 64); sprintf(cmd, "%s \"%s\" %ld %lu.%03lu", - config.ssc_prog, path, (long)offset, len_ms / 1000, len_ms % 1000); + config.ssc_prog, newpath, (long)offset, len_ms / 1000, len_ms % 1000); + DPRINTF(E_INF,L_SCAN,"Executing %s\n",cmd); f = popen(cmd, "r"); + free(newpath); + free(cmd); /* should really have in-place expanded the path */ return f; } @@ -191,7 +134,7 @@ FILE *server_side_convert_open(char *path, off_t offset, unsigned long len_ms) void server_side_convert_close(FILE *f) { if (f) - pclose(f); + pclose(f); return; } diff --git a/src/ssc.h b/src/ssc.h index ca2f4dca..c75892e5 100644 --- a/src/ssc.h +++ b/src/ssc.h @@ -25,7 +25,7 @@ #define SERVER_SIDE_CONVERT_SUFFIX ".-*-ssc-*-.wav" #define SERVER_SIDE_CONVERT_DESCR " (converted to WAV)" -extern int server_side_convert(char *fname); +extern int server_side_convert(char *codectype); extern int server_side_convert_set(MP3FILE *pmp3); extern char *server_side_convert_path(char *path); extern FILE *server_side_convert_open(char *path, diff --git a/src/xml-rpc.c b/src/xml-rpc.c index 3ec900c4..655cea56 100644 --- a/src/xml-rpc.c +++ b/src/xml-rpc.c @@ -15,10 +15,25 @@ #include "mp3-scanner.h" #include "webserver.h" +/* typedefs */ +typedef struct tag_xmlstruct { +} XMLSTRUCT; + /* Forwards */ void xml_get_stats(WS_CONNINFO *pwsc); char *xml_entity_encode(char *original); +/** + * create an xml response structure, a helper struct for + * building xml responses. + * + * @returns XMLSTRUCT on success, or NULL if failure + */ +XMLSTRUCT *xml_init(void) { +} + + + /** * main entrypoint for the xmlrpc functions. *