From 6aca074f822dc66bda9171075f3c099650167a7f Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Sun, 3 May 2009 11:07:25 +0200 Subject: [PATCH] Remove plugin infrastructure --- configure.in | 3 - src/Makefile.am | 8 +- src/db-sql.c | 1 - src/err.c | 10 - src/ff-plugin-events.h | 26 -- src/ff-plugins.c | 780 ----------------------------------------- src/ff-plugins.h | 176 ---------- src/plugin.c | 615 -------------------------------- src/plugin.h | 52 --- src/xml-rpc.c | 12 - 10 files changed, 4 insertions(+), 1679 deletions(-) delete mode 100644 src/ff-plugin-events.h delete mode 100644 src/ff-plugins.c delete mode 100644 src/ff-plugins.h delete mode 100644 src/plugin.c delete mode 100644 src/plugin.h diff --git a/configure.in b/configure.in index fc72cf23..4ac52d2d 100644 --- a/configure.in +++ b/configure.in @@ -101,9 +101,6 @@ AC_PROG_GCC_TRADITIONAL AC_TYPE_SIGNAL AC_CHECK_FUNCS(select socket strdup strerror) -AC_CHECK_LIB(dl, dlsym, LIBDL=-ldl) -AC_SUBST(LIBDL) - dnl check to see if we need -lsocket (solaris) V_NETLIBS="" AC_CHECK_LIB(socket,socket,V_NETLIBS="-lsocket $V_NETLIBS",,) diff --git a/src/Makefile.am b/src/Makefile.am index 2ccfed33..288b21fc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,7 @@ MUSEPACKSRC=scan-mpc.c endif mt_daapd_CPPFLAGS = -D_GNU_SOURCE @AVAHI_CFLAGS@ @SQLITE3_CFLAGS@ @FFMPEG_CFLAGS@ @CONFUSE_CFLAGS@ @TAGLIB_CFLAGS@ @MINIXML_CFLAGS@ -mt_daapd_LDADD = @AVAHI_LIBS@ @SQLITE3_LIBS@ @FFMPEG_LIBS@ @CONFUSE_LIBS@ @FLAC_LIBS@ @TAGLIB_LIBS@ @LIBEVENT_LIBS@ @LIBAVL_LIBS@ @MINIXML_LIBS@ @LIBDL@ +mt_daapd_LDADD = @AVAHI_LIBS@ @SQLITE3_LIBS@ @FFMPEG_LIBS@ @CONFUSE_LIBS@ @FLAC_LIBS@ @TAGLIB_LIBS@ @LIBEVENT_LIBS@ @LIBAVL_LIBS@ @MINIXML_LIBS@ mt_daapd_LDFLAGS = -export-dynamic mt_daapd_SOURCES = main.c daapd.h webserver.c \ webserver.h configfile.c configfile.h err.c err.h \ @@ -25,11 +25,11 @@ mt_daapd_SOURCES = main.c daapd.h webserver.c \ httpd_daap.c httpd_daap.h \ transcode.c transcode.h \ misc.c misc.h \ - db-generic.c db-generic.h ff-plugins.c ff-plugins.h \ + db-generic.c db-generic.h \ scan-wma.c \ smart-parser.c smart-parser.h xml-rpc.c xml-rpc.h \ util.c util.h \ - plugin.c plugin.h db-sql-updates.c \ + db-sql-updates.c \ io.h io.c io-errors.h io-plugin.h \ db-sql.c db-sql.h db-sql-sqlite3.c db-sql-sqlite3.h\ $(FLACSRC) $(MUSEPACKSRC) @@ -37,4 +37,4 @@ mt_daapd_SOURCES = main.c daapd.h webserver.c \ EXTRA_DIST = scan-mpc.c \ scan-flac.c \ conf.h \ - ff-plugins.h ff-dbstruct.h ff-plugin-events.h + ff-dbstruct.h diff --git a/src/db-sql.c b/src/db-sql.c index e183b40f..b9bbc0b8 100644 --- a/src/db-sql.c +++ b/src/db-sql.c @@ -43,7 +43,6 @@ #include "db-generic.h" #include "db-sql.h" #include "smart-parser.h" -#include "plugin.h" #include "conf.h" /* FIXME */ #ifdef HAVE_SQLITE3 diff --git a/src/err.c b/src/err.c index 8a27457c..53d35126 100644 --- a/src/err.c +++ b/src/err.c @@ -52,10 +52,6 @@ #include "err.h" #include "io.h" -#ifndef ERR_LEAN -# include "plugin.h" -#endif - #include "util.h" #ifndef PACKAGE @@ -285,12 +281,6 @@ void err_log(int level, unsigned int cat, char *fmt, ...) util_mutex_unlock(l_err); -#ifndef ERR_LEAN - if(level < 2) { /* only event level fatals and log level */ - plugin_event_dispatch(PLUGIN_EVENT_LOG, level, errbuf, (int)strlen(errbuf)+1); - } -#endif - util_mutex_lock(l_err_list); __err_thread_del(); util_mutex_unlock(l_err_list); diff --git a/src/ff-plugin-events.h b/src/ff-plugin-events.h deleted file mode 100644 index 73427bce..00000000 --- a/src/ff-plugin-events.h +++ /dev/null @@ -1,26 +0,0 @@ - - -#ifndef _FF_PLUGIN_EVENTS_H_ -#define _FF_PLUGIN_EVENTS_H_ - -/* Plugin types */ -#define PLUGIN_OUTPUT 1 -#define PLUGIN_SCANNER 2 -#define PLUGIN_DATABASE 4 -#define PLUGIN_EVENT 8 -#define PLUGIN_TRANSCODE 16 - -/* plugin event types */ -#define PLUGIN_EVENT_LOG 0 -#define PLUGIN_EVENT_FULLSCAN_START 1 -#define PLUGIN_EVENT_FULLSCAN_END 2 -#define PLUGIN_EVENT_STARTING 3 -#define PLUGIN_EVENT_SHUTDOWN 4 -#define PLUGIN_EVENT_STARTSTREAM 5 -#define PLUGIN_EVENT_ABORTSTREAM 6 -#define PLUGIN_EVENT_ENDSTREAM 7 - -#define PLUGIN_VERSION 2 - - -#endif /* _FF_PLUGIN_EVENTS_ */ diff --git a/src/ff-plugins.c b/src/ff-plugins.c deleted file mode 100644 index e3e336fa..00000000 --- a/src/ff-plugins.c +++ /dev/null @@ -1,780 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include - -#include "conf.h" -#include "configfile.h" -#include "daapd.h" -#include "db-generic.h" -#include "err.h" -#include "ff-dbstruct.h" -#include "ff-plugins.h" -#include "io.h" -#include "plugin.h" -#include "util.h" -#include "webserver.h" - -EXPORT char *pi_ws_uri(WS_CONNINFO *pwsc) { - ASSERT(pwsc); - - if(!pwsc) - return NULL; - - return ws_uri(pwsc); -} - -EXPORT void pi_ws_will_close(WS_CONNINFO *pwsc) { - ASSERT(pwsc); - - if(!pwsc) - return; - - ws_should_close(pwsc,1); -} - -EXPORT int pi_ws_returnerror(WS_CONNINFO *pwsc, int ecode, char *msg) { - ASSERT(pwsc); - - if(!pwsc) - return FALSE; - - return ws_returnerror(pwsc,ecode,msg); -} - -EXPORT char *pi_ws_getvar(WS_CONNINFO *pwsc, char *var) { - ASSERT(pwsc); - ASSERT(var); - - if((!pwsc) || (!var)) - return NULL; - - return ws_getvar(pwsc,var); -} - -EXPORT int pi_ws_writefd(WS_CONNINFO *pwsc, char *fmt, ...) { - char *out; - va_list ap; - int result; - - ASSERT((pwsc) && (fmt)); - - if((!pwsc) || (!fmt)) - return FALSE; - - va_start(ap,fmt); - out = util_vasprintf(fmt,ap); - va_end(ap); - - result = ws_writefd(pwsc, "%s", out); - free(out); - return result; -} - -EXPORT int pi_ws_addresponseheader(WS_CONNINFO *pwsc, char *header, char *fmt, ...) { - char *out; - va_list ap; - int result; - - ASSERT(pwsc && header && fmt); - - if((!pwsc) || (!header) || (!fmt)) - return FALSE; - - va_start(ap,fmt); - out = util_vasprintf(fmt,ap); - va_end(ap); - - result = ws_addresponseheader(pwsc, header, "%s", out); - free(out); - return result; - -} - -EXPORT void pi_ws_emitheaders(WS_CONNINFO *pwsc) { - ASSERT(pwsc); - - if(!pwsc) - return; - - ws_emitheaders(pwsc); -} - -EXPORT char *pi_ws_getrequestheader(WS_CONNINFO *pwsc, char *header) { - ASSERT((pwsc) && (header)); - - if((!pwsc) || (!header)) - return NULL; - - return ws_getrequestheader(pwsc, header); -} - -EXPORT int pi_ws_writebinary(WS_CONNINFO *pwsc, char *data, int len) { - ASSERT((pwsc) && (data) && (len)); - - if((!pwsc) || (!data) || (!len)) - return 0; - - return ws_writebinary(pwsc, data, len); -} - -EXPORT char *pi_ws_gethostname(WS_CONNINFO *pwsc) { - ASSERT(pwsc); - - if(!pwsc) - return NULL; - - return ws_hostname(pwsc); -} - -EXPORT int pi_ws_matchesrole(WS_CONNINFO *pwsc, char *username, - char *password, char *role) { - ASSERT((pwsc) && (role)); - - if((!pwsc) || (!role)) - return FALSE; - - return config_matches_role(pwsc, username, password, role); -} - -/* misc helpers */ -EXPORT char *pi_server_ver(void) { - return VERSION; -} - -EXPORT int pi_server_name(char *name, int *len) { - char *servername; - - ASSERT((name) && (len)); - - if((!name) || (!len)) - return FALSE; - - servername = conf_get_servername(); - - /* FIXME: this is stupid */ - 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; -} - -EXPORT void pi_log(int level, char *fmt, ...) { - char *out; - va_list ap; - - va_start(ap,fmt); - out=util_vasprintf(fmt,ap); - va_end(ap); - - DPRINTF(level,L_PLUG,"%s",out); - free(out); -} - -/** - * check to see if we can transcode - * - * @param codec the codec we are trying to serve - * @returns TRUE if we can transcode, FALSE otherwise - */ -EXPORT int pi_should_transcode(WS_CONNINFO *pwsc, char *codec) { - return plugin_ssc_should_transcode(pwsc,codec); -} - - -EXPORT 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; -} - -EXPORT 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); -} - -EXPORT int pi_db_enum_end(char **pe) { - return db_enum_end(pe); -} - -EXPORT int pi_db_enum_restart(char **pe, DB_QUERY *pinfo) { - DBQUERYINFO *pqi; - - pqi = (DBQUERYINFO*)pinfo->priv; - return db_enum_reset(pe,pqi); -} - -EXPORT 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; - } - free(pqi); - pinfo->priv = NULL; - } -} - -EXPORT 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; - char *urltemp; - int ret; - - /* 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_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"); - - urltemp = io_urlencode(pmp3->path); - if (!urltemp) - { - ws_set_err(pwsc,E_WS_NATIVE); - DPRINTF(E_WARN,L_WS,"Thread %d: Error opening %s: out of memory\n", - ws_threadno(pwsc),pmp3->path); - ws_returnerror(pwsc,404,"Not found"); - config_set_status(pwsc,session,NULL); - db_dispose_item(pmp3); - io_dispose(hfile); - } - - ret = io_open(hfile, "file://%s", urltemp); - free(urltemp); - if (!ret) { - /* 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)) { - /* FIXME: Get webserver error string */ - DPRINTF(E_INF,L_WS,"Error copying file to remote...\n"); - 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); -} - -EXPORT int pi_db_add_playlist(char **pe, char *name, int type, char *clause, - char *path, int index, int *playlistid) { - return db_add_playlist(pe, name, type, clause, path, index, playlistid); -} - -EXPORT int pi_db_add_playlist_item(char **pe, int playlistid, int songid) { - return db_add_playlist_item(pe, playlistid, songid); -} - -EXPORT int pi_db_edit_playlist(char **pe, int id, char *name, char *clause) { - return db_edit_playlist(pe, id, name, clause); -} - -EXPORT int pi_db_delete_playlist(char **pe, int playlistid) { - return db_delete_playlist(pe, playlistid); -} - -EXPORT int pi_db_delete_playlist_item(char **pe, int playlistid, int songid) { - return db_delete_playlist_item(pe, playlistid, songid); -} - -EXPORT int pi_db_revision(void) { - return db_revision(); -} - -EXPORT int pi_db_count_items(int what) { - int count=0; - char *pe = NULL; - - switch(what) { - case COUNT_SONGS: - db_get_song_count(&pe,&count); - break; - case COUNT_PLAYLISTS: - db_get_playlist_count(&pe,&count); - break; - } - - if(pe) { - DPRINTF(E_LOG,L_DB,"Error getting item count: %s\n",pe); - free(pe); - } - return count; -} - -EXPORT 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; -} - -EXPORT char *pi_conf_alloc_string(char *section, char *key, char *dflt) { - return conf_alloc_string(section, key, dflt); -} - -EXPORT void pi_conf_dispose_string(char *str) { - free(str); -} - -EXPORT int pi_conf_get_int(char *section, char *key, int dflt) { - return conf_get_int(section, key, dflt); -} - -EXPORT void pi_config_set_status(WS_CONNINFO *pwsc, int session, char *fmt, ...) { - char *out; - va_list ap; - - ASSERT(fmt); - if(!fmt) - return; - - va_start(ap,fmt); - out = util_vasprintf(fmt,ap); - va_end(ap); - - config_set_status(pwsc, session, "%s", out); - free(out); -} - -/** - * allocte an io object - * - * @returns NULL on malloc error, IOHANDLE otherwise - */ -EXPORT IOHANDLE pi_io_new(void) { - return io_new(); -} - -/** - * open an io object given a printf-style URI - * - * @param io io handle allocated with pi_io_new - * @param fmt printf-style format string for URI (%U URI-encodes strings) - * @returns TRUE on success, FALSE otherwise. use io_err* to get error info - */ -EXPORT int pi_io_open(IOHANDLE io, char *fmt, ...) { - char uri_copy[4096]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(uri_copy, sizeof(uri_copy), fmt, ap); - va_end(ap); - - return io_open(io, "%s", uri_copy); -} - -/** - * close an open io_object - * - * @param io handle to close - * @returns TRUE on success, FALSE otherwise - */ -EXPORT int pi_io_close(IOHANDLE io) { - return io_close(io); -} - -/** - * read from an open io handle - * - * @param io open handle to read from - * @param buf buffer to read into - * @param len length to read, on return: length read - * @returns TRUE on success, FALSE otherwise, len set with bytes read - */ -EXPORT int pi_io_read(IOHANDLE io, unsigned char *buf, uint32_t *len){ - return io_read(io, buf, len); -} - -/** - * read from an io handle with timeout - * - * Returns FALSE on read error or timeout. Timeout versus - * read error condition can be determined by ms. If ms is 0, - * then a timeout condition occurred - * - * @param io open handle to read from - * @param buf buffer to read into - * @param len length to read, on return: length read - * @param ms time to wait (in ms), on return: time left - * @returns TRUE on success, FALSE on failure (or timeout) - */ -EXPORT int pi_io_read_timeout(IOHANDLE io, unsigned char *buf, uint32_t *len, uint32_t *ms) { - return io_read_timeout(io, buf, len, ms); -} - -/** - * write a block of data to an open io handle - * - * @param io io handle to write to - * @param buf buffer to write from - * @param len bytes to write to io handle, on return: bytes written - * @returns TRUE on success, FALSE otherwise - */ -EXPORT int pi_io_write(IOHANDLE io, unsigned char *buf, uint32_t *len) { - return io_write(io, buf, len); -} - -/** - * write a printf formatted string to io handle - * - * @param io io handle to write to - * @param fmt printf style format specifier - * @returns TRUE on success, FALSE otherwise - */ -EXPORT int pi_io_printf(IOHANDLE io, char *fmt, ...) { - char *out; - va_list ap; - int result; - - ASSERT(fmt); - if(!fmt) - return FALSE; - - va_start(ap,fmt); - out = util_vasprintf(fmt,ap); - va_end(ap); - - result = io_printf(io,"%s",out); - free(out); - - return result; -} - -/** - * get the (64-bit) size of a file. Built in URI's use seekability - * to determine extent of file, so non-seekable io objects (sockets, etc) - * will return IO_E_BADFN. - * - * @param io io handle to get size of - * @param size returns the 64-bit size of file - * @returns TRUE on success, FALSE on error (check io_errstr) - */ -EXPORT int pi_io_size(IOHANDLE io, uint64_t *size) { - return io_size(io, size); -} - -/** - * set the position of file read handle. There are several limitations - * to this. Non seekable handles (sockets, etc) won't seek, NOT - * EVEN FORWARD! - * - * FIXME: seeking on buffered file handle makes explode - * - * @param io handle to set position of - * @param offset how far to move - * @param whence from where (in lseek style -- SEEK_SET, SEEK_CUR, SEEK_END) - * @returns TRUE on success, FALSE otherwise (check io_errstr) - */ -EXPORT int pi_io_setpos(IOHANDLE io, uint64_t offset, int whence) { - return io_setpos(io, offset, whence); -} - -/** - * get current file position in a stream. Like setpos, this won't work on non- - * streamable io handles, and it won't (currently) work on buffered file handles. - * in addition, it might behave strangely various filter drivers (ssl, etc) - * - * @param io io handle to get position for - * @param pos on return, the current file position - * @returns TRUE on success, FALSE otherwise (see io_errstr) - */ -EXPORT int pi_io_getpos(IOHANDLE io, uint64_t *pos) { - return io_getpos(io, pos); -} - - -/** - * turn on buffering for a file handle. This really only makes sense - * when doing readlines. Note that you can't currently turn of buffered - * mode, so if doing a mix of buffered and unbuffered io, don't buffer the - * handle. Also, once the handle is buffered, setpos and getpos won't work - * right, and will very likely make Bad Things Happen. You have been - * warned. - * - * @param io handle to buffer - * @returns TRUE - */ -EXPORT int pi_io_buffer(IOHANDLE io) { - return io_buffer(io); -} - -/** - * read a line from the file handle. If the file is opened with - * ascii=1, then line ending conversions to/from windows/unix will - * take place. - * - * @param io handle to read line from - * @param buf buffer to read line into - * @param len size of buffer, on return: bytes read - * @returns TRUE on success, FALSE on error (see io_errstr) - */ -EXPORT int pi_io_readline(IOHANDLE io, unsigned char *buf, uint32_t *len) { - return io_readline(io, buf, len); -} - -/** - * read a line from a file handle with timeout. - * - * Errors (including timeout) return FALSE. Timeout errors - * can be detected because ms=0 - * - * @param io handle to read from - * @param buf buffer to read into - * @param len size of buffer, on return: bytes read - * @param ms timeout, in ms, on return: time remaining - * @returns TRUE on success, FALSE otherwise - */ -EXPORT int pi_io_readline_timeout(IOHANDLE io, unsigned char *buf, uint32_t *len, uint32_t *ms) { - return io_readline_timeout(io, buf, len, ms); -} - -/** - * get error string of last error - * - * @param io handle to get error of - * @returns error string, does not need to be free'd - */ -EXPORT char* pi_io_errstr(IOHANDLE io) { - return io_errstr(io); -} - -/** - * get native error code - * - * @param io handle to get error code for - * @returns error code (see io-errors.h) - */ -EXPORT int pi_io_errcode(IOHANDLE io) { - return io_errcode(io); -} - -/** - * dispose of an io handle, freeing up any internally allocated - * memory and structs. This implicitly calls io_close, so - * you don't *need* to do io_close(hio); io_dispoase(hio);, but I - * do anyway. :) - * - * @param io handle to dispose of - */ -EXPORT void pi_io_dispose(IOHANDLE io) { - return io_dispose(io); -} diff --git a/src/ff-plugins.h b/src/ff-plugins.h deleted file mode 100644 index aacba793..00000000 --- a/src/ff-plugins.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Public plug-in interface - * - * Copyright (C) 2006 Ron Pedde (ron@pedde.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _FF_PLUGINS_H_ -#define _FF_PLUGINS_H_ - -#include "ff-dbstruct.h" -#include "ff-plugin-events.h" -#include "smart-parser.h" - -#define EXPORT - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#ifndef E_FATAL -# define E_FATAL 0 -# define E_LOG 1 -# define E_WARN 2 -# define E_INF 5 -# define E_DBG 9 -# define E_SPAM 10 -#endif - -#define COUNT_SONGS 0 -#define COUNT_PLAYLISTS 1 - -struct tag_ws_conninfo; -typedef void* HANDLE; - -/* Functions that must be exported by different plugin types */ -typedef struct tag_plugin_output_fn { - int(*can_handle)(struct tag_ws_conninfo *pwsc); - void(*handler)(struct tag_ws_conninfo *pwsc); - int(*auth)(struct tag_ws_conninfo *pwsc, char *username, char *pw); -} PLUGIN_OUTPUT_FN; - -typedef struct tag_plugin_event_fn { - void(*handler)(int event_id, int intval, void *vp, int len); -} PLUGIN_EVENT_FN; - -typedef struct tag_plugin_transcode_fn { - void *(*ssc_init)(void); - void (*ssc_deinit)(void*); - int (*ssc_open)(void*, MP3FILE *); - int (*ssc_close)(void*); - int (*ssc_read)(void*, char*, int); - char *(*ssc_error)(void*); -} PLUGIN_TRANSCODE_FN; - -/* info for rendezvous advertising */ -typedef struct tag_plugin_rend_info { - char *type; - char **txt; -} PLUGIN_REND_INFO; - -/* main info struct that plugins must provide */ -typedef struct tag_plugin_info { - int version; /* PLUGIN_VERSION */ - int type; /* PLUGIN_OUTPUT, etc */ - char *server; /* Server/version format */ - PLUGIN_OUTPUT_FN *output_fns; /* functions for different plugin types */ - PLUGIN_EVENT_FN *event_fns; - PLUGIN_TRANSCODE_FN *transcode_fns; - PLUGIN_REND_INFO *rend_info; /* array of rend announcements */ - char *codeclist; /* comma separated list of codecs */ -} PLUGIN_INFO; - - -#define QUERY_TYPE_ITEMS 0 -#define QUERY_TYPE_PLAYLISTS 1 -#define QUERY_TYPE_DISTINCT 2 - -typedef struct tag_db_query { - int query_type; - char *distinct_field; - int filter_type; - char *filter; - - int offset; - int limit; - - int playlist_id; /* for items query */ - int totalcount; /* returned total count */ - void *priv; -} DB_QUERY; - -#ifdef __cplusplus -extern "C" { -#endif - -/* webserver functions */ -extern EXPORT char *pi_ws_uri(struct tag_ws_conninfo *); -extern EXPORT void pi_ws_will_close(struct tag_ws_conninfo *); -extern 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 *); - -/* misc helpers */ -extern EXPORT char *pi_server_ver(void); -extern EXPORT int pi_server_name(char *, int *); -extern EXPORT void pi_log(int, char *, ...); -extern EXPORT int pi_should_transcode(struct tag_ws_conninfo *, char *); - -/* db functions */ -extern EXPORT int pi_db_enum_start(char **, DB_QUERY *); -extern EXPORT int pi_db_enum_fetch_row(char **, char ***, DB_QUERY *); -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 *); - -extern EXPORT int pi_db_add_playlist(char **pe, char *name, int type, char *clause, char *path, int index, int *playlistid); -extern EXPORT int pi_db_add_playlist_item(char **pe, int playlistid, int songid); -extern EXPORT int pi_db_edit_playlist(char **pe, int id, char *name, char *clause); -extern EXPORT int pi_db_delete_playlist(char **pe, int playlistid); -extern EXPORT int pi_db_delete_playlist_item(char **pe, int playlistid, int songid); -extern EXPORT int pi_db_revision(void); -extern EXPORT int pi_db_count_items(int what); -extern EXPORT int pi_db_wait_update(struct tag_ws_conninfo *); - -/* config/misc functions */ -extern EXPORT char *pi_conf_alloc_string(char *section, char *key, char *dflt); -extern EXPORT void pi_conf_dispose_string(char *str); -extern EXPORT int pi_conf_get_int(char *section, char *key, int dflt); -extern EXPORT void pi_config_set_status(struct tag_ws_conninfo *pwsc, int session, char *fmt, ...); - -/* io functions */ -extern EXPORT HANDLE pi_io_new(void); -extern EXPORT int pi_io_open(HANDLE io, char *fmt, ...); -extern EXPORT int pi_io_close(HANDLE io); -extern EXPORT int pi_io_read(HANDLE io, unsigned char *buf, uint32_t *len); -extern EXPORT int pi_io_read_timeout(HANDLE io, unsigned char *buf, uint32_t *len, uint32_t *ms); -extern EXPORT int pi_io_write(HANDLE io, unsigned char *buf, uint32_t *len); -extern EXPORT int pi_io_printf(HANDLE io, char *fmt, ...); -extern EXPORT int pi_io_size(HANDLE io, uint64_t *size); -extern EXPORT int pi_io_setpos(HANDLE io, uint64_t offset, int whence); -extern EXPORT int pi_io_getpos(HANDLE io, uint64_t *pos); -extern EXPORT int pi_io_buffer(HANDLE io); /* unimplemented */ -extern EXPORT int pi_io_readline(HANDLE io, unsigned char *buf, uint32_t *len); -extern EXPORT int pi_io_readline_timeout(HANDLE io, unsigned char *buf, uint32_t *len, uint32_t *ms); -extern EXPORT char* pi_io_errstr(HANDLE io); -extern EXPORT int pi_io_errcode(HANDLE io); -extern EXPORT void pi_io_dispose(HANDLE io); - -#ifdef __cplusplus -} -#endif - - -#endif /* _FF_PLUGINS_ */ diff --git a/src/plugin.c b/src/plugin.c deleted file mode 100644 index daf9106e..00000000 --- a/src/plugin.c +++ /dev/null @@ -1,615 +0,0 @@ -/* - * Simple plug-in api for output, transcode, and scanning plug-ins - * - * Copyright (C) 2006 Ron Pedde (ron@pedde.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define _XOPEN_SOURCE 500 /** unix98? pthread_once_t, etc */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_STDINT_H -#include -#endif -#ifdef HAVE_STRINGS_H -#include -#endif - -#ifdef HAVE_SYS_SELECT_H -#include -#endif -#include -#include -#ifdef HAVE_SYS_TIME_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif - -#include - -#include "daapd.h" -#include "conf.h" -#include "configfile.h" -#include "db-generic.h" -#include "err.h" -#include "io.h" -#include "plugin.h" -#include "smart-parser.h" -#include "xml-rpc.h" -#include "webserver.h" -#include "ff-plugins.h" -#include "io.h" - -#include "mdns_avahi.h" - -typedef struct tag_pluginentry { - void *phandle; - PLUGIN_INFO *pinfo; - struct tag_pluginentry *next; -} PLUGIN_ENTRY; - -/* Globals */ -static PLUGIN_ENTRY _plugin_list; -static int _plugin_initialized = 0; -static char *_plugin_ssc_codecs = NULL; - -static char* _plugin_error_list[] = { - "Success.", - "Could not load plugin: %s", - "Plugin missing required export: plugin_type/plugin_ver" -}; - -/* Forwards */ -void _plugin_readlock(void); -void _plugin_writelock(void); -void _plugin_unlock(void); -int _plugin_error(char **pe, int error, ...); -void _plugin_free(int *pi); -void _plugin_recalc_codecs(void); -int _plugin_ssc_transcode(WS_CONNINFO *pwsc, MP3FILE *pmp3, int offset, int headers); - -/** - * initialize stuff for plugins - * - * @returns TRUE on success, FALSE otherwise - */ -int plugin_init(void) { - return TRUE; -} - -/** - * free the tls - */ -void _plugin_free(int *pi) { - if(pi) - free(pi); -} - -/** - * deinitialize stuff for plugins - * - * @returns TRUE on success, FALSE otherwise - */ -int plugin_deinit(void) { - return TRUE; -} - -/** - * return the error - * - * @param pe buffer to store the error string in - * @param error error to return - * @returns the specified error,to thelp with returns - */ -int _plugin_error(char **pe, int error, ...) { - va_list ap; - char errbuf[1024]; - - if(!pe) - return error; - - va_start(ap, error); - vsnprintf(errbuf, sizeof(errbuf), _plugin_error_list[error], ap); - va_end(ap); - - DPRINTF(E_SPAM,L_PLUG,"Raising error: %s\n",errbuf); - - *pe = strdup(errbuf); - return error; -} - -/** - * walk through the installed plugins and recalculate - * the codec string - */ -void _plugin_recalc_codecs(void) { - PLUGIN_ENTRY *ppi; - size_t size=0; - - ppi = _plugin_list.next; - while(ppi) { - if(ppi->pinfo->type & PLUGIN_TRANSCODE) { - if(size) size++; - size += strlen(ppi->pinfo->codeclist); - } - ppi=ppi->next; - } - - if(_plugin_ssc_codecs) { - free(_plugin_ssc_codecs); - } - - _plugin_ssc_codecs = (char*)malloc(size+1); - if(!_plugin_ssc_codecs) { - DPRINTF(E_FATAL,L_PLUG,"_plugin_recalc_codecs: malloc\n"); - } - - memset(_plugin_ssc_codecs,0,size+1); - - ppi = _plugin_list.next; - while(ppi) { - if(ppi->pinfo->type & PLUGIN_TRANSCODE) { - if(strlen(_plugin_ssc_codecs)) { - strcat(_plugin_ssc_codecs,","); - } - strcat(_plugin_ssc_codecs,ppi->pinfo->codeclist); - } - ppi=ppi->next; - } - - DPRINTF(E_DBG,L_PLUG,"New transcode codec list: %s\n",_plugin_ssc_codecs); - return; - -} - -/** - * plugin_get_description - */ -char *plugin_get_description(void *which) { - PLUGIN_ENTRY *ppi = (PLUGIN_ENTRY *)which; - - return ppi->pinfo->server; -} - - -/** - * walk through the loaded plugin list - */ -void *plugin_enum(void *where) { - PLUGIN_ENTRY *ppi = (PLUGIN_ENTRY *)where; - - if(!ppi) { - // _plugin_readlock(); - return (void*) _plugin_list.next; - } - - if(!ppi->next) { - // _plugin_unlock(); - return NULL; - } - - return (void*) ppi->next; -} - -/** - * load a specified plugin. - * - * @param pe pointer to error string returned (if error) - * @param plugin path to plugin to load - * - * return PLUGIN_E_SUCCESS, or not, with pe set - */ -int plugin_load(char **pe, char *path) { - PLUGIN_ENTRY *ppi; - void *phandle; - PLUGIN_INFO *(*info_func)(void); - PLUGIN_INFO *pinfo; - - DPRINTF(E_DBG,L_PLUG,"Attempting to load plugin %s\n",path); - - phandle = dlopen(path, RTLD_NOW); - if (!phandle) { - *pe = strdup(dlerror()); - DPRINTF(E_INF,L_PLUG,"Couldn't get lib handle for %s\n",path); - return PLUGIN_E_NOLOAD; - } - - ppi = (PLUGIN_ENTRY*)malloc(sizeof(PLUGIN_ENTRY)); - memset(ppi,0x00,sizeof(PLUGIN_ENTRY)); - - ppi->phandle = phandle; - - info_func = (PLUGIN_INFO*(*)(void)) dlsym(phandle, "plugin_info"); - if(info_func == NULL) { - *pe = strdup(dlerror()); - DPRINTF(E_INF,L_PLUG,"Couldn't get info_func for %s\n",path); - dlclose(phandle); - free(ppi); - return PLUGIN_E_BADFUNCS; - } - - pinfo = info_func(); - ppi->pinfo = pinfo; - - if(!pinfo) { - if(pe) *pe = strdup("plugin declined to load"); - dlclose(phandle); - free(ppi); - return PLUGIN_E_NOLOAD; - } - - if(pinfo->version != PLUGIN_VERSION) { - DPRINTF(E_INF,L_PLUG,"Plugin is too old: version %d, expecting %d\n", - pinfo->version, PLUGIN_VERSION); - dlclose(phandle); - free(ppi); - return PLUGIN_E_NOLOAD; - } - - DPRINTF(E_INF,L_PLUG,"Loaded plugin %s (%s)\n",path,pinfo->server); - - if(!_plugin_initialized) { - _plugin_initialized = 1; - memset((void*)&_plugin_list,0,sizeof(_plugin_list)); - } - - ppi->next = _plugin_list.next; - _plugin_list.next = ppi; - - _plugin_recalc_codecs(); - return PLUGIN_E_SUCCESS; -} - -/** - * check to see if we want to dispatch a particular url - * - * @param pwsc the connection info (including uri) to check - * @returns TRUE if we want to handle it - */ -int plugin_url_candispatch(WS_CONNINFO *pwsc) { - PLUGIN_ENTRY *ppi; - - ppi = _plugin_list.next; - while(ppi) { - if(ppi->pinfo->type & PLUGIN_OUTPUT) { - if((ppi->pinfo->output_fns)->can_handle(pwsc)) { - return TRUE; - } - } - ppi = ppi->next; - } - - return FALSE; -} - -/** - * actually DISPATCH the hander we said we wanted - * - * @param pwsc the connection info (including uri) to check - * @returns TRUE if we want to handle it - */ -void plugin_url_handle(WS_CONNINFO *pwsc) { - PLUGIN_ENTRY *ppi; - void (*disp_fn)(WS_CONNINFO *pwsc); - - ppi = _plugin_list.next; - while(ppi) { - if(ppi->pinfo->type & PLUGIN_OUTPUT) { - if((ppi->pinfo->output_fns)->can_handle(pwsc)) { - /* we have a winner */ - DPRINTF(E_DBG,L_PLUG,"Dispatching %s to %s\n", ws_uri(pwsc), - ppi->pinfo->server); - - /* so functions must be a tag_plugin_output_fn */ - disp_fn=(ppi->pinfo->output_fns)->handler; - disp_fn(pwsc); - return; - } - } - ppi = ppi->next; - } - - /* should 500 here or something */ - ws_returnerror(pwsc, 500, "Can't find plugin handler"); - return; -} - -/** - * walk through the plugins and register whatever rendezvous - * names the clients want - */ -int plugin_rend_register(char *name, int port, char **txt) { - PLUGIN_ENTRY *ppi; - PLUGIN_REND_INFO *pri; - char **supplied_txt; - - ppi = _plugin_list.next; - - while(ppi) { - DPRINTF(E_DBG,L_PLUG,"Checking %s\n",ppi->pinfo->server); - if(ppi->pinfo->rend_info) { - pri = ppi->pinfo->rend_info; - while(pri->type) { - supplied_txt = pri->txt; - if(!pri->txt) - supplied_txt = txt; - - DPRINTF(E_DBG,L_PLUG,"Registering %s\n",pri->type); - mdns_register(name, pri->type, port, supplied_txt); - pri++; - } - } - ppi=ppi->next; - } - - return TRUE; -} - -/** - * Test password for the handled namespace - * - * @param pwsc the connection info (including uri) to check - * @param username user attempting to login - * @param pw password attempting - * @returns TRUE if we want to handle it - */ -int plugin_auth_handle(WS_CONNINFO *pwsc, char *username, char *pw) { - PLUGIN_ENTRY *ppi; - int (*auth_fn)(WS_CONNINFO *pwsc, char *username, char *pw); - int result; - - ppi = _plugin_list.next; - while(ppi) { - if(ppi->pinfo->type & PLUGIN_OUTPUT) { - if((ppi->pinfo->output_fns)->can_handle(pwsc)) { - /* we have a winner */ - DPRINTF(E_DBG,L_PLUG,"Dispatching %s to %s\n", ws_uri(pwsc), - ppi->pinfo->server); - - /* so functions must be a tag_plugin_output_fn */ - auth_fn=(ppi->pinfo->output_fns)->auth; - if(auth_fn) { - result=auth_fn(pwsc,username,pw); - return result; - } else { - return TRUE; - } - } - } - ppi = ppi->next; - } - - /* should 500 here or something */ - ws_returnerror(pwsc, 500, "Can't find plugin handler"); - return FALSE; -} - -/** - * send an event to a plugin... this can be a connection, disconnection, etc. - */ -void plugin_event_dispatch(int event_id, int intval, void *vp, int len) { - PLUGIN_ENTRY *ppi; - - ppi = _plugin_list.next; - while(ppi) { - if(ppi->pinfo->type & PLUGIN_EVENT) { -/* DPRINTF(E_DBG,L_PLUG,"Dispatching event %d to %s\n", - event_id,ppi->versionstring); */ - - if((ppi->pinfo->event_fns) && (ppi->pinfo->event_fns->handler)) { - ppi->pinfo->event_fns->handler(event_id, intval, vp, len); - } - } - ppi=ppi->next; - } -} - - -/** - * 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; -} - -int plugin_ssc_should_transcode(WS_CONNINFO *pwsc, char *codec) { - int result; - char *native_codecs=NULL; - char *user_agent=NULL; - char *never_transcode = NULL; - char *always_transcode = NULL; - - ASSERT((pwsc) && (codec)); - - if(!pwsc) - return FALSE; - - if(!codec) { - DPRINTF(E_LOG,L_PLUG,"testing transcode on null codec?\n"); - return FALSE; - } - - never_transcode = conf_alloc_string("general","never_transcode",NULL); - if(never_transcode) { - if(strstr(never_transcode,codec)) { - free(never_transcode); - return FALSE; - } - free(never_transcode); - } - - if(pwsc) { - /* see if the headers give us any guidance */ - native_codecs = ws_getrequestheader(pwsc,"accept-codecs"); - if(!native_codecs) { - user_agent = ws_getrequestheader(pwsc,"user-agent"); - if(user_agent) { - if(strncmp(user_agent,"iTunes",6)==0) { - native_codecs = "mpeg,mp4a,wav,mp4v,alac"; - } else if(strncmp(user_agent,"Roku",4)==0) { - native_codecs = "mpeg,mp4a,wav,wma"; - } else if(strncmp(user_agent,"Hifidelio",9)==0) { - return FALSE; - } - } - } - } - - if(!native_codecs) { - native_codecs = "mpeg,wav"; - } - - /* can't transcode it if we can't transcode it */ - if(!_plugin_ssc_codecs) - return FALSE; - - always_transcode = conf_alloc_string("general","always_transcode",NULL); - if(always_transcode) { - if(strstr(always_transcode,codec)) { - free(always_transcode); - return TRUE; - } - free(always_transcode); - } - - if(strstr(native_codecs,codec)) - return FALSE; - - result = FALSE; - if(strstr(_plugin_ssc_codecs,codec)) { - result = TRUE; - } - return result; -} - diff --git a/src/plugin.h b/src/plugin.h deleted file mode 100644 index 45b18377..00000000 --- a/src/plugin.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Simple plug-in api for output, transcode, and scanning plug-ins - * - * Copyright (C) 2006 Ron Pedde (ron@pedde.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _PLUGIN_H_ -#define _PLUGIN_H_ - -#include "webserver.h" -#include "xml-rpc.h" -#include "db-generic.h" -#include "ff-plugin-events.h" - -extern int plugin_init(void); -extern int plugin_load(char **pe, char *path); -extern int plugin_deinit(void); - -/* Interfaces for web */ -extern int plugin_url_candispatch(WS_CONNINFO *pwsc); -extern void plugin_url_handle(WS_CONNINFO *pwsc); -extern int plugin_auth_handle(WS_CONNINFO *pwsc, char *username, char *pw); -extern int plugin_rend_register(char *name, int port, char **txt); -extern void plugin_event_dispatch(int event_id, int intval, void *vp, int len); - -extern void *plugin_enum(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 */ - -#define PLUGIN_E_SUCCESS 0 -#define PLUGIN_E_NOLOAD 1 -#define PLUGIN_E_BADFUNCS 2 - -#endif /* _PLUGIN_H_ */ diff --git a/src/xml-rpc.c b/src/xml-rpc.c index c0f12e29..8ac89301 100644 --- a/src/xml-rpc.c +++ b/src/xml-rpc.c @@ -33,7 +33,6 @@ #include "conf.h" #include "db-generic.h" #include "err.h" -#include "plugin.h" #include "webserver.h" #include "xml-rpc.h" @@ -510,7 +509,6 @@ void xml_get_stats(WS_CONNINFO *pwsc) { WSTHREADENUM wste; int count; XMLSTRUCT *pxml; - void *phandle; pxml=xml_init(pwsc,1); xml_push(pxml,"status"); @@ -529,16 +527,6 @@ void xml_get_stats(WS_CONNINFO *pwsc) { xml_pop(pxml); /* service_status */ - xml_push(pxml,"plugins"); - phandle = NULL; - while((phandle = plugin_enum(phandle))) { - xml_push(pxml,"plugin"); - xml_output(pxml,"name",plugin_get_description(phandle)); - xml_pop(pxml); /* plugin */ - } - - xml_pop(pxml); /* plugins */ - xml_push(pxml,"thread_status"); pci = ws_thread_enum_first(config.server,&wste);