remove function backpointers for dll plugins

This commit is contained in:
Ron Pedde 2007-08-09 06:33:41 +00:00
parent 366ae9913c
commit 0429230d00
15 changed files with 539 additions and 863 deletions

View File

@ -23,6 +23,8 @@ AC_CHECK_HEADERS([dirent.h])
AC_CHECK_FUNCS(strptime) AC_CHECK_FUNCS(strptime)
AC_CHECK_FUNCS(strtok_r) AC_CHECK_FUNCS(strtok_r)
AC_CHECK_FUNCS(timegm) AC_CHECK_FUNCS(timegm)
AC_CHECK_FUNCS(va_copy)
AC_CHECK_FUNCS(__va_copy)
AM_CONDITIONAL(COND_REND_OSX,false) AM_CONDITIONAL(COND_REND_OSX,false)

View File

@ -64,7 +64,7 @@ wavstreamer_SOURCES = wavstreamer.c
mt_daapd_SOURCES = main.c daapd.h rend.h webserver.c \ mt_daapd_SOURCES = main.c daapd.h rend.h webserver.c \
webserver.h configfile.c configfile.h err.c err.h restart.c restart.h \ webserver.h configfile.c configfile.h err.c err.h restart.c restart.h \
mp3-scanner.h mp3-scanner.c rend-unix.h \ mp3-scanner.h mp3-scanner.c rend-unix.h \
db-generic.c db-generic.h \ db-generic.c db-generic.h ff-plugins.c ff-plugins.h \
rxml.c rxml.h redblack.c redblack.h scan-mp3.c scan-mp4.c scan-aif.c \ rxml.c rxml.h redblack.c redblack.h scan-mp3.c scan-mp4.c scan-aif.c \
scan-xml.c scan-wma.c scan-aac.c scan-aac.h scan-wav.c scan-url.c \ scan-xml.c scan-wma.c scan-aac.c scan-aac.h scan-wav.c scan-url.c \
smart-parser.c smart-parser.h xml-rpc.c xml-rpc.h \ smart-parser.c smart-parser.h xml-rpc.c xml-rpc.h \

View File

@ -39,6 +39,20 @@
# include <stdint.h> # include <stdint.h>
#endif #endif
#ifdef DEBUG
# ifndef ASSERT
# define ASSERT(f) \
if(f) \
{} \
else \
err_log(0,"Assert error in %s, line %d\n",__FILE__,__LINE__)
# endif /* ndef ASSERT */
#else /* ndef DEBUG */
# ifndef ASSERT
# define ASSERT(f)
# endif
#endif
#include <time.h> #include <time.h>
#include "memdebug.h" /* redefine free/malloc/etc */ #include "memdebug.h" /* redefine free/malloc/etc */
#include "compat.h" #include "compat.h"

View File

@ -24,6 +24,13 @@
#include "ff-dbstruct.h" #include "ff-dbstruct.h"
#ifdef WIN32
# define EXPORT __declspec(dllimport)
#else
# define EXPORT
#endif
#ifndef TRUE #ifndef TRUE
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0
@ -122,51 +129,49 @@ typedef struct tag_db_query {
void *priv; void *priv;
} DB_QUERY; } DB_QUERY;
/* webserver functions */
extern EXPORT EXPORT char *pi_ws_uri(struct tag_ws_conninfo *);
extern EXPORT EXPORT void pi_ws_will_close(struct tag_ws_conninfo *);
extern EXPORT EXPORT int pi_ws_returnerror(struct tag_ws_conninfo *, int, char *);
extern EXPORT char *pi_ws_getvar(struct tag_ws_conninfo *, char *);
extern EXPORT int pi_ws_writefd(struct tag_ws_conninfo *, char *, ...);
extern EXPORT int pi_ws_addresponseheader(struct tag_ws_conninfo *, char *, char *, ...);
extern EXPORT void pi_ws_emitheaders(struct tag_ws_conninfo *);
extern EXPORT char *pi_ws_getrequestheader(struct tag_ws_conninfo *, char *);
extern EXPORT int pi_ws_writebinary(struct tag_ws_conninfo *, char *, int);
extern EXPORT char *pi_ws_gethostname(struct tag_ws_conninfo *);
extern EXPORT int pi_ws_matchesrole(struct tag_ws_conninfo *, char *, char *, char *);
/* version 1 plugin imports */ /* misc helpers */
typedef struct tag_plugin_input_fn { extern EXPORT char *pi_server_ver(void);
/* webserver helpers */ extern EXPORT int pi_server_name(char *, int *);
char* (*ws_uri)(struct tag_ws_conninfo *); extern EXPORT void pi_log(int, char *, ...);
void (*ws_will_close)(struct tag_ws_conninfo *); extern EXPORT int pi_should_transcode(struct tag_ws_conninfo *, char *);
int (*ws_returnerror)(struct tag_ws_conninfo *, int, char *);
char* (*ws_getvar)(struct tag_ws_conninfo *, char *);
int (*ws_writefd)(struct tag_ws_conninfo *, char *, ...);
int (*ws_addresponseheader)(struct tag_ws_conninfo *, char *, char *, ...);
void (*ws_emitheaders)(struct tag_ws_conninfo *);
char* (*ws_getrequestheader)(struct tag_ws_conninfo *, char *);
int (*ws_writebinary)(struct tag_ws_conninfo *, char *, int);
char* (*ws_gethostname)(struct tag_ws_conninfo *);
int (*ws_matchesrole)(struct tag_ws_conninfo *, char *, char *, char *);
/* misc helpers */ /* db functions */
char* (*server_ver)(void); extern EXPORT int pi_db_count(void);
int (*server_name)(char *, int *); extern EXPORT int pi_db_enum_start(char **, DB_QUERY *);
void (*log)(int, char *, ...); extern EXPORT int pi_db_enum_fetch_row(char **, char ***, DB_QUERY *);
int (*should_transcode)(struct tag_ws_conninfo *, char *); extern EXPORT int pi_db_enum_end(char **);
extern EXPORT int pi_db_enum_restart(char **, DB_QUERY *);
extern EXPORT void pi_db_enum_dispose(char **, DB_QUERY*);
extern EXPORT void pi_stream(struct tag_ws_conninfo *, char *);
int (*db_count)(void); extern EXPORT int pi_db_add_playlist(char **pe, char *name, int type, char *clause, char *path, int index, int *playlistid);
int (*db_enum_start)(char **, DB_QUERY *); extern EXPORT int pi_db_add_playlist_item(char **pe, int playlistid, int songid);
int (*db_enum_fetch_row)(char **, char ***, DB_QUERY *); extern EXPORT int pi_db_edit_playlist(char **pe, int id, char *name, char *clause);
int (*db_enum_end)(char **); extern EXPORT int pi_db_delete_playlist(char **pe, int playlistid);
int (*db_enum_restart)(char **, DB_QUERY *); extern EXPORT int pi_db_delete_playlist_item(char **pe, int playlistid, int songid);
void (*db_enum_dispose)(char **, DB_QUERY*); extern EXPORT int pi_db_revision(void);
void (*stream)(struct tag_ws_conninfo *, char *); extern EXPORT int pi_db_count_items(int what);
extern EXPORT int pi_db_wait_update(struct tag_ws_conninfo *);
int (*db_add_playlist)(char **pe, char *name, int type, char *clause, char *path, int index, int *playlistid); /* config/misc functions */
int (*db_add_playlist_item)(char **pe, int playlistid, int songid); extern EXPORT char *pi_conf_alloc_string(char *section, char *key, char *dflt);
int (*db_edit_playlist)(char **pe, int id, char *name, char *clause); extern EXPORT void pi_conf_dispose_string(char *str);
int (*db_delete_playlist)(char **pe, int playlistid); extern EXPORT int pi_conf_get_int(char *section, char *key, int dflt);
int (*db_delete_playlist_item)(char **pe, int playlistid, int songid);
int (*db_revision)(void);
int (*db_count_items)(int what);
int (*db_wait_update)(struct tag_ws_conninfo *);
char *(*conf_alloc_string)(char *section, char *key, char *dflt); extern EXPORT void pi_config_set_status(struct tag_ws_conninfo *pwsc, int session, char *fmt, ...);
void (*conf_dispose_string)(char *str);
int (*conf_get_int)(char *section, char *key, int dflt);
void (*config_set_status)(struct tag_ws_conninfo *pwsc, int session, char *fmt, ...);
} PLUGIN_INPUT_FN;
#endif /* _FF_PLUGINS_ */ #endif /* _FF_PLUGINS_ */

View File

@ -92,74 +92,6 @@ void _plugin_free(int *pi);
void _plugin_recalc_codecs(void); void _plugin_recalc_codecs(void);
int _plugin_ssc_transcode(WS_CONNINFO *pwsc, MP3FILE *pmp3, int offset, int headers); int _plugin_ssc_transcode(WS_CONNINFO *pwsc, MP3FILE *pmp3, int offset, int headers);
/* webserver helpers */
void pi_ws_will_close(WS_CONNINFO *pwsc);
int pi_ws_fd(WS_CONNINFO *pwsc);
char *pi_ws_gethostname(WS_CONNINFO *pwsc);
/* misc helpers */
char *pi_server_ver(void);
int pi_server_name(char *, int *);
void pi_log(int, char *, ...);
/* db helpers */
int pi_db_count(void);
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);
int pi_db_enum_restart(char **pe, DB_QUERY *pinfo);
void pi_db_enum_dispose(char **pe, DB_QUERY *pinfo);
void pi_stream(WS_CONNINFO *pwsc, char *id);
int pi_db_count_items(int what);
int pi_db_wait_update(WS_CONNINFO *pwsc);
void pi_conf_dispose_string(char *str);
/* transcode helpers */
int pi_ssc_should_transcode(WS_CONNINFO *pwsc, char *codec);
PLUGIN_INPUT_FN pi = {
ws_uri,
pi_ws_will_close,
ws_returnerror,
ws_getvar,
ws_writefd,
ws_addresponseheader,
ws_emitheaders,
ws_getrequestheader,
ws_writebinary,
pi_ws_gethostname,
config_matches_role,
pi_server_ver,
pi_server_name,
pi_log,
pi_ssc_should_transcode,
pi_db_count,
pi_db_enum_start,
pi_db_enum_fetch_row,
pi_db_enum_end,
pi_db_enum_restart,
pi_db_enum_dispose,
pi_stream,
db_add_playlist,
db_add_playlist_item,
db_edit_playlist,
db_delete_playlist,
db_delete_playlist_item,
db_revision,
pi_db_count_items,
pi_db_wait_update,
conf_alloc_string,
pi_conf_dispose_string,
conf_get_int,
config_set_status
};
/** /**
* initialize stuff for plugins * initialize stuff for plugins
* *
@ -294,7 +226,7 @@ void *plugin_enum(void *where) {
int plugin_load(char **pe, char *path) { int plugin_load(char **pe, char *path) {
PLUGIN_ENTRY *ppi; PLUGIN_ENTRY *ppi;
void *phandle; void *phandle;
PLUGIN_INFO *(*info_func)(PLUGIN_INPUT_FN *); PLUGIN_INFO *(*info_func)(void);
PLUGIN_INFO *pinfo; PLUGIN_INFO *pinfo;
DPRINTF(E_DBG,L_PLUG,"Attempting to load plugin %s\n",path); DPRINTF(E_DBG,L_PLUG,"Attempting to load plugin %s\n",path);
@ -310,7 +242,7 @@ int plugin_load(char **pe, char *path) {
ppi->phandle = phandle; ppi->phandle = phandle;
info_func = (PLUGIN_INFO*(*)(PLUGIN_INPUT_FN*)) os_libfunc(pe, phandle,"plugin_info"); info_func = (PLUGIN_INFO*(*)(void)) os_libfunc(pe, phandle,"plugin_info");
if(info_func == NULL) { if(info_func == NULL) {
DPRINTF(E_INF,L_PLUG,"Couldn't get info_func for %s\n",path); DPRINTF(E_INF,L_PLUG,"Couldn't get info_func for %s\n",path);
os_unload(phandle); os_unload(phandle);
@ -318,7 +250,7 @@ int plugin_load(char **pe, char *path) {
return PLUGIN_E_BADFUNCS; return PLUGIN_E_BADFUNCS;
} }
pinfo = info_func(&pi); pinfo = info_func();
ppi->pinfo = pinfo; ppi->pinfo = pinfo;
if(!pinfo) { if(!pinfo) {
@ -486,25 +418,137 @@ void plugin_event_dispatch(int event_id, int intval, void *vp, int len) {
} }
} }
/** /**
* check to see if we can transcode * stupid helper to copy transcode stream to the fd
*
* @param codec the codec we are trying to serve
* @returns TRUE if we can transcode, FALSE otherwise
*/ */
int pi_ssc_should_transcode(WS_CONNINFO *pwsc, char *codec) { int __plugin_ssc_copy(WS_CONNINFO *pwsc, PLUGIN_TRANSCODE_FN *pfn,
void *vp,int offset) {
int bytes_read;
int bytes_to_read;
int total_bytes_read = 0;
char buffer[1024];
/* first, skip past the offset */
while(offset) {
bytes_to_read = sizeof(buffer);
if(bytes_to_read > offset)
bytes_to_read = offset;
bytes_read = pfn->ssc_read(vp,buffer,bytes_to_read);
if(bytes_read <= 0)
return bytes_read;
offset -= bytes_read;
}
while((bytes_read=pfn->ssc_read(vp,buffer,sizeof(buffer))) > 0) {
total_bytes_read += bytes_read;
if(ws_writebinary(pwsc,buffer,bytes_read) != bytes_read) {
return total_bytes_read;
}
}
/*
if(bytes_read < 0) {
return bytes_read;
}
*/
return total_bytes_read;
}
/**
* do the transcode, emitting the headers, content type,
* and shoving the file down the wire
*
* @param pwsc connection to transcode to
* @param file file to transcode
* @param codec source codec
* @param duration time in ms
* @returns bytes transferred, or -1 on error
*/
int plugin_ssc_transcode(WS_CONNINFO *pwsc, MP3FILE *pmp3, int offset, int headers) {
PLUGIN_ENTRY *ppi, *ptc=NULL;
PLUGIN_TRANSCODE_FN *pfn = NULL;
void *vp_ssc;
int post_error = 1;
int result = -1;
/* first, find the plugin that will do the conversion */
ppi = _plugin_list.next;
while((ppi) && (!pfn)) {
if(ppi->pinfo->type & PLUGIN_TRANSCODE) {
if(strstr(ppi->pinfo->codeclist,pmp3->codectype)) {
ptc = ppi;
pfn = ppi->pinfo->transcode_fns;
}
}
ppi = ppi->next;
}
if(pfn) {
DPRINTF(E_DBG,L_PLUG,"Transcoding %s with %s\n",pmp3->path,
ptc->pinfo->server);
vp_ssc = pfn->ssc_init();
if(vp_ssc) {
if(pfn->ssc_open(vp_ssc,pmp3)) {
/* start reading and throwing */
if(headers) {
ws_addresponseheader(pwsc,"Content-Type","audio/wav");
ws_addresponseheader(pwsc,"Connection","Close");
if(!offset) {
ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
} else {
ws_addresponseheader(pwsc,"Content-Range",
"bytes %ld-*/*",
(long)offset);
ws_writefd(pwsc,"HTTP/1.1 206 Partial Content\r\n");
}
ws_emitheaders(pwsc);
}
/* start reading/writing */
result = __plugin_ssc_copy(pwsc,pfn,vp_ssc,offset);
post_error = 0;
pfn->ssc_close(vp_ssc);
} else {
DPRINTF(E_LOG,L_PLUG,"Error opening %s for ssc: %s\n",
pmp3->path,pfn->ssc_error(vp_ssc));
}
pfn->ssc_deinit(vp_ssc);
} else {
DPRINTF(E_LOG,L_PLUG,"Error initializing transcoder: %s\n",
ptc->pinfo->server);
}
}
if(post_error) {
pwsc->error = EPERM; /* ?? */
ws_returnerror(pwsc,500,"Internal error");
}
return result;
}
int plugin_ssc_should_transcode(WS_CONNINFO *pwsc, char *codec) {
int result; int result;
char *native_codecs=NULL; char *native_codecs=NULL;
char *user_agent=NULL; char *user_agent=NULL;
char *never_transcode = NULL; char *never_transcode = NULL;
char *always_transcode = NULL; char *always_transcode = NULL;
ASSERT((pwsc) && (codec));
if(!pwsc)
return FALSE;
if(!codec) { if(!codec) {
DPRINTF(E_LOG,L_PLUG,"testing transcode on null codec?\n"); DPRINTF(E_LOG,L_PLUG,"testing transcode on null codec?\n");
return FALSE; return FALSE;
} }
never_transcode = conf_alloc_string("general","never_transcode",NULL); never_transcode = conf_alloc_string("general","never_transcode",NULL);
if(never_transcode) { if(never_transcode) {
if(strstr(never_transcode,codec)) { if(strstr(never_transcode,codec)) {
@ -558,462 +602,3 @@ int pi_ssc_should_transcode(WS_CONNINFO *pwsc, char *codec) {
return result; return result;
} }
/**
* stupid helper to copy transcode stream to the fd
*/
int _plugin_ssc_copy(WS_CONNINFO *pwsc, PLUGIN_TRANSCODE_FN *pfn,
void *vp,int offset) {
int bytes_read;
int bytes_to_read;
int total_bytes_read = 0;
char buffer[1024];
/* first, skip past the offset */
while(offset) {
bytes_to_read = sizeof(buffer);
if(bytes_to_read > offset)
bytes_to_read = offset;
bytes_read = pfn->ssc_read(vp,buffer,bytes_to_read);
if(bytes_read <= 0)
return bytes_read;
offset -= bytes_read;
}
while((bytes_read=pfn->ssc_read(vp,buffer,sizeof(buffer))) > 0) {
total_bytes_read += bytes_read;
if(ws_writebinary(pwsc,buffer,bytes_read) != bytes_read) {
return total_bytes_read;
}
}
/*
if(bytes_read < 0) {
return bytes_read;
}
*/
return total_bytes_read;
}
/**
* do the transcode, emitting the headers, content type,
* and shoving the file down the wire
*
* @param pwsc connection to transcode to
* @param file file to transcode
* @param codec source codec
* @param duration time in ms
* @returns bytes transferred, or -1 on error
*/
int _plugin_ssc_transcode(WS_CONNINFO *pwsc, MP3FILE *pmp3, int offset, int headers) {
PLUGIN_ENTRY *ppi, *ptc=NULL;
PLUGIN_TRANSCODE_FN *pfn = NULL;
void *vp_ssc;
int post_error = 1;
int result = -1;
/* first, find the plugin that will do the conversion */
ppi = _plugin_list.next;
while((ppi) && (!pfn)) {
if(ppi->pinfo->type & PLUGIN_TRANSCODE) {
if(strstr(ppi->pinfo->codeclist,pmp3->codectype)) {
ptc = ppi;
pfn = ppi->pinfo->transcode_fns;
}
}
ppi = ppi->next;
}
if(pfn) {
DPRINTF(E_DBG,L_PLUG,"Transcoding %s with %s\n",pmp3->path,
ptc->pinfo->server);
vp_ssc = pfn->ssc_init();
if(vp_ssc) {
if(pfn->ssc_open(vp_ssc,pmp3)) {
/* start reading and throwing */
if(headers) {
ws_addresponseheader(pwsc,"Content-Type","audio/wav");
ws_addresponseheader(pwsc,"Connection","Close");
if(!offset) {
ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
} else {
ws_addresponseheader(pwsc,"Content-Range",
"bytes %ld-*/*",
(long)offset);
ws_writefd(pwsc,"HTTP/1.1 206 Partial Content\r\n");
}
ws_emitheaders(pwsc);
}
/* start reading/writing */
result = _plugin_ssc_copy(pwsc,pfn,vp_ssc,offset);
post_error = 0;
pfn->ssc_close(vp_ssc);
} else {
DPRINTF(E_LOG,L_PLUG,"Error opening %s for ssc: %s\n",
pmp3->path,pfn->ssc_error(vp_ssc));
}
pfn->ssc_deinit(vp_ssc);
} else {
DPRINTF(E_LOG,L_PLUG,"Error initializing transcoder: %s\n",
ptc->pinfo->server);
}
}
if(post_error) {
pwsc->error = EPERM; /* ?? */
ws_returnerror(pwsc,500,"Internal error");
}
return result;
}
/* plugin wrappers for utility functions & stuff
*
* these functions need to be wrapped so we can maintain a stable
* interface to older plugins even if we get newer functions or apis
* upstream... it's a binary compatibility layer.
*/
void pi_ws_will_close(WS_CONNINFO *pwsc) {
ws_should_close(pwsc,1);
}
char *pi_ws_gethostname(WS_CONNINFO *pwsc) {
return ws_hostname(pwsc);
}
void pi_log(int level, char *fmt, ...) {
char buf[256];
va_list ap;
va_start(ap,fmt);
vsnprintf(buf,sizeof(buf),fmt,ap);
va_end(ap);
DPRINTF(level,L_PLUG,"%s",buf);
}
char *pi_server_ver(void) {
return VERSION;
}
int pi_server_name(char *name, int *len) {
char *servername;
servername = conf_get_servername();
if((servername) && (strlen(servername) < (size_t)len)) {
strcpy(name,servername);
} else {
if((size_t)len > strlen("Firefly Media Server"))
strcpy(name,"Firefly Media Server");
}
free(servername);
return CONF_E_SUCCESS;
}
int pi_db_count(void) {
int count;
db_get_song_count(NULL, &count);
return count;
}
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->priv = (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");
if(pqi->pt)
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;
pqi->correct_order = conf_get_int("scan","correct_order",1);
break;
}
pqi->playlist_id = pinfo->playlist_id;
result = db_enum_start(pe, pqi);
pinfo->totalcount = pqi->specifiedtotalcount;
return DB_E_SUCCESS;
}
int pi_db_enum_fetch_row(char **pe, char ***row, DB_QUERY *pinfo) {
return db_enum_fetch_row(pe, (PACKED_MP3FILE*)row,
(DBQUERYINFO*)pinfo->priv);
}
int pi_db_enum_end(char **pe) {
return db_enum_end(pe);
}
/* FIXME: error checking */
int pi_db_count_items(int what) {
int count=0;
switch(what) {
case COUNT_SONGS:
db_get_song_count(NULL,&count);
break;
case COUNT_PLAYLISTS:
db_get_playlist_count(NULL,&count);
break;
}
return count;
}
int pi_db_enum_restart(char **pe, DB_QUERY *pinfo) {
DBQUERYINFO *pqi;
pqi = (DBQUERYINFO*)pinfo->priv;
return db_enum_reset(pe,pqi);
}
void pi_db_enum_dispose(char **pe, DB_QUERY *pinfo) {
DBQUERYINFO *pqi;
if(!pinfo)
return;
if(pinfo->priv) {
pqi = (DBQUERYINFO *)pinfo->priv;
if(pqi->pt) {
sp_dispose(pqi->pt);
pqi->pt = NULL;
}
}
}
int pi_db_wait_update(WS_CONNINFO *pwsc) {
int clientver=1;
int lastver=0;
IO_WAITHANDLE hwait;
uint32_t ms;
if(ws_getvar(pwsc,"revision-number")) {
clientver=atoi(ws_getvar(pwsc,"revision-number"));
}
/* wait for db_version to be stable for 30 seconds */
hwait = io_wait_new();
if(!hwait)
DPRINTF(E_FATAL,L_MISC,"Can't get wait handle in db_wait_update\n");
/* FIXME: Move this up into webserver to avoid groping around
* inside reserved data structures */
io_wait_add(hwait,pwsc->hclient,IO_WAIT_ERROR);
while((clientver == db_revision()) ||
(lastver && (db_revision() != lastver))) {
lastver = db_revision();
if(!io_wait(hwait,&ms) && (ms != 0)) {
/* can't be ready for read, must be error */
DPRINTF(E_DBG,L_DAAP,"Update session stopped\n");
io_wait_dispose(hwait);
return FALSE;
}
}
io_wait_dispose(hwait);
return TRUE;
}
void pi_stream(WS_CONNINFO *pwsc, char *id) {
int session = 0;
MP3FILE *pmp3;
IOHANDLE hfile;
uint64_t bytes_copied=0;
uint64_t real_len;
uint64_t file_len;
uint64_t offset=0;
int item;
/* stream out the song */
ws_should_close(pwsc,1);
item = atoi(id);
if(ws_getrequestheader(pwsc,"range")) {
offset=(off_t)atol(ws_getrequestheader(pwsc,"range") + 6);
}
/* FIXME: error handling */
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,session,NULL);
ws_returnerror(pwsc,404,"File Not Found");
} else if (pi_ssc_should_transcode(pwsc,pmp3->codectype)) {
/************************
* Server side conversion
************************/
config_set_status(pwsc,session,
"Transcoding '%s' (id %d)",
pmp3->title,pmp3->id);
DPRINTF(E_WARN,L_WS,
"Session %d: Streaming file '%s' to %s (offset %ld)\n",
session,pmp3->fname, ws_hostname(pwsc),(long)offset);
/* estimate the real length of this thing */
bytes_copied = _plugin_ssc_transcode(pwsc,pmp3,offset,1);
if(bytes_copied != -1)
real_len = bytes_copied;
config_set_status(pwsc,session,NULL);
db_dispose_item(pmp3);
} else {
/**********************
* stream file normally
**********************/
if(pmp3->data_kind != 0) {
ws_returnerror(pwsc,500,"Can't stream radio station");
return;
}
hfile = io_new();
if(!hfile)
DPRINTF(E_FATAL,L_WS,"Cannot allocate file handle\n");
if(!io_open(hfile,"file://%U",pmp3->path)) {
/* FIXME: ws_set_errstr */
ws_set_err(pwsc,E_WS_NATIVE);
DPRINTF(E_WARN,L_WS,"Thread %d: Error opening %s: %s\n",
ws_threadno(pwsc),pmp3->path,io_errstr(hfile));
ws_returnerror(pwsc,404,"Not found");
config_set_status(pwsc,session,NULL);
db_dispose_item(pmp3);
io_dispose(hfile);
} else {
io_size(hfile,&real_len);
file_len = real_len - offset;
DPRINTF(E_DBG,L_WS,"Thread %d: Length of file (remaining): %lld\n",
ws_threadno(pwsc),file_len);
// DWB: fix content-type to correctly reflect data
// content type (dmap tagged) should only be used on
// dmap protocol requests, not the actually song data
if(pmp3->type)
ws_addresponseheader(pwsc,"Content-Type","audio/%s",pmp3->type);
ws_addresponseheader(pwsc,"Content-Length","%ld",(long)file_len);
if((ws_getrequestheader(pwsc,"user-agent")) &&
(!strncmp(ws_getrequestheader(pwsc,"user-agent"),
"Hifidelio",9))) {
ws_addresponseheader(pwsc,"Connection","Keep-Alive");
ws_should_close(pwsc,0);
} else {
ws_addresponseheader(pwsc,"Connection","Close");
}
if(!offset)
ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
else {
ws_addresponseheader(pwsc,"Content-Range","bytes %ld-%ld/%ld",
(long)offset,(long)real_len,
(long)real_len+1);
ws_writefd(pwsc,"HTTP/1.1 206 Partial Content\r\n");
}
ws_emitheaders(pwsc);
config_set_status(pwsc,session,"Streaming '%s' (id %d)",
pmp3->title, pmp3->id);
DPRINTF(E_WARN,L_WS,"Session %d: Streaming file '%s' to %s (offset %d)\n",
session,pmp3->fname, ws_hostname(pwsc),(long)offset);
if(offset) {
DPRINTF(E_INF,L_WS,"Seeking to offset %ld\n",(long)offset);
io_setpos(hfile,offset,SEEK_SET);
}
if(!ws_copyfile(pwsc,hfile,&bytes_copied)) {
DPRINTF(E_INF,L_WS,"Error copying file to remote... %s\n",
strerror(errno));
ws_should_close(pwsc,1);
} else {
DPRINTF(E_INF,L_WS,"Finished streaming file to remote: %lld bytes\n",
bytes_copied);
}
config_set_status(pwsc,session,NULL);
io_close(hfile);
io_dispose(hfile);
db_dispose_item(pmp3);
}
/* update play counts */
if(bytes_copied >= (real_len * 80 / 100)) {
db_playcount_increment(NULL,pmp3->id);
if(!offset)
config.stats.songs_served++; /* FIXME: remove stat races */
}
}
// free(pqi);
}
void pi_conf_dispose_string(char *str) {
free(str);
}

View File

@ -40,6 +40,9 @@ extern void plugin_event_dispatch(int event_id, int intval, void *vp, int len);
extern void *plugin_enum(void *); extern void *plugin_enum(void *);
extern char *plugin_get_description(void *); extern char *plugin_get_description(void *);
extern int plugin_ssc_should_transcode(WS_CONNINFO *pwsc, char *codec);
extern int plugin_ssc_transcode(WS_CONNINFO *pwsc, MP3FILE *pmp3, int offset, int headers);
/* these should really get rows */ /* these should really get rows */
#define PLUGIN_E_SUCCESS 0 #define PLUGIN_E_SUCCESS 0

View File

@ -262,10 +262,10 @@ MetaField_t daap_encode_meta(char *meta) {
if(m->tag) if(m->tag)
bits |= (((MetaField_t) 1) << m->bit); bits |= (((MetaField_t) 1) << m->bit);
else else
_ppi->log(E_WARN,"Unknown meta code: %.*s\n", len, start); pi_log(E_WARN,"Unknown meta code: %.*s\n", len, start);
} }
_ppi->log(E_DBG, "meta codes: %llu\n", bits); pi_log(E_DBG, "meta codes: %llu\n", bits);
return bits; return bits;
} }
@ -475,12 +475,12 @@ int daap_enum_size(char **pe, PRIVINFO *pinfo, int *count, int *total_size) {
int record_size; int record_size;
char **row; char **row;
_ppi->log(E_DBG,"Enumerating size\n"); pi_log(E_DBG,"Enumerating size\n");
*count=0; *count=0;
*total_size = 0; *total_size = 0;
while((!(err=_ppi->db_enum_fetch_row(pe,&row,&pinfo->dq))) && (row)) { while((!(err=pi_db_enum_fetch_row(pe,&row,&pinfo->dq))) && (row)) {
if((record_size = daap_get_size(pinfo,row))) { if((record_size = daap_get_size(pinfo,row))) {
*total_size += record_size; *total_size += record_size;
*count = *count + 1; *count = *count + 1;
@ -488,14 +488,14 @@ int daap_enum_size(char **pe, PRIVINFO *pinfo, int *count, int *total_size) {
} }
if(err) { if(err) {
_ppi->db_enum_end(NULL); pi_db_enum_end(NULL);
_ppi->db_enum_dispose(NULL,&pinfo->dq); pi_db_enum_dispose(NULL,&pinfo->dq);
return err; return err;
} }
err=_ppi->db_enum_restart(pe, &pinfo->dq); err=pi_db_enum_restart(pe, &pinfo->dq);
_ppi->log(E_DBG,"Got size: %d\n",*total_size); pi_log(E_DBG,"Got size: %d\n",*total_size);
return err; return err;
} }
@ -508,10 +508,10 @@ int daap_enum_fetch(char **pe, PRIVINFO *pinfo, int *size, unsigned char **pdmap
unsigned char *presult; unsigned char *presult;
char **row; char **row;
err=_ppi->db_enum_fetch_row(pe, &row, &pinfo->dq); err=pi_db_enum_fetch_row(pe, &row, &pinfo->dq);
if(err) { if(err) {
_ppi->db_enum_end(NULL); pi_db_enum_end(NULL);
_ppi->db_enum_dispose(NULL,&pinfo->dq); pi_db_enum_dispose(NULL,&pinfo->dq);
return err; return err;
} }
@ -520,7 +520,7 @@ int daap_enum_fetch(char **pe, PRIVINFO *pinfo, int *size, unsigned char **pdmap
if(result_size) { if(result_size) {
presult = (unsigned char*)malloc(result_size); presult = (unsigned char*)malloc(result_size);
if(!presult) { if(!presult) {
_ppi->log(E_FATAL,"Malloc error\n"); pi_log(E_FATAL,"Malloc error\n");
} }
daap_build_dmap(pinfo,row,presult,result_size); daap_build_dmap(pinfo,row,presult,result_size);
@ -570,7 +570,7 @@ int daap_get_size(PRIVINFO *pinfo, char **valarray) {
break; break;
case QUERY_TYPE_ITEMS: case QUERY_TYPE_ITEMS:
/* see if this is going to be transcoded */ /* see if this is going to be transcoded */
transcode = _ppi->should_transcode(pinfo->pwsc,valarray[SG_CODECTYPE]); transcode = pi_should_transcode(pinfo->pwsc,valarray[SG_CODECTYPE]);
/* Items that get changed by transcode: /* Items that get changed by transcode:
* *
@ -720,7 +720,7 @@ int daap_get_size(PRIVINFO *pinfo, char **valarray) {
break; break;
default: default:
_ppi->log(E_LOG,"Unknown query type: %d\n",(int)pinfo->dq.query_type); pi_log(E_LOG,"Unknown query type: %d\n",(int)pinfo->dq.query_type);
return 0; return 0;
} }
return 0; return 0;
@ -759,7 +759,7 @@ int daap_build_dmap(PRIVINFO *pinfo, char **valarray, unsigned char *presult, in
break; break;
case QUERY_TYPE_ITEMS: case QUERY_TYPE_ITEMS:
/* see if this is going to be transcoded */ /* see if this is going to be transcoded */
transcode = _ppi->should_transcode(pinfo->pwsc,valarray[SG_CODECTYPE]); transcode = pi_should_transcode(pinfo->pwsc,valarray[SG_CODECTYPE]);
/* Items that get changed by transcode: /* Items that get changed by transcode:
* *
@ -924,7 +924,7 @@ int daap_build_dmap(PRIVINFO *pinfo, char **valarray, unsigned char *presult, in
break; break;
default: default:
_ppi->log(E_LOG,"Unknown query type: %d\n",(int)pinfo->dq.query_type); pi_log(E_LOG,"Unknown query type: %d\n",(int)pinfo->dq.query_type);
return 0; return 0;
} }
return 0; return 0;

View File

@ -90,18 +90,17 @@ static int out_daap_output_xml_write(WS_CONNINFO *pwsc, PRIVINFO *ppi, unsigned
static void out_daap_cleanup(PRIVINFO *ppi); static void out_daap_cleanup(PRIVINFO *ppi);
PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *);
void plugin_handler(WS_CONNINFO *pwsc); void plugin_handler(WS_CONNINFO *pwsc);
int plugin_can_handle(WS_CONNINFO *pwsc); int plugin_can_handle(WS_CONNINFO *pwsc);
int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password); int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password);
PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *); PLUGIN_INFO *plugin_info(void);
PLUGIN_OUTPUT_FN _pofn = { plugin_can_handle, plugin_handler, plugin_auth }; PLUGIN_OUTPUT_FN _pofn = { plugin_can_handle, plugin_handler, plugin_auth };
PLUGIN_REND_INFO _pri[] = { PLUGIN_REND_INFO _pri[] = {
{ "_daap._tcp", NULL }, { "_daap._tcp", NULL },
{ NULL, NULL } { NULL, NULL }
}; };
PLUGIN_INPUT_FN *_ppi;
PLUGIN_INFO _pi = { PLUGIN_INFO _pi = {
PLUGIN_VERSION, /* version */ PLUGIN_VERSION, /* version */
PLUGIN_OUTPUT, /* type */ PLUGIN_OUTPUT, /* type */
@ -161,8 +160,7 @@ PLUGIN_RESPONSE daap_uri_map[] = {
/** /**
* return info about this plugin module * return info about this plugin module
*/ */
PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *ppi) { PLUGIN_INFO *plugin_info(void) {
_ppi = ppi;
return &_pi; return &_pi;
} }
@ -170,9 +168,9 @@ PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *ppi) {
* see if the plugin should handle this request * see if the plugin should handle this request
*/ */
int plugin_can_handle(WS_CONNINFO *pwsc) { int plugin_can_handle(WS_CONNINFO *pwsc) {
char *uri = _ppi->ws_uri(pwsc); char *uri = pi_ws_uri(pwsc);
_ppi->log(E_DBG,"Checking url %s\n",uri); pi_log(E_DBG,"Checking url %s\n",uri);
if(strncasecmp(uri,"/databases",10) == 0) if(strncasecmp(uri,"/databases",10) == 0)
return TRUE; return TRUE;
if(strncasecmp(uri,"/server-info",12) == 0) if(strncasecmp(uri,"/server-info",12) == 0)
@ -194,7 +192,7 @@ int plugin_can_handle(WS_CONNINFO *pwsc) {
* works. * works.
*/ */
int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password) { int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password) {
char *uri = _ppi->ws_uri(pwsc); char *uri = pi_ws_uri(pwsc);
/* don't auth for stuff we shouldn't */ /* don't auth for stuff we shouldn't */
if(strncasecmp(uri,"/server-info",12) == 0) if(strncasecmp(uri,"/server-info",12) == 0)
@ -204,7 +202,7 @@ int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password) {
if(strncasecmp(uri,"/databases/1/items/",19) == 0) if(strncasecmp(uri,"/databases/1/items/",19) == 0)
return TRUE; return TRUE;
return _ppi->ws_matchesrole(pwsc,username,password,"user"); return pi_ws_matchesrole(pwsc,username,password,"user");
} }
@ -249,7 +247,7 @@ int daap_auth(WS_CONNINFO *pwsc, char *username, char *password) {
char *readpassword; char *readpassword;
int result; int result;
readpassword = _ppi->conf_alloc_string("general","password",NULL); readpassword = pi_conf_alloc_string("general","password",NULL);
if(password == NULL) { if(password == NULL) {
if((readpassword == NULL)||(strlen(readpassword) == 0)) { if((readpassword == NULL)||(strlen(readpassword) == 0)) {
@ -265,7 +263,7 @@ int daap_auth(WS_CONNINFO *pwsc, char *username, char *password) {
} }
} }
if(readpassword) _ppi->conf_dispose_string(readpassword); if(readpassword) pi_conf_dispose_string(readpassword);
return result; return result;
} }
@ -282,46 +280,46 @@ void plugin_handler(WS_CONNINFO *pwsc) {
long l,h; long l,h;
char *ptr; char *ptr;
_ppi->log(E_DBG,"Getting uri...\n"); pi_log(E_DBG,"Getting uri...\n");
string = _ppi->ws_uri(pwsc); string = pi_ws_uri(pwsc);
string++; string++;
_ppi->log(E_DBG,"Mallocing privinfo...\n"); pi_log(E_DBG,"Mallocing privinfo...\n");
ppi = (PRIVINFO *)malloc(sizeof(PRIVINFO)); ppi = (PRIVINFO *)malloc(sizeof(PRIVINFO));
if(ppi) { if(ppi) {
memset(ppi,0,sizeof(PRIVINFO)); memset(ppi,0,sizeof(PRIVINFO));
} }
if(!ppi) { if(!ppi) {
_ppi->ws_returnerror(pwsc,500,"Malloc error in plugin_handler"); pi_ws_returnerror(pwsc,500,"Malloc error in plugin_handler");
return; return;
} }
memset((void*)&ppi->dq,0,sizeof(DB_QUERY)); memset((void*)&ppi->dq,0,sizeof(DB_QUERY));
ppi->empty_strings = _ppi->conf_get_int("daap","empty_strings",0); ppi->empty_strings = pi_conf_get_int("daap","empty_strings",0);
ppi->pwsc = pwsc; ppi->pwsc = pwsc;
_ppi->ws_addresponseheader(pwsc,"Accept-Ranges","bytes"); pi_ws_addresponseheader(pwsc,"Accept-Ranges","bytes");
_ppi->ws_addresponseheader(pwsc,"DAAP-Server","firefly/" VERSION); pi_ws_addresponseheader(pwsc,"DAAP-Server","firefly/" VERSION);
_ppi->ws_addresponseheader(pwsc,"Content-Type","application/x-dmap-tagged"); pi_ws_addresponseheader(pwsc,"Content-Type","application/x-dmap-tagged");
_ppi->ws_addresponseheader(pwsc,"Cache-Control","no-cache"); pi_ws_addresponseheader(pwsc,"Cache-Control","no-cache");
_ppi->ws_addresponseheader(pwsc,"Expires","-1"); pi_ws_addresponseheader(pwsc,"Expires","-1");
if(_ppi->ws_getvar(pwsc,"session-id")) if(pi_ws_getvar(pwsc,"session-id"))
ppi->session_id = atoi(_ppi->ws_getvar(pwsc,"session-id")); ppi->session_id = atoi(pi_ws_getvar(pwsc,"session-id"));
ppi->dq.offset = 0; ppi->dq.offset = 0;
ppi->dq.limit = 999999; ppi->dq.limit = 999999;
l=h=0; l=h=0;
if(_ppi->ws_getvar(pwsc,"index")) { if(pi_ws_getvar(pwsc,"index")) {
index_req = _ppi->ws_getvar(pwsc,"index"); index_req = pi_ws_getvar(pwsc,"index");
l = strtol(index_req,&ptr,10); l = strtol(index_req,&ptr,10);
if(l<0) { /* "-h"... tail range, last "h" entries */ if(l<0) { /* "-h"... tail range, last "h" entries */
_ppi->log(E_LOG,"Unsupported index range: %s\n",index_req); pi_log(E_LOG,"Unsupported index range: %s\n",index_req);
} else if(*ptr == 0) { } else if(*ptr == 0) {
/* single item */ /* single item */
ppi->dq.offset = l; ppi->dq.offset = l;
@ -334,31 +332,31 @@ void plugin_handler(WS_CONNINFO *pwsc) {
} }
} }
_ppi->log(E_DBG,"Index %s: offset %d, limit %d\n",index_req, pi_log(E_DBG,"Index %s: offset %d, limit %d\n",index_req,
ppi->dq.offset,ppi->dq.limit); ppi->dq.offset,ppi->dq.limit);
} }
if(_ppi->ws_getvar(pwsc,"query")) { if(pi_ws_getvar(pwsc,"query")) {
ppi->dq.filter_type = FILTER_TYPE_APPLE; ppi->dq.filter_type = FILTER_TYPE_APPLE;
ppi->dq.filter = _ppi->ws_getvar(pwsc,"query"); ppi->dq.filter = pi_ws_getvar(pwsc,"query");
} }
_ppi->log(E_DBG,"Tokenizing url\n"); pi_log(E_DBG,"Tokenizing url\n");
while((ppi->uri_count < 10) && (token=strtok_r(string,"/",&save))) { while((ppi->uri_count < 10) && (token=strtok_r(string,"/",&save))) {
string=NULL; string=NULL;
ppi->uri_sections[ppi->uri_count++] = token; ppi->uri_sections[ppi->uri_count++] = token;
} }
elements = sizeof(daap_uri_map) / sizeof(PLUGIN_RESPONSE); elements = sizeof(daap_uri_map) / sizeof(PLUGIN_RESPONSE);
_ppi->log(E_DBG,"Found %d elements\n",elements); pi_log(E_DBG,"Found %d elements\n",elements);
index = 0; index = 0;
found = 0; found = 0;
while((!found) && (index < elements)) { while((!found) && (index < elements)) {
/* test this set */ /* test this set */
_ppi->log(E_DBG,"Checking reponse %d\n",index); pi_log(E_DBG,"Checking reponse %d\n",index);
part=0; part=0;
while(part < 10) { while(part < 10) {
if((daap_uri_map[index].uri[part]) && (!ppi->uri_sections[part])) if((daap_uri_map[index].uri[part]) && (!ppi->uri_sections[part]))
@ -377,7 +375,7 @@ void plugin_handler(WS_CONNINFO *pwsc) {
if(part == 10) { if(part == 10) {
found = 1; found = 1;
_ppi->log(E_DBG,"Found it! Index: %d\n",index); pi_log(E_DBG,"Found it! Index: %d\n",index);
} else { } else {
index++; index++;
} }
@ -389,8 +387,8 @@ void plugin_handler(WS_CONNINFO *pwsc) {
return; return;
} }
_ppi->ws_returnerror(pwsc,400,"Bad request"); pi_ws_returnerror(pwsc,400,"Bad request");
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
out_daap_cleanup(ppi); out_daap_cleanup(ppi);
return; return;
} }
@ -408,33 +406,33 @@ int out_daap_output_start(WS_CONNINFO *pwsc, PRIVINFO *ppi, int content_length)
poi=(OUTPUT_INFO*)calloc(1,sizeof(OUTPUT_INFO)); poi=(OUTPUT_INFO*)calloc(1,sizeof(OUTPUT_INFO));
if(!poi) { if(!poi) {
_ppi->log(E_LOG,"Malloc error in out_daap_ouput_start\n"); pi_log(E_LOG,"Malloc error in out_daap_ouput_start\n");
return -1; return -1;
} }
ppi->output_info = (void*) poi; ppi->output_info = (void*) poi;
poi->dmap_response_length = content_length; poi->dmap_response_length = content_length;
if(_ppi->ws_getvar(pwsc,"output")) { if(pi_ws_getvar(pwsc,"output")) {
if(strcasecmp(_ppi->ws_getvar(pwsc,"output"),"readable") == 0) if(strcasecmp(pi_ws_getvar(pwsc,"output"),"readable") == 0)
poi->readable=1; poi->readable=1;
poi->xml_output=1; poi->xml_output=1;
_ppi->ws_addresponseheader(pwsc,"Content-Type","text/xml"); pi_ws_addresponseheader(pwsc,"Content-Type","text/xml");
_ppi->ws_addresponseheader(pwsc,"Connection","Close"); pi_ws_addresponseheader(pwsc,"Connection","Close");
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
_ppi->ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n"); pi_ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
_ppi->ws_emitheaders(pwsc); pi_ws_emitheaders(pwsc);
_ppi->ws_writefd(pwsc,"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"); pi_ws_writefd(pwsc,"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
if(poi->readable) if(poi->readable)
_ppi->ws_writefd(pwsc,"\n"); pi_ws_writefd(pwsc,"\n");
return 0; return 0;
} }
_ppi->ws_addresponseheader(pwsc,"Content-Length","%d", pi_ws_addresponseheader(pwsc,"Content-Length","%d",
poi->dmap_response_length); poi->dmap_response_length);
_ppi->ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n"); pi_ws_writefd(pwsc,"HTTP/1.1 200 OK\r\n");
_ppi->ws_emitheaders(pwsc); pi_ws_emitheaders(pwsc);
/* I guess now we would start writing the output */ /* I guess now we would start writing the output */
return 0; return 0;
@ -458,7 +456,7 @@ int out_daap_output_write(WS_CONNINFO *pwsc, PRIVINFO *ppi, unsigned char *block
if(poi->xml_output) if(poi->xml_output)
return out_daap_output_xml_write(pwsc, ppi, block, len); return out_daap_output_xml_write(pwsc, ppi, block, len);
result=_ppi->ws_writebinary(pwsc,(char*)block,len); result=pi_ws_writebinary(pwsc,(char*)block,len);
if(result != len) if(result != len)
return -1; return -1;
@ -493,7 +491,7 @@ int out_daap_output_xml_write(WS_CONNINFO *pwsc, PRIVINFO *ppi, unsigned char *b
block_done=1; block_done=1;
len_left=(int)((block+len) - current); len_left=(int)((block+len) - current);
if(len_left < 8) { if(len_left < 8) {
_ppi->log(E_FATAL,"Badly formatted dmap block - frag size: %d",len_left); pi_log(E_FATAL,"Badly formatted dmap block - frag size: %d",len_left);
} }
/* set up block */ /* set up block */
@ -509,49 +507,49 @@ int out_daap_output_xml_write(WS_CONNINFO *pwsc, PRIVINFO *ppi, unsigned char *b
} }
/* lookup and serialize */ /* lookup and serialize */
_ppi->log(E_SPAM,"%*s %s: %d\n",poi->stack_height,"",block_tag,block_len); pi_log(E_SPAM,"%*s %s: %d\n",poi->stack_height,"",block_tag,block_len);
pitem=out_daap_xml_lookup_tag(block_tag); pitem=out_daap_xml_lookup_tag(block_tag);
if(poi->readable) if(poi->readable)
_ppi->ws_writefd(pwsc,"%*s",poi->stack_height,""); pi_ws_writefd(pwsc,"%*s",poi->stack_height,"");
_ppi->ws_writefd(pwsc,"<%s>",pitem->description); pi_ws_writefd(pwsc,"<%s>",pitem->description);
switch(pitem->type) { switch(pitem->type) {
case 0x01: /* byte */ case 0x01: /* byte */
if(block_len != 1) { if(block_len != 1) {
_ppi->log(E_FATAL,"tag %s, size %d, wanted 1\n",block_tag, block_len); pi_log(E_FATAL,"tag %s, size %d, wanted 1\n",block_tag, block_len);
} }
_ppi->ws_writefd(pwsc,"%d",*((char *)data)); pi_ws_writefd(pwsc,"%d",*((char *)data));
break; break;
case 0x02: /* unsigned byte */ case 0x02: /* unsigned byte */
if(block_len != 1) { if(block_len != 1) {
_ppi->log(E_FATAL,"tag %s, size %d, wanted 1\n",block_tag, block_len); pi_log(E_FATAL,"tag %s, size %d, wanted 1\n",block_tag, block_len);
} }
_ppi->ws_writefd(pwsc,"%ud",*((char *)data)); pi_ws_writefd(pwsc,"%ud",*((char *)data));
break; break;
case 0x03: /* short */ case 0x03: /* short */
if(block_len != 2) { if(block_len != 2) {
_ppi->log(E_FATAL,"tag %s, size %d, wanted 2\n",block_tag, block_len); pi_log(E_FATAL,"tag %s, size %d, wanted 2\n",block_tag, block_len);
} }
ivalue = data[0] << 8 | data[1]; ivalue = data[0] << 8 | data[1];
_ppi->ws_writefd(pwsc,"%d",ivalue); pi_ws_writefd(pwsc,"%d",ivalue);
break; break;
case 0x05: /* int */ case 0x05: /* int */
case 0x0A: /* epoch */ case 0x0A: /* epoch */
if(block_len != 4) { if(block_len != 4) {
_ppi->log(E_FATAL,"tag %s, size %d, wanted 4\n",block_tag, block_len); pi_log(E_FATAL,"tag %s, size %d, wanted 4\n",block_tag, block_len);
} }
ivalue = data[0] << 24 | ivalue = data[0] << 24 |
data[1] << 16 | data[1] << 16 |
data[2] << 8 | data[2] << 8 |
data[3]; data[3];
_ppi->ws_writefd(pwsc,"%d",ivalue); pi_ws_writefd(pwsc,"%d",ivalue);
break; break;
case 0x07: /* long long */ case 0x07: /* long long */
if(block_len != 8) { if(block_len != 8) {
_ppi->log(E_FATAL,"tag %s, size %d, wanted 8\n",block_tag, block_len); pi_log(E_FATAL,"tag %s, size %d, wanted 8\n",block_tag, block_len);
} }
ivalue = data[0] << 24 | ivalue = data[0] << 24 |
@ -564,29 +562,29 @@ int out_daap_output_xml_write(WS_CONNINFO *pwsc, PRIVINFO *ppi, unsigned char *b
data[6] << 8 | data[6] << 8 |
data[7]; data[7];
lvalue = (lvalue << 32) | ivalue; lvalue = (lvalue << 32) | ivalue;
_ppi->ws_writefd(pwsc,"%ll",ivalue); pi_ws_writefd(pwsc,"%ll",ivalue);
break; break;
case 0x09: /* string */ case 0x09: /* string */
if(block_len) { if(block_len) {
encoded_string=out_daap_xml_encode((char*)data,block_len); encoded_string=out_daap_xml_encode((char*)data,block_len);
_ppi->ws_writefd(pwsc,"%s",encoded_string); pi_ws_writefd(pwsc,"%s",encoded_string);
free(encoded_string); free(encoded_string);
} }
break; break;
case 0x0B: /* version? */ case 0x0B: /* version? */
if(block_len != 4) { if(block_len != 4) {
_ppi->log(E_FATAL,"tag %s, size %d, wanted 4\n",block_tag, block_len); pi_log(E_FATAL,"tag %s, size %d, wanted 4\n",block_tag, block_len);
} }
ivalue=data[0] << 8 | data[1]; ivalue=data[0] << 8 | data[1];
_ppi->ws_writefd(pwsc,"%d.%d.%d",ivalue,data[2],data[3]); pi_ws_writefd(pwsc,"%d.%d.%d",ivalue,data[2],data[3]);
break; break;
case 0x0C: case 0x0C:
if((poi->browse_response)&&(strcmp(block_tag,"mlit") ==0)) { if((poi->browse_response)&&(strcmp(block_tag,"mlit") ==0)) {
if(block_len) { if(block_len) {
encoded_string=out_daap_xml_encode((char*)data,block_len); encoded_string=out_daap_xml_encode((char*)data,block_len);
_ppi->ws_writefd(pwsc,"%s",encoded_string); pi_ws_writefd(pwsc,"%s",encoded_string);
free(encoded_string); free(encoded_string);
} }
} else { } else {
@ -599,29 +597,29 @@ int out_daap_output_xml_write(WS_CONNINFO *pwsc, PRIVINFO *ppi, unsigned char *b
memcpy(poi->stack[poi->stack_height].tag,block_tag,5); memcpy(poi->stack[poi->stack_height].tag,block_tag,5);
poi->stack_height++; poi->stack_height++;
if(poi->stack_height == 10) { if(poi->stack_height == 10) {
_ppi->log(E_FATAL,"Stack overflow\n"); pi_log(E_FATAL,"Stack overflow\n");
} }
block_done=0; block_done=0;
} }
break; break;
default: default:
_ppi->log(E_FATAL,"Bad dmap type: %d, %s\n", pi_log(E_FATAL,"Bad dmap type: %d, %s\n",
pitem->type, pitem->description); pitem->type, pitem->description);
break; break;
} }
if(block_done) { if(block_done) {
_ppi->ws_writefd(pwsc,"</%s>",pitem->description); pi_ws_writefd(pwsc,"</%s>",pitem->description);
if(poi->readable) if(poi->readable)
_ppi->ws_writefd(pwsc,"\n"); pi_ws_writefd(pwsc,"\n");
block_len += 8; block_len += 8;
} else { } else {
/* must be a container */ /* must be a container */
block_len = 8; block_len = 8;
if(poi->readable) if(poi->readable)
_ppi->ws_writefd(pwsc,"\n"); pi_ws_writefd(pwsc,"\n");
} }
current += block_len; current += block_len;
@ -631,17 +629,17 @@ int out_daap_output_xml_write(WS_CONNINFO *pwsc, PRIVINFO *ppi, unsigned char *b
while(stack_ptr--) { while(stack_ptr--) {
poi->stack[stack_ptr].bytes_left -= block_len; poi->stack[stack_ptr].bytes_left -= block_len;
if(poi->stack[stack_ptr].bytes_left < 0) { if(poi->stack[stack_ptr].bytes_left < 0) {
_ppi->log(E_FATAL,"negative container\n"); pi_log(E_FATAL,"negative container\n");
} }
if(!poi->stack[stack_ptr].bytes_left) { if(!poi->stack[stack_ptr].bytes_left) {
poi->stack_height--; poi->stack_height--;
pitem=out_daap_xml_lookup_tag(poi->stack[stack_ptr].tag); pitem=out_daap_xml_lookup_tag(poi->stack[stack_ptr].tag);
if(poi->readable) if(poi->readable)
_ppi->ws_writefd(pwsc,"%*s",poi->stack_height,""); pi_ws_writefd(pwsc,"%*s",poi->stack_height,"");
_ppi->ws_writefd(pwsc,"</%s>",pitem->description); pi_ws_writefd(pwsc,"</%s>",pitem->description);
if(poi->readable) if(poi->readable)
_ppi->ws_writefd(pwsc,"\n"); pi_ws_writefd(pwsc,"\n");
} }
} }
} }
@ -662,10 +660,10 @@ int out_daap_output_end(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
OUTPUT_INFO *poi = ppi->output_info; OUTPUT_INFO *poi = ppi->output_info;
if((poi) && (poi->xml_output) && (poi->stack_height)) { if((poi) && (poi->xml_output) && (poi->stack_height)) {
_ppi->log(E_LOG,"Badly formed xml -- still stack\n"); pi_log(E_LOG,"Badly formed xml -- still stack\n");
} }
_ppi->config_set_status(pwsc,ppi->session_id,NULL); pi_config_set_status(pwsc,ppi->session_id,NULL);
return 0; return 0;
} }
@ -680,7 +678,7 @@ DAAP_ITEMS *out_daap_xml_lookup_tag(char *tag) {
} }
if(!pitem->tag) if(!pitem->tag)
_ppi->log(E_FATAL,"Unknown daap tag: %c%c%c%c\n",tag[0],tag[1],tag[2],tag[3]); pi_log(E_FATAL,"Unknown daap tag: %c%c%c%c\n",tag[0],tag[1],tag[2],tag[3]);
return pitem; return pitem;
} }
@ -747,7 +745,7 @@ char *out_daap_xml_encode(char *original, int len) {
void out_daap_stream(WS_CONNINFO *pwsc, PRIVINFO *ppi) { void out_daap_stream(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
/* should show sesson id */ /* should show sesson id */
_ppi->stream(pwsc, ppi->uri_sections[3]); pi_stream(pwsc, ppi->uri_sections[3]);
} }
/** /**
@ -762,19 +760,19 @@ void out_daap_addplaylistitems(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
playlist_id = atoi(ppi->uri_sections[3]); playlist_id = atoi(ppi->uri_sections[3]);
if(!_ppi->ws_getvar(pwsc,"dmap.itemid")) { if(!pi_ws_getvar(pwsc,"dmap.itemid")) {
_ppi->log(E_LOG,"Attempt to add playlist item w/o dmap.itemid\n"); pi_log(E_LOG,"Attempt to add playlist item w/o dmap.itemid\n");
out_daap_error(pwsc,ppi,"MAPI","No item id specified (dmap.itemid)"); out_daap_error(pwsc,ppi,"MAPI","No item id specified (dmap.itemid)");
return; return;
} }
tempstring=strdup(_ppi->ws_getvar(pwsc,"dmap.itemid")); tempstring=strdup(pi_ws_getvar(pwsc,"dmap.itemid"));
current=(unsigned char*)tempstring; current=(unsigned char*)tempstring;
while((token=_strsep((char**)(char*)&current,","))) { while((token=_strsep((char**)(char*)&current,","))) {
if(token) { if(token) {
/* FIXME: error handling */ /* FIXME: error handling */
_ppi->db_add_playlist_item(NULL,playlist_id,atoi(token)); pi_db_add_playlist_item(NULL,playlist_id,atoi(token));
} }
} }
@ -789,7 +787,7 @@ void out_daap_addplaylistitems(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
out_daap_output_write(pwsc,ppi,playlist_response,20); out_daap_output_write(pwsc,ppi,playlist_response,20);
out_daap_output_end(pwsc,ppi); out_daap_output_end(pwsc,ppi);
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
return; return;
} }
@ -801,14 +799,14 @@ void out_daap_deleteplaylist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
unsigned char playlist_response[20]; unsigned char playlist_response[20];
unsigned char *current; unsigned char *current;
if(!_ppi->ws_getvar(pwsc,"dmap.itemid")) { if(!pi_ws_getvar(pwsc,"dmap.itemid")) {
_ppi->log(E_LOG,"Attempt to delete playlist w/o dmap.itemid\n"); pi_log(E_LOG,"Attempt to delete playlist w/o dmap.itemid\n");
out_daap_error(pwsc,ppi,"MDPR","No playlist id specified"); out_daap_error(pwsc,ppi,"MDPR","No playlist id specified");
return; return;
} }
/* FIXME: error handling */ /* FIXME: error handling */
_ppi->db_delete_playlist(NULL,atoi(_ppi->ws_getvar(pwsc,"dmap.itemid"))); pi_db_delete_playlist(NULL,atoi(pi_ws_getvar(pwsc,"dmap.itemid")));
/* success(ish)... spool out a dmap block */ /* success(ish)... spool out a dmap block */
current = playlist_response; current = playlist_response;
@ -819,7 +817,7 @@ void out_daap_deleteplaylist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
out_daap_output_write(pwsc,ppi,playlist_response,20); out_daap_output_write(pwsc,ppi,playlist_response,20);
out_daap_output_end(pwsc,ppi); out_daap_output_end(pwsc,ppi);
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
return; return;
} }
@ -834,22 +832,22 @@ void out_daap_deleteplaylistitems(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
char *token; char *token;
int playlist_id; int playlist_id;
if(!_ppi->ws_getvar(pwsc,"dmap.itemid")) { if(!pi_ws_getvar(pwsc,"dmap.itemid")) {
_ppi->log(E_LOG,"Delete playlist item w/o dmap.itemid\n"); pi_log(E_LOG,"Delete playlist item w/o dmap.itemid\n");
out_daap_error(pwsc,ppi,"MDPI","No playlist item specified"); out_daap_error(pwsc,ppi,"MDPI","No playlist item specified");
return; return;
} }
playlist_id = atoi(ppi->uri_sections[3]); playlist_id = atoi(ppi->uri_sections[3]);
tempstring=strdup(_ppi->ws_getvar(pwsc,"dmap.itemid")); tempstring=strdup(pi_ws_getvar(pwsc,"dmap.itemid"));
current=(unsigned char *)tempstring; current=(unsigned char *)tempstring;
/* this looks strange, but gets rid of gcc 4 warnings */ /* this looks strange, but gets rid of gcc 4 warnings */
while((token=_strsep((char**)(char*)&current,","))) { while((token=_strsep((char**)(char*)&current,","))) {
if(token) { if(token) {
/* FIXME: Error handling */ /* FIXME: Error handling */
_ppi->db_delete_playlist_item(NULL,playlist_id,atoi(token)); pi_db_delete_playlist_item(NULL,playlist_id,atoi(token));
} }
} }
@ -864,7 +862,7 @@ void out_daap_deleteplaylistitems(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
out_daap_output_write(pwsc,ppi,playlist_response,20); out_daap_output_write(pwsc,ppi,playlist_response,20);
out_daap_output_end(pwsc,ppi); out_daap_output_end(pwsc,ppi);
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
return; return;
} }
@ -880,21 +878,21 @@ void out_daap_addplaylist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
int retval, playlistid; int retval, playlistid;
char *estring = NULL; char *estring = NULL;
if((!_ppi->ws_getvar(pwsc,"org.mt-daapd.playlist-type")) || if((!pi_ws_getvar(pwsc,"org.mt-daapd.playlist-type")) ||
(!_ppi->ws_getvar(pwsc,"dmap.itemname"))) { (!pi_ws_getvar(pwsc,"dmap.itemname"))) {
_ppi->log(E_LOG,"attempt to add playlist with invalid type\n"); pi_log(E_LOG,"attempt to add playlist with invalid type\n");
out_daap_error(pwsc,ppi,"MAPR","bad playlist info specified"); out_daap_error(pwsc,ppi,"MAPR","bad playlist info specified");
return; return;
} }
type=atoi(_ppi->ws_getvar(pwsc,"org.mt-daapd.playlist-type")); type=atoi(pi_ws_getvar(pwsc,"org.mt-daapd.playlist-type"));
name=_ppi->ws_getvar(pwsc,"dmap.itemname"); name=pi_ws_getvar(pwsc,"dmap.itemname");
query=_ppi->ws_getvar(pwsc,"org.mt-daapd.smart-playlist-spec"); query=pi_ws_getvar(pwsc,"org.mt-daapd.smart-playlist-spec");
retval=_ppi->db_add_playlist(&estring,name,type,query,NULL,0,&playlistid); retval=pi_db_add_playlist(&estring,name,type,query,NULL,0,&playlistid);
if(retval) { if(retval) {
out_daap_error(pwsc,ppi,"MAPR",estring); out_daap_error(pwsc,ppi,"MAPR",estring);
_ppi->log(E_LOG,"error adding playlist %s: %s\n",name,estring); pi_log(E_LOG,"error adding playlist %s: %s\n",name,estring);
free(estring); free(estring);
return; return;
} }
@ -908,7 +906,7 @@ void out_daap_addplaylist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
out_daap_output_write(pwsc,ppi,playlist_response,32); out_daap_output_write(pwsc,ppi,playlist_response,32);
out_daap_output_end(pwsc,ppi); out_daap_output_end(pwsc,ppi);
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
return; return;
} }
@ -924,20 +922,20 @@ void out_daap_editplaylist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
int retval; int retval;
if(!_ppi->ws_getvar(pwsc,"dmap.itemid")) { if(!pi_ws_getvar(pwsc,"dmap.itemid")) {
_ppi->log(E_LOG,"Missing itemid on playlist edit"); pi_log(E_LOG,"Missing itemid on playlist edit");
out_daap_error(pwsc,ppi,"MEPR","No itemid specified"); out_daap_error(pwsc,ppi,"MEPR","No itemid specified");
return; return;
} }
name=_ppi->ws_getvar(pwsc,"dmap.itemname"); name=pi_ws_getvar(pwsc,"dmap.itemname");
query=_ppi->ws_getvar(pwsc,"org.mt-daapd.smart-playlist-spec"); query=pi_ws_getvar(pwsc,"org.mt-daapd.smart-playlist-spec");
id=atoi(_ppi->ws_getvar(pwsc,"dmap.itemid")); id=atoi(pi_ws_getvar(pwsc,"dmap.itemid"));
/* FIXME: Error handling */ /* FIXME: Error handling */
retval=_ppi->db_edit_playlist(&pe,id,name,query); retval=pi_db_edit_playlist(&pe,id,name,query);
if(retval) { if(retval) {
_ppi->log(E_LOG,"error editing playlist.\n"); pi_log(E_LOG,"error editing playlist.\n");
out_daap_error(pwsc,ppi,"MEPR",pe); out_daap_error(pwsc,ppi,"MEPR",pe);
if(pe) free(pe); if(pe) free(pe);
return; return;
@ -950,7 +948,7 @@ void out_daap_editplaylist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
out_daap_output_write(pwsc,ppi,edit_response,20); out_daap_output_write(pwsc,ppi,edit_response,20);
out_daap_output_end(pwsc,ppi); out_daap_output_end(pwsc,ppi);
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
return; return;
} }
@ -967,8 +965,8 @@ void out_daap_playlistitems(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
char *pe = NULL; char *pe = NULL;
int mtco; int mtco;
if(_ppi->ws_getvar(pwsc,"meta")) { if(pi_ws_getvar(pwsc,"meta")) {
ppi->meta = daap_encode_meta(_ppi->ws_getvar(pwsc,"meta")); ppi->meta = daap_encode_meta(pi_ws_getvar(pwsc,"meta"));
} else { } else {
ppi->meta = ((1ll << metaItemId) | ppi->meta = ((1ll << metaItemId) |
(1ll << metaItemName) | (1ll << metaItemName) |
@ -980,21 +978,21 @@ void out_daap_playlistitems(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
ppi->dq.query_type = QUERY_TYPE_ITEMS; ppi->dq.query_type = QUERY_TYPE_ITEMS;
ppi->dq.playlist_id = atoi(ppi->uri_sections[3]); ppi->dq.playlist_id = atoi(ppi->uri_sections[3]);
if(_ppi->db_enum_start(&pe,&ppi->dq)) { if(pi_db_enum_start(&pe,&ppi->dq)) {
_ppi->log(E_LOG,"Could not start enum: %s\n",pe); pi_log(E_LOG,"Could not start enum: %s\n",pe);
out_daap_error(pwsc,ppi,"apso",pe); out_daap_error(pwsc,ppi,"apso",pe);
if(pe) free(pe); if(pe) free(pe);
return; return;
} }
if(daap_enum_size(&pe,ppi,&song_count,&list_length)) { if(daap_enum_size(&pe,ppi,&song_count,&list_length)) {
_ppi->log(E_LOG,"Could not enum size: %s\n",pe); pi_log(E_LOG,"Could not enum size: %s\n",pe);
out_daap_error(pwsc,ppi,"apso",pe); out_daap_error(pwsc,ppi,"apso",pe);
if(pe) free(pe); if(pe) free(pe);
return; return;
} }
_ppi->log(E_DBG,"Item enum: got %d songs, dmap size: %d\n",song_count,list_length); pi_log(E_DBG,"Item enum: got %d songs, dmap size: %d\n",song_count,list_length);
mtco = song_count; mtco = song_count;
if(ppi->dq.offset || ppi->dq.limit) if(ppi->dq.offset || ppi->dq.limit)
@ -1013,15 +1011,15 @@ void out_daap_playlistitems(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
/* FIXME: Error checking */ /* FIXME: Error checking */
while((daap_enum_fetch(NULL,ppi,&list_length,&block)==0) && while((daap_enum_fetch(NULL,ppi,&list_length,&block)==0) &&
(list_length)) { (list_length)) {
_ppi->log(E_SPAM,"Got block of size %d\n",list_length); pi_log(E_SPAM,"Got block of size %d\n",list_length);
out_daap_output_write(pwsc,ppi,block,list_length); out_daap_output_write(pwsc,ppi,block,list_length);
free(block); free(block);
} }
_ppi->log(E_DBG,"Done enumerating.\n"); pi_log(E_DBG,"Done enumerating.\n");
_ppi->db_enum_end(NULL); pi_db_enum_end(NULL);
_ppi->db_enum_dispose(NULL,&ppi->dq); pi_db_enum_dispose(NULL,&ppi->dq);
out_daap_output_end(pwsc,ppi); out_daap_output_end(pwsc,ppi);
return; return;
@ -1042,7 +1040,7 @@ void out_daap_browse(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
which_field = 3; which_field = 3;
} }
_ppi->log(E_DBG,"Browsing by %s (field %d)\n", pi_log(E_DBG,"Browsing by %s (field %d)\n",
ppi->uri_sections[which_field],which_field); ppi->uri_sections[which_field],which_field);
ppi->dq.query_type = QUERY_TYPE_DISTINCT; ppi->dq.query_type = QUERY_TYPE_DISTINCT;
@ -1062,25 +1060,25 @@ void out_daap_browse(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
response_type = "abcp"; response_type = "abcp";
ppi->dq.distinct_field = "composer"; ppi->dq.distinct_field = "composer";
} else { } else {
_ppi->log(E_WARN,"Invalid browse request type %s\n",ppi->uri_sections[3]); pi_log(E_WARN,"Invalid browse request type %s\n",ppi->uri_sections[3]);
out_daap_error(pwsc,ppi,"abro","Invalid browse type"); out_daap_error(pwsc,ppi,"abro","Invalid browse type");
_ppi->config_set_status(pwsc,ppi->session_id,NULL); pi_config_set_status(pwsc,ppi->session_id,NULL);
return; return;
} }
if(_ppi->db_enum_start(&pe,&ppi->dq)) { if(pi_db_enum_start(&pe,&ppi->dq)) {
_ppi->log(E_LOG,"Could not start enum: %s\n",pe); pi_log(E_LOG,"Could not start enum: %s\n",pe);
out_daap_error(pwsc,ppi,"abro",pe); out_daap_error(pwsc,ppi,"abro",pe);
if(pe) free(pe); if(pe) free(pe);
return; return;
} }
_ppi->log(E_DBG,"Getting enum size.\n"); pi_log(E_DBG,"Getting enum size.\n");
/* FIXME: Error handling */ /* FIXME: Error handling */
daap_enum_size(NULL,ppi,&item_count,&list_length); daap_enum_size(NULL,ppi,&item_count,&list_length);
_ppi->log(E_DBG,"Item enum: got %d items, dmap size: %d\n", pi_log(E_DBG,"Item enum: got %d items, dmap size: %d\n",
item_count,list_length); item_count,list_length);
mtco = item_count; mtco = item_count;
@ -1099,15 +1097,15 @@ void out_daap_browse(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
while((daap_enum_fetch(NULL,ppi,&list_length,&block)==0) && while((daap_enum_fetch(NULL,ppi,&list_length,&block)==0) &&
(list_length)) (list_length))
{ {
_ppi->log(E_SPAM,"Got block of size %d\n",list_length); pi_log(E_SPAM,"Got block of size %d\n",list_length);
out_daap_output_write(pwsc,ppi,block,list_length); out_daap_output_write(pwsc,ppi,block,list_length);
free(block); free(block);
} }
_ppi->log(E_DBG,"Done enumerating\n"); pi_log(E_DBG,"Done enumerating\n");
_ppi->db_enum_end(NULL); pi_db_enum_end(NULL);
_ppi->db_enum_dispose(NULL,&ppi->dq); pi_db_enum_dispose(NULL,&ppi->dq);
out_daap_output_end(pwsc,ppi); out_daap_output_end(pwsc,ppi);
return; return;
@ -1123,8 +1121,8 @@ void out_daap_playlists(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
int mtco; int mtco;
/* currently, this is ignored for playlist queries */ /* currently, this is ignored for playlist queries */
if(_ppi->ws_getvar(pwsc,"meta")) { if(pi_ws_getvar(pwsc,"meta")) {
ppi->meta = daap_encode_meta(_ppi->ws_getvar(pwsc,"meta")); ppi->meta = daap_encode_meta(pi_ws_getvar(pwsc,"meta"));
} else { } else {
ppi->meta = ((1ll << metaItemId) | ppi->meta = ((1ll << metaItemId) |
(1ll << metaItemName) | (1ll << metaItemName) |
@ -1135,21 +1133,21 @@ void out_daap_playlists(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
ppi->dq.query_type = QUERY_TYPE_PLAYLISTS; ppi->dq.query_type = QUERY_TYPE_PLAYLISTS;
if(_ppi->db_enum_start(&pe,&ppi->dq)) { if(pi_db_enum_start(&pe,&ppi->dq)) {
_ppi->log(E_LOG,"Could not start enum: %s\n",pe); pi_log(E_LOG,"Could not start enum: %s\n",pe);
out_daap_error(pwsc,ppi,"aply",pe); out_daap_error(pwsc,ppi,"aply",pe);
if(pe) free(pe); if(pe) free(pe);
return; return;
} }
if(daap_enum_size(NULL,ppi,&pl_count,&list_length)) { if(daap_enum_size(NULL,ppi,&pl_count,&list_length)) {
_ppi->log(E_LOG,"error in enumerating size: %s\n",pe); pi_log(E_LOG,"error in enumerating size: %s\n",pe);
out_daap_error(pwsc,ppi,"aply",pe); out_daap_error(pwsc,ppi,"aply",pe);
if(pe) free(pe); if(pe) free(pe);
return; return;
} }
_ppi->log(E_DBG,"Item enum: got %d playlists, dmap size: %d\n",pl_count,list_length); pi_log(E_DBG,"Item enum: got %d playlists, dmap size: %d\n",pl_count,list_length);
mtco = pl_count; mtco = pl_count;
if((ppi->dq.offset) || (ppi->dq.limit)) if((ppi->dq.offset) || (ppi->dq.limit))
@ -1169,15 +1167,15 @@ void out_daap_playlists(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
while((daap_enum_fetch(NULL,ppi,&list_length,&block)==0) && while((daap_enum_fetch(NULL,ppi,&list_length,&block)==0) &&
(list_length)) (list_length))
{ {
_ppi->log(E_SPAM,"Got block of size %d\n",list_length); pi_log(E_SPAM,"Got block of size %d\n",list_length);
out_daap_output_write(pwsc,ppi,block,list_length); out_daap_output_write(pwsc,ppi,block,list_length);
free(block); free(block);
} }
_ppi->log(E_DBG,"Done enumerating.\n"); pi_log(E_DBG,"Done enumerating.\n");
_ppi->db_enum_end(NULL); pi_db_enum_end(NULL);
_ppi->db_enum_dispose(NULL,&ppi->dq); pi_db_enum_dispose(NULL,&ppi->dq);
out_daap_output_end(pwsc,ppi); out_daap_output_end(pwsc,ppi);
return; return;
@ -1192,16 +1190,16 @@ void out_daap_items(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
char *pe = NULL; char *pe = NULL;
int mtco; int mtco;
if(_ppi->ws_getvar(pwsc,"meta")) { if(pi_ws_getvar(pwsc,"meta")) {
ppi->meta = daap_encode_meta(_ppi->ws_getvar(pwsc,"meta")); ppi->meta = daap_encode_meta(pi_ws_getvar(pwsc,"meta"));
} else { } else {
ppi->meta = (MetaField_t) -1ll; ppi->meta = (MetaField_t) -1ll;
} }
ppi->dq.query_type = QUERY_TYPE_ITEMS; ppi->dq.query_type = QUERY_TYPE_ITEMS;
if(_ppi->db_enum_start(&pe,&ppi->dq)) { if(pi_db_enum_start(&pe,&ppi->dq)) {
_ppi->log(E_LOG,"Could not start enum: %s\n",pe); pi_log(E_LOG,"Could not start enum: %s\n",pe);
out_daap_error(pwsc,ppi,"adbs",pe); out_daap_error(pwsc,ppi,"adbs",pe);
if(pe) free(pe); if(pe) free(pe);
return; return;
@ -1209,13 +1207,13 @@ void out_daap_items(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
/* FIXME: Error handling */ /* FIXME: Error handling */
if(daap_enum_size(&pe,ppi,&song_count,&list_length)) { if(daap_enum_size(&pe,ppi,&song_count,&list_length)) {
_ppi->log(E_LOG,"Error getting dmap size: %s\n",pe); pi_log(E_LOG,"Error getting dmap size: %s\n",pe);
out_daap_error(pwsc,ppi,"adbs",pe); out_daap_error(pwsc,ppi,"adbs",pe);
if(pe) free(pe); if(pe) free(pe);
return; return;
} }
_ppi->log(E_DBG,"Item enum: got %d songs, dmap size: %d\n",song_count, pi_log(E_DBG,"Item enum: got %d songs, dmap size: %d\n",song_count,
list_length); list_length);
mtco = song_count; mtco = song_count;
@ -1235,13 +1233,13 @@ void out_daap_items(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
/* FIXME: check errors */ /* FIXME: check errors */
while((daap_enum_fetch(NULL,ppi,&list_length,&block)==0) && while((daap_enum_fetch(NULL,ppi,&list_length,&block)==0) &&
(list_length)) { (list_length)) {
_ppi->log(E_SPAM,"Got block of size %d\n",list_length); pi_log(E_SPAM,"Got block of size %d\n",list_length);
out_daap_output_write(pwsc,ppi,block,list_length); out_daap_output_write(pwsc,ppi,block,list_length);
free(block); free(block);
} }
_ppi->log(E_DBG,"Done enumerating.\n"); pi_log(E_DBG,"Done enumerating.\n");
_ppi->db_enum_end(NULL); pi_db_enum_end(NULL);
_ppi->db_enum_dispose(NULL,&ppi->dq); pi_db_enum_dispose(NULL,&ppi->dq);
out_daap_output_end(pwsc,ppi); out_daap_output_end(pwsc,ppi);
return; return;
} }
@ -1250,18 +1248,18 @@ void out_daap_update(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
unsigned char update_response[32]; unsigned char update_response[32];
unsigned char *current=update_response; unsigned char *current=update_response;
_ppi->log(E_DBG,"Preparing to send update response\n"); pi_log(E_DBG,"Preparing to send update response\n");
_ppi->config_set_status(pwsc,ppi->session_id,"Waiting for DB update"); pi_config_set_status(pwsc,ppi->session_id,"Waiting for DB update");
if(!_ppi->db_wait_update(pwsc)) { if(!pi_db_wait_update(pwsc)) {
_ppi->log(E_DBG,"Update session stopped\n"); pi_log(E_DBG,"Update session stopped\n");
return; return;
} }
/* otherwise, send the info about this version */ /* otherwise, send the info about this version */
current += dmap_add_container(current,"mupd",24); current += dmap_add_container(current,"mupd",24);
current += dmap_add_int(current,"mstt",200); /* 12 */ current += dmap_add_int(current,"mstt",200); /* 12 */
current += dmap_add_int(current,"musr",_ppi->db_revision()); /* 12 */ current += dmap_add_int(current,"musr",pi_db_revision()); /* 12 */
out_daap_output_start(pwsc,ppi,32); out_daap_output_start(pwsc,ppi,32);
out_daap_output_write(pwsc,ppi,update_response,32); out_daap_output_write(pwsc,ppi,update_response,32);
@ -1279,7 +1277,7 @@ void out_daap_dbinfo(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
int servername_size; int servername_size;
servername_size = sizeof(servername); servername_size = sizeof(servername);
_ppi->server_name(servername,&servername_size); pi_server_name(servername,&servername_size);
namelen=(int) strlen(servername); namelen=(int) strlen(servername);
@ -1293,9 +1291,9 @@ void out_daap_dbinfo(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
current += dmap_add_int(current,"miid",1); /* 12 */ current += dmap_add_int(current,"miid",1); /* 12 */
current += dmap_add_long(current,"mper",1); /* 16 */ current += dmap_add_long(current,"mper",1); /* 16 */
current += dmap_add_string(current,"minm",servername); /* 8 + namelen */ current += dmap_add_string(current,"minm",servername); /* 8 + namelen */
count = _ppi->db_count_items(COUNT_SONGS); count = pi_db_count_items(COUNT_SONGS);
current += dmap_add_int(current,"mimc",count); /* 12 */ current += dmap_add_int(current,"mimc",count); /* 12 */
count = _ppi->db_count_items(COUNT_PLAYLISTS); count = pi_db_count_items(COUNT_PLAYLISTS);
current += dmap_add_int(current,"mctc",count); /* 12 */ current += dmap_add_int(current,"mctc",count); /* 12 */
out_daap_output_start(pwsc,ppi,129+namelen); out_daap_output_start(pwsc,ppi,129+namelen);
@ -1306,8 +1304,8 @@ void out_daap_dbinfo(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
} }
void out_daap_logout(WS_CONNINFO *pwsc, PRIVINFO *ppi) { void out_daap_logout(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
_ppi->config_set_status(pwsc,ppi->session_id,NULL); pi_config_set_status(pwsc,ppi->session_id,NULL);
_ppi->ws_returnerror(pwsc,204,"Logout Successful"); pi_ws_returnerror(pwsc,204,"Logout Successful");
} }
@ -1368,9 +1366,9 @@ void out_daap_content_codes(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
int out_daap_conf_isset(char *section, char *key) { int out_daap_conf_isset(char *section, char *key) {
char *value; char *value;
value = _ppi->conf_alloc_string(section,key,NULL); value = pi_conf_alloc_string(section,key,NULL);
if(value) { if(value) {
_ppi->conf_dispose_string(value); pi_conf_dispose_string(value);
return TRUE; return TRUE;
} }
@ -1389,7 +1387,7 @@ void out_daap_server_info(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
int supports_update=0; int supports_update=0;
size = sizeof(servername); size = sizeof(servername);
_ppi->server_name(servername,&size); pi_server_name(servername,&size);
// supports_update = conf_get_int("daap","supports_update",1); // supports_update = conf_get_int("daap","supports_update",1);
actual_length=139 + (int) strlen(servername); actual_length=139 + (int) strlen(servername);
@ -1397,10 +1395,10 @@ void out_daap_server_info(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
actual_length -= 9; actual_length -= 9;
if(actual_length > sizeof(server_info)) { if(actual_length > sizeof(server_info)) {
_ppi->log(E_FATAL,"Server name too long.\n"); pi_log(E_FATAL,"Server name too long.\n");
} }
client_version=_ppi->ws_getrequestheader(pwsc,"Client-DAAP-Version"); client_version=pi_ws_getrequestheader(pwsc,"Client-DAAP-Version");
current += dmap_add_container(current,"msrv",actual_length - 8); current += dmap_add_container(current,"msrv",actual_length - 8);
current += dmap_add_int(current,"mstt",200); /* 12 */ current += dmap_add_int(current,"mstt",200); /* 12 */
@ -1453,7 +1451,7 @@ void out_daap_error(WS_CONNINFO *pwsc, PRIVINFO *ppi, char *container, char *err
block = (unsigned char *)malloc(len); block = (unsigned char *)malloc(len);
if(!block) if(!block)
_ppi->log(E_FATAL,"Malloc error\n"); pi_log(E_FATAL,"Malloc error\n");
current = block; current = block;
current += dmap_add_container(current,container,len - 8); current += dmap_add_container(current,container,len - 8);
@ -1466,7 +1464,7 @@ void out_daap_error(WS_CONNINFO *pwsc, PRIVINFO *ppi, char *container, char *err
free(block); free(block);
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
} }

View File

@ -92,7 +92,5 @@ typedef struct tag_daap_privinfo {
WS_CONNINFO *pwsc; WS_CONNINFO *pwsc;
} PRIVINFO; } PRIVINFO;
extern PLUGIN_INPUT_FN *_ppi;
#endif /* _OUT_DAAP_H_ */ #endif /* _OUT_DAAP_H_ */

View File

@ -27,7 +27,7 @@ typedef struct tag_rsp_privinfo {
} PRIVINFO; } PRIVINFO;
/* Forwards */ /* Forwards */
PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *); PLUGIN_INFO *plugin_info(void);
void plugin_handler(WS_CONNINFO *pwsc); void plugin_handler(WS_CONNINFO *pwsc);
int plugin_can_handle(WS_CONNINFO *pwsc); int plugin_can_handle(WS_CONNINFO *pwsc);
int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password); int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password);
@ -45,7 +45,6 @@ PLUGIN_REND_INFO _pri[] = {
{ NULL, NULL } { NULL, NULL }
}; };
PLUGIN_INPUT_FN *_ppi;
PLUGIN_INFO _pi = { PLUGIN_INFO _pi = {
PLUGIN_VERSION, /* version */ PLUGIN_VERSION, /* version */
PLUGIN_OUTPUT, /* type */ PLUGIN_OUTPUT, /* type */
@ -150,8 +149,7 @@ FIELDSPEC rsp_fields[] = {
/** /**
* return info about this plugin module * return info about this plugin module
*/ */
PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *ppi) { PLUGIN_INFO *plugin_info(void) {
_ppi = ppi;
return &_pi; return &_pi;
} }
@ -159,8 +157,8 @@ PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *ppi) {
* see if the plugin should handle this request * see if the plugin should handle this request
*/ */
int plugin_can_handle(WS_CONNINFO *pwsc) { int plugin_can_handle(WS_CONNINFO *pwsc) {
_ppi->log(E_DBG,"Checking url %s\n",_ppi->ws_uri(pwsc)); pi_log(E_DBG,"Checking url %s\n",pi_ws_uri(pwsc));
if(strncasecmp(_ppi->ws_uri(pwsc),"/rsp/",5) == 0) if(strncasecmp(pi_ws_uri(pwsc),"/rsp/",5) == 0)
return TRUE; return TRUE;
return FALSE; return FALSE;
} }
@ -170,7 +168,7 @@ int plugin_can_handle(WS_CONNINFO *pwsc) {
* works. * works.
*/ */
int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password) { int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password) {
return _ppi->ws_matchesrole(pwsc,username,password,"user"); return pi_ws_matchesrole(pwsc,username,password,"user");
} }
/** /**
@ -183,39 +181,39 @@ void plugin_handler(WS_CONNINFO *pwsc) {
int index, part; int index, part;
int found; int found;
_ppi->log(E_DBG,"Getting uri...\n"); pi_log(E_DBG,"Getting uri...\n");
string = _ppi->ws_uri(pwsc); string = pi_ws_uri(pwsc);
string++; string++;
_ppi->log(E_DBG,"Mallocing privinfo...\n"); pi_log(E_DBG,"Mallocing privinfo...\n");
ppi = (PRIVINFO *)malloc(sizeof(PRIVINFO)); ppi = (PRIVINFO *)malloc(sizeof(PRIVINFO));
if(ppi) { if(ppi) {
memset(ppi,0,sizeof(PRIVINFO)); memset(ppi,0,sizeof(PRIVINFO));
} }
if(!ppi) { if(!ppi) {
_ppi->ws_returnerror(pwsc,500,"Malloc error in plugin_handler"); pi_ws_returnerror(pwsc,500,"Malloc error in plugin_handler");
return; return;
} }
memset((void*)&ppi->dq,0,sizeof(DB_QUERY)); memset((void*)&ppi->dq,0,sizeof(DB_QUERY));
_ppi->log(E_DBG,"Tokenizing url\n"); pi_log(E_DBG,"Tokenizing url\n");
while((ppi->uri_count < 10) && (token=strtok_r(string,"/",&save))) { while((ppi->uri_count < 10) && (token=strtok_r(string,"/",&save))) {
string=NULL; string=NULL;
ppi->uri_sections[ppi->uri_count++] = token; ppi->uri_sections[ppi->uri_count++] = token;
} }
elements = sizeof(rsp_uri_map) / sizeof(PLUGIN_RESPONSE); elements = sizeof(rsp_uri_map) / sizeof(PLUGIN_RESPONSE);
_ppi->log(E_DBG,"Found %d elements\n",elements); pi_log(E_DBG,"Found %d elements\n",elements);
index = 0; index = 0;
found = 0; found = 0;
while((!found) && (index < elements)) { while((!found) && (index < elements)) {
/* test this set */ /* test this set */
_ppi->log(E_DBG,"Checking reponse %d\n",index); pi_log(E_DBG,"Checking reponse %d\n",index);
part=0; part=0;
while(part < 10) { while(part < 10) {
if((rsp_uri_map[index].uri[part]) && (!ppi->uri_sections[part])) if((rsp_uri_map[index].uri[part]) && (!ppi->uri_sections[part]))
@ -234,7 +232,7 @@ void plugin_handler(WS_CONNINFO *pwsc) {
if(part == 10) { if(part == 10) {
found = 1; found = 1;
_ppi->log(E_DBG,"Found it! Index: %d\n",index); pi_log(E_DBG,"Found it! Index: %d\n",index);
} else { } else {
index++; index++;
} }
@ -242,13 +240,13 @@ void plugin_handler(WS_CONNINFO *pwsc) {
if(found) { if(found) {
rsp_uri_map[index].dispatch(pwsc, ppi); rsp_uri_map[index].dispatch(pwsc, ppi);
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
free(ppi); free(ppi);
return; return;
} }
rsp_error(pwsc, ppi, 1, "Bad path"); rsp_error(pwsc, ppi, 1, "Bad path");
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
free(ppi); free(ppi);
return; return;
} }
@ -261,7 +259,7 @@ void rsp_info(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
char servername[256]; char servername[256];
int size; int size;
_ppi->log(E_DBG,"Starting rsp_info\n"); pi_log(E_DBG,"Starting rsp_info\n");
pxml = xml_init(pwsc,1); pxml = xml_init(pwsc,1);
@ -275,13 +273,13 @@ void rsp_info(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
/* info block */ /* info block */
xml_push(pxml,"info"); xml_push(pxml,"info");
xml_output(pxml,"count","%d",_ppi->db_count()); xml_output(pxml,"count","%d",pi_db_count());
xml_output(pxml,"rsp-version","%s",RSP_VERSION); xml_output(pxml,"rsp-version","%s",RSP_VERSION);
xml_output(pxml,"server-version","%s",_ppi->server_ver()); xml_output(pxml,"server-version","%s",pi_server_ver());
size = sizeof(servername); size = sizeof(servername);
_ppi->server_name(servername,&size); pi_server_name(servername,&size);
xml_output(pxml,"name","%s",servername); xml_output(pxml,"name","%s",servername);
xml_pop(pxml); /* info */ xml_pop(pxml); /* info */
@ -303,9 +301,9 @@ void rsp_db(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
ppi->dq.query_type = QUERY_TYPE_PLAYLISTS; ppi->dq.query_type = QUERY_TYPE_PLAYLISTS;
if((err=_ppi->db_enum_start(&pe,&ppi->dq)) != 0) { if((err=pi_db_enum_start(&pe,&ppi->dq)) != 0) {
rsp_error(pwsc, ppi, err | E_DB, pe); rsp_error(pwsc, ppi, err | E_DB, pe);
_ppi->db_enum_dispose(NULL,&ppi->dq); pi_db_enum_dispose(NULL,&ppi->dq);
return; return;
} }
@ -321,7 +319,7 @@ void rsp_db(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
xml_push(pxml,"playlists"); xml_push(pxml,"playlists");
while((_ppi->db_enum_fetch_row(NULL,&row,&ppi->dq) == 0) && (row)) { while((pi_db_enum_fetch_row(NULL,&row,&ppi->dq) == 0) && (row)) {
xml_push(pxml,"playlist"); xml_push(pxml,"playlist");
rowindex=0; rowindex=0;
while(rsp_playlist_fields[rowindex].name) { while(rsp_playlist_fields[rowindex].name) {
@ -334,8 +332,8 @@ void rsp_db(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
xml_pop(pxml); /* playlist */ xml_pop(pxml); /* playlist */
} }
_ppi->db_enum_end(NULL); pi_db_enum_end(NULL);
_ppi->db_enum_dispose(NULL,&ppi->dq); pi_db_enum_dispose(NULL,&ppi->dq);
xml_pop(pxml); /* playlists */ xml_pop(pxml); /* playlists */
xml_pop(pxml); /* response */ xml_pop(pxml); /* response */
@ -359,17 +357,17 @@ void rsp_playlist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
unsigned int samplerate; unsigned int samplerate;
int done = 0; int done = 0;
ppi->dq.filter = _ppi->ws_getvar(pwsc,"query"); ppi->dq.filter = pi_ws_getvar(pwsc,"query");
ppi->dq.filter_type = FILTER_TYPE_FIREFLY; ppi->dq.filter_type = FILTER_TYPE_FIREFLY;
if(_ppi->ws_getvar(pwsc,"offset")) { if(pi_ws_getvar(pwsc,"offset")) {
ppi->dq.offset = atoi(_ppi->ws_getvar(pwsc,"offset")); ppi->dq.offset = atoi(pi_ws_getvar(pwsc,"offset"));
} }
if(_ppi->ws_getvar(pwsc,"limit")) { if(pi_ws_getvar(pwsc,"limit")) {
ppi->dq.limit = atoi(_ppi->ws_getvar(pwsc,"limit")); ppi->dq.limit = atoi(pi_ws_getvar(pwsc,"limit"));
} }
browse_type = _ppi->ws_getvar(pwsc,"type"); browse_type = pi_ws_getvar(pwsc,"type");
type = F_FULL; type = F_FULL;
if(browse_type) { if(browse_type) {
@ -385,9 +383,9 @@ void rsp_playlist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
ppi->dq.query_type = QUERY_TYPE_ITEMS; ppi->dq.query_type = QUERY_TYPE_ITEMS;
ppi->dq.playlist_id = atoi(ppi->uri_sections[2]); ppi->dq.playlist_id = atoi(ppi->uri_sections[2]);
if((err=_ppi->db_enum_start(&pe,&ppi->dq)) != 0) { if((err=pi_db_enum_start(&pe,&ppi->dq)) != 0) {
rsp_error(pwsc, ppi, err | E_DB, pe); rsp_error(pwsc, ppi, err | E_DB, pe);
_ppi->db_enum_dispose(NULL,&ppi->dq); pi_db_enum_dispose(NULL,&ppi->dq);
free(pe); free(pe);
return; return;
} }
@ -412,15 +410,15 @@ void rsp_playlist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
xml_push(pxml,"items"); xml_push(pxml,"items");
while((!done) && (_ppi->db_enum_fetch_row(NULL,&row,&ppi->dq) == 0) && while((!done) && (pi_db_enum_fetch_row(NULL,&row,&ppi->dq) == 0) &&
(row)) { (row)) {
xml_push(pxml,"item"); xml_push(pxml,"item");
rowindex=0; rowindex=0;
transcode = 0; transcode = 0;
transcode = _ppi->should_transcode(pwsc,row[37]); transcode = pi_should_transcode(pwsc,row[37]);
_ppi->log(E_DBG,"Transcode: %d, %s: %s\n",transcode,row[37],row[2]); pi_log(E_DBG,"Transcode: %d, %s: %s\n",transcode,row[37],row[2]);
while(rsp_fields[rowindex].name) { while(rsp_fields[rowindex].name) {
if((rsp_fields[rowindex].flags & type) && if((rsp_fields[rowindex].flags & type) &&
@ -466,7 +464,7 @@ void rsp_playlist(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
xml_pop(pxml); /* item */ xml_pop(pxml); /* item */
} }
_ppi->db_enum_end(NULL); pi_db_enum_end(NULL);
xml_pop(pxml); /* items */ xml_pop(pxml); /* items */
xml_pop(pxml); /* response */ xml_pop(pxml); /* response */
@ -483,22 +481,22 @@ void rsp_browse(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
/* this might fail if an unsupported browse type */ /* this might fail if an unsupported browse type */
ppi->dq.query_type = QUERY_TYPE_DISTINCT; ppi->dq.query_type = QUERY_TYPE_DISTINCT;
ppi->dq.distinct_field = ppi->uri_sections[3]; ppi->dq.distinct_field = ppi->uri_sections[3];
ppi->dq.filter = _ppi->ws_getvar(pwsc,"query"); ppi->dq.filter = pi_ws_getvar(pwsc,"query");
ppi->dq.filter_type = FILTER_TYPE_FIREFLY; ppi->dq.filter_type = FILTER_TYPE_FIREFLY;
if(_ppi->ws_getvar(pwsc,"offset")) { if(pi_ws_getvar(pwsc,"offset")) {
ppi->dq.offset = atoi(_ppi->ws_getvar(pwsc,"offset")); ppi->dq.offset = atoi(pi_ws_getvar(pwsc,"offset"));
} }
if(_ppi->ws_getvar(pwsc,"limit")) { if(pi_ws_getvar(pwsc,"limit")) {
ppi->dq.limit = atoi(_ppi->ws_getvar(pwsc,"limit")); ppi->dq.limit = atoi(pi_ws_getvar(pwsc,"limit"));
} }
ppi->dq.playlist_id = atoi(ppi->uri_sections[2]); ppi->dq.playlist_id = atoi(ppi->uri_sections[2]);
if((err=_ppi->db_enum_start(&pe,&ppi->dq)) != 0) { if((err=pi_db_enum_start(&pe,&ppi->dq)) != 0) {
rsp_error(pwsc, ppi, err | E_DB, pe); rsp_error(pwsc, ppi, err | E_DB, pe);
_ppi->db_enum_dispose(NULL,&ppi->dq); pi_db_enum_dispose(NULL,&ppi->dq);
return; return;
} }
@ -522,12 +520,12 @@ void rsp_browse(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
xml_push(pxml,"items"); xml_push(pxml,"items");
while((_ppi->db_enum_fetch_row(NULL,&row,&ppi->dq) == 0) && (row)) { while((pi_db_enum_fetch_row(NULL,&row,&ppi->dq) == 0) && (row)) {
xml_output(pxml,"item","%s",row[0]); xml_output(pxml,"item","%s",row[0]);
} }
_ppi->db_enum_end(NULL); pi_db_enum_end(NULL);
_ppi->db_enum_dispose(NULL,&ppi->dq); pi_db_enum_dispose(NULL,&ppi->dq);
xml_pop(pxml); /* items */ xml_pop(pxml); /* items */
xml_pop(pxml); /* response */ xml_pop(pxml); /* response */
@ -535,7 +533,7 @@ void rsp_browse(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
} }
void rsp_stream(WS_CONNINFO *pwsc, PRIVINFO *ppi) { void rsp_stream(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
_ppi->stream(pwsc, ppi->uri_sections[2]); pi_stream(pwsc, ppi->uri_sections[2]);
return; return;
} }
@ -552,6 +550,6 @@ void rsp_error(WS_CONNINFO *pwsc, PRIVINFO *ppi, int eno, char *estr) {
xml_pop(pxml); /* status */ xml_pop(pxml); /* status */
xml_pop(pxml); /* response */ xml_pop(pxml); /* response */
xml_deinit(pxml); xml_deinit(pxml);
_ppi->ws_will_close(pwsc); pi_ws_will_close(pwsc);
} }

View File

@ -194,7 +194,7 @@ int ssc_ffmpeg_open(void *vp, MP3FILE *pmp3) {
handle->first_frame = 1; handle->first_frame = 1;
handle->raw=0; handle->raw=0;
_ppi->log(E_DBG,"opening %s\n",file); pi_log(E_DBG,"opening %s\n",file);
if(strcasecmp(codec,"flac") == 0) { if(strcasecmp(codec,"flac") == 0) {
handle->raw=1; handle->raw=1;
@ -211,7 +211,7 @@ int ssc_ffmpeg_open(void *vp, MP3FILE *pmp3) {
handle->samples = (uint32_t)pmp3->sample_count; handle->samples = (uint32_t)pmp3->sample_count;
handle->sample_rate = pmp3->samplerate; handle->sample_rate = pmp3->samplerate;
_ppi->log(E_DBG,"opening file raw\n"); pi_log(E_DBG,"opening file raw\n");
handle->pCodec = avcodec_find_decoder(id); handle->pCodec = avcodec_find_decoder(id);
if(!handle->pCodec) { if(!handle->pCodec) {
handle->errnum = SSC_FFMPEG_E_BADCODEC; handle->errnum = SSC_FFMPEG_E_BADCODEC;
@ -235,7 +235,7 @@ int ssc_ffmpeg_open(void *vp, MP3FILE *pmp3) {
handle->fin = fopen(file,"rb"); handle->fin = fopen(file,"rb");
#endif #endif
if(!handle->fin) { if(!handle->fin) {
_ppi->log(E_DBG,"could not open file\n"); pi_log(E_DBG,"could not open file\n");
handle->errnum = SSC_FFMPEG_E_FILEOPEN; handle->errnum = SSC_FFMPEG_E_FILEOPEN;
return FALSE; return FALSE;
} }
@ -243,9 +243,9 @@ int ssc_ffmpeg_open(void *vp, MP3FILE *pmp3) {
/* check to see if there is an id3 tag there... if so, skip it. */ /* check to see if there is an id3 tag there... if so, skip it. */
if(fread((unsigned char *)&id3,1,sizeof(id3),handle->fin) != sizeof(id3)) { if(fread((unsigned char *)&id3,1,sizeof(id3),handle->fin) != sizeof(id3)) {
if(ferror(handle->fin)) { if(ferror(handle->fin)) {
_ppi->log(E_LOG,"Error reading file: %s\n",file); pi_log(E_LOG,"Error reading file: %s\n",file);
} else { } else {
_ppi->log(E_LOG,"Short file: %s\n",file); pi_log(E_LOG,"Short file: %s\n",file);
} }
handle->errnum = SSC_FFMPEG_E_FILEOPEN; handle->errnum = SSC_FFMPEG_E_FILEOPEN;
fclose(handle->fin); fclose(handle->fin);
@ -255,11 +255,11 @@ int ssc_ffmpeg_open(void *vp, MP3FILE *pmp3) {
if(strncmp(id3.id,"ID3",3)==0) { if(strncmp(id3.id,"ID3",3)==0) {
/* found an ID3 header... */ /* found an ID3 header... */
_ppi->log(E_DBG,"Found ID3 header\n"); pi_log(E_DBG,"Found ID3 header\n");
size = (id3.size[0] << 21 | id3.size[1] << 14 | size = (id3.size[0] << 21 | id3.size[1] << 14 |
id3.size[2] << 7 | id3.size[3]); id3.size[2] << 7 | id3.size[3]);
fseek(handle->fin,size + sizeof(SCAN_ID3HEADER),SEEK_SET); fseek(handle->fin,size + sizeof(SCAN_ID3HEADER),SEEK_SET);
_ppi->log(E_DBG,"Header length: %d\n",size); pi_log(E_DBG,"Header length: %d\n",size);
} else { } else {
fseek(handle->fin,0,SEEK_SET); fseek(handle->fin,0,SEEK_SET);
} }
@ -267,7 +267,7 @@ int ssc_ffmpeg_open(void *vp, MP3FILE *pmp3) {
return TRUE; return TRUE;
} }
_ppi->log(E_DBG,"opening file with format\n"); pi_log(E_DBG,"opening file with format\n");
if(av_open_input_file(&handle->pFmtCtx,file,handle->pFormat,0,NULL) < 0) { if(av_open_input_file(&handle->pFmtCtx,file,handle->pFormat,0,NULL) < 0) {
handle->errnum = SSC_FFMPEG_E_FILEOPEN; handle->errnum = SSC_FFMPEG_E_FILEOPEN;
return FALSE; return FALSE;
@ -501,10 +501,10 @@ int ssc_ffmpeg_read(void *vp, char *buffer, int len) {
byte_rate = sample_rate * channels * bits_per_sample / 8; byte_rate = sample_rate * channels * bits_per_sample / 8;
block_align = channels * bits_per_sample / 8; block_align = channels * bits_per_sample / 8;
_ppi->log(E_DBG,"Channels.......: %d\n",channels); pi_log(E_DBG,"Channels.......: %d\n",channels);
_ppi->log(E_DBG,"Sample rate....: %d\n",sample_rate); pi_log(E_DBG,"Sample rate....: %d\n",sample_rate);
_ppi->log(E_DBG,"Bits/Sample....: %d\n",bits_per_sample); pi_log(E_DBG,"Bits/Sample....: %d\n",bits_per_sample);
_ppi->log(E_DBG,"Swab...........: %d\n",handle->swab); pi_log(E_DBG,"Swab...........: %d\n",handle->swab);
memcpy(&handle->wav_header[0],"RIFF",4); memcpy(&handle->wav_header[0],"RIFF",4);
_ssc_ffmpeg_le32(&handle->wav_header[4],36 + data_len); _ssc_ffmpeg_le32(&handle->wav_header[4],36 + data_len);

View File

@ -30,7 +30,7 @@ int ssc_script_close(void *vp);
int ssc_script_read(void *vp, char *buffer, int len); int ssc_script_read(void *vp, char *buffer, int len);
char *ssc_script_error(void *vp); char *ssc_script_error(void *vp);
PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *); PLUGIN_INFO *plugin_info(void);
#define infn ((PLUGIN_INPUT_FN *)(_pi.pi)) #define infn ((PLUGIN_INPUT_FN *)(_pi.pi))
@ -44,8 +44,6 @@ PLUGIN_TRANSCODE_FN _ptfn = {
ssc_script_error ssc_script_error
}; };
PLUGIN_INPUT_FN *_ppi;
PLUGIN_INFO _pi = { PLUGIN_INFO _pi = {
PLUGIN_VERSION, /* version */ PLUGIN_VERSION, /* version */
PLUGIN_TRANSCODE, /* type */ PLUGIN_TRANSCODE, /* type */
@ -66,21 +64,19 @@ static char *_ssc_script_program = NULL;
/** /**
* return the plugininfo struct to firefly * return the plugininfo struct to firefly
*/ */
PLUGIN_INFO *plugin_info(PLUGIN_INPUT_FN *ppi) { PLUGIN_INFO *plugin_info(void) {
char *codeclist; char *codeclist;
_ppi = ppi; _ssc_script_program = pi_conf_alloc_string("general","ssc_prog",NULL);
_ssc_script_program = _ppi->conf_alloc_string("general","ssc_prog",NULL);
if(!_ssc_script_program) { if(!_ssc_script_program) {
_ppi->log(E_INF,"No ssc program specified for script transcoder.\n"); pi_log(E_INF,"No ssc program specified for script transcoder.\n");
return NULL; return NULL;
} }
/* FIXME: need an unload function to stop leak */ /* FIXME: need an unload function to stop leak */
codeclist = _ppi->conf_alloc_string("general","ssc_codectypes",NULL); codeclist = pi_conf_alloc_string("general","ssc_codectypes",NULL);
if(!codeclist) { if(!codeclist) {
_ppi->log(E_INF,"No codectypes specified for script transcoder.\n"); pi_log(E_INF,"No codectypes specified for script transcoder.\n");
return NULL; return NULL;
} }
@ -161,7 +157,7 @@ int ssc_script_open(void *vp, MP3FILE *pmp3) {
if(metachars) { if(metachars) {
newpath = (char*)malloc(strlen(file) + metacount + 1); newpath = (char*)malloc(strlen(file) + metacount + 1);
if(!newpath) { if(!newpath) {
_ppi->log(E_FATAL,"ssc_script_open: malloc\n"); pi_log(E_FATAL,"ssc_script_open: malloc\n");
} }
src=file; src=file;
dst=newpath; dst=newpath;
@ -189,7 +185,7 @@ int ssc_script_open(void *vp, MP3FILE *pmp3) {
sprintf(cmd, "%s \"%s\" 0 %lu.%03lu \"%s\"", sprintf(cmd, "%s \"%s\" 0 %lu.%03lu \"%s\"",
_ssc_script_program, newpath, (unsigned long) duration / 1000, _ssc_script_program, newpath, (unsigned long) duration / 1000,
(unsigned long)duration % 1000, (codec && *codec) ? codec : "*"); (unsigned long)duration % 1000, (codec && *codec) ? codec : "*");
_ppi->log(E_INF,"Executing %s\n",cmd); pi_log(E_INF,"Executing %s\n",cmd);
handle->fin = popen(cmd, "r"); handle->fin = popen(cmd, "r");
free(newpath); free(newpath);
free(cmd); /* should really have in-place expanded the path */ free(cmd); /* should really have in-place expanded the path */

View File

@ -46,8 +46,6 @@ struct tag_xmlstruct {
XML_STREAMBUFFER *psb; XML_STREAMBUFFER *psb;
}; };
extern PLUGIN_INPUT_FN *_ppi;
/* Forwards */ /* Forwards */
void xml_get_stats(WS_CONNINFO *pwsc); void xml_get_stats(WS_CONNINFO *pwsc);
void xml_set_config(WS_CONNINFO *pwsc); void xml_set_config(WS_CONNINFO *pwsc);
@ -72,7 +70,7 @@ int xml_write(XMLSTRUCT *pxml, char *fmt, ...) {
if(!result) if(!result)
result = -1; result = -1;
} else { } else {
result=_ppi->ws_writefd(pxml->pwsc,"%s",buffer); result=pi_ws_writefd(pxml->pwsc,"%s",buffer);
} }
return result; return result;
@ -101,14 +99,14 @@ XML_STREAMBUFFER *xml_stream_open(void) {
psb = (XML_STREAMBUFFER*) malloc(sizeof(XML_STREAMBUFFER)); psb = (XML_STREAMBUFFER*) malloc(sizeof(XML_STREAMBUFFER));
if(!psb) { if(!psb) {
_ppi->log(E_FATAL,"xml_stream_open: malloc\n"); pi_log(E_FATAL,"xml_stream_open: malloc\n");
} }
psb->out_buffer = (unsigned char*) malloc(XML_STREAM_BLOCK); psb->out_buffer = (unsigned char*) malloc(XML_STREAM_BLOCK);
psb->in_buffer = (unsigned char*) malloc(XML_STREAM_BLOCK); psb->in_buffer = (unsigned char*) malloc(XML_STREAM_BLOCK);
if((!psb->out_buffer) || (!psb->in_buffer)) { if((!psb->out_buffer) || (!psb->in_buffer)) {
_ppi->log(E_FATAL,"xml_stream_open: malloc\n"); pi_log(E_FATAL,"xml_stream_open: malloc\n");
} }
psb->strm.zalloc = Z_NULL; psb->strm.zalloc = Z_NULL;
@ -146,9 +144,9 @@ int xml_stream_write(XMLSTRUCT *pxml, char *out) {
while(!done) { while(!done) {
result = deflate(&psb->strm, Z_NO_FLUSH); result = deflate(&psb->strm, Z_NO_FLUSH);
if(result != Z_OK) { if(result != Z_OK) {
_ppi->log(E_FATAL,"Error in zlib: %d\n",result); pi_log(E_FATAL,"Error in zlib: %d\n",result);
} }
_ppi->ws_writebinary(pxml->pwsc,(char*)psb->out_buffer, pi_ws_writebinary(pxml->pwsc,(char*)psb->out_buffer,
XML_STREAM_BLOCK-psb->strm.avail_out); XML_STREAM_BLOCK-psb->strm.avail_out);
if(psb->strm.avail_out != 0) { if(psb->strm.avail_out != 0) {
done=1; done=1;
@ -175,14 +173,14 @@ int xml_stream_close(XMLSTRUCT *pxml) {
psb->strm.next_in = psb->in_buffer; psb->strm.next_in = psb->in_buffer;
deflate(&psb->strm,Z_FINISH); deflate(&psb->strm,Z_FINISH);
_ppi->ws_writebinary(pxml->pwsc,(char*)psb->out_buffer, pi_ws_writebinary(pxml->pwsc,(char*)psb->out_buffer,
XML_STREAM_BLOCK - psb->strm.avail_out); XML_STREAM_BLOCK - psb->strm.avail_out);
if(psb->strm.avail_out != 0) if(psb->strm.avail_out != 0)
done=1; done=1;
} }
_ppi->log(E_DBG,"Done sending xml stream\n"); pi_log(E_DBG,"Done sending xml stream\n");
deflateEnd(&psb->strm); deflateEnd(&psb->strm);
if(psb->out_buffer != NULL) if(psb->out_buffer != NULL)
free(psb->out_buffer); free(psb->out_buffer);
@ -208,7 +206,7 @@ XMLSTRUCT *xml_init(WS_CONNINFO *pwsc, int emit_header) {
pxml=(XMLSTRUCT*)malloc(sizeof(XMLSTRUCT)); pxml=(XMLSTRUCT*)malloc(sizeof(XMLSTRUCT));
if(!pxml) { if(!pxml) {
_ppi->log(E_FATAL,"Malloc error\n"); pi_log(E_FATAL,"Malloc error\n");
} }
memset(pxml,0,sizeof(XMLSTRUCT)); memset(pxml,0,sizeof(XMLSTRUCT));
@ -216,27 +214,27 @@ XMLSTRUCT *xml_init(WS_CONNINFO *pwsc, int emit_header) {
pxml->pwsc = pwsc; pxml->pwsc = pwsc;
/* should we compress output? */ /* should we compress output? */
nogzip = _ppi->ws_getvar(pwsc,"nogzip"); nogzip = pi_ws_getvar(pwsc,"nogzip");
accept = _ppi->ws_getrequestheader(pwsc,"accept-encoding"); accept = pi_ws_getrequestheader(pwsc,"accept-encoding");
if((!nogzip) && (accept) && (strcasestr(accept,"gzip"))) { if((!nogzip) && (accept) && (strcasestr(accept,"gzip"))) {
_ppi->log(E_DBG,"Gzipping output\n"); pi_log(E_DBG,"Gzipping output\n");
pxml->psb = xml_stream_open(); pxml->psb = xml_stream_open();
if(pxml->psb) { if(pxml->psb) {
_ppi->ws_addresponseheader(pwsc,"Content-Encoding","gzip"); pi_ws_addresponseheader(pwsc,"Content-Encoding","gzip");
_ppi->ws_addresponseheader(pwsc,"Vary","Accept-Encoding"); pi_ws_addresponseheader(pwsc,"Vary","Accept-Encoding");
_ppi->ws_addresponseheader(pwsc,"Connection","Close"); pi_ws_addresponseheader(pwsc,"Connection","Close");
} }
} }
/* the world would be a wonderful place without ie */ /* the world would be a wonderful place without ie */
_ppi->ws_addresponseheader(pwsc,"Cache-Control","no-cache"); pi_ws_addresponseheader(pwsc,"Cache-Control","no-cache");
_ppi->ws_addresponseheader(pwsc,"Expires","-1"); pi_ws_addresponseheader(pwsc,"Expires","-1");
if(emit_header) { if(emit_header) {
_ppi->ws_addresponseheader(pwsc,"Content-Type","text/xml; charset=utf-8"); pi_ws_addresponseheader(pwsc,"Content-Type","text/xml; charset=utf-8");
_ppi->ws_writefd(pwsc,"HTTP/1.0 200 OK\r\n"); pi_ws_writefd(pwsc,"HTTP/1.0 200 OK\r\n");
_ppi->ws_emitheaders(pwsc); pi_ws_emitheaders(pwsc);
xml_write(pxml,"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"); xml_write(pxml,"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
@ -275,7 +273,7 @@ void xml_pop(XMLSTRUCT *pxml) {
pstack=pxml->stack.next; pstack=pxml->stack.next;
if(!pstack) { if(!pstack) {
_ppi->log(E_LOG,"xml_pop: tried to pop an empty stack\n"); pi_log(E_LOG,"xml_pop: tried to pop an empty stack\n");
return; return;
} }
@ -326,7 +324,7 @@ void xml_deinit(XMLSTRUCT *pxml) {
XMLSTACK *pstack; XMLSTACK *pstack;
if(pxml->stack.next) { if(pxml->stack.next) {
_ppi->log(E_LOG,"xml_deinit: entries still on stack (%s)\n", pi_log(E_LOG,"xml_deinit: entries still on stack (%s)\n",
pxml->stack.next->tag); pxml->stack.next->tag);
} }

View File

@ -13,6 +13,7 @@
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
@ -23,6 +24,7 @@
#include "err.h" #include "err.h"
#include "util.h" #include "util.h"
/* Globals */ /* Globals */
pthread_mutex_t util_locks[(int)l_last]; pthread_mutex_t util_locks[(int)l_last];
pthread_mutex_t util_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t util_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -587,6 +589,81 @@ void util_dispose_split(char **argv) {
free(argv); free(argv);
} }
/**
* Write a formatted string to an allocated string. Leverage
* the existing util_vasprintf to do so
*/
char *util_asprintf(char *fmt, ...) {
char *outbuf;
va_list ap;
ASSERT(fmt);
if(!fmt)
return NULL;
va_start(ap,fmt);
outbuf = util_vasprintf(fmt, ap);
va_end(ap);
return outbuf;
}
/**
* Write a formatted string to an allocated string. This deals with
* versions of vsnprintf that return either the C99 way, or the pre-C99
* way, by increasing the buffer until it works.
*
* @param
* @param fmt format string of print (compatible with printf(2))
* @returns TRUE on success
*/
#ifdef HAVE_VA_COPY
# define VA_COPY(a,b) va_copy((a),(b))
#else
# ifdef HAVE___VA_COPY
# define VA_COPY(a,b) __va_copy((a),(b))
# else
# define VA_COPY(a,b) a=b;
# endif
#endif
char *util_vasprintf(char *fmt, va_list ap) {
char *outbuf;
char *newbuf;
va_list ap2;
int size=200;
int new_size;
outbuf = (char*)malloc(size);
if(!outbuf)
DPRINTF(E_FATAL,L_MISC,"Could not allocate buffer in vasprintf\n");
VA_COPY(ap2,ap);
while(1) {
new_size=vsnprintf(outbuf,size,fmt,ap);
if(new_size > -1 && new_size < size)
break;
if(new_size > -1)
size = new_size + 1;
else
size *= 2;
if((newbuf = realloc(outbuf,size)) == NULL) {
free(outbuf);
DPRINTF(E_FATAL,L_MISC,"malloc error in vasprintf\n");
exit(1);
}
outbuf = newbuf;
VA_COPY(ap,ap2);
}
return outbuf;
}
#ifdef DEBUG_MEM #ifdef DEBUG_MEM

View File

@ -13,6 +13,7 @@
# include <stdint.h> # include <stdint.h>
#endif #endif
#include <stdarg.h>
#include <sys/types.h> #include <sys/types.h>
typedef enum { typedef enum {
@ -54,7 +55,8 @@ extern int util_utf16toutf8(unsigned char *utf8, int dlen, unsigned char *utf16,
extern int util_utf16_byte_len(unsigned char *utf16); extern int util_utf16_byte_len(unsigned char *utf16);
extern void util_hexdump(unsigned char *block, int len); extern void util_hexdump(unsigned char *block, int len);
extern char *util_vasprintf(char *fmt, va_list ap);
extern char *util_asprintf(char *fmt, ...);
#endif /* _UTIL_H_ */ #endif /* _UTIL_H_ */