diff --git a/src/db-generic.c b/src/db-generic.c index 456a07c8..02cb3bbf 100644 --- a/src/db-generic.c +++ b/src/db-generic.c @@ -354,7 +354,8 @@ char *db_error_list[] = { "Could not initialize thread pool", "Passed buffer too small for result", "Wrong db schema. Use mtd-update to upgrade the db.", - "Database error: %s" + "Database error: %s", + "Malloc error" }; /* Globals */ diff --git a/src/db-generic.h b/src/db-generic.h index 122e6114..22aeef21 100644 --- a/src/db-generic.h +++ b/src/db-generic.h @@ -216,6 +216,7 @@ extern void db_dispose_playlist(M3UFILE *pm3u); #define DB_E_SIZE 0x0B /**< passed buffer too small */ #define DB_E_WRONGVERSION 0x0C /**< must upgrade db */ #define DB_E_DB_ERROR 0x0D /**< gdbm error */ +#define DB_E_MALLOC 0x0E /**< malloc error */ /* describes the individual database handlers */ typedef struct tag_dbinfo { diff --git a/src/dispatch.c b/src/dispatch.c index e8ffecde..6a4b3558 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -737,7 +737,7 @@ char *dispatch_xml_encode(char *original, int len) { return new; } -void dispatch_stream_id(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id) { +void dispatch_stream_id(WS_CONNINFO *pwsc, int session, char *id) { MP3FILE *pmp3; FILE *file_ptr; int file_fd; @@ -763,7 +763,7 @@ void dispatch_stream_id(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id) { pmp3=db_fetch_item(NULL,item); if(!pmp3) { DPRINTF(E_LOG,L_DAAP|L_WS|L_DB,"Could not find requested item %lu\n",item); - config_set_status(pwsc,pqi->session_id,NULL); + config_set_status(pwsc,session,NULL); ws_returnerror(pwsc,404,"File Not Found"); } else if (server_side_convert(pmp3->codectype)) { /************************ @@ -820,12 +820,12 @@ void dispatch_stream_id(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id) { ws_emitheaders(pwsc); - config_set_status(pwsc,pqi->session_id, + config_set_status(pwsc,session, "Transcoding '%s' (id %d)", pmp3->title,pmp3->id); DPRINTF(E_LOG,L_WS, "Session %d: Streaming file '%s' to %s (offset %ld)\n", - pqi->session_id,pmp3->fname, pwsc->hostname,(long)offset); + session,pmp3->fname, pwsc->hostname,(long)offset); if(!offset) config.stats.songs_served++; /* FIXME: remove stat races */ @@ -840,7 +840,7 @@ void dispatch_stream_id(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id) { } server_side_convert_close(file_ptr); - config_set_status(pwsc,pqi->session_id,NULL); + config_set_status(pwsc,session,NULL); db_dispose_item(pmp3); } } else { @@ -853,7 +853,7 @@ void dispatch_stream_id(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id) { DPRINTF(E_WARN,L_WS,"Thread %d: Error opening %s: %s\n", pwsc->threadno,pmp3->path,strerror(errno)); ws_returnerror(pwsc,404,"Not found"); - config_set_status(pwsc,pqi->session_id,NULL); + config_set_status(pwsc,session,NULL); db_dispose_item(pmp3); } else { real_len=lseek(file_fd,0,SEEK_END); @@ -903,10 +903,10 @@ void dispatch_stream_id(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id) { ws_emitheaders(pwsc); - config_set_status(pwsc,pqi->session_id,"Streaming '%s' (id %d)", + config_set_status(pwsc,session,"Streaming '%s' (id %d)", pmp3->title, pmp3->id); DPRINTF(E_LOG,L_WS,"Session %d: Streaming file '%s' to %s (offset %d)\n", - pqi->session_id,pmp3->fname, pwsc->hostname,(long)offset); + session,pmp3->fname, pwsc->hostname,(long)offset); if(!offset) config.stats.songs_served++; /* FIXME: remove stat races */ @@ -940,7 +940,7 @@ void dispatch_stream_id(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id) { } } - config_set_status(pwsc,pqi->session_id,NULL); + config_set_status(pwsc,session,NULL); r_close(file_fd); db_dispose_item(pmp3); } @@ -950,7 +950,7 @@ void dispatch_stream_id(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id) { } void dispatch_stream(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { - dispatch_stream_id(pwsc, pqi, pqi->uri_sections[3]); + dispatch_stream_id(pwsc, pqi->session_id, pqi->uri_sections[3]); } /** diff --git a/src/dispatch.h b/src/dispatch.h index 17f74c49..191d67e0 100644 --- a/src/dispatch.h +++ b/src/dispatch.h @@ -9,6 +9,6 @@ extern void daap_handler(WS_CONNINFO *pwsc); extern int daap_auth(WS_CONNINFO *pwsc, char *username, char *password); -extern void dispatch_stream_id(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id); +extern void dispatch_stream_id(WS_CONNINFO *pwsc, int session, char *id); #endif diff --git a/src/plugin.c b/src/plugin.c index 8fbb7406..dec725cc 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -43,6 +43,7 @@ #include "smart-parser.h" #include "xml-rpc.h" #include "webserver.h" +#include "ff-plugins.h" typedef struct tag_pluginentry { void *phandle; @@ -87,12 +88,13 @@ void pi_log(int, char *, ...); /* db helpers */ int pi_db_count(void); -int pi_db_enum_start(char **pe, DBQUERYINFO *pinfo); -int pi_db_enum_fetch_row(char **pe, char ***row, DBQUERYINFO *pinfo); +int pi_db_enum_start(char **pe, DB_QUERY *pinfo); +int pi_db_enum_fetch_row(char **pe, char ***row, DB_QUERY *pinfo); int pi_db_enum_end(char **pe); -void pi_stream(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id); +void pi_db_enum_dispose(char **pe, DB_QUERY *pinfo); +void pi_stream(WS_CONNINFO *pwsc, char *id); + void pi_conf_dispose_string(char *str); -int pi_sp_parse(PARSETREE tree, char *term); PLUGIN_INPUT_FN pi = { pi_ws_uri, @@ -114,13 +116,9 @@ PLUGIN_INPUT_FN pi = { pi_db_enum_start, pi_db_enum_fetch_row, pi_db_enum_end, + pi_db_enum_dispose, pi_stream, - sp_init, - pi_sp_parse, - sp_dispose, - sp_get_error, - conf_alloc_string, pi_conf_dispose_string }; @@ -577,25 +575,99 @@ int pi_db_count(void) { return count; } -int pi_db_enum_start(char **pe, DBQUERYINFO *pinfo) { - return db_enum_start(pe, pinfo); +int pi_db_enum_start(char **pe, DB_QUERY *pinfo) { + DBQUERYINFO *pqi; + int result; + + pqi = (DBQUERYINFO*)malloc(sizeof(DBQUERYINFO)); + if(!pqi) { + if(pe) *pe = strdup("Malloc error"); + return DB_E_MALLOC; + } + memset(pqi,0,sizeof(DBQUERYINFO)); + pinfo->private = (void*)pqi; + + if(pinfo->filter) { + pqi->pt = sp_init(); + if(!sp_parse(pqi->pt,pinfo->filter,pinfo->filter_type)) { + DPRINTF(E_LOG,L_PLUG,"Ignoring bad query (%s): %s\n", + pinfo->filter,sp_get_error(pqi->pt)); + sp_dispose(pqi->pt); + pqi->pt = NULL; + } + } + + if((pinfo->limit) || (pinfo->offset)) { + pqi->index_low = pinfo->offset; + pqi->index_high = pinfo->offset + pinfo->limit - 1; + if(pqi->index_high < pqi->index_low) + pqi->index_high = 9999999; + + pqi->index_type = indexTypeSub; + } else { + pqi->index_type = indexTypeNone; + } + + pqi->want_count = 1; + + switch(pinfo->query_type) { + case QUERY_TYPE_PLAYLISTS: + pqi->query_type = queryTypePlaylists; + break; + case QUERY_TYPE_DISTINCT: + if((strcmp(pinfo->distinct_field,"artist") == 0)) { + pqi->query_type = queryTypeBrowseArtists; + } else if((strcmp(pinfo->distinct_field,"genre") == 0)) { + pqi->query_type = queryTypeBrowseGenres; + } else if((strcmp(pinfo->distinct_field,"album") == 0)) { + pqi->query_type = queryTypeBrowseAlbums; + } else if((strcmp(pinfo->distinct_field,"composer") == 0)) { + pqi->query_type = queryTypeBrowseComposers; + } else { + if(pe) *pe = strdup("Unsupported browse type"); + sp_dispose(pqi->pt); + pqi->pt = NULL; + return -1; /* not really a db error for this */ + } + break; + case QUERY_TYPE_ITEMS: + default: + pqi->query_type = queryTypePlaylistItems; + break; + } + + pqi->playlist_id = pinfo->playlist_id; + result = db_enum_start(pe, pqi); + pinfo->totalcount = pqi->specifiedtotalcount; } -int pi_db_enum_fetch_row(char **pe, char ***row, DBQUERYINFO *pinfo) { - return db_enum_fetch_row(pe, (PACKED_MP3FILE*)row, pinfo); +int pi_db_enum_fetch_row(char **pe, char ***row, DB_QUERY *pinfo) { + return db_enum_fetch_row(pe, (PACKED_MP3FILE*)row, + (DBQUERYINFO*)pinfo->private); } int pi_db_enum_end(char **pe) { return db_enum_end(pe); } -void pi_stream(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, char *id) { - dispatch_stream_id(pwsc, pqi,id); +void pi_stream(WS_CONNINFO *pwsc, char *id) { + dispatch_stream_id(pwsc, 0, id); return; } -int pi_sp_parse(PARSETREE tree, char *term) { - return sp_parse(tree, term, 0); +void pi_db_enum_dispose(char **pe, DB_QUERY *pinfo) { + DBQUERYINFO *pqi; + + if(!pinfo) + return; + + if(pinfo->private) { + pqi = (DBQUERYINFO *)pinfo->private; + if(pqi->pt) { + sp_dispose(pqi->pt); + pqi->pt = NULL; + } + } } void pi_conf_dispose_string(char *str) { diff --git a/src/plugin.h b/src/plugin.h index d2d95234..e5206250 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -37,87 +37,10 @@ extern int plugin_auth_handle(WS_CONNINFO *pwsc, char *username, char *pw); extern int plugin_rend_register(char *name, int port, char *iface, char *txt); extern void plugin_event_dispatch(int event_id, int intval, void *vp, int len); - - #define PLUGIN_E_SUCCESS 0 #define PLUGIN_E_NOLOAD 1 #define PLUGIN_E_BADFUNCS 2 -#define PLUGIN_OUTPUT 1 -#define PLUGIN_SCANNER 2 -#define PLUGIN_DATABASE 4 -#define PLUGIN_EVENT 8 - -#define PLUGIN_EVENT_LOG 0 -#define PLUGIN_EVENT_FULLSCAN_START 1 -#define PLUGIN_EVENT_FULLSCAN_END 2 -#define PLUGIN_EVENT_STARTING 3 -#define PLUGIN_EVENT_SHUTDOWN 4 -#define PLUGIN_EVENT_STARTSTREAM 5 -#define PLUGIN_EVENT_ABORTSTREAM 6 -#define PLUGIN_EVENT_ENDSTREAM 7 - -#define PLUGIN_VERSION 1 - - -typedef struct tag_plugin_output_fn { - void(*handler)(WS_CONNINFO *pwsc); - int(*auth)(WS_CONNINFO *pwsc, char *username, char *pw); -} PLUGIN_OUTPUT_FN; - -typedef struct tag_plugin_event_fn { - void(*handler)(int event_id, int intval, void *vp, int len); -} PLUGIN_EVENT_FN; - -/* version 1 plugin info */ -typedef struct tag_plugin_rend_info { - char *type; - char *txt; -} PLUGIN_REND_INFO; - -typedef struct tag_plugin_info { - int version; - int type; - char *server; - char *url; /* for output plugins */ - PLUGIN_OUTPUT_FN *output_fns; - PLUGIN_EVENT_FN *event_fns; - void *pi; /* exported functions */ - PLUGIN_REND_INFO *rend_info; -} PLUGIN_INFO; - -/* version 1 plugin imports */ -typedef struct tag_plugin_input_fn { - /* webserver helpers */ - char* (*ws_uri)(WS_CONNINFO *); - void (*ws_close)(WS_CONNINFO *); - int (*ws_returnerror)(WS_CONNINFO *, int, char *); - char* (*ws_getvar)(WS_CONNINFO *, char *); - int (*ws_writefd)(WS_CONNINFO *, char *, ...); - int (*ws_addresponseheader)(WS_CONNINFO *, char *, char *, ...); - void (*ws_emitheaders)(WS_CONNINFO *); - int (*ws_fd)(WS_CONNINFO *); - char* (*ws_getrequestheader)(WS_CONNINFO *, char *); - int (*ws_writebinary)(WS_CONNINFO *, char *, int); - - /* misc helpers */ - char* (*server_ver)(void); - int (*server_name)(char *, int *); - void (*log)(int, char *, ...); - - int (*db_count)(void); - int (*db_enum_start)(char **, DBQUERYINFO *); - int (*db_enum_fetch_row)(char **, char ***, DBQUERYINFO *); - int (*db_enum_end)(char **); - void (*stream)(WS_CONNINFO *, DBQUERYINFO *, char *); - - PARSETREE (*sp_init)(void); - int (*sp_parse)(PARSETREE tree, char *term); - int (*sp_dispose)(PARSETREE tree); - char* (*sp_get_error)(PARSETREE tree); - - char *(*conf_alloc_string)(char *section, char *key, char *dflt); - void (*conf_dispose_string)(char *str); -} PLUGIN_INPUT_FN; +#include "ff-plugins.h" #endif /* _PLUGIN_H_ */ diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index f3143b75..283acc19 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -6,4 +6,7 @@ rsp_LTLIBRARIES=rsp.la rsp_la_LDFLAGS=-module -avoid-version rsp_la_SOURCES = compat.c rsp.c xml-rpc.c -EXTRA_DIST = compat.h rsp.h mtd-plugins.h xml-rpc.h \ No newline at end of file +EXTRA_DIST = compat.h rsp.h mtd-plugins.h xml-rpc.h + +AM_CFLAGS = -I.. + diff --git a/src/plugins/mtd-plugins.h b/src/plugins/mtd-plugins.h deleted file mode 100644 index 8d344763..00000000 --- a/src/plugins/mtd-plugins.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * $Id: $ - */ - -#ifndef _MTD_PLUGINS_H_ -#define _MTD_PLUGINS_H_ - -#define PLUGIN_OUTPUT 1 -#define PLUGIN_SCANNER 2 -#define PLUGIN_DATABASE 4 -#define PLUGIN_EVENT 8 - -#define PLUGIN_VERSION 1 - -#define PLUGIN_EVENT_LOG 0 -#define PLUGIN_EVENT_FULLSCAN_START 1 -#define PLUGIN_EVENT_FULLSCAN_END 2 -#define PLUGIN_EVENT_STARTING 3 -#define PLUGIN_EVENT_SHUTDOWN 4 -#define PLUGIN_EVENT_STARTSTREAM 5 -#define PLUGIN_EVENT_ABORTSTREAM 6 -#define PLUGIN_EVENT_ENDSTREAM 7 - -typedef void* PARSETREE; - -struct tag_ws_conninfo; -typedef struct tag_ws_conninfo WS_CONNINFO; - -typedef struct tag_plugin_output_fn { - void(*handler)(WS_CONNINFO *pwsc); - int(*auth)(WS_CONNINFO *pwsc, char *username, char *pw); -} PLUGIN_OUTPUT_FN; - -typedef struct tag_plugin_event_fn { - void(*handler)(int event_id, int intval, void *vp, int len); -} PLUGIN_EVENT_FN; - -typedef struct tag_plugin_rend_info { - char *type; - char *txt; -} PLUGIN_REND_INFO; - -typedef struct tag_plugin_info { - int version; - int type; - char *server; - char *url; /* regex of namespace to handle if OUTPUT type */ - PLUGIN_OUTPUT_FN *output_fns; - PLUGIN_EVENT_FN *event_fns; - void *pi; /* exported functions */ - PLUGIN_REND_INFO *rend_info; -} PLUGIN_INFO; - -/* xml helpers for output plugins */ - -/* logging */ -#define E_FATAL 0 -#define E_LOG 1 -#define E_INF 5 -#define E_DBG 9 - -/* db stuff */ -typedef enum { - queryTypeItems, - queryTypePlaylists, - queryTypePlaylistItems, - queryTypeBrowseArtists, - queryTypeBrowseAlbums, - queryTypeBrowseGenres, - queryTypeBrowseComposers -} QueryType_t; - -typedef enum { - indexTypeNone, - indexTypeFirst, - indexTypeLast, - indexTypeSub -} IndexType_t; - -typedef enum { - // generic meta data - metaItemId, - metaItemName, - metaItemKind, - metaPersistentId, - metaContainerItemId, - metaParentContainerId, - - firstTypeSpecificMetaId, - - // song meta data - metaSongAlbum = firstTypeSpecificMetaId, - metaSongArtist, - metaSongBPM, - metaSongBitRate, - metaSongComment, - metaSongCompilation, - metaSongComposer, - metaSongDataKind, - metaSongDataURL, - metaSongDateAdded, - metaSongDateModified, - metaSongDescription, - metaSongDisabled, - metaSongDiscCount, - metaSongDiscNumber, - metaSongEqPreset, - metaSongFormat, - metaSongGenre, - metaSongGrouping, - metaSongRelativeVolume, - metaSongSampleRate, - metaSongSize, - metaSongStartTime, - metaSongStopTime, - metaSongTime, - metaSongTrackCount, - metaSongTrackNumber, - metaSongUserRating, - metaSongYear, - - /* iTunes 4.5 + */ - metaSongCodecType, - metaSongCodecSubType, - metaItunesNormVolume, - metaItmsSongId, - metaItmsArtistId, - metaItmsPlaylistId, - metaItmsComposerId, - metaItmsGenreId, - metaItmsStorefrontId, - metaItunesSmartPlaylist, - - /* iTunes 5.0 + */ - metaSongContentRating, - metaHasChildContainers, - - /* iTunes 6.0.2+ */ - metaItunesHasVideo, - - /* mt-daapd specific */ - metaMPlaylistSpec, - metaMPlaylistType -} MetaFieldName_t; - -typedef unsigned long long MetaField_t; - -typedef struct tag_dbqueryinfo { - QueryType_t query_type; - IndexType_t index_type; - MetaField_t meta; - int zero_length; /* emit zero-length strings? */ - int index_low; - int index_high; - int playlist_id; - int db_id; - int session_id; - int want_count; - int specifiedtotalcount; - int uri_count; - char *uri_sections[10]; - PARSETREE pt; - void *output_info; -} DBQUERYINFO; - -typedef struct tag_plugin_input_fn { - /* webserver helpers */ - char* (*ws_uri)(WS_CONNINFO *); - void (*ws_close)(WS_CONNINFO *); - int (*ws_returnerror)(WS_CONNINFO *, int, char *); - char* (*ws_getvar)(WS_CONNINFO *, char *); - int (*ws_writefd)(WS_CONNINFO *, char *, ...); - int (*ws_addresponseheader)(WS_CONNINFO *, char *, char *, ...); - void (*ws_emitheaders)(WS_CONNINFO *); - int (*ws_fd)(WS_CONNINFO *); - char* (*ws_getrequestheader)(WS_CONNINFO *, char *); - int (*ws_writebinary)(WS_CONNINFO *, char *, int); - - /* misc helpers */ - char* (*server_ver)(void); - int (*server_name)(char *, int *); - void (*log)(int, char *, ...); - - int (*db_count)(void); - int (*db_enum_start)(char **, DBQUERYINFO *); - int (*db_enum_fetch_row)(char **, char ***, DBQUERYINFO *); - int (*db_enum_end)(char **); - void (*stream)(WS_CONNINFO *, DBQUERYINFO *, char *); - - PARSETREE (*sp_init)(void); - int (*sp_parse)(PARSETREE tree, char *term); - int (*sp_dispose)(PARSETREE tree); - char* (*sp_get_error)(PARSETREE tree); - - char *(*conf_alloc_string)(char *, char *, char *); - void (*conf_dispose_string)(char *); -} PLUGIN_INPUT_FN; - - -/* these are the functions that must be exported by the plugin */ -PLUGIN_INFO *plugin_info(void); - - -#endif /* _MTD_PLUGINS_H_ */ diff --git a/src/plugins/rsp.c b/src/plugins/rsp.c index 7e893760..5098ee6a 100644 --- a/src/plugins/rsp.c +++ b/src/plugins/rsp.c @@ -11,20 +11,26 @@ #include #include "compat.h" -#include "mtd-plugins.h" +#include "ff-plugins.h" #include "rsp.h" #include "xml-rpc.h" +typedef struct tag_rsp_privinfo { + DB_QUERY dq; + int uri_count; + char *uri_sections[10]; +} PRIVINFO; + /* Forwards */ PLUGIN_INFO *plugin_info(void); void plugin_handler(WS_CONNINFO *pwsc); int plugin_auth(WS_CONNINFO *pwsc, char *username, char *pw); -void rsp_info(WS_CONNINFO *pwsc, DBQUERYINFO *pqi); -void rsp_db(WS_CONNINFO *pwsc, DBQUERYINFO *pqi); -void rsp_playlist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi); -void rsp_browse(WS_CONNINFO *pwsc, DBQUERYINFO *pqi); -void rsp_stream(WS_CONNINFO *pwsc, DBQUERYINFO *pqi); -void rsp_error(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, int eno, char *estr); +void rsp_info(WS_CONNINFO *pwsc, PRIVINFO *ppi); +void rsp_db(WS_CONNINFO *pwsc, PRIVINFO *ppi); +void rsp_playlist(WS_CONNINFO *pwsc, PRIVINFO *ppi); +void rsp_browse(WS_CONNINFO *pwsc, PRIVINFO *ppi); +void rsp_stream(WS_CONNINFO *pwsc, PRIVINFO *ppi); +void rsp_error(WS_CONNINFO *pwsc, PRIVINFO *ppi, int eno, char *estr); /* Globals */ PLUGIN_OUTPUT_FN _pofn = { plugin_handler, plugin_auth }; @@ -34,19 +40,21 @@ PLUGIN_REND_INFO _pri[] = { }; PLUGIN_INFO _pi = { - PLUGIN_VERSION, - PLUGIN_OUTPUT, - "rsp/" RSP_VERSION, - "/rsp/.*", - &_pofn, - NULL, - NULL, - _pri + PLUGIN_VERSION, /* version */ + PLUGIN_OUTPUT, /* type */ + "rsp/" RSP_VERSION, /* server */ + "/rsp/.*", /* url */ + &_pofn, /* output fns */ + NULL, /* event fns */ + NULL, /* transcode fns */ + NULL, /* ff functions */ + _pri, /* rend info */ + NULL /* transcode info */ }; typedef struct tag_response { char *uri[10]; - void (*dispatch)(WS_CONNINFO *, DBQUERYINFO *); + void (*dispatch)(WS_CONNINFO *, PRIVINFO *); } PLUGIN_RESPONSE; @@ -155,26 +163,30 @@ int plugin_auth(WS_CONNINFO *pwsc, char *username, char *pw) { */ void plugin_handler(WS_CONNINFO *pwsc) { char *string, *save, *token; - DBQUERYINFO *pqi; + PRIVINFO *ppi; int elements; int index, part; int found; - string = infn->ws_uri(pwsc); string++; + + ppi = (PRIVINFO *)malloc(sizeof(PRIVINFO)); + if(ppi) { + memset(ppi,0,sizeof(PRIVINFO)); + } - pqi = (DBQUERYINFO *)malloc(sizeof(DBQUERYINFO)); - if(!pqi) { + if(!ppi) { infn->ws_returnerror(pwsc,500,"Malloc error in plugin_handler"); return; } - memset(pqi,0,sizeof(DBQUERYINFO)); + + memset((void*)&ppi->dq,0,sizeof(DB_QUERY)); infn->log(E_DBG,"Tokenizing url\n"); - while((pqi->uri_count < 10) && (token=strtok_r(string,"/",&save))) { + while((ppi->uri_count < 10) && (token=strtok_r(string,"/",&save))) { string=NULL; - pqi->uri_sections[pqi->uri_count++] = token; + ppi->uri_sections[ppi->uri_count++] = token; } elements = sizeof(rsp_uri_map) / sizeof(PLUGIN_RESPONSE); @@ -188,15 +200,15 @@ void plugin_handler(WS_CONNINFO *pwsc) { infn->log(E_DBG,"Checking reponse %d\n",index); part=0; while(part < 10) { - if((rsp_uri_map[index].uri[part]) && (!pqi->uri_sections[part])) + if((rsp_uri_map[index].uri[part]) && (!ppi->uri_sections[part])) break; - if((pqi->uri_sections[part]) && (!rsp_uri_map[index].uri[part])) + if((ppi->uri_sections[part]) && (!rsp_uri_map[index].uri[part])) break; if((rsp_uri_map[index].uri[part]) && (strcmp(rsp_uri_map[index].uri[part],"*") != 0)) { if(strcmp(rsp_uri_map[index].uri[part], - pqi->uri_sections[part])!= 0) + ppi->uri_sections[part])!= 0) break; } part++; @@ -211,20 +223,22 @@ void plugin_handler(WS_CONNINFO *pwsc) { } if(found) { - rsp_uri_map[index].dispatch(pwsc, pqi); + rsp_uri_map[index].dispatch(pwsc, ppi); infn->ws_close(pwsc); + free(ppi); return; } - rsp_error(pwsc, pqi, 1, "Bad path"); + rsp_error(pwsc, ppi, 1, "Bad path"); infn->ws_close(pwsc); + free(ppi); return; } /** * get server info */ -void rsp_info(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { +void rsp_info(WS_CONNINFO *pwsc, PRIVINFO *ppi) { XMLSTRUCT *pxml; char servername[256]; int size; @@ -262,17 +276,18 @@ void rsp_info(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { * * dump details about all playlists */ -void rsp_db(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { +void rsp_db(WS_CONNINFO *pwsc, PRIVINFO *ppi) { XMLSTRUCT *pxml; char *pe; int err; char **row; int rowindex; - pqi->want_count = 1; - pqi->query_type = queryTypePlaylists; - if((err=infn->db_enum_start(&pe,pqi)) != 0) { - rsp_error(pwsc, pqi, err | E_DB, pe); + ppi->dq.query_type = QUERY_TYPE_PLAYLISTS; + + if((err=infn->db_enum_start(&pe,&ppi->dq)) != 0) { + rsp_error(pwsc, ppi, err | E_DB, pe); + infn->db_enum_dispose(NULL,&ppi->dq); return; } @@ -282,13 +297,13 @@ void rsp_db(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { xml_push(pxml,"status"); xml_output(pxml,"errorcode","0"); xml_output(pxml,"errorstring",""); - xml_output(pxml,"records","%d",pqi->specifiedtotalcount); - xml_output(pxml,"totalrecords","%d",pqi->specifiedtotalcount); + xml_output(pxml,"records","%d",ppi->dq.totalcount); + xml_output(pxml,"totalrecords","%d",ppi->dq.totalcount); xml_pop(pxml); /* status */ xml_push(pxml,"playlists"); - while((infn->db_enum_fetch_row(NULL,&row,pqi) == 0) && (row)) { + while((infn->db_enum_fetch_row(NULL,&row,&ppi->dq) == 0) && (row)) { xml_push(pxml,"playlist"); rowindex=0; while(rsp_playlist_fields[rowindex].name) { @@ -302,6 +317,7 @@ void rsp_db(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { } infn->db_enum_end(NULL); + infn->db_enum_dispose(NULL,&ppi->dq); xml_pop(pxml); /* playlists */ xml_pop(pxml); /* response */ @@ -312,7 +328,7 @@ void rsp_db(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { /** * get all items under the playlist */ -void rsp_playlist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { +void rsp_playlist(WS_CONNINFO *pwsc, PRIVINFO *ppi) { XMLSTRUCT *pxml; char *pe; int err; @@ -321,8 +337,6 @@ void rsp_playlist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { int returned; char *browse_type; int type; - char *query; - char *estr = NULL; char *transcode_codecs; int transcode; int samplerate; @@ -341,30 +355,15 @@ void rsp_playlist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { } */ - query = infn->ws_getvar(pwsc,"query"); - if(query) { - pqi->pt = infn->sp_init(); - if(!infn->sp_parse(pqi->pt,query)) { - estr = strdup(infn->sp_get_error(pqi->pt)); - infn->log(E_LOG,"Ignoring bad query (%s): %s\n",query,estr); - infn->sp_dispose(pqi->pt); - pqi->pt = NULL; - } - } + ppi->dq.filter = infn->ws_getvar(pwsc,"query"); + ppi->dq.filter_type = FILTER_TYPE_FIREFLY; - pqi->index_type = indexTypeNone; if(infn->ws_getvar(pwsc,"offset")) { - pqi->index_low = atoi(infn->ws_getvar(pwsc,"offset")); + ppi->dq.offset = atoi(infn->ws_getvar(pwsc,"offset")); } if(infn->ws_getvar(pwsc,"limit")) { - pqi->index_high = pqi->index_low + atoi(infn->ws_getvar(pwsc,"limit")) -1; - if(pqi->index_high < pqi->index_low) { - pqi->index_high = 999999; - } - } else { - pqi->index_high = 999999; /* FIXME */ + ppi->dq.limit = atoi(infn->ws_getvar(pwsc,"limit")); } - pqi->index_type = indexTypeSub; browse_type = infn->ws_getvar(pwsc,"type"); type = F_FULL; @@ -376,26 +375,24 @@ void rsp_playlist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { type = F_ID; } } + ppi->dq.query_type = QUERY_TYPE_ITEMS; + ppi->dq.playlist_id = atoi(ppi->uri_sections[2]); - pqi->want_count = 1; - pqi->query_type = queryTypePlaylistItems; - pqi->playlist_id = atoi(pqi->uri_sections[2]); - - if((err=infn->db_enum_start(&pe,pqi)) != 0) { - if(pqi->pt) infn->sp_dispose(pqi->pt); - if(estr) free(estr); - rsp_error(pwsc, pqi, err | E_DB, pe); + if((err=infn->db_enum_start(&pe,&ppi->dq)) != 0) { + rsp_error(pwsc, ppi, err | E_DB, pe); + infn->db_enum_dispose(NULL,&ppi->dq); + free(pe); return; } pxml = xml_init(pwsc,1); - if(pqi->index_low > pqi->specifiedtotalcount) { + if(ppi->dq.offset > ppi->dq.totalcount) { returned = 0; } else { - returned = pqi->index_high - pqi->index_low + 1; - if(returned > (pqi->specifiedtotalcount - pqi->index_low)) - returned = pqi->specifiedtotalcount - pqi->index_low; + returned = ppi->dq.limit; + if(returned > (ppi->dq.totalcount - ppi->dq.offset)) + returned = ppi->dq.totalcount - ppi->dq.offset; } transcode_codecs = infn->conf_alloc_string("general","ssc_codectypes",""); @@ -403,14 +400,14 @@ void rsp_playlist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { xml_push(pxml,"response"); xml_push(pxml,"status"); xml_output(pxml,"errorcode","0"); - xml_output(pxml,"errorstring",estr ? estr : ""); + xml_output(pxml,"errorstring",""); xml_output(pxml,"records","%d",returned); - xml_output(pxml,"totalrecords","%d",pqi->specifiedtotalcount); + xml_output(pxml,"totalrecords","%d",ppi->dq.totalcount); xml_pop(pxml); /* status */ xml_push(pxml,"items"); - while((infn->db_enum_fetch_row(NULL,&row,pqi) == 0) && (row)) { + while((infn->db_enum_fetch_row(NULL,&row,&ppi->dq) == 0) && (row)) { xml_push(pxml,"item"); rowindex=0; transcode = 0; @@ -462,108 +459,75 @@ void rsp_playlist(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { xml_pop(pxml); /* items */ xml_pop(pxml); /* response */ xml_deinit(pxml); - - if(pqi->pt) infn->sp_dispose(pqi->pt); - if(estr) free(estr); } -void rsp_browse(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { +void rsp_browse(WS_CONNINFO *pwsc, PRIVINFO *ppi) { XMLSTRUCT *pxml; char *pe; int err; char **row; int returned; - char *query; - char *estr = NULL; - /* FIXME */ - if(!strcmp(pqi->uri_sections[3],"artist")) { - pqi->query_type = queryTypeBrowseArtists; - } else if(!strcmp(pqi->uri_sections[3],"genre")) { - pqi->query_type = queryTypeBrowseGenres; - } else if(!strcmp(pqi->uri_sections[3],"album")) { - pqi->query_type = queryTypeBrowseAlbums; - } else if(!strcmp(pqi->uri_sections[3],"composer")) { - pqi->query_type = queryTypeBrowseComposers; - } else { - rsp_error(pwsc, pqi, 0 | E_RSP, "Unsupported browse type"); - return; + /* this might fail if an unsupported browse type */ + ppi->dq.query_type = QUERY_TYPE_DISTINCT; + ppi->dq.distinct_field = ppi->uri_sections[3]; + ppi->dq.filter = infn->ws_getvar(pwsc,"query"); + ppi->dq.filter_type = FILTER_TYPE_FIREFLY; + + if(infn->ws_getvar(pwsc,"offset")) { + ppi->dq.offset = atoi(infn->ws_getvar(pwsc,"offset")); } - query = infn->ws_getvar(pwsc,"query"); - if(query) { - pqi->pt = infn->sp_init(); - if(!infn->sp_parse(pqi->pt,query)) { - estr = strdup(infn->sp_get_error(pqi->pt)); - infn->log(E_LOG,"Ignoring bad query (%s): %s\n",query,estr); - infn->sp_dispose(pqi->pt); - pqi->pt = NULL; - } - } - - pqi->index_type = indexTypeNone; - if(infn->ws_getvar(pwsc,"offset")) { - pqi->index_low = atoi(infn->ws_getvar(pwsc,"offset")); - } if(infn->ws_getvar(pwsc,"limit")) { - pqi->index_high = pqi->index_low + atoi(infn->ws_getvar(pwsc,"limit")) -1; - if(pqi->index_high < pqi->index_low) { - pqi->index_high = 999999; - } - } else { - pqi->index_high = 999999; /* FIXME */ + ppi->dq.limit = atoi(infn->ws_getvar(pwsc,"limit")); } - pqi->index_type = indexTypeSub; - pqi->want_count = 1; - pqi->playlist_id = atoi(pqi->uri_sections[2]); - if((err=infn->db_enum_start(&pe,pqi)) != 0) { - if(pqi->pt) infn->sp_dispose(pqi->pt); - if(estr) free(estr); - rsp_error(pwsc, pqi, err | E_DB, pe); + ppi->dq.playlist_id = atoi(ppi->uri_sections[2]); + + if((err=infn->db_enum_start(&pe,&ppi->dq)) != 0) { + rsp_error(pwsc, ppi, err | E_DB, pe); + infn->db_enum_dispose(NULL,&ppi->dq); return; } pxml = xml_init(pwsc,1); - if(pqi->index_low > pqi->specifiedtotalcount) { + if(ppi->dq.offset > ppi->dq.totalcount) { returned = 0; } else { - returned = pqi->index_high - pqi->index_low + 1; - if(returned > (pqi->specifiedtotalcount - pqi->index_low)) - returned = pqi->specifiedtotalcount - pqi->index_low; + returned = ppi->dq.limit; + if(returned > (ppi->dq.totalcount - ppi->dq.offset)) + returned = ppi->dq.totalcount - ppi->dq.offset; } xml_push(pxml,"response"); xml_push(pxml,"status"); xml_output(pxml,"errorcode","0"); - xml_output(pxml,"errorstring",estr ? estr : ""); + xml_output(pxml,"errorstring",""); xml_output(pxml,"records","%d",returned); - xml_output(pxml,"totalrecords","%d",pqi->specifiedtotalcount); + xml_output(pxml,"totalrecords","%d",ppi->dq.totalcount); xml_pop(pxml); /* status */ xml_push(pxml,"items"); - while((infn->db_enum_fetch_row(NULL,&row,pqi) == 0) && (row)) { + while((infn->db_enum_fetch_row(NULL,&row,&ppi->dq) == 0) && (row)) { xml_output(pxml,"item",row[0]); } infn->db_enum_end(NULL); + infn->db_enum_dispose(NULL,&ppi->dq); xml_pop(pxml); /* items */ xml_pop(pxml); /* response */ xml_deinit(pxml); - - if(pqi->pt) infn->sp_dispose(pqi->pt); - if(estr) free(estr); } -void rsp_stream(WS_CONNINFO *pwsc, DBQUERYINFO *pqi) { - infn->stream(pwsc, pqi, pqi->uri_sections[2]); +void rsp_stream(WS_CONNINFO *pwsc, PRIVINFO *ppi) { + infn->stream(pwsc, ppi->uri_sections[2]); return; } -void rsp_error(WS_CONNINFO *pwsc, DBQUERYINFO *pqi, int eno, char *estr) { +void rsp_error(WS_CONNINFO *pwsc, PRIVINFO *ppi, int eno, char *estr) { XMLSTRUCT *pxml; pxml = xml_init(pwsc, 1); diff --git a/src/plugins/xml-rpc.c b/src/plugins/xml-rpc.c index ec851896..b5f3de1a 100644 --- a/src/plugins/xml-rpc.c +++ b/src/plugins/xml-rpc.c @@ -16,10 +16,11 @@ #include #include "compat.h" -#include "mtd-plugins.h" +#include "ff-plugins.h" #include "rsp.h" #include "xml-rpc.h" + /* typedefs */ typedef struct tag_xmlstack { char *tag; @@ -135,7 +136,8 @@ int xml_stream_write(XMLSTRUCT *pxml, char *out) { if(result != Z_OK) { infn->log(E_FATAL,"Error in zlib: %d\n",result); } - infn->ws_writebinary(pxml->pwsc,psb->out_buffer,XML_STREAM_BLOCK-psb->strm.avail_out); + infn->ws_writebinary(pxml->pwsc,(char*)psb->out_buffer, + XML_STREAM_BLOCK-psb->strm.avail_out); if(psb->strm.avail_out != 0) { done=1; } else { @@ -161,7 +163,8 @@ int xml_stream_close(XMLSTRUCT *pxml) { psb->strm.next_in = psb->in_buffer; deflate(&psb->strm,Z_FINISH); - infn->ws_writebinary(pxml->pwsc,psb->out_buffer,XML_STREAM_BLOCK - psb->strm.avail_out); + infn->ws_writebinary(pxml->pwsc,(char*)psb->out_buffer, + XML_STREAM_BLOCK - psb->strm.avail_out); if(psb->strm.avail_out != 0) done=1; diff --git a/src/plugins/xml-rpc.h b/src/plugins/xml-rpc.h index cc34c31c..e8bc9b57 100644 --- a/src/plugins/xml-rpc.h +++ b/src/plugins/xml-rpc.h @@ -5,10 +5,11 @@ #ifndef _XMLRPC_H_ #define _XMLRPC_H_ -#include "mtd-plugins.h" +#include "ff-plugins.h" struct tag_xmlstruct; typedef struct tag_xmlstruct XMLSTRUCT; +typedef struct tag_ws_conninfo WS_CONNINFO; extern XMLSTRUCT *xml_init(WS_CONNINFO *pwsc, int emit_header); extern void xml_push(XMLSTRUCT *pxml, char *term); diff --git a/src/smart-parser.c b/src/smart-parser.c index 451538d4..6cfffd4c 100644 --- a/src/smart-parser.c +++ b/src/smart-parser.c @@ -717,9 +717,9 @@ int sp_parse(PARSETREE tree, char *term, int type) { tree->tree = sp_parse_phrase(tree); if(tree->tree) { - DPRINTF(E_SPAM,L_PARSE,"Parsed successfully\n"); + DPRINTF(E_SPAM,L_PARSE,"Parsed successfully (type %d)\n",type); } else { - DPRINTF(E_SPAM,L_PARSE,"Parsing error\n"); + DPRINTF(E_SPAM,L_PARSE,"Parsing error (type %d)\n",type); } return tree->tree ? 1 : 0;