mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-26 06:03:20 -05:00
abstract the plugin interface to the db to prepare for db plugins and making daap a plugin
This commit is contained in:
parent
9e547e6c16
commit
b3fbb9bbd5
@ -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 */
|
||||
|
@ -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 {
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
106
src/plugin.c
106
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) {
|
||||
|
79
src/plugin.h
79
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_ */
|
||||
|
@ -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
|
||||
EXTRA_DIST = compat.h rsp.h mtd-plugins.h xml-rpc.h
|
||||
|
||||
AM_CFLAGS = -I..
|
||||
|
||||
|
@ -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_ */
|
@ -11,20 +11,26 @@
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
|
@ -16,10 +16,11 @@
|
||||
#include <zlib.h>
|
||||
|
||||
#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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user