diff --git a/admin-root/index.html b/admin-root/index.html
index 3f0b6577..3faec37a 100644
--- a/admin-root/index.html
+++ b/admin-root/index.html
@@ -35,6 +35,17 @@
+
+
+
+
+ Plugin | Version |
+
+
+ | |
+
+
+
diff --git a/admin-root/status.js b/admin-root/status.js
index 5eb2dee4..f34171fb 100644
--- a/admin-root/status.js
+++ b/admin-root/status.js
@@ -51,6 +51,19 @@ var Updater = {
row.push(Element.textContent(element.childNodes[2]));
threadTable.addTbodyRow(row);
});
+
+ // Monkey see, monkey do
+ var plugin = $A(request.responseXML.getElementsByTagName('plugin'));
+ var pluginTable = new Table('plugin');
+ pluginTable.removeTBodyRows();
+ plugin.each(function(element) {
+ row = [];
+ info = Element.textContent(element.childNodes[0]).split('/',2);
+ row.push(info[0]);
+ row.push(info[1]);
+ pluginTable.addTbodyRow(row);
+ });
+
// $('session_count').replaceChild(document.createTextNode(users + ' Connected Users'),$('session_count').firstChild);
if (!Updater.stop) {
Updater.wait();
diff --git a/src/ff-dbstruct.h b/src/ff-dbstruct.h
index dc242137..adad5ea5 100644
--- a/src/ff-dbstruct.h
+++ b/src/ff-dbstruct.h
@@ -96,7 +96,7 @@ typedef struct tag_mp3file {
uint32_t play_count;
uint32_t rating;
uint32_t db_timestamp;
-
+
uint32_t disabled;
uint32_t bpm; /* TBPM */
@@ -187,6 +187,7 @@ typedef struct tag_packed_mp3file {
char *has_video;
char *contentrating;
char *bits_per_sample;
+ char *album_artist;
} PACKED_MP3FILE;
#define PL_STATICWEB 0
diff --git a/src/main.c b/src/main.c
index d47980fa..305d931b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -197,6 +197,50 @@ void usage(char *program) {
printf("\n\n");
}
+/**
+ * process a directory for plugins
+ *
+ * @returns TRUE if at least one plugin loaded successfully
+ */
+int load_plugin_dir(char *plugindir) {
+ DIR *d_plugin;
+ char de[sizeof(struct dirent) + MAXNAMLEN + 1]; /* ?? solaris */
+ struct dirent *pde;
+ char *pext;
+ char *perr=NULL;
+ int loaded=FALSE;
+ char plugin[PATH_MAX];
+
+ if((d_plugin=opendir(plugindir)) == NULL) {
+ DPRINTF(E_LOG,L_MAIN,"Error opening plugin dir %s. Ignoring\n",
+ plugindir);
+ return FALSE;
+
+ } else {
+ while((readdir_r(d_plugin,(struct dirent *)de,&pde) != 1) && pde) {
+ pext = strrchr(pde->d_name,'.');
+ if((strcasecmp(pext,".so") == 0) ||
+ (strcasecmp(pext,".dylib") == 0) ||
+ (strcasecmp(pext,".dll") == 0)) {
+ /* must be a plugin */
+ snprintf(plugin,PATH_MAX,"%s%c%s",plugindir,
+ PATHSEP,pde->d_name);
+ if(plugin_load(&perr,plugin) != PLUGIN_E_SUCCESS) {
+ DPRINTF(E_LOG,L_MAIN,"Error loading plugin %s: %s\n",
+ plugin,perr);
+ free(perr);
+ perr = NULL;
+ } else {
+ loaded = TRUE;
+ }
+ }
+ }
+ closedir(d_plugin);
+ }
+
+ return loaded;
+}
+
/**
* Kick off the daap server and wait for events.
*
@@ -233,18 +277,12 @@ int main(int argc, char *argv[]) {
char *servername, *iface;
char *ffid = NULL;
int appdir = 0;
-
+ char *perr=NULL;
char txtrecord[255];
-
+ void *phandle;
char *plugindir;
- char plugin[PATH_MAX];
- DIR *d_plugin;
- char de[sizeof(struct dirent) + MAXNAMLEN + 1]; /* ?? solaris */
- struct dirent *pde;
- char *pext;
int err;
- char *perr=NULL;
char *apppath;
int debuglevel=0;
@@ -390,28 +428,27 @@ int main(int argc, char *argv[]) {
if((plugindir=conf_alloc_string("plugins","plugin_dir",NULL)) != NULL) {
/* instead of specifying plugins, let's walk through the directory
* and load each of them */
- if((d_plugin=opendir(plugindir)) == NULL) {
- DPRINTF(E_LOG,L_MAIN,"Error opening plugin dir. Ignoring\n");
- } else {
- while((readdir_r(d_plugin,(struct dirent *)de,&pde) != 1) && pde) {
- pext = strrchr(pde->d_name,'.');
- if((strcasecmp(pext,".so") == 0) ||
- (strcasecmp(pext,".dylib") == 0) ||
- (strcasecmp(pext,".dll") == 0)) {
- /* must be a plugin */
- snprintf(plugin,PATH_MAX,"%s%c%s",plugindir,
- PATHSEP,pde->d_name);
- if(plugin_load(&perr,plugin) != PLUGIN_E_SUCCESS) {
- DPRINTF(E_LOG,L_MAIN,"Error loading plugin %s: %s\n",
- plugin,perr);
- free(perr);
- perr = NULL;
- }
- }
- }
- closedir(d_plugin);
+ if(!load_plugin_dir(plugindir)) {
+ DPRINTF(E_LOG,L_MAIN,"Warning: Could not load plugins\n");
}
free(plugindir);
+ } else {
+ if((!load_plugin_dir("/usr/lib/firefly")) &&
+ (!load_plugin_dir("/usr/lib/mt-daapd")) &&
+ (!load_plugin_dir("/usr/share/firefly/plugins")) &&
+ (!load_plugin_dir("/usr/share/mt-daapd/plugins")) &&
+ (!load_plugin_dir("/usr/local/share/firefly/plugins")) &&
+ (!load_plugin_dir("/usr/local/share/mt-daapd/plugins")) &&
+ (!load_plugin_dir("/opt/share/firefly/plugins")) &&
+ (!load_plugin_dir("/opt/share/mt-daapd/plugins")) &&
+ (!load_plugin_dir("plugins/.libs"))) {
+ DPRINTF(E_FATAL,L_MAIN,"plugins/plugin_dir not specified\n");
+ }
+ }
+
+ phandle=NULL;
+ while((phandle=plugin_enum(phandle))) {
+ DPRINTF(E_LOG,L_MAIN,"Plugin loaded: %s\n",plugin_get_description(phandle));
}
runas = conf_alloc_string("general","runas","nobody");
diff --git a/src/plugin.c b/src/plugin.c
index 4f4f4940..0f871f7c 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -247,6 +247,35 @@ void _plugin_recalc_codecs(void) {
}
+/**
+ * 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.
*
diff --git a/src/plugin.h b/src/plugin.h
index 4199bf5c..d5678f94 100644
--- a/src/plugin.h
+++ b/src/plugin.h
@@ -37,6 +37,9 @@ extern int plugin_auth_handle(WS_CONNINFO *pwsc, char *username, char *pw);
extern int plugin_rend_register(char *name, int port, char *iface, char *txt);
extern void plugin_event_dispatch(int event_id, int intval, void *vp, int len);
+extern void *plugin_enum(void *);
+extern char *plugin_get_description(void *);
+
/* these should really get rows */
#define PLUGIN_E_SUCCESS 0
diff --git a/src/xml-rpc.c b/src/xml-rpc.c
index 8426140a..6ecab575 100644
--- a/src/xml-rpc.c
+++ b/src/xml-rpc.c
@@ -508,6 +508,7 @@ void xml_get_stats(WS_CONNINFO *pwsc) {
WSTHREADENUM wste;
int count;
XMLSTRUCT *pxml;
+ void *phandle;
pxml=xml_init(pwsc,1);
xml_push(pxml,"status");
@@ -525,7 +526,6 @@ void xml_get_stats(WS_CONNINFO *pwsc) {
xml_output(pxml,"status","Disabled");
}
#else
-
ws_writefd(pwsc,"No Support | | \n");
#endif
xml_pop(pxml); /* service */
@@ -542,6 +542,16 @@ 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);