diff options
-rw-r--r-- | CMakeLists.txt | 12 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | nbproject/private/configurations.xml | 44 | ||||
-rw-r--r-- | nbproject/private/private.xml | 7 | ||||
-rw-r--r-- | plugins/CMakeLists.txt | 8 | ||||
-rw-r--r-- | plugins/audio/audio-api.c (renamed from src/alsa-api.c) | 0 | ||||
-rw-r--r-- | plugins/radio/radio-api.c (renamed from src/radio-api.c) | 51 | ||||
-rw-r--r-- | plugins/samples/HelloWorld.c (renamed from src/dbus-api.c) | 0 | ||||
-rw-r--r-- | plugins/samples/SamplePost.c (renamed from src/afbs-api.c) | 0 | ||||
-rw-r--r-- | plugins/session/token-api.c | 194 | ||||
-rw-r--r-- | src/CMakeLists.txt | 13 | ||||
-rw-r--r-- | src/SamplePost.c | 244 | ||||
-rw-r--r-- | src/rest-api.c | 1 |
13 files changed, 246 insertions, 330 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e9314d1..af98b389 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ PROJECT(afb-daemon C) -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8) SET(CMAKE_BUILD_TYPE, Debug) SET(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -35,10 +35,9 @@ ENDIF(CMAKE_BUILD_TYPE MATCHES Debug) INCLUDE(FindPkgConfig) PKG_CHECK_MODULES(json-c REQUIRED json-c) PKG_CHECK_MODULES(libmicrohttpd REQUIRED libmicrohttpd) +PKG_CHECK_MODULES(uuid REQUIRED uuid) # Optional plugin dependencies PKG_CHECK_MODULES(librtlsdr librtlsdr>=0.5.0) -PKG_CHECK_MODULES(uuid REQUIRED uuid) - IF(librtlsdr_FOUND) MESSAGE(STATUS "librtlsdr found ; will compile Radio plugin... (PLUGIN)") @@ -51,3 +50,10 @@ SET(include_dirs ${INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/include ${json-c_INCLUDE_DI SET(link_libraries ${json-c_LIBRARIES} ${libmicrohttpd_LIBRARIES} ${uuid_LIBRARIES} ${librtlsdr_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${libefence_LIBRARIES} -lmagic -lm) ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(plugins) + +ADD_EXECUTABLE(afb-daemon $<TARGET_OBJECTS:src> $<TARGET_OBJECTS:plugins>) +TARGET_LINK_LIBRARIES(afb-daemon ${link_libraries}) + +INSTALL(TARGETS afb-daemon + RUNTIME DESTINATION bin) @@ -23,7 +23,7 @@ industry requirementsas the primary target for this code is AGL. and the following tools: * pkg-config; - * cmake >= 2.8. + * cmake >= 2.8.8. To install all dependencies under OpenSUSE (except rtl-sdr), please type: diff --git a/nbproject/private/configurations.xml b/nbproject/private/configurations.xml index 706acf31..0b5e7921 100644 --- a/nbproject/private/configurations.xml +++ b/nbproject/private/configurations.xml @@ -2,30 +2,18 @@ <configurationDescriptor version="97"> <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT"> <df root="." name="0"> - <df name="build"> - <df name="CMakeFiles"> - <df name="3.3.2"> - <df name="CompilerIdC"> - <in>CMakeCCompilerId.c</in> - </df> - </df> - <df name="CMakeTmp"> - </df> - <in>feature_tests.c</in> - </df> - <df name="src"> - <df name="CMakeFiles"> - <df name="afb-daemon.dir"> - </df> + <df name="doc"> + <df name="nbproject.template"> + <df name="private"> </df> </df> </df> - <df name="doc"> - </df> <df name="include"> <in>local-def.h</in> <in>proto-def.h</in> </df> + <df name="plugins"> + </df> <df name="src"> <in>SamplePost.c</in> <in>afbs-api.c</in> @@ -40,26 +28,16 @@ </df> </df> <df root="." name="1"> - <df name="build"> - <df name="CMakeFiles"> - <df name="3.3.2"> - <df name="CompilerIdC"> - </df> - </df> - <df name="CMakeTmp"> - </df> - </df> - <df name="src"> - <df name="CMakeFiles"> - <df name="afb-daemon.dir"> - </df> + <df name="doc"> + <df name="nbproject.template"> + <df name="private"> </df> </df> </df> - <df name="doc"> - </df> <df name="include"> </df> + <df name="plugins"> + </df> <df name="src"> </df> </df> @@ -89,8 +67,6 @@ <gdb_interceptlist> <gdbinterceptoptions gdb_all="false" gdb_unhandled="true" gdb_unexpected="true"/> </gdb_interceptlist> - <gdb_signals> - </gdb_signals> <gdb_options> <DebugOptions> </DebugOptions> diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml index 795635d6..10916bd0 100644 --- a/nbproject/private/private.xml +++ b/nbproject/private/private.xml @@ -6,6 +6,11 @@ </data> <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/> <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2"> - <group/> + <group> + <file>file:/home/mbc/git/afb-daemon-newapi/include/local-def.h</file> + <file>file:/home/mbc/git/afb-daemon-newapi/src/radio-api.c</file> + <file>file:/home/mbc/git/afb-daemon-newapi/src/afbs-api.c</file> + <file>file:/home/mbc/git/afb-daemon-newapi/src/dbus-api.c</file> + </group> </open-files> </project-private> diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 00000000..269517ad --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,8 @@ +SET(PLUGINS_SOURCES audio/audio-api.c session/token-api.c) + +IF(librtlsdr_FOUND) + SET(PLUGINS_SOURCES ${PLUGINS_SOURCES} radio/radio-api.c) +ENDIF(librtlsdr_FOUND) + +ADD_LIBRARY(plugins OBJECT ${PLUGINS_SOURCES}) +INCLUDE_DIRECTORIES(${include_dirs}) diff --git a/src/alsa-api.c b/plugins/audio/audio-api.c index 9d4f3cb6..9d4f3cb6 100644 --- a/src/alsa-api.c +++ b/plugins/audio/audio-api.c diff --git a/src/radio-api.c b/plugins/radio/radio-api.c index ef345044..a3e230b1 100644 --- a/src/radio-api.c +++ b/plugins/radio/radio-api.c @@ -461,38 +461,6 @@ STATIC void* _output_thread_fn (void *ctx) { } - -STATIC json_object* start (AFB_session *session, AFB_request *request, void* handle) { - json_object *response; - char query [512]; - - // request all query key/value - getQueryAll (request, query, sizeof(query)); - - // check if we have some post data - if (request->post == NULL) request->post="NoData"; - - // return response to caller - response = jsonNewMessage(AFB_SUCCESS, "Start Radio plugin query={%s} PostData: \'%s\' ", query, request->post); - - //if (verbose) fprintf(stderr, "%d: \n", pingcount); - return (response); -} - -STATIC json_object* stop (AFB_session *session, AFB_request *request, void* handle) { - json_object *response; - char query [512]; - - getQueryAll (request, query, sizeof(query)); - - if (request->post == NULL) request->post="NoData"; - - response = jsonNewMessage(AFB_SUCCESS, "Stop Radio plugin query={%s} PostData: \'%s\' ", query, request->post); - - return (response); -} - - // ******************************************************** // FULUP integration proposal with client session context @@ -641,11 +609,24 @@ STATIC json_object* powerOnOff (AFB_request *request) { // At this point we should have something to retreive radio status before last poweroff [but this is only a demonstrator] } +STATIC json_object* start (AFB_request *request) { + return NULL; +} + +STATIC json_object* stop (AFB_request *request) { + return NULL; +} + +STATIC json_object* status (AFB_request *request) { + return NULL; +} + STATIC AFB_restapi pluginApis[]= { - {"power" , (AFB_apiCB)powerOnOff , "Ping Application Framework"}, - {"start" , (AFB_apiCB)start , "Ping Application Framework"}, - {"stop" , (AFB_apiCB)stop , "Ping Application Framework"}, + {"power" , AFB_SESSION_CREATE, (AFB_apiCB)powerOnOff , "Ping Application Framework"}, + {"start" , AFB_SESSION_CHECK, (AFB_apiCB)start , "Ping Application Framework"}, + {"stop" , AFB_SESSION_CHECK, (AFB_apiCB)stop , "Ping Application Framework"}, + {"status" , AFB_SESSION_RENEW, (AFB_apiCB)status , "Ping Application Framework"}, {NULL} }; diff --git a/src/dbus-api.c b/plugins/samples/HelloWorld.c index 70de03f0..70de03f0 100644 --- a/src/dbus-api.c +++ b/plugins/samples/HelloWorld.c diff --git a/src/afbs-api.c b/plugins/samples/SamplePost.c index 9e1c7660..9e1c7660 100644 --- a/src/afbs-api.c +++ b/plugins/samples/SamplePost.c diff --git a/plugins/session/token-api.c b/plugins/session/token-api.c new file mode 100644 index 00000000..9e1c7660 --- /dev/null +++ b/plugins/session/token-api.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2015 "IoT.bzh" + * Author "Fulup Ar Foll" + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + */ + + +#include "local-def.h" + +// Dummy sample of Client Application Context +typedef struct { + int something; + void *whateveryouwant; +} MyClientApplicationHandle; + + +// Request Creation of new context if it does not exist +STATIC json_object* clientContextCreate (AFB_request *request) { + json_object *jresp; + + // add an application specific client context to session + request->client->ctx = malloc (sizeof (MyClientApplicationHandle)); + + // Send response to UI + jresp = json_object_new_object(); + json_object_object_add(jresp, "token", json_object_new_string ("A New Token and Session Context Was Created")); + + return (jresp); +} + +// Before entering here token will be check and renew +STATIC json_object* clientContextRefresh (AFB_request *request) { + json_object *jresp; + + + jresp = json_object_new_object(); + json_object_object_add(jresp, "token", json_object_new_string ("Token was refreshed")); + + return (jresp); +} + + +// Session token will we verified before entering here +STATIC json_object* clientContextCheck (AFB_request *request) { + + json_object *jresp = json_object_new_object(); + json_object_object_add(jresp, "isvalid", json_object_new_boolean (TRUE)); + + return (jresp); +} + + +// Close and Free context +STATIC json_object* clientContextReset (AFB_request *request) { + json_object *jresp; + + jresp = json_object_new_object(); + json_object_object_add(jresp, "uuid", json_object_new_string (request->client->uuid)); + + return (jresp); +} + +// In this case or handle is quite basic +typedef struct { + int fd; +} appPostCtx; + +// This function is call when PostForm processing is completed +STATIC void DonePostForm (AFB_request *request) { + AFB_PostHandle *postHandle = (AFB_PostHandle*)request->post->data; + appPostCtx *appCtx= postHandle->ctx; + + // Close upload file ID + close (appCtx->fd); + + // Free application specific handle + free (postHandle->ctx); + + if (verbose) fprintf (stderr, "DonePostForm upload done\n"); +} + + +// WARNING: PostForm callback are call multiple time (one or each key within form) +// When processing POST_JSON request->data hold a PostHandle and not data directly as for POST_JSON +STATIC json_object* ProcessPostForm (AFB_request *request, AFB_PostItem *item) { + + AFB_PostHandle *postHandle; + appPostCtx *appCtx; + char filepath[512]; + + // When Post is fully processed the same callback is call with a item==NULL + if (item == NULL) { + // Close file, Free handle + + request->errcode = MHD_HTTP_OK; + return(jsonNewMessage(AFB_SUCCESS,"File [%s] uploaded at [%s] error=\n", item->filename, request->config->sessiondir)); + } + + // Let's make sure this is a valid PostForm request + if (!request->post && request->post->type != AFB_POST_FORM) { + request->errcode = MHD_HTTP_FORBIDDEN; + return(jsonNewMessage(AFB_FAIL,"This is not a valid PostForm request\n")); + } else { + // In AFB_POST_FORM case post->data is a PostForm handle + postHandle = (AFB_PostHandle*) request->post->data; + appCtx = (appPostCtx*) postHandle->ctx; + } + + // Check this is a file element + if (0 != strcmp (item->key, "file")) { + request->errcode = MHD_HTTP_FORBIDDEN; + return (jsonNewMessage(AFB_FAIL,"No File within element key=%s\n", item->key)); + } + + // This is the 1st Item iteration let's open output file and allocate necessary resources + if (postHandle->ctx == NULL) { + int fd; + + strncpy (filepath, request->config->sessiondir, sizeof(filepath)); + strncat (filepath, "/", sizeof(filepath)); + strncat (filepath, item->filename, sizeof(filepath)); + + if((fd = open(request->config->sessiondir, O_RDONLY)) < 0) { + request->errcode = MHD_HTTP_FORBIDDEN; + return (jsonNewMessage(AFB_FAIL,"Fail to Upload file [%s] at [%s] error=\n", item->filename, request->config->sessiondir, strerror(errno))); + }; + + // Create an application specific context + appCtx = malloc (sizeof(appPostCtx)); // May place anything here until post->completeCB handle resources liberation + appCtx->fd = fd; + + // attach application to postHandle + postHandle->ctx = (void*) appCtx; // May place anything here until post->completeCB handle resources liberation + postHandle->completeCB = (AFB_apiCB)DonePostForm; // CallBack when Form Processing is finished + + } else { + // this is not the call, FD is already open + appCtx = (appPostCtx*) postHandle->ctx; + } + + // We have something to write + if (item->len > 0) { + + if (!write (appCtx->fd, item->data, item->len)) { + request->errcode = MHD_HTTP_FORBIDDEN; + return (jsonNewMessage(AFB_FAIL,"Fail to write file [%s] at [%s] error=\n", item->filename, strerror(errno))); + } + } + + // every event should return Sucess or Form processing stop + request->errcode = MHD_HTTP_OK; + return NULL; +} + +// This function is call when Client Session Context is removed +// Note: when freeCtxCB==NULL standard free/malloc is called +STATIC void clientContextFree(AFB_clientCtx *client) { + fprintf (stderr,"Plugin[%s] Closing Session uuid=[%s]\n", client->plugin->prefix, client->uuid); + free (client->ctx); +} + +STATIC AFB_restapi pluginApis[]= { + {"ping" , AFB_SESSION_NONE , (AFB_apiCB)apiPingTest ,"Ping Rest Test Service"}, + {"token-create" , AFB_SESSION_CREATE, (AFB_apiCB)clientContextCreate ,"Request Client Context Creation"}, + {"token-refresh" , AFB_SESSION_RENEW , (AFB_apiCB)clientContextRefresh,"Refresh Client Context Token"}, + {"token-check" , AFB_SESSION_CHECK , (AFB_apiCB)clientContextCheck ,"Check Client Context Token"}, + {"token-reset" , AFB_SESSION_CLOSE , (AFB_apiCB)clientContextReset ,"Close Client Context and Free resources"}, + {"file-upload" , AFB_SESSION_NONE , (AFB_apiCB)ProcessPostForm ,"Demo for file upload"}, + {NULL} +}; + +PUBLIC AFB_plugin *afsvRegister () { + AFB_plugin *plugin = malloc (sizeof (AFB_plugin)); + plugin->type = AFB_PLUGIN_JSON; + plugin->info = "Application Framework Binder Service"; + plugin->prefix= "afbs"; // url base + plugin->apis = pluginApis; + plugin->handle= (void*) "What ever you want"; + plugin->freeCtxCB= (void*) clientContextFree; + + return (plugin); +};
\ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 663a7917..ed6947e9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,15 +1,6 @@ -SET(AFB-DAEMON_HEADERS local-def.h proto-def.h) -SET(AFB-DAEMON_SOURCES main.c config.c session.c http-svc.c afbs-api.c dbus-api.c rest-api.c alsa-api.c) - IF(librtlsdr_FOUND) ADD_DEFINITIONS(-DWITH_RADIO_PLUGIN=1) - SET(AFB-DAEMON_SOURCES ${AFB-DAEMON_SOURCES} radio-api.c) ENDIF(librtlsdr_FOUND) -ADD_EXECUTABLE(afb-daemon ${AFB-DAEMON_SOURCES}) - -include_directories(${include_dirs}) -target_link_libraries(afb-daemon ${link_libraries}) - -INSTALL(TARGETS afb-daemon - RUNTIME DESTINATION bin) +ADD_LIBRARY(src OBJECT main.c config.c session.c http-svc.c rest-api.c) +INCLUDE_DIRECTORIES(${include_dirs}) diff --git a/src/SamplePost.c b/src/SamplePost.c deleted file mode 100644 index 6d5c44be..00000000 --- a/src/SamplePost.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2015 "IoT.bzh" - * Author "Fulup Ar Foll" - * - * 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 3 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, see <http://www.gnu.org/licenses/>. - */ - -#include <sys/types.h> -#include <sys/select.h> -#include <sys/socket.h> -#include <microhttpd.h> - -#define PORT 8888 -#define POSTBUFFERSIZE 512 -#define MAXCLIENTS 2 - -#define GET 0 -#define POST 1 - -static unsigned int nr_of_uploading_clients = 0; - -struct connection_info_struct -{ - int connectiontype; - struct MHD_PostProcessor *postprocessor; - FILE *fp; - const char *answerstring; - int answercode; -}; - -const char *askpage = "<html><body>\n\ - Upload a file, please!<br>\n\ - There are %u clients uploading at the moment.<br>\n\ - <form action=\"/filepost\" method=\"post\" enctype=\"multipart/form-data\">\n\ - <input name=\"file\" type=\"file\">\n\ - <input type=\"submit\" value=\" Send \"></form>\n\ - </body></html>"; - -const char *busypage = - "<html><body>This server is busy, please try again later.</body></html>"; - -const char *completepage = - "<html><body>The upload has been completed.</body></html>"; - -const char *errorpage = - "<html><body>This doesn't seem to be right.</body></html>"; -const char *servererrorpage = - "<html><body>An internal server error has occured.</body></html>"; -const char *fileexistspage = - "<html><body>This file already exists.</body></html>"; - - -static int -send_page (struct MHD_Connection *connection, const char *page, - int status_code) -{ - int ret; - struct MHD_Response *response; - - response = - MHD_create_response_from_buffer (strlen (page), (void *) page, - MHD_RESPMEM_PERSISTENT); - if (!response) - return MHD_NO; - - ret = MHD_queue_response (connection, status_code, response); - MHD_destroy_response (response); - - return ret; -} - - -static int -iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key, - const char *filename, const char *content_type, - const char *transfer_encoding, const char *data, uint64_t off, - size_t size) -{ - struct connection_info_struct *con_info = coninfo_cls; - FILE *fp; - - con_info->answerstring = servererrorpage; - con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR; - - if (0 != strcmp (key, "file")) - return MHD_NO; - - if (!con_info->fp) - { - if (NULL != (fp = fopen (filename, "rb"))) - { - fclose (fp); - con_info->answerstring = fileexistspage; - con_info->answercode = MHD_HTTP_FORBIDDEN; - return MHD_NO; - } - - con_info->fp = fopen (filename, "ab"); - if (!con_info->fp) - return MHD_NO; - } - - if (size > 0) - { - if (!fwrite (data, size, sizeof (char), con_info->fp)) - return MHD_NO; - } - - con_info->answerstring = completepage; - con_info->answercode = MHD_HTTP_OK; - - return MHD_YES; -} - -static void -request_completed (void *cls, struct MHD_Connection *connection, - void **con_cls, enum MHD_RequestTerminationCode toe) -{ - struct connection_info_struct *con_info = *con_cls; - - if (NULL == con_info) - return; - - if (con_info->connectiontype == POST) - { - if (NULL != con_info->postprocessor) - { - MHD_destroy_post_processor (con_info->postprocessor); - nr_of_uploading_clients--; - } - - if (con_info->fp) - fclose (con_info->fp); - } - - free (con_info); - *con_cls = NULL; -} - - -static int -answer_to_connection (void *cls, struct MHD_Connection *connection, - const char *url, const char *method, - const char *version, const char *upload_data, - size_t *upload_data_size, void **con_cls) -{ - if (NULL == *con_cls) - { - struct connection_info_struct *con_info; - - if (nr_of_uploading_clients >= MAXCLIENTS) - return send_page (connection, busypage, MHD_HTTP_SERVICE_UNAVAILABLE); - - con_info = malloc (sizeof (struct connection_info_struct)); - if (NULL == con_info) - return MHD_NO; - - con_info->fp = NULL; - - if (0 == strcmp (method, "POST")) - { - con_info->postprocessor = - MHD_create_post_processor (connection, POSTBUFFERSIZE, - iterate_post, (void *) con_info); - - if (NULL == con_info->postprocessor) - { - free (con_info); - return MHD_NO; - } - - nr_of_uploading_clients++; - - con_info->connectiontype = POST; - con_info->answercode = MHD_HTTP_OK; - con_info->answerstring = completepage; - } - else - con_info->connectiontype = GET; - - *con_cls = (void *) con_info; - - return MHD_YES; - } - - if (0 == strcmp (method, "GET")) - { - int ret; - char buffer[1024]; - - sprintf (buffer, askpage, nr_of_uploading_clients); - return send_page (connection, buffer, MHD_HTTP_OK); - } - - if (0 == strcmp (method, "POST")) - { - struct connection_info_struct *con_info = *con_cls; - - if (0 != *upload_data_size) - { - MHD_post_process (con_info->postprocessor, upload_data, - *upload_data_size); - *upload_data_size = 0; - - return MHD_YES; - } - else - return send_page (connection, con_info->answerstring, - con_info->answercode); - } - - return send_page (connection, errorpage, MHD_HTTP_BAD_REQUEST); -} - -int -main () -{ - struct MHD_Daemon *daemon; - - - daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL, - &answer_to_connection, NULL, - MHD_OPTION_NOTIFY_COMPLETED, request_completed, - NULL, MHD_OPTION_END); - if (NULL == daemon) - return 1; - - getchar (); - - MHD_stop_daemon (daemon); - - return 0; -}
\ No newline at end of file diff --git a/src/rest-api.c b/src/rest-api.c index ad3a4f22..c1110c51 100644 --- a/src/rest-api.c +++ b/src/rest-api.c @@ -613,7 +613,6 @@ void initPlugins(AFB_session *session) { int i = 0; plugins[i++] = afsvRegister(session), - plugins[i++] = dbusRegister(session), plugins[i++] = alsaRegister(session), #ifdef HAVE_RADIO_PLUGIN plugins[i++] = radioRegister(session), |