From 7059e59cddc1c81321639875636e88895bc14309 Mon Sep 17 00:00:00 2001
From: José Bollo <jose.bollo@iot.bzh>
Date: Thu, 23 Jun 2016 20:34:57 +0200
Subject: vocabulary: moving from 'plugin' to 'binding'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Change-Id: Ic9e118df2bede1fefbb591f8ae7887266b7324ca
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
---
 CMakeLists.txt                         |    4 +-
 afb-daemon.pc.in                       |    2 +-
 bindings/CMakeLists.txt                |    5 +
 bindings/audio/CMakeLists.txt          |   27 +
 bindings/audio/audio-alsa.c            |  311 ++++++++
 bindings/audio/audio-alsa.h            |   56 ++
 bindings/audio/audio-api.c             |  383 ++++++++++
 bindings/audio/audio-api.h             |   38 +
 bindings/audio/audio-pulse.c           |  491 +++++++++++++
 bindings/audio/audio-pulse.h           |   66 ++
 bindings/audio/export.map              |    1 +
 bindings/intrinsics/CMakeLists.txt     |   15 +
 bindings/intrinsics/afb-dbus-binding.c |  631 ++++++++++++++++
 bindings/intrinsics/export.map         |    1 +
 bindings/media/CMakeLists.txt          |   18 +
 bindings/media/export.map              |    1 +
 bindings/media/media-api.c             |  331 +++++++++
 bindings/media/media-api.h             |   29 +
 bindings/media/media-rygel.c           |  721 +++++++++++++++++++
 bindings/media/media-rygel.h           |   68 ++
 bindings/radio/CMakeLists.txt          |   17 +
 bindings/radio/export.map              |    1 +
 bindings/radio/radio-api.c             |  376 ++++++++++
 bindings/radio/radio-api.h             |   49 ++
 bindings/radio/radio-rtlsdr.c          |  427 +++++++++++
 bindings/radio/radio-rtlsdr.h          |  100 +++
 bindings/samples/AuthLogin.c           |  129 ++++
 bindings/samples/CMakeLists.txt        |   63 ++
 bindings/samples/DemoContext.c         |  160 +++++
 bindings/samples/DemoPost.c            |  100 +++
 bindings/samples/HelloWorld.c          |  279 ++++++++
 bindings/samples/export.map            |    1 +
 bindings/samples/tic-tac-toe.c         |  605 ++++++++++++++++
 doc/FAQ.html                           |    2 +-
 doc/afb-application-writing.html       |    2 +-
 doc/afb-bindings-overview.html         |  157 ++++
 doc/afb-bindings-overview.md           |  168 +++++
 doc/afb-bindings-writing.html          |  951 +++++++++++++++++++++++++
 doc/afb-bindings-writing.md            | 1227 ++++++++++++++++++++++++++++++++
 doc/afb-daemon-vocabulary.html         |   14 +-
 doc/afb-daemon-vocabulary.md           |   16 +-
 doc/afb-overview.html                  |   42 +-
 doc/afb-overview.md                    |   44 +-
 doc/afb-plugin-writing.html            |  953 -------------------------
 doc/afb-plugin-writing.md              | 1227 --------------------------------
 doc/afb-plugins-overview.html          |  159 -----
 doc/afb-plugins-overview.md            |  168 -----
 doc/afb-tests-overview.html            |    6 +-
 doc/afb-tests-overview.md              |    4 +-
 include/afb/afb-binding.h              |  261 +++++++
 include/afb/afb-event-itf.h            |    2 +-
 include/afb/afb-plugin.h               |  253 +------
 include/afb/afb-req-itf.h              |   14 +-
 include/afb/afb-service-itf.h          |    4 +-
 plugins/CMakeLists.txt                 |    5 -
 plugins/audio/CMakeLists.txt           |   27 -
 plugins/audio/audio-alsa.c             |  311 --------
 plugins/audio/audio-alsa.h             |   56 --
 plugins/audio/audio-api.c              |  383 ----------
 plugins/audio/audio-api.h              |   38 -
 plugins/audio/audio-pulse.c            |  491 -------------
 plugins/audio/audio-pulse.h            |   66 --
 plugins/audio/export.map               |    1 -
 plugins/intrinsics/CMakeLists.txt      |   15 -
 plugins/intrinsics/afb-dbus-binding.c  |  633 ----------------
 plugins/intrinsics/export.map          |    1 -
 plugins/media/CMakeLists.txt           |   18 -
 plugins/media/export.map               |    1 -
 plugins/media/media-api.c              |  331 ---------
 plugins/media/media-api.h              |   29 -
 plugins/media/media-rygel.c            |  721 -------------------
 plugins/media/media-rygel.h            |   68 --
 plugins/radio/CMakeLists.txt           |   17 -
 plugins/radio/export.map               |    1 -
 plugins/radio/radio-api.c              |  376 ----------
 plugins/radio/radio-api.h              |   49 --
 plugins/radio/radio-rtlsdr.c           |  427 -----------
 plugins/radio/radio-rtlsdr.h           |  100 ---
 plugins/samples/AuthLogin.c            |  129 ----
 plugins/samples/CMakeLists.txt         |   63 --
 plugins/samples/DemoContext.c          |  160 -----
 plugins/samples/DemoPost.c             |  100 ---
 plugins/samples/HelloWorld.c           |  279 --------
 plugins/samples/export.map             |    1 -
 plugins/samples/tic-tac-toe.c          |  605 ----------------
 src/CMakeLists.txt                     |    2 +-
 src/afb-api-dbus.c                     |    1 -
 src/afb-api-so.c                       |  114 +--
 src/afb-api-so.h                       |    2 +-
 src/main.c                             |   32 +-
 90 files changed, 8438 insertions(+), 8395 deletions(-)
 create mode 100644 bindings/CMakeLists.txt
 create mode 100644 bindings/audio/CMakeLists.txt
 create mode 100644 bindings/audio/audio-alsa.c
 create mode 100644 bindings/audio/audio-alsa.h
 create mode 100644 bindings/audio/audio-api.c
 create mode 100644 bindings/audio/audio-api.h
 create mode 100644 bindings/audio/audio-pulse.c
 create mode 100644 bindings/audio/audio-pulse.h
 create mode 100644 bindings/audio/export.map
 create mode 100644 bindings/intrinsics/CMakeLists.txt
 create mode 100644 bindings/intrinsics/afb-dbus-binding.c
 create mode 100644 bindings/intrinsics/export.map
 create mode 100644 bindings/media/CMakeLists.txt
 create mode 100644 bindings/media/export.map
 create mode 100644 bindings/media/media-api.c
 create mode 100644 bindings/media/media-api.h
 create mode 100644 bindings/media/media-rygel.c
 create mode 100644 bindings/media/media-rygel.h
 create mode 100644 bindings/radio/CMakeLists.txt
 create mode 100644 bindings/radio/export.map
 create mode 100644 bindings/radio/radio-api.c
 create mode 100644 bindings/radio/radio-api.h
 create mode 100644 bindings/radio/radio-rtlsdr.c
 create mode 100644 bindings/radio/radio-rtlsdr.h
 create mode 100644 bindings/samples/AuthLogin.c
 create mode 100644 bindings/samples/CMakeLists.txt
 create mode 100644 bindings/samples/DemoContext.c
 create mode 100644 bindings/samples/DemoPost.c
 create mode 100644 bindings/samples/HelloWorld.c
 create mode 100644 bindings/samples/export.map
 create mode 100644 bindings/samples/tic-tac-toe.c
 create mode 100644 doc/afb-bindings-overview.html
 create mode 100644 doc/afb-bindings-overview.md
 create mode 100644 doc/afb-bindings-writing.html
 create mode 100644 doc/afb-bindings-writing.md
 delete mode 100644 doc/afb-plugin-writing.html
 delete mode 100644 doc/afb-plugin-writing.md
 delete mode 100644 doc/afb-plugins-overview.html
 delete mode 100644 doc/afb-plugins-overview.md
 create mode 100644 include/afb/afb-binding.h
 delete mode 100644 plugins/CMakeLists.txt
 delete mode 100644 plugins/audio/CMakeLists.txt
 delete mode 100644 plugins/audio/audio-alsa.c
 delete mode 100644 plugins/audio/audio-alsa.h
 delete mode 100644 plugins/audio/audio-api.c
 delete mode 100644 plugins/audio/audio-api.h
 delete mode 100644 plugins/audio/audio-pulse.c
 delete mode 100644 plugins/audio/audio-pulse.h
 delete mode 100644 plugins/audio/export.map
 delete mode 100644 plugins/intrinsics/CMakeLists.txt
 delete mode 100644 plugins/intrinsics/afb-dbus-binding.c
 delete mode 100644 plugins/intrinsics/export.map
 delete mode 100644 plugins/media/CMakeLists.txt
 delete mode 100644 plugins/media/export.map
 delete mode 100644 plugins/media/media-api.c
 delete mode 100644 plugins/media/media-api.h
 delete mode 100644 plugins/media/media-rygel.c
 delete mode 100644 plugins/media/media-rygel.h
 delete mode 100644 plugins/radio/CMakeLists.txt
 delete mode 100644 plugins/radio/export.map
 delete mode 100644 plugins/radio/radio-api.c
 delete mode 100644 plugins/radio/radio-api.h
 delete mode 100644 plugins/radio/radio-rtlsdr.c
 delete mode 100644 plugins/radio/radio-rtlsdr.h
 delete mode 100644 plugins/samples/AuthLogin.c
 delete mode 100644 plugins/samples/CMakeLists.txt
 delete mode 100644 plugins/samples/DemoContext.c
 delete mode 100644 plugins/samples/DemoPost.c
 delete mode 100644 plugins/samples/HelloWorld.c
 delete mode 100644 plugins/samples/export.map
 delete mode 100644 plugins/samples/tic-tac-toe.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 955eb20a..3ec58293 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -63,11 +63,11 @@ SET(link_libraries
 	${json-c_LIBRARIES}
 	)
 
-SET(plugin_install_dir ${CMAKE_INSTALL_FULL_LIBDIR}/afb)
+SET(binding_install_dir ${CMAKE_INSTALL_FULL_LIBDIR}/afb)
 
 ADD_SUBDIRECTORY(src)
 ADD_SUBDIRECTORY(include)
-ADD_SUBDIRECTORY(plugins)
+ADD_SUBDIRECTORY(bindings)
 
 ############################################################
 # installs the pkgconfig files
diff --git a/afb-daemon.pc.in b/afb-daemon.pc.in
index 23075eb9..34a470a3 100644
--- a/afb-daemon.pc.in
+++ b/afb-daemon.pc.in
@@ -18,7 +18,7 @@
 ##
 
 includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
-plugin_install_dir=@plugin_install_dir@
+binding_install_dir=@binding_install_dir@
 
 Name: @PROJECT_PRETTY_NAME@
 Description: @PROJECT_DESCRIPTION@
diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt
new file mode 100644
index 00000000..2aacf1a1
--- /dev/null
+++ b/bindings/CMakeLists.txt
@@ -0,0 +1,5 @@
+ADD_SUBDIRECTORY(samples)
+ADD_SUBDIRECTORY(audio)
+ADD_SUBDIRECTORY(radio)
+ADD_SUBDIRECTORY(media)
+ADD_SUBDIRECTORY(intrinsics)
diff --git a/bindings/audio/CMakeLists.txt b/bindings/audio/CMakeLists.txt
new file mode 100644
index 00000000..11da28e1
--- /dev/null
+++ b/bindings/audio/CMakeLists.txt
@@ -0,0 +1,27 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(alsa alsa)
+PKG_CHECK_MODULES(pulseaudio libpulse libpulse-simple)
+INCLUDE(FindThreads)
+FIND_PACKAGE(Threads)
+
+IF(alsa_FOUND)
+
+  MESSAGE(STATUS "ALSA found ; will compile Audio binding... (BINDING)")
+
+  IF(pulseaudio_FOUND)
+    MESSAGE(STATUS "PulseAudio found ; Audio binding will have PulseAudio support")
+    ADD_DEFINITIONS(-DHAVE_PULSE=1)
+    SET(pulse_sources audio-pulse.c)
+  ENDIF(pulseaudio_FOUND)
+
+  INCLUDE_DIRECTORIES(${include_dirs} ${alsa_INCLUDE_DIRS} ${pulseaudio_INCLUDE_DIRS})
+  ADD_LIBRARY(audio-api MODULE audio-api.c audio-alsa.c ${pulse_sources})
+  SET_TARGET_PROPERTIES(audio-api PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
+  )
+  TARGET_LINK_LIBRARIES(audio-api ${link_libraries} ${alsa_LIBRARIES} ${pulseaudio_LIBRARIES})
+  INSTALL(TARGETS audio-api
+          LIBRARY DESTINATION ${binding_install_dir})
+
+ENDIF(alsa_FOUND)
diff --git a/bindings/audio/audio-alsa.c b/bindings/audio/audio-alsa.c
new file mode 100644
index 00000000..45ff2edb
--- /dev/null
+++ b/bindings/audio/audio-alsa.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "audio-api.h"
+#include "audio-alsa.h"
+
+snd_mixer_selem_channel_id_t SCHANNELS[8] = {
+ SND_MIXER_SCHN_FRONT_LEFT,
+ SND_MIXER_SCHN_FRONT_RIGHT,
+ SND_MIXER_SCHN_FRONT_CENTER,
+ SND_MIXER_SCHN_REAR_LEFT,
+ SND_MIXER_SCHN_REAR_RIGHT,
+ SND_MIXER_SCHN_REAR_CENTER,
+ SND_MIXER_SCHN_SIDE_LEFT,
+ SND_MIXER_SCHN_SIDE_RIGHT
+};
+
+static struct dev_ctx_alsa **dev_ctx_a = NULL;
+
+
+unsigned char _alsa_init (const char *name, audioCtxHandleT *ctx) {
+
+    snd_pcm_t *dev;
+    snd_pcm_hw_params_t *params;
+    snd_mixer_t *mixer;
+    snd_mixer_selem_id_t *mixer_sid;
+    snd_mixer_elem_t *mixer_elm;
+    snd_mixer_elem_t *mixer_elm_m;
+    unsigned int rate = 22050;
+    long vol, vol_min, vol_max;
+    int num, i;
+
+    if (snd_pcm_open (&dev, name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
+        fprintf (stderr, "ALSA backend could not open card '%s'\n", name);
+        return 0;
+    }
+
+    snd_pcm_hw_params_malloc (&params);
+    snd_pcm_hw_params_any (dev, params);
+    snd_pcm_hw_params_set_access (dev, params, SND_PCM_ACCESS_RW_INTERLEAVED);
+    snd_pcm_hw_params_set_format (dev, params, SND_PCM_FORMAT_S16_LE);
+    snd_pcm_hw_params_set_rate_near (dev, params, &rate, 0);
+    snd_pcm_hw_params_set_channels (dev, params, ctx->channels);
+    if (snd_pcm_hw_params (dev, params) < 0) {
+        snd_pcm_hw_params_free (params);
+        fprintf (stderr, "ALSA backend could set channels on card '%s'\n", name);
+        return 0;
+    }
+    snd_pcm_prepare (dev);
+
+    snd_mixer_open (&mixer, 0);
+    if (snd_mixer_attach (mixer, name) < 0) {
+        snd_pcm_hw_params_free (params);
+        fprintf (stderr, "ALSA backend could not open mixer for card '%s'\n", name);
+        return 0;
+    }
+    snd_mixer_selem_register (mixer, NULL, NULL);
+    snd_mixer_load (mixer);
+
+    snd_mixer_selem_id_alloca (&mixer_sid);
+    snd_mixer_selem_id_set_index (mixer_sid, 0);
+    snd_mixer_selem_id_set_name (mixer_sid, "Master");
+
+    mixer_elm = snd_mixer_find_selem (mixer, mixer_sid);
+    mixer_elm_m = NULL;
+
+    if (!mixer_elm) {
+        /* no "Master" mixer ; we are probably on a board... search ! */
+        for (mixer_elm = snd_mixer_first_elem (mixer); mixer_elm != NULL;
+             mixer_elm = snd_mixer_elem_next (mixer_elm)) {
+            if (snd_mixer_elem_info (mixer_elm) < 0)
+                continue;
+            snd_mixer_selem_get_id (mixer_elm, mixer_sid);
+            if (strstr (snd_mixer_selem_id_get_name (mixer_sid), "DVC Out")) {
+
+                /* this is Porter... let us found the specific mute switch */
+                snd_mixer_selem_id_set_index (mixer_sid, 0);
+                snd_mixer_selem_id_set_name (mixer_sid, "DVC Out Mute");
+                mixer_elm_m = snd_mixer_find_selem (mixer, mixer_sid);
+
+                break;
+            }
+        }
+    }
+
+    if (mixer_elm) {
+        snd_mixer_selem_get_playback_volume_range (mixer_elm, &vol_min, &vol_max);
+        snd_mixer_selem_get_playback_volume (mixer_elm, SND_MIXER_SCHN_FRONT_LEFT, &vol);
+    }
+
+    /* allocate the global array if it hasn't been done */
+    if (!dev_ctx_a) {
+        dev_ctx_a = (dev_ctx_alsa_T**) malloc (sizeof(dev_ctx_alsa_T*));
+        dev_ctx_a[0] = (dev_ctx_alsa_T*) malloc (sizeof(dev_ctx_alsa_T));
+        dev_ctx_a[0]->name = NULL;
+        dev_ctx_a[0]->dev = NULL;
+    }
+
+    /* is a card with similar name already opened ? */
+    for (num = 0; num < (sizeof(dev_ctx_a)/sizeof(dev_ctx_alsa_T*)); num++) {
+        if (dev_ctx_a[num]->name &&
+           !strcmp (dev_ctx_a[num]->name, name)) {
+            fprintf (stderr, "Card '%s' already locked by other ALSA backend session\n", name);
+            return 0;
+        }
+    }
+    num--;
+
+    /* it's not... let us add it to the global array */
+    dev_ctx_a = (dev_ctx_alsa_T**) realloc (dev_ctx_a, (num+1)*sizeof(dev_ctx_alsa_T*));
+    if (!dev_ctx_a[num])
+        dev_ctx_a[num] = (dev_ctx_alsa_T*) malloc (sizeof(dev_ctx_alsa_T));
+    dev_ctx_a[num]->name = strdup (name);
+    dev_ctx_a[num]->dev = dev;
+    dev_ctx_a[num]->params = params;
+    dev_ctx_a[num]->mixer_elm = mixer_elm;
+    dev_ctx_a[num]->mixer_elm_m = mixer_elm_m;
+    dev_ctx_a[num]->vol_max = vol_max;
+    dev_ctx_a[num]->vol = vol;
+    dev_ctx_a[num]->thr_should_run = 0;
+    dev_ctx_a[num]->thr_finished = 0;
+
+    /* make the client context aware of current card state */
+    for (i = 0; i < 8; i++)
+        ctx->volume[i] = _alsa_get_volume (num, i);
+    ctx->mute = _alsa_get_mute (num);
+    ctx->idx = num;
+    ctx->name = strdup (name);
+
+    fprintf (stderr, "Successfully initialized ALSA backend.\n");
+
+    return 1;
+}
+
+void _alsa_free (const char *name) {
+
+    int num;
+
+    for (num = 0; num < (sizeof(dev_ctx_a)/sizeof(dev_ctx_alsa_T*)); num++) {
+        if (dev_ctx_a[num]->name &&
+           !strcmp (dev_ctx_a[num]->name, name)) {
+            snd_pcm_close (dev_ctx_a[num]->dev);
+            snd_pcm_hw_params_free (dev_ctx_a[num]->params);
+            free (dev_ctx_a[num]->name);
+            dev_ctx_a[num]->dev = NULL;
+            dev_ctx_a[num]->name = NULL;
+            free (dev_ctx_a[num]);
+            return;
+        }
+    }
+}
+
+void _alsa_play (int num) {
+
+    if (!dev_ctx_a || !dev_ctx_a[num] || dev_ctx_a[num]->thr_should_run ||
+        access (AUDIO_BUFFER, F_OK) == -1)
+        return;
+
+    dev_ctx_a[num]->thr_should_run = 1;
+    dev_ctx_a[num]->thr_finished = 0;
+    pthread_create (&dev_ctx_a[num]->thr, NULL, _alsa_play_thread_fn, (void*)dev_ctx_a[num]);
+}
+
+void _alsa_stop (int num) {
+
+    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->thr_should_run)
+        return;
+
+    /* stop the "while" loop in thread */
+    dev_ctx_a[num]->thr_should_run = 0;
+
+    while (!dev_ctx_a[num]->thr_finished)
+        usleep(100000);
+
+    pthread_join (dev_ctx_a[num]->thr, NULL);
+}
+
+unsigned int _alsa_get_volume (int num, unsigned int channel) {
+
+    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm)
+        return 0;
+
+    snd_mixer_selem_get_playback_volume (dev_ctx_a[num]->mixer_elm, SCHANNELS[channel], &dev_ctx_a[num]->vol);
+
+    return (unsigned int)(dev_ctx_a[num]->vol*100)/dev_ctx_a[num]->vol_max;
+}
+
+void _alsa_set_volume (int num, unsigned int channel, unsigned int vol) {
+
+    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm ||
+        vol > 100)
+        return;
+
+    snd_mixer_selem_set_playback_volume (dev_ctx_a[num]->mixer_elm, SCHANNELS[channel], (vol*dev_ctx_a[num]->vol_max)/100);
+}
+
+void _alsa_set_volume_all (int num, unsigned int vol) {
+
+    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm ||
+        vol > 100)
+
+    fflush (stdout); /* seems to force this logic to apply quickly */
+    snd_mixer_selem_set_playback_volume_all (dev_ctx_a[num]->mixer_elm, (vol*dev_ctx_a[num]->vol_max)/100);
+}
+
+unsigned char _alsa_get_mute (int num) {
+
+    int mute = 0;
+    snd_mixer_elem_t *elm_m;
+
+    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm)
+        return 0;
+
+    dev_ctx_a[num]->mixer_elm_m ? (elm_m = dev_ctx_a[num]->mixer_elm_m) :
+                                  (elm_m = dev_ctx_a[num]->mixer_elm);
+
+    if (snd_mixer_selem_has_playback_switch (elm_m)) {
+        snd_mixer_selem_get_playback_switch (elm_m, SND_MIXER_SCHN_FRONT_LEFT, &mute);
+        snd_mixer_selem_get_playback_switch (elm_m, SND_MIXER_SCHN_FRONT_RIGHT, &mute);
+    }
+
+    if (dev_ctx_a[num]->mixer_elm_m)
+        return (unsigned char)mute;
+    else
+        return (unsigned char)!mute;
+}
+
+void _alsa_set_mute (int num, unsigned char tomute) {
+
+    snd_mixer_elem_t *elm_m;
+    int mute;
+
+    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm || 1 < tomute)
+        return;
+
+    if (dev_ctx_a[num]->mixer_elm_m) {
+        elm_m = dev_ctx_a[num]->mixer_elm_m;
+        mute = (int)!tomute;
+    } else {
+        elm_m = dev_ctx_a[num]->mixer_elm;
+        mute = (int)tomute;
+    }
+
+    if (snd_mixer_selem_has_playback_switch (elm_m))
+        snd_mixer_selem_set_playback_switch_all (elm_m, !mute);
+}
+
+void _alsa_set_rate (int num, unsigned int rate) {
+
+    if (!dev_ctx_a || !dev_ctx_a[num])
+        return;
+
+    snd_pcm_hw_params_set_rate_near (dev_ctx_a[num]->dev, dev_ctx_a[num]->params, &rate, 0);
+}
+
+void _alsa_set_channels (int num, unsigned int channels) {
+
+    if (!dev_ctx_a || !dev_ctx_a[num])
+        return;
+
+    snd_pcm_hw_params_set_channels (dev_ctx_a[num]->dev, dev_ctx_a[num]->params, channels);
+}
+
+ /* ---- LOCAL THREADED FUNCTIONS ---- */
+
+void* _alsa_play_thread_fn (void *ctx) {
+
+    dev_ctx_alsa_T *dev_ctx_a = (dev_ctx_alsa_T *)ctx;
+    FILE *file = NULL;
+    char *buf = NULL;
+    long size;
+    int frames, res;
+
+    file = fopen (AUDIO_BUFFER, "rb");
+
+    while (dev_ctx_a->thr_should_run && file && (access (AUDIO_BUFFER, F_OK) != -1) ) {
+        fseek (file, 0, SEEK_END);
+        size = ftell (file);
+        buf = (char*) realloc (buf, size * sizeof(char));
+        frames = (size * sizeof(char)) / 4;
+
+        fseek (file, 0, SEEK_SET);
+        fread (buf, 1, size, file);
+        fflush (file);
+
+        if ((res = snd_pcm_writei (dev_ctx_a->dev, buf, frames)) != frames) {
+            snd_pcm_recover (dev_ctx_a->dev, res, 0);
+            snd_pcm_prepare (dev_ctx_a->dev);
+        }
+        /* snd_pcm_drain (dev_ctx->dev); */
+    }
+    if (buf) free(buf);
+    if (file) fclose(file);
+
+    dev_ctx_a->thr_finished = 1;
+    return 0;
+}
diff --git a/bindings/audio/audio-alsa.h b/bindings/audio/audio-alsa.h
new file mode 100644
index 00000000..679d4eee
--- /dev/null
+++ b/bindings/audio/audio-alsa.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_ALSA_H
+#define AUDIO_ALSA_H
+
+#include <pthread.h>
+#include <alsa/asoundlib.h>
+
+#include "audio-api.h"
+
+#define AUDIO_BUFFER "/tmp/audio_buf"
+
+typedef struct dev_ctx_alsa dev_ctx_alsa_T;
+
+struct dev_ctx_alsa {
+  char *name;
+  snd_pcm_t *dev;
+  snd_pcm_hw_params_t *params;
+  snd_mixer_elem_t *mixer_elm;
+  snd_mixer_elem_t *mixer_elm_m;
+  long vol_max;
+  long vol;
+  pthread_t thr;
+  unsigned char thr_should_run;
+  unsigned char thr_finished;
+};
+
+unsigned char _alsa_init (const char *, audioCtxHandleT *);
+void _alsa_free (const char *);
+void _alsa_play (int);
+void _alsa_stop (int);
+unsigned int _alsa_get_volume (int, unsigned int);
+void _alsa_set_volume (int, unsigned int, unsigned int);
+void _alsa_set_volume_all (int, unsigned int);
+unsigned char _alsa_get_mute (int);
+void _alsa_set_mute (int, unsigned char);
+void _alsa_set_channels (int, unsigned int);
+
+void* _alsa_play_thread_fn (void *);
+
+#endif /* AUDIO_ALSA_H */
diff --git a/bindings/audio/audio-api.c b/bindings/audio/audio-api.c
new file mode 100644
index 00000000..1ba9126c
--- /dev/null
+++ b/bindings/audio/audio-api.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <json-c/json.h>
+
+#include "audio-api.h"
+#include "audio-alsa.h"
+#ifdef HAVE_PULSE
+#include "audio-pulse.h"
+#endif
+
+#include <afb/afb-plugin.h>
+#include <afb/afb-req-itf.h>
+
+/* ------ BACKEND FUNCTIONS ------- */
+
+unsigned char _backend_init (const char *name, audioCtxHandleT *ctx) {
+
+    char *backend_env = getenv ("AFB_AUDIO_OUTPUT");
+    unsigned char res = 0;
+
+# ifdef HAVE_PULSE
+    if (!backend_env || (strcasecmp (backend_env, "Pulse") == 0))
+        res = _pulse_init (name, ctx);
+    if (!res)
+#endif
+    res = _alsa_init (name, ctx);
+
+    if (!res)
+        fprintf (stderr, "Could not initialize Audio backend\n");
+
+    return res;
+}
+
+void _backend_free (audioCtxHandleT *ctx) {
+
+# ifdef HAVE_PULSE
+    if (ctx->audio_dev) _pulse_free (ctx); else
+# endif
+    _alsa_free (ctx->name);
+}
+
+void _backend_play (audioCtxHandleT *ctx) {
+
+# ifdef HAVE_PULSE
+    if (ctx->audio_dev) _pulse_play (ctx); else
+# endif
+    _alsa_play (ctx->idx);
+}
+
+void _backend_stop (audioCtxHandleT *ctx) {
+
+# ifdef HAVE_PULSE
+    if (ctx->audio_dev) _pulse_stop (ctx); else
+# endif
+    _alsa_stop (ctx->idx);
+}
+
+unsigned int _backend_get_volume (audioCtxHandleT *ctx, unsigned int channel) {
+
+# ifdef HAVE_PULSE
+    if (ctx->audio_dev) return _pulse_get_volume (ctx, channel); else
+# endif
+    return _alsa_get_volume (ctx->idx, channel);
+}
+
+void _backend_set_volume (audioCtxHandleT *ctx, unsigned int channel, unsigned int vol) {
+
+# ifdef HAVE_PULSE
+    if (ctx->audio_dev) _pulse_set_volume (ctx, channel, vol); else
+# endif
+    _alsa_set_volume (ctx->idx, channel, vol);
+}
+
+void _backend_set_volume_all (audioCtxHandleT *ctx, unsigned int vol) {
+
+# ifdef HAVE_PULSE
+    if (ctx->audio_dev) _pulse_set_volume_all (ctx, vol); else
+# endif
+    _alsa_set_volume_all (ctx->idx, vol);
+}
+
+unsigned char _backend_get_mute (audioCtxHandleT *ctx) {
+
+# ifdef HAVE_PULSE
+    if (ctx->audio_dev) return _pulse_get_mute (ctx); else
+# endif
+    return _alsa_get_mute (ctx->idx);
+}
+
+void _backend_set_mute (audioCtxHandleT *ctx, unsigned char mute) {
+
+# ifdef HAVE_PULSE
+    if (ctx->audio_dev) _pulse_set_mute (ctx, mute); else
+# endif
+    _alsa_set_mute (ctx->idx, mute);
+}
+
+void _backend_set_channels (audioCtxHandleT *ctx, unsigned int channels) {
+
+# ifdef HAVE_PULSE
+    if (ctx->audio_dev) return; else
+# endif
+    _alsa_set_channels (ctx->idx, channels);
+}
+
+/* ------ LOCAL HELPER FUNCTIONS --------- */
+
+/* private client context constructor ; default values */
+static audioCtxHandleT* initAudioCtx () {
+
+    audioCtxHandleT *ctx;
+    int i;
+
+    ctx = malloc (sizeof(audioCtxHandleT));
+    ctx->audio_dev = NULL;
+    ctx->name = NULL;
+    ctx->idx = -1;
+    for (i = 0; i < 8; i++)
+        ctx->volume[i] = 25;
+    ctx->channels = 2;
+    ctx->mute = 0;
+    ctx->is_playing = 0;
+
+    return ctx;
+}
+
+static void releaseAudioCtx (void *context) {
+
+    audioCtxHandleT *ctx = (audioCtxHandleT*) context;
+
+    /* power it off */
+    _backend_free (ctx);
+
+    /* clean client context */
+    ctx->audio_dev = NULL;
+    if (ctx->name)
+		free (ctx->name);
+    ctx->idx = -1;
+    free (ctx);
+}
+
+
+/* ------ PUBLIC PLUGIN FUNCTIONS --------- */
+
+static void init (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    audioCtxHandleT *ctx = afb_req_context_get (request);
+    json_object *jresp;
+
+    /* create a private client context */
+	if (!ctx) {
+        ctx = initAudioCtx();
+        afb_req_context_set (request, ctx, releaseAudioCtx);
+    }
+
+    if (!_backend_init ("default", ctx))
+        afb_req_fail (request, "failed", "backend initialization failed");
+
+    jresp = json_object_new_object();
+    json_object_object_add (jresp, "init", json_object_new_string ("success"));
+    afb_req_success (request, jresp, "Audio initialized");
+}
+
+static void volume (struct afb_req request) {      /* AFB_SESSION_CHECK */
+
+    audioCtxHandleT *ctx = afb_req_context_get (request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp;
+    unsigned int volume[8], i;
+    char *volume_i;
+    char volume_str[256];
+    size_t len_str = 0;
+
+	if (!ctx) {
+        afb_req_fail (request, "failed", "you must call 'init' first");
+        return;
+    }
+    jresp = json_object_new_object();
+
+    /* no "?value=" parameter : return current state */
+    if (!value) {
+        for (i = 0; i < 8; i++) {
+            ctx->volume[i] = _backend_get_volume (ctx, i);
+            snprintf (volume_str+len_str, sizeof(volume_str)-len_str, "%d,", ctx->volume[i]);
+            len_str = strlen (volume_str);
+        }
+        json_object_object_add (jresp, "volume", json_object_new_string(volume_str));
+        afb_req_success (request, jresp, "Audio - Volume obtained");
+        return;
+    }
+
+    /* "?value=" parameter, set volume */
+    else {
+        volume_i = strdup (value);
+        volume_i = strtok (volume_i, ",");
+        volume[0] = (unsigned int) atoi (volume_i);
+
+        if (100 < volume[0]) {
+            free (volume_i);
+            afb_req_fail (request, "failed", "volume must be between 0 and 100");
+            return;
+        }
+        ctx->volume[0] = volume[0];
+        _backend_set_volume (ctx, 0, ctx->volume[0]);
+        snprintf (volume_str, sizeof(volume_str), "%d,", ctx->volume[0]);
+
+        for (i = 1; i < 8; i++) {
+            volume_i = strtok (NULL, ",");
+            /* if there is only one value, set all channels to this one */
+            if (!volume_i && i == 1)
+               _backend_set_volume_all (ctx, ctx->volume[0]);
+            if (!volume_i || 100 < atoi(volume_i) || atoi(volume_i) < 0)
+               ctx->volume[i] = _backend_get_volume (ctx, i);
+            else {
+               ctx->volume[i] = (unsigned int) atoi(volume_i);
+               _backend_set_volume (ctx, i, ctx->volume[i]);
+            }
+            len_str = strlen(volume_str);
+            snprintf (volume_str+len_str, sizeof(volume_str)-len_str, "%d,", ctx->volume[i]);
+        }
+        free (volume_i);
+        json_object_object_add (jresp, "volume", json_object_new_string(volume_str));
+    }
+
+    afb_req_success (request, jresp, "Audio - Volume changed");
+}
+
+static void channels (struct afb_req request) {    /* AFB_SESSION_CHECK */
+
+    audioCtxHandleT *ctx = afb_req_context_get (request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp;
+    char channels_str[256];
+
+	if (!ctx) {
+        afb_req_fail (request, "failed", "you must call 'init' first");
+        return;
+    }
+    jresp = json_object_new_object();
+
+    /* no "?value=" parameter : return current state */
+    if (!value) {
+        snprintf (channels_str, sizeof(channels_str), "%d", ctx->channels);
+
+        json_object_object_add (jresp, "channels", json_object_new_string (channels_str));
+        afb_req_success (request, jresp, "Audio - Channels obtained");
+        return;
+    }
+
+    /* "?value=" parameter, set channels */
+    else {
+        ctx->channels = (unsigned int) atoi (value);
+        _backend_set_channels (ctx, ctx->channels);
+        snprintf (channels_str, sizeof(channels_str), "%d", ctx->channels);
+
+        jresp = json_object_new_object();
+        json_object_object_add (jresp, "channels", json_object_new_string (channels_str));
+    }
+
+    afb_req_success (request, jresp, "Audio - Channels set");
+}
+
+static void mute (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    audioCtxHandleT *ctx = afb_req_context_get (request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp;
+
+	if (!ctx) {
+        afb_req_fail (request, "failed", "you must call 'init' first");
+        return;
+    }
+    jresp = json_object_new_object();
+
+    /* no "?value=" parameter : return current state */
+    if (!value) {
+        ctx->mute = _backend_get_mute (ctx);
+        ctx->mute ?
+            json_object_object_add (jresp, "mute", json_object_new_string ("on"))
+          : json_object_object_add (jresp, "mute", json_object_new_string ("off"));
+        afb_req_success (request, jresp, "Audio - Mute status obtained");
+        return;
+    }
+
+    /* "?value=" parameter is "1" or "true" */
+    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
+        ctx->mute = 1;
+        _backend_set_mute (ctx, ctx->mute);
+        json_object_object_add (jresp, "mute", json_object_new_string ("on"));
+    }
+
+    /* "?value=" parameter is "0" or "false" */
+    else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
+        ctx->mute = 0;
+        _backend_set_mute (ctx, ctx->mute);
+        json_object_object_add (jresp, "mute", json_object_new_string ("off"));
+    }
+
+    afb_req_success (request, jresp, "Audio - Mute set");
+}
+
+static void play (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    audioCtxHandleT *ctx = afb_req_context_get (request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp;
+
+	if (!ctx) {
+        afb_req_fail (request, "failed", "you must call 'init' first");
+        return;
+    }
+    jresp = json_object_new_object();
+
+    /* no "?value=" parameter : return current state */
+    if (!value) {
+        ctx->is_playing ?
+            json_object_object_add (jresp, "play", json_object_new_string ("on"))
+          : json_object_object_add (jresp, "play", json_object_new_string ("off"));
+        afb_req_success (request, jresp, "Audio - Playing status obtained");
+        return;
+    }
+
+    /* "?value=" parameter is "1" or "true" */
+    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
+        ctx->is_playing = 1;
+        _backend_play (ctx);
+        json_object_object_add (jresp, "play", json_object_new_string ("on"));
+    }
+
+    /* "?value=" parameter is "0" or "false" */
+    else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
+        ctx->is_playing = 0;
+        _backend_stop (ctx);
+        json_object_object_add (jresp, "play", json_object_new_string ("off"));
+    }
+
+    afb_req_success (request, jresp, "Audio - Play");
+}
+
+static void ping (struct afb_req request) {         /* AFB_SESSION_NONE */
+    afb_req_success (request, NULL, "Audio - Ping success");
+}
+
+static const struct AFB_verb_desc_v1 verbs[] = {
+  {"init"    , AFB_SESSION_CHECK,  init      , "Audio API - init"},
+  {"volume"  , AFB_SESSION_CHECK,  volume    , "Audio API - volume"},
+  {"channels", AFB_SESSION_CHECK,  channels  , "Audio API - channels"},
+  {"mute"    , AFB_SESSION_CHECK,  mute      , "Audio API - mute"},
+  {"play"    , AFB_SESSION_CHECK,  play      , "Audio API - play"},
+  {"ping"    , AFB_SESSION_NONE,   ping      , "Audio API - ping"},
+  {NULL}
+};
+
+static const struct AFB_plugin pluginDesc = {
+    .type   = AFB_PLUGIN_VERSION_1,
+    .v1 = {
+        .info   = "Application Framework Binder - Audio plugin",
+        .prefix = "audio",
+        .verbs   = verbs
+    }
+};
+
+const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
+{
+	return &pluginDesc;
+}
diff --git a/bindings/audio/audio-api.h b/bindings/audio/audio-api.h
new file mode 100644
index 00000000..f5c77c2e
--- /dev/null
+++ b/bindings/audio/audio-api.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_API_H
+#define AUDIO_API_H
+
+/* global plugin handle, should store everything we may need */
+typedef struct {
+  int devCount;
+} pluginHandleT;
+
+/* private client context [will be destroyed when client leaves] */
+typedef struct {
+  void *audio_dev;          /* handle to implementation (ALSA, PulseAudio...) */
+  char *name;               /* name of the audio card */
+  int idx;                  /* audio card index within global array           */
+  unsigned int volume[8];   /* audio volume (8 channels) : 0-100              */
+  unsigned int channels;    /* audio channels : 1(mono)/2(stereo)...          */
+  unsigned char mute;       /* audio muted : 0(false)/1(true)                 */
+  unsigned char is_playing; /* audio is playing: 0(false)/1(true)             */
+} audioCtxHandleT;
+
+
+#endif /* AUDIO_API_H */
diff --git a/bindings/audio/audio-pulse.c b/bindings/audio/audio-pulse.c
new file mode 100644
index 00000000..34643603
--- /dev/null
+++ b/bindings/audio/audio-pulse.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include "audio-api.h"
+#include "audio-pulse.h"
+
+static struct alsa_info **alsa_info = NULL;
+static struct dev_ctx_pulse **dev_ctx_p = NULL;
+static unsigned int client_count = 0;
+
+
+unsigned char _pulse_init (const char *name, audioCtxHandleT *ctx) {
+
+    pa_mainloop *pa_loop;
+    pa_mainloop_api *pa_api;
+    pa_context *pa_context;
+    pa_simple *pa;
+    pa_sample_spec *pa_spec;
+    struct timeval tv_start, tv_now;
+    int ret, error, i;
+
+    pa_loop = pa_mainloop_new ();
+    pa_api = pa_mainloop_get_api (pa_loop);
+    pa_context = pa_context_new (pa_api, "afb-audio-plugin");
+
+    /* allocate the global array if it hasn't been done */
+    if (!dev_ctx_p)
+        dev_ctx_p = (dev_ctx_pulse_T**) malloc (sizeof(dev_ctx_pulse_T*));
+
+    /* create a temporary device, to be held until sink gets discovered */
+    dev_ctx_pulse_T *dev_ctx_p_t = (dev_ctx_pulse_T*) malloc (sizeof(dev_ctx_pulse_T));
+    dev_ctx_p_t->sink_name = NULL;
+    dev_ctx_p_t->card_name = (char**) malloc (sizeof(char*));
+    dev_ctx_p_t->card_name[0] = strdup (name);
+    dev_ctx_p_t->pa_loop = pa_loop;
+    dev_ctx_p_t->pa_context = pa_context;
+
+    pa_context_set_state_callback (pa_context, _pulse_context_cb, (void*)dev_ctx_p_t);
+    pa_context_connect (pa_context, NULL, 0, NULL);
+
+    /* 1 second should be sufficient to retrieve sink info */
+    gettimeofday (&tv_start, NULL);
+    gettimeofday (&tv_now, NULL);
+    while (tv_now.tv_sec - tv_start.tv_sec <= 2) {
+        pa_mainloop_iterate (pa_loop, 0, &ret);
+
+        if (ret == -1) { /* generic error */
+            fprintf (stderr, "Stopping PulseAudio backend...\n");
+            return 0;
+        }
+
+        if ((ret > 0)&&(ret < 100)) { /* 0 and >100 are PulseAudio codes */
+            /* found a matching sink from callback */
+            fprintf (stderr, "Success : using sink n.%d\n", ret-1);
+            ctx->audio_dev = (void*)dev_ctx_p[ret-1];
+            break;
+        }
+        gettimeofday (&tv_now, NULL);
+    }
+    /* fail if we found no matching sink */
+    if (!ctx->audio_dev)
+      return 0;
+
+    /* make the client context aware of current card state */
+    ctx->mute = (unsigned char)dev_ctx_p[ret-1]->mute;
+    ctx->channels = (unsigned int)dev_ctx_p[ret-1]->volume.channels;
+    for (i = 0; i < ctx->channels; i++)
+        ctx->volume[i] = dev_ctx_p[ret-1]->volume.values[i];
+    ctx->idx = ret-1;
+
+    /* open matching sink for playback */
+    pa_spec = (pa_sample_spec*) malloc (sizeof(pa_sample_spec));
+    pa_spec->format = PA_SAMPLE_S16LE;
+    pa_spec->rate = 22050;
+    pa_spec->channels = (uint8_t)ctx->channels;
+
+    if (!(pa = pa_simple_new (NULL, "afb-audio-plugin", PA_STREAM_PLAYBACK, dev_ctx_p[ret-1]->sink_name,
+                              "afb-audio-output", pa_spec, NULL, NULL, &error))) {
+        fprintf (stderr, "Error opening PulseAudio sink %s : %s\n",
+                          dev_ctx_p[ret-1]->sink_name, pa_strerror(error));
+        return 0;
+    }
+    dev_ctx_p[ret-1]->pa = pa;
+    free (pa_spec);
+
+    client_count++;
+
+    fprintf (stderr, "Successfully initialized PulseAudio backend.\n");
+
+    return 1;
+}
+
+void _pulse_free (audioCtxHandleT *ctx) {
+
+    int num, i;
+
+    client_count--;
+    if (client_count > 0) return;
+
+    for (num = 0; num < (sizeof(dev_ctx_p)/sizeof(dev_ctx_pulse_T*)); num++) {
+
+         for (i = 0; num < (sizeof(dev_ctx_p[num]->card_name)/sizeof(char*)); i++) {
+             free (dev_ctx_p[num]->card_name[i]);
+             dev_ctx_p[num]->card_name[i] = NULL;
+         }
+         pa_context_disconnect (dev_ctx_p[num]->pa_context);
+         pa_context_unref (dev_ctx_p[num]->pa_context);
+         pa_mainloop_free (dev_ctx_p[num]->pa_loop);
+         pa_simple_free (dev_ctx_p[num]->pa);
+         free (dev_ctx_p[num]->sink_name);
+         dev_ctx_p[num]->pa_context = NULL;
+         dev_ctx_p[num]->pa_loop = NULL;
+         dev_ctx_p[num]->pa = NULL;
+         dev_ctx_p[num]->sink_name = NULL;
+         free (dev_ctx_p[num]);
+    }
+}
+
+void _pulse_play (audioCtxHandleT *ctx) {
+
+    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
+
+    if (!dev_ctx_p_c || dev_ctx_p_c->thr_should_run || access (AUDIO_BUFFER, F_OK) == -1)
+        return;
+
+    dev_ctx_p_c->thr_should_run = 1;
+    dev_ctx_p_c->thr_finished = 0;
+    pthread_create (&dev_ctx_p_c->thr, NULL, _pulse_play_thread_fn, (void*)dev_ctx_p_c);
+}
+
+void _pulse_stop (audioCtxHandleT *ctx) {
+
+    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
+
+    if (!dev_ctx_p_c || !dev_ctx_p_c->thr_should_run)
+        return;
+
+    dev_ctx_p_c->thr_should_run = 0;
+    while (!dev_ctx_p_c->thr_finished)
+        usleep(100000);
+    pthread_join (dev_ctx_p_c->thr, NULL);
+}
+
+unsigned int _pulse_get_volume (audioCtxHandleT *ctx, unsigned int channel) {
+
+    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
+
+    if (!dev_ctx_p_c)
+        return 0;
+
+    _pulse_refresh_sink (dev_ctx_p_c);
+
+    return (dev_ctx_p_c->volume.values[channel]*100)/PA_VOLUME_NORM;
+}
+
+void _pulse_set_volume (audioCtxHandleT *ctx, unsigned int channel, unsigned int vol) {
+
+    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
+    struct pa_cvolume volume;
+
+    if (!dev_ctx_p_c)
+        return;
+
+    volume = dev_ctx_p_c->volume;
+    volume.values[channel] = (vol*PA_VOLUME_NORM)/100;
+
+    pa_context_set_sink_volume_by_name (dev_ctx_p_c->pa_context, dev_ctx_p_c->sink_name,
+                                        &volume, NULL, NULL);
+    _pulse_refresh_sink (dev_ctx_p_c);
+}
+
+void _pulse_set_volume_all (audioCtxHandleT *ctx, unsigned int vol) {
+
+    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
+    struct pa_cvolume volume;
+
+    if (!dev_ctx_p_c)
+        return;
+
+    pa_cvolume_init (&volume);
+    pa_cvolume_set (&volume, dev_ctx_p_c->volume.channels, vol);
+
+    pa_context_set_sink_volume_by_name (dev_ctx_p_c->pa_context, dev_ctx_p_c->sink_name,
+                                        &volume, NULL, NULL);
+    _pulse_refresh_sink (dev_ctx_p_c);
+}
+
+unsigned char _pulse_get_mute (audioCtxHandleT *ctx) {
+
+    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
+
+    if (!dev_ctx_p_c)
+        return 0;
+
+    _pulse_refresh_sink (dev_ctx_p_c);
+
+    return (unsigned char)dev_ctx_p_c->mute;
+}
+
+void _pulse_set_mute (audioCtxHandleT *ctx, unsigned char mute) {
+
+    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
+
+    if (!dev_ctx_p_c)
+        return;
+
+    pa_context_set_sink_mute_by_name (dev_ctx_p_c->pa_context, dev_ctx_p_c->sink_name,
+                                      (int)mute, NULL, NULL);
+    _pulse_refresh_sink (dev_ctx_p_c);
+}
+
+ /* ---- LOCAL HELPER FUNCTIONS ---- */
+
+void _pulse_refresh_sink (dev_ctx_pulse_T* dev_ctx_p_c) {
+
+    pa_mainloop_api *pa_api;
+
+    dev_ctx_p_c->pa_loop = pa_mainloop_new ();
+    pa_api = pa_mainloop_get_api (dev_ctx_p_c->pa_loop);
+    dev_ctx_p_c->pa_context = pa_context_new (pa_api, "afb-audio-plugin");
+
+    dev_ctx_p_c->refresh = 1;
+
+    switch (pa_context_get_state (dev_ctx_p_c->pa_context)) {
+      case PA_CONTEXT_READY:
+        pa_context_get_sink_info_by_name (dev_ctx_p_c->pa_context,
+                                          dev_ctx_p_c->sink_name,
+                                          _pulse_sink_info_cb, (void*)dev_ctx_p_c);
+        break;
+      default:
+        return;
+    }
+
+    while (dev_ctx_p_c->refresh)
+        pa_mainloop_iterate (dev_ctx_p_c->pa_loop, 0, NULL);
+}
+
+void _pulse_enumerate_cards () {
+
+    void **cards, **card;
+    char *name, *found, *alsa_name, *card_name;
+    int new_info, i, num = 0;
+
+    /* allocate the global alsa array */
+    alsa_info = (alsa_info_T**) malloc (sizeof(alsa_info_T*));
+    alsa_info[0] = (alsa_info_T*) malloc (sizeof(alsa_info_T));
+    alsa_info[0]->device = NULL;
+    alsa_info[0]->synonyms = NULL;
+
+    /* we use ALSA to enumerate cards */
+    snd_device_name_hint (-1, "pcm", &cards);
+    card = cards;
+
+    for (; *card != NULL; card++) {
+        name = snd_device_name_get_hint (*card, "NAME");
+        new_info = 1;
+
+        /* alsa name is before ':' (if ':' misses, then it has no card) */
+        found = strstr (name, ":");
+        if (!found) continue;
+        /* */
+        alsa_name = (char*) malloc (found-name+1);
+        strncpy (alsa_name, name, found-name);
+        alsa_name[found-name] = '\0';
+
+        /* card name is the invariant between "CARD=" and ',' */
+        found = strstr (name, "CARD=");
+        if (!found) continue;
+        /* */
+        found += 5;
+        card_name = strdup (found);
+        found = strstr (card_name, ",");
+        if (found) card_name[found-card_name] = '\0';
+
+        /* was the card name already listed in the global alsa array ? */
+        for (i = 0; i < (sizeof(alsa_info)/sizeof(alsa_info_T*)); i++) {
+
+            if (alsa_info[i]->device &&
+                !strcmp (alsa_info[i]->device, card_name)) {
+                /* it was ; add the alsa name as a new synonym */
+                asprintf (&alsa_info[i]->synonyms, "%s:%s", alsa_info[i]->synonyms, alsa_name);
+                new_info = 0;
+                break;
+            }            
+        }
+        /* it was not ; create it */
+        if (new_info) {
+            alsa_info = (alsa_info_T**) realloc (alsa_info, (num+1)*sizeof(alsa_info_T*));
+            alsa_info[num] = (alsa_info_T*) malloc (sizeof(alsa_info_T));
+            alsa_info[num]->device = strdup (card_name);
+            asprintf (&alsa_info[num]->synonyms, ":%s", alsa_name);
+            num++;
+        }
+        free (alsa_name);
+        free (card_name);
+    }
+}
+
+char** _pulse_find_cards (const char *name) {
+
+    char **cards = NULL;
+    char *needle, *found, *next;
+    int num, i = 0;
+
+    if (!alsa_info)
+      _pulse_enumerate_cards ();
+
+    asprintf (&needle, ":%s", name);
+
+    for (num = 0; num < (sizeof(alsa_info)/sizeof(alsa_info_T*)); num++) {
+
+        found = strstr (alsa_info[num]->synonyms, needle);
+        while (found) {
+            /* if next character is not ':' or '\0', we are wrong */
+            if ((found[strlen(name)+1] != ':') && (found[strlen(name)+1] != '\0')) {
+                found = strstr (found+1, needle);
+                continue;
+            }
+            /* found it ; now return all the "synonym" cards */
+            found = strstr (alsa_info[num]->synonyms, ":");
+            while (found) {
+                next = strstr (found+1, ":");
+                if (!next) break;
+                cards = (char**) realloc (cards, (i+1)*sizeof(char*));
+                cards[i] = (char*) malloc (next-found+1);
+                strncpy (cards[i], found+1, next-found);
+                cards[i][next-found-1] = '\0';
+                found = next; i++;
+            }
+        }
+    }
+    free (needle);
+
+    return cards;
+}
+
+ /* ---- LOCAL CALLBACK FUNCTIONS ---- */
+
+void _pulse_context_cb (pa_context *context, void *data) {
+
+    pa_context_state_t state = pa_context_get_state (context);
+    dev_ctx_pulse_T *dev_ctx_p_t = (dev_ctx_pulse_T *)data;
+
+    if (state == PA_CONTEXT_FAILED) {
+        fprintf (stderr, "Could not connect to PulseAudio !\n");
+        pa_mainloop_quit (dev_ctx_p_t->pa_loop, -1);
+        pa_context_disconnect (dev_ctx_p_t->pa_context);
+        pa_context_unref (dev_ctx_p_t->pa_context);
+        pa_mainloop_free (dev_ctx_p_t->pa_loop);
+    }
+
+    if (state == PA_CONTEXT_READY)
+        pa_context_get_sink_info_list (context, _pulse_sink_list_cb, (void*)dev_ctx_p_t);
+}
+
+void _pulse_sink_list_cb (pa_context *context, const pa_sink_info *info,
+				 int eol, void *data) {
+
+    dev_ctx_pulse_T *dev_ctx_p_t = (dev_ctx_pulse_T *)data;
+    const char *device_string;
+    char *device, *found;
+    char **cards;
+    int num, i;
+
+    if (eol != 0)
+        return;
+
+    device_string = pa_proplist_gets (info->proplist, "device.string");
+    /* ignore sinks with no cards */
+    if (!device_string)
+        return;
+
+    /* was a sink with similar name already found ? */
+    for (num = 0; num < (sizeof(dev_ctx_p)/sizeof(dev_ctx_pulse_T*)); num++) {
+        if (dev_ctx_p[num]->sink_name &&
+           !strcmp (dev_ctx_p[num]->sink_name, info->name)) {
+
+            /* yet it was, did it have the required card ? */
+            cards = dev_ctx_p[num]->card_name;
+            for (i = 0; i < (sizeof(cards)/sizeof(char*)); i++) {
+                if (!strcmp (cards[i], dev_ctx_p_t->card_name[0])) {
+                    /* it did : stop there and succeed */
+                    fprintf (stderr, "Found matching sink : %s\n", info->name);
+                    /* we return num+1 because '0' is already used */
+                    pa_mainloop_quit (dev_ctx_p_t->pa_loop, num+1);
+                    pa_context_disconnect (dev_ctx_p_t->pa_context);
+                    pa_context_unref (dev_ctx_p_t->pa_context);
+                    pa_mainloop_free (dev_ctx_p_t->pa_loop);
+                }
+            }
+            /* it did not, ignore and return */
+            return;
+        }
+    }
+    num++;
+
+    /* remove ending ":0",":1"... in device name */
+    device = strdup (device_string);
+    found = strstr (device, ":");
+    if (found) device[found-device] = '\0';
+
+    /* new sink, find all the cards it manages, fail if none */
+    cards = _pulse_find_cards (device);
+    free (device);
+    if (!cards)
+        return;
+
+    /* everything is well, register it in global array */
+    dev_ctx_p_t->sink_name = strdup (info->name);
+    dev_ctx_p_t->card_name = cards;
+    dev_ctx_p_t->mute = info->mute;
+    dev_ctx_p_t->volume = info->volume;
+    dev_ctx_p_t->thr_should_run = 0;
+    dev_ctx_p_t->thr_finished = 0;
+    dev_ctx_p[num] = dev_ctx_p_t;
+
+    /* does this new sink have the card we are looking for ? */ /* TODO : factorize this */
+    for (i = 0; i < (sizeof(cards)/sizeof(char*)); i++) {
+        if (!strcmp (cards[i], dev_ctx_p_t->card_name[0])) {
+             /* it did : stop there and succeed */
+             fprintf (stderr, "Found matching sink : %s\n", info->name);
+             /* we return num+1 because '0' is already used */
+             pa_mainloop_quit (dev_ctx_p_t->pa_loop, num+1);
+             pa_context_disconnect (dev_ctx_p_t->pa_context);
+             pa_context_unref (dev_ctx_p_t->pa_context);
+             pa_mainloop_free (dev_ctx_p_t->pa_loop);
+        }
+    }
+}
+
+void _pulse_sink_info_cb (pa_context *context, const pa_sink_info *info,
+				 int eol, void *data) {
+
+    dev_ctx_pulse_T *dev_ctx_p_c = (dev_ctx_pulse_T *)data;
+
+    if (eol != 0)
+        return;
+
+    dev_ctx_p_c->refresh = 0;
+    dev_ctx_p_c->mute = info->mute;
+    dev_ctx_p_c->volume = info->volume;
+}
+
+ /* ---- LOCAL THREADED FUNCTIONS ---- */
+
+void* _pulse_play_thread_fn (void *ctx) {
+
+    dev_ctx_pulse_T *dev_ctx_p_c = (dev_ctx_pulse_T *)ctx;
+    FILE *file = NULL;
+    char *buf = NULL;
+    long size;
+    int error;
+
+    file = fopen (AUDIO_BUFFER, "rb");
+
+    while (dev_ctx_p_c->thr_should_run && file && (access (AUDIO_BUFFER, F_OK) != -1) ) {
+        fseek (file, 0, SEEK_END);
+        size = ftell (file);
+        buf = (char*) realloc (buf, size * sizeof(char));
+
+        fseek (file, 0, SEEK_SET);
+        fread (buf, 1, size, file);
+        fflush (file);
+
+        if (pa_simple_write (dev_ctx_p_c->pa, buf, size*2, &error) < 0)
+            fprintf (stderr, "Error writing to PulseAudio : %s\n", pa_strerror (error));
+        /* pa_simple_drain (dev_ctx_p_c->pa); */
+    }
+    if (buf) free(buf);
+    if (file) fclose(file);
+
+    dev_ctx_p_c->thr_finished = 1;
+    return 0;
+}
diff --git a/bindings/audio/audio-pulse.h b/bindings/audio/audio-pulse.h
new file mode 100644
index 00000000..ad8ff490
--- /dev/null
+++ b/bindings/audio/audio-pulse.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_PULSE_H
+#define AUDIO_PULSE_H
+
+#include <sys/time.h>
+#include <pulse/pulseaudio.h>
+#include <pulse/simple.h>
+#include <pulse/error.h>
+
+#include "audio-alsa.h"
+
+typedef struct dev_ctx_pulse dev_ctx_pulse_T;
+typedef struct alsa_info alsa_info_T;
+
+struct dev_ctx_pulse {
+  char *sink_name;
+  char **card_name;
+  pa_mainloop *pa_loop;
+  pa_context *pa_context;
+  pa_simple *pa;
+  pa_cvolume volume;
+  int mute;
+  unsigned char refresh;
+  pthread_t thr;
+  unsigned char thr_should_run;
+  unsigned char thr_finished;
+};
+
+struct alsa_info {
+  char *device;
+  char *synonyms;
+};
+
+unsigned char _pulse_init (const char *, audioCtxHandleT *);
+void _pulse_free (audioCtxHandleT *);
+void _pulse_play (audioCtxHandleT *);
+void _pulse_stop (audioCtxHandleT *);
+unsigned int _pulse_get_volume (audioCtxHandleT *, unsigned int);
+void _pulse_set_volume (audioCtxHandleT *, unsigned int, unsigned int);
+void _pulse_set_volume_all (audioCtxHandleT *, unsigned int);
+unsigned char _pulse_get_mute (audioCtxHandleT *);
+void _pulse_set_mute (audioCtxHandleT *, unsigned char);
+
+void  _pulse_context_cb (pa_context *, void *);
+void  _pulse_sink_list_cb (pa_context *, const pa_sink_info *, int, void *);
+void  _pulse_sink_info_cb (pa_context *, const pa_sink_info *, int, void *);
+void* _pulse_play_thread_fn (void *);
+void  _pulse_refresh_sink (dev_ctx_pulse_T *);
+
+#endif /* AUDIO_PULSE_H */
diff --git a/bindings/audio/export.map b/bindings/audio/export.map
new file mode 100644
index 00000000..0ef1ac79
--- /dev/null
+++ b/bindings/audio/export.map
@@ -0,0 +1 @@
+{ global: afbBindingV1Register; local: *; };
diff --git a/bindings/intrinsics/CMakeLists.txt b/bindings/intrinsics/CMakeLists.txt
new file mode 100644
index 00000000..c6ff8ef4
--- /dev/null
+++ b/bindings/intrinsics/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+INCLUDE_DIRECTORIES(${include_dirs})
+
+##################################################
+# DBus Binding
+##################################################
+ADD_LIBRARY(afb-dbus-binding MODULE afb-dbus-binding.c)
+SET_TARGET_PROPERTIES(afb-dbus-binding PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
+)
+TARGET_LINK_LIBRARIES(afb-dbus-binding ${link_libraries})
+INSTALL(TARGETS afb-dbus-binding
+        LIBRARY DESTINATION ${binding_install_dir})
+
diff --git a/bindings/intrinsics/afb-dbus-binding.c b/bindings/intrinsics/afb-dbus-binding.c
new file mode 100644
index 00000000..59fe78d6
--- /dev/null
+++ b/bindings/intrinsics/afb-dbus-binding.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <json-c/json.h>
+
+#include <systemd/sd-bus.h>
+#include <systemd/sd-bus-protocol.h>
+
+#include <afb/afb-binding.h>
+
+/*
+ * the interface to afb-daemon
+ */
+const struct afb_binding_interface *afbitf;
+
+/*
+ * union of possible dbus values
+ */
+union any {
+	uint8_t u8;
+	int16_t i16;
+	uint16_t u16;
+	int32_t i32;
+	uint32_t u32;
+	int64_t i64;
+	uint64_t u64;
+	double dbl;
+	const char *cstr;
+	char *str;
+};
+
+static int unpacklist(struct sd_bus_message *msg, struct json_object **result);
+static int packlist(struct sd_bus_message *msg, const char *signature, struct json_object *list);
+
+/*
+ * Get the string of 'key' from 'obj'
+ * Returns NULL if 'key' isn't in 'obj'
+ */ 
+static const char *strval(struct json_object *obj, const char *key)
+{
+	struct json_object *keyval;
+	return json_object_object_get_ex(obj, key, &keyval) ? json_object_get_string(keyval) : NULL;
+}
+
+/*
+ * Signature of a json object
+ */
+static const char *signature_for_json(struct json_object *obj)
+{
+	switch (json_object_get_type(obj)) {
+	default:
+	case json_type_null:
+		return NULL;
+	case json_type_boolean:
+		return "b";
+	case json_type_double:
+		return "d";
+	case json_type_int:
+		return "i";
+	case json_type_object:
+		return "a{sv}";
+	case json_type_array:
+		return "av";
+	case json_type_string:
+		return "s";
+	}
+}
+
+/*
+ * Length of a single complete type
+ */
+static int lentype(const char *signature, int allows_dict, int allows_not_basic)
+{
+	int rc, len;
+	switch(signature[0]) {
+
+	case SD_BUS_TYPE_ARRAY:
+		if (!allows_not_basic)
+			break;
+		rc = lentype(signature + 1, 1, 1);
+		if (rc < 0)
+			break;
+		return 1 + rc;
+
+	case SD_BUS_TYPE_STRUCT_BEGIN:
+		if (!allows_not_basic)
+			break;
+		len = 1;
+		rc = lentype(signature + len, 0, 1);
+		while (rc > 0 && signature[len] != SD_BUS_TYPE_STRUCT_END) {
+			len += rc;
+			rc = lentype(signature + len, 0, 1);
+		}
+		if (rc < 0)
+			break;
+		return 1 + len;		
+
+	case SD_BUS_TYPE_DICT_ENTRY_BEGIN:
+		if (!allows_not_basic || !allows_dict)
+			break;
+		rc = lentype(signature + 1, 0, 0);
+		if (rc < 0)
+			break;
+		len = 1 + rc;
+		rc = lentype(signature + len, 0, 1);
+		if (rc < 0 || signature[len + rc] != SD_BUS_TYPE_DICT_ENTRY_END)
+			break;
+		return len + rc + 1;
+
+	case '\x0':
+	case SD_BUS_TYPE_STRUCT:
+	case SD_BUS_TYPE_STRUCT_END:
+	case SD_BUS_TYPE_DICT_ENTRY:
+	case SD_BUS_TYPE_DICT_ENTRY_END:
+		break;
+
+	default:
+		return 1;
+	}
+	return -1;
+}
+
+
+/*
+ * Unpack a D-Bus message to a json object
+ */
+static int unpacksingle(struct sd_bus_message *msg, struct json_object **result)
+{
+	char c;
+	int rc;
+	union any any;
+	const char *content;
+	struct json_object *item;
+
+	*result = NULL;
+	rc = sd_bus_message_peek_type(msg, &c, &content);
+	if (rc <= 0)
+		return rc;
+
+	switch (c) {
+	case SD_BUS_TYPE_BYTE:
+	case SD_BUS_TYPE_BOOLEAN:
+	case SD_BUS_TYPE_INT16:
+	case SD_BUS_TYPE_UINT16:
+	case SD_BUS_TYPE_INT32:
+	case SD_BUS_TYPE_UINT32:
+	case SD_BUS_TYPE_INT64:
+	case SD_BUS_TYPE_UINT64:
+	case SD_BUS_TYPE_DOUBLE:
+	case SD_BUS_TYPE_STRING:
+	case SD_BUS_TYPE_OBJECT_PATH:
+	case SD_BUS_TYPE_SIGNATURE:
+		rc = sd_bus_message_read_basic(msg, c, &any);
+		if (rc < 0)
+			goto error;
+		switch (c) {
+		case SD_BUS_TYPE_BOOLEAN:
+			*result = json_object_new_boolean(any.i32);
+			break;
+		case SD_BUS_TYPE_BYTE:
+			*result = json_object_new_int(any.u8);
+			break;
+		case SD_BUS_TYPE_INT16:
+			*result = json_object_new_int(any.i16);
+			break;
+		case SD_BUS_TYPE_UINT16:
+			*result = json_object_new_int(any.u16);
+			break;
+		case SD_BUS_TYPE_INT32:
+			*result = json_object_new_int(any.i32);
+			break;
+		case SD_BUS_TYPE_UINT32:
+			*result = json_object_new_int64(any.u32);
+			break;
+		case SD_BUS_TYPE_INT64:
+			*result = json_object_new_int64(any.i64);
+			break;
+		case SD_BUS_TYPE_UINT64:
+			*result = json_object_new_int64((int64_t)any.u64);
+			break;
+		case SD_BUS_TYPE_DOUBLE:
+			*result = json_object_new_string(any.cstr);
+			break;
+		case SD_BUS_TYPE_STRING:
+		case SD_BUS_TYPE_OBJECT_PATH:
+		case SD_BUS_TYPE_SIGNATURE:
+			*result = json_object_new_string(any.cstr);
+			break;
+		}
+		return *result == NULL ? -1 : 1;
+
+	case SD_BUS_TYPE_ARRAY:
+	case SD_BUS_TYPE_VARIANT:
+	case SD_BUS_TYPE_STRUCT:
+	case SD_BUS_TYPE_DICT_ENTRY:
+		rc = sd_bus_message_enter_container(msg, c, content);
+		if (rc < 0)
+			goto error;
+		if (c == SD_BUS_TYPE_ARRAY && content[0] == SD_BUS_TYPE_DICT_ENTRY_BEGIN && content[1] == SD_BUS_TYPE_STRING) {
+			*result = json_object_new_object();
+			if (*result == NULL)
+				return -1;
+			for(;;) {
+				rc = sd_bus_message_enter_container(msg, 0, NULL);
+				if (rc < 0)
+					goto error;
+				if (rc == 0)
+					break;
+				rc = sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, &any);
+				if (rc < 0)
+					goto error;
+				rc = unpacksingle(msg, &item);
+				if (rc < 0)
+					goto error;
+				json_object_object_add(*result, any.cstr, item);
+				rc = sd_bus_message_exit_container(msg);
+				if (rc < 0)
+					goto error;
+			}
+		} else {
+			rc = unpacklist(msg, result);
+			if (rc < 0)
+				goto error;
+		}
+		rc = sd_bus_message_exit_container(msg);
+		if (rc < 0)
+			goto error;
+		return 1;
+	default:
+		goto error;
+	}
+error:
+	json_object_put(*result);
+	return -1;
+}
+
+/*
+ * Unpack a D-Bus message to a json object
+ */
+static int unpacklist(struct sd_bus_message *msg, struct json_object **result)
+{
+	int rc;
+	struct json_object *item;
+
+	/* allocates the result */
+	*result = json_object_new_array();
+	if (*result == NULL)
+		goto error;
+
+	/* read the values */
+	for (;;) {
+		rc = unpacksingle(msg, &item);
+		if (rc < 0)
+			goto error;
+		if (rc == 0)
+			return 0;
+		json_object_array_add(*result, item);
+	}
+error:
+	json_object_put(*result);
+	*result = NULL;
+	return -1;
+}
+
+static int packsingle(struct sd_bus_message *msg, const char *signature, struct json_object *item)
+{
+	int index, count, rc, len;
+	union any any;
+	char *subsig;
+	struct json_object_iterator it, end;
+
+	len = lentype(signature, 0, 1);
+	if (len < 0)
+		goto error;
+
+	switch (*signature) {
+	case SD_BUS_TYPE_BOOLEAN:
+		any.i32 = json_object_get_boolean(item);
+		break;
+
+	case SD_BUS_TYPE_BYTE:
+		any.i32 = json_object_get_int(item);
+		if (any.i32 != (int32_t)(uint8_t)any.i32)
+			goto error;
+		any.u8 = (uint8_t)any.i32;
+		break;
+
+	case SD_BUS_TYPE_INT16:
+		any.i32 = json_object_get_int(item);
+		if (any.i32 != (int32_t)(int16_t)any.i32)
+			goto error;
+		any.i16 = (int16_t)any.i32;
+		break;
+
+	case SD_BUS_TYPE_UINT16:
+		any.i32 = json_object_get_int(item);
+		if (any.i32 != (int32_t)(uint16_t)any.i32)
+			goto error;
+		any.u16 = (uint16_t)any.i32;
+		break;
+
+	case SD_BUS_TYPE_INT32:
+		any.i64 = json_object_get_int64(item);
+		if (any.i64 != (int64_t)(int32_t)any.i64)
+			goto error;
+		any.i32 = (int32_t)any.i64;
+		break;
+
+	case SD_BUS_TYPE_UINT32:
+		any.i64 = json_object_get_int64(item);
+		if (any.i64 != (int64_t)(uint32_t)any.i64)
+			goto error;
+		any.u32 = (uint32_t)any.i64;
+		break;
+
+	case SD_BUS_TYPE_INT64:
+		any.i64 = json_object_get_int64(item);
+		break;
+
+	case SD_BUS_TYPE_UINT64:
+		any.u64 = (uint64_t)json_object_get_int64(item);
+		break;
+
+	case SD_BUS_TYPE_DOUBLE:
+		any.dbl = json_object_get_double(item);
+		break;
+
+	case SD_BUS_TYPE_STRING:
+	case SD_BUS_TYPE_OBJECT_PATH:
+	case SD_BUS_TYPE_SIGNATURE:
+		any.cstr = json_object_get_string(item);
+		break;
+
+	case SD_BUS_TYPE_VARIANT:
+		signature = signature_for_json(item);
+		if (signature == NULL)
+			goto error;
+		rc = sd_bus_message_open_container(msg, SD_BUS_TYPE_VARIANT, signature);
+		if (rc < 0)
+			goto error;
+		rc = packsingle(msg, signature, item);
+		if (rc < 0)
+			goto error;
+		rc = sd_bus_message_close_container(msg);
+		if (rc < 0)
+			goto error;
+		return len;
+
+	case SD_BUS_TYPE_ARRAY:
+		subsig = strndupa(signature + 1, len - 1);
+		rc = sd_bus_message_open_container(msg, SD_BUS_TYPE_ARRAY, subsig);
+		if (rc < 0)
+			goto error;
+		if (json_object_is_type(item, json_type_array)) {
+			/* Is an array! */
+			count = json_object_array_length(item);
+			index = 0;
+			while(index < count) {
+				rc = packsingle(msg, subsig, json_object_array_get_idx(item, index++));
+				if (rc < 0)
+					goto error;
+			}
+		} else {
+			/* Not an array! Check if it matches an string dictionnary */
+			if (!json_object_is_type(item, json_type_object))
+				goto error;
+			if (*subsig++ != SD_BUS_TYPE_DICT_ENTRY_BEGIN)
+				goto error;
+			if (*subsig != SD_BUS_TYPE_STRING)
+				goto error;
+			/* iterate the object values */
+			subsig[strlen(subsig) - 1] = 0;
+			it = json_object_iter_begin(item);
+			end = json_object_iter_end(item);
+			while (!json_object_iter_equal(&it, &end)) {
+				rc = sd_bus_message_open_container(msg, SD_BUS_TYPE_DICT_ENTRY, subsig);
+				if (rc < 0)
+					goto error;
+				any.cstr = json_object_iter_peek_name(&it);
+				rc = sd_bus_message_append_basic(msg, *subsig, &any);
+				if (rc < 0)
+					goto error;
+				rc = packsingle(msg, subsig + 1, json_object_iter_peek_value(&it));
+				if (rc < 0)
+					goto error;
+				rc = sd_bus_message_close_container(msg);
+				if (rc < 0)
+					goto error;
+				json_object_iter_next(&it);
+			}
+		}
+		rc = sd_bus_message_close_container(msg);
+		if (rc < 0)
+			goto error;
+		return len;
+
+	case SD_BUS_TYPE_STRUCT_BEGIN:
+	case SD_BUS_TYPE_DICT_ENTRY_BEGIN:
+		subsig = strndupa(signature + 1, len - 2);
+		rc = sd_bus_message_open_container(msg,
+			((*signature) == SD_BUS_TYPE_STRUCT_BEGIN) ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY,
+			subsig);
+		if (rc < 0)
+			goto error;
+		rc = packlist(msg, subsig, item);
+		if (rc < 0)
+			goto error;
+		rc = sd_bus_message_close_container(msg);
+		if (rc < 0)
+			goto error;
+		return len;
+
+	default:
+		goto error;
+	}
+
+	rc = sd_bus_message_append_basic(msg, *signature, &any);
+	if (rc < 0)
+		goto error;
+	return len;
+
+error:
+	return -1;
+}
+
+static int packlist(struct sd_bus_message *msg, const char *signature, struct json_object *list)
+{
+	int rc, count, index, scan;
+	struct json_object *item;
+
+	scan = 0;
+	if (list == NULL) {
+		/* empty case */
+		if (*signature)
+			goto error;
+		return scan;
+	}
+
+	if (!json_object_is_type(list, json_type_array)) {
+		/* down grade gracefully to single */
+		rc = packsingle(msg, signature, list);
+		if (rc < 0)
+			goto error;
+		scan = rc;
+		if (signature[scan] != 0)
+			goto error;
+		return scan;
+	}
+
+	/* iterate over elements */
+	count = json_object_array_length(list);
+	index = 0;
+	for (;;) {
+		/* check state */
+		if (index == count && signature[scan] == 0)
+			return scan;
+		if (index == count || signature[scan] == 0)
+			goto error;
+
+		/* get the item */
+		item = json_object_array_get_idx(list, index);
+		if (item == NULL)
+			goto error;
+
+		/* pack the item */
+		rc = packsingle(msg, signature + scan, item);
+		if (rc < 0)
+			goto error;
+
+		/* advance */
+		scan += rc;
+		index++;
+	}
+
+error:
+	return -(scan + 1);
+}
+
+/*
+ * handle the reply
+ */
+static int on_rawcall_reply(sd_bus_message *msg, struct afb_req *req, sd_bus_error *ret_error)
+{
+	struct json_object *obj = NULL;
+	int rc;
+	const sd_bus_error *err;
+
+	err = sd_bus_message_get_error(msg);
+	if (err != NULL)
+		afb_req_fail_f(*req, "failed", "DBus-error-name: %s, DBus-error-message: %s", err->name, err->message);
+	else {
+		rc = unpacklist(msg, &obj);
+		if (rc < 0)
+			afb_req_fail(*req, "failed", "can't unpack");
+		else
+			afb_req_success(*req, obj, NULL);
+	}
+	json_object_put(obj);
+	afb_req_unref(*req);
+	free(req);
+	return 1;
+}
+
+/*
+ * Make a raw call to DBUS method
+ * The query should have:
+ *   {
+ *     "bus": "optional: 'system' or 'user' (default)"
+ *     "destination": "destination handling the object",
+ *     "path": "object path",
+ *     "interface": "interface of the call",
+ *     "member": "member of the interface of the call",
+ *     "signature": "signature of the arguments",
+ *     "arguments": "ARRAY of arguments"
+ *   }
+ */
+static void rawcall(struct afb_req req)
+{
+	struct json_object *obj;
+	struct json_object *args;
+
+	const char *busname;
+	const char *destination;
+	const char *path;
+	const char *interface;
+	const char *member;
+	const char *signature;
+
+	struct sd_bus_message *msg = NULL;
+	struct sd_bus *bus;
+	int rc;
+
+	/* get the query */
+	obj = afb_req_json(req);
+	if (obj == NULL)
+		goto internal_error;
+
+	/* get parameters */
+	destination = strval(obj, "destination");
+	path = strval(obj, "path");
+	interface = strval(obj, "interface");
+	member = strval(obj, "member");
+	if (path == NULL || member == NULL)
+		goto bad_request;
+
+	/* get arguments */
+	signature = strval(obj, "signature") ? : "";
+	args = NULL;
+	json_object_object_get_ex(obj, "arguments", &args);
+
+	/* get bus */
+	busname = strval(obj, "bus");
+	if (busname != NULL && !strcmp(busname, "system"))
+		bus = afb_daemon_get_system_bus(afbitf->daemon);
+	else
+		bus = afb_daemon_get_user_bus(afbitf->daemon);
+
+	/* creates the message */
+	rc = sd_bus_message_new_method_call(bus, &msg, destination, path, interface, member);
+	if (rc != 0)
+		goto internal_error;
+	rc = packlist(msg, signature, args);
+	if (rc < 0)
+		goto bad_request;
+
+	/*  */
+	rc = sd_bus_call_async(bus, NULL, msg, (void*)on_rawcall_reply, afb_req_store(req), -1);
+	if (rc < 0)
+		goto internal_error;
+	goto cleanup;
+
+internal_error:
+	afb_req_fail(req, "failed", "internal error");
+	goto cleanup;
+
+bad_request:
+	afb_req_fail(req, "failed", "bad request");
+
+cleanup:
+	sd_bus_message_unref(msg);
+}
+
+/*
+ * array of the verbs exported to afb-daemon
+ */
+static const struct afb_verb_desc_v1 binding_verbs[] = {
+  /* VERB'S NAME       SESSION MANAGEMENT          FUNCTION TO CALL     SHORT DESCRIPTION */
+  { .name= "rawcall",  .session= AFB_SESSION_NONE, .callback= rawcall,  .info= "raw call to dbus method" },
+  { .name= NULL } /* marker for end of the array */
+};
+
+/*
+ * description of the binding for afb-daemon
+ */
+static const struct afb_binding binding_description =
+{
+  /* description conforms to VERSION 1 */
+  .type= AFB_BINDING_VERSION_1,
+  .v1= {			/* fills the v1 field of the union when AFB_BINDING_VERSION_1 */
+    .prefix= "dbus",		/* the API name (or binding name or prefix) */
+    .info= "raw dbus binding",	/* short description of of the binding */
+    .verbs = binding_verbs	/* the array describing the verbs of the API */
+  }
+};
+
+/*
+ * activation function for registering the binding called by afb-daemon
+ */
+const struct afb_binding *afbBindingV1Register(const struct afb_binding_interface *itf)
+{
+	afbitf = itf;			/* records the interface for accessing afb-daemon */
+	return &binding_description;	/* returns the description of the binding */
+}
+
diff --git a/bindings/intrinsics/export.map b/bindings/intrinsics/export.map
new file mode 100644
index 00000000..0ef1ac79
--- /dev/null
+++ b/bindings/intrinsics/export.map
@@ -0,0 +1 @@
+{ global: afbBindingV1Register; local: *; };
diff --git a/bindings/media/CMakeLists.txt b/bindings/media/CMakeLists.txt
new file mode 100644
index 00000000..2866dfbc
--- /dev/null
+++ b/bindings/media/CMakeLists.txt
@@ -0,0 +1,18 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(gupnp gupnp-1.0 gupnp-av-1.0 gssdp-1.0 gobject-2.0 gio-2.0)
+
+IF(gupnp_FOUND)
+
+  MESSAGE(STATUS "gupnp found ; will compile Media binding... (binding)")
+
+  INCLUDE_DIRECTORIES( ${include_dirs} ${gupnp_INCLUDE_DIRS})
+  ADD_LIBRARY(media-api MODULE media-api.c media-rygel.c)
+  SET_TARGET_PROPERTIES(media-api PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
+  )
+  TARGET_LINK_LIBRARIES(media-api ${link_libraries} ${gupnp_LIBRARIES})
+  INSTALL(TARGETS media-api
+          LIBRARY DESTINATION ${binding_install_dir})
+
+ENDIF(gupnp_FOUND)
diff --git a/bindings/media/export.map b/bindings/media/export.map
new file mode 100644
index 00000000..0ef1ac79
--- /dev/null
+++ b/bindings/media/export.map
@@ -0,0 +1 @@
+{ global: afbBindingV1Register; local: *; };
diff --git a/bindings/media/media-api.c b/bindings/media/media-api.c
new file mode 100644
index 00000000..578d0066
--- /dev/null
+++ b/bindings/media/media-api.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+
+#include <string.h>
+
+#include <json-c/json.h>
+
+#include "media-api.h"
+#include "media-rygel.h"
+
+#include <afb/afb-plugin.h>
+#include <afb/afb-req-itf.h>
+
+json_object* _rygel_list (mediaCtxHandleT *);
+
+/* ------ LOCAL HELPER FUNCTIONS --------- */
+
+/* private client context creation ; default values */
+static mediaCtxHandleT* initMediaCtx () {
+
+    mediaCtxHandleT *ctx;
+
+    ctx = malloc (sizeof(mediaCtxHandleT));
+    ctx->media_server = NULL;
+    ctx->index = 0;
+
+    return ctx;
+}
+
+/* ------ PUBLIC PLUGIN FUNCTIONS --------- */
+
+static void init (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    mediaCtxHandleT *ctx = afb_req_context_get(request);
+    json_object *jresp;
+
+    /* create a private client context */
+    if (!ctx) {
+        ctx = initMediaCtx();
+        afb_req_context_set (request, ctx, free);
+    }
+
+    /* initialize server connection */
+    if (!ctx->media_server)
+      _rygel_init (ctx);
+
+    jresp = json_object_new_object ();
+    json_object_object_add (jresp, "init", json_object_new_string ("success"));
+    afb_req_success (request, jresp, "Media - Initialized");
+}
+
+static void list (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    mediaCtxHandleT *ctx = afb_req_context_get(request);
+    json_object *jresp;
+
+    /* check that context is initialized */
+    if (ctx == NULL) {
+      afb_req_fail (request, "failed", "uninitialized");
+      return;
+    }
+
+    jresp = _rygel_list (ctx);
+
+    if (!jresp) {
+      afb_req_fail (request, "failed", "no content found in media server");
+      return;
+    }
+
+    afb_req_success (request, jresp, "Media - Listed");
+}
+
+static void selecting (struct afb_req request) {   /* AFB_SESSION_CHECK */
+
+    mediaCtxHandleT *ctx = afb_req_context_get(request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp;
+    unsigned int index;
+    char index_str[5];
+
+    /* check that context is initialized */
+    if (ctx == NULL) {
+      afb_req_fail (request, "failed", "uninitialized");
+      return;
+    }
+
+    /* no "?value=" parameter : return current index */
+    if (!value) {
+        snprintf (index_str, sizeof(index_str), "%d", ctx->index);
+        jresp = json_object_new_object();
+        json_object_object_add (jresp, "index", json_object_new_string (index_str));
+    }
+
+    /* "?value=" parameter is negative */
+    else if (atoi(value) < 0) {
+        afb_req_fail (request, "failed", "chosen index cannot be negative");
+        return;
+    }
+
+    /* "?value=" parameter is positive */
+    else if (atoi(value) >= 0) {
+        index = (unsigned int) atoi(value);
+
+        if (!_rygel_select (ctx, index)) {
+          afb_req_fail (request, "failed", "chosen index superior to current media count");
+          return;
+        }
+
+        ctx->index = index;
+        jresp = json_object_new_object();
+        json_object_object_add (jresp, "index", json_object_new_string (value));
+    }
+    else
+        jresp = NULL;
+
+    afb_req_success (request, jresp, "Media - Listed");
+}
+
+static void play (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    mediaCtxHandleT *ctx = afb_req_context_get(request);
+    json_object *jresp;
+
+    /* check that context is initialized */
+    if (ctx == NULL) {
+      afb_req_fail (request, "failed", "uninitialized");
+      return;
+    }
+
+    if (!_rygel_do (ctx, PLAY, NULL)) {
+      afb_req_fail (request, "failed", "could not play chosen media");
+      return;
+    }
+
+    jresp = json_object_new_object ();
+    json_object_object_add (jresp, "play", json_object_new_string ("success"));
+    afb_req_success (request, jresp, "Media - Listed");
+}
+
+static void stop (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    mediaCtxHandleT *ctx = afb_req_context_get(request);
+    json_object *jresp;
+
+    /* check that context is initialized */
+    if (ctx == NULL) {
+      afb_req_fail (request, "failed", "uninitialized");
+      return;
+    }
+
+    if (!_rygel_do (ctx, STOP, NULL)) {
+      afb_req_fail (request, "failed", "could not stop chosen media");
+      return;
+    }
+
+    jresp = json_object_new_object ();
+    json_object_object_add (jresp, "stop", json_object_new_string ("success"));
+    afb_req_success (request, jresp, "Media - Stopped");
+}
+
+static void pausing (struct afb_req request) {     /* AFB_SESSION_CHECK */
+
+    mediaCtxHandleT *ctx = afb_req_context_get(request);
+    json_object *jresp;
+
+    /* check that context is initialized */
+    if (ctx == NULL) {
+      afb_req_fail (request, "failed", "uninitialized");
+      return;
+    }
+
+    if (!_rygel_do (ctx, PAUSE, NULL)) {
+      afb_req_fail (request, "failed", "could not pause chosen media");
+      return;
+    }
+
+    jresp = json_object_new_object();
+    json_object_object_add (jresp, "pause", json_object_new_string ("success"));
+    afb_req_success (request, jresp, "Media - Paused");
+}
+
+static void seek (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    mediaCtxHandleT *ctx = afb_req_context_get(request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp;
+
+    /* check that context is initialized */
+    if (ctx == NULL) {
+      afb_req_fail (request, "failed", "uninitialized");
+      return;
+    }
+
+    /* no "?value=" parameter : return error */
+    if (!value) {
+      afb_req_fail (request, "failed", "you must provide a time");
+      return;
+    }
+
+    if (!_rygel_do (ctx, SEEK, (char *)value)) {
+      afb_req_fail (request, "failed", "could not seek chosen media");
+      return;
+    }
+
+    jresp = json_object_new_object();
+    json_object_object_add (jresp, "seek", json_object_new_string ("success"));
+    afb_req_success (request, jresp, "Media - Sought");
+}
+
+static char *renamed_filename(struct afb_arg argfile)
+{
+    char *result;
+    const char *e = strrchr(argfile.path, '/');
+    if (e == NULL)
+        result = strdup(argfile.value);
+    else {
+        result = malloc((++e - argfile.path) + strlen(argfile.value) + 1);
+        if (result != NULL)
+            strcpy(stpncpy(result, argfile.path, e - argfile.path), argfile.value);
+    }
+    return result;
+}
+
+static void on_uploaded(struct afb_req *prequest, int status)
+{
+    struct afb_req request = afb_req_unstore(prequest);
+    struct afb_arg argfile = afb_req_get(request, "file-upload");
+    char *file = renamed_filename(argfile);
+    if (file != NULL)
+        unlink(file);
+    free(file);
+    if (status)
+        afb_req_fail (request, "failed", "expected file not received");
+    else
+        afb_req_success_f (request, NULL, "uploaded file %s", argfile.value);
+   afb_req_unref(request);
+}
+
+static void upload (struct afb_req request) { /* AFB_SESSION_CHECK */
+
+    mediaCtxHandleT *ctx = afb_req_context_get(request);
+    struct afb_req *prequest;
+    struct afb_arg argfile;
+    char *path;
+
+    /* check that context is initialized */
+    if (ctx == NULL) {
+      afb_req_fail (request, "failed", "uninitialized");
+      return;
+    }
+
+    /* get the file */
+    argfile = afb_req_get(request, "file-upload");
+    if (!argfile.value || !argfile.path) {
+        afb_req_fail (request, "failed", "expected file not received");
+        return;
+    }
+
+    /* rename the file */
+    path = renamed_filename(argfile);
+    if (path == NULL) {
+        afb_req_fail (request, "failed", "out of memory");
+        return;
+    }
+    if (rename(argfile.path, path) != 0) {
+        free(path);
+        afb_req_fail (request, "failed", "system error");
+        return;
+    }
+
+    /* for asynchronous processing */
+    prequest = afb_req_store(request);
+    if (path == NULL) {
+        unlink(path);
+        afb_req_fail (request, "failed", "out of memory");
+    }
+    else if (!_rygel_upload (ctx, path, (void*)on_uploaded, prequest)) {
+        afb_req_unref(afb_req_unstore(prequest));
+        unlink(path);
+        afb_req_fail (request, "failed", "Error when uploading file to media server... could not complete");
+    }
+    free(path);
+}
+
+static void ping (struct afb_req request) {         /* AFB_SESSION_NONE */
+    afb_req_success (request, NULL, "Media - Ping succeeded");
+}
+
+
+static const struct AFB_verb_desc_v1 verbs[]= {
+  {"init"   , AFB_SESSION_CHECK,  init       , "Media API - init"   },
+  {"list"   , AFB_SESSION_CHECK,  list       , "Media API - list"   },
+  {"select" , AFB_SESSION_CHECK,  selecting  , "Media API - select" },
+  {"play"   , AFB_SESSION_CHECK,  play       , "Media API - play"   },
+  {"stop"   , AFB_SESSION_CHECK,  stop       , "Media API - stop"   },
+  {"pause"  , AFB_SESSION_CHECK,  pausing    , "Media API - pause"  },
+  {"seek"   , AFB_SESSION_CHECK,  seek       , "Media API - seek"   },
+//  {"upload" , AFB_SESSION_CHECK,  upload     , "Media API - upload" },
+  {"ping"   , AFB_SESSION_NONE,   ping       , "Media API - ping"   },
+  {NULL}
+};
+
+static const struct AFB_plugin pluginDesc = {
+    .type   = AFB_PLUGIN_VERSION_1,
+    .v1 = {
+        .info   = "Application Framework Binder - Media plugin",
+        .prefix = "media",
+        .verbs   = verbs
+    }
+};
+
+const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
+{
+    return &pluginDesc;
+}
diff --git a/bindings/media/media-api.h b/bindings/media/media-api.h
new file mode 100644
index 00000000..c1d764c2
--- /dev/null
+++ b/bindings/media/media-api.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_API_H
+#define MEDIA_API_H
+
+/* -------------- PLUGIN DEFINITIONS ----------------- */
+
+/* private client context [will be destroyed when client leaves] */
+typedef struct {
+  void *media_server;          /* handle to implementation (Rygel...) */
+  unsigned int index;          /* currently selected media file       */
+} mediaCtxHandleT;
+
+#endif /* MEDIA_API_H */
diff --git a/bindings/media/media-rygel.c b/bindings/media/media-rygel.c
new file mode 100644
index 00000000..00327795
--- /dev/null
+++ b/bindings/media/media-rygel.c
@@ -0,0 +1,721 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+
+#include "media-api.h"
+#include "media-rygel.h"
+
+static void _rygel_device_cb (GUPnPControlPoint *, GUPnPDeviceProxy *, gpointer);
+static void _rygel_av_transport_cb (GUPnPControlPoint *, GUPnPDeviceProxy *, gpointer);
+static void _rygel_content_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
+static void _rygel_metadata_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
+static void _rygel_select_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
+static void _rygel_upload_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
+static void _rygel_transfer_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
+static void _rygel_do_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
+
+static unsigned int client_count = 0;
+static struct dev_ctx **dev_ctx = NULL;
+
+/* -------------- MEDIA RYGEL IMPLEMENTATION ---------------- */
+
+/* --- PUBLIC FUNCTIONS --- */
+
+unsigned char _rygel_init (mediaCtxHandleT *ctx) {
+
+    GMainContext *loop;
+    GUPnPContext *context;
+    GUPnPControlPoint *control_point;
+    gint handler_cb;
+    struct timeval tv_start, tv_now;
+
+    context = gupnp_context_new (NULL, NULL, 0, NULL);
+
+    control_point = gupnp_control_point_new (context, URN_MEDIA_SERVER);
+
+    handler_cb = g_signal_connect (control_point, "device-proxy-available",
+                                   G_CALLBACK (_rygel_device_cb), ctx);
+
+    /* start searching for servers */
+    gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (control_point), TRUE);
+
+    loop = g_main_context_default ();
+
+    /* 5 seconds should be sufficient to find Rygel */
+    gettimeofday (&tv_start, NULL);
+    gettimeofday (&tv_now, NULL);
+    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
+
+        g_main_context_iteration (loop, FALSE);
+
+        if (ctx->media_server)
+            break;
+        gettimeofday (&tv_now, NULL);
+    }
+    /* fail if we found no server */
+    if (!ctx->media_server)
+      return 0;
+
+    /* we have found the server ; stop looking for it... */
+    g_signal_handler_disconnect (control_point, handler_cb);
+
+    dev_ctx[client_count]->loop = loop;
+    dev_ctx[client_count]->context = context;
+    dev_ctx[client_count]->av_transport = NULL;
+    dev_ctx[client_count]->state = STOP;
+    dev_ctx[client_count]->target_state = STOP;
+    dev_ctx[client_count]->action_args = NULL;
+    dev_ctx[client_count]->transfer_started = 0;
+
+    client_count++;
+
+    return 1;
+}
+
+void _rygel_free (mediaCtxHandleT *ctx) {
+
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
+
+    client_count--;
+
+    g_main_context_unref (dev_ctx_c->loop);
+    dev_ctx_c->loop = NULL;
+    dev_ctx_c->context = NULL;
+    dev_ctx_c->device_info = NULL;
+    dev_ctx_c->av_transport = NULL;
+    dev_ctx_c->content_dir = NULL;
+    dev_ctx_c->content_res = NULL;
+}
+
+json_object* _rygel_list (mediaCtxHandleT *ctx) {
+
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
+    json_object *json_o, *json_a;
+    char *raw, *start, *end, *id, *title;
+    int length, i = 0;
+
+    if (!dev_ctx_c)
+      return NULL;
+
+    raw = _rygel_list_raw (dev_ctx_c, NULL);
+    if (!raw)
+      return NULL;
+
+    start = strstr (raw, "<dc:title>");
+    if (!start)
+      return NULL;
+
+    json_o = json_object_new_object ();
+    json_a = json_object_new_array ();
+    while (start) {
+        json_object *json_i, *json_id, *json_title;
+
+        start = strstr (start, "<dc:title>");
+        if (!start) break;
+        end = strstr (start, "</dc:title>");
+        start += 10;
+        length = end - start;
+
+        asprintf (&id, "%02d", i);
+
+        title = (char*) malloc (length+1);
+        strncpy (title, start, length);
+        title[length] = '\0';
+
+        json_i = json_object_new_object ();
+        json_id = json_object_new_string (id);
+        json_title = json_object_new_string (title);
+        json_object_object_add (json_i, "id", json_id);
+        json_object_object_add (json_i, "title", json_title);
+        json_object_array_add (json_a, json_i);
+
+        free (id); free (title); 
+        i++;
+    }
+
+    json_object_object_add (json_o, "list", json_a);
+
+    return json_o;
+}
+
+unsigned char _rygel_select (mediaCtxHandleT *ctx, unsigned int index) {
+
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
+    unsigned int count;
+
+    if (!dev_ctx_c)
+      return 0;
+
+    if (!_rygel_list_raw (dev_ctx_c, &count) ||
+        index >= count)
+      return 0;
+
+    if (ctx->index != index)
+      dev_ctx_c->state = STOP;
+
+    return 1;
+}
+
+unsigned char _rygel_upload (mediaCtxHandleT *ctx, const char *path, void (*oncompletion)(void*,int), void *closure) {
+
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
+    char *raw, *upload_id;
+
+    if (!dev_ctx_c)
+      return 0;
+
+    raw = _rygel_list_raw (dev_ctx_c, NULL);
+    if (!raw)
+      return 0;
+
+    /* for now, we always use the same upload container id */
+    upload_id = _rygel_find_upload_id (dev_ctx_c, raw);
+
+    return _rygel_start_uploading (dev_ctx_c, strdup(path), upload_id);
+}
+
+unsigned char _rygel_do (mediaCtxHandleT *ctx, State state, char *args) {
+
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
+    unsigned int index = ctx->index;
+    unsigned int count;
+    char *raw, *id, *metadata, *uri;
+
+    if (!dev_ctx_c || dev_ctx_c->state == state)
+        return 0;
+
+    raw = _rygel_list_raw (dev_ctx_c, &count);
+    if (!raw || index >= count)
+      return 0;
+
+          id = _rygel_find_id_for_index (dev_ctx_c, raw, index);
+    metadata = _rygel_find_metadata_for_id (dev_ctx_c, id);
+         uri = _rygel_find_uri_for_metadata (dev_ctx_c, metadata);
+
+    return _rygel_start_doing (dev_ctx_c, uri, metadata, state, args);
+}
+
+/* --- LOCAL HELPER FUNCTIONS --- */
+
+char* _rygel_list_raw (dev_ctx_T* dev_ctx_c, unsigned int *count) {
+
+    GUPnPServiceProxy *content_dir_proxy;
+    struct timeval tv_start, tv_now;
+
+    dev_ctx_c->content_res = NULL;
+    dev_ctx_c->content_num = 0;
+    content_dir_proxy = GUPNP_SERVICE_PROXY (dev_ctx_c->content_dir);
+
+    gupnp_service_proxy_begin_action (content_dir_proxy, "Browse", _rygel_content_cb, dev_ctx_c,
+                                      "ObjectID", G_TYPE_STRING, "Filesystem",
+                                      "BrowseFlag", G_TYPE_STRING, "BrowseDirectChildren",
+                                      "Filter", G_TYPE_STRING, "@childCount",
+                                      "StartingIndex", G_TYPE_UINT, 0,
+                                      "RequestedCount", G_TYPE_UINT, 64,
+                                      "SortCriteria", G_TYPE_STRING, "",
+                                       NULL);
+
+    gettimeofday (&tv_start, NULL);
+    gettimeofday (&tv_now, NULL);
+    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
+
+        g_main_context_iteration (dev_ctx_c->loop, FALSE);
+
+        if (dev_ctx_c->content_res)
+            break;
+        gettimeofday (&tv_now, NULL);
+    }
+
+    if (count) *count = dev_ctx_c->content_num;
+    return dev_ctx_c->content_res;
+}
+
+char* _rygel_find_upload_id (dev_ctx_T* dev_ctx_c, char *raw) {
+
+    char *found;
+    char id[33];
+
+    found = strstr (raw, "parentID=\"");
+    found += 10;
+
+    /* IDs are 32-bit strings */
+    strncpy (id, found, 32);
+    id[32] = '\0';
+
+    return strdup (id);
+}
+
+char* _rygel_find_id_for_index (dev_ctx_T* dev_ctx_c, char *raw, unsigned int index) {
+
+    char *found = raw;
+    char id[33];
+    int i;
+
+    for (i = 0; i <= index; i++) {
+        found = strstr (found, "item id=");
+        found += 9;
+
+        if (i == index) {
+	    /* IDs are 32-bit strings */
+            strncpy (id, found, 32);
+            id[32] = '\0';
+        }
+    }
+
+    return strdup (id);
+}
+
+char* _rygel_find_metadata_for_id (dev_ctx_T* dev_ctx_c, char *id) {
+
+    GUPnPServiceProxy *content_dir_proxy;
+    struct timeval tv_start, tv_now;
+
+    dev_ctx_c->content_res = NULL;
+
+    content_dir_proxy = GUPNP_SERVICE_PROXY (dev_ctx_c->content_dir);
+
+    gupnp_service_proxy_begin_action (content_dir_proxy, "Browse", _rygel_metadata_cb, dev_ctx_c,
+                                      "ObjectID", G_TYPE_STRING, id,
+                                      "BrowseFlag", G_TYPE_STRING, "BrowseMetadata",
+                                      "Filter", G_TYPE_STRING, "*",
+                                      "StartingIndex", G_TYPE_UINT, 0,
+                                      "RequestedCount", G_TYPE_UINT, 0,
+                                      "SortCriteria", G_TYPE_STRING, "",
+                                       NULL);
+
+    gettimeofday (&tv_start, NULL);
+    gettimeofday (&tv_now, NULL);
+    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
+
+        g_main_context_iteration (dev_ctx_c->loop, FALSE);
+
+        if (dev_ctx_c->content_res)
+            break;
+        gettimeofday (&tv_now, NULL);
+    }
+
+    return dev_ctx_c->content_res;
+}
+
+char* _rygel_find_uri_for_metadata (dev_ctx_T* dev_ctx_c, char *metadata) {
+
+    char *start, *end, *uri = NULL;
+    int length;
+
+    /* position ourselves after the first "<res " tag */
+    start = strstr (metadata, "<res ");
+
+    while (start) {
+        start = strstr (start, "http://");
+	if (!start) break;
+	end = strstr (start, "</res>");
+	length = end - start;
+
+
+        uri = (char *)malloc (length + 1);
+	strncpy (uri, start, length);
+        uri[length] = '\0';
+        /* if the URI contains "primary_http", it is the main one ; stop here...*/
+        if (strstr (uri, "primary_http"))
+          break;
+
+        free (uri); start = end;
+    }
+
+    return uri;
+}
+
+char * _rygel_time_for_string (char *string) {
+
+    int total_seconds;
+    unsigned int hours, minutes, seconds;
+    char *time;
+
+    total_seconds = atoi (string);
+    hours = total_seconds / 3600;
+    minutes = (total_seconds / 60) - (hours * 60);
+    seconds = total_seconds - (hours * 3600) - (minutes * 60);
+
+    asprintf (&time, "%u:%02u:%02u", hours, minutes, seconds);
+
+    return time;
+}
+
+unsigned char _rygel_start_uploading (dev_ctx_T* dev_ctx_c, char *path, char *upload_id) {
+
+    GUPnPServiceProxy *content_dir_proxy;
+    GUPnPDIDLLiteWriter *didl_writer;
+    GUPnPDIDLLiteObject *didl_object;
+    char *didl, *content_type, *mime_type, *upnp_class;
+    struct timeval tv_start, tv_now;
+
+    didl_writer = gupnp_didl_lite_writer_new (NULL);
+    didl_object = GUPNP_DIDL_LITE_OBJECT (gupnp_didl_lite_writer_add_item (didl_writer));
+
+    /* create the metadata for the file */
+    gupnp_didl_lite_object_set_parent_id (didl_object, upload_id);
+    gupnp_didl_lite_object_set_id (didl_object, "");
+    gupnp_didl_lite_object_set_restricted (didl_object, FALSE);
+    gupnp_didl_lite_object_set_title (didl_object, g_path_get_basename (path));
+    /* deduce the UPnP class from the MIME type ("audio/ogg" e.g.) */
+    content_type = g_content_type_guess (path, NULL, 0, NULL);
+    mime_type = g_content_type_get_mime_type (content_type);
+    if (strstr (mime_type, "audio/"))
+      upnp_class = strdup ("object.item.audioItem.musicTrack");
+    else if (strstr (mime_type, "video/"))
+      upnp_class = strdup ("object.item.videoItem");
+    else if (strstr (mime_type, "image/"))
+      upnp_class = strdup ("object.item.imageItem");
+    else
+      upnp_class = strdup ("object.item");
+    gupnp_didl_lite_object_set_upnp_class (didl_object, upnp_class);
+    didl = gupnp_didl_lite_writer_get_string (didl_writer);
+
+    dev_ctx_c->transfer_path = path;
+    dev_ctx_c->transfer_started = 0;
+    content_dir_proxy = GUPNP_SERVICE_PROXY (dev_ctx_c->content_dir);
+
+    gupnp_service_proxy_begin_action (content_dir_proxy, "CreateObject", _rygel_upload_cb, dev_ctx_c,
+                                      "ContainerID", G_TYPE_STRING, upload_id,
+                                      "Elements", G_TYPE_STRING, didl,
+                                       NULL);
+
+    gettimeofday (&tv_start, NULL);
+    gettimeofday (&tv_now, NULL);
+    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
+
+      g_main_context_iteration (dev_ctx_c->loop, FALSE);
+
+      if (dev_ctx_c->transfer_started)
+        break;
+      gettimeofday (&tv_now, NULL);
+    }
+    if (!dev_ctx_c->transfer_started)
+      return 0;
+
+    return 1;
+}
+
+unsigned char _rygel_start_doing (dev_ctx_T* dev_ctx_c, char *uri, char *metadata, State state, char *args) {
+
+    GUPnPServiceProxy *av_transport_proxy;
+    struct timeval tv_start, tv_now;
+
+    if (!dev_ctx_c->av_transport) {
+      if (!_rygel_find_av_transport (dev_ctx_c))
+         return 0;
+    }
+    dev_ctx_c->target_state = state;
+    dev_ctx_c->action_args = args;
+    av_transport_proxy = GUPNP_SERVICE_PROXY (dev_ctx_c->av_transport);
+
+    gupnp_service_proxy_begin_action (av_transport_proxy, "SetAVTransportURI", _rygel_select_cb, dev_ctx_c,
+                                      "InstanceID", G_TYPE_UINT, 0,
+                                      "CurrentURI", G_TYPE_STRING, uri,
+                                      "CurrentURIMetaData", G_TYPE_STRING, metadata,
+                                       NULL);
+
+    gettimeofday (&tv_start, NULL);
+    gettimeofday (&tv_now, NULL);
+    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
+
+      g_main_context_iteration (dev_ctx_c->loop, FALSE);
+
+      if (dev_ctx_c->state == state)
+        break;
+      gettimeofday (&tv_now, NULL);
+    }
+    if (dev_ctx_c->state != state)
+      return 0;
+
+    return 1;
+}
+
+unsigned char _rygel_find_av_transport (dev_ctx_T* dev_ctx_c) {
+
+    GUPnPControlPoint *control_point;
+    gint handler_cb;
+    struct timeval tv_start, tv_now;
+
+    control_point = gupnp_control_point_new (dev_ctx_c->context, URN_MEDIA_RENDERER);
+
+    handler_cb = g_signal_connect (control_point, "device-proxy-available",
+                                   G_CALLBACK (_rygel_av_transport_cb), dev_ctx_c);
+
+    gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (control_point), TRUE);
+
+    gettimeofday (&tv_start, NULL);
+    gettimeofday (&tv_now, NULL);
+    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
+
+        g_main_context_iteration (dev_ctx_c->loop, FALSE);
+
+        if (dev_ctx_c->av_transport)
+            break;
+        gettimeofday (&tv_now, NULL);
+    }
+    g_signal_handler_disconnect (control_point, handler_cb);
+
+    if (!dev_ctx_c->av_transport)
+      return 0;
+
+    return 1;
+}
+
+
+ /* ---- LOCAL CALLBACK FUNCTIONS ---- */
+
+static void _rygel_device_cb (GUPnPControlPoint *point, GUPnPDeviceProxy *proxy,
+                              gpointer data) {
+
+    mediaCtxHandleT *ctx = (mediaCtxHandleT*)data;
+    GUPnPDeviceInfo *device_info;
+    GUPnPServiceInfo *content_dir;
+    const char *device_name;
+
+    device_info = GUPNP_DEVICE_INFO (proxy);
+    device_name = gupnp_device_info_get_model_name (device_info);
+    content_dir = gupnp_device_info_get_service (device_info, URN_CONTENT_DIR);
+
+    if (strcmp (device_name, "Rygel") != 0)
+        return;
+    if (!content_dir)
+        return;
+
+    /* allocate the global array if it has not been not done */
+    if (!dev_ctx)
+        dev_ctx = (dev_ctx_T**) malloc (sizeof(dev_ctx_T));
+    else
+        dev_ctx = (dev_ctx_T**) realloc (dev_ctx, (client_count+1)*sizeof(dev_ctx_T));
+
+    /* create an element for the client in the global array */
+    dev_ctx[client_count] = (dev_ctx_T*) malloc (sizeof(dev_ctx_T));
+    dev_ctx[client_count]->device_info = device_info;
+    dev_ctx[client_count]->content_dir = content_dir;
+
+    /* make the client context aware of it */
+    ctx->media_server = (void*)dev_ctx[client_count];
+}
+
+static void _rygel_av_transport_cb (GUPnPControlPoint *point, GUPnPDeviceProxy *proxy,
+                                    gpointer data) {
+
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
+    GUPnPDeviceInfo *device_info;
+    GUPnPServiceInfo *av_transport;
+
+    device_info = GUPNP_DEVICE_INFO (proxy);
+    av_transport = gupnp_device_info_get_service (device_info, URN_AV_TRANSPORT);
+
+    dev_ctx_c->av_transport = av_transport;
+}
+
+static void _rygel_content_cb (GUPnPServiceProxy *content_dir, GUPnPServiceProxyAction *action,
+                               gpointer data) {
+
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
+    GUPnPServiceProxy *content_dir_proxy = GUPNP_SERVICE_PROXY (content_dir);
+    GError *error;
+    char *result;
+    guint32 number_returned;
+    guint32 total_matches;
+    char *found;
+    char subid[33];
+
+    gupnp_service_proxy_end_action (content_dir, action, &error,
+                                    "Result", G_TYPE_STRING, &result,
+                                    "NumberReturned", G_TYPE_UINT, &number_returned,
+                                    "TotalMatches", G_TYPE_UINT, &total_matches,
+                                     NULL);
+
+    if (number_returned == 0)
+        return;
+
+    if (number_returned == 1) {
+        found = strstr (result, "id=\"");	
+        found += 4;
+        strncpy (subid, found, 32); subid[32] = '\0';
+
+	gupnp_service_proxy_begin_action (content_dir_proxy, "Browse", _rygel_content_cb, dev_ctx_c,
+					  "ObjectID", G_TYPE_STRING, subid,
+					  "BrowseFlag", G_TYPE_STRING, "BrowseDirectChildren",
+					  "Filter", G_TYPE_STRING, "@childCount",
+					  "StartingIndex", G_TYPE_UINT, 0,
+					  "RequestedCount", G_TYPE_UINT, 64,
+					  "SortCriteria", G_TYPE_STRING, "",
+					   NULL);
+        return;
+    }
+
+    if (number_returned > 1) {
+        dev_ctx_c->content_res = result;
+        dev_ctx_c->content_num = number_returned;
+    }
+}
+
+static void _rygel_metadata_cb (GUPnPServiceProxy *content_dir, GUPnPServiceProxyAction *action,
+                                gpointer data) {
+
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
+    GError *error;
+    char *result;
+
+    gupnp_service_proxy_end_action (content_dir, action, &error,
+                                    "Result", G_TYPE_STRING, &result,
+				     NULL);
+
+    dev_ctx_c->content_res = result;
+}
+
+static void _rygel_select_cb (GUPnPServiceProxy *av_transport, GUPnPServiceProxyAction *action,
+                              gpointer data)
+{
+
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
+    GUPnPServiceProxy *av_transport_proxy;
+    GError *error;
+    char *time;
+    struct timeval tv_start, tv_now;
+
+    av_transport_proxy = GUPNP_SERVICE_PROXY (av_transport);
+
+    gupnp_service_proxy_end_action (av_transport, action, &error, NULL);
+
+    switch (dev_ctx_c->target_state) {
+        case PLAY:
+          gupnp_service_proxy_begin_action (av_transport_proxy, "Play", _rygel_do_cb, dev_ctx_c,
+                                           "InstanceID", G_TYPE_UINT, 0,
+                                           "Speed", G_TYPE_STRING, "1",
+                                            NULL);
+          break;
+       case PAUSE:
+          gupnp_service_proxy_begin_action (av_transport_proxy, "Pause", _rygel_do_cb, dev_ctx_c,
+                                           "InstanceID", G_TYPE_UINT, 0,
+                                            NULL);
+          break;
+       case STOP:
+          gupnp_service_proxy_begin_action (av_transport_proxy, "Stop", _rygel_do_cb, dev_ctx_c,
+                                           "InstanceID", G_TYPE_UINT, 0,
+                                            NULL);
+          break;
+       case SEEK:
+          time = _rygel_time_for_string (dev_ctx_c->action_args);
+          gupnp_service_proxy_begin_action (av_transport_proxy, "Seek", _rygel_do_cb, dev_ctx_c,
+                                           "InstanceID", G_TYPE_UINT, 0,
+                                           "Unit", G_TYPE_STRING, "ABS_TIME",
+                                           "Target", G_TYPE_STRING, time,
+                                            NULL);
+       default:
+	 break;
+    }
+
+    gettimeofday (&tv_start, NULL);
+    gettimeofday (&tv_now, NULL);
+    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
+
+        g_main_context_iteration (dev_ctx_c->loop, FALSE);
+
+        if (dev_ctx_c->state == dev_ctx_c->target_state)
+            break;
+        gettimeofday (&tv_now, NULL);
+    }
+}
+
+static void _rygel_upload_cb (GUPnPServiceProxy *content_dir, GUPnPServiceProxyAction *action,
+                              gpointer data)
+{
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
+    GUPnPServiceProxy *content_dir_proxy;
+    GError *error;
+    char *result, *start, *end, *dst_uri, *src_uri;
+    int length;
+    struct timeval tv_start, tv_now;
+
+    content_dir_proxy = GUPNP_SERVICE_PROXY (content_dir);
+
+    if (!gupnp_service_proxy_end_action (content_dir, action, &error,
+                                         "Result", G_TYPE_STRING, &result,
+                                          NULL))
+      return;
+
+    start = strstr (result, "<res importUri=\"");
+    if (!start)
+      return;
+
+    start += 16;
+    end = strstr (start, "\"");
+    length = end - start;
+
+    dst_uri = (char*) malloc(length+1);
+    strncpy (dst_uri, start, length);
+    dst_uri[length] = '\0';
+
+    asprintf (&src_uri, "http://%s:%u%s", gupnp_context_get_host_ip (dev_ctx_c->context),
+                                          gupnp_context_get_port (dev_ctx_c->context),
+                                          dev_ctx_c->transfer_path);
+
+    /* host the file */
+    gupnp_context_host_path (dev_ctx_c->context, dev_ctx_c->transfer_path,
+                                                 dev_ctx_c->transfer_path);
+
+    gupnp_service_proxy_begin_action (content_dir_proxy, "ImportResource", _rygel_transfer_cb, dev_ctx_c,
+                                      "SourceURI", G_TYPE_STRING, src_uri,
+                                      "DestinationURI", G_TYPE_STRING, dst_uri,
+                                       NULL);
+
+    gettimeofday (&tv_start, NULL);
+    gettimeofday (&tv_now, NULL);
+    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
+
+        g_main_context_iteration (dev_ctx_c->loop, FALSE);
+
+        if (dev_ctx_c->transfer_started)
+            break;
+        gettimeofday (&tv_now, NULL);
+    }
+}
+
+static void _rygel_transfer_cb (GUPnPServiceProxy *content_dir, GUPnPServiceProxyAction *action,
+                                gpointer data)
+{
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
+    GError *error;
+    guint transfer_id;
+
+    if (!gupnp_service_proxy_end_action (content_dir, action, &error,
+                                         "TransferID", G_TYPE_UINT, &transfer_id,
+                                          NULL))
+      return;
+
+    dev_ctx_c->transfer_started = 1;
+}
+
+static void _rygel_do_cb (GUPnPServiceProxy *av_transport, GUPnPServiceProxyAction *action,
+                          gpointer data)
+{
+    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
+    GError *error;
+
+    if (!gupnp_service_proxy_end_action (av_transport, action, &error,
+                                         NULL))
+      return;
+
+    dev_ctx_c->state = dev_ctx_c->target_state;
+}
diff --git a/bindings/media/media-rygel.h b/bindings/media/media-rygel.h
new file mode 100644
index 00000000..951c6b89
--- /dev/null
+++ b/bindings/media/media-rygel.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_RYGEL_H
+#define MEDIA_RYGEL_H
+
+/* --------------- MEDIA RYGEL DEFINITIONS ------------------ */
+
+#include <sys/time.h>
+#include <json-c/json.h>
+#include <libgupnp/gupnp-control-point.h>
+#include <libgupnp-av/gupnp-av.h>
+
+#include "media-api.h"
+
+#define URN_MEDIA_SERVER   "urn:schemas-upnp-org:device:MediaServer:1"
+#define URN_MEDIA_RENDERER "urn:schemas-upnp-org:device:MediaRenderer:1"
+#define URN_CONTENT_DIR    "urn:schemas-upnp-org:service:ContentDirectory"
+#define URN_AV_TRANSPORT   "urn:schemas-upnp-org:service:AVTransport"
+
+typedef enum { PLAY, PAUSE, STOP, SEEK } State;
+typedef struct dev_ctx dev_ctx_T;
+
+struct dev_ctx {
+    GMainContext *loop;
+    GUPnPContext *context;
+    GUPnPDeviceInfo *device_info;
+    GUPnPServiceInfo *content_dir;
+    GUPnPServiceInfo *av_transport;
+    char *content_res;
+    int content_num;
+    State state;
+    State target_state;
+    char *action_args;
+    char *transfer_path;
+    unsigned char transfer_started;
+};
+
+unsigned char _rygel_init (mediaCtxHandleT *);
+void _rygel_free (mediaCtxHandleT *);
+json_object* _rygel_list (mediaCtxHandleT *);
+unsigned char _rygel_select (mediaCtxHandleT *, unsigned int);
+unsigned char _rygel_upload (mediaCtxHandleT *ctx, const char *path, void (*oncompletion)(void*,int), void *closure);
+unsigned char _rygel_do (mediaCtxHandleT *, State, char *);
+
+char* _rygel_list_raw (dev_ctx_T *, unsigned int *);
+char* _rygel_find_upload_id (dev_ctx_T *, char *);
+char* _rygel_find_id_for_index (dev_ctx_T *, char *, unsigned int);
+char* _rygel_find_metadata_for_id (dev_ctx_T *, char *);
+char* _rygel_find_uri_for_metadata (dev_ctx_T *, char *);
+unsigned char _rygel_start_uploading (dev_ctx_T *, char *, char *);
+unsigned char _rygel_start_doing (dev_ctx_T *, char *, char *, State, char *);
+unsigned char _rygel_find_av_transport (dev_ctx_T *);
+#endif /* MEDIA_RYGEL_H */
diff --git a/bindings/radio/CMakeLists.txt b/bindings/radio/CMakeLists.txt
new file mode 100644
index 00000000..4df7adb2
--- /dev/null
+++ b/bindings/radio/CMakeLists.txt
@@ -0,0 +1,17 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(librtlsdr librtlsdr>=0.5.0)
+
+IF(librtlsdr_FOUND)
+
+  MESSAGE(STATUS "librtlsdr found ; will compile Radio binding... (binding)")
+  INCLUDE_DIRECTORIES(${include_dirs} ${librtlsdr_INCLUDE_DIRS})
+  ADD_LIBRARY(radio-api MODULE radio-api.c radio-rtlsdr.c)
+  SET_TARGET_PROPERTIES(radio-api PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
+  )
+  TARGET_LINK_LIBRARIES(radio-api ${link_libraries} ${librtlsdr_LIBRARIES} -lm)
+  INSTALL(TARGETS radio-api
+          LIBRARY DESTINATION ${binding_install_dir})
+
+ENDIF(librtlsdr_FOUND)
diff --git a/bindings/radio/export.map b/bindings/radio/export.map
new file mode 100644
index 00000000..0ef1ac79
--- /dev/null
+++ b/bindings/radio/export.map
@@ -0,0 +1 @@
+{ global: afbBindingV1Register; local: *; };
diff --git a/bindings/radio/radio-api.c b/bindings/radio/radio-api.c
new file mode 100644
index 00000000..0ed60e1c
--- /dev/null
+++ b/bindings/radio/radio-api.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <strings.h>
+#include <json-c/json.h>
+
+#include "radio-api.h"
+#include "radio-rtlsdr.h"
+
+#include <afb/afb-plugin.h>
+#include <afb/afb-req-itf.h>
+
+/* ********************************************************
+
+   FULUP integration proposal with client session context
+
+   ******************************************************** */
+
+/* ------ LOCAL HELPER FUNCTIONS --------- */
+
+static pluginHandleT *the_radio = NULL;
+
+/* detect new radio devices */
+void updateRadioDevList(pluginHandleT *handle) {
+
+  int idx;  
+
+  // loop on existing radio if any
+  for (idx = 0; idx < _radio_dev_count(); idx++) {
+      if (idx == MAX_RADIO) break;
+      handle->radios[idx] = calloc(1, sizeof(radioDevT)); /* use calloc to set "used" to FALSE */
+      handle->radios[idx]->name = (char *) _radio_dev_name(idx);
+  }
+  handle->devCount = _radio_dev_count();
+}
+
+/* global plugin context creation ; at loading time [radio devices might not be visible] */
+static void initRadioPlugin() {
+
+  pluginHandleT *handle;
+
+  handle = calloc (1, sizeof(pluginHandleT));
+  updateRadioDevList (handle);
+  the_radio = handle;
+}
+
+/* private client context creation ; default values */
+static radioCtxHandleT* initRadioCtx () {
+
+    radioCtxHandleT *ctx;
+
+    ctx = malloc (sizeof(radioCtxHandleT));
+    ctx->radio = NULL;
+    ctx->idx = -1;
+    ctx->mode = FM;
+    ctx->freq = 100.0;
+    ctx->mute = 0;
+    ctx->is_playing = 0;
+
+    return ctx;
+}
+
+/* reserve a radio device for requesting client, power it on */
+unsigned char reserveRadio (pluginHandleT *handle, radioCtxHandleT *ctx) {
+
+    unsigned int idx;
+
+    /* loop on all devices, find an unused one */
+    for (idx = 0; idx < _radio_dev_count(); idx++) {
+        if (idx == MAX_RADIO) break;
+        if (handle->radios[idx]->used == FALSE) goto found_radio; /* found one */
+    }
+    return 0;
+
+  found_radio:
+    /* try to power it on, passing client context info such as frequency... */
+
+    _radio_on (idx, ctx);
+    /* TODO : try to re-iterate from the next ones if it failed ! */
+
+    /* globally mark it as reserved */
+    handle->radios[idx]->used = TRUE;
+
+    /* store relevant info to client context (direct pointer, index) */
+    ctx->radio = handle->radios[idx];
+    ctx->idx = idx;
+
+    return 1;
+}
+
+/* free a radio device from requesting client, power it off */
+unsigned char releaseRadio (pluginHandleT *handle, radioCtxHandleT *ctx) {
+
+    /* stop playing if it was doing this (blocks otherwise) */
+    if (ctx->is_playing) {
+        ctx->is_playing = 0;
+        _radio_stop (ctx->idx);
+    }
+
+    /* power it off */
+    _radio_off (ctx->idx);
+
+    /* globally mark it as free */
+    handle->radios[ctx->idx]->used = FALSE;
+
+    /* clean client context */
+    ctx->radio = NULL;
+    ctx->idx = -1;
+
+    return 1;
+}
+
+/* called when client session dies [e.g. client quits for more than 15mns] */
+static void freeRadio (void *context) {
+
+    releaseRadio (the_radio, context);
+    free (context);
+}
+
+
+/* ------ PUBLIC PLUGIN FUNCTIONS --------- */
+
+static void init (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    radioCtxHandleT *ctx = afb_req_context_get (request);
+    json_object *jresp;
+
+    /* create a global plugin handle */
+    if (!the_radio)
+        initRadioPlugin();
+
+    /* create a private client context */
+    if (!ctx) {
+        ctx = initRadioCtx();
+        afb_req_context_set (request, ctx, free);
+    }
+
+    jresp = json_object_new_object();
+    json_object_object_add(jresp, "init", json_object_new_string ("success"));
+    afb_req_success (request, jresp, "Radio initialized");
+}
+
+static void power (struct afb_req request) {       /* AFB_SESSION_CHECK */
+
+    pluginHandleT *handle = the_radio;
+    radioCtxHandleT *ctx = afb_req_context_get (request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp;
+
+	if (!ctx) {
+        afb_req_fail (request, "failed", "you must call 'init' first");
+        return;
+    }
+    jresp = json_object_new_object();
+
+    /* no "?value=" parameter : return current state */
+    if (!value) {
+        ctx->radio ?
+            json_object_object_add (jresp, "power", json_object_new_string ("on"))
+          : json_object_object_add (jresp, "power", json_object_new_string ("off"));
+        afb_req_success (request, jresp, "Radio - Power status obtained");
+        return;
+    }
+
+    /* "?value=" parameter is "1" or "true" */
+    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
+        if (!ctx->radio) {
+            if (!reserveRadio (handle, ctx)) {
+                afb_req_fail (request, "failed", "no more radio devices available");
+		        return;
+            }
+        }
+        json_object_object_add (jresp, "power", json_object_new_string ("on"));
+    }
+
+    /* "?value=" parameter is "0" or "false" */
+    else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
+        if (ctx->radio) {
+            if (!releaseRadio (handle, ctx)) {
+                afb_req_fail (request, "failed", "Unable to release radio device");
+		        return;
+            }
+        }
+        json_object_object_add (jresp, "power", json_object_new_string ("off"));
+    }
+    else
+        jresp = NULL;
+
+    afb_req_success (request, jresp, "Radio - Power set");
+}
+
+static void mode (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    radioCtxHandleT *ctx = afb_req_context_get (request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp;
+
+	if (!ctx) {
+        afb_req_fail (request, "failed", "you must call 'init' first");
+        return;
+    }
+    jresp = json_object_new_object();
+
+    /* no "?value=" parameter : return current state */
+    if (!value || !ctx->radio) {
+        ctx->mode ?
+            json_object_object_add (jresp, "mode", json_object_new_string ("AM"))
+          : json_object_object_add (jresp, "mode", json_object_new_string ("FM"));
+    }
+
+    /* "?value=" parameter is "1" or "AM" */
+    else if ( atoi(value) == 1 || !strcasecmp(value, "AM") ) {
+        ctx->mode = AM;
+        _radio_set_mode (ctx->idx, ctx->mode);
+        json_object_object_add (jresp, "mode", json_object_new_string ("AM"));
+    }
+
+    /* "?value=" parameter is "0" or "FM" */
+    else if ( atoi(value) == 0 || !strcasecmp(value, "FM") ) {
+        ctx->mode = FM;
+        _radio_set_mode (ctx->idx, ctx->mode);
+        json_object_object_add (jresp, "mode", json_object_new_string ("FM"));
+    }
+
+    afb_req_success (request, jresp, "Radio - Mode set");
+}
+
+static void freq (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    radioCtxHandleT *ctx = afb_req_context_get (request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp;
+    double freq;
+    char freq_str[256];
+
+	if (!ctx) {
+        afb_req_fail (request, "failed", "you must call 'init' first");
+        return;
+    }
+    jresp = json_object_new_object();
+
+    /* no "?value=" parameter : return current state */
+    if (!value || !ctx->radio) {
+        snprintf (freq_str, sizeof(freq_str), "%f", ctx->freq);
+        json_object_object_add (jresp, "freq", json_object_new_string (freq_str));
+    }
+
+    /* "?value=" parameter, set frequency */
+    else {
+        freq = strtod (value, NULL);
+        _radio_set_freq (ctx->idx, freq);
+        ctx->freq = (float)freq;
+
+        snprintf (freq_str, sizeof(freq_str), "%f", ctx->freq);
+        json_object_object_add (jresp, "freq", json_object_new_string (freq_str));
+    }
+
+    afb_req_success (request, jresp, "Radio - Frequency Set");
+}
+
+static void mute (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    radioCtxHandleT *ctx = afb_req_context_get (request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp = json_object_new_object();
+
+	if (!ctx) {
+        afb_req_fail (request, "failed", "you must call 'init' first");
+        return;
+    }
+
+    /* no "?value=" parameter : return current state */
+    if (!value || !ctx->radio) {
+        ctx->mute ?
+            json_object_object_add (jresp, "mute", json_object_new_string ("on"))
+          : json_object_object_add (jresp, "mute", json_object_new_string ("off"));
+    }
+
+    /* "?value=" parameter is "1" or "true" */
+    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
+        ctx->mute = 1;
+        _radio_set_mute (ctx->idx, ctx->mute);
+        json_object_object_add (jresp, "mute", json_object_new_string ("on"));
+    }
+
+    /* "?value=" parameter is "0" or "false" */
+    else if ( atoi(value) == 0 || !strcasecmp(value, "off") ) {
+        ctx->mute = 0;
+        _radio_set_mute (ctx->idx, ctx->mute);
+        json_object_object_add (jresp, "mute", json_object_new_string ("off"));
+    }
+
+    afb_req_success (request, jresp, "Radio - Mute set"); 
+}
+
+static void play (struct afb_req request) {        /* AFB_SESSION_CHECK */
+
+    radioCtxHandleT *ctx = afb_req_context_get (request);
+    const char *value = afb_req_value (request, "value");
+    json_object *jresp = json_object_new_object();
+
+	if (!ctx) {
+        afb_req_fail (request, "failed", "you must call 'init' first");
+        return;
+    }
+    
+    /* no "?value=" parameter : return current state */
+    if (!value || !ctx->radio) {
+        ctx->is_playing ?
+            json_object_object_add (jresp, "play", json_object_new_string ("on"))
+          : json_object_object_add (jresp, "play", json_object_new_string ("off"));
+    }
+
+    /* "?value=" parameter is "1" or "true" */
+    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
+        /* radio playback */
+        ctx->is_playing = 1;
+        _radio_play (ctx->idx);
+        json_object_object_add (jresp, "play", json_object_new_string ("on"));
+    }
+
+    /* "?value=" parameter is "0" or "false" */
+    else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
+        /* radio stop */
+        ctx->is_playing = 0;
+        _radio_stop (ctx->idx);
+        json_object_object_add (jresp, "play", json_object_new_string ("off"));
+    }
+
+    afb_req_success (request, jresp, "Radio - Play succeeded");
+}
+
+static void ping (struct afb_req request) {         /* AFB_SESSION_NONE */
+    afb_req_success (request, NULL, "Radio - Ping succeeded");
+}
+
+
+static const struct AFB_verb_desc_v1 verbs[] = {
+  {"init"   , AFB_SESSION_CHECK,  init       , "Radio API - init"},
+  {"power"  , AFB_SESSION_CHECK,  power      , "Radio API - power"},
+  {"mode"   , AFB_SESSION_CHECK,  mode       , "Radio API - mode"},
+  {"freq"   , AFB_SESSION_CHECK,  freq       , "Radio API - freq"},
+  {"mute"   , AFB_SESSION_CHECK,  mute       , "Radio API - mute"},
+  {"play"   , AFB_SESSION_CHECK,  play       , "Radio API - play"},
+  {"ping"   , AFB_SESSION_NONE,   ping       , "Radio API - ping"},
+  {NULL}
+};
+
+static const struct AFB_plugin pluginDesc = {
+    .type  = AFB_PLUGIN_VERSION_1,
+    .v1 = {
+        .info  = "Application Framework Binder - Radio plugin",
+        .prefix  = "radio",
+        .verbs  = verbs
+    }
+};
+
+const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
+{
+	return &pluginDesc;
+}
diff --git a/bindings/radio/radio-api.h b/bindings/radio/radio-api.h
new file mode 100644
index 00000000..9b91ec69
--- /dev/null
+++ b/bindings/radio/radio-api.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RADIO_API_H
+#define RADIO_API_H
+
+/* -------------- PLUGIN DEFINITIONS ----------------- */
+
+#define MAX_RADIO 10
+typedef enum { FM, AM } Mode;
+
+/* structure holding one radio device with current usage status */
+typedef struct {
+    int   idx;
+    char *name;
+    int  used;
+} radioDevT;
+
+/* global plugin handle, should store everything we may need */
+typedef struct {
+  radioDevT *radios[MAX_RADIO];  // pointer to existing radio
+  unsigned int devCount;
+} pluginHandleT;
+
+/* private client context [will be destroyed when client leaves] */
+typedef struct {
+    radioDevT *radio;         /* pointer to client radio            */
+    int idx;                  /* radio index within global array    */
+    Mode mode;                /* radio mode: AM/FM                  */
+    float freq;               /* radio frequency (Mhz)              */
+    unsigned char mute;       /* radio muted: 0(false)/1(true)      */
+    unsigned char is_playing; /* radio is playing: 0(false)/1(true) */
+} radioCtxHandleT;
+
+#endif /* RADIO_API_H */
diff --git a/bindings/radio/radio-rtlsdr.c b/bindings/radio/radio-rtlsdr.c
new file mode 100644
index 00000000..7f76306e
--- /dev/null
+++ b/bindings/radio/radio-rtlsdr.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "radio-api.h"
+#include "radio-rtlsdr.h"
+
+static void* _dongle_thread_fn (void *);
+static void* _demod_thread_fn (void *);
+static void* _output_thread_fn (void *);
+
+static unsigned int init_dev_count = 0;
+static struct dev_ctx **dev_ctx = NULL;
+
+/* ------------- RADIO RTLSDR IMPLEMENTATION ---------------- */
+
+/* --- PUBLIC FUNCTIONS --- */
+
+/* Radio initialization should be done only when user start the radio and not at plugin initialization
+   Making this call too early would impose to restart the binder to detect a radio */
+unsigned char _radio_on (unsigned int num, radioCtxHandleT *ctx) {
+ 
+    if (num >= _radio_dev_count())
+        return 0;
+    
+    if (init_dev_count < _radio_dev_count()) {
+        init_dev_count = _radio_dev_count();
+        dev_ctx = (dev_ctx_T**) realloc (dev_ctx, init_dev_count * sizeof(dev_ctx_T*));           
+    }
+
+    dev_ctx[num] = (dev_ctx_T*) malloc (sizeof(dev_ctx_T));
+    dev_ctx[num]->dev = NULL;
+    dev_ctx[num]->mode = ctx->mode;
+    dev_ctx[num]->freq = ctx->freq;
+    dev_ctx[num]->mute = ctx->mute;
+    dev_ctx[num]->should_run = 0;
+    dev_ctx[num]->dongle = NULL;
+    dev_ctx[num]->demod = NULL;
+    dev_ctx[num]->output = NULL;
+    _radio_dev_init (dev_ctx[num], num);
+
+    return 1;
+}
+
+void _radio_off (unsigned int num) {
+
+    if (num >= _radio_dev_count())
+        return;
+
+    if (dev_ctx[num]) {
+        _radio_dev_free (dev_ctx[num]);
+        free (dev_ctx[num]);
+    }
+    
+    /* free(dev_ctx); */
+}
+
+void _radio_set_mode (unsigned int num, Mode mode) {
+    if (!dev_ctx || !dev_ctx[num])
+        return;
+
+    dev_ctx[num]->mode = mode;
+    _radio_apply_params (dev_ctx[num]);
+}
+
+void _radio_set_freq (unsigned int num, double freq) {
+    if (!dev_ctx || !dev_ctx[num])
+        return;
+
+    dev_ctx[num]->freq = (float)freq;
+    _radio_apply_params (dev_ctx[num]);
+}
+
+void _radio_set_mute (unsigned int num, unsigned char mute) {
+    if (!dev_ctx || !dev_ctx[num])
+        return;
+
+    dev_ctx[num]->mute = mute;
+    _radio_apply_params (dev_ctx[num]);
+}
+
+void _radio_play (unsigned int num) {
+    if (!dev_ctx || !dev_ctx[num])
+        return;
+
+    _radio_start_threads (dev_ctx[num]);
+}
+
+void _radio_stop (unsigned int num) {
+    if (!dev_ctx || !dev_ctx[num])
+        return;
+
+    _radio_stop_threads (dev_ctx[num]);
+}
+
+unsigned int _radio_dev_count () {
+    return rtlsdr_get_device_count();
+}
+
+const char* _radio_dev_name (unsigned int num) {
+    return rtlsdr_get_device_name (num);
+}
+
+
+/* --- LOCAL HELPER FUNCTIONS --- */
+
+unsigned char _radio_dev_init (dev_ctx_T *dev_ctx, unsigned int num) {
+    rtlsdr_dev_t *dev = dev_ctx->dev;
+
+    if (rtlsdr_open (&dev, num) < 0)
+        return 0;
+
+    rtlsdr_set_tuner_gain_mode (dev, 0);
+
+    if (rtlsdr_reset_buffer (dev) < 0)
+        return 0;
+
+    dev_ctx->dev = dev;
+
+    _radio_apply_params (dev_ctx);
+
+    return 1;
+}
+
+unsigned char _radio_dev_free (dev_ctx_T *dev_ctx) {
+    rtlsdr_dev_t *dev = dev_ctx->dev;
+
+    if (rtlsdr_close (dev) < 0)
+        return 0;
+    dev = NULL;
+
+    dev_ctx->dev = dev;
+
+    return 1;
+}
+
+void _radio_apply_params (dev_ctx_T *dev_ctx) {
+    rtlsdr_dev_t *dev = dev_ctx->dev;
+    Mode mode = dev_ctx->mode;
+    float freq = dev_ctx->freq;
+    int rate;
+
+    freq *= 1000000;
+    rate = ((1000000 / 200000) + 1) * 200000;
+
+    if (mode == FM)
+        freq += 16000;
+    freq += rate / 4;
+
+    rtlsdr_set_center_freq (dev, freq);
+    rtlsdr_set_sample_rate (dev, rate);
+
+    dev_ctx->dev = dev;
+}
+
+void _radio_start_threads (dev_ctx_T *dev_ctx) {
+    dev_ctx->dongle = (dongle_ctx*) malloc (sizeof(dongle_ctx));
+    dev_ctx->demod = (demod_ctx*) malloc (sizeof(demod_ctx));
+    dev_ctx->output = (output_ctx*) malloc (sizeof(output_ctx));
+
+    dongle_ctx *dongle = dev_ctx->dongle;
+    demod_ctx *demod = dev_ctx->demod;
+    output_ctx *output = dev_ctx->output;
+
+    pthread_rwlock_init (&demod->lck, NULL);
+    pthread_cond_init (&demod->ok, NULL);
+    pthread_mutex_init (&demod->ok_m, NULL);
+    pthread_rwlock_init (&output->lck, NULL);
+    pthread_cond_init (&output->ok, NULL);
+    pthread_mutex_init (&output->ok_m, NULL);
+
+    dev_ctx->should_run = 1;
+
+     /* dongle thread */
+    dongle->thr_finished = 0;
+    pthread_create (&dongle->thr, NULL, _dongle_thread_fn, (void*)dev_ctx);
+
+     /* demod thread */
+    demod->pre_r = demod->pre_j = 0;
+    demod->now_r = demod->now_j = 0;
+    demod->index = demod->pre_index = demod->now_index = 0;
+    demod->thr_finished = 0;
+    pthread_create (&demod->thr, NULL, _demod_thread_fn, (void*)dev_ctx);
+
+     /* output thread */
+    output->thr_finished = 0;
+    pthread_create (&output->thr, NULL, _output_thread_fn, (void*)dev_ctx);
+}
+
+void _radio_stop_threads (dev_ctx_T *dev_ctx) {
+    rtlsdr_dev_t *dev = dev_ctx->dev;
+    dongle_ctx *dongle = dev_ctx->dongle;
+    demod_ctx *demod = dev_ctx->demod;
+    output_ctx *output = dev_ctx->output;
+
+    if (!dongle || !demod || !output)
+        return;
+
+     /* stop each "while" loop in threads */
+    dev_ctx->should_run = 0;
+
+    rtlsdr_cancel_async (dev);
+    pthread_signal (&demod->ok, &demod->ok_m);
+    pthread_signal (&output->ok, &output->ok_m);
+
+    while (!dongle->thr_finished ||
+           !demod->thr_finished ||
+           !output->thr_finished)
+        usleep (100000);
+
+    pthread_join (dongle->thr, NULL);
+    pthread_join (demod->thr, NULL);
+    pthread_join (output->thr, NULL);
+    pthread_rwlock_destroy (&demod->lck);
+    pthread_cond_destroy (&demod->ok);
+    pthread_mutex_destroy (&demod->ok_m);
+    pthread_rwlock_destroy (&output->lck);
+    pthread_cond_destroy (&output->ok);
+    pthread_mutex_destroy (&output->ok_m);
+
+    free (dongle); dev_ctx->dongle = NULL;
+    free (demod); dev_ctx->demod = NULL;
+    free (output); dev_ctx->output = NULL;
+}
+
+ /* ---- LOCAL THREADED FUNCTIONS ---- */
+
+static void _rtlsdr_callback (unsigned char *buf, uint32_t len, void *ctx) {
+    dev_ctx_T *dev_ctx = (dev_ctx_T *)ctx;
+    dongle_ctx *dongle = dev_ctx->dongle;
+    demod_ctx *demod = dev_ctx->demod;
+    unsigned char tmp;
+    int i;
+
+    if (!dev_ctx->should_run)
+        return;
+
+     /* rotate 90° */
+    for (i = 0; i < (int)len; i += 8) {
+        tmp = 255 - buf[i+3];
+        buf[i+3] = buf[i+2];
+        buf[i+2] = tmp;
+
+        buf[i+4] = 255 - buf[i+4];
+        buf[i+5] = 255 - buf[i+5];
+
+        tmp = 255 - buf[i+6];
+        buf[i+6] = buf[i+7];
+        buf[i+7] = tmp;
+    }
+
+     /* write data */
+    for (i = 0; i < (int)len; i++)
+        dongle->buf[i] = (int16_t)buf[i] - 127;
+
+     /* lock demod thread, write to it, unlock */
+       pthread_rwlock_wrlock (&demod->lck);
+    memcpy (demod->buf, dongle->buf, 2 * len);
+    demod->buf_len = len;
+       pthread_rwlock_unlock (&demod->lck);
+       pthread_signal (&demod->ok, &demod->ok_m);
+}
+ /**/
+static void* _dongle_thread_fn (void *ctx) {
+    dev_ctx_T *dev_ctx = (dev_ctx_T *)ctx;
+    dongle_ctx *dongle = dev_ctx->dongle;
+
+    rtlsdr_read_async (dev_ctx->dev, _rtlsdr_callback, dev_ctx, 0, 0);
+
+    dongle->thr_finished = 1;
+    return 0;
+}
+
+static void _lowpass_demod (void *ctx) {
+    demod_ctx *demod = (demod_ctx *)ctx;
+    int i=0, i2=0;
+
+    while (i < demod->buf_len) {
+        demod->now_r += demod->buf[i];
+        demod->now_j += demod->buf[i+1];
+        i += 2;
+        demod->index++;
+        if (demod->index < ((1000000 / 200000) + 1))
+            continue;
+        demod->buf[i2] = demod->now_r;
+        demod->buf[i2+1] = demod->now_j;
+        demod->index = 0;
+        demod->now_r = demod->now_j = 0;
+        i2 += 2;
+    }
+    demod->buf_len = i2;
+}
+ /**/
+static void _lowpassreal_demod (void *ctx) {
+    demod_ctx *demod = (demod_ctx *)ctx;
+    int i=0, i2=0;
+    int fast = 200000;
+    int slow = 48000;
+
+    while (i < demod->res_len) {
+        demod->now_index += demod->res[i];
+        i++;
+        demod->pre_index += slow;
+        if (demod->pre_index < fast)
+            continue;
+        demod->res[i2] = (int16_t)(demod->now_index / (fast/slow));
+        demod->pre_index -= fast;
+        demod->now_index = 0;
+        i2 += 1;
+    }
+    demod->res_len = i2;
+}
+ /**/
+static void _multiply (int ar, int aj, int br, int bj, int *cr, int *cj) {
+    *cr = ar*br - aj*bj;
+    *cj = aj*br + ar*bj;
+}
+ /**/
+static int _polar_discriminant (int ar, int aj, int br, int bj) {
+    int cr, cj;
+    double angle;
+    _multiply (ar, aj, br, -bj, &cr, &cj);
+    angle = atan2 ((double)cj, (double)cr);
+    return (int)(angle / 3.14159 * (1<<14));
+}
+ /**/
+static void _fm_demod (void *ctx) {
+    demod_ctx *demod = (demod_ctx *)ctx;
+    int16_t *buf = demod->buf;
+    int buf_len = demod->buf_len;
+    int pcm, i;
+
+    pcm = _polar_discriminant (buf[0], buf[1], demod->pre_r, demod->pre_j);
+    demod->res[0] = (int16_t)pcm;
+
+    for (i = 2; i < (buf_len-1); i += 2) {
+        pcm = _polar_discriminant (buf[i], buf[i+1], buf[i-2], buf[i-1]);
+        demod->res[i/2] = (int16_t)pcm;
+    }
+    demod->pre_r = buf[buf_len - 2];
+    demod->pre_j = buf[buf_len - 1];
+    demod->res_len = buf_len/2;
+}
+ /**/
+static void _am_demod (void *ctx) {
+    demod_ctx *demod = (demod_ctx *)ctx;
+    int16_t *buf = demod->buf;
+    int buf_len = demod->buf_len;
+    int pcm, i;
+
+    for (i = 0; i < buf_len; i += 2) {
+        pcm = buf[i] * buf[i];
+        pcm += buf[i+1] * buf[i+1];
+        demod->res[i/2] = (int16_t)sqrt(pcm);
+    }
+    demod->res_len = buf_len/2;
+}
+ /**/
+static void* _demod_thread_fn (void *ctx) {
+    dev_ctx_T *dev_ctx = (dev_ctx_T *)ctx;
+    demod_ctx *demod = dev_ctx->demod;
+    output_ctx *output = dev_ctx->output;
+
+    while(dev_ctx->should_run) {
+            pthread_wait (&demod->ok, &demod->ok_m);
+            pthread_rwlock_wrlock (&demod->lck);
+        _lowpass_demod (demod);
+        if (dev_ctx->mode == FM)
+            _fm_demod (demod);
+        else
+            _am_demod (demod);
+        _lowpassreal_demod (demod);
+           pthread_rwlock_unlock (&demod->lck);
+
+         /* lock demod thread, write to it, unlock */
+           pthread_rwlock_wrlock (&output->lck);
+        memcpy (output->buf, demod->res, 2 * demod->res_len);
+        output->buf_len = demod->res_len;
+           pthread_rwlock_unlock (&output->lck);
+           pthread_signal (&output->ok, &output->ok_m);
+    }
+
+    demod->thr_finished = 1;
+    return 0;
+}
+
+static void* _output_thread_fn (void *ctx) {
+    dev_ctx_T *dev_ctx = (dev_ctx_T *)ctx;
+    output_ctx *output = dev_ctx->output;
+    FILE *file;
+
+    file = fopen (AUDIO_BUFFER, "wb");
+
+    while (dev_ctx->should_run) {
+           pthread_wait (&output->ok, &output->ok_m);
+           pthread_rwlock_rdlock (&output->lck);
+           if (!dev_ctx->mute && file) {
+               fwrite (output->buf, 2, output->buf_len, file);
+               fflush (file);
+               fseek (file, 0, SEEK_SET);
+           }
+           pthread_rwlock_unlock (&output->lck);
+    }
+    if (file) fclose(file);
+    unlink (AUDIO_BUFFER);
+
+    output->thr_finished = 1;
+    return 0;
+}
diff --git a/bindings/radio/radio-rtlsdr.h b/bindings/radio/radio-rtlsdr.h
new file mode 100644
index 00000000..2308f27e
--- /dev/null
+++ b/bindings/radio/radio-rtlsdr.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Manuel Bachmann"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RADIO_RTLSDR_H
+#define RADIO_RTLSDR_H
+
+/* -------------- RADIO RTLSDR DEFINITIONS ------------------ */
+
+#include <math.h>
+#include <pthread.h>
+#include <rtl-sdr.h>
+
+#include "radio-api.h"
+
+#define pthread_signal(n, m) pthread_mutex_lock(m); pthread_cond_signal(n); pthread_mutex_unlock(m)
+#define pthread_wait(n, m) pthread_mutex_lock(m); pthread_cond_wait(n, m); pthread_mutex_unlock(m)
+#define BUF_LEN 16*16384
+#define AUDIO_BUFFER "/tmp/audio_buf"
+
+typedef struct dongle_ctx dongle_ctx;
+typedef struct demod_ctx demod_ctx;
+typedef struct output_ctx output_ctx;
+typedef struct dev_ctx dev_ctx_T;
+
+struct dongle_ctx {
+    pthread_t thr;
+    unsigned char thr_finished;
+    uint16_t buf[BUF_LEN];
+    uint32_t buf_len;
+};
+
+struct demod_ctx {
+    pthread_t thr;
+    unsigned char thr_finished;
+    pthread_rwlock_t lck;
+    pthread_cond_t ok;
+    pthread_mutex_t ok_m;
+    int pre_r, pre_j, now_r, now_j, index;
+    int pre_index, now_index;
+    int16_t buf[BUF_LEN];
+    int buf_len;
+    int16_t res[BUF_LEN];
+    int res_len;
+};
+
+struct output_ctx {
+    pthread_t thr;
+    unsigned char thr_finished;
+    pthread_rwlock_t lck;
+    pthread_cond_t ok;
+    pthread_mutex_t ok_m;
+    int16_t buf[BUF_LEN];
+    int buf_len;
+};
+
+struct dev_ctx {
+    int used;  /* TODO: radio is free ??? */
+    rtlsdr_dev_t* dev;
+    Mode mode;
+    float freq;
+    unsigned char mute;
+    unsigned char should_run;
+     /* thread contexts */
+    dongle_ctx *dongle;
+    demod_ctx *demod;
+    output_ctx *output;
+};
+
+unsigned int _radio_dev_count (void);
+const char* _radio_dev_name (unsigned int);
+
+unsigned char _radio_on (unsigned int, radioCtxHandleT *);
+void _radio_off (unsigned int);
+void _radio_stop (unsigned int);
+void _radio_play (unsigned int);
+void _radio_set_mode (unsigned int, Mode);
+void _radio_set_freq (unsigned int, double);
+void _radio_set_mute (unsigned int, unsigned char);
+
+unsigned char _radio_dev_init (struct dev_ctx *, unsigned int);
+unsigned char _radio_dev_free (struct dev_ctx *);
+void _radio_apply_params (struct dev_ctx *);
+void _radio_start_threads (struct dev_ctx *);
+void _radio_stop_threads (struct dev_ctx *);
+
+#endif /* RADIO_RTLSDR_H */
diff --git a/bindings/samples/AuthLogin.c b/bindings/samples/AuthLogin.c
new file mode 100644
index 00000000..efecf240
--- /dev/null
+++ b/bindings/samples/AuthLogin.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Fulup Ar Foll"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <json-c/json.h>
+
+#include <afb/afb-plugin.h>
+
+// Dummy sample of Client Application Context
+typedef struct {
+  int  something;       
+  void *whateveryouwant;
+} MyClientApplicationHandle;
+
+
+// This function is call when Client Session Context is removed
+// Note: when freeCtxCB==NULL standard free/malloc is called
+static void clientContextFree(void *context) {
+    fprintf (stderr,"Plugin[token] Closing Session\n");
+    free (context);
+}
+
+// Request Creation of new context if it does not exist
+static void clientContextConnect (struct afb_req request)
+{
+    json_object *jresp;
+
+    // add an application specific client context to session
+    afb_req_context_set(request, malloc (sizeof (MyClientApplicationHandle)), clientContextFree);
+
+    // do something intelligent to check if we should or not update level of assurance from 0(anonymous) to 1(logged)
+    afb_req_session_set_LOA(request, 1);
+    
+    // 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"));
+
+    afb_req_success(request, jresp, NULL);
+    
+}
+
+// Before entering here token will be check and renew
+static void clientContextRefresh (struct afb_req request) {
+    json_object *jresp;
+
+  
+    jresp = json_object_new_object();
+    json_object_object_add(jresp, "token", json_object_new_string ("Token was refreshed"));              
+    
+    afb_req_success(request, jresp, NULL);
+}
+
+
+// Session token will we verified before entering here
+static void clientContextCheck (struct afb_req request) {
+    
+    json_object *jresp = json_object_new_object();    
+    json_object_object_add(jresp, "isvalid", json_object_new_boolean (TRUE));       
+        
+    afb_req_success(request, jresp, NULL);
+}
+
+
+// Close and Free context
+static void clientContextLogout (struct afb_req request) {
+    json_object *jresp;
+   
+    /* after this call token will be reset
+     *  - no further access to API will be possible 
+     *  - every context from any used plugin will be freed
+     */
+    
+    jresp = json_object_new_object();
+    json_object_object_add(jresp, "info", json_object_new_string ("Token and all resources are released"));
+    
+    // WARNING: if you free context resource manually here do not forget to set *request.context=NULL; 
+    afb_req_success(request, jresp, NULL);
+    
+    afb_req_session_set_LOA(request, 0);
+}
+// Close and Free context
+static void clientGetPing (struct afb_req request) {
+    static int count=0;
+    json_object *jresp;
+
+    jresp = json_object_new_object();
+    json_object_object_add(jresp, "count", json_object_new_int (count ++));
+    
+    afb_req_success(request, jresp, NULL);
+}
+
+
+static const struct AFB_verb_desc_v1 verbs[]= {
+  {"ping"    , AFB_SESSION_NONE                        , clientGetPing       ,"Ping Rest Test Service"},
+  {"connect" , AFB_SESSION_LOA_EQ_0 | AFB_SESSION_RENEW, clientContextConnect,"Connect/Login Client"},
+  {"refresh" , AFB_SESSION_LOA_GE_1 | AFB_SESSION_RENEW, clientContextRefresh,"Refresh Client Authentication Token"},
+  {"check"   , AFB_SESSION_LOA_GE_1                    , clientContextCheck  ,"Check Client Authentication Token"},
+  {"logout"  , AFB_SESSION_LOA_GE_1 | AFB_SESSION_CLOSE, clientContextLogout ,"Logout Client and Free resources"},
+  {NULL}
+};
+
+static const struct AFB_plugin plugin_desc = {
+	.type = AFB_PLUGIN_VERSION_1,
+	.v1 = {
+		.info = "Application Framework Binder Authentication sample",
+		.prefix = "auth",
+		.verbs = verbs
+	}
+};
+
+const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
+{
+	return &plugin_desc;
+}
diff --git a/bindings/samples/CMakeLists.txt b/bindings/samples/CMakeLists.txt
new file mode 100644
index 00000000..59a9a449
--- /dev/null
+++ b/bindings/samples/CMakeLists.txt
@@ -0,0 +1,63 @@
+
+INCLUDE_DIRECTORIES(${include_dirs})
+
+##################################################
+# AuthLogin
+##################################################
+ADD_LIBRARY(authLogin MODULE AuthLogin.c)
+SET_TARGET_PROPERTIES(authLogin PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
+)
+TARGET_LINK_LIBRARIES(authLogin ${link_libraries})
+INSTALL(TARGETS authLogin
+        LIBRARY DESTINATION ${binding_install_dir})
+
+##################################################
+# DemoContext
+##################################################
+ADD_LIBRARY(demoContext MODULE DemoContext.c)
+SET_TARGET_PROPERTIES(demoContext PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
+)
+TARGET_LINK_LIBRARIES(demoContext ${link_libraries})
+INSTALL(TARGETS demoContext
+        LIBRARY DESTINATION ${binding_install_dir})
+
+##################################################
+# DemoPost
+##################################################
+ADD_LIBRARY(demoPost MODULE DemoPost.c)
+SET_TARGET_PROPERTIES(demoPost PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
+)
+TARGET_LINK_LIBRARIES(demoPost ${link_libraries})
+INSTALL(TARGETS demoPost
+        LIBRARY DESTINATION ${binding_install_dir})
+
+##################################################
+# HelloWorld
+##################################################
+ADD_LIBRARY(helloWorld MODULE HelloWorld.c)
+SET_TARGET_PROPERTIES(helloWorld PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
+)
+TARGET_LINK_LIBRARIES(helloWorld ${link_libraries})
+INSTALL(TARGETS helloWorld
+        LIBRARY DESTINATION ${binding_install_dir})
+
+##################################################
+# tic-tac-toe
+##################################################
+ADD_LIBRARY(tic-tac-toe MODULE tic-tac-toe.c)
+SET_TARGET_PROPERTIES(tic-tac-toe PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
+)
+TARGET_LINK_LIBRARIES(tic-tac-toe ${link_libraries})
+INSTALL(TARGETS tic-tac-toe
+        LIBRARY DESTINATION ${binding_install_dir})
+
diff --git a/bindings/samples/DemoContext.c b/bindings/samples/DemoContext.c
new file mode 100644
index 00000000..ef703759
--- /dev/null
+++ b/bindings/samples/DemoContext.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Fulup Ar Foll"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <json-c/json.h>
+
+#include <afb/afb-plugin.h>
+
+typedef struct {
+  /* 
+   * client context is attached a session but private to a each plugin.
+   * Context is passed to each API under request->context
+   * 
+   * Note:
+   *  -client context is free when a session is closed. Developer should not
+   *   forget that even if context is private to each plugin, session is unique
+   *   to a client. When session close, every plugin are notified to free there
+   *   private context.
+   *  -by default standard "free" function from libc is used to free context.
+   *   Developer may define it own under plugin->freeCB. This call received
+   *   FreeCtxCb(void *ClientCtx, void*PluginHandle, char*SessionUUID) if
+   *   FreeCtxCb=(void*)-1 then context wont be free by session manager.
+   *  -when an API use AFB_SESSION_RESET this close the session and each plugin
+   *   will be notified to free ressources.
+   */
+    
+  int  count;
+  char *abcd;
+  
+} MyClientContextT;
+
+// This function is call at session open time. Any client trying to 
+// call it with an already open session will be denied.
+// Ex: http://localhost:1234/api/context/create?token=123456789
+static void myCreate (struct afb_req request)
+{
+    MyClientContextT *ctx = malloc (sizeof (MyClientContextT));
+
+    // store something in our plugin private client context
+    ctx->count = 0;
+    ctx->abcd  = "SomeThingUseful";        
+
+    afb_req_context_set(request, ctx, free);
+    afb_req_success_f(request, NULL, "SUCCESS: create client context for plugin [%s]", ctx->abcd);
+}
+
+// This function can only be called with a valid token. Token should be renew before
+// session timeout a standard renew api is avaliable at /api/token/renew this API
+// can be called automatically with <token-renew> HTML5 widget.
+// ex: http://localhost:1234/api/context/action?token=xxxxxx-xxxxxx-xxxxx-xxxxx-xxxxxx
+static void myAction (struct afb_req request)
+{
+    MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request);
+    
+    // store something in our plugin private client context
+    ctx->count++;
+    afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Check=[%d]\n", ctx->abcd, ctx->count);
+}
+
+// After execution of this function, client session will be close and if they
+// created a context [request->context != NULL] every plugins will be notified
+// that they should free context resources.
+// ex: http://localhost:1234/api/context/close?token=xxxxxx-xxxxxx-xxxxx-xxxxx-xxxxxx
+static void myClose (struct afb_req request)
+{
+    MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request);
+    
+    // store something in our plugin private client context
+    ctx->count++;
+    afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Close=[%d]\n", ctx->abcd, ctx->count);
+}
+
+// Set the LOA
+static void setLOA(struct afb_req request, unsigned loa)
+{
+    if (afb_req_session_set_LOA(request, loa))
+	afb_req_success_f(request, NULL, "loa set to %u", loa);
+    else
+	afb_req_fail_f(request, "failed", "can't set loa to %u", loa);
+}
+
+static void clientSetLOA0(struct afb_req request)
+{
+    setLOA(request, 0);
+}
+
+static void clientSetLOA1(struct afb_req request)
+{
+    setLOA(request, 1);
+}
+
+static void clientSetLOA2(struct afb_req request)
+{
+    setLOA(request, 2);
+}
+
+static void clientSetLOA3(struct afb_req request)
+{
+    setLOA(request, 3);
+}
+
+static void clientCheckLOA(struct afb_req request)
+{
+    afb_req_success(request, NULL, "LOA checked and okay");
+}
+
+// NOTE: this sample does not use session to keep test a basic as possible
+//       in real application most APIs should be protected with AFB_SESSION_CHECK
+static const struct AFB_verb_desc_v1 verbs[]= {
+  {"create", AFB_SESSION_CREATE, myCreate  , "Create a new session"},
+  {"action", AFB_SESSION_CHECK , myAction  , "Use Session Context"},
+  {"close" , AFB_SESSION_CLOSE , myClose   , "Free Context"},
+  {"set_loa_0", AFB_SESSION_RENEW, clientSetLOA0       ,"Set level of assurance to 0"},
+  {"set_loa_1", AFB_SESSION_RENEW, clientSetLOA1       ,"Set level of assurance to 1"},
+  {"set_loa_2", AFB_SESSION_RENEW, clientSetLOA2       ,"Set level of assurance to 2"},
+  {"set_loa_3", AFB_SESSION_RENEW, clientSetLOA3       ,"Set level of assurance to 3"},
+  {"check_loa_ge_0", AFB_SESSION_LOA_GE_0, clientCheckLOA ,"Check whether level of assurance is greater or equal to 0"},
+  {"check_loa_ge_1", AFB_SESSION_LOA_GE_1, clientCheckLOA ,"Check whether level of assurance is greater or equal to 1"},
+  {"check_loa_ge_2", AFB_SESSION_LOA_GE_2, clientCheckLOA ,"Check whether level of assurance is greater or equal to 2"},
+  {"check_loa_ge_3", AFB_SESSION_LOA_GE_3, clientCheckLOA ,"Check whether level of assurance is greater or equal to 3"},
+  {"check_loa_le_0", AFB_SESSION_LOA_LE_0, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 0"},
+  {"check_loa_le_1", AFB_SESSION_LOA_LE_1, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 1"},
+  {"check_loa_le_2", AFB_SESSION_LOA_LE_2, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 2"},
+  {"check_loa_le_3", AFB_SESSION_LOA_LE_3, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 3"},
+  {"check_loa_eq_0", AFB_SESSION_LOA_EQ_0, clientCheckLOA ,"Check whether level of assurance is equal to 0"},
+  {"check_loa_eq_1", AFB_SESSION_LOA_EQ_1, clientCheckLOA ,"Check whether level of assurance is equal to 1"},
+  {"check_loa_eq_2", AFB_SESSION_LOA_EQ_2, clientCheckLOA ,"Check whether level of assurance is equal to 2"},
+  {"check_loa_eq_3", AFB_SESSION_LOA_EQ_3, clientCheckLOA ,"Check whether level of assurance is equal to 3"},
+  {NULL}
+};
+
+static const struct AFB_plugin plugin_desc = {
+	.type = AFB_PLUGIN_VERSION_1,
+	.v1 = {
+		.info = "Sample of Client Context Usage",
+		.prefix = "context",
+		.verbs = verbs,
+	}
+};
+
+const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
+{
+	return &plugin_desc;
+}
+
diff --git a/bindings/samples/DemoPost.c b/bindings/samples/DemoPost.c
new file mode 100644
index 00000000..b61b91c4
--- /dev/null
+++ b/bindings/samples/DemoPost.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Fulup Ar Foll"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <json-c/json.h>
+
+#include <afb/afb-plugin.h>
+
+
+// Sample Generic Ping Debug API
+static void getPingTest(struct afb_req request)
+{
+    static int pingcount = 0;
+    json_object *query = afb_req_json(request);
+
+    afb_req_success_f(request, query, "Ping Binder Daemon count=%d", ++pingcount);
+}
+
+// With content-type=json data are directly avaliable in request->post->data
+static void GetJsonByPost (struct afb_req request)
+{
+    struct afb_arg arg;
+    json_object* jresp;
+    json_object *query = afb_req_json(request);
+
+    arg = afb_req_get(request, "");
+    jresp = arg.value ? json_tokener_parse(arg.value) : NULL;
+    afb_req_success_f(request, jresp, "GetJsonByPost query={%s}", json_object_to_json_string(query));
+}
+
+// Upload a file and execute a function when upload is done
+static void Uploads (struct afb_req request, const char *destination)
+{
+   struct afb_arg a = afb_req_get(request, "file");
+   if (a.value == NULL || *a.value == 0)
+     afb_req_fail(request, "failed", "no file selected");
+   else
+     afb_req_success_f(request, NULL, "uploaded file %s of path %s for destination %s", a.value, a.path, destination);
+}
+
+// Upload a file and execute a function when upload is done
+static void UploadAppli (struct afb_req request)
+{
+    Uploads(request, "applications");
+}
+
+// Simples Upload case just upload a file
+static void UploadMusic (struct afb_req request)
+{
+    Uploads(request, "musics");
+}
+
+// PostForm callback is called multiple times (one or each key within form, or once per file buffer)
+// When file has been fully uploaded call is call with item==NULL 
+static void UploadImage (struct afb_req request)
+{
+    Uploads(request, "images");
+}
+
+
+// NOTE: this sample does not use session to keep test a basic as possible
+//       in real application upload-xxx should be protected with AFB_SESSION_CHECK
+static const struct AFB_verb_desc_v1 verbs[]= {
+  {"ping"         , AFB_SESSION_NONE  , getPingTest    ,"Ping Rest Test Service"},
+  {"upload-json"  , AFB_SESSION_NONE  , GetJsonByPost  ,"Demo for Json Buffer on Post"},
+  {"upload-image" , AFB_SESSION_NONE  , UploadImage    ,"Demo for file upload"},
+  {"upload-music" , AFB_SESSION_NONE  , UploadMusic    ,"Demo for file upload"},
+  {"upload-appli" , AFB_SESSION_NONE  , UploadAppli    ,"Demo for file upload"},
+  {NULL}
+};
+
+static const struct AFB_plugin plugin_desc = {
+	.type = AFB_PLUGIN_VERSION_1,
+	.v1 = {
+		.info = "Sample with Post Upload Files",
+		.prefix = "post",
+		.verbs = verbs
+	}
+};
+
+const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
+{
+    return &plugin_desc;
+};
diff --git a/bindings/samples/HelloWorld.c b/bindings/samples/HelloWorld.c
new file mode 100644
index 00000000..b6f49b78
--- /dev/null
+++ b/bindings/samples/HelloWorld.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2015, 2016 "IoT.bzh"
+ * Author "Fulup Ar Foll"
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <json-c/json.h>
+
+#include <afb/afb-plugin.h>
+
+const struct AFB_interface *interface;
+
+struct event
+{
+	struct event *next;
+	struct afb_event event;
+	char tag[1];
+};
+
+static struct event *events = 0;
+
+/* searchs the event of tag */
+static struct event *event_get(const char *tag)
+{
+	struct event *e = events;
+	while(e && strcmp(e->tag, tag))
+		e = e->next;
+	return e;
+}
+
+/* deletes the event of tag */
+static int event_del(const char *tag)
+{
+	struct event *e, **p;
+
+	/* check exists */
+	e = event_get(tag);
+	if (!e) return -1;
+
+	/* unlink */
+	p = &events;
+	while(*p != e) p = &(*p)->next;
+	*p = e->next;
+
+	/* destroys */
+	afb_event_drop(e->event);
+	free(e);
+	return 0;
+}
+
+/* creates the event of tag */
+static int event_add(const char *tag, const char *name)
+{
+	struct event *e;
+
+	/* check valid tag */
+	e = event_get(tag);
+	if (e) return -1;
+
+	/* creation */
+	e = malloc(strlen(tag) + sizeof *e);
+	if (!e) return -1;
+	strcpy(e->tag, tag);
+
+	/* make the event */
+	e->event = afb_daemon_make_event(interface->daemon, name);
+	if (!e->event.closure) { free(e); return -1; }
+
+	/* link */
+	e->next = events;
+	events = e;
+	return 0;
+}
+
+static int event_subscribe(struct afb_req request, const char *tag)
+{
+	struct event *e;
+	e = event_get(tag);
+	return e ? afb_req_subscribe(request, e->event) : -1;
+}
+
+static int event_unsubscribe(struct afb_req request, const char *tag)
+{
+	struct event *e;
+	e = event_get(tag);
+	return e ? afb_req_unsubscribe(request, e->event) : -1;
+}
+
+static int event_push(struct json_object *args, const char *tag)
+{
+	struct event *e;
+	e = event_get(tag);
+	return e ? afb_event_push(e->event, json_object_get(args)) : -1;
+}
+
+// Sample Generic Ping Debug API
+static void ping(struct afb_req request, json_object *jresp, const char *tag)
+{
+	static int pingcount = 0;
+	json_object *query = afb_req_json(request);
+	afb_req_success_f(request, jresp, "Ping Binder Daemon tag=%s count=%d query=%s", tag, ++pingcount, json_object_to_json_string(query));
+}
+
+static void pingSample (struct afb_req request)
+{
+	ping(request, json_object_new_string ("Some String"), "pingSample");
+}
+
+static void pingFail (struct afb_req request)
+{
+	afb_req_fail(request, "failed", "Ping Binder Daemon fails");
+}
+
+static void pingNull (struct afb_req request)
+{
+	ping(request, NULL, "pingNull");
+}
+
+static void pingBug (struct afb_req request)
+{
+	ping((struct afb_req){NULL,NULL,NULL}, NULL, "pingBug");
+}
+
+static void pingEvent(struct afb_req request)
+{
+	json_object *query = afb_req_json(request);
+	afb_daemon_broadcast_event(interface->daemon, "event", json_object_get(query));
+	ping(request, json_object_get(query), "event");
+}
+
+
+// For samples https://linuxprograms.wordpress.com/2010/05/20/json-c-libjson-tutorial/
+static void pingJson (struct afb_req request) {
+    json_object *jresp, *embed;    
+    
+    jresp = json_object_new_object();
+    json_object_object_add(jresp, "myString", json_object_new_string ("Some String"));
+    json_object_object_add(jresp, "myInt", json_object_new_int (1234));
+     
+    embed  = json_object_new_object();
+    json_object_object_add(embed, "subObjString", json_object_new_string ("Some String"));
+    json_object_object_add(embed, "subObjInt", json_object_new_int (5678));
+    
+    json_object_object_add(jresp,"eobj", embed);
+
+    ping(request, jresp, "pingJson");
+}
+
+static void subcallcb (void *prequest, int iserror, json_object *object)
+{
+	struct afb_req request = afb_req_unstore(prequest);
+	if (iserror)
+		afb_req_fail(request, "failed", json_object_to_json_string(object));
+	else
+		afb_req_success(request, object, NULL);
+	afb_req_unref(request);
+}
+
+static void subcall (struct afb_req request)
+{
+	const char *api = afb_req_value(request, "api");
+	const char *verb = afb_req_value(request, "verb");
+	const char *args = afb_req_value(request, "args");
+	json_object *object = api && verb && args ? json_tokener_parse(args) : NULL;
+
+	if (object == NULL)
+		afb_req_fail(request, "failed", "bad arguments");
+	else
+		afb_req_subcall(request, api, verb, object, subcallcb, afb_req_store(request));
+}
+
+static void eventadd (struct afb_req request)
+{
+	const char *tag = afb_req_value(request, "tag");
+	const char *name = afb_req_value(request, "name");
+
+	if (tag == NULL || name == NULL)
+		afb_req_fail(request, "failed", "bad arguments");
+	else if (0 != event_add(tag, name))
+		afb_req_fail(request, "failed", "creation error");
+	else
+		afb_req_success(request, NULL, NULL);
+}
+
+static void eventdel (struct afb_req request)
+{
+	const char *tag = afb_req_value(request, "tag");
+
+	if (tag == NULL)
+		afb_req_fail(request, "failed", "bad arguments");
+	else if (0 != event_del(tag))
+		afb_req_fail(request, "failed", "deletion error");
+	else
+		afb_req_success(request, NULL, NULL);
+}
+
+static void eventsub (struct afb_req request)
+{
+	const char *tag = afb_req_value(request, "tag");
+
+	if (tag == NULL)
+		afb_req_fail(request, "failed", "bad arguments");
+	else if (0 != event_subscribe(request, tag))
+		afb_req_fail(request, "failed", "subscription error");
+	else
+		afb_req_success(request, NULL, NULL);
+}
+
+static void eventunsub (struct afb_req request)
+{
+	const char *tag = afb_req_value(request, "tag");
+
+	if (tag == NULL)
+		afb_req_fail(request, "failed", "bad arguments");
+	else if (0 != event_unsubscribe(request, tag))
+		afb_req_fail(request, "failed", "unsubscription error");
+	else
+		afb_req_success(request, NULL, NULL);
+}
+
+static void eventpush (struct afb_req request)
+{
+	const char *tag = afb_req_value(request, "tag");
+	const char *data = afb_req_value(request, "data");
+	json_object *object = data ? json_tokener_parse(data) : NULL;
+
+	if (tag == NULL)
+		afb_req_fail(request, "failed", "bad arguments");
+	else if (0 > event_push(object, tag))
+		afb_req_fail(request, "failed", "push error");
+	else
+		afb_req_success(request, NULL, NULL);
+}
+
+// NOTE: this sample does not use session to keep test a basic as possible
+//       in real application most APIs should be protected with AFB_SESSION_CHECK
+static const struct AFB_verb_desc_v1 verbs[]= {
+  {"ping"     , AFB_SESSION_NONE, pingSample  , "Ping Application Framework"},
+  {"pingfail" , AFB_SESSION_NONE, pingFail    , "Fails"},
+  {"pingnull" , AFB_SESSION_NONE, pingNull    , "Return NULL"},
+  {"pingbug"  , AFB_SESSION_NONE, pingBug     , "Do a Memory Violation"},
+  {"pingJson" , AFB_SESSION_NONE, pingJson    , "Return a JSON object"},
+  {"pingevent", AFB_SESSION_NONE, pingEvent   , "Send an event"},
+  {"subcall",   AFB_SESSION_NONE, subcall     , "Call api/verb(args)"},
+  {"eventadd",  AFB_SESSION_NONE, eventadd    , "adds the event of 'name' for the 'tag'"},
+  {"eventdel",  AFB_SESSION_NONE, eventdel    , "deletes the event of 'tag'"},
+  {"eventsub",  AFB_SESSION_NONE, eventsub    , "subscribes to the event of 'tag'"},
+  {"eventunsub",AFB_SESSION_NONE, eventunsub  , "unsubscribes to the event of 'tag'"},
+  {"eventpush", AFB_SESSION_NONE, eventpush   , "pushs the event of 'tag' with the 'data'"},
+  {NULL}
+};
+
+static const struct AFB_plugin plugin_desc = {
+	.type = AFB_PLUGIN_VERSION_1,
+	.v1 = {
+		.info = "Minimal Hello World Sample",
+		.prefix = "hello",
+		.verbs = verbs
+	}
+};
+
+const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
+{
+	interface = itf;
+	return &plugin_desc;
+}
diff --git a/bindings/samples/export.map b/bindings/samples/export.map
new file mode 100644
index 00000000..0ef1ac79
--- /dev/null
+++ b/bindings/samples/export.map
@@ -0,0 +1 @@
+{ global: afbBindingV1Register; local: *; };
diff --git a/bindings/samples/tic-tac-toe.c b/bindings/samples/tic-tac-toe.c
new file mode 100644
index 00000000..0100fc05
--- /dev/null
+++ b/bindings/samples/tic-tac-toe.c
@@ -0,0 +1,605 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <json-c/json.h>
+
+#include <afb/afb-binding.h>
+
+/*
+ * the interface to afb-daemon
+ */
+const struct afb_binding_interface *afbitf;
+
+/*
+ * definition of waiters
+ */
+struct waiter
+{
+	struct waiter *next;
+	struct afb_req req;
+};
+
+/*
+ * definition of a board
+ */
+struct board
+{
+	struct board *next;
+	int use_count;
+	int moves;
+	int history[9];
+	int id;
+	int level;
+	char board[9];
+	struct waiter *waiters;
+};
+
+/*
+ * list of boards
+ */
+static struct board *all_boards;
+
+/*
+ * Searchs a board having the 'id'.
+ * Returns it if found or NULL otherwise.
+ */
+static struct board *search_board(int id)
+{
+	struct board *board = all_boards;
+	while (board != NULL && board->id != id)
+		board = board->next;
+	return board;
+}
+
+/*
+ * Creates a new board and returns it.
+ */
+static struct board *get_new_board()
+{
+	/* allocation */
+	struct board *board = calloc(1, sizeof *board);
+
+	/* initialisation */
+	memset(board->board, ' ', sizeof board->board);
+	board->use_count = 1;
+	board->level = 1;
+	board->moves = 0;
+	do {
+		board->id = (rand() >> 2) % 1000;
+	} while(board->id == 0 || search_board(board->id) != NULL);
+
+	/* link */
+	board->next = all_boards;
+	all_boards = board;
+	return board;
+}
+
+/*
+ * Release a board
+ */
+static void release_board(struct board *board)
+{
+	/* decrease the reference count ... */
+	if (--board->use_count == 0) {
+		/* ... no more use */
+		/* unlink from the list of boards */
+		struct board **prv = &all_boards;
+		while (*prv != NULL && *prv != board)
+			prv = &(*prv)->next;
+		if (*prv != NULL)
+			*prv = board->next;
+		/* release the used memory */
+		free(board);
+	}
+}
+
+/*
+ * Checks who wins
+ * Returns zero if there is no winner
+ * Returns the char of the winner if a player won
+ */
+static char winner(const char b[9])
+{
+	int i;
+	char c;
+
+	/* check diagonals */
+	c = b[4];
+	if (c != ' ') {
+		if (b[0] == c && b[8] == c)
+			return c;
+		if (b[2] == c && b[6] == c)
+			return c;
+	}
+
+	/* check lines */
+	for (i = 0 ; i <= 6 ; i += 3) {
+		c = b[i];
+		if (c != ' ' && b[i+1] == c && b[i+2] == c)
+			return c;
+	}
+
+	/* check columns */
+	for (i = 0 ; i <= 2 ; i++) {
+		c = b[i];
+		if (c != ' ' && b[i+3] == c && b[i+6] == c)
+			return c;
+	}
+
+	return 0;
+}
+
+/* get the color (X or 0) of the move of index 'move' */
+static char color(int move)
+{
+	return (move & 1) == 0 ? 'X' : '0';
+}
+
+/* adds the move to the board */
+static void add_move(struct board *board, int index)
+{
+	int imove = board->moves++;
+	board->history[imove] = index;
+	board->board[index] = color(imove);
+}
+
+/* get a random possible move index from the board described by 'b' */
+static int get_random_move(char b[9])
+{
+	int index = rand() % 9;
+	while (b[index] != ' ')
+		index = (index + 1) % 9;
+	return index;
+}
+
+/*
+ * Scores the position described by 'b'
+ * for the player of color 'c' using an analysis of 'depth'.
+ * Returns 1 if player 'c' will win.
+ * Returns -1 if opponent of player 'c' will win.
+ * returns 0 otherwise.
+ */
+static int score_position(char b[9], char c, int depth)
+{
+	int i, t, r;
+
+	/* check if winner */
+	if (winner(b) == c)
+		return 1;
+
+	/* when depth of analysis is reached return unknown case */
+	if (--depth == 0)
+		return 0;
+
+	/* switch to the opponent */
+	c = (char)('O' + 'X' - c);
+
+	/* inspect opponent moves */
+	r = 1;
+	for (i = 0 ; i < 9 ; i++) {
+		if (b[i] == ' ') {
+			b[i] = c;
+			t = score_position(b, c, depth);
+			b[i] = ' ';
+			if (t > 0)
+				return -1; /* opponent will win */
+
+			if (t == 0)
+				r = 0; /* something not clear */
+		}
+	}
+	return r;
+}
+
+/* get one move: return the computed index of the move */
+static int get_move(struct board *board)
+{
+	int index, depth, t, f;
+	char c;
+	char b[9];
+
+	/* compute the depth */
+	depth = board->level - 1;
+	if (board->moves + depth > 9)
+		depth = 9 - board->moves;
+
+	/* case of null depth */
+	if (depth == 0)
+		return get_random_move(board->board);
+
+	/* depth and more */
+	memcpy(b, board->board, 9);
+	c = color(board->moves);
+	f = 0;
+	for (index = 0 ; index < 9 ; index++) {
+		if (board->board[index] == ' ') {
+			board->board[index] = c;
+			t = score_position(board->board, c, depth);
+			board->board[index] = ' ';
+			if (t > 0)
+				return index;
+			if (t < 0)
+				b[index] = '+';
+			else
+				f = 1;
+		}
+	}
+	return get_random_move(f ? b : board->board);
+}
+
+/*
+ * get the board description
+ */
+static struct json_object *describe(struct board *board)
+{
+	int i;
+	char w;
+	struct json_object *resu, *arr;
+
+	resu = json_object_new_object();
+
+	json_object_object_add(resu, "boardid", json_object_new_int(board->id));
+	json_object_object_add(resu, "level", json_object_new_int(board->level));
+
+	arr = json_object_new_array();
+	json_object_object_add(resu, "board", arr);
+	for (i = 0 ; i < 9 ; i++)
+		json_object_array_add(arr,
+				json_object_new_string_len(&board->board[i], 1));
+
+	arr = json_object_new_array();
+	json_object_object_add(resu, "history", arr);
+	for (i = 0 ; i < board->moves ; i++)
+		json_object_array_add(arr, json_object_new_int(board->history[i]));
+
+	w = winner(board->board);
+	if (w)
+		json_object_object_add(resu, "winner", json_object_new_string_len(&w, 1));
+	else if (board->moves == 9)
+		json_object_object_add(resu, "winner", json_object_new_string("none"));
+
+	return resu;
+}
+
+/*
+ * signals a change of the board
+ */
+static void changed(struct board *board, const char *reason)
+{
+	struct waiter *waiter, *next;
+	struct json_object *description;
+
+	/* get the description */
+	description = describe(board);
+
+	waiter = board->waiters;
+	board->waiters = NULL;
+	while (waiter != NULL) {
+		next = waiter->next;
+		afb_req_success(waiter->req, json_object_get(description), reason);
+		afb_req_unref(waiter->req);
+		free(waiter);
+		waiter = next;
+	}
+
+	afb_daemon_broadcast_event(afbitf->daemon, reason, description);
+}
+
+/*
+ * retrieves the board of the request
+ */
+static inline struct board *board_of_req(struct afb_req req)
+{
+	return afb_req_context(req, (void*)get_new_board, (void*)release_board);
+}
+
+/*
+ * start a new game
+ */
+static void new(struct afb_req req)
+{
+	struct board *board;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'new' called for boardid %d", board->id);
+
+	/* reset the game */
+	memset(board->board, ' ', sizeof board->board);
+	board->moves = 0;
+
+	/* replies */
+	afb_req_success(req, NULL, NULL);
+
+	/* signal change */
+	changed(board, "new");
+}
+
+/*
+ * get the board
+ */
+static void board(struct afb_req req)
+{
+	struct board *board;
+	struct json_object *description;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'board' called for boardid %d", board->id);
+
+	/* describe the board */
+	description = describe(board);
+
+	/* send the board's description */
+	afb_req_success(req, description, NULL);
+}
+
+/*
+ * move a piece
+ */
+static void move(struct afb_req req)
+{
+	struct board *board;
+	int i;
+	const char *index;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'move' called for boardid %d", board->id);
+
+	/* retrieves the arguments of the move */
+	index = afb_req_value(req, "index");
+	i = index == NULL ? -1 : atoi(index);
+
+	/* checks validity of arguments */
+	if (i < 0 || i > 8) {
+		WARNING(afbitf, "can't move to %s: %s", index?:"?", index?"wrong value":"not set");
+		afb_req_fail(req, "error", "bad request");
+		return;
+	}
+
+	/* checks validity of the state */
+	if (winner(board->board) != 0) {
+		WARNING(afbitf, "can't move to %s: game is terminated", index);
+		afb_req_fail(req, "error", "game terminated");
+		return;
+	}
+
+	/* checks validity of the move */
+	if (board->board[i] != ' ') {
+		WARNING(afbitf, "can't move to %s: room occupied", index);
+		afb_req_fail(req, "error", "occupied");
+		return;
+	}
+
+	/* applies the move */
+	INFO(afbitf, "method 'move' for boardid %d, index=%s", board->id, index);
+	add_move(board, i);
+
+	/* replies */
+	afb_req_success(req, NULL, NULL);
+
+	/* signals change */
+	changed(board, "move");
+}
+
+/*
+ * set the level
+ */
+static void level(struct afb_req req)
+{
+	struct board *board;
+	int l;
+	const char *level;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'level' called for boardid %d", board->id);
+
+	/* retrieves the arguments */
+	level = afb_req_value(req, "level");
+	l = level == NULL ? -1 : atoi(level);
+
+	/* check validity of arguments */
+	if (l < 1 || l > 10) {
+		WARNING(afbitf, "can't set level to %s: %s", level?:"?", level?"wrong value":"not set");
+		afb_req_fail(req, "error", "bad request");
+		return;
+	}
+
+	/* set the level */
+	INFO(afbitf, "method 'level' for boardid %d, level=%d", board->id, l);
+	board->level = l;
+
+	/* replies */
+	afb_req_success(req, NULL, NULL);
+
+	/* signals change */
+	changed(board, "level");
+}
+
+/*
+ * Join a board
+ */
+static void join(struct afb_req req)
+{
+	struct board *board, *new_board;
+	const char *id;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'join' called for boardid %d", board->id);
+
+	/* retrieves the arguments */
+	id = afb_req_value(req, "boardid");
+	if (id == NULL)
+		goto bad_request;
+
+	/* none is a special id for joining a new session */
+	if (strcmp(id, "none") == 0) {
+		new_board = get_new_board();
+		goto success;
+	}
+
+	/* searchs the board to join */
+	new_board = search_board(atoi(id));
+	if (new_board == NULL)
+		goto bad_request;
+
+	/*
+	 * joining its board is stupid but possible
+	 * however when called with the same stored pointer
+	 * afb_req_context_set will not call the release
+	 * function 'release_board'. So the use_count MUST not
+	 * be incremented.
+	 */
+	if (new_board != board)
+		new_board->use_count++;
+
+success:
+	/* set the new board (and leaves the previous one) */
+	afb_req_context_set(req, new_board, (void*)release_board);
+
+	/* replies */
+	afb_req_success(req, NULL, NULL);
+	return;
+
+bad_request:
+	WARNING(afbitf, "can't join boardid %s: %s", id ? : "?", !id ? "no boardid" : atoi(id) ? "not found" : "bad boardid");
+	afb_req_fail(req, "error", "bad request");
+	return;
+}
+
+/*
+ * Undo the last move
+ */
+static void undo(struct afb_req req)
+{
+	struct board *board;
+	int i;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'undo' called for boardid %d", board->id);
+
+	/* checks the state */
+	if (board->moves == 0) {
+		WARNING(afbitf, "can't undo");
+		afb_req_fail(req, "error", "bad request");
+		return;
+	}
+
+	/* undo the last move */
+	i = board->history[--board->moves];
+	board->board[i] = ' ';
+
+	/* replies */
+	afb_req_success(req, NULL, NULL);
+
+	/* signals change */
+	changed(board, "undo");
+}
+
+/*
+ * computer plays
+ */
+static void play(struct afb_req req)
+{
+	struct board *board;
+	int index;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'play' called for boardid %d", board->id);
+
+	/* checks validity of the state */
+	if (winner(board->board) != 0 || board->moves == 9) {
+		WARNING(afbitf, "can't play: game terminated (%s)", winner(board->board) ? "has winner" : "no room left");
+		afb_req_fail(req, "error", "game terminated");
+		return;
+	}
+
+	/* gets the move and plays it */
+	index = get_move(board);
+	add_move(board, index);
+
+	/* replies */
+	afb_req_success(req, describe(board), NULL);
+
+	/* signals change */
+	changed(board, "play");
+}
+
+static void wait(struct afb_req req)
+{
+	struct board *board;
+	struct waiter *waiter;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'wait' called for boardid %d", board->id);
+
+	/* creates the waiter and enqueues it */
+	waiter = calloc(1, sizeof *waiter);
+	waiter->req = req;
+	waiter->next = board->waiters;
+	afb_req_addref(req);
+	board->waiters = waiter;
+}
+
+/*
+ * array of the verbs exported to afb-daemon
+ */
+static const struct afb_verb_desc_v1 binding_verbs[] = {
+   /* VERB'S NAME     SESSION MANAGEMENT          FUNCTION TO CALL  SHORT DESCRIPTION */
+   { .name= "new",   .session= AFB_SESSION_NONE, .callback= new,   .info= "Starts a new game" },
+   { .name= "play",  .session= AFB_SESSION_NONE, .callback= play,  .info= "Asks the server to play" },
+   { .name= "move",  .session= AFB_SESSION_NONE, .callback= move,  .info= "Tells the client move" },
+   { .name= "board", .session= AFB_SESSION_NONE, .callback= board, .info= "Get the current board" },
+   { .name= "level", .session= AFB_SESSION_NONE, .callback= level, .info= "Set the server level" },
+   { .name= "join",  .session= AFB_SESSION_CHECK,.callback= join,  .info= "Join a board" },
+   { .name= "undo",  .session= AFB_SESSION_NONE, .callback= undo,  .info= "Undo the last move" },
+   { .name= "wait",  .session= AFB_SESSION_NONE, .callback= wait,  .info= "Wait for a change" },
+   { .name= NULL } /* marker for end of the array */
+};
+
+/*
+ * description of the binding for afb-daemon
+ */
+static const struct afb_binding binding_description =
+{
+   /* description conforms to VERSION 1 */
+   .type= AFB_BINDING_VERSION_1,
+   .v1= {				/* fills the v1 field of the union when AFB_BINDING_VERSION_1 */
+      .prefix= "tictactoe",		/* the API name (or binding name or prefix) */
+      .info= "Sample tac-tac-toe game",	/* short description of of the binding */
+      .verbs = binding_verbs		/* the array describing the verbs of the API */
+   }
+};
+
+/*
+ * activation function for registering the binding called by afb-daemon
+ */
+const struct afb_binding *afbBindingV1Register(const struct afb_binding_interface *itf)
+{
+   afbitf = itf;         // records the interface for accessing afb-daemon
+   return &binding_description;  // returns the description of the binding
+}
+
diff --git a/doc/FAQ.html b/doc/FAQ.html
index 0cad0b5b..e5f64273 100644
--- a/doc/FAQ.html
+++ b/doc/FAQ.html
@@ -16,7 +16,7 @@
 <header>
 <h1 class="title">Frequently Asked Question about AFB-DAEMON</h1>
 <h2 class="author">José Bollo</h2>
-<h3 class="date">27 mai 2016</h3>
+<h3 class="date">10 juin 2016</h3>
 </header>
 <nav id="TOC">
 <ul>
diff --git a/doc/afb-application-writing.html b/doc/afb-application-writing.html
index 1f1fcc1c..ad1911df 100644
--- a/doc/afb-application-writing.html
+++ b/doc/afb-application-writing.html
@@ -37,7 +37,7 @@ code > span.er { color: #ff0000; font-weight: bold; }
 <h1 class="title">HOWTO WRITE an APPLICATION above AGL FRAMEWORK</h1>
 <h2 class="author">José Bollo</h2>
 <h2 class="author">Fulup Ar Foll</h2>
-<h3 class="date">09 juin 2016</h3>
+<h3 class="date">10 juin 2016</h3>
 </header>
 <nav id="TOC">
 <ul>
diff --git a/doc/afb-bindings-overview.html b/doc/afb-bindings-overview.html
new file mode 100644
index 00000000..b731aff2
--- /dev/null
+++ b/doc/afb-bindings-overview.html
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <meta name="generator" content="pandoc">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
+  <meta name="author" content="José Bollo">
+  <title>Overview of bindings shipped with AFB-Daemon</title>
+  <style type="text/css">code{white-space: pre;}</style>
+  <!--[if lt IE 9]>
+    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+  <![endif]-->
+  <link rel="stylesheet" href="doc.css">
+</head>
+<body>
+<header>
+<h1 class="title">Overview of bindings shipped with AFB-Daemon</h1>
+<h2 class="author">José Bollo</h2>
+<h3 class="date">23 juin 2016</h3>
+</header>
+<nav id="TOC">
+<ul>
+<li><a href="#overview-of-bindings-shipped-with-afb-daemon">Overview of bindings shipped with AFB-Daemon</a><ul>
+<li><a href="#list-of-bindings">List of bindings</a></li>
+<li><a href="#detail-of-bindings">Detail of bindings</a><ul>
+<li><a href="#hello-world">Hello World</a></li>
+<li><a href="#authentication">Authentication</a></li>
+<li><a href="#tic-tac-toe">Tic Tac Toe</a></li>
+<li><a href="#audio">Audio</a></li>
+<li><a href="#radio">Radio</a></li>
+<li><a href="#media">Media</a></li>
+</ul></li>
+</ul></li>
+</ul>
+</nav>
+<h1 id="overview-of-bindings-shipped-with-afb-daemon">Overview of bindings shipped with AFB-Daemon</h1>
+<pre><code>Version: 1
+Date:    09 juin 2016
+Author:  Manuel Bachmann</code></pre>
+<h2 id="list-of-bindings">List of bindings</h2>
+<p>Here are the bindings shipped in the source tree:</p>
+<ul>
+<li>Hello World</li>
+<li>Authentication</li>
+<li>Tic Tac Toe</li>
+<li>Audio <em>(2 backends: ALSA/PulseAudio)</em></li>
+<li>Radio <em>(1 backend: RTLSDR RTL2832U)</em></li>
+<li>Media <em>(1 backend: Rygel UPnP)</em></li>
+</ul>
+<p>All bindings may not be built, depending on the development libraries present on the system at build time.</p>
+<h2 id="detail-of-bindings">Detail of bindings</h2>
+<h3 id="hello-world">Hello World</h3>
+<p>A sample Hello World binding for demonstration and learning purposes.</p>
+<p>This binding provides a few unauthenticated requests, all beginning with &quot;ping&quot;, to demonstrate basic binder capabilities.</p>
+<p><strong>Verbs</strong>:</p>
+<ul>
+<li><em>ping:</em> returns a success response</li>
+<li><em>pingfail:</em> returns a failure response</li>
+<li><em>pingnull:</em> returns a success response, with an empty JSON response field</li>
+<li><em>pingbug:</em> does a memory violation (intercepted by the binder)</li>
+<li><em>pingJson:</em> returns a success response, with a complex JSON response field</li>
+<li><em>pingevent:</em> broadcasts a global event</li>
+</ul>
+<p><br /></p>
+<h3 id="authentication">Authentication</h3>
+<p>An sample Authentication binding for demonstration purposes.</p>
+<p>This binding provides a few requests to demonstrate the binder's token-based security mechanism.</p>
+<p>Calling &quot;<em>connect</em>&quot; with a security token will initiate a session, calling &quot;<em>refresh</em>&quot; will issue a new token and invalidate the previous one, calling &quot;<em>logout</em>&quot; will invalidate all tokens and close the session.</p>
+<p><strong>Verbs</strong>:</p>
+<ul>
+<li><em>ping:</em> returns a success response</li>
+<li><em>connect:</em> creates a session and returns a new token</li>
+<li><em>refresh:</em> returns a new token</li>
+<li><em>check:</em> verifies the passed token is valid</li>
+<li><em>logout:</em> closes the session</li>
+</ul>
+<p><br /></p>
+<h3 id="tic-tac-toe">Tic Tac Toe</h3>
+<p>A sample Tic Tac Toe game binding.</p>
+<p>This binding provides an interactive Tic Tac Toe game where the binder returns the grid as a JSON response.</p>
+<p><strong>Verbs</strong>:</p>
+<ul>
+<li><em>new:</em> starts a new game</li>
+<li><em>play:</em> asks the server to play</li>
+<li><em>move:</em> gives a client move</li>
+<li><em>board:</em> gets the current board state, as a JSON structure</li>
+<li><em>level</em>: sets the server level</li>
+<li><em>join</em>: joins an existing board</li>
+<li><em>undo</em>: undo the last move</li>
+<li><em>wait</em>: wait for a move</li>
+</ul>
+<p><br /></p>
+<h3 id="audio">Audio</h3>
+<p>A sample Audio binding with 2 backends:</p>
+<ul>
+<li>ALSA (mandatory)</li>
+<li>PulseAudio (optional)</li>
+</ul>
+<p>This binding is able to initialize a specific soundcard, define volume levels, channels (mono/stereo...), mute sound, and play a 22,050 Hz PCM stream.</p>
+<p><strong>Verbs</strong>:</p>
+<ul>
+<li><em>ping:</em> returns a success response</li>
+<li><em>init:</em> initializes backend, on the &quot;default&quot; sound card</li>
+<li><em>volume:</em> gets or sets volume, in % (0-100)</li>
+<li><em>channels:</em> gets or sets channels count (1-8)</li>
+<li><em>mute:</em> gets or sets the mute status (on-off)</li>
+<li><em>play</em>: gets or sets the playing status (on-off)</li>
+</ul>
+<p><em>(if PulseAudio development libraries are not found at build time, only ALSA will be available)</em></p>
+<p><em>(if a PulseAudio server is not found at runtime, the binding will dynamically fall back to ALSA)</em></p>
+<p><em>(a specifc backend can be forced by using this syntax before running afb-daemon : <strong>$ export AFB_AUDIO_OUTPUT=Alsa</strong>)</em></p>
+<p><br /></p>
+<h3 id="radio">Radio</h3>
+<p>A sample AM/FM Radio binding with 1 backend:</p>
+<ul>
+<li>RTLSDR - Realtek RTL2832U dongles (mandatory)</li>
+</ul>
+<p>This binding is able to initialize specific RTL2832U dongles, switch between AM/FM modes, define frequency, mute sound, and play sound (if combining with the <strong>audio</strong> binding).</p>
+<p><strong>Verbs</strong>:</p>
+<ul>
+<li><em>ping:</em> returns a success response</li>
+<li><em>init:</em> initializes backend, looking for plugged-in devices</li>
+<li><em>power:</em> sets device power status (on-off)</li>
+<li><em>mode:</em> sets device reception mode (AM-FM)</li>
+<li><em>freq:</em> sets device frequency (in Hz)</li>
+<li><em>mute</em>: sets device mute status (on-off)</li>
+<li><em>play</em>: sets device playing status (on-off)</li>
+</ul>
+<p><em>(if rtlsdr development libraries are not found at build time, this binding will not be built)</em></p>
+<p><br /></p>
+<h3 id="media">Media</h3>
+<p>A sample Media Server binding with 1 backend:</p>
+<ul>
+<li>Rygel</li>
+</ul>
+<p>This binding is able to detect a local Rygel UPnP media server, list audio files, select an audio file for playback, play/pause/seek in this file, upload an audio file to the server.</p>
+<p><strong>Verbs</strong>:</p>
+<ul>
+<li><em>ping:</em> returns a success response</li>
+<li><em>init:</em> initializes backend, looking for an active local UPnP server</li>
+<li><em>list:</em> returns list of audio files, as a JSON structure</li>
+<li><em>select:</em> select an audio files, by index number (001-...)</li>
+<li><em>play:</em> plays the currently selected audio file</li>
+<li><em>stop:</em> stops the currently selected audio file</li>
+<li><em>pause:</em> pauses the currently selected audio file</li>
+<li><em>seek:</em> seeks in the currently selected audio file, in seconds</li>
+<li><em>upload:</em> uploads an audio file, with a POST request</li>
+</ul>
+<p><em>(if GUPnP/GSSDP development libraries are not fund at build time, this binding will not be built)</em></p>
+<p><br /></p>
+<hr />
+<p><br /></p>
+<p>Sample command-line applications: <em>afb-client-demo</em> (built by default)</p>
+<p>Sample HTML5 applications: **test/*.html<strong>, </strong><a href="https://gerrit.automotivelinux.org/gerrit/gitweb?p=src/app-framework-demo.git;a=tree">afb-client</a><strong>, </strong><a href="https://github.com/iotbzh/afb-radio">afb-radio</a>**</p>
+<p>Sample Qt/QML applications: <em>test/token-websock.qml</em></p>
+</body>
+</html>
diff --git a/doc/afb-bindings-overview.md b/doc/afb-bindings-overview.md
new file mode 100644
index 00000000..03650cd4
--- /dev/null
+++ b/doc/afb-bindings-overview.md
@@ -0,0 +1,168 @@
+Overview of bindings shipped with AFB-Daemon
+===========================================
+    Version: 1
+    Date:    09 juin 2016
+    Author:  Manuel Bachmann
+
+
+List of bindings
+---------------
+
+Here are the bindings shipped in the source tree:
+
+* Hello World
+* Authentication
+* Tic Tac Toe
+* Audio _(2 backends: ALSA/PulseAudio)_
+* Radio _(1 backend: RTLSDR RTL2832U)_
+* Media _(1 backend: Rygel UPnP)_
+
+All bindings may not be built, depending on the development libraries present on the system at build time.
+
+
+Detail of bindings
+-----------------
+
+### Hello World
+
+A sample Hello World binding for demonstration and learning purposes.
+
+This binding provides a few unauthenticated requests, all beginning with "ping", to demonstrate basic binder capabilities.
+
+**Verbs**:
+
+* _ping:_ returns a success response
+* _pingfail:_ returns a failure response
+* _pingnull:_ returns a success response, with an empty JSON response field
+* _pingbug:_ does a memory violation (intercepted by the binder)
+* _pingJson:_ returns a success response, with a complex JSON response field
+* _pingevent:_ broadcasts a global event
+
+<br />
+
+
+### Authentication
+
+An sample Authentication binding for demonstration purposes.
+
+This binding provides a few requests to demonstrate the binder's token-based security mechanism.
+
+Calling "_connect_" with a security token will initiate a session, calling "_refresh_" will issue a new token and invalidate the previous one, calling "_logout_" will invalidate all tokens and close the session.
+
+**Verbs**:
+
+* _ping:_ returns a success response
+* _connect:_ creates a session and returns a new token
+* _refresh:_ returns a new token
+* _check:_ verifies the passed token is valid
+* _logout:_ closes the session
+
+<br />
+
+
+### Tic Tac Toe
+
+A sample Tic Tac Toe game binding.
+
+This binding provides an interactive Tic Tac Toe game where the binder returns the grid as a JSON response. 
+
+**Verbs**:
+
+* _new:_ starts a new game
+* _play:_ asks the server to play
+* _move:_ gives a client move
+* _board:_ gets the current board state, as a JSON structure
+* _level_: sets the server level
+* _join_: joins an existing board
+* _undo_: undo the last move
+* _wait_: wait for a move
+
+<br />
+
+
+### Audio
+
+A sample Audio binding with 2 backends:
+
+* ALSA (mandatory)
+* PulseAudio (optional)
+
+This binding is able to initialize a specific soundcard, define volume levels, channels (mono/stereo...), mute sound, and play a 22,050 Hz PCM stream.
+
+**Verbs**:
+
+* _ping:_ returns a success response
+* _init:_ initializes backend, on the "default" sound card
+* _volume:_ gets or sets volume, in % (0-100)
+* _channels:_ gets or sets channels count (1-8)
+* _mute:_ gets or sets the mute status (on-off)
+* _play_: gets or sets the playing status (on-off)
+
+_(if PulseAudio development libraries are not found at build time, only ALSA will be available)_
+
+_(if a PulseAudio server is not found at runtime, the binding will dynamically fall back to ALSA)_
+
+_(a specifc backend can be forced by using this syntax before running afb-daemon : **$ export AFB_AUDIO_OUTPUT=Alsa**)_
+
+<br />
+
+
+### Radio
+
+A sample AM/FM Radio binding with 1 backend:
+
+* RTLSDR - Realtek RTL2832U dongles (mandatory)
+
+This binding is able to initialize specific RTL2832U dongles, switch between AM/FM modes, define frequency, mute sound, and play sound (if combining with the **audio** binding).
+
+**Verbs**:
+
+* _ping:_ returns a success response
+* _init:_ initializes backend, looking for plugged-in devices
+* _power:_ sets device power status (on-off)
+* _mode:_ sets device reception mode (AM-FM)
+* _freq:_ sets device frequency (in Hz)
+* _mute_: sets device mute status (on-off)
+* _play_: sets device playing status (on-off)
+
+_(if rtlsdr development libraries are not found at build time, this binding will not be built)_
+
+<br />
+
+
+### Media
+
+A sample Media Server binding with 1 backend:
+
+ * Rygel
+
+This binding is able to detect a local Rygel UPnP media server, list audio files, select an audio file for playback, play/pause/seek in this file, upload an audio file to the server.
+
+**Verbs**:
+
+* _ping:_ returns a success response
+* _init:_ initializes backend, looking for an active local UPnP server
+* _list:_ returns list of audio files, as a JSON structure
+* _select:_ select an audio files, by index number (001-...)
+* _play:_ plays the currently selected audio file
+* _stop:_ stops the currently selected audio file
+* _pause:_ pauses the currently selected audio file
+* _seek:_ seeks in the currently selected audio file, in seconds
+* _upload:_ uploads an audio file, with a POST request
+
+_(if GUPnP/GSSDP development libraries are not fund at build time, this binding will not be built)_
+
+<br />
+
+
+---
+<br />
+
+Sample command-line applications: _afb-client-demo_ (built by default)
+
+Sample HTML5 applications: 
+**test/*.html**, 
+**[afb-client](https://gerrit.automotivelinux.org/gerrit/gitweb?p=src/app-framework-demo.git;a=tree)**, 
+**[afb-radio](https://github.com/iotbzh/afb-radio)**
+
+Sample Qt/QML applications: *test/token-websock.qml*
diff --git a/doc/afb-bindings-writing.html b/doc/afb-bindings-writing.html
new file mode 100644
index 00000000..8017e190
--- /dev/null
+++ b/doc/afb-bindings-writing.html
@@ -0,0 +1,951 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <meta name="generator" content="pandoc">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
+  <meta name="author" content="José Bollo">
+  <title>HOWTO WRITE a BINDING for AFB-DAEMON</title>
+  <style type="text/css">code{white-space: pre;}</style>
+  <!--[if lt IE 9]>
+    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+  <![endif]-->
+  <style type="text/css">
+table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
+  margin: 0; padding: 0; vertical-align: baseline; border: none; }
+table.sourceCode { width: 100%; line-height: 100%; }
+td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
+td.sourceCode { padding-left: 5px; }
+code > span.kw { color: #007020; font-weight: bold; }
+code > span.dt { color: #902000; }
+code > span.dv { color: #40a070; }
+code > span.bn { color: #40a070; }
+code > span.fl { color: #40a070; }
+code > span.ch { color: #4070a0; }
+code > span.st { color: #4070a0; }
+code > span.co { color: #60a0b0; font-style: italic; }
+code > span.ot { color: #007020; }
+code > span.al { color: #ff0000; font-weight: bold; }
+code > span.fu { color: #06287e; }
+code > span.er { color: #ff0000; font-weight: bold; }
+  </style>
+  <link rel="stylesheet" href="doc.css">
+</head>
+<body>
+<header>
+<h1 class="title">HOWTO WRITE a BINDING for AFB-DAEMON</h1>
+<h2 class="author">José Bollo</h2>
+<h3 class="date">23 juin 2016</h3>
+</header>
+<nav id="TOC">
+<ul>
+<li><a href="#howto-write-a-binding-for-afb-daemon">HOWTO WRITE a BINDING for AFB-DAEMON</a><ul>
+<li><a href="#summary">Summary</a><ul>
+<li><a href="#nature-of-a-binding">Nature of a binding</a></li>
+<li><a href="#class-of-bindings">Class of bindings</a></li>
+<li><a href="#live-cycle-of-bindings-within-afb-daemon">Live cycle of bindings within afb-daemon</a></li>
+<li><a href="#binding-contend">Binding Contend</a></li>
+</ul></li>
+<li><a href="#the-tic-tac-toe-example">The Tic-Tac-Toe example</a></li>
+<li><a href="#dependencies-when-compiling">Dependencies when compiling</a></li>
+<li><a href="#header-files-to-include">Header files to include</a></li>
+<li><a href="#choosing-names">Choosing names</a><ul>
+<li><a href="#names-for-api-binding">Names for API (binding)</a></li>
+<li><a href="#names-for-methods">Names for methods</a></li>
+<li><a href="#names-for-arguments">Names for arguments</a></li>
+<li><a href="#forging-names-widely-available">Forging names widely available</a></li>
+</ul></li>
+<li><a href="#writing-a-synchronous-method-implementation">Writing a synchronous method implementation</a><ul>
+<li><a href="#the-incoming-request">The incoming request</a></li>
+<li><a href="#associating-a-client-context-to-a-session">Associating a client context to a session</a></li>
+<li><a href="#sending-reply-to-a-request">Sending reply to a request</a></li>
+</ul></li>
+<li><a href="#getting-argument-of-invocation">Getting argument of invocation</a><ul>
+<li><a href="#basic-functions-for-querying-arguments">Basic functions for querying arguments</a></li>
+<li><a href="#arguments-for-received-files">Arguments for received files</a></li>
+<li><a href="#arguments-as-a-json-object">Arguments as a JSON object</a></li>
+</ul></li>
+<li><a href="#initialisation-of-the-binding-and-declaration-of-methods">Initialisation of the binding and declaration of methods</a></li>
+<li><a href="#sending-messages-to-the-log-system">Sending messages to the log system</a><ul>
+<li><a href="#verbs-for-logging-messages">Verbs for logging messages</a></li>
+<li><a href="#managing-verbosity">Managing verbosity</a></li>
+<li><a href="#output-format-and-destination">Output format and destination</a></li>
+</ul></li>
+<li><a href="#sending-events">Sending events</a></li>
+<li><a href="#writing-an-asynchronous-method-implementation">Writing an asynchronous method implementation</a></li>
+<li><a href="#how-to-build-a-binding">How to build a binding</a><ul>
+<li><a href="#example-for-cmake-meta-build-system">Example for cmake meta build system</a></li>
+<li><a href="#exporting-the-function-afbbindingv1register">Exporting the function afbBindingV1Register</a></li>
+<li><a href="#building-within-yocto">Building within yocto</a></li>
+</ul></li>
+</ul></li>
+</ul>
+</nav>
+<h1 id="howto-write-a-binding-for-afb-daemon">HOWTO WRITE a BINDING for AFB-DAEMON</h1>
+<pre><code>version: 1
+Date:    09 juin 2016
+Author:  José Bollo</code></pre>
+<h2 id="summary">Summary</h2>
+<p>Afb-daemon binders serve files through HTTP protocol and offers to developers the capability to expose application API methods through HTTP or WebSocket protocol.</p>
+<p>Binder bindings are used to add API to afb-daemon. This part describes how to write a binding for afb-daemon.</p>
+<p>Excepting this summary, this document target developers.</p>
+<p>Before moving further through an example, here after a short overview of binder bindings fundamentals.</p>
+<h3 id="nature-of-a-binding">Nature of a binding</h3>
+<p>A binding is an independent piece of software. A binding is self contain and exposes application logic as sharable library. A binding is intended to be dynamically loaded by afb-daemon to expose application API.</p>
+<p>Technically, a binder binding does not reference and is not linked with any afb-daemon library.</p>
+<h3 id="class-of-bindings">Class of bindings</h3>
+<p>Application binder supports two kinds of bindings: application bindings and service bindings. Technically both class of binding are equivalent are use the same coding convention. Only sharing mode and security context diverge.</p>
+<h4 id="application-bindings">Application-bindings</h4>
+<p>Application-bindings implements the glue in between application's UI and services. Every AGL application has a corresponding binder that typically activates one or many bindings to interface the application logic with lower platform services. When an application is started by the AGL application framework, a dedicate binder is started that loads/activates application binding(s). API expose by application-binding are executed within corresponding application security context.</p>
+<p>Application bindings generally handle a unique context for a unique client. As the application framework start a dedicated instance of afb_daemon for each AGL application, if a given binding is used within multiple application each of those application get a new and private instance of eventually &quot;shared&quot; binding.</p>
+<h4 id="service-bindings">Service-bindings</h4>
+<p>Service-bindings enable API activation within corresponding service security context and not within calling application context. Service-bindings are intended to run as a unique instance. Service-bindings can be shared in between multiple clients.</p>
+<p>Service-bindings can either be stateless or manage client context. When managing context each client get a private context.</p>
+<p>Sharing may either be global to the platform (ie: GPS service) or dedicated to a given user (ie: user preferences)</p>
+<h3 id="live-cycle-of-bindings-within-afb-daemon">Live cycle of bindings within afb-daemon</h3>
+<p>Application and service bindings are loaded and activated each time a new afb-daemon is started.</p>
+<p>At launch time, every loaded binding initialise itself. If a single binding initialisation fail corresponding instance of afb-daemon self aborts.</p>
+<p>Conversely, when a binding initialisation succeeds, it should register its unique name as well as the list of verbs attached to the methods it exposes.</p>
+<p>When initialised, on request from application clients to the right API/verb, binding methods are activated by the afb-daemon attached to the application or service.</p>
+<p>At exit time, no special action is enforced by afb-daemon. When a specific actions is required at afb-daemon stop, developers should use 'atexit/on_exit' during binding initialisation sequence to register a custom exit function.</p>
+<h3 id="binding-contend">Binding Contend</h3>
+<p>Afb-daemon's binding register two classes of objects: names and functions.</p>
+<p>Bindings declare categories of names: - A unique binding name to access all API expose by this binding, - One name for each methods/verbs provided by this binding.</p>
+<p>Bindings declare two categories of functions: - function use for the initialisation - functions implementing exposed API methods</p>
+<p>Afb-daemon parses URI requests to extract the API(binding name) and the VERB(method to activate). As an example, URI <strong>foo/bar</strong> translates to binding named <strong>foo</strong> and method named <strong>bar</strong>. To serve such a request, afb-daemon looks for an active binding named <strong>foo</strong> and then within this binding for a method named <strong>bar</strong>. When find afb-daemon calls corresponding method with attached parameter if any.</p>
+<p>Afb-daemon ignores letter case when parsing URI. Thus <strong>TicTacToe/Board</strong> and <strong>tictactoe/board</strong> are equivalent.</p>
+<h4 id="the-name-of-the-binding">The name of the binding</h4>
+<p>The name of a given binding is also known as the name of the API prefix that defines the binding.</p>
+<p>The name of a binding SHOULD be unique within a given afb-daemon instance.</p>
+<p>For example, when a client of afb-daemon calls a URI named <strong>foo/bar</strong>. Afb-daemon extracts the prefix <strong>foo</strong> and the suffix <strong>bar</strong>. <strong>foo</strong> must match a binding name and <strong>bar</strong> a VERB attached to some method.</p>
+<h4 id="names-of-methods">Names of methods</h4>
+<p>Each binding exposes a set of methods that can be called by the clients of a given afb-daemon.</p>
+<p>VERB's name attached to a given binding (API) MUST be unique within a binding.</p>
+<p>Bindings static declaration link VERBS to corresponding methods. When clients emit requests on a given API/VERB corresponding method is called by afb-daemon.</p>
+<h4 id="initialisation-function">Initialisation function</h4>
+<p>Binding's initialisation function serves several purposes.</p>
+<ol type="1">
+<li><p>It allows afb-daemon to control binding version depending on initialisation function name. As today, the only supported initialisation function is <strong>afbBindingV1Register</strong>. This identifies version &quot;one&quot; of bindings.</p></li>
+<li><p>It allows bindings to initialise itself.</p></li>
+<li><p>It enables names declarations: descriptions, requirements and implementations of exposed API/VERB.</p></li>
+</ol>
+<h4 id="functions-instantiation-of-apiverbs">Functions instantiation of API/VERBs</h4>
+<p>When an API/VERB is called, afb-daemon constructs a request object. Then it passes this request object to the implementation function corresponding to requested method, this within attached API binding.</p>
+<p>An implementation function receives a request object that is used to: get arguments of the request, send answer, store session data.</p>
+<p>A binding MUST set an answer to every received requests.</p>
+<p>Nevertheless it is not mandatory to set the answer before returning from API/VERB implementing function. This behaviour is important for asynchronous actions.</p>
+<p>API/VERB implementation that set an answer before returning are called <em>synchronous implementations</em>. Those that do not systematically set an answer before returning are called <em>asynchronous implementations</em>.</p>
+<p>Asynchronous implementations typically launch asynchronous actions. They record some context at request time and provide answer to the request only at completion of asynchronous actions.</p>
+<h2 id="the-tic-tac-toe-example">The Tic-Tac-Toe example</h2>
+<p>This part explains how to write an afb-binding. For the sake of being practical it uses many examples based on tic-tac-toe. This binding example is in <em>bindings/samples/tic-tac-toe.c</em>.</p>
+<p>This binding is named <strong><em>tictactoe</em></strong>.</p>
+<h2 id="dependencies-when-compiling">Dependencies when compiling</h2>
+<p>Afb-daemon provides a configuration file for <em>pkg-config</em>. Typing the command</p>
+<pre><code>pkg-config --cflags afb-daemon</code></pre>
+<p>Print flags use for compilation:</p>
+<pre><code>$ pkg-config --cflags afb-daemon
+-I/opt/local/include -I/usr/include/json-c </code></pre>
+<p>For linking, you should use</p>
+<pre><code>$ pkg-config --libs afb-daemon
+-ljson-c</code></pre>
+<p>Afb-daemon automatically includes dependency to json-c. This is activated through <strong>Requires</strong> keyword in pkg-config. While almost every binding replies on <strong>json-c</strong> this is not a must have dependency.</p>
+<p>Internally, afb-daemon relies on <strong>libsystemd</strong> for its event loop, as well as for its binding to D-Bus. Bindings developers are encouraged to leverage <strong>libsystemd</strong> when possible. Nevertheless there is no hard dependency to <strong>libsystemd</strong> if ever you rather not use it, feel free to do so.</p>
+<blockquote>
+<p>Afb-daemon binding are fully self contain. They do not enforce dependency on any libraries from the application framework. Afb-daemon dependencies requirer to run AGL bindings are given at runtime through pointers leveraging read-only memory feature.</p>
+</blockquote>
+<h2 id="header-files-to-include">Header files to include</h2>
+<p>Binding <em>tictactoe</em> has following includes:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="ot">#define _GNU_SOURCE</span>
+<span class="ot">#include &lt;stdio.h&gt;</span>
+<span class="ot">#include &lt;string.h&gt;</span>
+<span class="ot">#include &lt;json-c/json.h&gt;</span>
+<span class="ot">#include &lt;afb/afb-binding.h&gt;</span></code></pre>
+<p>Header <em>afb/afb-binding.h</em> is the only hard dependency, it includes all features that a binding MUST HAVE. Outside of includes used to support application logic, common external headers used within bindings are:</p>
+<ul>
+<li><em>json-c/json.h</em>: should be include to handle json objects;</li>
+<li><em>systemd/sd-event.h</em>: should be include to access event main loop;</li>
+<li><em>systemd/sd-bus.h</em>: should be include for dbus connections.</li>
+</ul>
+<p>The <em>tictactoe</em> binding does not leverage systemd features, also only json.h is used on top of mandatory afb/afb-binding.h.</p>
+<p>When including <em>afb/afb-binding.h</em>, the macro **_GNU_SOURCE** MUST be defined.</p>
+<h2 id="choosing-names">Choosing names</h2>
+<p>Designers of bindings should define a unique name for every API binding as well as for methods VERBs. They should also define names for request arguments passed as name/value pair in URI.</p>
+<p>While forging names, designers should respect few rules to ensure that created names are valid and easy to use across platforms.</p>
+<p>All names and strings are UTF-8 encoded.</p>
+<h3 id="names-for-api-binding">Names for API (binding)</h3>
+<p>Binding API name are checked. All characters are authorised except:</p>
+<ul>
+<li>the control characters (000 .. 01f)</li>
+<li>the characters of the set { ' ', '&quot;', '#', '%', '&amp;', ''', '/', '?', '`', '7f' }</li>
+</ul>
+<p>In other words the set of forbidden characters is { 000..020, 022, 023, 025..027, 02f, 03f, 060, 07f }.</p>
+<p>Afb-daemon makes no distinction between lower case and upper case when searching for API/VERB.</p>
+<h3 id="names-for-methods">Names for methods</h3>
+<p>The names of methods VERBs are totally free and not checked.</p>
+<p>However, the validity rules for method's VERB name are the same as for Binding API name except that the dot(.) character is forbidden.</p>
+<p>Afb-daemon makes no case distinction when searching for an API by name.</p>
+<h3 id="names-for-arguments">Names for arguments</h3>
+<p>Argument's name are not restricted and can be everything you wish.</p>
+<blockquote>
+<p>Warning arguments search is case sensitive and &quot;index&quot; and &quot;Index&quot; are not two different arguments.</p>
+</blockquote>
+<h3 id="forging-names-widely-available">Forging names widely available</h3>
+<p>The key names of javascript object can be almost anything using the arrayed notation:</p>
+<pre><code>object[key] = value</code></pre>
+<p>Nevertheless this is not the case with javascript dot notation:</p>
+<pre><code>object.key = value</code></pre>
+<p>Using the dot notation, the key must be a valid javascript identifier and dash(-) as well as few other reserved characters cannot be used.</p>
+<p>For this reason, we advise developper to chose name compatible with both javascript and HTML notation.</p>
+<p>It is a good practice, even for arguments not to rely on case sensitivity. This may reduce headache strength at debug time, especially with interpreted language like javascript that may not warn you that a variable was not defined.</p>
+<h2 id="writing-a-synchronous-method-implementation">Writing a synchronous method implementation</h2>
+<p>The method <strong>tictactoe/board</strong> is a synchronous implementation. Here is its listing:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * get the board</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="dt">void</span> board(<span class="kw">struct</span> afb_req req)
+{
+    <span class="kw">struct</span> board *board;
+    <span class="kw">struct</span> json_object *description;
+
+    <span class="co">/* retrieves the context for the session */</span>
+    board = board_of_req(req);
+    INFO(afbitf, <span class="st">&quot;method &#39;board&#39; called for boardid %d&quot;</span>, board-&gt;id);
+
+    <span class="co">/* describe the board */</span>
+    description = describe(board);
+
+    <span class="co">/* send the board&#39;s description */</span>
+    afb_req_success(req, description, NULL);
+}</code></pre>
+<p>This example shows many aspects of a synchronous method implementation. Let summarise it:</p>
+<ol type="1">
+<li><p>The function <strong>board_of_req</strong> retrieves the context stored for the binding: the board.</p></li>
+<li><p>The macro <strong>INFO</strong> sends a message of kind <em>INFO</em> to the logging system. The global variable named <strong>afbitf</strong> used represents the interface to afb-daemon.</p></li>
+<li><p>The function <strong>describe</strong> creates a json_object representing the board.</p></li>
+<li><p>The function <strong>afb_req_success</strong> sends the reply, attaching to it the object <em>description</em>.</p></li>
+</ol>
+<h3 id="the-incoming-request">The incoming request</h3>
+<p>For any implementation, the request is received by a structure of type <strong>struct afb_req</strong>.</p>
+<blockquote>
+<p>Note that this is a PLAIN structure, not a pointer to a structure.</p>
+</blockquote>
+<p>The definition of <strong>struct afb_req</strong> is:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Describes the request by bindings from afb-daemon</span>
+<span class="co"> */</span>
+<span class="kw">struct</span> afb_req {
+    <span class="dt">const</span> <span class="kw">struct</span> afb_req_itf *itf;  <span class="co">/* the interfacing functions */</span>
+    <span class="dt">void</span> *closure;          <span class="co">/* the closure for functions */</span>
+};</code></pre>
+<p>It contains two pointers: first one <em>itf</em>, points to functions used to handle internal request. Second one <em>closure</em> point onto function closure.</p>
+<blockquote>
+<p>The structure must never be used directly. Instead developer should use the intended functions provided by afb-daemon as described here after.</p>
+</blockquote>
+<p><em>req</em> is used to get arguments of the request, to send answer, to store session data.</p>
+<p>This object and its interface is defined and documented in the file names <em>afb/afb-req-itf.h</em></p>
+<p>The above example uses twice <em>req</em> object request.</p>
+<p>The first time, to retrieve the board attached to the session of the request.</p>
+<p>The second time, to send the reply: an object that describes the current board.</p>
+<h3 id="associating-a-client-context-to-a-session">Associating a client context to a session</h3>
+<p>When <em>tic-tac-toe</em> binding receives a request, it musts get the board describing the game associated to the session.</p>
+<p>For a binding, having data associated to a session is common. This data is called &quot;binding context&quot; for the session. Within <em>tic-tac-toe</em> binding the context is the board.</p>
+<p>Requests <em>afb_req</em> offer four functions for storing and retrieving session associated context.</p>
+<p>These functions are:</p>
+<ul>
+<li><p><strong>afb_req_context_get</strong>: retrieves context data stored for current binding.</p></li>
+<li><p><strong>afb_req_context_set</strong>: store context data of current binding.</p></li>
+<li><p><strong>afb_req_context</strong>: if exist retrieves context data of current binding. if context does not yet exist, creates a new context and store it.</p></li>
+<li><p><strong>afb_req_context_clear</strong>: reset the stored context data.</p></li>
+</ul>
+<p>The binding <em>tictactoe</em> use a convenient function to retrieve its context: the board. This function is <em>board_of_req</em>:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * retrieves the board of the request</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="kw">inline</span> <span class="kw">struct</span> board *board_of_req(<span class="kw">struct</span> afb_req req)
+{
+    <span class="kw">return</span> afb_req_context(req, (<span class="dt">void</span>*)get_new_board, (<span class="dt">void</span>*)release_board);
+}</code></pre>
+<p>The function <strong>afb_req_context</strong> ensures an existing context for the session of the request. Its two last arguments are functions to allocate and free context. Note function type casts to avoid compilation warnings.</p>
+<p>Here is the definition of the function <strong>afb_req_context</strong></p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Gets the pointer stored by the binding for the session of &#39;req&#39;.</span>
+<span class="co"> * If the stored pointer is NULL, indicating that no pointer was</span>
+<span class="co"> * already stored, afb_req_context creates a new context by calling</span>
+<span class="co"> * the function &#39;create_context&#39; and stores it with the freeing function</span>
+<span class="co"> * &#39;free_context&#39;.</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="kw">inline</span> <span class="dt">void</span> *afb_req_context(<span class="kw">struct</span> afb_req req, <span class="dt">void</span> *(*create_context)(), <span class="dt">void</span> (*free_context)(<span class="dt">void</span>*))
+{
+    <span class="dt">void</span> *result = afb_req_context_get(req);
+    <span class="kw">if</span> (result == NULL) {
+        result = create_context();
+        afb_req_context_set(req, result, free_context);
+    }
+    <span class="kw">return</span> result;
+}</code></pre>
+<p>The second argument if the function that creates the context. For binding <em>tic-tac-toe</em> (function <strong>get_new_board</strong>). The function <strong>get_new_board</strong> creates a new board and set usage its count to 1. The boards are checking usage count to free resources when not used.</p>
+<p>The third argument is a function that frees context resources. For binding <em>tic-tac-toe</em> (function <strong>release_board</strong>). The function <strong>release_board</strong> decrease usage count of the board passed in argument. When usage count falls to zero, data board are freed.</p>
+<p>Definition of other functions dealing with contexts:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Gets the pointer stored by the binding for the session of &#39;req&#39;.</span>
+<span class="co"> * When the binding has not yet recorded a pointer, NULL is returned.</span>
+<span class="co"> */</span>
+<span class="dt">void</span> *afb_req_context_get(<span class="kw">struct</span> afb_req req);
+
+<span class="co">/*</span>
+<span class="co"> * Stores for the binding the pointer &#39;context&#39; to the session of &#39;req&#39;.</span>
+<span class="co"> * The function &#39;free_context&#39; will be called when the session is closed</span>
+<span class="co"> * or if binding stores an other pointer.</span>
+<span class="co"> */</span>
+<span class="dt">void</span> afb_req_context_set(<span class="kw">struct</span> afb_req req, <span class="dt">void</span> *context, <span class="dt">void</span> (*free_context)(<span class="dt">void</span>*));
+
+<span class="co">/*</span>
+<span class="co"> * Frees the pointer stored by the binding for the session of &#39;req&#39;</span>
+<span class="co"> * and sets it to NULL.</span>
+<span class="co"> *</span>
+<span class="co"> * Shortcut for: afb_req_context_set(req, NULL, NULL)</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="kw">inline</span> <span class="dt">void</span> afb_req_context_clear(<span class="kw">struct</span> afb_req req)
+{
+    afb_req_context_set(req, NULL, NULL);
+}</code></pre>
+<h3 id="sending-reply-to-a-request">Sending reply to a request</h3>
+<p>Two kinds of replies: successful or failure.</p>
+<blockquote>
+<p>Sending a reply to a request MUST be done once and only once.</p>
+</blockquote>
+<p>It exists two functions for &quot;success&quot; replies: <strong>afb_req_success</strong> and <strong>afb_req_success_f</strong>.</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Sends a reply of kind success to the request &#39;req&#39;.</span>
+<span class="co"> * The status of the reply is automatically set to &quot;success&quot;.</span>
+<span class="co"> * Its send the object &#39;obj&#39; (can be NULL) with an</span>
+<span class="co"> * informationnal comment &#39;info (can also be NULL).</span>
+<span class="co"> *</span>
+<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;obj&#39;.</span>
+<span class="co"> * Thus, in the case where &#39;obj&#39; should remain available after</span>
+<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
+<span class="co"> */</span>
+<span class="dt">void</span> afb_req_success(<span class="kw">struct</span> afb_req req, <span class="kw">struct</span> json_object *obj, <span class="dt">const</span> <span class="dt">char</span> *info);
+
+<span class="co">/*</span>
+<span class="co"> * Same as &#39;afb_req_success&#39; but the &#39;info&#39; is a formatting</span>
+<span class="co"> * string followed by arguments.</span>
+<span class="co"> *</span>
+<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;obj&#39;.</span>
+<span class="co"> * Thus, in the case where &#39;obj&#39; should remain available after</span>
+<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
+<span class="co"> */</span>
+<span class="dt">void</span> afb_req_success_f(<span class="kw">struct</span> afb_req req, <span class="kw">struct</span> json_object *obj, <span class="dt">const</span> <span class="dt">char</span> *info, ...);</code></pre>
+<p>It exists two functions for &quot;failure&quot; replies: <strong>afb_req_fail</strong> and <strong>afb_req_fail_f</strong>.</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Sends a reply of kind failure to the request &#39;req&#39;.</span>
+<span class="co"> * The status of the reply is set to &#39;status&#39; and an</span>
+<span class="co"> * informational comment &#39;info&#39; (can also be NULL) can be added.</span>
+<span class="co"> *</span>
+<span class="co"> * Note that calling afb_req_fail(&quot;success&quot;, info) is equivalent</span>
+<span class="co"> * to call afb_req_success(NULL, info). Thus even if possible it</span>
+<span class="co"> * is strongly recommended to NEVER use &quot;success&quot; for status.</span>
+<span class="co"> *</span>
+<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;obj&#39;.</span>
+<span class="co"> * Thus, in the case where &#39;obj&#39; should remain available after</span>
+<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
+<span class="co"> */</span>
+<span class="dt">void</span> afb_req_fail(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *status, <span class="dt">const</span> <span class="dt">char</span> *info);
+
+<span class="co">/*</span>
+<span class="co"> * Same as &#39;afb_req_fail&#39; but the &#39;info&#39; is a formatting</span>
+<span class="co"> * string followed by arguments.</span>
+<span class="co"> *</span>
+<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;obj&#39;.</span>
+<span class="co"> * Thus, in the case where &#39;obj&#39; should remain available after</span>
+<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
+<span class="co"> */</span>
+<span class="dt">void</span> afb_req_fail_f(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *status, <span class="dt">const</span> <span class="dt">char</span> *info, ...);</code></pre>
+<blockquote>
+<p>For conveniency, these functions automatically call <strong>json_object_put</strong> to release <strong>obj</strong>. Because <strong>obj</strong> usage count is null after being passed to a reply function, it SHOULD not be used anymore. If exceptionally <strong>obj</strong> needs to remain usable after reply function then using <strong>json_object_get</strong> on <strong>obj</strong> to increase usage count and cancels the effect the <strong>json_object_put</strong> is possible.</p>
+</blockquote>
+<h2 id="getting-argument-of-invocation">Getting argument of invocation</h2>
+<p>Many methods expect arguments. Afb-daemon's bindings retrieve arguments by name and not by position.</p>
+<p>Arguments are passed by requests through either HTTP or WebSockets.</p>
+<p>For example, the method <strong>join</strong> of binding <strong>tic-tac-toe</strong> expects one argument: the <em>boardid</em> to join. Here is an extract:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Join a board</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="dt">void</span> join(<span class="kw">struct</span> afb_req req)
+{
+    <span class="kw">struct</span> board *board, *new_board;
+    <span class="dt">const</span> <span class="dt">char</span> *id;
+
+    <span class="co">/* retrieves the context for the session */</span>
+    board = board_of_req(req);
+    INFO(afbitf, <span class="st">&quot;method &#39;join&#39; called for boardid %d&quot;</span>, board-&gt;id);
+
+    <span class="co">/* retrieves the argument */</span>
+    id = afb_req_value(req, <span class="st">&quot;boardid&quot;</span>);
+    <span class="kw">if</span> (id == NULL)
+        <span class="kw">goto</span> bad_request;
+    ...</code></pre>
+<p>The function <strong>afb_req_value</strong> searches in the request <em>req</em> for argument name passed in the second argument. When argument name is not passed, <strong>afb_req_value</strong> returns NULL.</p>
+<blockquote>
+<p>The search is case sensitive and <em>boardid</em> is not equivalent to <em>BoardId</em>. Nevertheless having argument names that only differ by name case is not a good idea.</p>
+</blockquote>
+<h3 id="basic-functions-for-querying-arguments">Basic functions for querying arguments</h3>
+<p>The function <strong>afb_req_value</strong> is defined here after:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Gets from the request &#39;req&#39; the string value of the argument of &#39;name&#39;.</span>
+<span class="co"> * Returns NULL if when there is no argument of &#39;name&#39;.</span>
+<span class="co"> * Returns the value of the argument of &#39;name&#39; otherwise.</span>
+<span class="co"> *</span>
+<span class="co"> * Shortcut for: afb_req_get(req, name).value</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="kw">inline</span> <span class="dt">const</span> <span class="dt">char</span> *afb_req_value(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *name)
+{
+    <span class="kw">return</span> afb_req_get(req, name).value;
+}</code></pre>
+<p>It is defined as a shortcut to call the function <strong>afb_req_get</strong>. That function is defined here after:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Gets from the request &#39;req&#39; the argument of &#39;name&#39;.</span>
+<span class="co"> * Returns a PLAIN structure of type &#39;struct afb_arg&#39;.</span>
+<span class="co"> * When the argument of &#39;name&#39; is not found, all fields of result are set to NULL.</span>
+<span class="co"> * When the argument of &#39;name&#39; is found, the fields are filled,</span>
+<span class="co"> * in particular, the field &#39;result.name&#39; is set to &#39;name&#39;.</span>
+<span class="co"> *</span>
+<span class="co"> * There is a special name value: the empty string.</span>
+<span class="co"> * The argument of name &quot;&quot; is defined only if the request was made using</span>
+<span class="co"> * an HTTP POST of Content-Type &quot;application/json&quot;. In that case, the</span>
+<span class="co"> * argument of name &quot;&quot; receives the value of the body of the HTTP request.</span>
+<span class="co"> */</span>
+<span class="kw">struct</span> afb_arg afb_req_get(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *name);</code></pre>
+<p>That function takes 2 parameters: the request and the name of the argument to retrieve. It returns a PLAIN structure of type <strong>struct afb_arg</strong>.</p>
+<p>There is a special name that is defined when the request is of type HTTP/POST with a Content-Type being application/json. This name is <strong>&quot;&quot;</strong> (the empty string). In that case, the value of this argument of empty name is the string received as a body of the post and is supposed to be a JSON string.</p>
+<p>The definition of <strong>struct afb_arg</strong> is:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Describes an argument (or parameter) of a request</span>
+<span class="co"> */</span>
+<span class="kw">struct</span> afb_arg {
+    <span class="dt">const</span> <span class="dt">char</span> *name;   <span class="co">/* name of the argument or NULL if invalid */</span>
+    <span class="dt">const</span> <span class="dt">char</span> *value;  <span class="co">/* string representation of the value of the argument */</span>
+                <span class="co">/* original filename of the argument if path != NULL */</span>
+    <span class="dt">const</span> <span class="dt">char</span> *path;   <span class="co">/* if not NULL, path of the received file for the argument */</span>
+                <span class="co">/* when the request is finalized this file is removed */</span>
+};</code></pre>
+<p>The structure returns the data arguments that are known for the request. This data include a field named <strong>path</strong>. This <strong>path</strong> can be accessed using the function <strong>afb_req_path</strong> defined here after:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Gets from the request &#39;req&#39; the path for file attached to the argument of &#39;name&#39;.</span>
+<span class="co"> * Returns NULL if when there is no argument of &#39;name&#39; or when there is no file.</span>
+<span class="co"> * Returns the path of the argument of &#39;name&#39; otherwise.</span>
+<span class="co"> *</span>
+<span class="co"> * Shortcut for: afb_req_get(req, name).path</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="kw">inline</span> <span class="dt">const</span> <span class="dt">char</span> *afb_req_path(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *name)
+{
+    <span class="kw">return</span> afb_req_get(req, name).path;
+}</code></pre>
+<p>The path is only defined for HTTP/POST requests that send file.</p>
+<h3 id="arguments-for-received-files">Arguments for received files</h3>
+<p>As it is explained above, clients can send files using HTTP/POST requests.</p>
+<p>Received files are attached to &quot;file&quot; argument name. For example, the following HTTP fragment (from test/sample-post.html) will send an HTTP/POST request to the method <strong>post/upload-image</strong> with 2 arguments named <em>file</em> and <em>hidden</em>.</p>
+<pre class="sourceCode html"><code class="sourceCode html"><span class="kw">&lt;h2&gt;</span>Sample Post File<span class="kw">&lt;/h2&gt;</span>
+<span class="kw">&lt;form</span><span class="ot"> enctype=</span><span class="st">&quot;multipart/form-data&quot;</span><span class="kw">&gt;</span>
+    <span class="kw">&lt;input</span><span class="ot"> type=</span><span class="st">&quot;file&quot;</span><span class="ot"> name=</span><span class="st">&quot;file&quot;</span> <span class="kw">/&gt;</span>
+    <span class="kw">&lt;input</span><span class="ot"> type=</span><span class="st">&quot;hidden&quot;</span><span class="ot"> name=</span><span class="st">&quot;hidden&quot;</span><span class="ot"> value=</span><span class="st">&quot;bollobollo&quot;</span> <span class="kw">/&gt;</span>
+    <span class="kw">&lt;br&gt;</span>
+    <span class="kw">&lt;button</span><span class="ot"> formmethod=</span><span class="st">&quot;POST&quot;</span><span class="ot"> formaction=</span><span class="st">&quot;api/post/upload-image&quot;</span><span class="kw">&gt;</span>Post File<span class="kw">&lt;/button&gt;</span>
+<span class="kw">&lt;/form&gt;</span></code></pre>
+<p>Argument named <strong>file</strong> should have both its value and path defined.</p>
+<p>The value is the name of the file as it was set by the HTTP client. Generally it is the filename on client side.</p>
+<p>The path is the effective path of saved file on the temporary local storage area of the application. This is a randomly generated and unique filename. It is not linked with the original filename as used on client side.</p>
+<p>After success the binding can use the uploaded file directly from local storage path with no restriction: read, write, remove, copy, rename... Nevertheless when request reply is set and query terminated, the uploaded temporary file at path is destroyed.</p>
+<h3 id="arguments-as-a-json-object">Arguments as a JSON object</h3>
+<p>Bindings may also request every arguments of a given call as one single object. This feature is provided by the function <strong>afb_req_json</strong> defined here after:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Gets from the request &#39;req&#39; the json object hashing the arguments.</span>
+<span class="co"> * The returned object must not be released using &#39;json_object_put&#39;.</span>
+<span class="co"> */</span>
+<span class="kw">struct</span> json_object *afb_req_json(<span class="kw">struct</span> afb_req req);</code></pre>
+<p>It returns a json object. This object depends on how the request was built:</p>
+<ul>
+<li><p>For HTTP requests, this json object uses key names mapped on argument name. Values are either string for common arguments or object ie: { &quot;file&quot;: &quot;...&quot;, &quot;path&quot;: &quot;...&quot; }</p></li>
+<li><p>For WebSockets requests, returned directly the object as provided by the client.</p></li>
+</ul>
+<blockquote>
+<p>In fact, for Websockets requests, the function <strong>afb_req_value</strong> can be seen as a shortcut to <strong><em>json_object_get_string(json_object_object_get(afb_req_json(req), name))</em></strong></p>
+</blockquote>
+<h2 id="initialisation-of-the-binding-and-declaration-of-methods">Initialisation of the binding and declaration of methods</h2>
+<p>To be active, binding's methods should be declared to afb-daemon. Furthermore, the binding itself must be recorded.</p>
+<p>The registration mechanism is very basic: when afb-need starts, it loads all bindings listed in: command line or configuration file.</p>
+<p>Loading a binding follows the following steps:</p>
+<ol type="1">
+<li><p>Afb-daemon loads the binding with <em>dlopen</em>.</p></li>
+<li><p>Afb-daemon searches for a symbol named <strong>afbBindingV1Register</strong> using <em>dlsym</em>. This symbol is assumed to be the exported initialisation function of the binding.</p></li>
+<li><p>Afb-daemon builds an interface object for the binding.</p></li>
+<li><p>Afb-daemon calls the found function <strong>afbBindingV1Register</strong> with interface pointer as parameter.</p></li>
+<li><p>Function <strong>afbBindingV1Register</strong> setups the binding and initialises it.</p></li>
+<li><p>Function <strong>afbBindingV1Register</strong> returns the pointer to a structure describing the binding: version, name (prefix or API name), and list of methods.</p></li>
+<li><p>Afb-daemon checks that the returned version and name can be managed. If so, binding and its methods are register to become usable as soon as afb-daemon initialisation is finished.</p></li>
+</ol>
+<p>Here after the code used for <strong>afbBindingV1Register</strong> from binding <em>tic-tac-toe</em>:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * activation function for registering the binding called by afb-daemon</span>
+<span class="co"> */</span>
+<span class="dt">const</span> <span class="kw">struct</span> afb_binding *afbBindingV1Register(<span class="dt">const</span> <span class="kw">struct</span> afb_binding_interface *itf)
+{
+   afbitf = itf;         <span class="co">// records the interface for accessing afb-daemon</span>
+   <span class="kw">return</span> &amp;binding_description;  <span class="co">// returns the description of the binding</span>
+}</code></pre>
+<p>It is a very minimal initialisation function because <em>tic-tac-toe</em> binding doesn't have any application related initialisation step. It merely record daemon's interface and returns its description.</p>
+<p>The variable <strong>afbitf</strong> is a binding global variable. It keeps the interface to afb-daemon that should be used for logging and pushing events. Here is its declaration:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * the interface to afb-daemon</span>
+<span class="co"> */</span>
+<span class="dt">const</span> <span class="kw">struct</span> afb_binding_interface *afbitf;</code></pre>
+<p>The description of the binding is defined here after.</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * array of the methods exported to afb-daemon</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="dt">const</span> <span class="kw">struct</span> afb_verb_desc_v1 binding_methods[] = {
+   <span class="co">/* VERB&#39;S NAME     SESSION MANAGEMENT          FUNCTION TO CALL  SHORT DESCRIPTION */</span>
+   { .name= <span class="st">&quot;new&quot;</span>,   .session= AFB_SESSION_NONE, .callback= new,   .info= <span class="st">&quot;Starts a new game&quot;</span> },
+   { .name= <span class="st">&quot;play&quot;</span>,  .session= AFB_SESSION_NONE, .callback= play,  .info= <span class="st">&quot;Asks the server to play&quot;</span> },
+   { .name= <span class="st">&quot;move&quot;</span>,  .session= AFB_SESSION_NONE, .callback= move,  .info= <span class="st">&quot;Tells the client move&quot;</span> },
+   { .name= <span class="st">&quot;board&quot;</span>, .session= AFB_SESSION_NONE, .callback= board, .info= <span class="st">&quot;Get the current board&quot;</span> },
+   { .name= <span class="st">&quot;level&quot;</span>, .session= AFB_SESSION_NONE, .callback= level, .info= <span class="st">&quot;Set the server level&quot;</span> },
+   { .name= <span class="st">&quot;join&quot;</span>,  .session= AFB_SESSION_CHECK,.callback= join,  .info= <span class="st">&quot;Join a board&quot;</span> },
+   { .name= <span class="st">&quot;undo&quot;</span>,  .session= AFB_SESSION_NONE, .callback= undo,  .info= <span class="st">&quot;Undo the last move&quot;</span> },
+   { .name= <span class="st">&quot;wait&quot;</span>,  .session= AFB_SESSION_NONE, .callback= wait,  .info= <span class="st">&quot;Wait for a change&quot;</span> },
+   { .name= NULL } <span class="co">/* marker for end of the array */</span>
+};
+
+<span class="co">/*</span>
+<span class="co"> * description of the binding for afb-daemon</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="dt">const</span> <span class="kw">struct</span> afb_binding binding_description =
+{
+   <span class="co">/* description conforms to VERSION 1 */</span>
+   .type= AFB_BINDING_VERSION_1,
+   .v1= {               <span class="co">/* fills the v1 field of the union when AFB_BINDING_VERSION_1 */</span>
+      .prefix= <span class="st">&quot;tictactoe&quot;</span>,     <span class="co">/* the API name (or binding name or prefix) */</span>
+      .info= <span class="st">&quot;Sample tac-tac-toe game&quot;</span>, <span class="co">/* short description of of the binding */</span>
+      .methods = binding_methods        <span class="co">/* the array describing the methods of the API */</span>
+   }
+};</code></pre>
+<p>The structure <strong>binding_description</strong> describes the binding. It declares the type and version of the binding, its name, a short description and its methods list.</p>
+<p>The list of methods is an array of structures describing the methods and terminated by a NULL marker.</p>
+<p>In version one of afb-damon binding, a method description contains 4 fields:</p>
+<ul>
+<li><p>the name of the method,</p></li>
+<li><p>the session management flags,</p></li>
+<li><p>the implementation function to be call for the method,</p></li>
+<li><p>a short description.</p></li>
+</ul>
+<p>The structure describing methods is defined as follows:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Description of one method of the API provided by the binding</span>
+<span class="co"> * This enumeration is valid for bindings of type 1</span>
+<span class="co"> */</span>
+<span class="kw">struct</span> afb_verb_desc_v1
+{
+       <span class="dt">const</span> <span class="dt">char</span> *name;                       <span class="co">/* name of the method */</span>
+       <span class="kw">enum</span> AFB_session_v1 session;            <span class="co">/* authorisation and session requirements of the method */</span>
+       <span class="dt">void</span> (*callback)(<span class="kw">struct</span> afb_req req);   <span class="co">/* callback function implementing the method */</span>
+       <span class="dt">const</span> <span class="dt">char</span> *info;                       <span class="co">/* textual description of the method */</span>
+};</code></pre>
+<p>For technical reasons, the enumeration <strong>enum AFB_session_v1</strong> is not exactly an enumeration but the wrapper of constant definitions that can be mixed using bitwise or (the C operator |).</p>
+<p>The constants that can bit mixed are:</p>
+<table>
+<thead>
+<tr class="header">
+<th style="text-align: left;">Constant name</th>
+<th style="text-align: left;">Meaning</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: left;"><strong>AFB_SESSION_CREATE</strong></td>
+<td style="text-align: left;">Equals to AFB_SESSION_LOA_EQ_0</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;"><strong>AFB_SESSION_CLOSE</strong></td>
+<td style="text-align: left;">Closes the session after the reply and set the LOA to 0</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;"><strong>AFB_SESSION_RENEW</strong></td>
+<td style="text-align: left;">Refreshes the token of authentification</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;"><strong>AFB_SESSION_CHECK</strong></td>
+<td style="text-align: left;">Just requires the token authentification</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_LE_0</strong></td>
+<td style="text-align: left;">Requires the current LOA to be lesser then or equal to 0</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_LE_1</strong></td>
+<td style="text-align: left;">Requires the current LOA to be lesser then or equal to 1</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_LE_2</strong></td>
+<td style="text-align: left;">Requires the current LOA to be lesser then or equal to 2</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_LE_3</strong></td>
+<td style="text-align: left;">Requires the current LOA to be lesser then or equal to 3</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_GE_0</strong></td>
+<td style="text-align: left;">Requires the current LOA to be greater then or equal to 0</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_GE_1</strong></td>
+<td style="text-align: left;">Requires the current LOA to be greater then or equal to 1</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_GE_2</strong></td>
+<td style="text-align: left;">Requires the current LOA to be greater then or equal to 2</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_GE_3</strong></td>
+<td style="text-align: left;">Requires the current LOA to be greater then or equal to 3</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_EQ_0</strong></td>
+<td style="text-align: left;">Requires the current LOA to be equal to 0</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_EQ_1</strong></td>
+<td style="text-align: left;">Requires the current LOA to be equal to 1</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_EQ_2</strong></td>
+<td style="text-align: left;">Requires the current LOA to be equal to 2</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;"><strong>AFB_SESSION_LOA_EQ_3</strong></td>
+<td style="text-align: left;">Requires the current LOA to be equal to 3</td>
+</tr>
+</tbody>
+</table>
+<p>If any of this flag is set, afb-daemon requires an authentication token as if <strong>AFB_SESSION_CHECK</strong> flag was also set.</p>
+<p>The special value <strong>AFB_SESSION_NONE</strong> is zero and can be used to bypass token check.</p>
+<blockquote>
+<p>Note that <strong>AFB_SESSION_CREATE</strong> and <strong>AFB_SESSION_CLOSE</strong> might be removed in later versions.</p>
+</blockquote>
+<h2 id="sending-messages-to-the-log-system">Sending messages to the log system</h2>
+<p>Afb-daemon provides 4 levels of verbosity and 5 methods for logging messages.</p>
+<p>The verbosity is managed. Options allow the change the verbosity of afb-daemon and the verbosity of the bindings can be set binding by binding.</p>
+<p>The methods for logging messages are defined as macros that test the verbosity level and that call the real logging function only if the message must be output. This avoid evaluation of arguments of the formatting messages if the message must not be output.</p>
+<h3 id="verbs-for-logging-messages">Verbs for logging messages</h3>
+<p>The 5 logging methods are:</p>
+<table>
+<thead>
+<tr class="header">
+<th style="text-align: left;">Macro</th>
+<th style="text-align: center;">Verbosity</th>
+<th style="text-align: left;">Meaning</th>
+<th style="text-align: center;">syslog level</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: left;">ERROR</td>
+<td style="text-align: center;">0</td>
+<td style="text-align: left;">Error conditions</td>
+<td style="text-align: center;">3</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">WARNING</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: left;">Warning conditions</td>
+<td style="text-align: center;">4</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">NOTICE</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: left;">Normal but significant condition</td>
+<td style="text-align: center;">5</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">INFO</td>
+<td style="text-align: center;">2</td>
+<td style="text-align: left;">Informational</td>
+<td style="text-align: center;">6</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">DEBUG</td>
+<td style="text-align: center;">3</td>
+<td style="text-align: left;">Debug-level messages</td>
+<td style="text-align: center;">7</td>
+</tr>
+</tbody>
+</table>
+<p>You can note that the 2 methods <strong>WARNING</strong> and <strong>INFO</strong> have the same level of verbosity. But they don't have the same <em>syslog level</em>. It means that they are output with a different level on the logging system.</p>
+<p>All of these methods have the same signature:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="dt">void</span> ERROR(<span class="dt">const</span> <span class="kw">struct</span> afb_binding_interface *afbitf, <span class="dt">const</span> <span class="dt">char</span> *message, ...);</code></pre>
+<p>The first argument <strong>afbitf</strong> is the interface to afb daemon that the binding received at initialisation time when <strong>afbBindingV1Register</strong> is called.</p>
+<p>The second argument <strong>message</strong> is a formatting string compatible with printf/sprintf.</p>
+<p>The remaining arguments are arguments of the formating message like with printf.</p>
+<h3 id="managing-verbosity">Managing verbosity</h3>
+<p>Depending on the level of verbosity, the messages are output or not. The following table explains what messages will be output depending ont the verbosity level.</p>
+<table>
+<thead>
+<tr class="header">
+<th style="text-align: center;">Level of verbosity</th>
+<th style="text-align: left;">Outputed macro</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: center;">0</td>
+<td style="text-align: left;">ERROR</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">1</td>
+<td style="text-align: left;">ERROR + WARNING + NOTICE</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">2</td>
+<td style="text-align: left;">ERROR + WARNING + NOTICE + INFO</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">3</td>
+<td style="text-align: left;">ERROR + WARNING + NOTICE + INFO + DEBUG</td>
+</tr>
+</tbody>
+</table>
+<h3 id="output-format-and-destination">Output format and destination</h3>
+<p>The syslog level is used for forging a prefix to the message. The prefixes are:</p>
+<table>
+<thead>
+<tr class="header">
+<th style="text-align: center;">syslog level</th>
+<th style="text-align: left;">prefix</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: center;">0</td>
+<td style="text-align: left;">&lt;0&gt; EMERGENCY</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">1</td>
+<td style="text-align: left;">&lt;1&gt; ALERT</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">2</td>
+<td style="text-align: left;">&lt;2&gt; CRITICAL</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">3</td>
+<td style="text-align: left;">&lt;3&gt; ERROR</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">4</td>
+<td style="text-align: left;">&lt;4&gt; WARNING</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">5</td>
+<td style="text-align: left;">&lt;5&gt; NOTICE</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">6</td>
+<td style="text-align: left;">&lt;6&gt; INFO</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">7</td>
+<td style="text-align: left;">&lt;7&gt; DEBUG</td>
+</tr>
+</tbody>
+</table>
+<p>The message is pushed to standard error. The final destination of the message depends on how systemd service was configured through its variable <strong>StandardError</strong>. It can be journal, syslog or kmsg. (See man sd-daemon).</p>
+<h2 id="sending-events">Sending events</h2>
+<p>Since version 0.5, bindings can broadcast events to any potential listener. As today only unattended even are supported. Targeted events are expected for next coming version.</p>
+<p>The binding <em>tic-tac-toe</em> broadcasts events when the board changes. This is done in the function <strong>changed</strong>:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * signals a change of the board</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="dt">void</span> changed(<span class="kw">struct</span> board *board, <span class="dt">const</span> <span class="dt">char</span> *reason)
+{
+    ...
+    <span class="kw">struct</span> json_object *description;
+
+    <span class="co">/* get the description */</span>
+    description = describe(board);
+
+    ...
+
+    afb_daemon_broadcast_event(afbitf-&gt;daemon, reason, description);
+}</code></pre>
+<p>The description of the changed board is pushed via the daemon interface.</p>
+<p>Within binding <em>tic-tac-toe</em>, <em>reason</em> indicates the origin of the change. In function <strong>afb_daemon_broadcast_event</strong> the second parameter is the name of broadcasted event. The third argument is the object that is transmitted with the event.</p>
+<p>Function <strong>afb_daemon_broadcast_event</strong> is defined here after:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * Broadcasts widely the event of &#39;name&#39; with the data &#39;object&#39;.</span>
+<span class="co"> * &#39;object&#39; can be NULL.</span>
+<span class="co"> * &#39;daemon&#39; MUST be the daemon given in interface when activating the binding.</span>
+<span class="co"> *</span>
+<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;object&#39;.</span>
+<span class="co"> * Thus, in the case where &#39;object&#39; should remain available after</span>
+<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
+<span class="co"> */</span>
+<span class="dt">void</span> afb_daemon_broadcast_event(<span class="kw">struct</span> afb_daemon daemon, <span class="dt">const</span> <span class="dt">char</span> *name, <span class="kw">struct</span> json_object *object);</code></pre>
+<blockquote>
+<p>Be aware, as with reply functions <strong>object</strong> is automatically released using <strong>json_object_put</strong> when using this function. Call <strong>json_object_get</strong> before calling <strong>afb_daemon_broadcast_event</strong> to keep <strong>object</strong> available after function returns.</p>
+</blockquote>
+<p>Event name received by listeners is prefixed with binding name. So when a change occurs after a move, the reason is <strong>move</strong> and every clients receive an event <strong>tictactoe/move</strong>.</p>
+<blockquote>
+<p>Note that nothing is said about case sensitivity of event names. However, the event is always prefixed with the name that the binding declared, with the same case, followed with a slash /. Thus it is safe to compare event using a case sensitive comparison.</p>
+</blockquote>
+<h2 id="writing-an-asynchronous-method-implementation">Writing an asynchronous method implementation</h2>
+<p>The <em>tic-tac-toe</em> example allows two clients or more to share the same board. This is implemented by the method <strong>join</strong> that illustrated partly how to retrieve arguments.</p>
+<p>When two or more clients are sharing a same board, one of them can wait until the state of the board changes, but this could also be implemented using events because an even is generated each time the board changes.</p>
+<p>In this case, the reply to the wait is sent only when the board changes. See the diagram below:</p>
+<pre><code>CLIENT A       CLIENT B         TIC-TAC-TOE
+   |              |                  |
+   +--------------|-----------------&gt;| wait . . . . . . . .
+   |              |                  |                     .
+   :              :                  :                      .
+   :              :                  :                      .
+   |              |                  |                      .
+   |              +-----------------&gt;| move . . .           .
+   |              |                  |          V           .
+   |              |&lt;-----------------+ success of move      .
+   |              |                  |                    .
+   |&lt;-------------|------------------+ success of wait  &lt;</code></pre>
+<p>Here, this is an invocation of the binding by an other client that unblock the suspended <em>wait</em> call. Nevertheless in most case this should be a timer, a hardware event, a sync with a concurrent process or thread, ...</p>
+<p>Common case of an asynchronous implementation.</p>
+<p>Here is the listing of the function <strong>wait</strong>:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="dt">static</span> <span class="dt">void</span> wait(<span class="kw">struct</span> afb_req req)
+{
+    <span class="kw">struct</span> board *board;
+    <span class="kw">struct</span> waiter *waiter;
+
+    <span class="co">/* retrieves the context for the session */</span>
+    board = board_of_req(req);
+    INFO(afbitf, <span class="st">&quot;method &#39;wait&#39; called for boardid %d&quot;</span>, board-&gt;id);
+
+    <span class="co">/* creates the waiter and enqueues it */</span>
+    waiter = calloc(<span class="dv">1</span>, <span class="kw">sizeof</span> *waiter);
+    waiter-&gt;req = req;
+    waiter-&gt;next = board-&gt;waiters;
+    afb_req_addref(req);
+    board-&gt;waiters = waiter;
+}</code></pre>
+<p>After retrieving the board, the function adds a new waiter to waiters list and returns without setting a reply.</p>
+<p>Before returning, it increases <strong>req</strong> request's reference count using <strong>afb_req_addref</strong> function.</p>
+<blockquote>
+<p>When a method returns without setting a reply, it <strong>MUST</strong> increment request's reference count using <strong>afb_req_addref</strong>. If unpredictable behaviour may pop up.</p>
+</blockquote>
+<p>Later, when a board changes, it calls <em>tic-tac-toe</em> <strong>changed</strong> function with reason of change in parameter.</p>
+<p>Here is the full listing of the function <strong>changed</strong>:</p>
+<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
+<span class="co"> * signals a change of the board</span>
+<span class="co"> */</span>
+<span class="dt">static</span> <span class="dt">void</span> changed(<span class="kw">struct</span> board *board, <span class="dt">const</span> <span class="dt">char</span> *reason)
+{
+    <span class="kw">struct</span> waiter *waiter, *next;
+    <span class="kw">struct</span> json_object *description;
+
+    <span class="co">/* get the description */</span>
+    description = describe(board);
+
+    waiter = board-&gt;waiters;
+    board-&gt;waiters = NULL;
+    <span class="kw">while</span> (waiter != NULL) {
+        next = waiter-&gt;next;
+        afb_req_success(waiter-&gt;req, json_object_get(description), reason);
+        afb_req_unref(waiter-&gt;req);
+        free(waiter);
+        waiter = next;
+    }
+
+    afb_event_sender_push(afb_daemon_get_event_sender(afbitf-&gt;daemon), reason, description);
+}</code></pre>
+<p>The list of waiters is walked and a reply is sent to each waiter. After sending the reply, the reference count of the request is decremented using <strong>afb_req_unref</strong> to allow resources to be freed.</p>
+<blockquote>
+<p>The reference count <strong>MUST</strong> be decremented using <strong>afb_req_unref</strong> to free resources and avoid memory leaks. This usage count decrement should happen <strong>AFTER</strong> setting reply or bad things may happen.</p>
+</blockquote>
+<h2 id="how-to-build-a-binding">How to build a binding</h2>
+<p>Afb-daemon provides a <em>pkg-config</em> configuration file that can be queried by providing <strong>afb-daemon</strong> in command line arguments. This configuration file provides data that should be used for bindings compilation. Examples:</p>
+<pre class="sourceCode bash"><code class="sourceCode bash">$ <span class="kw">pkg-config</span> --cflags afb-daemon
+$ <span class="kw">pkg-config</span> --libs afb-daemon</code></pre>
+<h3 id="example-for-cmake-meta-build-system">Example for cmake meta build system</h3>
+<p>This example is the extract for building the binding <em>afm-main</em> using <em>CMAKE</em>.</p>
+<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="fu">pkg_check_modules</span>(afb afb-daemon)
+<span class="kw">if</span>(afb_FOUND)
+    <span class="kw">message</span>(<span class="ot">STATUS</span> <span class="st">&quot;Creation afm-main-binding for AFB-DAEMON&quot;</span>)
+    <span class="kw">add_library</span>(afm-main-binding <span class="ot">MODULE</span> afm-main-binding.c)
+    <span class="kw">target_compile_options</span>(afm-main-binding <span class="ot">PRIVATE</span> <span class="dv">${afb_CFLAGS}</span>)
+    <span class="kw">target_include_directories</span>(afm-main-binding <span class="ot">PRIVATE</span> <span class="dv">${afb_INCLUDE_DIRS}</span>)
+    <span class="kw">target_link_libraries</span>(afm-main-binding utils <span class="dv">${afb_LIBRARIES}</span>)
+    <span class="kw">set_target_properties</span>(afm-main-binding <span class="ot">PROPERTIES</span>
+        <span class="ot">PREFIX</span> <span class="st">&quot;&quot;</span>
+        <span class="ot">LINK_FLAGS</span> <span class="st">&quot;-Wl,--version-script=</span><span class="dv">${CMAKE_CURRENT_SOURCE_DIR}</span><span class="st">/afm-main-binding.export-map&quot;</span>
+    )
+    <span class="kw">install</span>(<span class="ot">TARGETS</span> afm-main-binding <span class="ot">LIBRARY</span> <span class="ot">DESTINATION</span> <span class="dv">${binding_dir}</span>)
+<span class="kw">else</span>()
+    <span class="kw">message</span>(<span class="ot">STATUS</span> <span class="st">&quot;Not creating the binding for AFB-DAEMON&quot;</span>)
+<span class="kw">endif</span>()</code></pre>
+<p>Let now describe some of these lines.</p>
+<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="fu">pkg_check_modules</span>(afb afb-daemon)</code></pre>
+<p>This first lines searches to the <em>pkg-config</em> configuration file for <strong>afb-daemon</strong>. Resulting data are stored in the following variables:</p>
+<table>
+<thead>
+<tr class="header">
+<th style="text-align: left;">Variable</th>
+<th style="text-align: left;">Meaning</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: left;">afb_FOUND</td>
+<td style="text-align: left;">Set to 1 if afb-daemon binding development files exist</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">afb_LIBRARIES</td>
+<td style="text-align: left;">Only the libraries (w/o the '-l') for compiling afb-daemon bindings</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">afb_LIBRARY_DIRS</td>
+<td style="text-align: left;">The paths of the libraries (w/o the '-L') for compiling afb-daemon bindings</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">afb_LDFLAGS</td>
+<td style="text-align: left;">All required linker flags for compiling afb-daemon bindings</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">afb_INCLUDE_DIRS</td>
+<td style="text-align: left;">The '-I' preprocessor flags (w/o the '-I') for compiling afb-daemon bindings</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">afb_CFLAGS</td>
+<td style="text-align: left;">All required cflags for compiling afb-daemon bindings</td>
+</tr>
+</tbody>
+</table>
+<p>If development files are found, the binding can be added to the set of target to build.</p>
+<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="kw">add_library</span>(afm-main-binding <span class="ot">MODULE</span> afm-main-binding.c)</code></pre>
+<p>This line asks to create a shared library having a single source file named afm-main-binding.c to be compiled. The default name of the created shared object is <strong>libafm-main-binding.so</strong>.</p>
+<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="kw">set_target_properties</span>(afm-main-binding <span class="ot">PROPERTIES</span>
+    <span class="ot">PREFIX</span> <span class="st">&quot;&quot;</span>
+    <span class="ot">LINK_FLAGS</span> <span class="st">&quot;-Wl,--version-script=</span><span class="dv">${CMAKE_CURRENT_SOURCE_DIR}</span><span class="st">/afm-main-binding.export-map&quot;</span>
+)</code></pre>
+<p>This lines are doing two things:</p>
+<ol type="1">
+<li><p>It renames the built library from <strong>libafm-main-binding.so</strong> to <strong>afm-main-binding.so</strong> by removing the implicitly added prefix <em>lib</em>. This step is not mandatory because afb-daemon doesn't check names of files at load time. The only filename convention used by afb-daemon relates to <strong>.so</strong> termination. *.so pattern is used when afb-daemon automatically discovers binding from a directory hierarchy.</p></li>
+<li><p>It applies a version script at link time to only export the reserved name <strong>afbBindingV1Register</strong> for registration entry point. By default, when building a shared library linker exports all the public symbols (C functions that are not <strong>static</strong>).</p></li>
+</ol>
+<p>Next line are:</p>
+<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="kw">target_include_directories</span>(afm-main-binding <span class="ot">PRIVATE</span> <span class="dv">${afb_INCLUDE_DIRS}</span>)
+<span class="kw">target_link_libraries</span>(afm-main-binding utils <span class="dv">${afb_LIBRARIES}</span>)</code></pre>
+<p>As you can see it uses the variables computed by <strong><em>pkg_check_modules(afb afb-daemon)</em></strong> to configure the compiler and the linker.</p>
+<h3 id="exporting-the-function-afbbindingv1register">Exporting the function afbBindingV1Register</h3>
+<p>The function <strong>afbBindingV1Register</strong> MUST be exported. This can be achieved using a version script at link time. Here after is a version script used for <em>tic-tac-toe</em> (bindings/samples/export.map).</p>
+<pre><code>{ global: afbBindingV1Register; local: *; };</code></pre>
+<p>This sample <a href="https://sourceware.org/binutils/docs-2.26/ld/VERSION.html#VERSION">version script</a> exports as global the symbol <em>afbBindingV1Register</em> and hides any other symbols.</p>
+<p>This version script is added to the link options using the option <strong>--version-script=export.map</strong> is given directly to the linker or using the option <strong>-Wl,--version-script=export.map</strong> when the option is given to the C compiler.</p>
+<h3 id="building-within-yocto">Building within yocto</h3>
+<p>Adding a dependency to afb-daemon is enough. See below:</p>
+<pre><code>DEPENDS += &quot; afb-daemon &quot;</code></pre>
+</body>
+</html>
diff --git a/doc/afb-bindings-writing.md b/doc/afb-bindings-writing.md
new file mode 100644
index 00000000..9efc5bd3
--- /dev/null
+++ b/doc/afb-bindings-writing.md
@@ -0,0 +1,1227 @@
+HOWTO WRITE a BINDING for AFB-DAEMON
+===================================
+    version: 1
+    Date:    09 juin 2016
+    Author:  José Bollo
+
+
+
+Summary
+-------
+
+Afb-daemon binders serve files through HTTP protocol
+and offers to developers the capability to expose application API methods through
+HTTP or WebSocket protocol.
+
+Binder bindings are used to add API to afb-daemon.
+This part describes how to write a binding for afb-daemon.
+
+Excepting this summary, this document target developers.
+
+Before moving further through an example, here after
+a short overview of binder bindings fundamentals.
+
+### Nature of a binding
+
+A binding is an independent piece of software. A binding is self contain and exposes application logic as sharable library.
+A binding is intended to be dynamically loaded by afb-daemon to expose application API.
+
+Technically, a binder binding does not reference and is not linked with any afb-daemon library.
+
+### Class of bindings
+
+Application binder supports two kinds of bindings: application bindings and service bindings.
+Technically both class of binding are equivalent are use the same coding convention. Only sharing mode and security context diverge.
+
+#### Application-bindings
+
+Application-bindings implements the glue in between application's UI and services. Every AGL application
+has a corresponding binder that typically activates one or many bindings to interface the application logic with lower platform services.
+When an application is started by the AGL application framework, a dedicate binder is started that loads/activates application binding(s). 
+API expose by application-binding are executed within corresponding application security context.
+
+Application bindings generally handle a unique context for a unique client. As the application framework start
+a dedicated instance of afb_daemon for each AGL application, if a given binding is used within multiple application each of those
+application get a new and private instance of eventually "shared" binding.
+
+#### Service-bindings
+
+Service-bindings enable API activation within corresponding service security context and not within calling application context. 
+Service-bindings are intended to run as a unique instance. Service-bindings can be shared in between multiple clients.
+
+Service-bindings can either be stateless or manage client context. When managing context each client get a private context.
+
+Sharing may either be global to the platform (ie: GPS service) or dedicated to a given user (ie: user preferences)
+ 
+### Live cycle of bindings within afb-daemon
+
+Application and service bindings are loaded and activated each time a new afb-daemon is started.
+
+At launch time, every loaded binding initialise itself.
+If a single binding initialisation fail corresponding instance of afb-daemon self aborts.
+
+Conversely, when a binding initialisation succeeds, it should register 
+its unique name as well as the list of verbs attached to the methods it exposes.
+
+When initialised, on request from application clients to the right API/verb, binding methods
+are activated by the afb-daemon attached to the application or service.
+
+At exit time, no special action is enforced by afb-daemon. When a specific actions is required at afb-daemon stop,
+developers should use 'atexit/on_exit' during binding initialisation sequence to register a custom exit function.
+
+### Binding Contend
+
+Afb-daemon's binding register two classes of objects: names and functions.
+
+Bindings declare categories of names:
+ - A unique binding name to access all API expose by this binding,
+ - One name for each methods/verbs provided by this binding.
+
+Bindings declare two categories of functions:
+ - function use for the initialisation
+ - functions implementing exposed API methods
+
+Afb-daemon parses URI requests to extract the API(binding name) and the VERB(method to activate).
+As an example, URI **foo/bar** translates to binding named **foo** and method named **bar**.
+To serve such a request, afb-daemon looks for an active binding named **foo** and then within this binding for a method named **bar**.
+When find afb-daemon calls corresponding method with attached parameter if any.
+
+Afb-daemon ignores letter case when parsing URI. Thus **TicTacToe/Board** and **tictactoe/board** are equivalent.
+
+#### The name of the binding
+
+The name of a given binding is also known as the name
+of the API prefix that defines the binding.
+
+The name of a binding SHOULD be unique within a given afb-daemon instance.
+
+For example, when a client of afb-daemon calls a URI named **foo/bar**. Afb-daemon
+extracts the prefix **foo** and the suffix **bar**. **foo** must match a binding name and **bar** a VERB attached to some method.
+
+#### Names of methods
+
+Each binding exposes a set of methods that can be called
+by the clients of a given afb-daemon.
+
+VERB's name attached to a given binding (API) MUST be unique within a binding.
+
+Bindings static declaration link VERBS to corresponding methods. 
+When clients emit requests on a given API/VERB corresponding method is called by afb-daemon.
+
+#### Initialisation function
+
+Binding's initialisation function serves several purposes.
+
+1. It allows afb-daemon to control binding version depending on initialisation function name.
+As today, the only supported initialisation function is **afbBindingV1Register**. This identifies
+version "one" of bindings.
+
+2. It allows bindings to initialise itself.
+
+3. It enables names declarations: descriptions, requirements and implementations of exposed API/VERB.
+
+#### Functions instantiation of API/VERBs
+
+When an API/VERB is called, afb-daemon constructs a request object. Then it 
+passes this request object to the implementation function corresponding to requested method, this
+within attached API binding.
+
+An implementation function receives a request object that
+is used to: get arguments of the request, send
+answer, store session data.
+
+A binding MUST set an answer to every received requests.
+
+Nevertheless it is not mandatory to set the answer
+before returning from API/VERB implementing function.
+This behaviour is important for asynchronous actions.
+
+API/VERB implementation that set an answer before returning are called *synchronous implementations*.
+Those that do not systematically set an answer before returning are called *asynchronous implementations*.
+
+Asynchronous implementations typically launch asynchronous actions. They record some context at
+request time and provide answer to the request only at completion of asynchronous actions.
+
+The Tic-Tac-Toe example
+-----------------------
+
+This part explains how to write an afb-binding.
+For the sake of being practical it uses many
+examples based on tic-tac-toe.
+This binding example is in *bindings/samples/tic-tac-toe.c*.
+
+This binding is named ***tictactoe***.
+
+Dependencies when compiling
+---------------------------
+
+Afb-daemon provides a configuration file for *pkg-config*.
+Typing the command
+
+	pkg-config --cflags afb-daemon
+
+Print flags use for compilation:
+
+	$ pkg-config --cflags afb-daemon
+	-I/opt/local/include -I/usr/include/json-c 
+
+For linking, you should use
+
+	$ pkg-config --libs afb-daemon
+	-ljson-c
+
+Afb-daemon automatically includes dependency to json-c.
+This is activated through **Requires** keyword in pkg-config.
+While almost every binding replies on **json-c** this is not a must have dependency.
+
+Internally, afb-daemon relies on **libsystemd** for its event loop, as well 
+as for its binding to D-Bus.
+Bindings developers are encouraged to leverage **libsystemd** when possible.
+Nevertheless there is no hard dependency to **libsystemd** if ever
+you rather not use it, feel free to do so.
+
+> Afb-daemon binding are fully self contain. They do not enforce dependency on any libraries from the application framework.
+> Afb-daemon dependencies requirer to run AGL bindings are given at runtime through pointers leveraging read-only
+> memory feature.
+
+Header files to include
+-----------------------
+
+Binding *tictactoe* has following includes:
+
+```C
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <json-c/json.h>
+#include <afb/afb-binding.h>
+```
+
+Header *afb/afb-binding.h* is the only hard dependency, it includes all features
+that a binding MUST HAVE. Outside of includes used to support application logic,
+common external headers used within bindings are:
+
+- *json-c/json.h*: should be include to handle json objects;
+- *systemd/sd-event.h*: should be include to access event main loop;
+- *systemd/sd-bus.h*: should be include for dbus connections.
+
+The *tictactoe* binding does not leverage systemd features, also only json.h
+is used on top of mandatory afb/afb-binding.h.
+
+When including *afb/afb-binding.h*, the macro **_GNU_SOURCE** MUST be
+defined.
+
+Choosing names
+--------------
+
+Designers of bindings should define a unique name for every API binding
+as well as for methods VERBs. They should also define names for request
+arguments passed as name/value pair in URI.
+
+While forging names, designers should respect few rules to
+ensure that created names are valid and easy to use across platforms.
+
+All names and strings are UTF-8 encoded.
+
+### Names for API (binding)
+
+Binding API name are checked.
+All characters are authorised except:
+
+- the control characters (\u0000 .. \u001f)
+- the characters of the set { ' ', '"', '#', '%', '&',
+  '\'', '/', '?', '`', '\x7f' }
+
+In other words the set of forbidden characters is
+{ \u0000..\u0020, \u0022, \u0023, \u0025..\u0027,
+  \u002f, \u003f, \u0060, \u007f }.
+
+Afb-daemon makes no distinction between lower case
+and upper case when searching for API/VERB.
+
+### Names for methods
+
+The names of methods VERBs are totally free and not checked.
+
+However, the validity rules for method's VERB name are the
+same as for Binding API name except that the dot(.) character
+is forbidden.
+
+Afb-daemon makes no case distinction when searching for an API by name.
+
+### Names for arguments
+
+Argument's name are not restricted and can be everything you wish.
+
+> Warning arguments search is case sensitive and "index" and "Index"
+> are not two different arguments.
+
+### Forging names widely available
+
+The key names of javascript object can be almost
+anything using the arrayed notation:
+
+	object[key] = value
+
+Nevertheless this is not the case with javascript dot notation:
+
+	object.key = value
+
+Using the dot notation, the key must be a valid javascript
+identifier and dash(-) as well as few other reserved characters cannot be used.
+
+For this reason, we advise developper to chose name compatible with both javascript and HTML notation.
+
+It is a good practice, even for arguments not to rely on case sensitivity.
+This may reduce headache strength at debug time, especially with interpreted language like
+javascript that may not warn you that a variable was not defined.
+
+Writing a synchronous method implementation
+-----------------------------------------
+
+The method **tictactoe/board** is a synchronous implementation.
+Here is its listing:
+
+```C
+/*
+ * get the board
+ */
+static void board(struct afb_req req)
+{
+	struct board *board;
+	struct json_object *description;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'board' called for boardid %d", board->id);
+
+	/* describe the board */
+	description = describe(board);
+
+	/* send the board's description */
+	afb_req_success(req, description, NULL);
+}
+```
+
+This example shows many aspects of a synchronous
+method implementation. Let summarise it:
+
+1. The function **board_of_req** retrieves the context stored
+for the binding: the board.
+
+2. The macro **INFO** sends a message of kind *INFO*
+to the logging system. The global variable named **afbitf**
+used represents the interface to afb-daemon.
+
+3. The function **describe** creates a json_object representing
+the board.
+
+4. The function **afb_req_success** sends the reply, attaching to
+it the object *description*.
+
+### The incoming request
+
+For any implementation, the request is received by a structure of type
+**struct afb_req**.
+
+> Note that this is a PLAIN structure, not a pointer to a structure.
+
+The definition of **struct afb_req** is:
+
+```C
+/*
+ * Describes the request by bindings from afb-daemon
+ */
+struct afb_req {
+	const struct afb_req_itf *itf;	/* the interfacing functions */
+	void *closure;			/* the closure for functions */
+};
+```
+
+It contains two pointers: first one *itf*, points to functions used
+to handle internal request. Second one *closure* point onto function closure. 
+
+> The structure must never be used directly.
+> Instead developer should use the intended functions provided
+> by afb-daemon as described here after.
+
+*req* is used to get arguments of the request, to send
+answer, to store session data.
+
+This object and its interface is defined and documented
+in the file names *afb/afb-req-itf.h*
+
+The above example uses twice *req* object request.
+
+The first time, to retrieve the board attached to the session of the request.
+
+The second time, to send the reply: an object that describes the current board.
+
+### Associating a client context to a session
+
+When *tic-tac-toe* binding receives a request, it musts get
+the board describing the game associated to the session.
+
+For a binding, having data associated to a session is common.
+This data is called "binding context" for the session.
+Within *tic-tac-toe* binding the context is the board.
+
+Requests *afb_req* offer four functions for storing and retrieving session associated context.
+
+These functions are:
+
+- **afb_req_context_get**:
+  retrieves context data stored for current binding.
+
+- **afb_req_context_set**:
+  store context data of current binding.
+
+- **afb_req_context**:
+  if exist retrieves context data of current binding.
+  if context does not yet exist, creates a new context and store it.
+
+- **afb_req_context_clear**:
+  reset the stored context data.
+
+The binding *tictactoe* use a convenient function to retrieve
+its context: the board. This function is *board_of_req*:
+
+```C
+/*
+ * retrieves the board of the request
+ */
+static inline struct board *board_of_req(struct afb_req req)
+{
+	return afb_req_context(req, (void*)get_new_board, (void*)release_board);
+}
+```
+
+The function **afb_req_context** ensures an existing context
+for the session of the request.
+Its two last arguments are functions to allocate and free context. 
+Note function type casts to avoid compilation warnings.
+
+Here is the definition of the function **afb_req_context**
+
+```C
+/*
+ * Gets the pointer stored by the binding for the session of 'req'.
+ * If the stored pointer is NULL, indicating that no pointer was
+ * already stored, afb_req_context creates a new context by calling
+ * the function 'create_context' and stores it with the freeing function
+ * 'free_context'.
+ */
+static inline void *afb_req_context(struct afb_req req, void *(*create_context)(), void (*free_context)(void*))
+{
+	void *result = afb_req_context_get(req);
+	if (result == NULL) {
+		result = create_context();
+		afb_req_context_set(req, result, free_context);
+	}
+	return result;
+}
+```
+
+The second argument if the function that creates the context.
+For binding *tic-tac-toe* (function **get_new_board**).
+The function **get_new_board** creates a new board and set usage its count to 1.
+The boards are checking usage count to free resources when not used.
+
+The third argument is a function that frees context resources.
+For binding *tic-tac-toe* (function **release_board**).
+The function **release_board** decrease usage count of the board passed in argument.
+When usage count falls to zero, data board are freed.
+
+Definition of other functions dealing with contexts:
+
+```C
+/*
+ * Gets the pointer stored by the binding for the session of 'req'.
+ * When the binding has not yet recorded a pointer, NULL is returned.
+ */
+void *afb_req_context_get(struct afb_req req);
+
+/*
+ * Stores for the binding the pointer 'context' to the session of 'req'.
+ * The function 'free_context' will be called when the session is closed
+ * or if binding stores an other pointer.
+ */
+void afb_req_context_set(struct afb_req req, void *context, void (*free_context)(void*));
+
+/*
+ * Frees the pointer stored by the binding for the session of 'req'
+ * and sets it to NULL.
+ *
+ * Shortcut for: afb_req_context_set(req, NULL, NULL)
+ */
+static inline void afb_req_context_clear(struct afb_req req)
+{
+	afb_req_context_set(req, NULL, NULL);
+}
+```
+
+### Sending reply to a request
+
+Two kinds of replies: successful or failure.
+
+> Sending a reply to a request MUST be done once and only once.
+
+It exists two functions for "success" replies: **afb_req_success** and **afb_req_success_f**.
+
+```C
+/*
+ * Sends a reply of kind success to the request 'req'.
+ * The status of the reply is automatically set to "success".
+ * Its send the object 'obj' (can be NULL) with an
+ * informationnal comment 'info (can also be NULL).
+ *
+ * For conveniency, the function calls 'json_object_put' for 'obj'.
+ * Thus, in the case where 'obj' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
+ */
+void afb_req_success(struct afb_req req, struct json_object *obj, const char *info);
+
+/*
+ * Same as 'afb_req_success' but the 'info' is a formatting
+ * string followed by arguments.
+ *
+ * For conveniency, the function calls 'json_object_put' for 'obj'.
+ * Thus, in the case where 'obj' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
+ */
+void afb_req_success_f(struct afb_req req, struct json_object *obj, const char *info, ...);
+```
+
+It exists two functions for "failure" replies: **afb_req_fail** and **afb_req_fail_f**.
+
+```C
+/*
+ * Sends a reply of kind failure to the request 'req'.
+ * The status of the reply is set to 'status' and an
+ * informational comment 'info' (can also be NULL) can be added.
+ *
+ * Note that calling afb_req_fail("success", info) is equivalent
+ * to call afb_req_success(NULL, info). Thus even if possible it
+ * is strongly recommended to NEVER use "success" for status.
+ *
+ * For conveniency, the function calls 'json_object_put' for 'obj'.
+ * Thus, in the case where 'obj' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
+ */
+void afb_req_fail(struct afb_req req, const char *status, const char *info);
+
+/*
+ * Same as 'afb_req_fail' but the 'info' is a formatting
+ * string followed by arguments.
+ *
+ * For conveniency, the function calls 'json_object_put' for 'obj'.
+ * Thus, in the case where 'obj' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
+ */
+void afb_req_fail_f(struct afb_req req, const char *status, const char *info, ...);
+```
+
+> For conveniency, these functions automatically call **json_object_put** to release **obj**.
+> Because **obj** usage count is null after being passed to a reply function, it SHOULD not be used anymore.
+> If exceptionally **obj** needs to remain usable after reply function then using **json_object_get** on **obj**
+> to increase usage count and cancels the effect the **json_object_put** is possible.
+
+Getting argument of invocation
+------------------------------
+
+Many methods expect arguments. Afb-daemon's bindings
+retrieve arguments by name and not by position.
+
+Arguments are passed by requests through either HTTP
+or WebSockets.
+
+For example, the method **join** of binding **tic-tac-toe**
+expects one argument: the *boardid* to join. Here is an extract:
+
+```C
+/*
+ * Join a board
+ */
+static void join(struct afb_req req)
+{
+	struct board *board, *new_board;
+	const char *id;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'join' called for boardid %d", board->id);
+
+	/* retrieves the argument */
+	id = afb_req_value(req, "boardid");
+	if (id == NULL)
+		goto bad_request;
+	...
+```
+
+The function **afb_req_value** searches in the request *req*
+for argument name passed in the second argument. When argument name
+is not passed, **afb_req_value** returns NULL.
+
+> The search is case sensitive and *boardid* is not equivalent to *BoardId*.
+> Nevertheless having argument names that only differ by name case is not a good idea.
+
+### Basic functions for querying arguments
+
+The function **afb_req_value** is defined here after:
+
+```C
+/*
+ * Gets from the request 'req' the string value of the argument of 'name'.
+ * Returns NULL if when there is no argument of 'name'.
+ * Returns the value of the argument of 'name' otherwise.
+ *
+ * Shortcut for: afb_req_get(req, name).value
+ */
+static inline const char *afb_req_value(struct afb_req req, const char *name)
+{
+	return afb_req_get(req, name).value;
+}
+```
+
+It is defined as a shortcut to call the function **afb_req_get**.
+That function is defined here after:
+
+```C
+/*
+ * Gets from the request 'req' the argument of 'name'.
+ * Returns a PLAIN structure of type 'struct afb_arg'.
+ * When the argument of 'name' is not found, all fields of result are set to NULL.
+ * When the argument of 'name' is found, the fields are filled,
+ * in particular, the field 'result.name' is set to 'name'.
+ *
+ * There is a special name value: the empty string.
+ * The argument of name "" is defined only if the request was made using
+ * an HTTP POST of Content-Type "application/json". In that case, the
+ * argument of name "" receives the value of the body of the HTTP request.
+ */
+struct afb_arg afb_req_get(struct afb_req req, const char *name);
+```
+
+That function takes 2 parameters: the request and the name
+of the argument to retrieve. It returns a PLAIN structure of
+type **struct afb_arg**.
+
+There is a special name that is defined when the request is
+of type HTTP/POST with a Content-Type being application/json.
+This name is **""** (the empty string). In that case, the value
+of this argument of empty name is the string received as a body
+of the post and is supposed to be a JSON string.
+
+The definition of **struct afb_arg** is:
+
+```C
+/*
+ * Describes an argument (or parameter) of a request
+ */
+struct afb_arg {
+	const char *name;	/* name of the argument or NULL if invalid */
+	const char *value;	/* string representation of the value of the argument */
+				/* original filename of the argument if path != NULL */
+	const char *path;	/* if not NULL, path of the received file for the argument */
+				/* when the request is finalized this file is removed */
+};
+```
+
+The structure returns the data arguments that are known for the
+request. This data include a field named **path**. This **path**
+can be accessed using the function **afb_req_path** defined here after:
+
+```C
+/*
+ * Gets from the request 'req' the path for file attached to the argument of 'name'.
+ * Returns NULL if when there is no argument of 'name' or when there is no file.
+ * Returns the path of the argument of 'name' otherwise.
+ *
+ * Shortcut for: afb_req_get(req, name).path
+ */
+static inline const char *afb_req_path(struct afb_req req, const char *name)
+{
+	return afb_req_get(req, name).path;
+}
+```
+
+The path is only defined for HTTP/POST requests that send file.
+
+### Arguments for received files
+
+As it is explained above, clients can send files using HTTP/POST requests.
+
+Received files are attached to "file" argument name. For example, the
+following HTTP fragment (from test/sample-post.html)
+will send an HTTP/POST request to the method
+**post/upload-image** with 2 arguments named *file* and
+*hidden*.
+
+```html
+<h2>Sample Post File</h2>
+<form enctype="multipart/form-data">
+    <input type="file" name="file" />
+    <input type="hidden" name="hidden" value="bollobollo" />
+    <br>
+    <button formmethod="POST" formaction="api/post/upload-image">Post File</button>
+</form>
+```
+
+Argument named **file** should have both its value and path defined.
+
+The value is the name of the file as it was set by the HTTP client.
+Generally it is the filename on client side.
+
+The path is the effective path of saved file on the temporary local storage
+area of the application. This is a randomly generated and unique filename. 
+It is not linked with the original filename as used on client side.
+
+After success the binding can use the uploaded file directly from local storage path with no restriction:
+read, write, remove, copy, rename...
+Nevertheless when request reply is set and query terminated, the uploaded temporary file at
+path is destroyed.
+
+### Arguments as a JSON object
+
+Bindings may also request every arguments of a given call as one single object.
+This feature is provided by the function **afb_req_json** defined here after:
+
+```C
+/*
+ * Gets from the request 'req' the json object hashing the arguments.
+ * The returned object must not be released using 'json_object_put'.
+ */
+struct json_object *afb_req_json(struct afb_req req);
+```
+
+It returns a json object. This object depends on how the request was built:
+
+- For HTTP requests, this json object uses key names mapped on argument name. 
+Values are either string for common arguments or object ie: { "file": "...", "path": "..." }
+
+- For WebSockets requests, returned directly the object as provided by the client.
+
+> In fact, for Websockets requests, the function **afb_req_value**
+> can be seen as a shortcut to
+> ***json_object_get_string(json_object_object_get(afb_req_json(req), name))***
+
+Initialisation of the binding and declaration of methods
+-----------------------------------------------------
+
+To be active, binding's methods should be declared to
+afb-daemon. Furthermore, the binding itself must be recorded.
+
+The registration mechanism is very basic: when afb-need starts,
+it loads all bindings listed in: command line or configuration file.
+
+Loading a binding follows the following steps:
+
+1. Afb-daemon loads the binding with *dlopen*.
+
+2. Afb-daemon searches for a symbol named **afbBindingV1Register** using *dlsym*.
+This symbol is assumed to be the exported initialisation function of the binding.
+
+3. Afb-daemon builds an interface object for the binding.
+
+4. Afb-daemon calls the found function **afbBindingV1Register** with interface pointer
+as parameter.
+
+5. Function **afbBindingV1Register** setups the binding and initialises it.
+
+6. Function **afbBindingV1Register** returns the pointer to a structure
+describing the binding: version, name (prefix or API name), and list of methods.
+
+7. Afb-daemon checks that the returned version and name can be managed.
+If so, binding and its methods are register to become usable as soon as
+afb-daemon initialisation is finished.
+
+Here after the code used for **afbBindingV1Register** from binding *tic-tac-toe*:
+
+```C
+/*
+ * activation function for registering the binding called by afb-daemon
+ */
+const struct afb_binding *afbBindingV1Register(const struct afb_binding_interface *itf)
+{
+   afbitf = itf;         // records the interface for accessing afb-daemon
+   return &binding_description;  // returns the description of the binding
+}
+```
+
+It is a very minimal initialisation function because *tic-tac-toe* binding doesn't
+have any application related initialisation step. It merely record daemon's interface
+and returns its description.
+
+The variable **afbitf** is a binding global variable. It keeps the
+interface to afb-daemon that should be used for logging and pushing events.
+Here is its declaration:
+
+```C
+/*
+ * the interface to afb-daemon
+ */
+const struct afb_binding_interface *afbitf;
+```
+
+The description of the binding is defined here after.
+
+```C
+/*
+ * array of the methods exported to afb-daemon
+ */
+static const struct afb_verb_desc_v1 binding_methods[] = {
+   /* VERB'S NAME     SESSION MANAGEMENT          FUNCTION TO CALL  SHORT DESCRIPTION */
+   { .name= "new",   .session= AFB_SESSION_NONE, .callback= new,   .info= "Starts a new game" },
+   { .name= "play",  .session= AFB_SESSION_NONE, .callback= play,  .info= "Asks the server to play" },
+   { .name= "move",  .session= AFB_SESSION_NONE, .callback= move,  .info= "Tells the client move" },
+   { .name= "board", .session= AFB_SESSION_NONE, .callback= board, .info= "Get the current board" },
+   { .name= "level", .session= AFB_SESSION_NONE, .callback= level, .info= "Set the server level" },
+   { .name= "join",  .session= AFB_SESSION_CHECK,.callback= join,  .info= "Join a board" },
+   { .name= "undo",  .session= AFB_SESSION_NONE, .callback= undo,  .info= "Undo the last move" },
+   { .name= "wait",  .session= AFB_SESSION_NONE, .callback= wait,  .info= "Wait for a change" },
+   { .name= NULL } /* marker for end of the array */
+};
+
+/*
+ * description of the binding for afb-daemon
+ */
+static const struct afb_binding binding_description =
+{
+   /* description conforms to VERSION 1 */
+   .type= AFB_BINDING_VERSION_1,
+   .v1= {				/* fills the v1 field of the union when AFB_BINDING_VERSION_1 */
+      .prefix= "tictactoe",		/* the API name (or binding name or prefix) */
+      .info= "Sample tac-tac-toe game",	/* short description of of the binding */
+      .methods = binding_methods		/* the array describing the methods of the API */
+   }
+};
+```
+
+The structure **binding_description** describes the binding.
+It declares the type and version of the binding, its name, a short description
+and its methods list.
+
+The list of methods is an array of structures describing the methods and terminated by a NULL marker.
+
+In version one of afb-damon binding, a method description contains 4 fields:
+
+- the name of the method,
+
+- the session management flags,
+
+- the implementation function to be call for the method,
+
+- a short description.
+
+The structure describing methods is defined as follows:
+
+```C
+/*
+ * Description of one method of the API provided by the binding
+ * This enumeration is valid for bindings of type 1
+ */
+struct afb_verb_desc_v1
+{
+       const char *name;                       /* name of the method */
+       enum AFB_session_v1 session;            /* authorisation and session requirements of the method */
+       void (*callback)(struct afb_req req);   /* callback function implementing the method */
+       const char *info;                       /* textual description of the method */
+};
+```
+
+For technical reasons, the enumeration **enum AFB_session_v1** is not exactly an
+enumeration but the wrapper of constant definitions that can be mixed using bitwise or
+(the C operator |).
+
+The constants that can bit mixed are:
+
+Constant name            | Meaning
+-------------------------|-------------------------------------------------------------
+**AFB_SESSION_CREATE**   | Equals to AFB_SESSION_LOA_EQ_0|AFB_SESSION_RENEW
+**AFB_SESSION_CLOSE**    | Closes the session after the reply and set the LOA to 0
+**AFB_SESSION_RENEW**    | Refreshes the token of authentification
+**AFB_SESSION_CHECK**    | Just requires the token authentification
+**AFB_SESSION_LOA_LE_0** | Requires the current LOA to be lesser then or equal to 0
+**AFB_SESSION_LOA_LE_1** | Requires the current LOA to be lesser then or equal to 1
+**AFB_SESSION_LOA_LE_2** | Requires the current LOA to be lesser then or equal to 2
+**AFB_SESSION_LOA_LE_3** | Requires the current LOA to be lesser then or equal to 3
+**AFB_SESSION_LOA_GE_0** | Requires the current LOA to be greater then or equal to 0
+**AFB_SESSION_LOA_GE_1** | Requires the current LOA to be greater then or equal to 1
+**AFB_SESSION_LOA_GE_2** | Requires the current LOA to be greater then or equal to 2
+**AFB_SESSION_LOA_GE_3** | Requires the current LOA to be greater then or equal to 3
+**AFB_SESSION_LOA_EQ_0** | Requires the current LOA to be equal to 0
+**AFB_SESSION_LOA_EQ_1** | Requires the current LOA to be equal to 1
+**AFB_SESSION_LOA_EQ_2** | Requires the current LOA to be equal to 2
+**AFB_SESSION_LOA_EQ_3** | Requires the current LOA to be equal to 3
+
+If any of this flag is set, afb-daemon requires an authentication token
+as if **AFB_SESSION_CHECK** flag was also set.
+
+The special value **AFB_SESSION_NONE** is zero and can be used to bypass token check.
+
+> Note that **AFB_SESSION_CREATE** and **AFB_SESSION_CLOSE** might be removed in later versions.
+
+Sending messages to the log system
+----------------------------------
+
+Afb-daemon provides 4 levels of verbosity and 5 methods for logging messages.
+
+The verbosity is managed. Options allow the change the verbosity of afb-daemon
+and the verbosity of the bindings can be set binding by binding.
+
+The methods for logging messages are defined as macros that test the
+verbosity level and that call the real logging function only if the
+message must be output. This avoid evaluation of arguments of the
+formatting messages if the message must not be output.
+
+### Verbs for logging messages
+
+The 5 logging methods are:
+
+Macro   | Verbosity | Meaning                           | syslog level
+--------|:---------:|-----------------------------------|:-----------:
+ERROR   |     0     | Error conditions                  |     3
+WARNING |     1     | Warning conditions                |     4
+NOTICE  |     1     | Normal but significant condition  |     5
+INFO    |     2     | Informational                     |     6
+DEBUG   |     3     | Debug-level messages              |     7
+
+You can note that the 2 methods **WARNING** and **INFO** have the same level
+of verbosity. But they don't have the same *syslog level*. It means that
+they are output with a different level on the logging system.
+
+All of these methods have the same signature:
+
+```C
+void ERROR(const struct afb_binding_interface *afbitf, const char *message, ...);
+```
+
+The first argument **afbitf** is the interface to afb daemon that the
+binding received at initialisation time when **afbBindingV1Register** is called.
+
+The second argument **message** is a formatting string compatible with printf/sprintf.
+
+The remaining arguments are arguments of the formating message like with printf.
+
+### Managing verbosity
+
+Depending on the level of verbosity, the messages are output or not.
+The following table explains what messages will be output depending
+ont the verbosity level.
+
+Level of verbosity | Outputed macro
+:-----------------:|--------------------------
+0                  | ERROR
+1                  | ERROR + WARNING + NOTICE
+2                  | ERROR + WARNING + NOTICE + INFO
+3                  | ERROR + WARNING + NOTICE + INFO + DEBUG
+
+### Output format and destination
+
+The syslog level is used for forging a prefix to the message.
+The prefixes are:
+
+syslog level | prefix
+:-----------:|---------------
+0            | <0> EMERGENCY
+1            | <1> ALERT
+2            | <2> CRITICAL
+3            | <3> ERROR
+4            | <4> WARNING
+5            | <5> NOTICE
+6            | <6> INFO
+7            | <7> DEBUG
+
+
+The message is pushed to standard error.
+The final destination of the message depends on how systemd service
+was configured through its variable **StandardError**. It can be
+journal, syslog or kmsg. (See man sd-daemon).
+
+Sending events
+--------------
+
+Since version 0.5, bindings can broadcast events to any potential listener.
+As today only unattended even are supported. Targeted events are expected for next
+coming version.
+
+The binding *tic-tac-toe* broadcasts events when the board changes.
+This is done in the function **changed**:
+
+```C
+/*
+ * signals a change of the board
+ */
+static void changed(struct board *board, const char *reason)
+{
+	...
+	struct json_object *description;
+
+	/* get the description */
+	description = describe(board);
+
+	...
+
+	afb_daemon_broadcast_event(afbitf->daemon, reason, description);
+}
+```
+
+The description of the changed board is pushed via the daemon interface.
+
+Within binding *tic-tac-toe*, *reason* indicates the origin of
+the change. In function **afb_daemon_broadcast_event** the second
+parameter is the name of broadcasted event. The third argument is the
+object that is transmitted with the event.
+
+Function **afb_daemon_broadcast_event** is defined here after:
+
+```C
+/*
+ * Broadcasts widely the event of 'name' with the data 'object'.
+ * 'object' can be NULL.
+ * 'daemon' MUST be the daemon given in interface when activating the binding.
+ *
+ * For conveniency, the function calls 'json_object_put' for 'object'.
+ * Thus, in the case where 'object' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
+ */
+void afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object);
+```
+
+> Be aware, as with reply functions **object** is automatically released using
+> **json_object_put** when using this function. Call **json_object_get** before
+> calling **afb_daemon_broadcast_event** to keep **object** available
+> after function returns.
+
+Event name received by listeners is prefixed with binding name.
+So when a change occurs after a move, the reason is **move** and every clients
+receive an event **tictactoe/move**.
+
+> Note that nothing is said about case sensitivity of event names.
+> However, the event is always prefixed with the name that the binding
+> declared, with the same case, followed with a slash /.
+> Thus it is safe to compare event using a case sensitive comparison.
+
+
+
+Writing an asynchronous method implementation
+-------------------------------------------
+
+The *tic-tac-toe* example allows two clients or more to share the same board.
+This is implemented by the method **join** that illustrated partly how to
+retrieve arguments.
+
+When two or more clients are sharing a same board, one of them can wait
+until the state of the board changes, but this could also be implemented using
+events because an even is generated each time the board changes.
+
+In this case, the reply to the wait is sent only when the board changes.
+See the diagram below:
+
+	CLIENT A       CLIENT B         TIC-TAC-TOE
+	   |              |                  |
+	   +--------------|----------------->| wait . . . . . . . .
+	   |              |                  |                     .
+	   :              :                  :                      .
+	   :              :                  :                      .
+	   |              |                  |                      .
+	   |              +----------------->| move . . .           .
+	   |              |                  |          V           .
+	   |              |<-----------------+ success of move      .
+	   |              |                  |                    .
+	   |<-------------|------------------+ success of wait  <
+
+Here, this is an invocation of the binding by an other client that
+unblock the suspended *wait* call.
+Nevertheless in most case this should be a timer, a hardware event, a sync with
+a concurrent process or thread, ...
+
+Common case of an asynchronous implementation.
+
+Here is the listing of the function **wait**:
+
+```C
+static void wait(struct afb_req req)
+{
+	struct board *board;
+	struct waiter *waiter;
+
+	/* retrieves the context for the session */
+	board = board_of_req(req);
+	INFO(afbitf, "method 'wait' called for boardid %d", board->id);
+
+	/* creates the waiter and enqueues it */
+	waiter = calloc(1, sizeof *waiter);
+	waiter->req = req;
+	waiter->next = board->waiters;
+	afb_req_addref(req);
+	board->waiters = waiter;
+}
+```
+
+After retrieving the board, the function adds a new waiter to
+waiters list and returns without setting a reply.
+
+Before returning, it increases **req** request's reference count using **afb_req_addref** function.
+
+> When a method returns without setting a reply,
+> it **MUST** increment request's reference count
+> using **afb_req_addref**. If unpredictable behaviour may pop up.
+
+Later, when a board changes, it calls *tic-tac-toe* **changed** function
+with reason of change in parameter.
+
+Here is the full listing of the function **changed**:
+
+```C
+/*
+ * signals a change of the board
+ */
+static void changed(struct board *board, const char *reason)
+{
+	struct waiter *waiter, *next;
+	struct json_object *description;
+
+	/* get the description */
+	description = describe(board);
+
+	waiter = board->waiters;
+	board->waiters = NULL;
+	while (waiter != NULL) {
+		next = waiter->next;
+		afb_req_success(waiter->req, json_object_get(description), reason);
+		afb_req_unref(waiter->req);
+		free(waiter);
+		waiter = next;
+	}
+
+	afb_event_sender_push(afb_daemon_get_event_sender(afbitf->daemon), reason, description);
+}
+```
+
+The list of waiters is walked and a reply is sent to each waiter.
+After sending the reply, the reference count of the request
+is decremented using **afb_req_unref** to allow resources to be freed.
+
+> The reference count **MUST** be decremented using **afb_req_unref** to free
+> resources and avoid memory leaks.
+> This usage count decrement should happen **AFTER** setting reply or 
+> bad things may happen.
+
+How to build a binding
+---------------------
+
+Afb-daemon provides a *pkg-config* configuration file that can be
+queried by providing **afb-daemon** in command line arguments.
+This configuration file provides data that should be used
+for bindings compilation. Examples:
+
+```bash
+$ pkg-config --cflags afb-daemon
+$ pkg-config --libs afb-daemon
+```
+
+### Example for cmake meta build system
+
+This example is the extract for building the binding *afm-main* using *CMAKE*.
+
+```cmake
+pkg_check_modules(afb afb-daemon)
+if(afb_FOUND)
+	message(STATUS "Creation afm-main-binding for AFB-DAEMON")
+	add_library(afm-main-binding MODULE afm-main-binding.c)
+	target_compile_options(afm-main-binding PRIVATE ${afb_CFLAGS})
+	target_include_directories(afm-main-binding PRIVATE ${afb_INCLUDE_DIRS})
+	target_link_libraries(afm-main-binding utils ${afb_LIBRARIES})
+	set_target_properties(afm-main-binding PROPERTIES
+		PREFIX ""
+		LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/afm-main-binding.export-map"
+	)
+	install(TARGETS afm-main-binding LIBRARY DESTINATION ${binding_dir})
+else()
+	message(STATUS "Not creating the binding for AFB-DAEMON")
+endif()
+```
+
+Let now describe some of these lines.
+
+```cmake
+pkg_check_modules(afb afb-daemon)
+```
+
+This first lines searches to the *pkg-config* configuration file for
+**afb-daemon**. Resulting data are stored in the following variables:
+
+Variable          | Meaning
+------------------|------------------------------------------------
+afb_FOUND         | Set to 1 if afb-daemon binding development files exist
+afb_LIBRARIES     | Only the libraries (w/o the '-l') for compiling afb-daemon bindings
+afb_LIBRARY_DIRS  | The paths of the libraries (w/o the '-L') for compiling afb-daemon bindings
+afb_LDFLAGS       | All required linker flags for compiling afb-daemon bindings
+afb_INCLUDE_DIRS  | The '-I' preprocessor flags (w/o the '-I') for compiling afb-daemon bindings
+afb_CFLAGS        | All required cflags for compiling afb-daemon bindings
+
+If development files are found, the binding can be added to the set of
+target to build.
+
+```cmake
+add_library(afm-main-binding MODULE afm-main-binding.c)
+```
+
+This line asks to create a shared library having a single
+source file named afm-main-binding.c to be compiled.
+The default name of the created shared object is
+**libafm-main-binding.so**.
+
+```cmake
+set_target_properties(afm-main-binding PROPERTIES
+	PREFIX ""
+	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/afm-main-binding.export-map"
+)
+```
+
+This lines are doing two things:
+
+1. It renames the built library from **libafm-main-binding.so** to **afm-main-binding.so**
+by removing the implicitly added prefix *lib*. This step is not mandatory
+because afb-daemon doesn't check names of files at load time.
+The only filename convention used by afb-daemon relates to **.so** termination.
+*.so pattern is used when afb-daemon automatically discovers binding from a directory hierarchy.
+
+2. It applies a version script at link time to only export the reserved name
+**afbBindingV1Register** for registration entry point. By default, when building 
+a shared library linker exports all the public symbols (C functions that are not **static**).
+
+Next line are:
+
+```cmake
+target_include_directories(afm-main-binding PRIVATE ${afb_INCLUDE_DIRS})
+target_link_libraries(afm-main-binding utils ${afb_LIBRARIES})
+```
+
+As you can see it uses the variables computed by ***pkg_check_modules(afb afb-daemon)***
+to configure the compiler and the linker.
+
+### Exporting the function afbBindingV1Register
+
+The function **afbBindingV1Register** MUST be exported. This can be achieved
+using a version script at link time. Here after is a version script used for
+*tic-tac-toe* (bindings/samples/export.map).
+
+	{ global: afbBindingV1Register; local: *; };
+
+This sample [version script](https://sourceware.org/binutils/docs-2.26/ld/VERSION.html#VERSION)
+exports as global the symbol *afbBindingV1Register* and hides any
+other symbols.
+
+This version script is added to the link options using the
+option **--version-script=export.map** is given directly to the
+linker or using the option **-Wl,--version-script=export.map**
+when the option is given to the C compiler.
+
+### Building within yocto
+
+Adding a dependency to afb-daemon is enough. See below:
+
+	DEPENDS += " afb-daemon "
+
diff --git a/doc/afb-daemon-vocabulary.html b/doc/afb-daemon-vocabulary.html
index d2d4f512..bffe91f6 100644
--- a/doc/afb-daemon-vocabulary.html
+++ b/doc/afb-daemon-vocabulary.html
@@ -16,11 +16,12 @@
 <header>
 <h1 class="title">Vocabulary for AFB-DAEMON</h1>
 <h2 class="author">José Bollo</h2>
-<h3 class="date">27 mai 2016</h3>
+<h3 class="date">23 juin 2016</h3>
 </header>
 <nav id="TOC">
 <ul>
 <li><a href="#vocabulary-for-afb-daemon">Vocabulary for AFB-DAEMON</a><ul>
+<li><a href="#binding">Binding</a></li>
 <li><a href="#event">Event</a></li>
 <li><a href="#level-of-assurance-loa">Level of assurance (LOA)</a></li>
 <li><a href="#plugin">Plugin</a></li>
@@ -40,6 +41,9 @@
 <pre><code>version: 1
 Date:    27 mai 2016
 Author:  José Bollo</code></pre>
+<h2 id="binding">Binding</h2>
+<p>A shared library object intended to be add a functionnality to an afb-daemon instance. It implements an API. It may provide a service.</p>
+<p>Binding made for services can have specific entry point called after initialisation and before serving.</p>
 <h2 id="event">Event</h2>
 <p>Message with data propagated from the services to the client and not expecting any reply.</p>
 <p>The current implementation allows to widely broadcast events to all clients.</p>
@@ -47,14 +51,14 @@ Author:  José Bollo</code></pre>
 <p>This level that can be from 0 to 3 represent the level of assurance that the services can expect from the session.</p>
 <p>The exact definition of the meaning of this levels and of how to use it remains to be achived.</p>
 <h2 id="plugin">Plugin</h2>
-<p>A shared library object intended to be plug to an afb-daemon instance to implement an API.</p>
+<p>Old name for binding, see binding.</p>
 <h2 id="request">Request</h2>
-<p>A request is an invocation by a client to a method of a plugin using a message transfered through some protocol: HTTP, WebSocket, DBUS... served by afb-daemon</p>
+<p>A request is an invocation by a client to a method of a binding using a message transfered through some protocol: HTTP, WebSocket, DBUS... served by afb-daemon</p>
 <h2 id="replyresponse">Reply/Response</h2>
 <p>This is a message sent to client as the result of the request.</p>
 <h2 id="service">Service</h2>
-<p>Service are made of plugins runnning by their side on their binder. It can serve many client. Each one being attached to one session.</p>
-<p>The framework establishes the connection between the services and the clients. Using DBus currently.</p>
+<p>Service are made of binding runnning by their side on their binder. It can serve many client. Each one being attached to one session.</p>
+<p>The framework establishes the connection between the services and the clients. Using DBus currently but other protocols are considered.</p>
 <h2 id="session">Session</h2>
 <p>A session is meant to be the unic context of an instance of client, identifying that instance across requests.</p>
 <p>Each session has an identifier. Session identifier generated by afb-daemon are UUIDs.</p>
diff --git a/doc/afb-daemon-vocabulary.md b/doc/afb-daemon-vocabulary.md
index 83472d51..0be4e3db 100644
--- a/doc/afb-daemon-vocabulary.md
+++ b/doc/afb-daemon-vocabulary.md
@@ -5,6 +5,13 @@ Vocabulary for AFB-DAEMON
     Author:  José Bollo
 
 
+## Binding
+
+A shared library object intended to be add a functionnality to an afb-daemon
+instance. It implements an API. It may provide a service.
+
+Binding made for services can have specific entry point called after
+initialisation and before serving.
 
 ## Event
 
@@ -23,12 +30,11 @@ how to use it remains to be achived.
 
 ## Plugin
 
-A shared library object intended to be plug to an afb-daemon instance
-to implement an API.
+Old name for binding, see binding.
 
 ## Request
 
-A request is an invocation by a client to a method of a plugin using a message
+A request is an invocation by a client to a method of a binding using a message
 transfered through some protocol: HTTP, WebSocket, DBUS... served by afb-daemon
 
 ## Reply/Response
@@ -37,11 +43,11 @@ This is a message sent to client as the result of the request.
 
 ## Service
 
-Service are made of plugins runnning by their side on their binder.
+Service are made of binding runnning by their side on their binder.
 It can serve many client. Each one being attached to one session.
 
 The framework establishes the connection between the services and
-the clients. Using DBus currently.
+the clients. Using DBus currently but other protocols are considered.
 
 ## Session
 
diff --git a/doc/afb-overview.html b/doc/afb-overview.html
index e8050f9a..23ca6e9c 100644
--- a/doc/afb-overview.html
+++ b/doc/afb-overview.html
@@ -16,7 +16,7 @@
 <header>
 <h1 class="title">Overview of AFB-DAEMON</h1>
 <h2 class="author">José Bollo</h2>
-<h3 class="date">30 mai 2016</h3>
+<h3 class="date">23 juin 2016</h3>
 </header>
 <nav id="TOC">
 <ul>
@@ -27,7 +27,7 @@
 <li><a href="#adding-native-features-to-html5qml-applications">Adding native features to HTML5/QML applications</a></li>
 <li><a href="#offering-services-to-the-system">Offering services to the system</a></li>
 </ul></li>
-<li><a href="#the-plugins-of-the-binder-afb-daemon">The plugins of the binder afb-daemon</a></li>
+<li><a href="#the-bindings-of-the-binder-afb-daemon">The bindings of the binder afb-daemon</a></li>
 <li><a href="#launching-the-binder-afb-daemon">Launching the binder afb-daemon</a></li>
 <li><a href="#future-development-of-afb-daemon">Future development of afb-daemon</a></li>
 </ul></li>
@@ -59,7 +59,7 @@ Figure: binder afb-daemon, basis
 .   +-------------------+----------------------+  .
 .   |                            :             |  .
 .   |        b i n d e r         :             |  .
-.   |    A F B - D A E M O N     :   PLUGINS   |  .
+.   |    A F B - D A E M O N     :  BINDINGS   |  .
 .   |                            :             |  .
 .   +-------------------+----------------------+  .
 .                       |                         .
@@ -106,7 +106,7 @@ Figure: binder afb-daemon and remotely running application
 .                           |                           .
 .       +-------------------+----------------------+    .
 .       |                            :             |    .
-.       |    A F B - D A E M O N     :   PLUGINS   |    .
+.       |    A F B - D A E M O N     :   BINDINGS  |    .
 .       |                            :             |    .
 .       +-------------------+----------------------+    .
 .                           |                           .
@@ -115,9 +115,9 @@ Figure: binder afb-daemon and remotely running application
                             v
                        AGL SYSTEM</code></pre>
 <h3 id="adding-native-features-to-html5qml-applications">Adding native features to HTML5/QML applications</h3>
-<p>Applications can provide with their packaged delivery a plugin. That plugin will be instanciated for each application instance. The methods of the plugin will be accessible by applications and will be excuted within the security context.</p>
+<p>Applications can provide with their packaged delivery a binding. That binding will be instanciated for each application instance. The methods of the binding will be accessible by applications and will be excuted within the security context.</p>
 <h3 id="offering-services-to-the-system">Offering services to the system</h3>
-<p>It is possible to run the binder afb-daemon as a daemon that provides the API of its plugins.</p>
+<p>It is possible to run the binder afb-daemon as a daemon that provides the API of its bindings.</p>
 <p>This will be used for:</p>
 <ol type="1">
 <li><p>offering common APIs</p></li>
@@ -142,7 +142,7 @@ Figure: binder afb-daemon for services
 . +-----------------+------------------+  .     . +------------------------------------+  .
 . |                        :           |  .     . |                        :           |  .
 . |      b i n d e r       :           |  .     . |      b i n d e r       :  service  |  .
-. |  A F B - D A E M O N   :  PLUGINS  |  .     . |  A F B - D A E M O N   :  PLUGINS  |  .
+. |  A F B - D A E M O N   : BINDINGS  |  .     . |  A F B - D A E M O N   : BINDINGS  |  .
 . |                        :           |  .     . |                        :     A     |  .
 . +-----------------+------------------+  .     . +-----------------+------------------+  .
 .                   |                     .     .                   |                     .
@@ -159,22 +159,22 @@ Figure: binder afb-daemon for services
 . +-----------------+------------------+  .     . +-----------------+------------------+  .
 . |                        :           |  .     . |                        :           |  .
 . |      b i n d e r       :  service  |  .     . |      b i n d e r       :  service  |  .
-. |  A F B - D A E M O N   :  PLUGINS  |  .     . |  A F B - D A E M O N   :  PLUGINS  |  .
+. |  A F B - D A E M O N   : BINDINGS  |  .     . |  A F B - D A E M O N   : BINDINGS  |  .
 . |                        :     B     |  .     . |                        :     C     |  .
 . +------------------------------------+  .     . +------------------------------------+  .
 .                                         .     .                                         .
 .        Isolated security context B      .     .        Isolated security context C      .
 . . . . . . . . . . . . . . . . . . . . . .     . . . . . . . . . . . . . . . . . . . . . .</code></pre>
-<p>For this case, the binder afb-daemon takes care to attribute one single session context to each client instance. It allows plugins to store and retrieve data associated to each of its client.</p>
-<h2 id="the-plugins-of-the-binder-afb-daemon">The plugins of the binder afb-daemon</h2>
-<p>The binder can instanciate plugins. The primary use of plugins is to add native methods that can be accessed by applications written with any language through web technologies ala JSON RPC.</p>
+<p>For this case, the binder afb-daemon takes care to attribute one single session context to each client instance. It allows bindings to store and retrieve data associated to each of its client.</p>
+<h2 id="the-bindings-of-the-binder-afb-daemon">The bindings of the binder afb-daemon</h2>
+<p>The binder can instanciate bindings. The primary use of bindings is to add native methods that can be accessed by applications written with any language through web technologies ala JSON RPC.</p>
 <p>This simple idea is declined to serves multiple purposes:</p>
 <ol type="1">
 <li><p>add native feature to applications</p></li>
 <li><p>add common API available by any applications</p></li>
 <li><p>provide customers services</p></li>
 </ol>
-<p>A specific document explains how to write an afb-daemon binder plugin: <a href="afb-plugin-writing.html">HOWTO WRITE a PLUGIN for AFB-DAEMON</a></p>
+<p>A specific document explains how to write an afb-daemon binder binding: <a href="afb-binding-writing.html">HOWTO WRITE a BINDING for AFB-DAEMON</a></p>
 <h2 id="launching-the-binder-afb-daemon">Launching the binder afb-daemon</h2>
 <p>The launch options for binder <strong>afb-daemon</strong> are:</p>
 <pre><code>  --help
@@ -209,7 +209,7 @@ Figure: binder afb-daemon for services
 
     HTML Root API URL [default /api]
 
-    The plugins are available within that url.
+    The bindings are available within that url.
 
   --alias=xxxx
 
@@ -224,7 +224,7 @@ Figure: binder afb-daemon for services
 
   --apitimeout=xxxx
 
-    Plugin API timeout in seconds [default 20]
+    binding API timeout in seconds [default 20]
 
     Defines how many seconds maximum a method is allowed to run.
     0 means no limit.
@@ -247,19 +247,19 @@ Figure: binder afb-daemon for services
 
   --ldpaths=xxxx
 
-    Load Plugins from given paths separated by colons
-    as for dir1:dir2:plugin1.so:... [default = $libdir/afb]
+    Load bindings from given paths separated by colons
+    as for dir1:dir2:binding1.so:... [default = $libdir/afb]
 
-    You can mix path to directories and to plugins.
+    You can mix path to directories and to bindings.
     The sub-directories of the given directories are searched
     recursively.
 
-    The plugins are the files terminated by &#39;.so&#39; (the extension
+    The bindings are the files terminated by &#39;.so&#39; (the extension
     so denotes shared object) that contain the public entry symbol.
 
-  --plugin=xxxx
+  --binding=xxxx
 
-    Load the plugin of given path.
+    Load the binding of given path.
 
   --token=xxxx
 
@@ -294,7 +294,7 @@ Figure: binder afb-daemon for services
 
     Provides a binder afb-daemon service through dbus.
 
-    The name xxxx must be the name of an API defined by a plugin.
+    The name xxxx must be the name of an API defined by a binding.
     This API is exported through DBUS.
 
   --foreground
diff --git a/doc/afb-overview.md b/doc/afb-overview.md
index 1bd83240..ab24606c 100644
--- a/doc/afb-overview.md
+++ b/doc/afb-overview.md
@@ -34,7 +34,7 @@ of afb-daemon:
 	.   +-------------------+----------------------+  .
 	.   |                            :             |  .
 	.   |        b i n d e r         :             |  .
-	.   |    A F B - D A E M O N     :   PLUGINS   |  .
+	.   |    A F B - D A E M O N     :  BINDINGS   |  .
 	.   |                            :             |  .
 	.   +-------------------+----------------------+  .
 	.                       |                         .
@@ -97,7 +97,7 @@ when the application is run remotely:
 	.                           |                           .
 	.       +-------------------+----------------------+    .
 	.       |                            :             |    .
-	.       |    A F B - D A E M O N     :   PLUGINS   |    .
+	.       |    A F B - D A E M O N     :   BINDINGS  |    .
 	.       |                            :             |    .
 	.       +-------------------+----------------------+    .
 	.                           |                           .
@@ -108,15 +108,15 @@ when the application is run remotely:
 
 ### Adding native features to HTML5/QML applications
 
-Applications can provide with their packaged delivery a plugin.
-That plugin will be instanciated for each application instance.
-The methods of the plugin will be accessible by applications and
+Applications can provide with their packaged delivery a binding.
+That binding will be instanciated for each application instance.
+The methods of the binding will be accessible by applications and
 will be excuted within the security context.
 
 ### Offering services to the system
 
 It is possible to run the binder afb-daemon as a daemon that provides the
-API of its plugins.
+API of its bindings.
 
 This will be used for:
 
@@ -141,7 +141,7 @@ In that case, the figure showing the whole aspects is
 	. +-----------------+------------------+  .     . +------------------------------------+  .
 	. |                        :           |  .     . |                        :           |  .
 	. |      b i n d e r       :           |  .     . |      b i n d e r       :  service  |  .
-	. |  A F B - D A E M O N   :  PLUGINS  |  .     . |  A F B - D A E M O N   :  PLUGINS  |  .
+	. |  A F B - D A E M O N   : BINDINGS  |  .     . |  A F B - D A E M O N   : BINDINGS  |  .
 	. |                        :           |  .     . |                        :     A     |  .
 	. +-----------------+------------------+  .     . +-----------------+------------------+  .
 	.                   |                     .     .                   |                     .
@@ -158,7 +158,7 @@ In that case, the figure showing the whole aspects is
 	. +-----------------+------------------+  .     . +-----------------+------------------+  .
 	. |                        :           |  .     . |                        :           |  .
 	. |      b i n d e r       :  service  |  .     . |      b i n d e r       :  service  |  .
-	. |  A F B - D A E M O N   :  PLUGINS  |  .     . |  A F B - D A E M O N   :  PLUGINS  |  .
+	. |  A F B - D A E M O N   : BINDINGS  |  .     . |  A F B - D A E M O N   : BINDINGS  |  .
 	. |                        :     B     |  .     . |                        :     C     |  .
 	. +------------------------------------+  .     . +------------------------------------+  .
 	.                                         .     .                                         .
@@ -167,13 +167,13 @@ In that case, the figure showing the whole aspects is
 
 
 For this case, the binder afb-daemon takes care to attribute one single session
-context to each client instance. It allows plugins to store and retrieve data
+context to each client instance. It allows bindings to store and retrieve data
 associated to each of its client.
 
-The plugins of the binder afb-daemon
+The bindings of the binder afb-daemon
 ------------------------------------
 
-The binder can instanciate plugins. The primary use of plugins
+The binder can instanciate bindings. The primary use of bindings
 is to add native methods that can be accessed by applications
 written with any language through web technologies ala JSON RPC.
 
@@ -185,8 +185,8 @@ This simple idea is declined to serves multiple purposes:
 
 3. provide customers services
 
-A specific document explains how to write an afb-daemon binder plugin:
-[HOWTO WRITE a PLUGIN for AFB-DAEMON](afb-plugin-writing.html)
+A specific document explains how to write an afb-daemon binder binding:
+[HOWTO WRITE a BINDING for AFB-DAEMON](afb-binding-writing.html)
 
 
 Launching the binder afb-daemon
@@ -226,7 +226,7 @@ The launch options for binder **afb-daemon** are:
 
 		HTML Root API URL [default /api]
 
-		The plugins are available within that url.
+		The bindings are available within that url.
 
 	  --alias=xxxx
 
@@ -241,7 +241,7 @@ The launch options for binder **afb-daemon** are:
 
 	  --apitimeout=xxxx
 
-		Plugin API timeout in seconds [default 20]
+		binding API timeout in seconds [default 20]
 
 		Defines how many seconds maximum a method is allowed to run.
 		0 means no limit.
@@ -264,19 +264,19 @@ The launch options for binder **afb-daemon** are:
 
 	  --ldpaths=xxxx
 
-		Load Plugins from given paths separated by colons
-		as for dir1:dir2:plugin1.so:... [default = $libdir/afb]
+		Load bindings from given paths separated by colons
+		as for dir1:dir2:binding1.so:... [default = $libdir/afb]
 
-		You can mix path to directories and to plugins.
+		You can mix path to directories and to bindings.
 		The sub-directories of the given directories are searched
 		recursively.
 
-		The plugins are the files terminated by '.so' (the extension
+		The bindings are the files terminated by '.so' (the extension
 		so denotes shared object) that contain the public entry symbol.
 
-	  --plugin=xxxx
+	  --binding=xxxx
 
-		Load the plugin of given path.
+		Load the binding of given path.
 
 	  --token=xxxx
 
@@ -311,7 +311,7 @@ The launch options for binder **afb-daemon** are:
 
 		Provides a binder afb-daemon service through dbus.
 
-		The name xxxx must be the name of an API defined by a plugin.
+		The name xxxx must be the name of an API defined by a binding.
 		This API is exported through DBUS.
 
 	  --foreground
diff --git a/doc/afb-plugin-writing.html b/doc/afb-plugin-writing.html
deleted file mode 100644
index 6c866fb6..00000000
--- a/doc/afb-plugin-writing.html
+++ /dev/null
@@ -1,953 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  <meta name="generator" content="pandoc">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
-  <meta name="author" content="José Bollo">
-  <meta name="author" content="Fulup Ar Foll">
-  <title>HOWTO WRITE a PLUGIN for AFB-DAEMON</title>
-  <style type="text/css">code{white-space: pre;}</style>
-  <!--[if lt IE 9]>
-    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
-  <![endif]-->
-  <style type="text/css">
-table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
-  margin: 0; padding: 0; vertical-align: baseline; border: none; }
-table.sourceCode { width: 100%; line-height: 100%; }
-td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
-td.sourceCode { padding-left: 5px; }
-code > span.kw { color: #007020; font-weight: bold; }
-code > span.dt { color: #902000; }
-code > span.dv { color: #40a070; }
-code > span.bn { color: #40a070; }
-code > span.fl { color: #40a070; }
-code > span.ch { color: #4070a0; }
-code > span.st { color: #4070a0; }
-code > span.co { color: #60a0b0; font-style: italic; }
-code > span.ot { color: #007020; }
-code > span.al { color: #ff0000; font-weight: bold; }
-code > span.fu { color: #06287e; }
-code > span.er { color: #ff0000; font-weight: bold; }
-  </style>
-  <link rel="stylesheet" href="doc.css">
-</head>
-<body>
-<header>
-<h1 class="title">HOWTO WRITE a PLUGIN for AFB-DAEMON</h1>
-<h2 class="author">José Bollo</h2>
-<h2 class="author">Fulup Ar Foll</h2>
-<h3 class="date">09 juin 2016</h3>
-</header>
-<nav id="TOC">
-<ul>
-<li><a href="#howto-write-a-plugin-for-afb-daemon">HOWTO WRITE a PLUGIN for AFB-DAEMON</a><ul>
-<li><a href="#summary">Summary</a><ul>
-<li><a href="#nature-of-a-plugin">Nature of a plugin</a></li>
-<li><a href="#class-of-plugins">Class of plugins</a></li>
-<li><a href="#live-cycle-of-plugins-within-afb-daemon">Live cycle of plugins within afb-daemon</a></li>
-<li><a href="#plugin-contend">Plugin Contend</a></li>
-</ul></li>
-<li><a href="#the-tic-tac-toe-example">The Tic-Tac-Toe example</a></li>
-<li><a href="#dependencies-when-compiling">Dependencies when compiling</a></li>
-<li><a href="#header-files-to-include">Header files to include</a></li>
-<li><a href="#choosing-names">Choosing names</a><ul>
-<li><a href="#names-for-api-plugin">Names for API (plugin)</a></li>
-<li><a href="#names-for-methods">Names for methods</a></li>
-<li><a href="#names-for-arguments">Names for arguments</a></li>
-<li><a href="#forging-names-widely-available">Forging names widely available</a></li>
-</ul></li>
-<li><a href="#writing-a-synchronous-method-implementation">Writing a synchronous method implementation</a><ul>
-<li><a href="#the-incoming-request">The incoming request</a></li>
-<li><a href="#associating-a-client-context-to-a-session">Associating a client context to a session</a></li>
-<li><a href="#sending-reply-to-a-request">Sending reply to a request</a></li>
-</ul></li>
-<li><a href="#getting-argument-of-invocation">Getting argument of invocation</a><ul>
-<li><a href="#basic-functions-for-querying-arguments">Basic functions for querying arguments</a></li>
-<li><a href="#arguments-for-received-files">Arguments for received files</a></li>
-<li><a href="#arguments-as-a-json-object">Arguments as a JSON object</a></li>
-</ul></li>
-<li><a href="#initialisation-of-the-plugin-and-declaration-of-methods">Initialisation of the plugin and declaration of methods</a></li>
-<li><a href="#sending-messages-to-the-log-system">Sending messages to the log system</a><ul>
-<li><a href="#verbs-for-logging-messages">Verbs for logging messages</a></li>
-<li><a href="#managing-verbosity">Managing verbosity</a></li>
-<li><a href="#output-format-and-destination">Output format and destination</a></li>
-</ul></li>
-<li><a href="#sending-events">Sending events</a></li>
-<li><a href="#writing-an-asynchronous-method-implementation">Writing an asynchronous method implementation</a></li>
-<li><a href="#how-to-build-a-plugin">How to build a plugin</a><ul>
-<li><a href="#example-for-cmake-meta-build-system">Example for cmake meta build system</a></li>
-<li><a href="#exporting-the-function-pluginafbv1register">Exporting the function pluginAfbV1Register</a></li>
-<li><a href="#building-within-yocto">Building within yocto</a></li>
-</ul></li>
-</ul></li>
-</ul>
-</nav>
-<h1 id="howto-write-a-plugin-for-afb-daemon">HOWTO WRITE a PLUGIN for AFB-DAEMON</h1>
-<pre><code>version: 1
-Date:    09 juin 2016
-Author:  José Bollo</code></pre>
-<h2 id="summary">Summary</h2>
-<p>Afb-daemon binders serve files through HTTP protocol and offers to developers the capability to expose application API methods through HTTP or WebSocket protocol.</p>
-<p>Binder plugins are used to add API to afb-daemon. This part describes how to write a plugin for afb-daemon.</p>
-<p>Excepting this summary, this document target developers.</p>
-<p>Before moving further through an example, here after a short overview of binder plugins fundamentals.</p>
-<h3 id="nature-of-a-plugin">Nature of a plugin</h3>
-<p>A plugin is an independent piece of software. A plugin is self contain and exposes application logic as sharable library. A plugin is intended to be dynamically loaded by afb-daemon to expose application API.</p>
-<p>Technically, a binder plugin does not reference and is not linked with any afb-daemon library.</p>
-<h3 id="class-of-plugins">Class of plugins</h3>
-<p>Application binder supports two kinds of plugins: application plugins and service plugins. Technically both class of plugin are equivalent are use the same coding convention. Only sharing mode and security context diverge.</p>
-<h4 id="application-plugins">Application-plugins</h4>
-<p>Application-plugins implements the glue in between application's UI and services. Every AGL application has a corresponding binder that typically activates one or many plugins to interface the application logic with lower platform services. When an application is started by the AGL application framework, a dedicate binder is started that loads/activates application plugin(s). API expose by application-plugin are executed within corresponding application security context.</p>
-<p>Application plugins generally handle a unique context for a unique client. As the application framework start a dedicated instance of afb_daemon for each AGL application, if a given plugin is used within multiple application each of those application get a new and private instance of eventually &quot;shared&quot; plugin.</p>
-<h4 id="service-plugins">Service-plugins</h4>
-<p>Service-plugins enable API activation within corresponding service security context and not within calling application context. Service-plugins are intended to run as a unique instance. Service-plugins can be shared in between multiple clients.</p>
-<p>Service-plugins can either be stateless or manage client context. When managing context each client get a private context.</p>
-<p>Sharing may either be global to the platform (ie: GPS service) or dedicated to a given user (ie: user preferences)</p>
-<h3 id="live-cycle-of-plugins-within-afb-daemon">Live cycle of plugins within afb-daemon</h3>
-<p>Application and service plugins are loaded and activated each time a new afb-daemon is started.</p>
-<p>At launch time, every loaded plugin initialise itself. If a single plugin initialisation fail corresponding instance of afb-daemon self aborts.</p>
-<p>Conversely, when a plugin initialisation succeeds, it should register its unique name as well as the list of verbs attached to the methods it exposes.</p>
-<p>When initialised, on request from application clients to the right API/verb, plugin methods are activated by the afb-daemon attached to the application or service.</p>
-<p>At exit time, no special action is enforced by afb-daemon. When a specific actions is required at afb-daemon stop, developers should use 'atexit/on_exit' during plugin initialisation sequence to register a custom exit function.</p>
-<h3 id="plugin-contend">Plugin Contend</h3>
-<p>Afb-daemon's plugin register two classes of objects: names and functions.</p>
-<p>Plugins declare categories of names: - A unique plugin name to access all API expose by this plugin, - One name for each methods/verbs provided by this plugin.</p>
-<p>Plugins declare two categories of functions: - function use for the initialisation - functions implementing exposed API methods</p>
-<p>Afb-daemon parses URI requests to extract the API(plugin name) and the VERB(method to activate). As an example, URI <strong>foo/bar</strong> translates to plugin named <strong>foo</strong> and method named <strong>bar</strong>. To serve such a request, afb-daemon looks for an active plugin named <strong>foo</strong> and then within this plugin for a method named <strong>bar</strong>. When find afb-daemon calls corresponding method with attached parameter if any.</p>
-<p>Afb-daemon ignores letter case when parsing URI. Thus <strong>TicTacToe/Board</strong> and <strong>tictactoe/board</strong> are equivalent.</p>
-<h4 id="the-name-of-the-plugin">The name of the plugin</h4>
-<p>The name of a given plugin is also known as the name of the API prefix that defines the plugin.</p>
-<p>The name of a plugin SHOULD be unique within a given afb-daemon instance.</p>
-<p>For example, when a client of afb-daemon calls a URI named <strong>foo/bar</strong>. Afb-daemon extracts the prefix <strong>foo</strong> and the suffix <strong>bar</strong>. <strong>foo</strong> must match a plugin name and <strong>bar</strong> a VERB attached to some method.</p>
-<h4 id="names-of-methods">Names of methods</h4>
-<p>Each plugin exposes a set of methods that can be called by the clients of a given afb-daemon.</p>
-<p>VERB's name attached to a given plugin (API) MUST be unique within a plugin.</p>
-<p>Plugins static declaration link VERBS to corresponding methods. When clients emit requests on a given API/VERB corresponding method is called by afb-daemon.</p>
-<h4 id="initialisation-function">Initialisation function</h4>
-<p>Plugin's initialisation function serves several purposes.</p>
-<ol type="1">
-<li><p>It allows afb-daemon to control plugin version depending on initialisation function name. As today, the only supported initialisation function is <strong>pluginAfbV1Register</strong>. This identifies version &quot;one&quot; of plugins.</p></li>
-<li><p>It allows plugins to initialise itself.</p></li>
-<li><p>It enables names declarations: descriptions, requirements and implementations of exposed API/VERB.</p></li>
-</ol>
-<h4 id="functions-instantiation-of-apiverbs">Functions instantiation of API/VERBs</h4>
-<p>When an API/VERB is called, afb-daemon constructs a request object. Then it passes this request object to the implementation function corresponding to requested method, this within attached API plugin.</p>
-<p>An implementation function receives a request object that is used to: get arguments of the request, send answer, store session data.</p>
-<p>A plugin MUST set an answer to every received requests.</p>
-<p>Nevertheless it is not mandatory to set the answer before returning from API/VERB implementing function. This behaviour is important for asynchronous actions.</p>
-<p>API/VERB implementation that set an answer before returning are called <em>synchronous implementations</em>. Those that do not systematically set an answer before returning are called <em>asynchronous implementations</em>.</p>
-<p>Asynchronous implementations typically launch asynchronous actions. They record some context at request time and provide answer to the request only at completion of asynchronous actions.</p>
-<h2 id="the-tic-tac-toe-example">The Tic-Tac-Toe example</h2>
-<p>This part explains how to write an afb-plugin. For the sake of being practical it uses many examples based on tic-tac-toe. This plugin example is in <em>plugins/samples/tic-tac-toe.c</em>.</p>
-<p>This plugin is named <strong><em>tictactoe</em></strong>.</p>
-<h2 id="dependencies-when-compiling">Dependencies when compiling</h2>
-<p>Afb-daemon provides a configuration file for <em>pkg-config</em>. Typing the command</p>
-<pre><code>pkg-config --cflags afb-daemon</code></pre>
-<p>Print flags use for compilation:</p>
-<pre><code>$ pkg-config --cflags afb-daemon
--I/opt/local/include -I/usr/include/json-c </code></pre>
-<p>For linking, you should use</p>
-<pre><code>$ pkg-config --libs afb-daemon
--ljson-c</code></pre>
-<p>Afb-daemon automatically includes dependency to json-c. This is activated through <strong>Requires</strong> keyword in pkg-config. While almost every plugin replies on <strong>json-c</strong> this is not a must have dependency.</p>
-<p>Internally, afb-daemon relies on <strong>libsystemd</strong> for its event loop, as well as for its binding to D-Bus. Plugins developers are encouraged to leverage <strong>libsystemd</strong> when possible. Nevertheless there is no hard dependency to <strong>libsystemd</strong> if ever you rather not use it, feel free to do so.</p>
-<blockquote>
-<p>Afb-daemon plugin are fully self contain. They do not enforce dependency on any libraries from the application framework. Afb-daemon dependencies requirer to run AGL plugins are given at runtime through pointers leveraging read-only memory feature.</p>
-</blockquote>
-<h2 id="header-files-to-include">Header files to include</h2>
-<p>Plugin <em>tictactoe</em> has following includes:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="ot">#define _GNU_SOURCE</span>
-<span class="ot">#include &lt;stdio.h&gt;</span>
-<span class="ot">#include &lt;string.h&gt;</span>
-<span class="ot">#include &lt;json-c/json.h&gt;</span>
-<span class="ot">#include &lt;afb/afb-plugin.h&gt;</span></code></pre>
-<p>Header <em>afb/afb-plugin.h</em> is the only hard dependency, it includes all features that a plugin MUST HAVE. Outside of includes used to support application logic, common external headers used within plugins are:</p>
-<ul>
-<li><em>json-c/json.h</em>: should be include to handle json objects;</li>
-<li><em>systemd/sd-event.h</em>: should be include to access event main loop;</li>
-<li><em>systemd/sd-bus.h</em>: should be include for dbus connections.</li>
-</ul>
-<p>The <em>tictactoe</em> plugin does not leverage systemd features, also only json.h is used on top of mandatory afb/afb-plugin.h.</p>
-<p>When including <em>afb/afb-plugin.h</em>, the macro **_GNU_SOURCE** MUST be defined.</p>
-<h2 id="choosing-names">Choosing names</h2>
-<p>Designers of plugins should define a unique name for every API plugin as well as for methods VERBs. They should also define names for request arguments passed as name/value pair in URI.</p>
-<p>While forging names, designers should respect few rules to ensure that created names are valid and easy to use across platforms.</p>
-<p>All names and strings are UTF-8 encoded.</p>
-<h3 id="names-for-api-plugin">Names for API (plugin)</h3>
-<p>Plugin API name are checked. All characters are authorised except:</p>
-<ul>
-<li>the control characters (000 .. 01f)</li>
-<li>the characters of the set { ' ', '&quot;', '#', '%', '&amp;', ''', '/', '?', '`', '7f' }</li>
-</ul>
-<p>In other words the set of forbidden characters is { 000..020, 022, 023, 025..027, 02f, 03f, 060, 07f }.</p>
-<p>Afb-daemon makes no distinction between lower case and upper case when searching for API/VERB.</p>
-<h3 id="names-for-methods">Names for methods</h3>
-<p>The names of methods VERBs are totally free and not checked.</p>
-<p>However, the validity rules for method's VERB name are the same as for Plugin API name except that the dot(.) character is forbidden.</p>
-<p>Afb-daemon makes no case distinction when searching for an API by name.</p>
-<h3 id="names-for-arguments">Names for arguments</h3>
-<p>Argument's name are not restricted and can be everything you wish.</p>
-<blockquote>
-<p>Warning arguments search is case sensitive and &quot;index&quot; and &quot;Index&quot; are not two different arguments.</p>
-</blockquote>
-<h3 id="forging-names-widely-available">Forging names widely available</h3>
-<p>The key names of javascript object can be almost anything using the arrayed notation:</p>
-<pre><code>object[key] = value</code></pre>
-<p>Nevertheless this is not the case with javascript dot notation:</p>
-<pre><code>object.key = value</code></pre>
-<p>Using the dot notation, the key must be a valid javascript identifier and dash(-) as well as few other reserved characters cannot be used.</p>
-<p>For this reason, we advise developper to chose name compatible with both javascript and HTML notation.</p>
-<p>It is a good practice, even for arguments not to rely on case sensitivity. This may reduce headache strength at debug time, especially with interpreted language like javascript that may not warn you that a variable was not defined.</p>
-<h2 id="writing-a-synchronous-method-implementation">Writing a synchronous method implementation</h2>
-<p>The method <strong>tictactoe/board</strong> is a synchronous implementation. Here is its listing:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * get the board</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="dt">void</span> board(<span class="kw">struct</span> afb_req req)
-{
-    <span class="kw">struct</span> board *board;
-    <span class="kw">struct</span> json_object *description;
-
-    <span class="co">/* retrieves the context for the session */</span>
-    board = board_of_req(req);
-    INFO(afbitf, <span class="st">&quot;method &#39;board&#39; called for boardid %d&quot;</span>, board-&gt;id);
-
-    <span class="co">/* describe the board */</span>
-    description = describe(board);
-
-    <span class="co">/* send the board&#39;s description */</span>
-    afb_req_success(req, description, NULL);
-}</code></pre>
-<p>This example shows many aspects of a synchronous method implementation. Let summarise it:</p>
-<ol type="1">
-<li><p>The function <strong>board_of_req</strong> retrieves the context stored for the plugin: the board.</p></li>
-<li><p>The macro <strong>INFO</strong> sends a message of kind <em>INFO</em> to the logging system. The global variable named <strong>afbitf</strong> used represents the interface to afb-daemon.</p></li>
-<li><p>The function <strong>describe</strong> creates a json_object representing the board.</p></li>
-<li><p>The function <strong>afb_req_success</strong> sends the reply, attaching to it the object <em>description</em>.</p></li>
-</ol>
-<h3 id="the-incoming-request">The incoming request</h3>
-<p>For any implementation, the request is received by a structure of type <strong>struct afb_req</strong>.</p>
-<blockquote>
-<p>Note that this is a PLAIN structure, not a pointer to a structure.</p>
-</blockquote>
-<p>The definition of <strong>struct afb_req</strong> is:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Describes the request by plugins from afb-daemon</span>
-<span class="co"> */</span>
-<span class="kw">struct</span> afb_req {
-    <span class="dt">const</span> <span class="kw">struct</span> afb_req_itf *itf;  <span class="co">/* the interfacing functions */</span>
-    <span class="dt">void</span> *closure;          <span class="co">/* the closure for functions */</span>
-};</code></pre>
-<p>It contains two pointers: first one <em>itf</em>, points to functions used to handle internal request. Second one <em>closure</em> point onto function closure.</p>
-<blockquote>
-<p>The structure must never be used directly. Instead developer should use the intended functions provided by afb-daemon as described here after.</p>
-</blockquote>
-<p><em>req</em> is used to get arguments of the request, to send answer, to store session data.</p>
-<p>This object and its interface is defined and documented in the file names <em>afb/afb-req-itf.h</em></p>
-<p>The above example uses twice <em>req</em> object request.</p>
-<p>The first time, to retrieve the board attached to the session of the request.</p>
-<p>The second time, to send the reply: an object that describes the current board.</p>
-<h3 id="associating-a-client-context-to-a-session">Associating a client context to a session</h3>
-<p>When <em>tic-tac-toe</em> plugin receives a request, it musts get the board describing the game associated to the session.</p>
-<p>For a plugin, having data associated to a session is common. This data is called &quot;plugin context&quot; for the session. Within <em>tic-tac-toe</em> plugin the context is the board.</p>
-<p>Requests <em>afb_req</em> offer four functions for storing and retrieving session associated context.</p>
-<p>These functions are:</p>
-<ul>
-<li><p><strong>afb_req_context_get</strong>: retrieves context data stored for current plugin.</p></li>
-<li><p><strong>afb_req_context_set</strong>: store context data of current plugin.</p></li>
-<li><p><strong>afb_req_context</strong>: if exist retrieves context data of current plugin. if context does not yet exist, creates a new context and store it.</p></li>
-<li><p><strong>afb_req_context_clear</strong>: reset the stored context data.</p></li>
-</ul>
-<p>The plugin <em>tictactoe</em> use a convenient function to retrieve its context: the board. This function is <em>board_of_req</em>:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * retrieves the board of the request</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="kw">inline</span> <span class="kw">struct</span> board *board_of_req(<span class="kw">struct</span> afb_req req)
-{
-    <span class="kw">return</span> afb_req_context(req, (<span class="dt">void</span>*)get_new_board, (<span class="dt">void</span>*)release_board);
-}</code></pre>
-<p>The function <strong>afb_req_context</strong> ensures an existing context for the session of the request. Its two last arguments are functions to allocate and free context. Note function type casts to avoid compilation warnings.</p>
-<p>Here is the definition of the function <strong>afb_req_context</strong></p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Gets the pointer stored by the plugin for the session of &#39;req&#39;.</span>
-<span class="co"> * If the stored pointer is NULL, indicating that no pointer was</span>
-<span class="co"> * already stored, afb_req_context creates a new context by calling</span>
-<span class="co"> * the function &#39;create_context&#39; and stores it with the freeing function</span>
-<span class="co"> * &#39;free_context&#39;.</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="kw">inline</span> <span class="dt">void</span> *afb_req_context(<span class="kw">struct</span> afb_req req, <span class="dt">void</span> *(*create_context)(), <span class="dt">void</span> (*free_context)(<span class="dt">void</span>*))
-{
-    <span class="dt">void</span> *result = afb_req_context_get(req);
-    <span class="kw">if</span> (result == NULL) {
-        result = create_context();
-        afb_req_context_set(req, result, free_context);
-    }
-    <span class="kw">return</span> result;
-}</code></pre>
-<p>The second argument if the function that creates the context. For plugin <em>tic-tac-toe</em> (function <strong>get_new_board</strong>). The function <strong>get_new_board</strong> creates a new board and set usage its count to 1. The boards are checking usage count to free resources when not used.</p>
-<p>The third argument is a function that frees context resources. For plugin <em>tic-tac-toe</em> (function <strong>release_board</strong>). The function <strong>release_board</strong> decrease usage count of the board passed in argument. When usage count falls to zero, data board are freed.</p>
-<p>Definition of other functions dealing with contexts:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Gets the pointer stored by the plugin for the session of &#39;req&#39;.</span>
-<span class="co"> * When the plugin has not yet recorded a pointer, NULL is returned.</span>
-<span class="co"> */</span>
-<span class="dt">void</span> *afb_req_context_get(<span class="kw">struct</span> afb_req req);
-
-<span class="co">/*</span>
-<span class="co"> * Stores for the plugin the pointer &#39;context&#39; to the session of &#39;req&#39;.</span>
-<span class="co"> * The function &#39;free_context&#39; will be called when the session is closed</span>
-<span class="co"> * or if plugin stores an other pointer.</span>
-<span class="co"> */</span>
-<span class="dt">void</span> afb_req_context_set(<span class="kw">struct</span> afb_req req, <span class="dt">void</span> *context, <span class="dt">void</span> (*free_context)(<span class="dt">void</span>*));
-
-<span class="co">/*</span>
-<span class="co"> * Frees the pointer stored by the plugin for the session of &#39;req&#39;</span>
-<span class="co"> * and sets it to NULL.</span>
-<span class="co"> *</span>
-<span class="co"> * Shortcut for: afb_req_context_set(req, NULL, NULL)</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="kw">inline</span> <span class="dt">void</span> afb_req_context_clear(<span class="kw">struct</span> afb_req req)
-{
-    afb_req_context_set(req, NULL, NULL);
-}</code></pre>
-<h3 id="sending-reply-to-a-request">Sending reply to a request</h3>
-<p>Two kinds of replies: successful or failure.</p>
-<blockquote>
-<p>Sending a reply to a request MUST be done once and only once.</p>
-</blockquote>
-<p>It exists two functions for &quot;success&quot; replies: <strong>afb_req_success</strong> and <strong>afb_req_success_f</strong>.</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Sends a reply of kind success to the request &#39;req&#39;.</span>
-<span class="co"> * The status of the reply is automatically set to &quot;success&quot;.</span>
-<span class="co"> * Its send the object &#39;obj&#39; (can be NULL) with an</span>
-<span class="co"> * informationnal comment &#39;info (can also be NULL).</span>
-<span class="co"> *</span>
-<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;obj&#39;.</span>
-<span class="co"> * Thus, in the case where &#39;obj&#39; should remain available after</span>
-<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
-<span class="co"> */</span>
-<span class="dt">void</span> afb_req_success(<span class="kw">struct</span> afb_req req, <span class="kw">struct</span> json_object *obj, <span class="dt">const</span> <span class="dt">char</span> *info);
-
-<span class="co">/*</span>
-<span class="co"> * Same as &#39;afb_req_success&#39; but the &#39;info&#39; is a formatting</span>
-<span class="co"> * string followed by arguments.</span>
-<span class="co"> *</span>
-<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;obj&#39;.</span>
-<span class="co"> * Thus, in the case where &#39;obj&#39; should remain available after</span>
-<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
-<span class="co"> */</span>
-<span class="dt">void</span> afb_req_success_f(<span class="kw">struct</span> afb_req req, <span class="kw">struct</span> json_object *obj, <span class="dt">const</span> <span class="dt">char</span> *info, ...);</code></pre>
-<p>It exists two functions for &quot;failure&quot; replies: <strong>afb_req_fail</strong> and <strong>afb_req_fail_f</strong>.</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Sends a reply of kind failure to the request &#39;req&#39;.</span>
-<span class="co"> * The status of the reply is set to &#39;status&#39; and an</span>
-<span class="co"> * informational comment &#39;info&#39; (can also be NULL) can be added.</span>
-<span class="co"> *</span>
-<span class="co"> * Note that calling afb_req_fail(&quot;success&quot;, info) is equivalent</span>
-<span class="co"> * to call afb_req_success(NULL, info). Thus even if possible it</span>
-<span class="co"> * is strongly recommended to NEVER use &quot;success&quot; for status.</span>
-<span class="co"> *</span>
-<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;obj&#39;.</span>
-<span class="co"> * Thus, in the case where &#39;obj&#39; should remain available after</span>
-<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
-<span class="co"> */</span>
-<span class="dt">void</span> afb_req_fail(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *status, <span class="dt">const</span> <span class="dt">char</span> *info);
-
-<span class="co">/*</span>
-<span class="co"> * Same as &#39;afb_req_fail&#39; but the &#39;info&#39; is a formatting</span>
-<span class="co"> * string followed by arguments.</span>
-<span class="co"> *</span>
-<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;obj&#39;.</span>
-<span class="co"> * Thus, in the case where &#39;obj&#39; should remain available after</span>
-<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
-<span class="co"> */</span>
-<span class="dt">void</span> afb_req_fail_f(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *status, <span class="dt">const</span> <span class="dt">char</span> *info, ...);</code></pre>
-<blockquote>
-<p>For conveniency, these functions automatically call <strong>json_object_put</strong> to release <strong>obj</strong>. Because <strong>obj</strong> usage count is null after being passed to a reply function, it SHOULD not be used anymore. If exceptionally <strong>obj</strong> needs to remain usable after reply function then using <strong>json_object_get</strong> on <strong>obj</strong> to increase usage count and cancels the effect the <strong>json_object_put</strong> is possible.</p>
-</blockquote>
-<h2 id="getting-argument-of-invocation">Getting argument of invocation</h2>
-<p>Many methods expect arguments. Afb-daemon's plugins retrieve arguments by name and not by position.</p>
-<p>Arguments are passed by requests through either HTTP or WebSockets.</p>
-<p>For example, the method <strong>join</strong> of plugin <strong>tic-tac-toe</strong> expects one argument: the <em>boardid</em> to join. Here is an extract:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Join a board</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="dt">void</span> join(<span class="kw">struct</span> afb_req req)
-{
-    <span class="kw">struct</span> board *board, *new_board;
-    <span class="dt">const</span> <span class="dt">char</span> *id;
-
-    <span class="co">/* retrieves the context for the session */</span>
-    board = board_of_req(req);
-    INFO(afbitf, <span class="st">&quot;method &#39;join&#39; called for boardid %d&quot;</span>, board-&gt;id);
-
-    <span class="co">/* retrieves the argument */</span>
-    id = afb_req_value(req, <span class="st">&quot;boardid&quot;</span>);
-    <span class="kw">if</span> (id == NULL)
-        <span class="kw">goto</span> bad_request;
-    ...</code></pre>
-<p>The function <strong>afb_req_value</strong> searches in the request <em>req</em> for argument name passed in the second argument. When argument name is not passed, <strong>afb_req_value</strong> returns NULL.</p>
-<blockquote>
-<p>The search is case sensitive and <em>boardid</em> is not equivalent to <em>BoardId</em>. Nevertheless having argument names that only differ by name case is not a good idea.</p>
-</blockquote>
-<h3 id="basic-functions-for-querying-arguments">Basic functions for querying arguments</h3>
-<p>The function <strong>afb_req_value</strong> is defined here after:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Gets from the request &#39;req&#39; the string value of the argument of &#39;name&#39;.</span>
-<span class="co"> * Returns NULL if when there is no argument of &#39;name&#39;.</span>
-<span class="co"> * Returns the value of the argument of &#39;name&#39; otherwise.</span>
-<span class="co"> *</span>
-<span class="co"> * Shortcut for: afb_req_get(req, name).value</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="kw">inline</span> <span class="dt">const</span> <span class="dt">char</span> *afb_req_value(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *name)
-{
-    <span class="kw">return</span> afb_req_get(req, name).value;
-}</code></pre>
-<p>It is defined as a shortcut to call the function <strong>afb_req_get</strong>. That function is defined here after:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Gets from the request &#39;req&#39; the argument of &#39;name&#39;.</span>
-<span class="co"> * Returns a PLAIN structure of type &#39;struct afb_arg&#39;.</span>
-<span class="co"> * When the argument of &#39;name&#39; is not found, all fields of result are set to NULL.</span>
-<span class="co"> * When the argument of &#39;name&#39; is found, the fields are filled,</span>
-<span class="co"> * in particular, the field &#39;result.name&#39; is set to &#39;name&#39;.</span>
-<span class="co"> *</span>
-<span class="co"> * There is a special name value: the empty string.</span>
-<span class="co"> * The argument of name &quot;&quot; is defined only if the request was made using</span>
-<span class="co"> * an HTTP POST of Content-Type &quot;application/json&quot;. In that case, the</span>
-<span class="co"> * argument of name &quot;&quot; receives the value of the body of the HTTP request.</span>
-<span class="co"> */</span>
-<span class="kw">struct</span> afb_arg afb_req_get(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *name);</code></pre>
-<p>That function takes 2 parameters: the request and the name of the argument to retrieve. It returns a PLAIN structure of type <strong>struct afb_arg</strong>.</p>
-<p>There is a special name that is defined when the request is of type HTTP/POST with a Content-Type being application/json. This name is <strong>&quot;&quot;</strong> (the empty string). In that case, the value of this argument of empty name is the string received as a body of the post and is supposed to be a JSON string.</p>
-<p>The definition of <strong>struct afb_arg</strong> is:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Describes an argument (or parameter) of a request</span>
-<span class="co"> */</span>
-<span class="kw">struct</span> afb_arg {
-    <span class="dt">const</span> <span class="dt">char</span> *name;   <span class="co">/* name of the argument or NULL if invalid */</span>
-    <span class="dt">const</span> <span class="dt">char</span> *value;  <span class="co">/* string representation of the value of the argument */</span>
-                <span class="co">/* original filename of the argument if path != NULL */</span>
-    <span class="dt">const</span> <span class="dt">char</span> *path;   <span class="co">/* if not NULL, path of the received file for the argument */</span>
-                <span class="co">/* when the request is finalized this file is removed */</span>
-};</code></pre>
-<p>The structure returns the data arguments that are known for the request. This data include a field named <strong>path</strong>. This <strong>path</strong> can be accessed using the function <strong>afb_req_path</strong> defined here after:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Gets from the request &#39;req&#39; the path for file attached to the argument of &#39;name&#39;.</span>
-<span class="co"> * Returns NULL if when there is no argument of &#39;name&#39; or when there is no file.</span>
-<span class="co"> * Returns the path of the argument of &#39;name&#39; otherwise.</span>
-<span class="co"> *</span>
-<span class="co"> * Shortcut for: afb_req_get(req, name).path</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="kw">inline</span> <span class="dt">const</span> <span class="dt">char</span> *afb_req_path(<span class="kw">struct</span> afb_req req, <span class="dt">const</span> <span class="dt">char</span> *name)
-{
-    <span class="kw">return</span> afb_req_get(req, name).path;
-}</code></pre>
-<p>The path is only defined for HTTP/POST requests that send file.</p>
-<h3 id="arguments-for-received-files">Arguments for received files</h3>
-<p>As it is explained above, clients can send files using HTTP/POST requests.</p>
-<p>Received files are attached to &quot;file&quot; argument name. For example, the following HTTP fragment (from test/sample-post.html) will send an HTTP/POST request to the method <strong>post/upload-image</strong> with 2 arguments named <em>file</em> and <em>hidden</em>.</p>
-<pre class="sourceCode html"><code class="sourceCode html"><span class="kw">&lt;h2&gt;</span>Sample Post File<span class="kw">&lt;/h2&gt;</span>
-<span class="kw">&lt;form</span><span class="ot"> enctype=</span><span class="st">&quot;multipart/form-data&quot;</span><span class="kw">&gt;</span>
-    <span class="kw">&lt;input</span><span class="ot"> type=</span><span class="st">&quot;file&quot;</span><span class="ot"> name=</span><span class="st">&quot;file&quot;</span> <span class="kw">/&gt;</span>
-    <span class="kw">&lt;input</span><span class="ot"> type=</span><span class="st">&quot;hidden&quot;</span><span class="ot"> name=</span><span class="st">&quot;hidden&quot;</span><span class="ot"> value=</span><span class="st">&quot;bollobollo&quot;</span> <span class="kw">/&gt;</span>
-    <span class="kw">&lt;br&gt;</span>
-    <span class="kw">&lt;button</span><span class="ot"> formmethod=</span><span class="st">&quot;POST&quot;</span><span class="ot"> formaction=</span><span class="st">&quot;api/post/upload-image&quot;</span><span class="kw">&gt;</span>Post File<span class="kw">&lt;/button&gt;</span>
-<span class="kw">&lt;/form&gt;</span></code></pre>
-<p>Argument named <strong>file</strong> should have both its value and path defined.</p>
-<p>The value is the name of the file as it was set by the HTTP client. Generally it is the filename on client side.</p>
-<p>The path is the effective path of saved file on the temporary local storage area of the application. This is a randomly generated and unique filename. It is not linked with the original filename as used on client side.</p>
-<p>After success the plugin can use the uploaded file directly from local storage path with no restriction: read, write, remove, copy, rename... Nevertheless when request reply is set and query terminated, the uploaded temporary file at path is destroyed.</p>
-<h3 id="arguments-as-a-json-object">Arguments as a JSON object</h3>
-<p>Plugins may also request every arguments of a given call as one single object. This feature is provided by the function <strong>afb_req_json</strong> defined here after:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Gets from the request &#39;req&#39; the json object hashing the arguments.</span>
-<span class="co"> * The returned object must not be released using &#39;json_object_put&#39;.</span>
-<span class="co"> */</span>
-<span class="kw">struct</span> json_object *afb_req_json(<span class="kw">struct</span> afb_req req);</code></pre>
-<p>It returns a json object. This object depends on how the request was built:</p>
-<ul>
-<li><p>For HTTP requests, this json object uses key names mapped on argument name. Values are either string for common arguments or object ie: { &quot;file&quot;: &quot;...&quot;, &quot;path&quot;: &quot;...&quot; }</p></li>
-<li><p>For WebSockets requests, returned directly the object as provided by the client.</p></li>
-</ul>
-<blockquote>
-<p>In fact, for Websockets requests, the function <strong>afb_req_value</strong> can be seen as a shortcut to <strong><em>json_object_get_string(json_object_object_get(afb_req_json(req), name))</em></strong></p>
-</blockquote>
-<h2 id="initialisation-of-the-plugin-and-declaration-of-methods">Initialisation of the plugin and declaration of methods</h2>
-<p>To be active, plugin's methods should be declared to afb-daemon. Furthermore, the plugin itself must be recorded.</p>
-<p>The registration mechanism is very basic: when afb-need starts, it loads all plugins listed in: command line or configuration file.</p>
-<p>Loading a plugin follows the following steps:</p>
-<ol type="1">
-<li><p>Afb-daemon loads the plugin with <em>dlopen</em>.</p></li>
-<li><p>Afb-daemon searches for a symbol named <strong>pluginAfbV1Register</strong> using <em>dlsym</em>. This symbol is assumed to be the exported initialisation function of the plugin.</p></li>
-<li><p>Afb-daemon builds an interface object for the plugin.</p></li>
-<li><p>Afb-daemon calls the found function <strong>pluginAfbV1Register</strong> with interface pointer as parameter.</p></li>
-<li><p>Function <strong>pluginAfbV1Register</strong> setups the plugin and initialises it.</p></li>
-<li><p>Function <strong>pluginAfbV1Register</strong> returns the pointer to a structure describing the plugin: version, name (prefix or API name), and list of methods.</p></li>
-<li><p>Afb-daemon checks that the returned version and name can be managed. If so, plugin and its methods are register to become usable as soon as afb-daemon initialisation is finished.</p></li>
-</ol>
-<p>Here after the code used for <strong>pluginAfbV1Register</strong> from plugin <em>tic-tac-toe</em>:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * activation function for registering the plugin called by afb-daemon</span>
-<span class="co"> */</span>
-<span class="dt">const</span> <span class="kw">struct</span> AFB_plugin *pluginAfbV1Register(<span class="dt">const</span> <span class="kw">struct</span> AFB_interface *itf)
-{
-   afbitf = itf;         <span class="co">// records the interface for accessing afb-daemon</span>
-   <span class="kw">return</span> &amp;plugin_description;  <span class="co">// returns the description of the plugin</span>
-}</code></pre>
-<p>It is a very minimal initialisation function because <em>tic-tac-toe</em> plugin doesn't have any application related initialisation step. It merely record daemon's interface and returns its description.</p>
-<p>The variable <strong>afbitf</strong> is a plugin global variable. It keeps the interface to afb-daemon that should be used for logging and pushing events. Here is its declaration:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * the interface to afb-daemon</span>
-<span class="co"> */</span>
-<span class="dt">const</span> <span class="kw">struct</span> AFB_interface *afbitf;</code></pre>
-<p>The description of the plugin is defined here after.</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * array of the methods exported to afb-daemon</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="dt">const</span> <span class="kw">struct</span> AFB_method_desc_v1 plugin_methods[] = {
-   <span class="co">/* VERB&#39;S NAME     SESSION MANAGEMENT          FUNCTION TO CALL  SHORT DESCRIPTION */</span>
-   { .name= <span class="st">&quot;new&quot;</span>,   .session= AFB_SESSION_NONE, .callback= new,   .info= <span class="st">&quot;Starts a new game&quot;</span> },
-   { .name= <span class="st">&quot;play&quot;</span>,  .session= AFB_SESSION_NONE, .callback= play,  .info= <span class="st">&quot;Asks the server to play&quot;</span> },
-   { .name= <span class="st">&quot;move&quot;</span>,  .session= AFB_SESSION_NONE, .callback= move,  .info= <span class="st">&quot;Tells the client move&quot;</span> },
-   { .name= <span class="st">&quot;board&quot;</span>, .session= AFB_SESSION_NONE, .callback= board, .info= <span class="st">&quot;Get the current board&quot;</span> },
-   { .name= <span class="st">&quot;level&quot;</span>, .session= AFB_SESSION_NONE, .callback= level, .info= <span class="st">&quot;Set the server level&quot;</span> },
-   { .name= <span class="st">&quot;join&quot;</span>,  .session= AFB_SESSION_CHECK,.callback= join,  .info= <span class="st">&quot;Join a board&quot;</span> },
-   { .name= <span class="st">&quot;undo&quot;</span>,  .session= AFB_SESSION_NONE, .callback= undo,  .info= <span class="st">&quot;Undo the last move&quot;</span> },
-   { .name= <span class="st">&quot;wait&quot;</span>,  .session= AFB_SESSION_NONE, .callback= wait,  .info= <span class="st">&quot;Wait for a change&quot;</span> },
-   { .name= NULL } <span class="co">/* marker for end of the array */</span>
-};
-
-<span class="co">/*</span>
-<span class="co"> * description of the plugin for afb-daemon</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="dt">const</span> <span class="kw">struct</span> AFB_plugin plugin_description =
-{
-   <span class="co">/* description conforms to VERSION 1 */</span>
-   .type= AFB_PLUGIN_VERSION_1,
-   .v1= {               <span class="co">/* fills the v1 field of the union when AFB_PLUGIN_VERSION_1 */</span>
-      .prefix= <span class="st">&quot;tictactoe&quot;</span>,     <span class="co">/* the API name (or plugin name or prefix) */</span>
-      .info= <span class="st">&quot;Sample tac-tac-toe game&quot;</span>, <span class="co">/* short description of of the plugin */</span>
-      .methods = plugin_methods     <span class="co">/* the array describing the methods of the API */</span>
-   }
-};</code></pre>
-<p>The structure <strong>plugin_description</strong> describes the plugin. It declares the type and version of the plugin, its name, a short description and its methods list.</p>
-<p>The list of methods is an array of structures describing the methods and terminated by a NULL marker.</p>
-<p>In version one of afb-damon plugin, a method description contains 4 fields:</p>
-<ul>
-<li><p>the name of the method,</p></li>
-<li><p>the session management flags,</p></li>
-<li><p>the implementation function to be call for the method,</p></li>
-<li><p>a short description.</p></li>
-</ul>
-<p>The structure describing methods is defined as follows:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Description of one method of the API provided by the plugin</span>
-<span class="co"> * This enumeration is valid for plugins of type 1</span>
-<span class="co"> */</span>
-<span class="kw">struct</span> AFB_method_desc_v1
-{
-       <span class="dt">const</span> <span class="dt">char</span> *name;                       <span class="co">/* name of the method */</span>
-       <span class="kw">enum</span> AFB_session_v1 session;            <span class="co">/* authorisation and session requirements of the method */</span>
-       <span class="dt">void</span> (*callback)(<span class="kw">struct</span> afb_req req);   <span class="co">/* callback function implementing the method */</span>
-       <span class="dt">const</span> <span class="dt">char</span> *info;                       <span class="co">/* textual description of the method */</span>
-};</code></pre>
-<p>For technical reasons, the enumeration <strong>enum AFB_session_v1</strong> is not exactly an enumeration but the wrapper of constant definitions that can be mixed using bitwise or (the C operator |).</p>
-<p>The constants that can bit mixed are:</p>
-<table>
-<thead>
-<tr class="header">
-<th style="text-align: left;">Constant name</th>
-<th style="text-align: left;">Meaning</th>
-</tr>
-</thead>
-<tbody>
-<tr class="odd">
-<td style="text-align: left;"><strong>AFB_SESSION_CREATE</strong></td>
-<td style="text-align: left;">Equals to AFB_SESSION_LOA_EQ_0</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;"><strong>AFB_SESSION_CLOSE</strong></td>
-<td style="text-align: left;">Closes the session after the reply and set the LOA to 0</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;"><strong>AFB_SESSION_RENEW</strong></td>
-<td style="text-align: left;">Refreshes the token of authentification</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;"><strong>AFB_SESSION_CHECK</strong></td>
-<td style="text-align: left;">Just requires the token authentification</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_LE_0</strong></td>
-<td style="text-align: left;">Requires the current LOA to be lesser then or equal to 0</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_LE_1</strong></td>
-<td style="text-align: left;">Requires the current LOA to be lesser then or equal to 1</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_LE_2</strong></td>
-<td style="text-align: left;">Requires the current LOA to be lesser then or equal to 2</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_LE_3</strong></td>
-<td style="text-align: left;">Requires the current LOA to be lesser then or equal to 3</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_GE_0</strong></td>
-<td style="text-align: left;">Requires the current LOA to be greater then or equal to 0</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_GE_1</strong></td>
-<td style="text-align: left;">Requires the current LOA to be greater then or equal to 1</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_GE_2</strong></td>
-<td style="text-align: left;">Requires the current LOA to be greater then or equal to 2</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_GE_3</strong></td>
-<td style="text-align: left;">Requires the current LOA to be greater then or equal to 3</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_EQ_0</strong></td>
-<td style="text-align: left;">Requires the current LOA to be equal to 0</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_EQ_1</strong></td>
-<td style="text-align: left;">Requires the current LOA to be equal to 1</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_EQ_2</strong></td>
-<td style="text-align: left;">Requires the current LOA to be equal to 2</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;"><strong>AFB_SESSION_LOA_EQ_3</strong></td>
-<td style="text-align: left;">Requires the current LOA to be equal to 3</td>
-</tr>
-</tbody>
-</table>
-<p>If any of this flag is set, afb-daemon requires an authentication token as if <strong>AFB_SESSION_CHECK</strong> flag was also set.</p>
-<p>The special value <strong>AFB_SESSION_NONE</strong> is zero and can be used to bypass token check.</p>
-<blockquote>
-<p>Note that <strong>AFB_SESSION_CREATE</strong> and <strong>AFB_SESSION_CLOSE</strong> might be removed in later versions.</p>
-</blockquote>
-<h2 id="sending-messages-to-the-log-system">Sending messages to the log system</h2>
-<p>Afb-daemon provides 4 levels of verbosity and 5 methods for logging messages.</p>
-<p>The verbosity is managed. Options allow the change the verbosity of afb-daemon and the verbosity of the plugins can be set plugin by plugin.</p>
-<p>The methods for logging messages are defined as macros that test the verbosity level and that call the real logging function only if the message must be output. This avoid evaluation of arguments of the formatting messages if the message must not be output.</p>
-<h3 id="verbs-for-logging-messages">Verbs for logging messages</h3>
-<p>The 5 logging methods are:</p>
-<table>
-<thead>
-<tr class="header">
-<th style="text-align: left;">Macro</th>
-<th style="text-align: center;">Verbosity</th>
-<th style="text-align: left;">Meaning</th>
-<th style="text-align: center;">syslog level</th>
-</tr>
-</thead>
-<tbody>
-<tr class="odd">
-<td style="text-align: left;">ERROR</td>
-<td style="text-align: center;">0</td>
-<td style="text-align: left;">Error conditions</td>
-<td style="text-align: center;">3</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;">WARNING</td>
-<td style="text-align: center;">1</td>
-<td style="text-align: left;">Warning conditions</td>
-<td style="text-align: center;">4</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;">NOTICE</td>
-<td style="text-align: center;">1</td>
-<td style="text-align: left;">Normal but significant condition</td>
-<td style="text-align: center;">5</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;">INFO</td>
-<td style="text-align: center;">2</td>
-<td style="text-align: left;">Informational</td>
-<td style="text-align: center;">6</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;">DEBUG</td>
-<td style="text-align: center;">3</td>
-<td style="text-align: left;">Debug-level messages</td>
-<td style="text-align: center;">7</td>
-</tr>
-</tbody>
-</table>
-<p>You can note that the 2 methods <strong>WARNING</strong> and <strong>INFO</strong> have the same level of verbosity. But they don't have the same <em>syslog level</em>. It means that they are output with a different level on the logging system.</p>
-<p>All of these methods have the same signature:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="dt">void</span> ERROR(<span class="dt">const</span> <span class="kw">struct</span> AFB_interface *afbitf, <span class="dt">const</span> <span class="dt">char</span> *message, ...);</code></pre>
-<p>The first argument <strong>afbitf</strong> is the interface to afb daemon that the plugin received at initialisation time when <strong>pluginAfbV1Register</strong> is called.</p>
-<p>The second argument <strong>message</strong> is a formatting string compatible with printf/sprintf.</p>
-<p>The remaining arguments are arguments of the formating message like with printf.</p>
-<h3 id="managing-verbosity">Managing verbosity</h3>
-<p>Depending on the level of verbosity, the messages are output or not. The following table explains what messages will be output depending ont the verbosity level.</p>
-<table>
-<thead>
-<tr class="header">
-<th style="text-align: center;">Level of verbosity</th>
-<th style="text-align: left;">Outputed macro</th>
-</tr>
-</thead>
-<tbody>
-<tr class="odd">
-<td style="text-align: center;">0</td>
-<td style="text-align: left;">ERROR</td>
-</tr>
-<tr class="even">
-<td style="text-align: center;">1</td>
-<td style="text-align: left;">ERROR + WARNING + NOTICE</td>
-</tr>
-<tr class="odd">
-<td style="text-align: center;">2</td>
-<td style="text-align: left;">ERROR + WARNING + NOTICE + INFO</td>
-</tr>
-<tr class="even">
-<td style="text-align: center;">3</td>
-<td style="text-align: left;">ERROR + WARNING + NOTICE + INFO + DEBUG</td>
-</tr>
-</tbody>
-</table>
-<h3 id="output-format-and-destination">Output format and destination</h3>
-<p>The syslog level is used for forging a prefix to the message. The prefixes are:</p>
-<table>
-<thead>
-<tr class="header">
-<th style="text-align: center;">syslog level</th>
-<th style="text-align: left;">prefix</th>
-</tr>
-</thead>
-<tbody>
-<tr class="odd">
-<td style="text-align: center;">0</td>
-<td style="text-align: left;">&lt;0&gt; EMERGENCY</td>
-</tr>
-<tr class="even">
-<td style="text-align: center;">1</td>
-<td style="text-align: left;">&lt;1&gt; ALERT</td>
-</tr>
-<tr class="odd">
-<td style="text-align: center;">2</td>
-<td style="text-align: left;">&lt;2&gt; CRITICAL</td>
-</tr>
-<tr class="even">
-<td style="text-align: center;">3</td>
-<td style="text-align: left;">&lt;3&gt; ERROR</td>
-</tr>
-<tr class="odd">
-<td style="text-align: center;">4</td>
-<td style="text-align: left;">&lt;4&gt; WARNING</td>
-</tr>
-<tr class="even">
-<td style="text-align: center;">5</td>
-<td style="text-align: left;">&lt;5&gt; NOTICE</td>
-</tr>
-<tr class="odd">
-<td style="text-align: center;">6</td>
-<td style="text-align: left;">&lt;6&gt; INFO</td>
-</tr>
-<tr class="even">
-<td style="text-align: center;">7</td>
-<td style="text-align: left;">&lt;7&gt; DEBUG</td>
-</tr>
-</tbody>
-</table>
-<p>The message is pushed to standard error. The final destination of the message depends on how systemd service was configured through its variable <strong>StandardError</strong>. It can be journal, syslog or kmsg. (See man sd-daemon).</p>
-<h2 id="sending-events">Sending events</h2>
-<p>Since version 0.5, plugins can broadcast events to any potential listener. As today only unattended even are supported. Targeted events are expected for next coming version.</p>
-<p>The plugin <em>tic-tac-toe</em> broadcasts events when the board changes. This is done in the function <strong>changed</strong>:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * signals a change of the board</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="dt">void</span> changed(<span class="kw">struct</span> board *board, <span class="dt">const</span> <span class="dt">char</span> *reason)
-{
-    ...
-    <span class="kw">struct</span> json_object *description;
-
-    <span class="co">/* get the description */</span>
-    description = describe(board);
-
-    ...
-
-    afb_daemon_broadcast_event(afbitf-&gt;daemon, reason, description);
-}</code></pre>
-<p>The description of the changed board is pushed via the daemon interface.</p>
-<p>Within plugin <em>tic-tac-toe</em>, <em>reason</em> indicates the origin of the change. In function <strong>afb_daemon_broadcast_event</strong> the second parameter is the name of broadcasted event. The third argument is the object that is transmitted with the event.</p>
-<p>Function <strong>afb_daemon_broadcast_event</strong> is defined here after:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * Broadcasts widely the event of &#39;name&#39; with the data &#39;object&#39;.</span>
-<span class="co"> * &#39;object&#39; can be NULL.</span>
-<span class="co"> * &#39;daemon&#39; MUST be the daemon given in interface when activating the plugin.</span>
-<span class="co"> *</span>
-<span class="co"> * For conveniency, the function calls &#39;json_object_put&#39; for &#39;object&#39;.</span>
-<span class="co"> * Thus, in the case where &#39;object&#39; should remain available after</span>
-<span class="co"> * the function returns, the function &#39;json_object_get&#39; shall be used.</span>
-<span class="co"> */</span>
-<span class="dt">void</span> afb_daemon_broadcast_event(<span class="kw">struct</span> afb_daemon daemon, <span class="dt">const</span> <span class="dt">char</span> *name, <span class="kw">struct</span> json_object *object);</code></pre>
-<blockquote>
-<p>Be aware, as with reply functions <strong>object</strong> is automatically released using <strong>json_object_put</strong> when using this function. Call <strong>json_object_get</strong> before calling <strong>afb_daemon_broadcast_event</strong> to keep <strong>object</strong> available after function returns.</p>
-</blockquote>
-<p>Event name received by listeners is prefixed with plugin name. So when a change occurs after a move, the reason is <strong>move</strong> and every clients receive an event <strong>tictactoe/move</strong>.</p>
-<blockquote>
-<p>Note that nothing is said about case sensitivity of event names. However, the event is always prefixed with the name that the plugin declared, with the same case, followed with a slash /. Thus it is safe to compare event using a case sensitive comparison.</p>
-</blockquote>
-<h2 id="writing-an-asynchronous-method-implementation">Writing an asynchronous method implementation</h2>
-<p>The <em>tic-tac-toe</em> example allows two clients or more to share the same board. This is implemented by the method <strong>join</strong> that illustrated partly how to retrieve arguments.</p>
-<p>When two or more clients are sharing a same board, one of them can wait until the state of the board changes, but this could also be implemented using events because an even is generated each time the board changes.</p>
-<p>In this case, the reply to the wait is sent only when the board changes. See the diagram below:</p>
-<pre><code>CLIENT A       CLIENT B         TIC-TAC-TOE
-   |              |                  |
-   +--------------|-----------------&gt;| wait . . . . . . . .
-   |              |                  |                     .
-   :              :                  :                      .
-   :              :                  :                      .
-   |              |                  |                      .
-   |              +-----------------&gt;| move . . .           .
-   |              |                  |          V           .
-   |              |&lt;-----------------+ success of move      .
-   |              |                  |                    .
-   |&lt;-------------|------------------+ success of wait  &lt;</code></pre>
-<p>Here, this is an invocation of the plugin by an other client that unblock the suspended <em>wait</em> call. Nevertheless in most case this should be a timer, a hardware event, a sync with a concurrent process or thread, ...</p>
-<p>Common case of an asynchronous implementation.</p>
-<p>Here is the listing of the function <strong>wait</strong>:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="dt">static</span> <span class="dt">void</span> wait(<span class="kw">struct</span> afb_req req)
-{
-    <span class="kw">struct</span> board *board;
-    <span class="kw">struct</span> waiter *waiter;
-
-    <span class="co">/* retrieves the context for the session */</span>
-    board = board_of_req(req);
-    INFO(afbitf, <span class="st">&quot;method &#39;wait&#39; called for boardid %d&quot;</span>, board-&gt;id);
-
-    <span class="co">/* creates the waiter and enqueues it */</span>
-    waiter = calloc(<span class="dv">1</span>, <span class="kw">sizeof</span> *waiter);
-    waiter-&gt;req = req;
-    waiter-&gt;next = board-&gt;waiters;
-    afb_req_addref(req);
-    board-&gt;waiters = waiter;
-}</code></pre>
-<p>After retrieving the board, the function adds a new waiter to waiters list and returns without setting a reply.</p>
-<p>Before returning, it increases <strong>req</strong> request's reference count using <strong>afb_req_addref</strong> function.</p>
-<blockquote>
-<p>When a method returns without setting a reply, it <strong>MUST</strong> increment request's reference count using <strong>afb_req_addref</strong>. If unpredictable behaviour may pop up.</p>
-</blockquote>
-<p>Later, when a board changes, it calls <em>tic-tac-toe</em> <strong>changed</strong> function with reason of change in parameter.</p>
-<p>Here is the full listing of the function <strong>changed</strong>:</p>
-<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
-<span class="co"> * signals a change of the board</span>
-<span class="co"> */</span>
-<span class="dt">static</span> <span class="dt">void</span> changed(<span class="kw">struct</span> board *board, <span class="dt">const</span> <span class="dt">char</span> *reason)
-{
-    <span class="kw">struct</span> waiter *waiter, *next;
-    <span class="kw">struct</span> json_object *description;
-
-    <span class="co">/* get the description */</span>
-    description = describe(board);
-
-    waiter = board-&gt;waiters;
-    board-&gt;waiters = NULL;
-    <span class="kw">while</span> (waiter != NULL) {
-        next = waiter-&gt;next;
-        afb_req_success(waiter-&gt;req, json_object_get(description), reason);
-        afb_req_unref(waiter-&gt;req);
-        free(waiter);
-        waiter = next;
-    }
-
-    afb_event_sender_push(afb_daemon_get_event_sender(afbitf-&gt;daemon), reason, description);
-}</code></pre>
-<p>The list of waiters is walked and a reply is sent to each waiter. After sending the reply, the reference count of the request is decremented using <strong>afb_req_unref</strong> to allow resources to be freed.</p>
-<blockquote>
-<p>The reference count <strong>MUST</strong> be decremented using <strong>afb_req_unref</strong> to free resources and avoid memory leaks. This usage count decrement should happen <strong>AFTER</strong> setting reply or bad things may happen.</p>
-</blockquote>
-<h2 id="how-to-build-a-plugin">How to build a plugin</h2>
-<p>Afb-daemon provides a <em>pkg-config</em> configuration file that can be queried by providing <strong>afb-daemon</strong> in command line arguments. This configuration file provides data that should be used for plugins compilation. Examples:</p>
-<pre class="sourceCode bash"><code class="sourceCode bash">$ <span class="kw">pkg-config</span> --cflags afb-daemon
-$ <span class="kw">pkg-config</span> --libs afb-daemon</code></pre>
-<h3 id="example-for-cmake-meta-build-system">Example for cmake meta build system</h3>
-<p>This example is the extract for building the plugin <em>afm-main</em> using <em>CMAKE</em>.</p>
-<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="fu">pkg_check_modules</span>(afb afb-daemon)
-<span class="kw">if</span>(afb_FOUND)
-    <span class="kw">message</span>(<span class="ot">STATUS</span> <span class="st">&quot;Creation afm-main-plugin for AFB-DAEMON&quot;</span>)
-    <span class="kw">add_library</span>(afm-main-plugin <span class="ot">MODULE</span> afm-main-plugin.c)
-    <span class="kw">target_compile_options</span>(afm-main-plugin <span class="ot">PRIVATE</span> <span class="dv">${afb_CFLAGS}</span>)
-    <span class="kw">target_include_directories</span>(afm-main-plugin <span class="ot">PRIVATE</span> <span class="dv">${afb_INCLUDE_DIRS}</span>)
-    <span class="kw">target_link_libraries</span>(afm-main-plugin utils <span class="dv">${afb_LIBRARIES}</span>)
-    <span class="kw">set_target_properties</span>(afm-main-plugin <span class="ot">PROPERTIES</span>
-        <span class="ot">PREFIX</span> <span class="st">&quot;&quot;</span>
-        <span class="ot">LINK_FLAGS</span> <span class="st">&quot;-Wl,--version-script=</span><span class="dv">${CMAKE_CURRENT_SOURCE_DIR}</span><span class="st">/afm-main-plugin.export-map&quot;</span>
-    )
-    <span class="kw">install</span>(<span class="ot">TARGETS</span> afm-main-plugin <span class="ot">LIBRARY</span> <span class="ot">DESTINATION</span> <span class="dv">${plugin_dir}</span>)
-<span class="kw">else</span>()
-    <span class="kw">message</span>(<span class="ot">STATUS</span> <span class="st">&quot;Not creating the plugin for AFB-DAEMON&quot;</span>)
-<span class="kw">endif</span>()</code></pre>
-<p>Let now describe some of these lines.</p>
-<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="fu">pkg_check_modules</span>(afb afb-daemon)</code></pre>
-<p>This first lines searches to the <em>pkg-config</em> configuration file for <strong>afb-daemon</strong>. Resulting data are stored in the following variables:</p>
-<table>
-<thead>
-<tr class="header">
-<th style="text-align: left;">Variable</th>
-<th style="text-align: left;">Meaning</th>
-</tr>
-</thead>
-<tbody>
-<tr class="odd">
-<td style="text-align: left;">afb_FOUND</td>
-<td style="text-align: left;">Set to 1 if afb-daemon plugin development files exist</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;">afb_LIBRARIES</td>
-<td style="text-align: left;">Only the libraries (w/o the '-l') for compiling afb-daemon plugins</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;">afb_LIBRARY_DIRS</td>
-<td style="text-align: left;">The paths of the libraries (w/o the '-L') for compiling afb-daemon plugins</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;">afb_LDFLAGS</td>
-<td style="text-align: left;">All required linker flags for compiling afb-daemon plugins</td>
-</tr>
-<tr class="odd">
-<td style="text-align: left;">afb_INCLUDE_DIRS</td>
-<td style="text-align: left;">The '-I' preprocessor flags (w/o the '-I') for compiling afb-daemon plugins</td>
-</tr>
-<tr class="even">
-<td style="text-align: left;">afb_CFLAGS</td>
-<td style="text-align: left;">All required cflags for compiling afb-daemon plugins</td>
-</tr>
-</tbody>
-</table>
-<p>If development files are found, the plugin can be added to the set of target to build.</p>
-<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="kw">add_library</span>(afm-main-plugin <span class="ot">MODULE</span> afm-main-plugin.c)</code></pre>
-<p>This line asks to create a shared library having a single source file named afm-main-plugin.c to be compiled. The default name of the created shared object is <strong>libafm-main-plugin.so</strong>.</p>
-<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="kw">set_target_properties</span>(afm-main-plugin <span class="ot">PROPERTIES</span>
-    <span class="ot">PREFIX</span> <span class="st">&quot;&quot;</span>
-    <span class="ot">LINK_FLAGS</span> <span class="st">&quot;-Wl,--version-script=</span><span class="dv">${CMAKE_CURRENT_SOURCE_DIR}</span><span class="st">/afm-main-plugin.export-map&quot;</span>
-)</code></pre>
-<p>This lines are doing two things:</p>
-<ol type="1">
-<li><p>It renames the built library from <strong>libafm-main-plugin.so</strong> to <strong>afm-main-plugin.so</strong> by removing the implicitly added prefix <em>lib</em>. This step is not mandatory because afb-daemon doesn't check names of files at load time. The only filename convention used by afb-daemon relates to <strong>.so</strong> termination. *.so pattern is used when afb-daemon automatically discovers plugin from a directory hierarchy.</p></li>
-<li><p>It applies a version script at link time to only export the reserved name <strong>pluginAfbV1Register</strong> for registration entry point. By default, when building a shared library linker exports all the public symbols (C functions that are not <strong>static</strong>).</p></li>
-</ol>
-<p>Next line are:</p>
-<pre class="sourceCode cmake"><code class="sourceCode cmake"><span class="kw">target_include_directories</span>(afm-main-plugin <span class="ot">PRIVATE</span> <span class="dv">${afb_INCLUDE_DIRS}</span>)
-<span class="kw">target_link_libraries</span>(afm-main-plugin utils <span class="dv">${afb_LIBRARIES}</span>)</code></pre>
-<p>As you can see it uses the variables computed by <strong><em>pkg_check_modules(afb afb-daemon)</em></strong> to configure the compiler and the linker.</p>
-<h3 id="exporting-the-function-pluginafbv1register">Exporting the function pluginAfbV1Register</h3>
-<p>The function <strong>pluginAfbV1Register</strong> MUST be exported. This can be achieved using a version script at link time. Here after is a version script used for <em>tic-tac-toe</em> (plugins/samples/export.map).</p>
-<pre><code>{ global: pluginAfbV1Register; local: *; };</code></pre>
-<p>This sample <a href="https://sourceware.org/binutils/docs-2.26/ld/VERSION.html#VERSION">version script</a> exports as global the symbol <em>pluginAfbV1Register</em> and hides any other symbols.</p>
-<p>This version script is added to the link options using the option <strong>--version-script=export.map</strong> is given directly to the linker or using the option <strong>-Wl,--version-script=export.map</strong> when the option is given to the C compiler.</p>
-<h3 id="building-within-yocto">Building within yocto</h3>
-<p>Adding a dependency to afb-daemon is enough. See below:</p>
-<pre><code>DEPENDS += &quot; afb-daemon &quot;</code></pre>
-</body>
-</html>
diff --git a/doc/afb-plugin-writing.md b/doc/afb-plugin-writing.md
deleted file mode 100644
index 9e13d0d5..00000000
--- a/doc/afb-plugin-writing.md
+++ /dev/null
@@ -1,1227 +0,0 @@
-HOWTO WRITE a PLUGIN for AFB-DAEMON
-===================================
-    version: 1
-    Date:    09 juin 2016
-    Author:  José Bollo
-
-
-
-Summary
--------
-
-Afb-daemon binders serve files through HTTP protocol
-and offers to developers the capability to expose application API methods through
-HTTP or WebSocket protocol.
-
-Binder plugins are used to add API to afb-daemon.
-This part describes how to write a plugin for afb-daemon.
-
-Excepting this summary, this document target developers.
-
-Before moving further through an example, here after
-a short overview of binder plugins fundamentals.
-
-### Nature of a plugin
-
-A plugin is an independent piece of software. A plugin is self contain and exposes application logic as sharable library.
-A plugin is intended to be dynamically loaded by afb-daemon to expose application API.
-
-Technically, a binder plugin does not reference and is not linked with any afb-daemon library.
-
-### Class of plugins
-
-Application binder supports two kinds of plugins: application plugins and service plugins.
-Technically both class of plugin are equivalent are use the same coding convention. Only sharing mode and security context diverge.
-
-#### Application-plugins
-
-Application-plugins implements the glue in between application's UI and services. Every AGL application
-has a corresponding binder that typically activates one or many plugins to interface the application logic with lower platform services.
-When an application is started by the AGL application framework, a dedicate binder is started that loads/activates application plugin(s). 
-API expose by application-plugin are executed within corresponding application security context.
-
-Application plugins generally handle a unique context for a unique client. As the application framework start
-a dedicated instance of afb_daemon for each AGL application, if a given plugin is used within multiple application each of those
-application get a new and private instance of eventually "shared" plugin.
-
-#### Service-plugins
-
-Service-plugins enable API activation within corresponding service security context and not within calling application context. 
-Service-plugins are intended to run as a unique instance. Service-plugins can be shared in between multiple clients.
-
-Service-plugins can either be stateless or manage client context. When managing context each client get a private context.
-
-Sharing may either be global to the platform (ie: GPS service) or dedicated to a given user (ie: user preferences)
- 
-### Live cycle of plugins within afb-daemon
-
-Application and service plugins are loaded and activated each time a new afb-daemon is started.
-
-At launch time, every loaded plugin initialise itself.
-If a single plugin initialisation fail corresponding instance of afb-daemon self aborts.
-
-Conversely, when a plugin initialisation succeeds, it should register 
-its unique name as well as the list of verbs attached to the methods it exposes.
-
-When initialised, on request from application clients to the right API/verb, plugin methods
-are activated by the afb-daemon attached to the application or service.
-
-At exit time, no special action is enforced by afb-daemon. When a specific actions is required at afb-daemon stop,
-developers should use 'atexit/on_exit' during plugin initialisation sequence to register a custom exit function.
-
-### Plugin Contend
-
-Afb-daemon's plugin register two classes of objects: names and functions.
-
-Plugins declare categories of names:
- - A unique plugin name to access all API expose by this plugin,
- - One name for each methods/verbs provided by this plugin.
-
-Plugins declare two categories of functions:
- - function use for the initialisation
- - functions implementing exposed API methods
-
-Afb-daemon parses URI requests to extract the API(plugin name) and the VERB(method to activate).
-As an example, URI **foo/bar** translates to plugin named **foo** and method named **bar**.
-To serve such a request, afb-daemon looks for an active plugin named **foo** and then within this plugin for a method named **bar**.
-When find afb-daemon calls corresponding method with attached parameter if any.
-
-Afb-daemon ignores letter case when parsing URI. Thus **TicTacToe/Board** and **tictactoe/board** are equivalent.
-
-#### The name of the plugin
-
-The name of a given plugin is also known as the name
-of the API prefix that defines the plugin.
-
-The name of a plugin SHOULD be unique within a given afb-daemon instance.
-
-For example, when a client of afb-daemon calls a URI named **foo/bar**. Afb-daemon
-extracts the prefix **foo** and the suffix **bar**. **foo** must match a plugin name and **bar** a VERB attached to some method.
-
-#### Names of methods
-
-Each plugin exposes a set of methods that can be called
-by the clients of a given afb-daemon.
-
-VERB's name attached to a given plugin (API) MUST be unique within a plugin.
-
-Plugins static declaration link VERBS to corresponding methods. 
-When clients emit requests on a given API/VERB corresponding method is called by afb-daemon.
-
-#### Initialisation function
-
-Plugin's initialisation function serves several purposes.
-
-1. It allows afb-daemon to control plugin version depending on initialisation function name.
-As today, the only supported initialisation function is **pluginAfbV1Register**. This identifies
-version "one" of plugins.
-
-2. It allows plugins to initialise itself.
-
-3. It enables names declarations: descriptions, requirements and implementations of exposed API/VERB.
-
-#### Functions instantiation of API/VERBs
-
-When an API/VERB is called, afb-daemon constructs a request object. Then it 
-passes this request object to the implementation function corresponding to requested method, this
-within attached API plugin.
-
-An implementation function receives a request object that
-is used to: get arguments of the request, send
-answer, store session data.
-
-A plugin MUST set an answer to every received requests.
-
-Nevertheless it is not mandatory to set the answer
-before returning from API/VERB implementing function.
-This behaviour is important for asynchronous actions.
-
-API/VERB implementation that set an answer before returning are called *synchronous implementations*.
-Those that do not systematically set an answer before returning are called *asynchronous implementations*.
-
-Asynchronous implementations typically launch asynchronous actions. They record some context at
-request time and provide answer to the request only at completion of asynchronous actions.
-
-The Tic-Tac-Toe example
------------------------
-
-This part explains how to write an afb-plugin.
-For the sake of being practical it uses many
-examples based on tic-tac-toe.
-This plugin example is in *plugins/samples/tic-tac-toe.c*.
-
-This plugin is named ***tictactoe***.
-
-Dependencies when compiling
----------------------------
-
-Afb-daemon provides a configuration file for *pkg-config*.
-Typing the command
-
-	pkg-config --cflags afb-daemon
-
-Print flags use for compilation:
-
-	$ pkg-config --cflags afb-daemon
-	-I/opt/local/include -I/usr/include/json-c 
-
-For linking, you should use
-
-	$ pkg-config --libs afb-daemon
-	-ljson-c
-
-Afb-daemon automatically includes dependency to json-c.
-This is activated through **Requires** keyword in pkg-config.
-While almost every plugin replies on **json-c** this is not a must have dependency.
-
-Internally, afb-daemon relies on **libsystemd** for its event loop, as well 
-as for its binding to D-Bus.
-Plugins developers are encouraged to leverage **libsystemd** when possible.
-Nevertheless there is no hard dependency to **libsystemd** if ever
-you rather not use it, feel free to do so.
-
-> Afb-daemon plugin are fully self contain. They do not enforce dependency on any libraries from the application framework.
-> Afb-daemon dependencies requirer to run AGL plugins are given at runtime through pointers leveraging read-only
-> memory feature.
-
-Header files to include
------------------------
-
-Plugin *tictactoe* has following includes:
-
-```C
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <json-c/json.h>
-#include <afb/afb-plugin.h>
-```
-
-Header *afb/afb-plugin.h* is the only hard dependency, it includes all features
-that a plugin MUST HAVE. Outside of includes used to support application logic,
-common external headers used within plugins are:
-
-- *json-c/json.h*: should be include to handle json objects;
-- *systemd/sd-event.h*: should be include to access event main loop;
-- *systemd/sd-bus.h*: should be include for dbus connections.
-
-The *tictactoe* plugin does not leverage systemd features, also only json.h
-is used on top of mandatory afb/afb-plugin.h.
-
-When including *afb/afb-plugin.h*, the macro **_GNU_SOURCE** MUST be
-defined.
-
-Choosing names
---------------
-
-Designers of plugins should define a unique name for every API plugin
-as well as for methods VERBs. They should also define names for request
-arguments passed as name/value pair in URI.
-
-While forging names, designers should respect few rules to
-ensure that created names are valid and easy to use across platforms.
-
-All names and strings are UTF-8 encoded.
-
-### Names for API (plugin)
-
-Plugin API name are checked.
-All characters are authorised except:
-
-- the control characters (\u0000 .. \u001f)
-- the characters of the set { ' ', '"', '#', '%', '&',
-  '\'', '/', '?', '`', '\x7f' }
-
-In other words the set of forbidden characters is
-{ \u0000..\u0020, \u0022, \u0023, \u0025..\u0027,
-  \u002f, \u003f, \u0060, \u007f }.
-
-Afb-daemon makes no distinction between lower case
-and upper case when searching for API/VERB.
-
-### Names for methods
-
-The names of methods VERBs are totally free and not checked.
-
-However, the validity rules for method's VERB name are the
-same as for Plugin API name except that the dot(.) character
-is forbidden.
-
-Afb-daemon makes no case distinction when searching for an API by name.
-
-### Names for arguments
-
-Argument's name are not restricted and can be everything you wish.
-
-> Warning arguments search is case sensitive and "index" and "Index"
-> are not two different arguments.
-
-### Forging names widely available
-
-The key names of javascript object can be almost
-anything using the arrayed notation:
-
-	object[key] = value
-
-Nevertheless this is not the case with javascript dot notation:
-
-	object.key = value
-
-Using the dot notation, the key must be a valid javascript
-identifier and dash(-) as well as few other reserved characters cannot be used.
-
-For this reason, we advise developper to chose name compatible with both javascript and HTML notation.
-
-It is a good practice, even for arguments not to rely on case sensitivity.
-This may reduce headache strength at debug time, especially with interpreted language like
-javascript that may not warn you that a variable was not defined.
-
-Writing a synchronous method implementation
------------------------------------------
-
-The method **tictactoe/board** is a synchronous implementation.
-Here is its listing:
-
-```C
-/*
- * get the board
- */
-static void board(struct afb_req req)
-{
-	struct board *board;
-	struct json_object *description;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'board' called for boardid %d", board->id);
-
-	/* describe the board */
-	description = describe(board);
-
-	/* send the board's description */
-	afb_req_success(req, description, NULL);
-}
-```
-
-This example shows many aspects of a synchronous
-method implementation. Let summarise it:
-
-1. The function **board_of_req** retrieves the context stored
-for the plugin: the board.
-
-2. The macro **INFO** sends a message of kind *INFO*
-to the logging system. The global variable named **afbitf**
-used represents the interface to afb-daemon.
-
-3. The function **describe** creates a json_object representing
-the board.
-
-4. The function **afb_req_success** sends the reply, attaching to
-it the object *description*.
-
-### The incoming request
-
-For any implementation, the request is received by a structure of type
-**struct afb_req**.
-
-> Note that this is a PLAIN structure, not a pointer to a structure.
-
-The definition of **struct afb_req** is:
-
-```C
-/*
- * Describes the request by plugins from afb-daemon
- */
-struct afb_req {
-	const struct afb_req_itf *itf;	/* the interfacing functions */
-	void *closure;			/* the closure for functions */
-};
-```
-
-It contains two pointers: first one *itf*, points to functions used
-to handle internal request. Second one *closure* point onto function closure. 
-
-> The structure must never be used directly.
-> Instead developer should use the intended functions provided
-> by afb-daemon as described here after.
-
-*req* is used to get arguments of the request, to send
-answer, to store session data.
-
-This object and its interface is defined and documented
-in the file names *afb/afb-req-itf.h*
-
-The above example uses twice *req* object request.
-
-The first time, to retrieve the board attached to the session of the request.
-
-The second time, to send the reply: an object that describes the current board.
-
-### Associating a client context to a session
-
-When *tic-tac-toe* plugin receives a request, it musts get
-the board describing the game associated to the session.
-
-For a plugin, having data associated to a session is common.
-This data is called "plugin context" for the session.
-Within *tic-tac-toe* plugin the context is the board.
-
-Requests *afb_req* offer four functions for storing and retrieving session associated context.
-
-These functions are:
-
-- **afb_req_context_get**:
-  retrieves context data stored for current plugin.
-
-- **afb_req_context_set**:
-  store context data of current plugin.
-
-- **afb_req_context**:
-  if exist retrieves context data of current plugin.
-  if context does not yet exist, creates a new context and store it.
-
-- **afb_req_context_clear**:
-  reset the stored context data.
-
-The plugin *tictactoe* use a convenient function to retrieve
-its context: the board. This function is *board_of_req*:
-
-```C
-/*
- * retrieves the board of the request
- */
-static inline struct board *board_of_req(struct afb_req req)
-{
-	return afb_req_context(req, (void*)get_new_board, (void*)release_board);
-}
-```
-
-The function **afb_req_context** ensures an existing context
-for the session of the request.
-Its two last arguments are functions to allocate and free context. 
-Note function type casts to avoid compilation warnings.
-
-Here is the definition of the function **afb_req_context**
-
-```C
-/*
- * Gets the pointer stored by the plugin for the session of 'req'.
- * If the stored pointer is NULL, indicating that no pointer was
- * already stored, afb_req_context creates a new context by calling
- * the function 'create_context' and stores it with the freeing function
- * 'free_context'.
- */
-static inline void *afb_req_context(struct afb_req req, void *(*create_context)(), void (*free_context)(void*))
-{
-	void *result = afb_req_context_get(req);
-	if (result == NULL) {
-		result = create_context();
-		afb_req_context_set(req, result, free_context);
-	}
-	return result;
-}
-```
-
-The second argument if the function that creates the context.
-For plugin *tic-tac-toe* (function **get_new_board**).
-The function **get_new_board** creates a new board and set usage its count to 1.
-The boards are checking usage count to free resources when not used.
-
-The third argument is a function that frees context resources.
-For plugin *tic-tac-toe* (function **release_board**).
-The function **release_board** decrease usage count of the board passed in argument.
-When usage count falls to zero, data board are freed.
-
-Definition of other functions dealing with contexts:
-
-```C
-/*
- * Gets the pointer stored by the plugin for the session of 'req'.
- * When the plugin has not yet recorded a pointer, NULL is returned.
- */
-void *afb_req_context_get(struct afb_req req);
-
-/*
- * Stores for the plugin the pointer 'context' to the session of 'req'.
- * The function 'free_context' will be called when the session is closed
- * or if plugin stores an other pointer.
- */
-void afb_req_context_set(struct afb_req req, void *context, void (*free_context)(void*));
-
-/*
- * Frees the pointer stored by the plugin for the session of 'req'
- * and sets it to NULL.
- *
- * Shortcut for: afb_req_context_set(req, NULL, NULL)
- */
-static inline void afb_req_context_clear(struct afb_req req)
-{
-	afb_req_context_set(req, NULL, NULL);
-}
-```
-
-### Sending reply to a request
-
-Two kinds of replies: successful or failure.
-
-> Sending a reply to a request MUST be done once and only once.
-
-It exists two functions for "success" replies: **afb_req_success** and **afb_req_success_f**.
-
-```C
-/*
- * Sends a reply of kind success to the request 'req'.
- * The status of the reply is automatically set to "success".
- * Its send the object 'obj' (can be NULL) with an
- * informationnal comment 'info (can also be NULL).
- *
- * For conveniency, the function calls 'json_object_put' for 'obj'.
- * Thus, in the case where 'obj' should remain available after
- * the function returns, the function 'json_object_get' shall be used.
- */
-void afb_req_success(struct afb_req req, struct json_object *obj, const char *info);
-
-/*
- * Same as 'afb_req_success' but the 'info' is a formatting
- * string followed by arguments.
- *
- * For conveniency, the function calls 'json_object_put' for 'obj'.
- * Thus, in the case where 'obj' should remain available after
- * the function returns, the function 'json_object_get' shall be used.
- */
-void afb_req_success_f(struct afb_req req, struct json_object *obj, const char *info, ...);
-```
-
-It exists two functions for "failure" replies: **afb_req_fail** and **afb_req_fail_f**.
-
-```C
-/*
- * Sends a reply of kind failure to the request 'req'.
- * The status of the reply is set to 'status' and an
- * informational comment 'info' (can also be NULL) can be added.
- *
- * Note that calling afb_req_fail("success", info) is equivalent
- * to call afb_req_success(NULL, info). Thus even if possible it
- * is strongly recommended to NEVER use "success" for status.
- *
- * For conveniency, the function calls 'json_object_put' for 'obj'.
- * Thus, in the case where 'obj' should remain available after
- * the function returns, the function 'json_object_get' shall be used.
- */
-void afb_req_fail(struct afb_req req, const char *status, const char *info);
-
-/*
- * Same as 'afb_req_fail' but the 'info' is a formatting
- * string followed by arguments.
- *
- * For conveniency, the function calls 'json_object_put' for 'obj'.
- * Thus, in the case where 'obj' should remain available after
- * the function returns, the function 'json_object_get' shall be used.
- */
-void afb_req_fail_f(struct afb_req req, const char *status, const char *info, ...);
-```
-
-> For conveniency, these functions automatically call **json_object_put** to release **obj**.
-> Because **obj** usage count is null after being passed to a reply function, it SHOULD not be used anymore.
-> If exceptionally **obj** needs to remain usable after reply function then using **json_object_get** on **obj**
-> to increase usage count and cancels the effect the **json_object_put** is possible.
-
-Getting argument of invocation
-------------------------------
-
-Many methods expect arguments. Afb-daemon's plugins
-retrieve arguments by name and not by position.
-
-Arguments are passed by requests through either HTTP
-or WebSockets.
-
-For example, the method **join** of plugin **tic-tac-toe**
-expects one argument: the *boardid* to join. Here is an extract:
-
-```C
-/*
- * Join a board
- */
-static void join(struct afb_req req)
-{
-	struct board *board, *new_board;
-	const char *id;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'join' called for boardid %d", board->id);
-
-	/* retrieves the argument */
-	id = afb_req_value(req, "boardid");
-	if (id == NULL)
-		goto bad_request;
-	...
-```
-
-The function **afb_req_value** searches in the request *req*
-for argument name passed in the second argument. When argument name
-is not passed, **afb_req_value** returns NULL.
-
-> The search is case sensitive and *boardid* is not equivalent to *BoardId*.
-> Nevertheless having argument names that only differ by name case is not a good idea.
-
-### Basic functions for querying arguments
-
-The function **afb_req_value** is defined here after:
-
-```C
-/*
- * Gets from the request 'req' the string value of the argument of 'name'.
- * Returns NULL if when there is no argument of 'name'.
- * Returns the value of the argument of 'name' otherwise.
- *
- * Shortcut for: afb_req_get(req, name).value
- */
-static inline const char *afb_req_value(struct afb_req req, const char *name)
-{
-	return afb_req_get(req, name).value;
-}
-```
-
-It is defined as a shortcut to call the function **afb_req_get**.
-That function is defined here after:
-
-```C
-/*
- * Gets from the request 'req' the argument of 'name'.
- * Returns a PLAIN structure of type 'struct afb_arg'.
- * When the argument of 'name' is not found, all fields of result are set to NULL.
- * When the argument of 'name' is found, the fields are filled,
- * in particular, the field 'result.name' is set to 'name'.
- *
- * There is a special name value: the empty string.
- * The argument of name "" is defined only if the request was made using
- * an HTTP POST of Content-Type "application/json". In that case, the
- * argument of name "" receives the value of the body of the HTTP request.
- */
-struct afb_arg afb_req_get(struct afb_req req, const char *name);
-```
-
-That function takes 2 parameters: the request and the name
-of the argument to retrieve. It returns a PLAIN structure of
-type **struct afb_arg**.
-
-There is a special name that is defined when the request is
-of type HTTP/POST with a Content-Type being application/json.
-This name is **""** (the empty string). In that case, the value
-of this argument of empty name is the string received as a body
-of the post and is supposed to be a JSON string.
-
-The definition of **struct afb_arg** is:
-
-```C
-/*
- * Describes an argument (or parameter) of a request
- */
-struct afb_arg {
-	const char *name;	/* name of the argument or NULL if invalid */
-	const char *value;	/* string representation of the value of the argument */
-				/* original filename of the argument if path != NULL */
-	const char *path;	/* if not NULL, path of the received file for the argument */
-				/* when the request is finalized this file is removed */
-};
-```
-
-The structure returns the data arguments that are known for the
-request. This data include a field named **path**. This **path**
-can be accessed using the function **afb_req_path** defined here after:
-
-```C
-/*
- * Gets from the request 'req' the path for file attached to the argument of 'name'.
- * Returns NULL if when there is no argument of 'name' or when there is no file.
- * Returns the path of the argument of 'name' otherwise.
- *
- * Shortcut for: afb_req_get(req, name).path
- */
-static inline const char *afb_req_path(struct afb_req req, const char *name)
-{
-	return afb_req_get(req, name).path;
-}
-```
-
-The path is only defined for HTTP/POST requests that send file.
-
-### Arguments for received files
-
-As it is explained above, clients can send files using HTTP/POST requests.
-
-Received files are attached to "file" argument name. For example, the
-following HTTP fragment (from test/sample-post.html)
-will send an HTTP/POST request to the method
-**post/upload-image** with 2 arguments named *file* and
-*hidden*.
-
-```html
-<h2>Sample Post File</h2>
-<form enctype="multipart/form-data">
-    <input type="file" name="file" />
-    <input type="hidden" name="hidden" value="bollobollo" />
-    <br>
-    <button formmethod="POST" formaction="api/post/upload-image">Post File</button>
-</form>
-```
-
-Argument named **file** should have both its value and path defined.
-
-The value is the name of the file as it was set by the HTTP client.
-Generally it is the filename on client side.
-
-The path is the effective path of saved file on the temporary local storage
-area of the application. This is a randomly generated and unique filename. 
-It is not linked with the original filename as used on client side.
-
-After success the plugin can use the uploaded file directly from local storage path with no restriction:
-read, write, remove, copy, rename...
-Nevertheless when request reply is set and query terminated, the uploaded temporary file at
-path is destroyed.
-
-### Arguments as a JSON object
-
-Plugins may also request every arguments of a given call as one single object.
-This feature is provided by the function **afb_req_json** defined here after:
-
-```C
-/*
- * Gets from the request 'req' the json object hashing the arguments.
- * The returned object must not be released using 'json_object_put'.
- */
-struct json_object *afb_req_json(struct afb_req req);
-```
-
-It returns a json object. This object depends on how the request was built:
-
-- For HTTP requests, this json object uses key names mapped on argument name. 
-Values are either string for common arguments or object ie: { "file": "...", "path": "..." }
-
-- For WebSockets requests, returned directly the object as provided by the client.
-
-> In fact, for Websockets requests, the function **afb_req_value**
-> can be seen as a shortcut to
-> ***json_object_get_string(json_object_object_get(afb_req_json(req), name))***
-
-Initialisation of the plugin and declaration of methods
------------------------------------------------------
-
-To be active, plugin's methods should be declared to
-afb-daemon. Furthermore, the plugin itself must be recorded.
-
-The registration mechanism is very basic: when afb-need starts,
-it loads all plugins listed in: command line or configuration file.
-
-Loading a plugin follows the following steps:
-
-1. Afb-daemon loads the plugin with *dlopen*.
-
-2. Afb-daemon searches for a symbol named **pluginAfbV1Register** using *dlsym*.
-This symbol is assumed to be the exported initialisation function of the plugin.
-
-3. Afb-daemon builds an interface object for the plugin.
-
-4. Afb-daemon calls the found function **pluginAfbV1Register** with interface pointer
-as parameter.
-
-5. Function **pluginAfbV1Register** setups the plugin and initialises it.
-
-6. Function **pluginAfbV1Register** returns the pointer to a structure
-describing the plugin: version, name (prefix or API name), and list of methods.
-
-7. Afb-daemon checks that the returned version and name can be managed.
-If so, plugin and its methods are register to become usable as soon as
-afb-daemon initialisation is finished.
-
-Here after the code used for **pluginAfbV1Register** from plugin *tic-tac-toe*:
-
-```C
-/*
- * activation function for registering the plugin called by afb-daemon
- */
-const struct AFB_plugin *pluginAfbV1Register(const struct AFB_interface *itf)
-{
-   afbitf = itf;         // records the interface for accessing afb-daemon
-   return &plugin_description;  // returns the description of the plugin
-}
-```
-
-It is a very minimal initialisation function because *tic-tac-toe* plugin doesn't
-have any application related initialisation step. It merely record daemon's interface
-and returns its description.
-
-The variable **afbitf** is a plugin global variable. It keeps the
-interface to afb-daemon that should be used for logging and pushing events.
-Here is its declaration:
-
-```C
-/*
- * the interface to afb-daemon
- */
-const struct AFB_interface *afbitf;
-```
-
-The description of the plugin is defined here after.
-
-```C
-/*
- * array of the methods exported to afb-daemon
- */
-static const struct AFB_method_desc_v1 plugin_methods[] = {
-   /* VERB'S NAME     SESSION MANAGEMENT          FUNCTION TO CALL  SHORT DESCRIPTION */
-   { .name= "new",   .session= AFB_SESSION_NONE, .callback= new,   .info= "Starts a new game" },
-   { .name= "play",  .session= AFB_SESSION_NONE, .callback= play,  .info= "Asks the server to play" },
-   { .name= "move",  .session= AFB_SESSION_NONE, .callback= move,  .info= "Tells the client move" },
-   { .name= "board", .session= AFB_SESSION_NONE, .callback= board, .info= "Get the current board" },
-   { .name= "level", .session= AFB_SESSION_NONE, .callback= level, .info= "Set the server level" },
-   { .name= "join",  .session= AFB_SESSION_CHECK,.callback= join,  .info= "Join a board" },
-   { .name= "undo",  .session= AFB_SESSION_NONE, .callback= undo,  .info= "Undo the last move" },
-   { .name= "wait",  .session= AFB_SESSION_NONE, .callback= wait,  .info= "Wait for a change" },
-   { .name= NULL } /* marker for end of the array */
-};
-
-/*
- * description of the plugin for afb-daemon
- */
-static const struct AFB_plugin plugin_description =
-{
-   /* description conforms to VERSION 1 */
-   .type= AFB_PLUGIN_VERSION_1,
-   .v1= {				/* fills the v1 field of the union when AFB_PLUGIN_VERSION_1 */
-      .prefix= "tictactoe",		/* the API name (or plugin name or prefix) */
-      .info= "Sample tac-tac-toe game",	/* short description of of the plugin */
-      .methods = plugin_methods		/* the array describing the methods of the API */
-   }
-};
-```
-
-The structure **plugin_description** describes the plugin.
-It declares the type and version of the plugin, its name, a short description
-and its methods list.
-
-The list of methods is an array of structures describing the methods and terminated by a NULL marker.
-
-In version one of afb-damon plugin, a method description contains 4 fields:
-
-- the name of the method,
-
-- the session management flags,
-
-- the implementation function to be call for the method,
-
-- a short description.
-
-The structure describing methods is defined as follows:
-
-```C
-/*
- * Description of one method of the API provided by the plugin
- * This enumeration is valid for plugins of type 1
- */
-struct AFB_method_desc_v1
-{
-       const char *name;                       /* name of the method */
-       enum AFB_session_v1 session;            /* authorisation and session requirements of the method */
-       void (*callback)(struct afb_req req);   /* callback function implementing the method */
-       const char *info;                       /* textual description of the method */
-};
-```
-
-For technical reasons, the enumeration **enum AFB_session_v1** is not exactly an
-enumeration but the wrapper of constant definitions that can be mixed using bitwise or
-(the C operator |).
-
-The constants that can bit mixed are:
-
-Constant name            | Meaning
--------------------------|-------------------------------------------------------------
-**AFB_SESSION_CREATE**   | Equals to AFB_SESSION_LOA_EQ_0|AFB_SESSION_RENEW
-**AFB_SESSION_CLOSE**    | Closes the session after the reply and set the LOA to 0
-**AFB_SESSION_RENEW**    | Refreshes the token of authentification
-**AFB_SESSION_CHECK**    | Just requires the token authentification
-**AFB_SESSION_LOA_LE_0** | Requires the current LOA to be lesser then or equal to 0
-**AFB_SESSION_LOA_LE_1** | Requires the current LOA to be lesser then or equal to 1
-**AFB_SESSION_LOA_LE_2** | Requires the current LOA to be lesser then or equal to 2
-**AFB_SESSION_LOA_LE_3** | Requires the current LOA to be lesser then or equal to 3
-**AFB_SESSION_LOA_GE_0** | Requires the current LOA to be greater then or equal to 0
-**AFB_SESSION_LOA_GE_1** | Requires the current LOA to be greater then or equal to 1
-**AFB_SESSION_LOA_GE_2** | Requires the current LOA to be greater then or equal to 2
-**AFB_SESSION_LOA_GE_3** | Requires the current LOA to be greater then or equal to 3
-**AFB_SESSION_LOA_EQ_0** | Requires the current LOA to be equal to 0
-**AFB_SESSION_LOA_EQ_1** | Requires the current LOA to be equal to 1
-**AFB_SESSION_LOA_EQ_2** | Requires the current LOA to be equal to 2
-**AFB_SESSION_LOA_EQ_3** | Requires the current LOA to be equal to 3
-
-If any of this flag is set, afb-daemon requires an authentication token
-as if **AFB_SESSION_CHECK** flag was also set.
-
-The special value **AFB_SESSION_NONE** is zero and can be used to bypass token check.
-
-> Note that **AFB_SESSION_CREATE** and **AFB_SESSION_CLOSE** might be removed in later versions.
-
-Sending messages to the log system
-----------------------------------
-
-Afb-daemon provides 4 levels of verbosity and 5 methods for logging messages.
-
-The verbosity is managed. Options allow the change the verbosity of afb-daemon
-and the verbosity of the plugins can be set plugin by plugin.
-
-The methods for logging messages are defined as macros that test the
-verbosity level and that call the real logging function only if the
-message must be output. This avoid evaluation of arguments of the
-formatting messages if the message must not be output.
-
-### Verbs for logging messages
-
-The 5 logging methods are:
-
-Macro   | Verbosity | Meaning                           | syslog level
---------|:---------:|-----------------------------------|:-----------:
-ERROR   |     0     | Error conditions                  |     3
-WARNING |     1     | Warning conditions                |     4
-NOTICE  |     1     | Normal but significant condition  |     5
-INFO    |     2     | Informational                     |     6
-DEBUG   |     3     | Debug-level messages              |     7
-
-You can note that the 2 methods **WARNING** and **INFO** have the same level
-of verbosity. But they don't have the same *syslog level*. It means that
-they are output with a different level on the logging system.
-
-All of these methods have the same signature:
-
-```C
-void ERROR(const struct AFB_interface *afbitf, const char *message, ...);
-```
-
-The first argument **afbitf** is the interface to afb daemon that the
-plugin received at initialisation time when **pluginAfbV1Register** is called.
-
-The second argument **message** is a formatting string compatible with printf/sprintf.
-
-The remaining arguments are arguments of the formating message like with printf.
-
-### Managing verbosity
-
-Depending on the level of verbosity, the messages are output or not.
-The following table explains what messages will be output depending
-ont the verbosity level.
-
-Level of verbosity | Outputed macro
-:-----------------:|--------------------------
-0                  | ERROR
-1                  | ERROR + WARNING + NOTICE
-2                  | ERROR + WARNING + NOTICE + INFO
-3                  | ERROR + WARNING + NOTICE + INFO + DEBUG
-
-### Output format and destination
-
-The syslog level is used for forging a prefix to the message.
-The prefixes are:
-
-syslog level | prefix
-:-----------:|---------------
-0            | <0> EMERGENCY
-1            | <1> ALERT
-2            | <2> CRITICAL
-3            | <3> ERROR
-4            | <4> WARNING
-5            | <5> NOTICE
-6            | <6> INFO
-7            | <7> DEBUG
-
-
-The message is pushed to standard error.
-The final destination of the message depends on how systemd service
-was configured through its variable **StandardError**. It can be
-journal, syslog or kmsg. (See man sd-daemon).
-
-Sending events
---------------
-
-Since version 0.5, plugins can broadcast events to any potential listener.
-As today only unattended even are supported. Targeted events are expected for next
-coming version.
-
-The plugin *tic-tac-toe* broadcasts events when the board changes.
-This is done in the function **changed**:
-
-```C
-/*
- * signals a change of the board
- */
-static void changed(struct board *board, const char *reason)
-{
-	...
-	struct json_object *description;
-
-	/* get the description */
-	description = describe(board);
-
-	...
-
-	afb_daemon_broadcast_event(afbitf->daemon, reason, description);
-}
-```
-
-The description of the changed board is pushed via the daemon interface.
-
-Within plugin *tic-tac-toe*, *reason* indicates the origin of
-the change. In function **afb_daemon_broadcast_event** the second
-parameter is the name of broadcasted event. The third argument is the
-object that is transmitted with the event.
-
-Function **afb_daemon_broadcast_event** is defined here after:
-
-```C
-/*
- * Broadcasts widely the event of 'name' with the data 'object'.
- * 'object' can be NULL.
- * 'daemon' MUST be the daemon given in interface when activating the plugin.
- *
- * For conveniency, the function calls 'json_object_put' for 'object'.
- * Thus, in the case where 'object' should remain available after
- * the function returns, the function 'json_object_get' shall be used.
- */
-void afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object);
-```
-
-> Be aware, as with reply functions **object** is automatically released using
-> **json_object_put** when using this function. Call **json_object_get** before
-> calling **afb_daemon_broadcast_event** to keep **object** available
-> after function returns.
-
-Event name received by listeners is prefixed with plugin name.
-So when a change occurs after a move, the reason is **move** and every clients
-receive an event **tictactoe/move**.
-
-> Note that nothing is said about case sensitivity of event names.
-> However, the event is always prefixed with the name that the plugin
-> declared, with the same case, followed with a slash /.
-> Thus it is safe to compare event using a case sensitive comparison.
-
-
-
-Writing an asynchronous method implementation
--------------------------------------------
-
-The *tic-tac-toe* example allows two clients or more to share the same board.
-This is implemented by the method **join** that illustrated partly how to
-retrieve arguments.
-
-When two or more clients are sharing a same board, one of them can wait
-until the state of the board changes, but this could also be implemented using
-events because an even is generated each time the board changes.
-
-In this case, the reply to the wait is sent only when the board changes.
-See the diagram below:
-
-	CLIENT A       CLIENT B         TIC-TAC-TOE
-	   |              |                  |
-	   +--------------|----------------->| wait . . . . . . . .
-	   |              |                  |                     .
-	   :              :                  :                      .
-	   :              :                  :                      .
-	   |              |                  |                      .
-	   |              +----------------->| move . . .           .
-	   |              |                  |          V           .
-	   |              |<-----------------+ success of move      .
-	   |              |                  |                    .
-	   |<-------------|------------------+ success of wait  <
-
-Here, this is an invocation of the plugin by an other client that
-unblock the suspended *wait* call.
-Nevertheless in most case this should be a timer, a hardware event, a sync with
-a concurrent process or thread, ...
-
-Common case of an asynchronous implementation.
-
-Here is the listing of the function **wait**:
-
-```C
-static void wait(struct afb_req req)
-{
-	struct board *board;
-	struct waiter *waiter;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'wait' called for boardid %d", board->id);
-
-	/* creates the waiter and enqueues it */
-	waiter = calloc(1, sizeof *waiter);
-	waiter->req = req;
-	waiter->next = board->waiters;
-	afb_req_addref(req);
-	board->waiters = waiter;
-}
-```
-
-After retrieving the board, the function adds a new waiter to
-waiters list and returns without setting a reply.
-
-Before returning, it increases **req** request's reference count using **afb_req_addref** function.
-
-> When a method returns without setting a reply,
-> it **MUST** increment request's reference count
-> using **afb_req_addref**. If unpredictable behaviour may pop up.
-
-Later, when a board changes, it calls *tic-tac-toe* **changed** function
-with reason of change in parameter.
-
-Here is the full listing of the function **changed**:
-
-```C
-/*
- * signals a change of the board
- */
-static void changed(struct board *board, const char *reason)
-{
-	struct waiter *waiter, *next;
-	struct json_object *description;
-
-	/* get the description */
-	description = describe(board);
-
-	waiter = board->waiters;
-	board->waiters = NULL;
-	while (waiter != NULL) {
-		next = waiter->next;
-		afb_req_success(waiter->req, json_object_get(description), reason);
-		afb_req_unref(waiter->req);
-		free(waiter);
-		waiter = next;
-	}
-
-	afb_event_sender_push(afb_daemon_get_event_sender(afbitf->daemon), reason, description);
-}
-```
-
-The list of waiters is walked and a reply is sent to each waiter.
-After sending the reply, the reference count of the request
-is decremented using **afb_req_unref** to allow resources to be freed.
-
-> The reference count **MUST** be decremented using **afb_req_unref** to free
-> resources and avoid memory leaks.
-> This usage count decrement should happen **AFTER** setting reply or 
-> bad things may happen.
-
-How to build a plugin
----------------------
-
-Afb-daemon provides a *pkg-config* configuration file that can be
-queried by providing **afb-daemon** in command line arguments.
-This configuration file provides data that should be used
-for plugins compilation. Examples:
-
-```bash
-$ pkg-config --cflags afb-daemon
-$ pkg-config --libs afb-daemon
-```
-
-### Example for cmake meta build system
-
-This example is the extract for building the plugin *afm-main* using *CMAKE*.
-
-```cmake
-pkg_check_modules(afb afb-daemon)
-if(afb_FOUND)
-	message(STATUS "Creation afm-main-plugin for AFB-DAEMON")
-	add_library(afm-main-plugin MODULE afm-main-plugin.c)
-	target_compile_options(afm-main-plugin PRIVATE ${afb_CFLAGS})
-	target_include_directories(afm-main-plugin PRIVATE ${afb_INCLUDE_DIRS})
-	target_link_libraries(afm-main-plugin utils ${afb_LIBRARIES})
-	set_target_properties(afm-main-plugin PROPERTIES
-		PREFIX ""
-		LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/afm-main-plugin.export-map"
-	)
-	install(TARGETS afm-main-plugin LIBRARY DESTINATION ${plugin_dir})
-else()
-	message(STATUS "Not creating the plugin for AFB-DAEMON")
-endif()
-```
-
-Let now describe some of these lines.
-
-```cmake
-pkg_check_modules(afb afb-daemon)
-```
-
-This first lines searches to the *pkg-config* configuration file for
-**afb-daemon**. Resulting data are stored in the following variables:
-
-Variable          | Meaning
-------------------|------------------------------------------------
-afb_FOUND         | Set to 1 if afb-daemon plugin development files exist
-afb_LIBRARIES     | Only the libraries (w/o the '-l') for compiling afb-daemon plugins
-afb_LIBRARY_DIRS  | The paths of the libraries (w/o the '-L') for compiling afb-daemon plugins
-afb_LDFLAGS       | All required linker flags for compiling afb-daemon plugins
-afb_INCLUDE_DIRS  | The '-I' preprocessor flags (w/o the '-I') for compiling afb-daemon plugins
-afb_CFLAGS        | All required cflags for compiling afb-daemon plugins
-
-If development files are found, the plugin can be added to the set of
-target to build.
-
-```cmake
-add_library(afm-main-plugin MODULE afm-main-plugin.c)
-```
-
-This line asks to create a shared library having a single
-source file named afm-main-plugin.c to be compiled.
-The default name of the created shared object is
-**libafm-main-plugin.so**.
-
-```cmake
-set_target_properties(afm-main-plugin PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/afm-main-plugin.export-map"
-)
-```
-
-This lines are doing two things:
-
-1. It renames the built library from **libafm-main-plugin.so** to **afm-main-plugin.so**
-by removing the implicitly added prefix *lib*. This step is not mandatory
-because afb-daemon doesn't check names of files at load time.
-The only filename convention used by afb-daemon relates to **.so** termination.
-*.so pattern is used when afb-daemon automatically discovers plugin from a directory hierarchy.
-
-2. It applies a version script at link time to only export the reserved name
-**pluginAfbV1Register** for registration entry point. By default, when building 
-a shared library linker exports all the public symbols (C functions that are not **static**).
-
-Next line are:
-
-```cmake
-target_include_directories(afm-main-plugin PRIVATE ${afb_INCLUDE_DIRS})
-target_link_libraries(afm-main-plugin utils ${afb_LIBRARIES})
-```
-
-As you can see it uses the variables computed by ***pkg_check_modules(afb afb-daemon)***
-to configure the compiler and the linker.
-
-### Exporting the function pluginAfbV1Register
-
-The function **pluginAfbV1Register** MUST be exported. This can be achieved
-using a version script at link time. Here after is a version script used for
-*tic-tac-toe* (plugins/samples/export.map).
-
-	{ global: pluginAfbV1Register; local: *; };
-
-This sample [version script](https://sourceware.org/binutils/docs-2.26/ld/VERSION.html#VERSION)
-exports as global the symbol *pluginAfbV1Register* and hides any
-other symbols.
-
-This version script is added to the link options using the
-option **--version-script=export.map** is given directly to the
-linker or using the option **-Wl,--version-script=export.map**
-when the option is given to the C compiler.
-
-### Building within yocto
-
-Adding a dependency to afb-daemon is enough. See below:
-
-	DEPENDS += " afb-daemon "
-
diff --git a/doc/afb-plugins-overview.html b/doc/afb-plugins-overview.html
deleted file mode 100644
index 291b7f79..00000000
--- a/doc/afb-plugins-overview.html
+++ /dev/null
@@ -1,159 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  <meta name="generator" content="pandoc">
-  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
-  <meta name="author" content="Manuel Bachmann">
-  <meta name="author" content="José Bollo">
-  <title>Overview of plugins shipped with AFB-Daemon</title>
-  <style type="text/css">code{white-space: pre;}</style>
-  <!--[if lt IE 9]>
-    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
-  <![endif]-->
-  <link rel="stylesheet" href="doc.css">
-</head>
-<body>
-<header>
-<h1 class="title">Overview of plugins shipped with AFB-Daemon</h1>
-<h2 class="author">Manuel Bachmann</h2>
-<h2 class="author">José Bollo</h2>
-<h3 class="date">09 juin 2016</h3>
-</header>
-<nav id="TOC">
-<ul>
-<li><a href="#overview-of-plugins-shipped-with-afb-daemon">Overview of plugins shipped with AFB-Daemon</a><ul>
-<li><a href="#list-of-plugins">List of plugins</a></li>
-<li><a href="#detail-of-plugins">Detail of plugins</a><ul>
-<li><a href="#hello-world">Hello World</a></li>
-<li><a href="#authentication">Authentication</a></li>
-<li><a href="#tic-tac-toe">Tic Tac Toe</a></li>
-<li><a href="#audio">Audio</a></li>
-<li><a href="#radio">Radio</a></li>
-<li><a href="#media">Media</a></li>
-</ul></li>
-</ul></li>
-</ul>
-</nav>
-<h1 id="overview-of-plugins-shipped-with-afb-daemon">Overview of plugins shipped with AFB-Daemon</h1>
-<pre><code>Version: 1
-Date:    09 juin 2016
-Author:  Manuel Bachmann</code></pre>
-<h2 id="list-of-plugins">List of plugins</h2>
-<p>Here are the plugins shipped in the source tree:</p>
-<ul>
-<li>Hello World</li>
-<li>Authentication</li>
-<li>Tic Tac Toe</li>
-<li>Audio <em>(2 backends: ALSA/PulseAudio)</em></li>
-<li>Radio <em>(1 backend: RTLSDR RTL2832U)</em></li>
-<li>Media <em>(1 backend: Rygel UPnP)</em></li>
-</ul>
-<p>All plugins may not be built, depending on the development libraries present on the system at build time.</p>
-<h2 id="detail-of-plugins">Detail of plugins</h2>
-<h3 id="hello-world">Hello World</h3>
-<p>A sample Hello World plugin for demonstration and learning purposes.</p>
-<p>This plugin provides a few unauthenticated requests, all beginning with &quot;ping&quot;, to demonstrate basic binder capabilities.</p>
-<p><strong>Verbs</strong>:</p>
-<ul>
-<li><em>ping:</em> returns a success response</li>
-<li><em>pingfail:</em> returns a failure response</li>
-<li><em>pingnull:</em> returns a success response, with an empty JSON response field</li>
-<li><em>pingbug:</em> does a memory violation (intercepted by the binder)</li>
-<li><em>pingJson:</em> returns a success response, with a complex JSON response field</li>
-<li><em>pingevent:</em> broadcasts a global event</li>
-</ul>
-<p><br /></p>
-<h3 id="authentication">Authentication</h3>
-<p>An sample Authentication plugin for demonstration purposes.</p>
-<p>This plugin provides a few requests to demonstrate the binder's token-based security mechanism.</p>
-<p>Calling &quot;<em>connect</em>&quot; with a security token will initiate a session, calling &quot;<em>refresh</em>&quot; will issue a new token and invalidate the previous one, calling &quot;<em>logout</em>&quot; will invalidate all tokens and close the session.</p>
-<p><strong>Verbs</strong>:</p>
-<ul>
-<li><em>ping:</em> returns a success response</li>
-<li><em>connect:</em> creates a session and returns a new token</li>
-<li><em>refresh:</em> returns a new token</li>
-<li><em>check:</em> verifies the passed token is valid</li>
-<li><em>logout:</em> closes the session</li>
-</ul>
-<p><br /></p>
-<h3 id="tic-tac-toe">Tic Tac Toe</h3>
-<p>A sample Tic Tac Toe game plugin.</p>
-<p>This plugin provides an interactive Tic Tac Toe game where the binder returns the grid as a JSON response.</p>
-<p><strong>Verbs</strong>:</p>
-<ul>
-<li><em>new:</em> starts a new game</li>
-<li><em>play:</em> asks the server to play</li>
-<li><em>move:</em> gives a client move</li>
-<li><em>board:</em> gets the current board state, as a JSON structure</li>
-<li><em>level</em>: sets the server level</li>
-<li><em>join</em>: joins an existing board</li>
-<li><em>undo</em>: undo the last move</li>
-<li><em>wait</em>: wait for a move</li>
-</ul>
-<p><br /></p>
-<h3 id="audio">Audio</h3>
-<p>A sample Audio plugin with 2 backends:</p>
-<ul>
-<li>ALSA (mandatory)</li>
-<li>PulseAudio (optional)</li>
-</ul>
-<p>This plugin is able to initialize a specific soundcard, define volume levels, channels (mono/stereo...), mute sound, and play a 22,050 Hz PCM stream.</p>
-<p><strong>Verbs</strong>:</p>
-<ul>
-<li><em>ping:</em> returns a success response</li>
-<li><em>init:</em> initializes backend, on the &quot;default&quot; sound card</li>
-<li><em>volume:</em> gets or sets volume, in % (0-100)</li>
-<li><em>channels:</em> gets or sets channels count (1-8)</li>
-<li><em>mute:</em> gets or sets the mute status (on-off)</li>
-<li><em>play</em>: gets or sets the playing status (on-off)</li>
-</ul>
-<p><em>(if PulseAudio development libraries are not found at build time, only ALSA will be available)</em></p>
-<p><em>(if a PulseAudio server is not found at runtime, the plugin will dynamically fall back to ALSA)</em></p>
-<p><em>(a specifc backend can be forced by using this syntax before running afb-daemon : <strong>$ export AFB_AUDIO_OUTPUT=Alsa</strong>)</em></p>
-<p><br /></p>
-<h3 id="radio">Radio</h3>
-<p>A sample AM/FM Radio plugin with 1 backend:</p>
-<ul>
-<li>RTLSDR - Realtek RTL2832U dongles (mandatory)</li>
-</ul>
-<p>This plugin is able to initialize specific RTL2832U dongles, switch between AM/FM modes, define frequency, mute sound, and play sound (if combining with the <strong>audio</strong> plugin).</p>
-<p><strong>Verbs</strong>:</p>
-<ul>
-<li><em>ping:</em> returns a success response</li>
-<li><em>init:</em> initializes backend, looking for plugged-in devices</li>
-<li><em>power:</em> sets device power status (on-off)</li>
-<li><em>mode:</em> sets device reception mode (AM-FM)</li>
-<li><em>freq:</em> sets device frequency (in Hz)</li>
-<li><em>mute</em>: sets device mute status (on-off)</li>
-<li><em>play</em>: sets device playing status (on-off)</li>
-</ul>
-<p><em>(if rtlsdr development libraries are not found at build time, this plugin will not be built)</em></p>
-<p><br /></p>
-<h3 id="media">Media</h3>
-<p>A sample Media Server plugin with 1 backend:</p>
-<ul>
-<li>Rygel</li>
-</ul>
-<p>This plugin is able to detect a local Rygel UPnP media server, list audio files, select an audio file for playback, play/pause/seek in this file, upload an audio file to the server.</p>
-<p><strong>Verbs</strong>:</p>
-<ul>
-<li><em>ping:</em> returns a success response</li>
-<li><em>init:</em> initializes backend, looking for an active local UPnP server</li>
-<li><em>list:</em> returns list of audio files, as a JSON structure</li>
-<li><em>select:</em> select an audio files, by index number (001-...)</li>
-<li><em>play:</em> plays the currently selected audio file</li>
-<li><em>stop:</em> stops the currently selected audio file</li>
-<li><em>pause:</em> pauses the currently selected audio file</li>
-<li><em>seek:</em> seeks in the currently selected audio file, in seconds</li>
-<li><em>upload:</em> uploads an audio file, with a POST request</li>
-</ul>
-<p><em>(if GUPnP/GSSDP development libraries are not fund at build time, this plugin will not be built)</em></p>
-<p><br /></p>
-<hr />
-<p><br /></p>
-<p>Sample command-line applications: <em>afb-client-demo</em> (built by default)</p>
-<p>Sample HTML5 applications: **test/*.html<strong>, </strong><a href="https://gerrit.automotivelinux.org/gerrit/gitweb?p=src/app-framework-demo.git;a=tree">afb-client</a><strong>, </strong><a href="https://github.com/iotbzh/afb-radio">afb-radio</a>**</p>
-<p>Sample Qt/QML applications: <em>test/token-websock.qml</em></p>
-</body>
-</html>
diff --git a/doc/afb-plugins-overview.md b/doc/afb-plugins-overview.md
deleted file mode 100644
index dfbe6010..00000000
--- a/doc/afb-plugins-overview.md
+++ /dev/null
@@ -1,168 +0,0 @@
-Overview of plugins shipped with AFB-Daemon
-===========================================
-    Version: 1
-    Date:    09 juin 2016
-    Author:  Manuel Bachmann
-
-
-List of plugins
----------------
-
-Here are the plugins shipped in the source tree:
-
-* Hello World
-* Authentication
-* Tic Tac Toe
-* Audio _(2 backends: ALSA/PulseAudio)_
-* Radio _(1 backend: RTLSDR RTL2832U)_
-* Media _(1 backend: Rygel UPnP)_
-
-All plugins may not be built, depending on the development libraries present on the system at build time.
-
-
-Detail of plugins
------------------
-
-### Hello World
-
-A sample Hello World plugin for demonstration and learning purposes.
-
-This plugin provides a few unauthenticated requests, all beginning with "ping", to demonstrate basic binder capabilities.
-
-**Verbs**:
-
-* _ping:_ returns a success response
-* _pingfail:_ returns a failure response
-* _pingnull:_ returns a success response, with an empty JSON response field
-* _pingbug:_ does a memory violation (intercepted by the binder)
-* _pingJson:_ returns a success response, with a complex JSON response field
-* _pingevent:_ broadcasts a global event
-
-<br />
-
-
-### Authentication
-
-An sample Authentication plugin for demonstration purposes.
-
-This plugin provides a few requests to demonstrate the binder's token-based security mechanism.
-
-Calling "_connect_" with a security token will initiate a session, calling "_refresh_" will issue a new token and invalidate the previous one, calling "_logout_" will invalidate all tokens and close the session.
-
-**Verbs**:
-
-* _ping:_ returns a success response
-* _connect:_ creates a session and returns a new token
-* _refresh:_ returns a new token
-* _check:_ verifies the passed token is valid
-* _logout:_ closes the session
-
-<br />
-
-
-### Tic Tac Toe
-
-A sample Tic Tac Toe game plugin.
-
-This plugin provides an interactive Tic Tac Toe game where the binder returns the grid as a JSON response. 
-
-**Verbs**:
-
-* _new:_ starts a new game
-* _play:_ asks the server to play
-* _move:_ gives a client move
-* _board:_ gets the current board state, as a JSON structure
-* _level_: sets the server level
-* _join_: joins an existing board
-* _undo_: undo the last move
-* _wait_: wait for a move
-
-<br />
-
-
-### Audio
-
-A sample Audio plugin with 2 backends:
-
-* ALSA (mandatory)
-* PulseAudio (optional)
-
-This plugin is able to initialize a specific soundcard, define volume levels, channels (mono/stereo...), mute sound, and play a 22,050 Hz PCM stream.
-
-**Verbs**:
-
-* _ping:_ returns a success response
-* _init:_ initializes backend, on the "default" sound card
-* _volume:_ gets or sets volume, in % (0-100)
-* _channels:_ gets or sets channels count (1-8)
-* _mute:_ gets or sets the mute status (on-off)
-* _play_: gets or sets the playing status (on-off)
-
-_(if PulseAudio development libraries are not found at build time, only ALSA will be available)_
-
-_(if a PulseAudio server is not found at runtime, the plugin will dynamically fall back to ALSA)_
-
-_(a specifc backend can be forced by using this syntax before running afb-daemon : **$ export AFB_AUDIO_OUTPUT=Alsa**)_
-
-<br />
-
-
-### Radio
-
-A sample AM/FM Radio plugin with 1 backend:
-
-* RTLSDR - Realtek RTL2832U dongles (mandatory)
-
-This plugin is able to initialize specific RTL2832U dongles, switch between AM/FM modes, define frequency, mute sound, and play sound (if combining with the **audio** plugin).
-
-**Verbs**:
-
-* _ping:_ returns a success response
-* _init:_ initializes backend, looking for plugged-in devices
-* _power:_ sets device power status (on-off)
-* _mode:_ sets device reception mode (AM-FM)
-* _freq:_ sets device frequency (in Hz)
-* _mute_: sets device mute status (on-off)
-* _play_: sets device playing status (on-off)
-
-_(if rtlsdr development libraries are not found at build time, this plugin will not be built)_
-
-<br />
-
-
-### Media
-
-A sample Media Server plugin with 1 backend:
-
- * Rygel
-
-This plugin is able to detect a local Rygel UPnP media server, list audio files, select an audio file for playback, play/pause/seek in this file, upload an audio file to the server.
-
-**Verbs**:
-
-* _ping:_ returns a success response
-* _init:_ initializes backend, looking for an active local UPnP server
-* _list:_ returns list of audio files, as a JSON structure
-* _select:_ select an audio files, by index number (001-...)
-* _play:_ plays the currently selected audio file
-* _stop:_ stops the currently selected audio file
-* _pause:_ pauses the currently selected audio file
-* _seek:_ seeks in the currently selected audio file, in seconds
-* _upload:_ uploads an audio file, with a POST request
-
-_(if GUPnP/GSSDP development libraries are not fund at build time, this plugin will not be built)_
-
-<br />
-
-
----
-<br />
-
-Sample command-line applications: _afb-client-demo_ (built by default)
-
-Sample HTML5 applications: 
-**test/*.html**, 
-**[afb-client](https://gerrit.automotivelinux.org/gerrit/gitweb?p=src/app-framework-demo.git;a=tree)**, 
-**[afb-radio](https://github.com/iotbzh/afb-radio)**
-
-Sample Qt/QML applications: *test/token-websock.qml*
diff --git a/doc/afb-tests-overview.html b/doc/afb-tests-overview.html
index e9711c4e..b29c1920 100644
--- a/doc/afb-tests-overview.html
+++ b/doc/afb-tests-overview.html
@@ -18,7 +18,7 @@
 <h1 class="title">Overview of tests shipped with AFB-Daemon</h1>
 <h2 class="author">Manuel Bachmann</h2>
 <h2 class="author">José Bollo</h2>
-<h3 class="date">09 juin 2016</h3>
+<h3 class="date">23 juin 2016</h3>
 </header>
 <nav id="TOC">
 <ul>
@@ -45,12 +45,12 @@ Author:  Manuel Bachmann</code></pre>
 </ul>
 <h2 id="detail-of-tests">Detail of tests</h2>
 <h3 id="afb-client-demo-command-line-websockets">afb-client-demo (command-line WebSockets)</h3>
-<p>This clients interactively calls plugins APIs from the command line, using the binder <a href="https://en.wikipedia.org/wiki/WebSocket">WebSockets</a> facility.</p>
+<p>This clients interactively calls bindings APIs from the command line, using the binder <a href="https://en.wikipedia.org/wiki/WebSocket">WebSockets</a> facility.</p>
 <p>If <em>afb-daemon</em> has been launched with the following parameters:</p>
 <pre><code>$ afb-daemon --port=1234 --token=123456 [...]</code></pre>
 <p>Then run the client with :</p>
 <pre><code>afb-client-demo ws://localhost:1234/api?token=123456 [&lt;api&gt; &lt;verb&gt; [&lt;json-data&gt;]]</code></pre>
-<p>For instance, to initialize the Audio plugin from the command line :</p>
+<p>For instance, to initialize the Audio binding from the command line :</p>
 <pre><code>afb-client-demo ws://localhost:1234/api?token=123456</code></pre>
 <p>The command doesn't return. You should type requests of type <api> <verb> [<json-data>]. So, try:</p>
 <pre><code>auth connect
diff --git a/doc/afb-tests-overview.md b/doc/afb-tests-overview.md
index 6bb1b8a9..4fc0c9b2 100644
--- a/doc/afb-tests-overview.md
+++ b/doc/afb-tests-overview.md
@@ -22,7 +22,7 @@ Detail of tests
 
 ### afb-client-demo (command-line WebSockets)
 
-This clients interactively calls plugins APIs from the command line, using the binder
+This clients interactively calls bindings APIs from the command line, using the binder
 [WebSockets](https://en.wikipedia.org/wiki/WebSocket) facility.
 
 If _afb-daemon_ has been launched with the following parameters:
@@ -35,7 +35,7 @@ Then run the client with :
 
     afb-client-demo ws://localhost:1234/api?token=123456 [<api> <verb> [<json-data>]]
 
-For instance, to initialize the Audio plugin from the command line :
+For instance, to initialize the Audio binding from the command line :
 
     afb-client-demo ws://localhost:1234/api?token=123456
 
diff --git a/include/afb/afb-binding.h b/include/afb/afb-binding.h
new file mode 100644
index 00000000..ac63d36b
--- /dev/null
+++ b/include/afb/afb-binding.h
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author: José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdarg.h>
+
+/*****************************************************************************
+ * This files is the main file to include for writing bindings dedicated to
+ *
+ *                      AFB-DAEMON
+ *
+ * Functions of bindings of afb-daemon are accessible by authorized clients
+ * through the apis module of afb-daemon.
+ *
+ * A binding is a shared library. This shared library must have at least one
+ * exported symbol for being registered in afb-daemon.
+ * For the current version of afb-daemon, the function exported MUST be named
+ *
+ *                  afbBindingV1Register
+ */
+
+/*
+ * Some function of the library are exported to afb-daemon.
+ */
+
+#include <afb/afb-event-itf.h>
+#include <afb/afb-req-itf.h>
+
+/*
+ * Definition of the type+versions of the binding.
+ * The definition uses hashes.
+ */
+enum  afb_binding_type
+{
+       AFB_BINDING_VERSION_1 = 123456789        /* version 1 */
+};
+
+/*
+ * Enum for Session/Token/Assurance middleware.
+ * This enumeration is valid for bindings of type 1
+ */
+enum afb_session_v1
+{
+       AFB_SESSION_NONE = 0,   /* nothing required */
+       AFB_SESSION_CREATE = 1, /* Obsolete */
+       AFB_SESSION_CLOSE = 2,  /* After token authentification, closes the session at end */
+       AFB_SESSION_RENEW = 4,  /* After token authentification, refreshes the token at end */
+       AFB_SESSION_CHECK = 8,  /* Requires token authentification */
+
+       AFB_SESSION_LOA_GE = 16, /* check that the LOA is greater or equal to the given value */
+       AFB_SESSION_LOA_LE = 32, /* check that the LOA is lesser or equal to the given value */
+       AFB_SESSION_LOA_EQ = 48, /* check that the LOA is equal to the given value */
+
+       AFB_SESSION_LOA_SHIFT = 6, /* shift for LOA */
+       AFB_SESSION_LOA_MASK = 7,  /* mask for LOA */
+
+       AFB_SESSION_LOA_0 = 0,   /* value for LOA of 0 */
+       AFB_SESSION_LOA_1 = 64,  /* value for LOA of 1 */
+       AFB_SESSION_LOA_2 = 128, /* value for LOA of 2 */
+       AFB_SESSION_LOA_3 = 192, /* value for LOA of 3 */
+       AFB_SESSION_LOA_4 = 256, /* value for LOA of 4 */
+
+       AFB_SESSION_LOA_LE_0 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_0, /* check LOA <= 0 */
+       AFB_SESSION_LOA_LE_1 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_1, /* check LOA <= 1 */
+       AFB_SESSION_LOA_LE_2 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_2, /* check LOA <= 2 */
+       AFB_SESSION_LOA_LE_3 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_3, /* check LOA <= 3 */
+
+       AFB_SESSION_LOA_GE_0 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_0, /* check LOA >= 0 */
+       AFB_SESSION_LOA_GE_1 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_1, /* check LOA >= 1 */
+       AFB_SESSION_LOA_GE_2 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_2, /* check LOA >= 2 */
+       AFB_SESSION_LOA_GE_3 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_3, /* check LOA >= 3 */
+
+       AFB_SESSION_LOA_EQ_0 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_0, /* check LOA == 0 */
+       AFB_SESSION_LOA_EQ_1 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_1, /* check LOA == 1 */
+       AFB_SESSION_LOA_EQ_2 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_2, /* check LOA == 2 */
+       AFB_SESSION_LOA_EQ_3 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_3  /* check LOA == 3 */
+};
+
+/*
+ * Description of one verb of the API provided by the binding
+ * This enumeration is valid for bindings of type 1
+ */
+struct afb_verb_desc_v1
+{
+       const char *name;                       /* name of the verb */
+       enum afb_session_v1 session;            /* authorisation and session requirements of the verb */
+       void (*callback)(struct afb_req req);   /* callback function implementing the verb */
+       const char *info;                       /* textual description of the verb */
+};
+
+/*
+ * Description of the bindings of type 1
+ */
+struct afb_binding_desc_v1
+{
+       const char *info;                       /* textual information about the binding */
+       const char *prefix;                     /* required prefix name for the binding */
+       const struct afb_verb_desc_v1 *verbs;   /* array of descriptions of verbs terminated by a NULL name */
+};
+
+/*
+ * Description of a binding
+ */
+struct afb_binding
+{
+       enum afb_binding_type type; /* type of the binding */
+       union {
+               struct afb_binding_desc_v1 v1;   /* description of the binding of type 1 */
+       };
+};
+
+/*
+ * config mode
+ */
+enum afb_mode {
+       AFB_MODE_LOCAL = 0,     /* run locally */
+       AFB_MODE_REMOTE,        /* run remotely */
+       AFB_MODE_GLOBAL         /* run either remotely or locally (DONT USE! reserved for future) */
+};
+
+/* declaration of features of libsystemd */
+struct sd_event;
+struct sd_bus;
+
+/*
+ * Definition of the facilities provided by the daemon.
+ */
+struct afb_daemon_itf {
+       int (*event_broadcast)(void *closure, const char *name, struct json_object *object); /* broadcasts evant 'name' with 'object' */
+       struct sd_event *(*get_event_loop)(void *closure);      /* gets the common systemd's event loop */
+       struct sd_bus *(*get_user_bus)(void *closure);          /* gets the common systemd's user d-bus */
+       struct sd_bus *(*get_system_bus)(void *closure);        /* gets the common systemd's system d-bus */
+       void (*vverbose)(void*closure, int level, const char *file, int line, const char *fmt, va_list args);
+       struct afb_event (*event_make)(void *closure, const char *name); /* creates an event of 'name' */
+};
+
+/*
+ * Structure for accessing daemon.
+ * See also: afb_daemon_get_event_sender, afb_daemon_get_event_loop, afb_daemon_get_user_bus, afb_daemon_get_system_bus
+ */
+struct afb_daemon {
+       const struct afb_daemon_itf *itf;       /* the interfacing functions */
+       void *closure;                          /* the closure when calling these functions */
+};
+
+/*
+ * Interface between the daemon and the binding.
+ */
+struct afb_binding_interface
+{
+       struct afb_daemon daemon;       /* access to the daemon facilies */
+       int verbosity;                  /* level of verbosity */
+       enum afb_mode mode;             /* run mode (local or remote) */
+};
+
+/*
+ * Function for registering the binding
+ */
+extern const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *interface);
+
+/*
+ * Retrieves the common systemd's event loop of AFB
+ * 'daemon' MUST be the daemon given in interface when activating the binding.
+ */
+static inline struct sd_event *afb_daemon_get_event_loop(struct afb_daemon daemon)
+{
+	return daemon.itf->get_event_loop(daemon.closure);
+}
+
+/*
+ * Retrieves the common systemd's user/session d-bus of AFB
+ * 'daemon' MUST be the daemon given in interface when activating the binding.
+ */
+static inline struct sd_bus *afb_daemon_get_user_bus(struct afb_daemon daemon)
+{
+	return daemon.itf->get_user_bus(daemon.closure);
+}
+
+/*
+ * Retrieves the common systemd's system d-bus of AFB
+ * 'daemon' MUST be the daemon given in interface when activating the binding.
+ */
+static inline struct sd_bus *afb_daemon_get_system_bus(struct afb_daemon daemon)
+{
+	return daemon.itf->get_system_bus(daemon.closure);
+}
+
+/*
+ * Broadcasts widely the event of 'name' with the data 'object'.
+ * 'object' can be NULL.
+ * 'daemon' MUST be the daemon given in interface when activating the binding.
+ *
+ * For conveniency, the function calls 'json_object_put' for 'object'.
+ * Thus, in the case where 'object' should remain available after
+ * the function returns, the function 'json_object_get' shall be used.
+ *
+ * Returns the count of clients that received the event.
+ */
+static inline int afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object)
+{
+	return daemon.itf->event_broadcast(daemon.closure, name, object);
+}
+
+/*
+ * Creates an event of 'name' and returns it.
+ * 'daemon' MUST be the daemon given in interface when activating the binding.
+ */
+static inline struct afb_event afb_daemon_make_event(struct afb_daemon daemon, const char *name)
+{
+	return daemon.itf->event_make(daemon.closure, name);
+}
+
+/*
+ * Send a message described by 'fmt' and following parameters
+ * to the journal for the verbosity 'level'.
+ * 'file' and 'line' are indicators of position of the code in source files.
+ * 'daemon' MUST be the daemon given in interface when activating the binding.
+ */
+static inline void afb_daemon_verbose(struct afb_daemon daemon, int level, const char *file, int line, const char *fmt, ...) __attribute__((format(printf, 5, 6)));
+static inline void afb_daemon_verbose(struct afb_daemon daemon, int level, const char *file, int line, const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	return daemon.itf->vverbose(daemon.closure, level, file, line, fmt, args);
+	va_end(args);
+}
+
+/*
+ * Macros for logging messages
+ */
+#if !defined(NO_BINDING_VERBOSE_MACRO)
+# if !defined(NO_BINDING_FILE_LINE_INDICATION)
+#  define ERROR(itf,...)   do{if(itf->verbosity>=0)afb_daemon_verbose(itf->daemon,3,__FILE__,__LINE__,__VA_ARGS__);}while(0)
+#  define WARNING(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,4,__FILE__,__LINE__,__VA_ARGS__);}while(0)
+#  define NOTICE(itf,...)  do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,5,__FILE__,__LINE__,__VA_ARGS__);}while(0)
+#  define INFO(itf,...)    do{if(itf->verbosity>=2)afb_daemon_verbose(itf->daemon,6,__FILE__,__LINE__,__VA_ARGS__);}while(0)
+#  define DEBUG(itf,...)   do{if(itf->verbosity>=3)afb_daemon_verbose(itf->daemon,7,__FILE__,__LINE__,__VA_ARGS__);}while(0)
+# else
+#  define ERROR(itf,...)   do{if(itf->verbosity>=0)afb_daemon_verbose(itf->daemon,3,NULL,0,__VA_ARGS__);}while(0)
+#  define WARNING(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,4,NULL,0,__VA_ARGS__);}while(0)
+#  define NOTICE(itf,...)  do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,5,NULL,0,__VA_ARGS__);}while(0)
+#  define INFO(itf,...)    do{if(itf->verbosity>=2)afb_daemon_verbose(itf->daemon,6,NULL,0,__VA_ARGS__);}while(0)
+#  define DEBUG(itf,...)   do{if(itf->verbosity>=3)afb_daemon_verbose(itf->daemon,7,NULL,0,__VA_ARGS__);}while(0)
+# endif
+#endif
+
diff --git a/include/afb/afb-event-itf.h b/include/afb/afb-event-itf.h
index 47ffa387..b89b9415 100644
--- a/include/afb/afb-event-itf.h
+++ b/include/afb/afb-event-itf.h
@@ -35,7 +35,7 @@ struct afb_event_itf {
 };
 
 /*
- * Describes the request by plugins from afb-daemon
+ * Describes the request of afb-daemon for bindings
  */
 struct afb_event {
 	const struct afb_event_itf *itf;	/* the interface to use */
diff --git a/include/afb/afb-plugin.h b/include/afb/afb-plugin.h
index 85e8de7e..3a8a8f4f 100644
--- a/include/afb/afb-plugin.h
+++ b/include/afb/afb-plugin.h
@@ -17,245 +17,24 @@
 
 #pragma once
 
-#include <stdarg.h>
-
-/*****************************************************************************
- * This files is the main file to include for writing plugins dedicated to
- *
- *                      AFB-DAEMON
- *
- * Functions of plugins of afb-daemon are accessible by authorized clients
- * through the apis module of afb-daemon.
- *
- * A plugin is a shared library. This shared library must have at least one
- * exported symbol for being registered in afb-daemon.
- * For the current version of afb-daemon, the function exported MUST be named
- *
- *                  pluginAfbV1Register
- */
-
-/*
- * Some function of the library are exported to afb-daemon.
- */
-
-#include <afb/afb-event-itf.h>
-#include <afb/afb-req-itf.h>
-
-/*
- * Definition of the versions of the plugin.
- * The definition uses hashes.
- */
-enum  AFB_plugin_version
-{
-       AFB_PLUGIN_VERSION_1 = 123456789        /* version 1 */
-};
-
-/*
- * Enum for Session/Token/Assurance middleware.
- * This enumeration is valid for plugins of type 1
- */
-enum AFB_session_v1
-{
-       AFB_SESSION_NONE = 0,   /* nothing required */
-       AFB_SESSION_CREATE = 1, /* Obsolete */
-       AFB_SESSION_CLOSE = 2,  /* After token authentification, closes the session at end */
-       AFB_SESSION_RENEW = 4,  /* After token authentification, refreshes the token at end */
-       AFB_SESSION_CHECK = 8,  /* Requires token authentification */
-
-       AFB_SESSION_LOA_GE = 16, /* check that the LOA is greater or equal to the given value */
-       AFB_SESSION_LOA_LE = 32, /* check that the LOA is lesser or equal to the given value */
-       AFB_SESSION_LOA_EQ = 48, /* check that the LOA is equal to the given value */
-
-       AFB_SESSION_LOA_SHIFT = 6, /* shift for LOA */
-       AFB_SESSION_LOA_MASK = 7,  /* mask for LOA */
-
-       AFB_SESSION_LOA_0 = 0,   /* value for LOA of 0 */
-       AFB_SESSION_LOA_1 = 64,  /* value for LOA of 1 */
-       AFB_SESSION_LOA_2 = 128, /* value for LOA of 2 */
-       AFB_SESSION_LOA_3 = 192, /* value for LOA of 3 */
-       AFB_SESSION_LOA_4 = 256, /* value for LOA of 4 */
-
-       AFB_SESSION_LOA_LE_0 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_0, /* check LOA <= 0 */
-       AFB_SESSION_LOA_LE_1 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_1, /* check LOA <= 1 */
-       AFB_SESSION_LOA_LE_2 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_2, /* check LOA <= 2 */
-       AFB_SESSION_LOA_LE_3 = AFB_SESSION_LOA_LE | AFB_SESSION_LOA_3, /* check LOA <= 3 */
-
-       AFB_SESSION_LOA_GE_0 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_0, /* check LOA >= 0 */
-       AFB_SESSION_LOA_GE_1 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_1, /* check LOA >= 1 */
-       AFB_SESSION_LOA_GE_2 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_2, /* check LOA >= 2 */
-       AFB_SESSION_LOA_GE_3 = AFB_SESSION_LOA_GE | AFB_SESSION_LOA_3, /* check LOA >= 3 */
-
-       AFB_SESSION_LOA_EQ_0 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_0, /* check LOA == 0 */
-       AFB_SESSION_LOA_EQ_1 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_1, /* check LOA == 1 */
-       AFB_SESSION_LOA_EQ_2 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_2, /* check LOA == 2 */
-       AFB_SESSION_LOA_EQ_3 = AFB_SESSION_LOA_EQ | AFB_SESSION_LOA_3  /* check LOA == 3 */
-};
-
-/*
- * Description of one verb of the API provided by the plugin
- * This enumeration is valid for plugins of type 1
- */
-struct AFB_verb_desc_v1
-{
-       const char *name;                       /* name of the verb */
-       enum AFB_session_v1 session;            /* authorisation and session requirements of the verb */
-       void (*callback)(struct afb_req req);   /* callback function implementing the verb */
-       const char *info;                       /* textual description of the verb */
-};
-
-/*
- * Description of the plugins of type 1
- */
-struct AFB_plugin_desc_v1
-{
-       const char *info;                       /* textual information about the plugin */
-       const char *prefix;                     /* required prefix name for the plugin */
-       const struct AFB_verb_desc_v1 *verbs;   /* array of descriptions of verbs terminated by a NULL name */
-};
-
-/*
- * Description of a plugin
- */
-struct AFB_plugin
-{
-       enum AFB_plugin_version type; /* type of the plugin */
-       union {
-               struct AFB_plugin_desc_v1 v1;   /* description of the plugin of type 1 */
-       };
-};
-
-/*
- * config mode
- */
-enum AFB_Mode {
-       AFB_MODE_LOCAL = 0,     /* run locally */
-       AFB_MODE_REMOTE,        /* run remotely */
-       AFB_MODE_GLOBAL         /* run either remotely or locally (DONT USE! reserved for future) */
-};
-
-/* declaration of features of libsystemd */
-struct sd_event;
-struct sd_bus;
-
-/*
- * Definition of the facilities provided by the daemon.
- */
-struct afb_daemon_itf {
-       int (*event_broadcast)(void *closure, const char *name, struct json_object *object); /* broadcasts evant 'name' with 'object' */
-       struct sd_event *(*get_event_loop)(void *closure);      /* gets the common systemd's event loop */
-       struct sd_bus *(*get_user_bus)(void *closure);          /* gets the common systemd's user d-bus */
-       struct sd_bus *(*get_system_bus)(void *closure);        /* gets the common systemd's system d-bus */
-       void (*vverbose)(void*closure, int level, const char *file, int line, const char *fmt, va_list args);
-       struct afb_event (*event_make)(void *closure, const char *name); /* creates an event of 'name' */
-};
-
-/*
- * Structure for accessing daemon.
- * See also: afb_daemon_get_event_sender, afb_daemon_get_event_loop, afb_daemon_get_user_bus, afb_daemon_get_system_bus
- */
-struct afb_daemon {
-       const struct afb_daemon_itf *itf;       /* the interfacing functions */
-       void *closure;                          /* the closure when calling these functions */
-};
-
-/*
- * Interface between the daemon and the plugin.
- */
-struct AFB_interface
-{
-       struct afb_daemon daemon;       /* access to the daemon facilies */
-       int verbosity;                  /* level of verbosity */
-       enum AFB_Mode mode;             /* run mode (local or remote) */
-};
-
-/*
- * Function for registering the plugin
- */
-extern const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *interface);
-
-/*
- * Retrieves the common systemd's event loop of AFB
- * 'daemon' MUST be the daemon given in interface when activating the plugin.
- */
-static inline struct sd_event *afb_daemon_get_event_loop(struct afb_daemon daemon)
-{
-	return daemon.itf->get_event_loop(daemon.closure);
-}
-
-/*
- * Retrieves the common systemd's user/session d-bus of AFB
- * 'daemon' MUST be the daemon given in interface when activating the plugin.
- */
-static inline struct sd_bus *afb_daemon_get_user_bus(struct afb_daemon daemon)
-{
-	return daemon.itf->get_user_bus(daemon.closure);
-}
-
-/*
- * Retrieves the common systemd's system d-bus of AFB
- * 'daemon' MUST be the daemon given in interface when activating the plugin.
- */
-static inline struct sd_bus *afb_daemon_get_system_bus(struct afb_daemon daemon)
-{
-	return daemon.itf->get_system_bus(daemon.closure);
-}
+#if defined(NO_PLUGIN_VERBOSE_MACRO)
+#  define NO_BINDING_VERBOSE_MACRO
+#endif
 
-/*
- * Broadcasts widely the event of 'name' with the data 'object'.
- * 'object' can be NULL.
- * 'daemon' MUST be the daemon given in interface when activating the plugin.
- *
- * For conveniency, the function calls 'json_object_put' for 'object'.
- * Thus, in the case where 'object' should remain available after
- * the function returns, the function 'json_object_get' shall be used.
- *
- * Returns the count of clients that received the event.
- */
-static inline int afb_daemon_broadcast_event(struct afb_daemon daemon, const char *name, struct json_object *object)
-{
-	return daemon.itf->event_broadcast(daemon.closure, name, object);
-}
+#if defined(NO_PLUGIN_FILE_LINE_INDICATION)
+#  define NO_BINDING_FILE_LINE_INDICATION
+#endif
 
-/*
- * Creates an event of 'name' and returns it.
- * 'daemon' MUST be the daemon given in interface when activating the plugin.
- */
-static inline struct afb_event afb_daemon_make_event(struct afb_daemon daemon, const char *name)
-{
-	return daemon.itf->event_make(daemon.closure, name);
-}
+#include "afb-binding.h"
 
-/*
- * Send a message described by 'fmt' and following parameters
- * to the journal for the verbosity 'level'.
- * 'file' and 'line' are indicators of position of the code in source files.
- * 'daemon' MUST be the daemon given in interface when activating the plugin.
- */
-static inline void afb_daemon_verbose(struct afb_daemon daemon, int level, const char *file, int line, const char *fmt, ...) __attribute__((format(printf, 5, 6)));
-static inline void afb_daemon_verbose(struct afb_daemon daemon, int level, const char *file, int line, const char *fmt, ...)
-{
-	va_list args;
-	va_start(args, fmt);
-	return daemon.itf->vverbose(daemon.closure, level, file, line, fmt, args);
-	va_end(args);
-}
+#define AFB_plugin_version         afb_binding_type
+#define AFB_PLUGIN_VERSION_1       AFB_BINDING_VERSION_1
+#define AFB_plugin_desc_v1         afb_binding_desc_v1
+#define AFB_plugin                 afb_binding
+#define AFB_interface              afb_binding_interface
+#define pluginAfbV1Register        afbBindingV1Register
 
-/*
- * Macros for logging messages
- */
-#if !defined(NO_PLUGIN_VERBOSE_MACRO)
-# if !defined(NO_PLUGIN_FILE_LINE_INDICATION)
-#  define ERROR(itf,...)   do{if(itf->verbosity>=0)afb_daemon_verbose(itf->daemon,3,__FILE__,__LINE__,__VA_ARGS__);}while(0)
-#  define WARNING(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,4,__FILE__,__LINE__,__VA_ARGS__);}while(0)
-#  define NOTICE(itf,...)  do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,5,__FILE__,__LINE__,__VA_ARGS__);}while(0)
-#  define INFO(itf,...)    do{if(itf->verbosity>=2)afb_daemon_verbose(itf->daemon,6,__FILE__,__LINE__,__VA_ARGS__);}while(0)
-#  define DEBUG(itf,...)   do{if(itf->verbosity>=3)afb_daemon_verbose(itf->daemon,7,__FILE__,__LINE__,__VA_ARGS__);}while(0)
-# else
-#  define ERROR(itf,...)   do{if(itf->verbosity>=0)afb_daemon_verbose(itf->daemon,3,NULL,0,__VA_ARGS__);}while(0)
-#  define WARNING(itf,...) do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,4,NULL,0,__VA_ARGS__);}while(0)
-#  define NOTICE(itf,...)  do{if(itf->verbosity>=1)afb_daemon_verbose(itf->daemon,5,NULL,0,__VA_ARGS__);}while(0)
-#  define INFO(itf,...)    do{if(itf->verbosity>=2)afb_daemon_verbose(itf->daemon,6,NULL,0,__VA_ARGS__);}while(0)
-#  define DEBUG(itf,...)   do{if(itf->verbosity>=3)afb_daemon_verbose(itf->daemon,7,NULL,0,__VA_ARGS__);}while(0)
-# endif
-#endif
 
+#define AFB_Mode                   afb_mode
+#define AFB_session_v1             afb_session_v1
+#define AFB_verb_desc_v1           afb_verb_desc_v1
diff --git a/include/afb/afb-req-itf.h b/include/afb/afb-req-itf.h
index 3efb089d..af452faf 100644
--- a/include/afb/afb-req-itf.h
+++ b/include/afb/afb-req-itf.h
@@ -75,7 +75,7 @@ struct afb_req_itf {
 };
 
 /*
- * Describes the request by plugins from afb-daemon
+ * Describes the request by bindings from afb-daemon
  */
 struct afb_req {
 	const struct afb_req_itf *itf;	/* the interface to use */
@@ -206,8 +206,8 @@ static inline void afb_req_fail_f(struct afb_req req, const char *status, const
 }
 
 /*
- * Gets the pointer stored by the plugin for the session of 'req'.
- * When the plugin has not yet recorded a pointer, NULL is returned.
+ * Gets the pointer stored by the binding for the session of 'req'.
+ * When the binding has not yet recorded a pointer, NULL is returned.
  */
 static inline void *afb_req_context_get(struct afb_req req)
 {
@@ -215,9 +215,9 @@ static inline void *afb_req_context_get(struct afb_req req)
 }
 
 /*
- * Stores for the plugin the pointer 'context' to the session of 'req'.
+ * Stores for the binding the pointer 'context' to the session of 'req'.
  * The function 'free_context' will be called when the session is closed
- * or if plugin stores an other pointer.
+ * or if binding stores an other pointer.
  */
 static inline void afb_req_context_set(struct afb_req req, void *context, void (*free_context)(void*))
 {
@@ -225,7 +225,7 @@ static inline void afb_req_context_set(struct afb_req req, void *context, void (
 }
 
 /*
- * Gets the pointer stored by the plugin for the session of 'req'.
+ * Gets the pointer stored by the binding for the session of 'req'.
  * If the stored pointer is NULL, indicating that no pointer was
  * already stored, afb_req_context creates a new context by calling
  * the function 'create_context' and stores it with the freeing function
@@ -242,7 +242,7 @@ static inline void *afb_req_context(struct afb_req req, void *(*create_context)(
 }
 
 /*
- * Frees the pointer stored by the plugin for the session of 'req'
+ * Frees the pointer stored by the binding for the session of 'req'
  * and sets it to NULL.
  *
  * Shortcut for: afb_req_context_set(req, NULL, NULL)
diff --git a/include/afb/afb-service-itf.h b/include/afb/afb-service-itf.h
index ac40cf79..1218cd5b 100644
--- a/include/afb/afb-service-itf.h
+++ b/include/afb/afb-service-itf.h
@@ -31,9 +31,9 @@ struct afb_service
 	void *closure;
 };
 
-extern int pluginAfbV1ServiceInit(struct afb_service service);
+extern int afbBindingV1ServiceInit(struct afb_service service);
 
-extern void pluginAfbV1ServiceEvent(const char *event, struct json_object *object);
+extern void afbBindingV1ServiceEvent(const char *event, struct json_object *object);
 
 static inline void afb_service_call(struct afb_service service, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *callback_closure)
 {
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
deleted file mode 100644
index 2aacf1a1..00000000
--- a/plugins/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-ADD_SUBDIRECTORY(samples)
-ADD_SUBDIRECTORY(audio)
-ADD_SUBDIRECTORY(radio)
-ADD_SUBDIRECTORY(media)
-ADD_SUBDIRECTORY(intrinsics)
diff --git a/plugins/audio/CMakeLists.txt b/plugins/audio/CMakeLists.txt
deleted file mode 100644
index 2d74fd62..00000000
--- a/plugins/audio/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-INCLUDE(FindPkgConfig)
-PKG_CHECK_MODULES(alsa alsa)
-PKG_CHECK_MODULES(pulseaudio libpulse libpulse-simple)
-INCLUDE(FindThreads)
-FIND_PACKAGE(Threads)
-
-IF(alsa_FOUND)
-
-  MESSAGE(STATUS "ALSA found ; will compile Audio plugin... (PLUGIN)")
-
-  IF(pulseaudio_FOUND)
-    MESSAGE(STATUS "PulseAudio found ; Audio plugin will have PulseAudio support")
-    ADD_DEFINITIONS(-DHAVE_PULSE=1)
-    SET(pulse_sources audio-pulse.c)
-  ENDIF(pulseaudio_FOUND)
-
-  INCLUDE_DIRECTORIES(${include_dirs} ${alsa_INCLUDE_DIRS} ${pulseaudio_INCLUDE_DIRS})
-  ADD_LIBRARY(audio-api MODULE audio-api.c audio-alsa.c ${pulse_sources})
-  SET_TARGET_PROPERTIES(audio-api PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
-  )
-  TARGET_LINK_LIBRARIES(audio-api ${link_libraries} ${alsa_LIBRARIES} ${pulseaudio_LIBRARIES})
-  INSTALL(TARGETS audio-api
-          LIBRARY DESTINATION ${plugin_install_dir})
-
-ENDIF(alsa_FOUND)
diff --git a/plugins/audio/audio-alsa.c b/plugins/audio/audio-alsa.c
deleted file mode 100644
index 45ff2edb..00000000
--- a/plugins/audio/audio-alsa.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "audio-api.h"
-#include "audio-alsa.h"
-
-snd_mixer_selem_channel_id_t SCHANNELS[8] = {
- SND_MIXER_SCHN_FRONT_LEFT,
- SND_MIXER_SCHN_FRONT_RIGHT,
- SND_MIXER_SCHN_FRONT_CENTER,
- SND_MIXER_SCHN_REAR_LEFT,
- SND_MIXER_SCHN_REAR_RIGHT,
- SND_MIXER_SCHN_REAR_CENTER,
- SND_MIXER_SCHN_SIDE_LEFT,
- SND_MIXER_SCHN_SIDE_RIGHT
-};
-
-static struct dev_ctx_alsa **dev_ctx_a = NULL;
-
-
-unsigned char _alsa_init (const char *name, audioCtxHandleT *ctx) {
-
-    snd_pcm_t *dev;
-    snd_pcm_hw_params_t *params;
-    snd_mixer_t *mixer;
-    snd_mixer_selem_id_t *mixer_sid;
-    snd_mixer_elem_t *mixer_elm;
-    snd_mixer_elem_t *mixer_elm_m;
-    unsigned int rate = 22050;
-    long vol, vol_min, vol_max;
-    int num, i;
-
-    if (snd_pcm_open (&dev, name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
-        fprintf (stderr, "ALSA backend could not open card '%s'\n", name);
-        return 0;
-    }
-
-    snd_pcm_hw_params_malloc (&params);
-    snd_pcm_hw_params_any (dev, params);
-    snd_pcm_hw_params_set_access (dev, params, SND_PCM_ACCESS_RW_INTERLEAVED);
-    snd_pcm_hw_params_set_format (dev, params, SND_PCM_FORMAT_S16_LE);
-    snd_pcm_hw_params_set_rate_near (dev, params, &rate, 0);
-    snd_pcm_hw_params_set_channels (dev, params, ctx->channels);
-    if (snd_pcm_hw_params (dev, params) < 0) {
-        snd_pcm_hw_params_free (params);
-        fprintf (stderr, "ALSA backend could set channels on card '%s'\n", name);
-        return 0;
-    }
-    snd_pcm_prepare (dev);
-
-    snd_mixer_open (&mixer, 0);
-    if (snd_mixer_attach (mixer, name) < 0) {
-        snd_pcm_hw_params_free (params);
-        fprintf (stderr, "ALSA backend could not open mixer for card '%s'\n", name);
-        return 0;
-    }
-    snd_mixer_selem_register (mixer, NULL, NULL);
-    snd_mixer_load (mixer);
-
-    snd_mixer_selem_id_alloca (&mixer_sid);
-    snd_mixer_selem_id_set_index (mixer_sid, 0);
-    snd_mixer_selem_id_set_name (mixer_sid, "Master");
-
-    mixer_elm = snd_mixer_find_selem (mixer, mixer_sid);
-    mixer_elm_m = NULL;
-
-    if (!mixer_elm) {
-        /* no "Master" mixer ; we are probably on a board... search ! */
-        for (mixer_elm = snd_mixer_first_elem (mixer); mixer_elm != NULL;
-             mixer_elm = snd_mixer_elem_next (mixer_elm)) {
-            if (snd_mixer_elem_info (mixer_elm) < 0)
-                continue;
-            snd_mixer_selem_get_id (mixer_elm, mixer_sid);
-            if (strstr (snd_mixer_selem_id_get_name (mixer_sid), "DVC Out")) {
-
-                /* this is Porter... let us found the specific mute switch */
-                snd_mixer_selem_id_set_index (mixer_sid, 0);
-                snd_mixer_selem_id_set_name (mixer_sid, "DVC Out Mute");
-                mixer_elm_m = snd_mixer_find_selem (mixer, mixer_sid);
-
-                break;
-            }
-        }
-    }
-
-    if (mixer_elm) {
-        snd_mixer_selem_get_playback_volume_range (mixer_elm, &vol_min, &vol_max);
-        snd_mixer_selem_get_playback_volume (mixer_elm, SND_MIXER_SCHN_FRONT_LEFT, &vol);
-    }
-
-    /* allocate the global array if it hasn't been done */
-    if (!dev_ctx_a) {
-        dev_ctx_a = (dev_ctx_alsa_T**) malloc (sizeof(dev_ctx_alsa_T*));
-        dev_ctx_a[0] = (dev_ctx_alsa_T*) malloc (sizeof(dev_ctx_alsa_T));
-        dev_ctx_a[0]->name = NULL;
-        dev_ctx_a[0]->dev = NULL;
-    }
-
-    /* is a card with similar name already opened ? */
-    for (num = 0; num < (sizeof(dev_ctx_a)/sizeof(dev_ctx_alsa_T*)); num++) {
-        if (dev_ctx_a[num]->name &&
-           !strcmp (dev_ctx_a[num]->name, name)) {
-            fprintf (stderr, "Card '%s' already locked by other ALSA backend session\n", name);
-            return 0;
-        }
-    }
-    num--;
-
-    /* it's not... let us add it to the global array */
-    dev_ctx_a = (dev_ctx_alsa_T**) realloc (dev_ctx_a, (num+1)*sizeof(dev_ctx_alsa_T*));
-    if (!dev_ctx_a[num])
-        dev_ctx_a[num] = (dev_ctx_alsa_T*) malloc (sizeof(dev_ctx_alsa_T));
-    dev_ctx_a[num]->name = strdup (name);
-    dev_ctx_a[num]->dev = dev;
-    dev_ctx_a[num]->params = params;
-    dev_ctx_a[num]->mixer_elm = mixer_elm;
-    dev_ctx_a[num]->mixer_elm_m = mixer_elm_m;
-    dev_ctx_a[num]->vol_max = vol_max;
-    dev_ctx_a[num]->vol = vol;
-    dev_ctx_a[num]->thr_should_run = 0;
-    dev_ctx_a[num]->thr_finished = 0;
-
-    /* make the client context aware of current card state */
-    for (i = 0; i < 8; i++)
-        ctx->volume[i] = _alsa_get_volume (num, i);
-    ctx->mute = _alsa_get_mute (num);
-    ctx->idx = num;
-    ctx->name = strdup (name);
-
-    fprintf (stderr, "Successfully initialized ALSA backend.\n");
-
-    return 1;
-}
-
-void _alsa_free (const char *name) {
-
-    int num;
-
-    for (num = 0; num < (sizeof(dev_ctx_a)/sizeof(dev_ctx_alsa_T*)); num++) {
-        if (dev_ctx_a[num]->name &&
-           !strcmp (dev_ctx_a[num]->name, name)) {
-            snd_pcm_close (dev_ctx_a[num]->dev);
-            snd_pcm_hw_params_free (dev_ctx_a[num]->params);
-            free (dev_ctx_a[num]->name);
-            dev_ctx_a[num]->dev = NULL;
-            dev_ctx_a[num]->name = NULL;
-            free (dev_ctx_a[num]);
-            return;
-        }
-    }
-}
-
-void _alsa_play (int num) {
-
-    if (!dev_ctx_a || !dev_ctx_a[num] || dev_ctx_a[num]->thr_should_run ||
-        access (AUDIO_BUFFER, F_OK) == -1)
-        return;
-
-    dev_ctx_a[num]->thr_should_run = 1;
-    dev_ctx_a[num]->thr_finished = 0;
-    pthread_create (&dev_ctx_a[num]->thr, NULL, _alsa_play_thread_fn, (void*)dev_ctx_a[num]);
-}
-
-void _alsa_stop (int num) {
-
-    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->thr_should_run)
-        return;
-
-    /* stop the "while" loop in thread */
-    dev_ctx_a[num]->thr_should_run = 0;
-
-    while (!dev_ctx_a[num]->thr_finished)
-        usleep(100000);
-
-    pthread_join (dev_ctx_a[num]->thr, NULL);
-}
-
-unsigned int _alsa_get_volume (int num, unsigned int channel) {
-
-    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm)
-        return 0;
-
-    snd_mixer_selem_get_playback_volume (dev_ctx_a[num]->mixer_elm, SCHANNELS[channel], &dev_ctx_a[num]->vol);
-
-    return (unsigned int)(dev_ctx_a[num]->vol*100)/dev_ctx_a[num]->vol_max;
-}
-
-void _alsa_set_volume (int num, unsigned int channel, unsigned int vol) {
-
-    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm ||
-        vol > 100)
-        return;
-
-    snd_mixer_selem_set_playback_volume (dev_ctx_a[num]->mixer_elm, SCHANNELS[channel], (vol*dev_ctx_a[num]->vol_max)/100);
-}
-
-void _alsa_set_volume_all (int num, unsigned int vol) {
-
-    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm ||
-        vol > 100)
-
-    fflush (stdout); /* seems to force this logic to apply quickly */
-    snd_mixer_selem_set_playback_volume_all (dev_ctx_a[num]->mixer_elm, (vol*dev_ctx_a[num]->vol_max)/100);
-}
-
-unsigned char _alsa_get_mute (int num) {
-
-    int mute = 0;
-    snd_mixer_elem_t *elm_m;
-
-    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm)
-        return 0;
-
-    dev_ctx_a[num]->mixer_elm_m ? (elm_m = dev_ctx_a[num]->mixer_elm_m) :
-                                  (elm_m = dev_ctx_a[num]->mixer_elm);
-
-    if (snd_mixer_selem_has_playback_switch (elm_m)) {
-        snd_mixer_selem_get_playback_switch (elm_m, SND_MIXER_SCHN_FRONT_LEFT, &mute);
-        snd_mixer_selem_get_playback_switch (elm_m, SND_MIXER_SCHN_FRONT_RIGHT, &mute);
-    }
-
-    if (dev_ctx_a[num]->mixer_elm_m)
-        return (unsigned char)mute;
-    else
-        return (unsigned char)!mute;
-}
-
-void _alsa_set_mute (int num, unsigned char tomute) {
-
-    snd_mixer_elem_t *elm_m;
-    int mute;
-
-    if (!dev_ctx_a || !dev_ctx_a[num] || !dev_ctx_a[num]->mixer_elm || 1 < tomute)
-        return;
-
-    if (dev_ctx_a[num]->mixer_elm_m) {
-        elm_m = dev_ctx_a[num]->mixer_elm_m;
-        mute = (int)!tomute;
-    } else {
-        elm_m = dev_ctx_a[num]->mixer_elm;
-        mute = (int)tomute;
-    }
-
-    if (snd_mixer_selem_has_playback_switch (elm_m))
-        snd_mixer_selem_set_playback_switch_all (elm_m, !mute);
-}
-
-void _alsa_set_rate (int num, unsigned int rate) {
-
-    if (!dev_ctx_a || !dev_ctx_a[num])
-        return;
-
-    snd_pcm_hw_params_set_rate_near (dev_ctx_a[num]->dev, dev_ctx_a[num]->params, &rate, 0);
-}
-
-void _alsa_set_channels (int num, unsigned int channels) {
-
-    if (!dev_ctx_a || !dev_ctx_a[num])
-        return;
-
-    snd_pcm_hw_params_set_channels (dev_ctx_a[num]->dev, dev_ctx_a[num]->params, channels);
-}
-
- /* ---- LOCAL THREADED FUNCTIONS ---- */
-
-void* _alsa_play_thread_fn (void *ctx) {
-
-    dev_ctx_alsa_T *dev_ctx_a = (dev_ctx_alsa_T *)ctx;
-    FILE *file = NULL;
-    char *buf = NULL;
-    long size;
-    int frames, res;
-
-    file = fopen (AUDIO_BUFFER, "rb");
-
-    while (dev_ctx_a->thr_should_run && file && (access (AUDIO_BUFFER, F_OK) != -1) ) {
-        fseek (file, 0, SEEK_END);
-        size = ftell (file);
-        buf = (char*) realloc (buf, size * sizeof(char));
-        frames = (size * sizeof(char)) / 4;
-
-        fseek (file, 0, SEEK_SET);
-        fread (buf, 1, size, file);
-        fflush (file);
-
-        if ((res = snd_pcm_writei (dev_ctx_a->dev, buf, frames)) != frames) {
-            snd_pcm_recover (dev_ctx_a->dev, res, 0);
-            snd_pcm_prepare (dev_ctx_a->dev);
-        }
-        /* snd_pcm_drain (dev_ctx->dev); */
-    }
-    if (buf) free(buf);
-    if (file) fclose(file);
-
-    dev_ctx_a->thr_finished = 1;
-    return 0;
-}
diff --git a/plugins/audio/audio-alsa.h b/plugins/audio/audio-alsa.h
deleted file mode 100644
index 679d4eee..00000000
--- a/plugins/audio/audio-alsa.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef AUDIO_ALSA_H
-#define AUDIO_ALSA_H
-
-#include <pthread.h>
-#include <alsa/asoundlib.h>
-
-#include "audio-api.h"
-
-#define AUDIO_BUFFER "/tmp/audio_buf"
-
-typedef struct dev_ctx_alsa dev_ctx_alsa_T;
-
-struct dev_ctx_alsa {
-  char *name;
-  snd_pcm_t *dev;
-  snd_pcm_hw_params_t *params;
-  snd_mixer_elem_t *mixer_elm;
-  snd_mixer_elem_t *mixer_elm_m;
-  long vol_max;
-  long vol;
-  pthread_t thr;
-  unsigned char thr_should_run;
-  unsigned char thr_finished;
-};
-
-unsigned char _alsa_init (const char *, audioCtxHandleT *);
-void _alsa_free (const char *);
-void _alsa_play (int);
-void _alsa_stop (int);
-unsigned int _alsa_get_volume (int, unsigned int);
-void _alsa_set_volume (int, unsigned int, unsigned int);
-void _alsa_set_volume_all (int, unsigned int);
-unsigned char _alsa_get_mute (int);
-void _alsa_set_mute (int, unsigned char);
-void _alsa_set_channels (int, unsigned int);
-
-void* _alsa_play_thread_fn (void *);
-
-#endif /* AUDIO_ALSA_H */
diff --git a/plugins/audio/audio-api.c b/plugins/audio/audio-api.c
deleted file mode 100644
index 1ba9126c..00000000
--- a/plugins/audio/audio-api.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdlib.h>
-#include <json-c/json.h>
-
-#include "audio-api.h"
-#include "audio-alsa.h"
-#ifdef HAVE_PULSE
-#include "audio-pulse.h"
-#endif
-
-#include <afb/afb-plugin.h>
-#include <afb/afb-req-itf.h>
-
-/* ------ BACKEND FUNCTIONS ------- */
-
-unsigned char _backend_init (const char *name, audioCtxHandleT *ctx) {
-
-    char *backend_env = getenv ("AFB_AUDIO_OUTPUT");
-    unsigned char res = 0;
-
-# ifdef HAVE_PULSE
-    if (!backend_env || (strcasecmp (backend_env, "Pulse") == 0))
-        res = _pulse_init (name, ctx);
-    if (!res)
-#endif
-    res = _alsa_init (name, ctx);
-
-    if (!res)
-        fprintf (stderr, "Could not initialize Audio backend\n");
-
-    return res;
-}
-
-void _backend_free (audioCtxHandleT *ctx) {
-
-# ifdef HAVE_PULSE
-    if (ctx->audio_dev) _pulse_free (ctx); else
-# endif
-    _alsa_free (ctx->name);
-}
-
-void _backend_play (audioCtxHandleT *ctx) {
-
-# ifdef HAVE_PULSE
-    if (ctx->audio_dev) _pulse_play (ctx); else
-# endif
-    _alsa_play (ctx->idx);
-}
-
-void _backend_stop (audioCtxHandleT *ctx) {
-
-# ifdef HAVE_PULSE
-    if (ctx->audio_dev) _pulse_stop (ctx); else
-# endif
-    _alsa_stop (ctx->idx);
-}
-
-unsigned int _backend_get_volume (audioCtxHandleT *ctx, unsigned int channel) {
-
-# ifdef HAVE_PULSE
-    if (ctx->audio_dev) return _pulse_get_volume (ctx, channel); else
-# endif
-    return _alsa_get_volume (ctx->idx, channel);
-}
-
-void _backend_set_volume (audioCtxHandleT *ctx, unsigned int channel, unsigned int vol) {
-
-# ifdef HAVE_PULSE
-    if (ctx->audio_dev) _pulse_set_volume (ctx, channel, vol); else
-# endif
-    _alsa_set_volume (ctx->idx, channel, vol);
-}
-
-void _backend_set_volume_all (audioCtxHandleT *ctx, unsigned int vol) {
-
-# ifdef HAVE_PULSE
-    if (ctx->audio_dev) _pulse_set_volume_all (ctx, vol); else
-# endif
-    _alsa_set_volume_all (ctx->idx, vol);
-}
-
-unsigned char _backend_get_mute (audioCtxHandleT *ctx) {
-
-# ifdef HAVE_PULSE
-    if (ctx->audio_dev) return _pulse_get_mute (ctx); else
-# endif
-    return _alsa_get_mute (ctx->idx);
-}
-
-void _backend_set_mute (audioCtxHandleT *ctx, unsigned char mute) {
-
-# ifdef HAVE_PULSE
-    if (ctx->audio_dev) _pulse_set_mute (ctx, mute); else
-# endif
-    _alsa_set_mute (ctx->idx, mute);
-}
-
-void _backend_set_channels (audioCtxHandleT *ctx, unsigned int channels) {
-
-# ifdef HAVE_PULSE
-    if (ctx->audio_dev) return; else
-# endif
-    _alsa_set_channels (ctx->idx, channels);
-}
-
-/* ------ LOCAL HELPER FUNCTIONS --------- */
-
-/* private client context constructor ; default values */
-static audioCtxHandleT* initAudioCtx () {
-
-    audioCtxHandleT *ctx;
-    int i;
-
-    ctx = malloc (sizeof(audioCtxHandleT));
-    ctx->audio_dev = NULL;
-    ctx->name = NULL;
-    ctx->idx = -1;
-    for (i = 0; i < 8; i++)
-        ctx->volume[i] = 25;
-    ctx->channels = 2;
-    ctx->mute = 0;
-    ctx->is_playing = 0;
-
-    return ctx;
-}
-
-static void releaseAudioCtx (void *context) {
-
-    audioCtxHandleT *ctx = (audioCtxHandleT*) context;
-
-    /* power it off */
-    _backend_free (ctx);
-
-    /* clean client context */
-    ctx->audio_dev = NULL;
-    if (ctx->name)
-		free (ctx->name);
-    ctx->idx = -1;
-    free (ctx);
-}
-
-
-/* ------ PUBLIC PLUGIN FUNCTIONS --------- */
-
-static void init (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    audioCtxHandleT *ctx = afb_req_context_get (request);
-    json_object *jresp;
-
-    /* create a private client context */
-	if (!ctx) {
-        ctx = initAudioCtx();
-        afb_req_context_set (request, ctx, releaseAudioCtx);
-    }
-
-    if (!_backend_init ("default", ctx))
-        afb_req_fail (request, "failed", "backend initialization failed");
-
-    jresp = json_object_new_object();
-    json_object_object_add (jresp, "init", json_object_new_string ("success"));
-    afb_req_success (request, jresp, "Audio initialized");
-}
-
-static void volume (struct afb_req request) {      /* AFB_SESSION_CHECK */
-
-    audioCtxHandleT *ctx = afb_req_context_get (request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp;
-    unsigned int volume[8], i;
-    char *volume_i;
-    char volume_str[256];
-    size_t len_str = 0;
-
-	if (!ctx) {
-        afb_req_fail (request, "failed", "you must call 'init' first");
-        return;
-    }
-    jresp = json_object_new_object();
-
-    /* no "?value=" parameter : return current state */
-    if (!value) {
-        for (i = 0; i < 8; i++) {
-            ctx->volume[i] = _backend_get_volume (ctx, i);
-            snprintf (volume_str+len_str, sizeof(volume_str)-len_str, "%d,", ctx->volume[i]);
-            len_str = strlen (volume_str);
-        }
-        json_object_object_add (jresp, "volume", json_object_new_string(volume_str));
-        afb_req_success (request, jresp, "Audio - Volume obtained");
-        return;
-    }
-
-    /* "?value=" parameter, set volume */
-    else {
-        volume_i = strdup (value);
-        volume_i = strtok (volume_i, ",");
-        volume[0] = (unsigned int) atoi (volume_i);
-
-        if (100 < volume[0]) {
-            free (volume_i);
-            afb_req_fail (request, "failed", "volume must be between 0 and 100");
-            return;
-        }
-        ctx->volume[0] = volume[0];
-        _backend_set_volume (ctx, 0, ctx->volume[0]);
-        snprintf (volume_str, sizeof(volume_str), "%d,", ctx->volume[0]);
-
-        for (i = 1; i < 8; i++) {
-            volume_i = strtok (NULL, ",");
-            /* if there is only one value, set all channels to this one */
-            if (!volume_i && i == 1)
-               _backend_set_volume_all (ctx, ctx->volume[0]);
-            if (!volume_i || 100 < atoi(volume_i) || atoi(volume_i) < 0)
-               ctx->volume[i] = _backend_get_volume (ctx, i);
-            else {
-               ctx->volume[i] = (unsigned int) atoi(volume_i);
-               _backend_set_volume (ctx, i, ctx->volume[i]);
-            }
-            len_str = strlen(volume_str);
-            snprintf (volume_str+len_str, sizeof(volume_str)-len_str, "%d,", ctx->volume[i]);
-        }
-        free (volume_i);
-        json_object_object_add (jresp, "volume", json_object_new_string(volume_str));
-    }
-
-    afb_req_success (request, jresp, "Audio - Volume changed");
-}
-
-static void channels (struct afb_req request) {    /* AFB_SESSION_CHECK */
-
-    audioCtxHandleT *ctx = afb_req_context_get (request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp;
-    char channels_str[256];
-
-	if (!ctx) {
-        afb_req_fail (request, "failed", "you must call 'init' first");
-        return;
-    }
-    jresp = json_object_new_object();
-
-    /* no "?value=" parameter : return current state */
-    if (!value) {
-        snprintf (channels_str, sizeof(channels_str), "%d", ctx->channels);
-
-        json_object_object_add (jresp, "channels", json_object_new_string (channels_str));
-        afb_req_success (request, jresp, "Audio - Channels obtained");
-        return;
-    }
-
-    /* "?value=" parameter, set channels */
-    else {
-        ctx->channels = (unsigned int) atoi (value);
-        _backend_set_channels (ctx, ctx->channels);
-        snprintf (channels_str, sizeof(channels_str), "%d", ctx->channels);
-
-        jresp = json_object_new_object();
-        json_object_object_add (jresp, "channels", json_object_new_string (channels_str));
-    }
-
-    afb_req_success (request, jresp, "Audio - Channels set");
-}
-
-static void mute (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    audioCtxHandleT *ctx = afb_req_context_get (request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp;
-
-	if (!ctx) {
-        afb_req_fail (request, "failed", "you must call 'init' first");
-        return;
-    }
-    jresp = json_object_new_object();
-
-    /* no "?value=" parameter : return current state */
-    if (!value) {
-        ctx->mute = _backend_get_mute (ctx);
-        ctx->mute ?
-            json_object_object_add (jresp, "mute", json_object_new_string ("on"))
-          : json_object_object_add (jresp, "mute", json_object_new_string ("off"));
-        afb_req_success (request, jresp, "Audio - Mute status obtained");
-        return;
-    }
-
-    /* "?value=" parameter is "1" or "true" */
-    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
-        ctx->mute = 1;
-        _backend_set_mute (ctx, ctx->mute);
-        json_object_object_add (jresp, "mute", json_object_new_string ("on"));
-    }
-
-    /* "?value=" parameter is "0" or "false" */
-    else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
-        ctx->mute = 0;
-        _backend_set_mute (ctx, ctx->mute);
-        json_object_object_add (jresp, "mute", json_object_new_string ("off"));
-    }
-
-    afb_req_success (request, jresp, "Audio - Mute set");
-}
-
-static void play (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    audioCtxHandleT *ctx = afb_req_context_get (request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp;
-
-	if (!ctx) {
-        afb_req_fail (request, "failed", "you must call 'init' first");
-        return;
-    }
-    jresp = json_object_new_object();
-
-    /* no "?value=" parameter : return current state */
-    if (!value) {
-        ctx->is_playing ?
-            json_object_object_add (jresp, "play", json_object_new_string ("on"))
-          : json_object_object_add (jresp, "play", json_object_new_string ("off"));
-        afb_req_success (request, jresp, "Audio - Playing status obtained");
-        return;
-    }
-
-    /* "?value=" parameter is "1" or "true" */
-    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
-        ctx->is_playing = 1;
-        _backend_play (ctx);
-        json_object_object_add (jresp, "play", json_object_new_string ("on"));
-    }
-
-    /* "?value=" parameter is "0" or "false" */
-    else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
-        ctx->is_playing = 0;
-        _backend_stop (ctx);
-        json_object_object_add (jresp, "play", json_object_new_string ("off"));
-    }
-
-    afb_req_success (request, jresp, "Audio - Play");
-}
-
-static void ping (struct afb_req request) {         /* AFB_SESSION_NONE */
-    afb_req_success (request, NULL, "Audio - Ping success");
-}
-
-static const struct AFB_verb_desc_v1 verbs[] = {
-  {"init"    , AFB_SESSION_CHECK,  init      , "Audio API - init"},
-  {"volume"  , AFB_SESSION_CHECK,  volume    , "Audio API - volume"},
-  {"channels", AFB_SESSION_CHECK,  channels  , "Audio API - channels"},
-  {"mute"    , AFB_SESSION_CHECK,  mute      , "Audio API - mute"},
-  {"play"    , AFB_SESSION_CHECK,  play      , "Audio API - play"},
-  {"ping"    , AFB_SESSION_NONE,   ping      , "Audio API - ping"},
-  {NULL}
-};
-
-static const struct AFB_plugin pluginDesc = {
-    .type   = AFB_PLUGIN_VERSION_1,
-    .v1 = {
-        .info   = "Application Framework Binder - Audio plugin",
-        .prefix = "audio",
-        .verbs   = verbs
-    }
-};
-
-const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
-{
-	return &pluginDesc;
-}
diff --git a/plugins/audio/audio-api.h b/plugins/audio/audio-api.h
deleted file mode 100644
index f5c77c2e..00000000
--- a/plugins/audio/audio-api.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef AUDIO_API_H
-#define AUDIO_API_H
-
-/* global plugin handle, should store everything we may need */
-typedef struct {
-  int devCount;
-} pluginHandleT;
-
-/* private client context [will be destroyed when client leaves] */
-typedef struct {
-  void *audio_dev;          /* handle to implementation (ALSA, PulseAudio...) */
-  char *name;               /* name of the audio card */
-  int idx;                  /* audio card index within global array           */
-  unsigned int volume[8];   /* audio volume (8 channels) : 0-100              */
-  unsigned int channels;    /* audio channels : 1(mono)/2(stereo)...          */
-  unsigned char mute;       /* audio muted : 0(false)/1(true)                 */
-  unsigned char is_playing; /* audio is playing: 0(false)/1(true)             */
-} audioCtxHandleT;
-
-
-#endif /* AUDIO_API_H */
diff --git a/plugins/audio/audio-pulse.c b/plugins/audio/audio-pulse.c
deleted file mode 100644
index 34643603..00000000
--- a/plugins/audio/audio-pulse.c
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-
-#include "audio-api.h"
-#include "audio-pulse.h"
-
-static struct alsa_info **alsa_info = NULL;
-static struct dev_ctx_pulse **dev_ctx_p = NULL;
-static unsigned int client_count = 0;
-
-
-unsigned char _pulse_init (const char *name, audioCtxHandleT *ctx) {
-
-    pa_mainloop *pa_loop;
-    pa_mainloop_api *pa_api;
-    pa_context *pa_context;
-    pa_simple *pa;
-    pa_sample_spec *pa_spec;
-    struct timeval tv_start, tv_now;
-    int ret, error, i;
-
-    pa_loop = pa_mainloop_new ();
-    pa_api = pa_mainloop_get_api (pa_loop);
-    pa_context = pa_context_new (pa_api, "afb-audio-plugin");
-
-    /* allocate the global array if it hasn't been done */
-    if (!dev_ctx_p)
-        dev_ctx_p = (dev_ctx_pulse_T**) malloc (sizeof(dev_ctx_pulse_T*));
-
-    /* create a temporary device, to be held until sink gets discovered */
-    dev_ctx_pulse_T *dev_ctx_p_t = (dev_ctx_pulse_T*) malloc (sizeof(dev_ctx_pulse_T));
-    dev_ctx_p_t->sink_name = NULL;
-    dev_ctx_p_t->card_name = (char**) malloc (sizeof(char*));
-    dev_ctx_p_t->card_name[0] = strdup (name);
-    dev_ctx_p_t->pa_loop = pa_loop;
-    dev_ctx_p_t->pa_context = pa_context;
-
-    pa_context_set_state_callback (pa_context, _pulse_context_cb, (void*)dev_ctx_p_t);
-    pa_context_connect (pa_context, NULL, 0, NULL);
-
-    /* 1 second should be sufficient to retrieve sink info */
-    gettimeofday (&tv_start, NULL);
-    gettimeofday (&tv_now, NULL);
-    while (tv_now.tv_sec - tv_start.tv_sec <= 2) {
-        pa_mainloop_iterate (pa_loop, 0, &ret);
-
-        if (ret == -1) { /* generic error */
-            fprintf (stderr, "Stopping PulseAudio backend...\n");
-            return 0;
-        }
-
-        if ((ret > 0)&&(ret < 100)) { /* 0 and >100 are PulseAudio codes */
-            /* found a matching sink from callback */
-            fprintf (stderr, "Success : using sink n.%d\n", ret-1);
-            ctx->audio_dev = (void*)dev_ctx_p[ret-1];
-            break;
-        }
-        gettimeofday (&tv_now, NULL);
-    }
-    /* fail if we found no matching sink */
-    if (!ctx->audio_dev)
-      return 0;
-
-    /* make the client context aware of current card state */
-    ctx->mute = (unsigned char)dev_ctx_p[ret-1]->mute;
-    ctx->channels = (unsigned int)dev_ctx_p[ret-1]->volume.channels;
-    for (i = 0; i < ctx->channels; i++)
-        ctx->volume[i] = dev_ctx_p[ret-1]->volume.values[i];
-    ctx->idx = ret-1;
-
-    /* open matching sink for playback */
-    pa_spec = (pa_sample_spec*) malloc (sizeof(pa_sample_spec));
-    pa_spec->format = PA_SAMPLE_S16LE;
-    pa_spec->rate = 22050;
-    pa_spec->channels = (uint8_t)ctx->channels;
-
-    if (!(pa = pa_simple_new (NULL, "afb-audio-plugin", PA_STREAM_PLAYBACK, dev_ctx_p[ret-1]->sink_name,
-                              "afb-audio-output", pa_spec, NULL, NULL, &error))) {
-        fprintf (stderr, "Error opening PulseAudio sink %s : %s\n",
-                          dev_ctx_p[ret-1]->sink_name, pa_strerror(error));
-        return 0;
-    }
-    dev_ctx_p[ret-1]->pa = pa;
-    free (pa_spec);
-
-    client_count++;
-
-    fprintf (stderr, "Successfully initialized PulseAudio backend.\n");
-
-    return 1;
-}
-
-void _pulse_free (audioCtxHandleT *ctx) {
-
-    int num, i;
-
-    client_count--;
-    if (client_count > 0) return;
-
-    for (num = 0; num < (sizeof(dev_ctx_p)/sizeof(dev_ctx_pulse_T*)); num++) {
-
-         for (i = 0; num < (sizeof(dev_ctx_p[num]->card_name)/sizeof(char*)); i++) {
-             free (dev_ctx_p[num]->card_name[i]);
-             dev_ctx_p[num]->card_name[i] = NULL;
-         }
-         pa_context_disconnect (dev_ctx_p[num]->pa_context);
-         pa_context_unref (dev_ctx_p[num]->pa_context);
-         pa_mainloop_free (dev_ctx_p[num]->pa_loop);
-         pa_simple_free (dev_ctx_p[num]->pa);
-         free (dev_ctx_p[num]->sink_name);
-         dev_ctx_p[num]->pa_context = NULL;
-         dev_ctx_p[num]->pa_loop = NULL;
-         dev_ctx_p[num]->pa = NULL;
-         dev_ctx_p[num]->sink_name = NULL;
-         free (dev_ctx_p[num]);
-    }
-}
-
-void _pulse_play (audioCtxHandleT *ctx) {
-
-    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
-
-    if (!dev_ctx_p_c || dev_ctx_p_c->thr_should_run || access (AUDIO_BUFFER, F_OK) == -1)
-        return;
-
-    dev_ctx_p_c->thr_should_run = 1;
-    dev_ctx_p_c->thr_finished = 0;
-    pthread_create (&dev_ctx_p_c->thr, NULL, _pulse_play_thread_fn, (void*)dev_ctx_p_c);
-}
-
-void _pulse_stop (audioCtxHandleT *ctx) {
-
-    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
-
-    if (!dev_ctx_p_c || !dev_ctx_p_c->thr_should_run)
-        return;
-
-    dev_ctx_p_c->thr_should_run = 0;
-    while (!dev_ctx_p_c->thr_finished)
-        usleep(100000);
-    pthread_join (dev_ctx_p_c->thr, NULL);
-}
-
-unsigned int _pulse_get_volume (audioCtxHandleT *ctx, unsigned int channel) {
-
-    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
-
-    if (!dev_ctx_p_c)
-        return 0;
-
-    _pulse_refresh_sink (dev_ctx_p_c);
-
-    return (dev_ctx_p_c->volume.values[channel]*100)/PA_VOLUME_NORM;
-}
-
-void _pulse_set_volume (audioCtxHandleT *ctx, unsigned int channel, unsigned int vol) {
-
-    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
-    struct pa_cvolume volume;
-
-    if (!dev_ctx_p_c)
-        return;
-
-    volume = dev_ctx_p_c->volume;
-    volume.values[channel] = (vol*PA_VOLUME_NORM)/100;
-
-    pa_context_set_sink_volume_by_name (dev_ctx_p_c->pa_context, dev_ctx_p_c->sink_name,
-                                        &volume, NULL, NULL);
-    _pulse_refresh_sink (dev_ctx_p_c);
-}
-
-void _pulse_set_volume_all (audioCtxHandleT *ctx, unsigned int vol) {
-
-    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
-    struct pa_cvolume volume;
-
-    if (!dev_ctx_p_c)
-        return;
-
-    pa_cvolume_init (&volume);
-    pa_cvolume_set (&volume, dev_ctx_p_c->volume.channels, vol);
-
-    pa_context_set_sink_volume_by_name (dev_ctx_p_c->pa_context, dev_ctx_p_c->sink_name,
-                                        &volume, NULL, NULL);
-    _pulse_refresh_sink (dev_ctx_p_c);
-}
-
-unsigned char _pulse_get_mute (audioCtxHandleT *ctx) {
-
-    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
-
-    if (!dev_ctx_p_c)
-        return 0;
-
-    _pulse_refresh_sink (dev_ctx_p_c);
-
-    return (unsigned char)dev_ctx_p_c->mute;
-}
-
-void _pulse_set_mute (audioCtxHandleT *ctx, unsigned char mute) {
-
-    dev_ctx_pulse_T* dev_ctx_p_c = (dev_ctx_pulse_T*)ctx->audio_dev;
-
-    if (!dev_ctx_p_c)
-        return;
-
-    pa_context_set_sink_mute_by_name (dev_ctx_p_c->pa_context, dev_ctx_p_c->sink_name,
-                                      (int)mute, NULL, NULL);
-    _pulse_refresh_sink (dev_ctx_p_c);
-}
-
- /* ---- LOCAL HELPER FUNCTIONS ---- */
-
-void _pulse_refresh_sink (dev_ctx_pulse_T* dev_ctx_p_c) {
-
-    pa_mainloop_api *pa_api;
-
-    dev_ctx_p_c->pa_loop = pa_mainloop_new ();
-    pa_api = pa_mainloop_get_api (dev_ctx_p_c->pa_loop);
-    dev_ctx_p_c->pa_context = pa_context_new (pa_api, "afb-audio-plugin");
-
-    dev_ctx_p_c->refresh = 1;
-
-    switch (pa_context_get_state (dev_ctx_p_c->pa_context)) {
-      case PA_CONTEXT_READY:
-        pa_context_get_sink_info_by_name (dev_ctx_p_c->pa_context,
-                                          dev_ctx_p_c->sink_name,
-                                          _pulse_sink_info_cb, (void*)dev_ctx_p_c);
-        break;
-      default:
-        return;
-    }
-
-    while (dev_ctx_p_c->refresh)
-        pa_mainloop_iterate (dev_ctx_p_c->pa_loop, 0, NULL);
-}
-
-void _pulse_enumerate_cards () {
-
-    void **cards, **card;
-    char *name, *found, *alsa_name, *card_name;
-    int new_info, i, num = 0;
-
-    /* allocate the global alsa array */
-    alsa_info = (alsa_info_T**) malloc (sizeof(alsa_info_T*));
-    alsa_info[0] = (alsa_info_T*) malloc (sizeof(alsa_info_T));
-    alsa_info[0]->device = NULL;
-    alsa_info[0]->synonyms = NULL;
-
-    /* we use ALSA to enumerate cards */
-    snd_device_name_hint (-1, "pcm", &cards);
-    card = cards;
-
-    for (; *card != NULL; card++) {
-        name = snd_device_name_get_hint (*card, "NAME");
-        new_info = 1;
-
-        /* alsa name is before ':' (if ':' misses, then it has no card) */
-        found = strstr (name, ":");
-        if (!found) continue;
-        /* */
-        alsa_name = (char*) malloc (found-name+1);
-        strncpy (alsa_name, name, found-name);
-        alsa_name[found-name] = '\0';
-
-        /* card name is the invariant between "CARD=" and ',' */
-        found = strstr (name, "CARD=");
-        if (!found) continue;
-        /* */
-        found += 5;
-        card_name = strdup (found);
-        found = strstr (card_name, ",");
-        if (found) card_name[found-card_name] = '\0';
-
-        /* was the card name already listed in the global alsa array ? */
-        for (i = 0; i < (sizeof(alsa_info)/sizeof(alsa_info_T*)); i++) {
-
-            if (alsa_info[i]->device &&
-                !strcmp (alsa_info[i]->device, card_name)) {
-                /* it was ; add the alsa name as a new synonym */
-                asprintf (&alsa_info[i]->synonyms, "%s:%s", alsa_info[i]->synonyms, alsa_name);
-                new_info = 0;
-                break;
-            }            
-        }
-        /* it was not ; create it */
-        if (new_info) {
-            alsa_info = (alsa_info_T**) realloc (alsa_info, (num+1)*sizeof(alsa_info_T*));
-            alsa_info[num] = (alsa_info_T*) malloc (sizeof(alsa_info_T));
-            alsa_info[num]->device = strdup (card_name);
-            asprintf (&alsa_info[num]->synonyms, ":%s", alsa_name);
-            num++;
-        }
-        free (alsa_name);
-        free (card_name);
-    }
-}
-
-char** _pulse_find_cards (const char *name) {
-
-    char **cards = NULL;
-    char *needle, *found, *next;
-    int num, i = 0;
-
-    if (!alsa_info)
-      _pulse_enumerate_cards ();
-
-    asprintf (&needle, ":%s", name);
-
-    for (num = 0; num < (sizeof(alsa_info)/sizeof(alsa_info_T*)); num++) {
-
-        found = strstr (alsa_info[num]->synonyms, needle);
-        while (found) {
-            /* if next character is not ':' or '\0', we are wrong */
-            if ((found[strlen(name)+1] != ':') && (found[strlen(name)+1] != '\0')) {
-                found = strstr (found+1, needle);
-                continue;
-            }
-            /* found it ; now return all the "synonym" cards */
-            found = strstr (alsa_info[num]->synonyms, ":");
-            while (found) {
-                next = strstr (found+1, ":");
-                if (!next) break;
-                cards = (char**) realloc (cards, (i+1)*sizeof(char*));
-                cards[i] = (char*) malloc (next-found+1);
-                strncpy (cards[i], found+1, next-found);
-                cards[i][next-found-1] = '\0';
-                found = next; i++;
-            }
-        }
-    }
-    free (needle);
-
-    return cards;
-}
-
- /* ---- LOCAL CALLBACK FUNCTIONS ---- */
-
-void _pulse_context_cb (pa_context *context, void *data) {
-
-    pa_context_state_t state = pa_context_get_state (context);
-    dev_ctx_pulse_T *dev_ctx_p_t = (dev_ctx_pulse_T *)data;
-
-    if (state == PA_CONTEXT_FAILED) {
-        fprintf (stderr, "Could not connect to PulseAudio !\n");
-        pa_mainloop_quit (dev_ctx_p_t->pa_loop, -1);
-        pa_context_disconnect (dev_ctx_p_t->pa_context);
-        pa_context_unref (dev_ctx_p_t->pa_context);
-        pa_mainloop_free (dev_ctx_p_t->pa_loop);
-    }
-
-    if (state == PA_CONTEXT_READY)
-        pa_context_get_sink_info_list (context, _pulse_sink_list_cb, (void*)dev_ctx_p_t);
-}
-
-void _pulse_sink_list_cb (pa_context *context, const pa_sink_info *info,
-				 int eol, void *data) {
-
-    dev_ctx_pulse_T *dev_ctx_p_t = (dev_ctx_pulse_T *)data;
-    const char *device_string;
-    char *device, *found;
-    char **cards;
-    int num, i;
-
-    if (eol != 0)
-        return;
-
-    device_string = pa_proplist_gets (info->proplist, "device.string");
-    /* ignore sinks with no cards */
-    if (!device_string)
-        return;
-
-    /* was a sink with similar name already found ? */
-    for (num = 0; num < (sizeof(dev_ctx_p)/sizeof(dev_ctx_pulse_T*)); num++) {
-        if (dev_ctx_p[num]->sink_name &&
-           !strcmp (dev_ctx_p[num]->sink_name, info->name)) {
-
-            /* yet it was, did it have the required card ? */
-            cards = dev_ctx_p[num]->card_name;
-            for (i = 0; i < (sizeof(cards)/sizeof(char*)); i++) {
-                if (!strcmp (cards[i], dev_ctx_p_t->card_name[0])) {
-                    /* it did : stop there and succeed */
-                    fprintf (stderr, "Found matching sink : %s\n", info->name);
-                    /* we return num+1 because '0' is already used */
-                    pa_mainloop_quit (dev_ctx_p_t->pa_loop, num+1);
-                    pa_context_disconnect (dev_ctx_p_t->pa_context);
-                    pa_context_unref (dev_ctx_p_t->pa_context);
-                    pa_mainloop_free (dev_ctx_p_t->pa_loop);
-                }
-            }
-            /* it did not, ignore and return */
-            return;
-        }
-    }
-    num++;
-
-    /* remove ending ":0",":1"... in device name */
-    device = strdup (device_string);
-    found = strstr (device, ":");
-    if (found) device[found-device] = '\0';
-
-    /* new sink, find all the cards it manages, fail if none */
-    cards = _pulse_find_cards (device);
-    free (device);
-    if (!cards)
-        return;
-
-    /* everything is well, register it in global array */
-    dev_ctx_p_t->sink_name = strdup (info->name);
-    dev_ctx_p_t->card_name = cards;
-    dev_ctx_p_t->mute = info->mute;
-    dev_ctx_p_t->volume = info->volume;
-    dev_ctx_p_t->thr_should_run = 0;
-    dev_ctx_p_t->thr_finished = 0;
-    dev_ctx_p[num] = dev_ctx_p_t;
-
-    /* does this new sink have the card we are looking for ? */ /* TODO : factorize this */
-    for (i = 0; i < (sizeof(cards)/sizeof(char*)); i++) {
-        if (!strcmp (cards[i], dev_ctx_p_t->card_name[0])) {
-             /* it did : stop there and succeed */
-             fprintf (stderr, "Found matching sink : %s\n", info->name);
-             /* we return num+1 because '0' is already used */
-             pa_mainloop_quit (dev_ctx_p_t->pa_loop, num+1);
-             pa_context_disconnect (dev_ctx_p_t->pa_context);
-             pa_context_unref (dev_ctx_p_t->pa_context);
-             pa_mainloop_free (dev_ctx_p_t->pa_loop);
-        }
-    }
-}
-
-void _pulse_sink_info_cb (pa_context *context, const pa_sink_info *info,
-				 int eol, void *data) {
-
-    dev_ctx_pulse_T *dev_ctx_p_c = (dev_ctx_pulse_T *)data;
-
-    if (eol != 0)
-        return;
-
-    dev_ctx_p_c->refresh = 0;
-    dev_ctx_p_c->mute = info->mute;
-    dev_ctx_p_c->volume = info->volume;
-}
-
- /* ---- LOCAL THREADED FUNCTIONS ---- */
-
-void* _pulse_play_thread_fn (void *ctx) {
-
-    dev_ctx_pulse_T *dev_ctx_p_c = (dev_ctx_pulse_T *)ctx;
-    FILE *file = NULL;
-    char *buf = NULL;
-    long size;
-    int error;
-
-    file = fopen (AUDIO_BUFFER, "rb");
-
-    while (dev_ctx_p_c->thr_should_run && file && (access (AUDIO_BUFFER, F_OK) != -1) ) {
-        fseek (file, 0, SEEK_END);
-        size = ftell (file);
-        buf = (char*) realloc (buf, size * sizeof(char));
-
-        fseek (file, 0, SEEK_SET);
-        fread (buf, 1, size, file);
-        fflush (file);
-
-        if (pa_simple_write (dev_ctx_p_c->pa, buf, size*2, &error) < 0)
-            fprintf (stderr, "Error writing to PulseAudio : %s\n", pa_strerror (error));
-        /* pa_simple_drain (dev_ctx_p_c->pa); */
-    }
-    if (buf) free(buf);
-    if (file) fclose(file);
-
-    dev_ctx_p_c->thr_finished = 1;
-    return 0;
-}
diff --git a/plugins/audio/audio-pulse.h b/plugins/audio/audio-pulse.h
deleted file mode 100644
index ad8ff490..00000000
--- a/plugins/audio/audio-pulse.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef AUDIO_PULSE_H
-#define AUDIO_PULSE_H
-
-#include <sys/time.h>
-#include <pulse/pulseaudio.h>
-#include <pulse/simple.h>
-#include <pulse/error.h>
-
-#include "audio-alsa.h"
-
-typedef struct dev_ctx_pulse dev_ctx_pulse_T;
-typedef struct alsa_info alsa_info_T;
-
-struct dev_ctx_pulse {
-  char *sink_name;
-  char **card_name;
-  pa_mainloop *pa_loop;
-  pa_context *pa_context;
-  pa_simple *pa;
-  pa_cvolume volume;
-  int mute;
-  unsigned char refresh;
-  pthread_t thr;
-  unsigned char thr_should_run;
-  unsigned char thr_finished;
-};
-
-struct alsa_info {
-  char *device;
-  char *synonyms;
-};
-
-unsigned char _pulse_init (const char *, audioCtxHandleT *);
-void _pulse_free (audioCtxHandleT *);
-void _pulse_play (audioCtxHandleT *);
-void _pulse_stop (audioCtxHandleT *);
-unsigned int _pulse_get_volume (audioCtxHandleT *, unsigned int);
-void _pulse_set_volume (audioCtxHandleT *, unsigned int, unsigned int);
-void _pulse_set_volume_all (audioCtxHandleT *, unsigned int);
-unsigned char _pulse_get_mute (audioCtxHandleT *);
-void _pulse_set_mute (audioCtxHandleT *, unsigned char);
-
-void  _pulse_context_cb (pa_context *, void *);
-void  _pulse_sink_list_cb (pa_context *, const pa_sink_info *, int, void *);
-void  _pulse_sink_info_cb (pa_context *, const pa_sink_info *, int, void *);
-void* _pulse_play_thread_fn (void *);
-void  _pulse_refresh_sink (dev_ctx_pulse_T *);
-
-#endif /* AUDIO_PULSE_H */
diff --git a/plugins/audio/export.map b/plugins/audio/export.map
deleted file mode 100644
index e2da85ca..00000000
--- a/plugins/audio/export.map
+++ /dev/null
@@ -1 +0,0 @@
-{ global: pluginAfbV1Register; local: *; };
diff --git a/plugins/intrinsics/CMakeLists.txt b/plugins/intrinsics/CMakeLists.txt
deleted file mode 100644
index b9bd638a..00000000
--- a/plugins/intrinsics/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-INCLUDE_DIRECTORIES(${include_dirs})
-
-##################################################
-# DBus Binding
-##################################################
-ADD_LIBRARY(afb-dbus-binding MODULE afb-dbus-binding.c)
-SET_TARGET_PROPERTIES(afb-dbus-binding PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
-)
-TARGET_LINK_LIBRARIES(afb-dbus-binding ${link_libraries})
-INSTALL(TARGETS afb-dbus-binding
-        LIBRARY DESTINATION ${plugin_install_dir})
-
diff --git a/plugins/intrinsics/afb-dbus-binding.c b/plugins/intrinsics/afb-dbus-binding.c
deleted file mode 100644
index 37988559..00000000
--- a/plugins/intrinsics/afb-dbus-binding.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author José Bollo <jose.bollo@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <json-c/json.h>
-
-#include <systemd/sd-bus.h>
-#include <systemd/sd-bus-protocol.h>
-
-#include <afb/afb-plugin.h>
-#include <afb/afb-plugin.h>
-#include <afb/afb-plugin.h>
-
-/*
- * the interface to afb-daemon
- */
-const struct AFB_interface *afbitf;
-
-/*
- * union of possible dbus values
- */
-union any {
-	uint8_t u8;
-	int16_t i16;
-	uint16_t u16;
-	int32_t i32;
-	uint32_t u32;
-	int64_t i64;
-	uint64_t u64;
-	double dbl;
-	const char *cstr;
-	char *str;
-};
-
-static int unpacklist(struct sd_bus_message *msg, struct json_object **result);
-static int packlist(struct sd_bus_message *msg, const char *signature, struct json_object *list);
-
-/*
- * Get the string of 'key' from 'obj'
- * Returns NULL if 'key' isn't in 'obj'
- */ 
-static const char *strval(struct json_object *obj, const char *key)
-{
-	struct json_object *keyval;
-	return json_object_object_get_ex(obj, key, &keyval) ? json_object_get_string(keyval) : NULL;
-}
-
-/*
- * Signature of a json object
- */
-static const char *signature_for_json(struct json_object *obj)
-{
-	switch (json_object_get_type(obj)) {
-	default:
-	case json_type_null:
-		return NULL;
-	case json_type_boolean:
-		return "b";
-	case json_type_double:
-		return "d";
-	case json_type_int:
-		return "i";
-	case json_type_object:
-		return "a{sv}";
-	case json_type_array:
-		return "av";
-	case json_type_string:
-		return "s";
-	}
-}
-
-/*
- * Length of a single complete type
- */
-static int lentype(const char *signature, int allows_dict, int allows_not_basic)
-{
-	int rc, len;
-	switch(signature[0]) {
-
-	case SD_BUS_TYPE_ARRAY:
-		if (!allows_not_basic)
-			break;
-		rc = lentype(signature + 1, 1, 1);
-		if (rc < 0)
-			break;
-		return 1 + rc;
-
-	case SD_BUS_TYPE_STRUCT_BEGIN:
-		if (!allows_not_basic)
-			break;
-		len = 1;
-		rc = lentype(signature + len, 0, 1);
-		while (rc > 0 && signature[len] != SD_BUS_TYPE_STRUCT_END) {
-			len += rc;
-			rc = lentype(signature + len, 0, 1);
-		}
-		if (rc < 0)
-			break;
-		return 1 + len;		
-
-	case SD_BUS_TYPE_DICT_ENTRY_BEGIN:
-		if (!allows_not_basic || !allows_dict)
-			break;
-		rc = lentype(signature + 1, 0, 0);
-		if (rc < 0)
-			break;
-		len = 1 + rc;
-		rc = lentype(signature + len, 0, 1);
-		if (rc < 0 || signature[len + rc] != SD_BUS_TYPE_DICT_ENTRY_END)
-			break;
-		return len + rc + 1;
-
-	case '\x0':
-	case SD_BUS_TYPE_STRUCT:
-	case SD_BUS_TYPE_STRUCT_END:
-	case SD_BUS_TYPE_DICT_ENTRY:
-	case SD_BUS_TYPE_DICT_ENTRY_END:
-		break;
-
-	default:
-		return 1;
-	}
-	return -1;
-}
-
-
-/*
- * Unpack a D-Bus message to a json object
- */
-static int unpacksingle(struct sd_bus_message *msg, struct json_object **result)
-{
-	char c;
-	int rc;
-	union any any;
-	const char *content;
-	struct json_object *item;
-
-	*result = NULL;
-	rc = sd_bus_message_peek_type(msg, &c, &content);
-	if (rc <= 0)
-		return rc;
-
-	switch (c) {
-	case SD_BUS_TYPE_BYTE:
-	case SD_BUS_TYPE_BOOLEAN:
-	case SD_BUS_TYPE_INT16:
-	case SD_BUS_TYPE_UINT16:
-	case SD_BUS_TYPE_INT32:
-	case SD_BUS_TYPE_UINT32:
-	case SD_BUS_TYPE_INT64:
-	case SD_BUS_TYPE_UINT64:
-	case SD_BUS_TYPE_DOUBLE:
-	case SD_BUS_TYPE_STRING:
-	case SD_BUS_TYPE_OBJECT_PATH:
-	case SD_BUS_TYPE_SIGNATURE:
-		rc = sd_bus_message_read_basic(msg, c, &any);
-		if (rc < 0)
-			goto error;
-		switch (c) {
-		case SD_BUS_TYPE_BOOLEAN:
-			*result = json_object_new_boolean(any.i32);
-			break;
-		case SD_BUS_TYPE_BYTE:
-			*result = json_object_new_int(any.u8);
-			break;
-		case SD_BUS_TYPE_INT16:
-			*result = json_object_new_int(any.i16);
-			break;
-		case SD_BUS_TYPE_UINT16:
-			*result = json_object_new_int(any.u16);
-			break;
-		case SD_BUS_TYPE_INT32:
-			*result = json_object_new_int(any.i32);
-			break;
-		case SD_BUS_TYPE_UINT32:
-			*result = json_object_new_int64(any.u32);
-			break;
-		case SD_BUS_TYPE_INT64:
-			*result = json_object_new_int64(any.i64);
-			break;
-		case SD_BUS_TYPE_UINT64:
-			*result = json_object_new_int64((int64_t)any.u64);
-			break;
-		case SD_BUS_TYPE_DOUBLE:
-			*result = json_object_new_string(any.cstr);
-			break;
-		case SD_BUS_TYPE_STRING:
-		case SD_BUS_TYPE_OBJECT_PATH:
-		case SD_BUS_TYPE_SIGNATURE:
-			*result = json_object_new_string(any.cstr);
-			break;
-		}
-		return *result == NULL ? -1 : 1;
-
-	case SD_BUS_TYPE_ARRAY:
-	case SD_BUS_TYPE_VARIANT:
-	case SD_BUS_TYPE_STRUCT:
-	case SD_BUS_TYPE_DICT_ENTRY:
-		rc = sd_bus_message_enter_container(msg, c, content);
-		if (rc < 0)
-			goto error;
-		if (c == SD_BUS_TYPE_ARRAY && content[0] == SD_BUS_TYPE_DICT_ENTRY_BEGIN && content[1] == SD_BUS_TYPE_STRING) {
-			*result = json_object_new_object();
-			if (*result == NULL)
-				return -1;
-			for(;;) {
-				rc = sd_bus_message_enter_container(msg, 0, NULL);
-				if (rc < 0)
-					goto error;
-				if (rc == 0)
-					break;
-				rc = sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, &any);
-				if (rc < 0)
-					goto error;
-				rc = unpacksingle(msg, &item);
-				if (rc < 0)
-					goto error;
-				json_object_object_add(*result, any.cstr, item);
-				rc = sd_bus_message_exit_container(msg);
-				if (rc < 0)
-					goto error;
-			}
-		} else {
-			rc = unpacklist(msg, result);
-			if (rc < 0)
-				goto error;
-		}
-		rc = sd_bus_message_exit_container(msg);
-		if (rc < 0)
-			goto error;
-		return 1;
-	default:
-		goto error;
-	}
-error:
-	json_object_put(*result);
-	return -1;
-}
-
-/*
- * Unpack a D-Bus message to a json object
- */
-static int unpacklist(struct sd_bus_message *msg, struct json_object **result)
-{
-	int rc;
-	struct json_object *item;
-
-	/* allocates the result */
-	*result = json_object_new_array();
-	if (*result == NULL)
-		goto error;
-
-	/* read the values */
-	for (;;) {
-		rc = unpacksingle(msg, &item);
-		if (rc < 0)
-			goto error;
-		if (rc == 0)
-			return 0;
-		json_object_array_add(*result, item);
-	}
-error:
-	json_object_put(*result);
-	*result = NULL;
-	return -1;
-}
-
-static int packsingle(struct sd_bus_message *msg, const char *signature, struct json_object *item)
-{
-	int index, count, rc, len;
-	union any any;
-	char *subsig;
-	struct json_object_iterator it, end;
-
-	len = lentype(signature, 0, 1);
-	if (len < 0)
-		goto error;
-
-	switch (*signature) {
-	case SD_BUS_TYPE_BOOLEAN:
-		any.i32 = json_object_get_boolean(item);
-		break;
-
-	case SD_BUS_TYPE_BYTE:
-		any.i32 = json_object_get_int(item);
-		if (any.i32 != (int32_t)(uint8_t)any.i32)
-			goto error;
-		any.u8 = (uint8_t)any.i32;
-		break;
-
-	case SD_BUS_TYPE_INT16:
-		any.i32 = json_object_get_int(item);
-		if (any.i32 != (int32_t)(int16_t)any.i32)
-			goto error;
-		any.i16 = (int16_t)any.i32;
-		break;
-
-	case SD_BUS_TYPE_UINT16:
-		any.i32 = json_object_get_int(item);
-		if (any.i32 != (int32_t)(uint16_t)any.i32)
-			goto error;
-		any.u16 = (uint16_t)any.i32;
-		break;
-
-	case SD_BUS_TYPE_INT32:
-		any.i64 = json_object_get_int64(item);
-		if (any.i64 != (int64_t)(int32_t)any.i64)
-			goto error;
-		any.i32 = (int32_t)any.i64;
-		break;
-
-	case SD_BUS_TYPE_UINT32:
-		any.i64 = json_object_get_int64(item);
-		if (any.i64 != (int64_t)(uint32_t)any.i64)
-			goto error;
-		any.u32 = (uint32_t)any.i64;
-		break;
-
-	case SD_BUS_TYPE_INT64:
-		any.i64 = json_object_get_int64(item);
-		break;
-
-	case SD_BUS_TYPE_UINT64:
-		any.u64 = (uint64_t)json_object_get_int64(item);
-		break;
-
-	case SD_BUS_TYPE_DOUBLE:
-		any.dbl = json_object_get_double(item);
-		break;
-
-	case SD_BUS_TYPE_STRING:
-	case SD_BUS_TYPE_OBJECT_PATH:
-	case SD_BUS_TYPE_SIGNATURE:
-		any.cstr = json_object_get_string(item);
-		break;
-
-	case SD_BUS_TYPE_VARIANT:
-		signature = signature_for_json(item);
-		if (signature == NULL)
-			goto error;
-		rc = sd_bus_message_open_container(msg, SD_BUS_TYPE_VARIANT, signature);
-		if (rc < 0)
-			goto error;
-		rc = packsingle(msg, signature, item);
-		if (rc < 0)
-			goto error;
-		rc = sd_bus_message_close_container(msg);
-		if (rc < 0)
-			goto error;
-		return len;
-
-	case SD_BUS_TYPE_ARRAY:
-		subsig = strndupa(signature + 1, len - 1);
-		rc = sd_bus_message_open_container(msg, SD_BUS_TYPE_ARRAY, subsig);
-		if (rc < 0)
-			goto error;
-		if (json_object_is_type(item, json_type_array)) {
-			/* Is an array! */
-			count = json_object_array_length(item);
-			index = 0;
-			while(index < count) {
-				rc = packsingle(msg, subsig, json_object_array_get_idx(item, index++));
-				if (rc < 0)
-					goto error;
-			}
-		} else {
-			/* Not an array! Check if it matches an string dictionnary */
-			if (!json_object_is_type(item, json_type_object))
-				goto error;
-			if (*subsig++ != SD_BUS_TYPE_DICT_ENTRY_BEGIN)
-				goto error;
-			if (*subsig != SD_BUS_TYPE_STRING)
-				goto error;
-			/* iterate the object values */
-			subsig[strlen(subsig) - 1] = 0;
-			it = json_object_iter_begin(item);
-			end = json_object_iter_end(item);
-			while (!json_object_iter_equal(&it, &end)) {
-				rc = sd_bus_message_open_container(msg, SD_BUS_TYPE_DICT_ENTRY, subsig);
-				if (rc < 0)
-					goto error;
-				any.cstr = json_object_iter_peek_name(&it);
-				rc = sd_bus_message_append_basic(msg, *subsig, &any);
-				if (rc < 0)
-					goto error;
-				rc = packsingle(msg, subsig + 1, json_object_iter_peek_value(&it));
-				if (rc < 0)
-					goto error;
-				rc = sd_bus_message_close_container(msg);
-				if (rc < 0)
-					goto error;
-				json_object_iter_next(&it);
-			}
-		}
-		rc = sd_bus_message_close_container(msg);
-		if (rc < 0)
-			goto error;
-		return len;
-
-	case SD_BUS_TYPE_STRUCT_BEGIN:
-	case SD_BUS_TYPE_DICT_ENTRY_BEGIN:
-		subsig = strndupa(signature + 1, len - 2);
-		rc = sd_bus_message_open_container(msg,
-			((*signature) == SD_BUS_TYPE_STRUCT_BEGIN) ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY,
-			subsig);
-		if (rc < 0)
-			goto error;
-		rc = packlist(msg, subsig, item);
-		if (rc < 0)
-			goto error;
-		rc = sd_bus_message_close_container(msg);
-		if (rc < 0)
-			goto error;
-		return len;
-
-	default:
-		goto error;
-	}
-
-	rc = sd_bus_message_append_basic(msg, *signature, &any);
-	if (rc < 0)
-		goto error;
-	return len;
-
-error:
-	return -1;
-}
-
-static int packlist(struct sd_bus_message *msg, const char *signature, struct json_object *list)
-{
-	int rc, count, index, scan;
-	struct json_object *item;
-
-	scan = 0;
-	if (list == NULL) {
-		/* empty case */
-		if (*signature)
-			goto error;
-		return scan;
-	}
-
-	if (!json_object_is_type(list, json_type_array)) {
-		/* down grade gracefully to single */
-		rc = packsingle(msg, signature, list);
-		if (rc < 0)
-			goto error;
-		scan = rc;
-		if (signature[scan] != 0)
-			goto error;
-		return scan;
-	}
-
-	/* iterate over elements */
-	count = json_object_array_length(list);
-	index = 0;
-	for (;;) {
-		/* check state */
-		if (index == count && signature[scan] == 0)
-			return scan;
-		if (index == count || signature[scan] == 0)
-			goto error;
-
-		/* get the item */
-		item = json_object_array_get_idx(list, index);
-		if (item == NULL)
-			goto error;
-
-		/* pack the item */
-		rc = packsingle(msg, signature + scan, item);
-		if (rc < 0)
-			goto error;
-
-		/* advance */
-		scan += rc;
-		index++;
-	}
-
-error:
-	return -(scan + 1);
-}
-
-/*
- * handle the reply
- */
-static int on_rawcall_reply(sd_bus_message *msg, struct afb_req *req, sd_bus_error *ret_error)
-{
-	struct json_object *obj = NULL;
-	int rc;
-	const sd_bus_error *err;
-
-	err = sd_bus_message_get_error(msg);
-	if (err != NULL)
-		afb_req_fail_f(*req, "failed", "DBus-error-name: %s, DBus-error-message: %s", err->name, err->message);
-	else {
-		rc = unpacklist(msg, &obj);
-		if (rc < 0)
-			afb_req_fail(*req, "failed", "can't unpack");
-		else
-			afb_req_success(*req, obj, NULL);
-	}
-	json_object_put(obj);
-	afb_req_unref(*req);
-	free(req);
-	return 1;
-}
-
-/*
- * Make a raw call to DBUS method
- * The query should have:
- *   {
- *     "bus": "optional: 'system' or 'user' (default)"
- *     "destination": "destination handling the object",
- *     "path": "object path",
- *     "interface": "interface of the call",
- *     "member": "member of the interface of the call",
- *     "signature": "signature of the arguments",
- *     "arguments": "ARRAY of arguments"
- *   }
- */
-static void rawcall(struct afb_req req)
-{
-	struct json_object *obj;
-	struct json_object *args;
-
-	const char *busname;
-	const char *destination;
-	const char *path;
-	const char *interface;
-	const char *member;
-	const char *signature;
-
-	struct sd_bus_message *msg = NULL;
-	struct sd_bus *bus;
-	int rc;
-
-	/* get the query */
-	obj = afb_req_json(req);
-	if (obj == NULL)
-		goto internal_error;
-
-	/* get parameters */
-	destination = strval(obj, "destination");
-	path = strval(obj, "path");
-	interface = strval(obj, "interface");
-	member = strval(obj, "member");
-	if (path == NULL || member == NULL)
-		goto bad_request;
-
-	/* get arguments */
-	signature = strval(obj, "signature") ? : "";
-	args = NULL;
-	json_object_object_get_ex(obj, "arguments", &args);
-
-	/* get bus */
-	busname = strval(obj, "bus");
-	if (busname != NULL && !strcmp(busname, "system"))
-		bus = afb_daemon_get_system_bus(afbitf->daemon);
-	else
-		bus = afb_daemon_get_user_bus(afbitf->daemon);
-
-	/* creates the message */
-	rc = sd_bus_message_new_method_call(bus, &msg, destination, path, interface, member);
-	if (rc != 0)
-		goto internal_error;
-	rc = packlist(msg, signature, args);
-	if (rc < 0)
-		goto bad_request;
-
-	/*  */
-	rc = sd_bus_call_async(bus, NULL, msg, (void*)on_rawcall_reply, afb_req_store(req), -1);
-	if (rc < 0)
-		goto internal_error;
-	goto cleanup;
-
-internal_error:
-	afb_req_fail(req, "failed", "internal error");
-	goto cleanup;
-
-bad_request:
-	afb_req_fail(req, "failed", "bad request");
-
-cleanup:
-	sd_bus_message_unref(msg);
-}
-
-/*
- * array of the verbs exported to afb-daemon
- */
-static const struct AFB_verb_desc_v1 plugin_verbs[] = {
-  /* VERB'S NAME       SESSION MANAGEMENT          FUNCTION TO CALL     SHORT DESCRIPTION */
-  { .name= "rawcall",  .session= AFB_SESSION_NONE, .callback= rawcall,  .info= "raw call to dbus method" },
-  { .name= NULL } /* marker for end of the array */
-};
-
-/*
- * description of the plugin for afb-daemon
- */
-static const struct AFB_plugin plugin_description =
-{
-  /* description conforms to VERSION 1 */
-  .type= AFB_PLUGIN_VERSION_1,
-  .v1= {			/* fills the v1 field of the union when AFB_PLUGIN_VERSION_1 */
-    .prefix= "dbus",		/* the API name (or plugin name or prefix) */
-    .info= "raw dbus binding",	/* short description of of the plugin */
-    .verbs = plugin_verbs	/* the array describing the verbs of the API */
-  }
-};
-
-/*
- * activation function for registering the plugin called by afb-daemon
- */
-const struct AFB_plugin *pluginAfbV1Register(const struct AFB_interface *itf)
-{
-	afbitf = itf;			/* records the interface for accessing afb-daemon */
-	return &plugin_description;	/* returns the description of the plugin */
-}
-
diff --git a/plugins/intrinsics/export.map b/plugins/intrinsics/export.map
deleted file mode 100644
index e2da85ca..00000000
--- a/plugins/intrinsics/export.map
+++ /dev/null
@@ -1 +0,0 @@
-{ global: pluginAfbV1Register; local: *; };
diff --git a/plugins/media/CMakeLists.txt b/plugins/media/CMakeLists.txt
deleted file mode 100644
index 5febc02d..00000000
--- a/plugins/media/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-INCLUDE(FindPkgConfig)
-PKG_CHECK_MODULES(gupnp gupnp-1.0 gupnp-av-1.0 gssdp-1.0 gobject-2.0 gio-2.0)
-
-IF(gupnp_FOUND)
-
-  MESSAGE(STATUS "gupnp found ; will compile Media plugin... (PLUGIN)")
-
-  INCLUDE_DIRECTORIES( ${include_dirs} ${gupnp_INCLUDE_DIRS})
-  ADD_LIBRARY(media-api MODULE media-api.c media-rygel.c)
-  SET_TARGET_PROPERTIES(media-api PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
-  )
-  TARGET_LINK_LIBRARIES(media-api ${link_libraries} ${gupnp_LIBRARIES})
-  INSTALL(TARGETS media-api
-          LIBRARY DESTINATION ${plugin_install_dir})
-
-ENDIF(gupnp_FOUND)
diff --git a/plugins/media/export.map b/plugins/media/export.map
deleted file mode 100644
index e2da85ca..00000000
--- a/plugins/media/export.map
+++ /dev/null
@@ -1 +0,0 @@
-{ global: pluginAfbV1Register; local: *; };
diff --git a/plugins/media/media-api.c b/plugins/media/media-api.c
deleted file mode 100644
index 578d0066..00000000
--- a/plugins/media/media-api.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-
-#include <string.h>
-
-#include <json-c/json.h>
-
-#include "media-api.h"
-#include "media-rygel.h"
-
-#include <afb/afb-plugin.h>
-#include <afb/afb-req-itf.h>
-
-json_object* _rygel_list (mediaCtxHandleT *);
-
-/* ------ LOCAL HELPER FUNCTIONS --------- */
-
-/* private client context creation ; default values */
-static mediaCtxHandleT* initMediaCtx () {
-
-    mediaCtxHandleT *ctx;
-
-    ctx = malloc (sizeof(mediaCtxHandleT));
-    ctx->media_server = NULL;
-    ctx->index = 0;
-
-    return ctx;
-}
-
-/* ------ PUBLIC PLUGIN FUNCTIONS --------- */
-
-static void init (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    mediaCtxHandleT *ctx = afb_req_context_get(request);
-    json_object *jresp;
-
-    /* create a private client context */
-    if (!ctx) {
-        ctx = initMediaCtx();
-        afb_req_context_set (request, ctx, free);
-    }
-
-    /* initialize server connection */
-    if (!ctx->media_server)
-      _rygel_init (ctx);
-
-    jresp = json_object_new_object ();
-    json_object_object_add (jresp, "init", json_object_new_string ("success"));
-    afb_req_success (request, jresp, "Media - Initialized");
-}
-
-static void list (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    mediaCtxHandleT *ctx = afb_req_context_get(request);
-    json_object *jresp;
-
-    /* check that context is initialized */
-    if (ctx == NULL) {
-      afb_req_fail (request, "failed", "uninitialized");
-      return;
-    }
-
-    jresp = _rygel_list (ctx);
-
-    if (!jresp) {
-      afb_req_fail (request, "failed", "no content found in media server");
-      return;
-    }
-
-    afb_req_success (request, jresp, "Media - Listed");
-}
-
-static void selecting (struct afb_req request) {   /* AFB_SESSION_CHECK */
-
-    mediaCtxHandleT *ctx = afb_req_context_get(request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp;
-    unsigned int index;
-    char index_str[5];
-
-    /* check that context is initialized */
-    if (ctx == NULL) {
-      afb_req_fail (request, "failed", "uninitialized");
-      return;
-    }
-
-    /* no "?value=" parameter : return current index */
-    if (!value) {
-        snprintf (index_str, sizeof(index_str), "%d", ctx->index);
-        jresp = json_object_new_object();
-        json_object_object_add (jresp, "index", json_object_new_string (index_str));
-    }
-
-    /* "?value=" parameter is negative */
-    else if (atoi(value) < 0) {
-        afb_req_fail (request, "failed", "chosen index cannot be negative");
-        return;
-    }
-
-    /* "?value=" parameter is positive */
-    else if (atoi(value) >= 0) {
-        index = (unsigned int) atoi(value);
-
-        if (!_rygel_select (ctx, index)) {
-          afb_req_fail (request, "failed", "chosen index superior to current media count");
-          return;
-        }
-
-        ctx->index = index;
-        jresp = json_object_new_object();
-        json_object_object_add (jresp, "index", json_object_new_string (value));
-    }
-    else
-        jresp = NULL;
-
-    afb_req_success (request, jresp, "Media - Listed");
-}
-
-static void play (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    mediaCtxHandleT *ctx = afb_req_context_get(request);
-    json_object *jresp;
-
-    /* check that context is initialized */
-    if (ctx == NULL) {
-      afb_req_fail (request, "failed", "uninitialized");
-      return;
-    }
-
-    if (!_rygel_do (ctx, PLAY, NULL)) {
-      afb_req_fail (request, "failed", "could not play chosen media");
-      return;
-    }
-
-    jresp = json_object_new_object ();
-    json_object_object_add (jresp, "play", json_object_new_string ("success"));
-    afb_req_success (request, jresp, "Media - Listed");
-}
-
-static void stop (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    mediaCtxHandleT *ctx = afb_req_context_get(request);
-    json_object *jresp;
-
-    /* check that context is initialized */
-    if (ctx == NULL) {
-      afb_req_fail (request, "failed", "uninitialized");
-      return;
-    }
-
-    if (!_rygel_do (ctx, STOP, NULL)) {
-      afb_req_fail (request, "failed", "could not stop chosen media");
-      return;
-    }
-
-    jresp = json_object_new_object ();
-    json_object_object_add (jresp, "stop", json_object_new_string ("success"));
-    afb_req_success (request, jresp, "Media - Stopped");
-}
-
-static void pausing (struct afb_req request) {     /* AFB_SESSION_CHECK */
-
-    mediaCtxHandleT *ctx = afb_req_context_get(request);
-    json_object *jresp;
-
-    /* check that context is initialized */
-    if (ctx == NULL) {
-      afb_req_fail (request, "failed", "uninitialized");
-      return;
-    }
-
-    if (!_rygel_do (ctx, PAUSE, NULL)) {
-      afb_req_fail (request, "failed", "could not pause chosen media");
-      return;
-    }
-
-    jresp = json_object_new_object();
-    json_object_object_add (jresp, "pause", json_object_new_string ("success"));
-    afb_req_success (request, jresp, "Media - Paused");
-}
-
-static void seek (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    mediaCtxHandleT *ctx = afb_req_context_get(request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp;
-
-    /* check that context is initialized */
-    if (ctx == NULL) {
-      afb_req_fail (request, "failed", "uninitialized");
-      return;
-    }
-
-    /* no "?value=" parameter : return error */
-    if (!value) {
-      afb_req_fail (request, "failed", "you must provide a time");
-      return;
-    }
-
-    if (!_rygel_do (ctx, SEEK, (char *)value)) {
-      afb_req_fail (request, "failed", "could not seek chosen media");
-      return;
-    }
-
-    jresp = json_object_new_object();
-    json_object_object_add (jresp, "seek", json_object_new_string ("success"));
-    afb_req_success (request, jresp, "Media - Sought");
-}
-
-static char *renamed_filename(struct afb_arg argfile)
-{
-    char *result;
-    const char *e = strrchr(argfile.path, '/');
-    if (e == NULL)
-        result = strdup(argfile.value);
-    else {
-        result = malloc((++e - argfile.path) + strlen(argfile.value) + 1);
-        if (result != NULL)
-            strcpy(stpncpy(result, argfile.path, e - argfile.path), argfile.value);
-    }
-    return result;
-}
-
-static void on_uploaded(struct afb_req *prequest, int status)
-{
-    struct afb_req request = afb_req_unstore(prequest);
-    struct afb_arg argfile = afb_req_get(request, "file-upload");
-    char *file = renamed_filename(argfile);
-    if (file != NULL)
-        unlink(file);
-    free(file);
-    if (status)
-        afb_req_fail (request, "failed", "expected file not received");
-    else
-        afb_req_success_f (request, NULL, "uploaded file %s", argfile.value);
-   afb_req_unref(request);
-}
-
-static void upload (struct afb_req request) { /* AFB_SESSION_CHECK */
-
-    mediaCtxHandleT *ctx = afb_req_context_get(request);
-    struct afb_req *prequest;
-    struct afb_arg argfile;
-    char *path;
-
-    /* check that context is initialized */
-    if (ctx == NULL) {
-      afb_req_fail (request, "failed", "uninitialized");
-      return;
-    }
-
-    /* get the file */
-    argfile = afb_req_get(request, "file-upload");
-    if (!argfile.value || !argfile.path) {
-        afb_req_fail (request, "failed", "expected file not received");
-        return;
-    }
-
-    /* rename the file */
-    path = renamed_filename(argfile);
-    if (path == NULL) {
-        afb_req_fail (request, "failed", "out of memory");
-        return;
-    }
-    if (rename(argfile.path, path) != 0) {
-        free(path);
-        afb_req_fail (request, "failed", "system error");
-        return;
-    }
-
-    /* for asynchronous processing */
-    prequest = afb_req_store(request);
-    if (path == NULL) {
-        unlink(path);
-        afb_req_fail (request, "failed", "out of memory");
-    }
-    else if (!_rygel_upload (ctx, path, (void*)on_uploaded, prequest)) {
-        afb_req_unref(afb_req_unstore(prequest));
-        unlink(path);
-        afb_req_fail (request, "failed", "Error when uploading file to media server... could not complete");
-    }
-    free(path);
-}
-
-static void ping (struct afb_req request) {         /* AFB_SESSION_NONE */
-    afb_req_success (request, NULL, "Media - Ping succeeded");
-}
-
-
-static const struct AFB_verb_desc_v1 verbs[]= {
-  {"init"   , AFB_SESSION_CHECK,  init       , "Media API - init"   },
-  {"list"   , AFB_SESSION_CHECK,  list       , "Media API - list"   },
-  {"select" , AFB_SESSION_CHECK,  selecting  , "Media API - select" },
-  {"play"   , AFB_SESSION_CHECK,  play       , "Media API - play"   },
-  {"stop"   , AFB_SESSION_CHECK,  stop       , "Media API - stop"   },
-  {"pause"  , AFB_SESSION_CHECK,  pausing    , "Media API - pause"  },
-  {"seek"   , AFB_SESSION_CHECK,  seek       , "Media API - seek"   },
-//  {"upload" , AFB_SESSION_CHECK,  upload     , "Media API - upload" },
-  {"ping"   , AFB_SESSION_NONE,   ping       , "Media API - ping"   },
-  {NULL}
-};
-
-static const struct AFB_plugin pluginDesc = {
-    .type   = AFB_PLUGIN_VERSION_1,
-    .v1 = {
-        .info   = "Application Framework Binder - Media plugin",
-        .prefix = "media",
-        .verbs   = verbs
-    }
-};
-
-const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
-{
-    return &pluginDesc;
-}
diff --git a/plugins/media/media-api.h b/plugins/media/media-api.h
deleted file mode 100644
index c1d764c2..00000000
--- a/plugins/media/media-api.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MEDIA_API_H
-#define MEDIA_API_H
-
-/* -------------- PLUGIN DEFINITIONS ----------------- */
-
-/* private client context [will be destroyed when client leaves] */
-typedef struct {
-  void *media_server;          /* handle to implementation (Rygel...) */
-  unsigned int index;          /* currently selected media file       */
-} mediaCtxHandleT;
-
-#endif /* MEDIA_API_H */
diff --git a/plugins/media/media-rygel.c b/plugins/media/media-rygel.c
deleted file mode 100644
index 00327795..00000000
--- a/plugins/media/media-rygel.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-
-#include "media-api.h"
-#include "media-rygel.h"
-
-static void _rygel_device_cb (GUPnPControlPoint *, GUPnPDeviceProxy *, gpointer);
-static void _rygel_av_transport_cb (GUPnPControlPoint *, GUPnPDeviceProxy *, gpointer);
-static void _rygel_content_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
-static void _rygel_metadata_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
-static void _rygel_select_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
-static void _rygel_upload_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
-static void _rygel_transfer_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
-static void _rygel_do_cb (GUPnPServiceProxy *, GUPnPServiceProxyAction *, gpointer);
-
-static unsigned int client_count = 0;
-static struct dev_ctx **dev_ctx = NULL;
-
-/* -------------- MEDIA RYGEL IMPLEMENTATION ---------------- */
-
-/* --- PUBLIC FUNCTIONS --- */
-
-unsigned char _rygel_init (mediaCtxHandleT *ctx) {
-
-    GMainContext *loop;
-    GUPnPContext *context;
-    GUPnPControlPoint *control_point;
-    gint handler_cb;
-    struct timeval tv_start, tv_now;
-
-    context = gupnp_context_new (NULL, NULL, 0, NULL);
-
-    control_point = gupnp_control_point_new (context, URN_MEDIA_SERVER);
-
-    handler_cb = g_signal_connect (control_point, "device-proxy-available",
-                                   G_CALLBACK (_rygel_device_cb), ctx);
-
-    /* start searching for servers */
-    gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (control_point), TRUE);
-
-    loop = g_main_context_default ();
-
-    /* 5 seconds should be sufficient to find Rygel */
-    gettimeofday (&tv_start, NULL);
-    gettimeofday (&tv_now, NULL);
-    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
-
-        g_main_context_iteration (loop, FALSE);
-
-        if (ctx->media_server)
-            break;
-        gettimeofday (&tv_now, NULL);
-    }
-    /* fail if we found no server */
-    if (!ctx->media_server)
-      return 0;
-
-    /* we have found the server ; stop looking for it... */
-    g_signal_handler_disconnect (control_point, handler_cb);
-
-    dev_ctx[client_count]->loop = loop;
-    dev_ctx[client_count]->context = context;
-    dev_ctx[client_count]->av_transport = NULL;
-    dev_ctx[client_count]->state = STOP;
-    dev_ctx[client_count]->target_state = STOP;
-    dev_ctx[client_count]->action_args = NULL;
-    dev_ctx[client_count]->transfer_started = 0;
-
-    client_count++;
-
-    return 1;
-}
-
-void _rygel_free (mediaCtxHandleT *ctx) {
-
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
-
-    client_count--;
-
-    g_main_context_unref (dev_ctx_c->loop);
-    dev_ctx_c->loop = NULL;
-    dev_ctx_c->context = NULL;
-    dev_ctx_c->device_info = NULL;
-    dev_ctx_c->av_transport = NULL;
-    dev_ctx_c->content_dir = NULL;
-    dev_ctx_c->content_res = NULL;
-}
-
-json_object* _rygel_list (mediaCtxHandleT *ctx) {
-
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
-    json_object *json_o, *json_a;
-    char *raw, *start, *end, *id, *title;
-    int length, i = 0;
-
-    if (!dev_ctx_c)
-      return NULL;
-
-    raw = _rygel_list_raw (dev_ctx_c, NULL);
-    if (!raw)
-      return NULL;
-
-    start = strstr (raw, "<dc:title>");
-    if (!start)
-      return NULL;
-
-    json_o = json_object_new_object ();
-    json_a = json_object_new_array ();
-    while (start) {
-        json_object *json_i, *json_id, *json_title;
-
-        start = strstr (start, "<dc:title>");
-        if (!start) break;
-        end = strstr (start, "</dc:title>");
-        start += 10;
-        length = end - start;
-
-        asprintf (&id, "%02d", i);
-
-        title = (char*) malloc (length+1);
-        strncpy (title, start, length);
-        title[length] = '\0';
-
-        json_i = json_object_new_object ();
-        json_id = json_object_new_string (id);
-        json_title = json_object_new_string (title);
-        json_object_object_add (json_i, "id", json_id);
-        json_object_object_add (json_i, "title", json_title);
-        json_object_array_add (json_a, json_i);
-
-        free (id); free (title); 
-        i++;
-    }
-
-    json_object_object_add (json_o, "list", json_a);
-
-    return json_o;
-}
-
-unsigned char _rygel_select (mediaCtxHandleT *ctx, unsigned int index) {
-
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
-    unsigned int count;
-
-    if (!dev_ctx_c)
-      return 0;
-
-    if (!_rygel_list_raw (dev_ctx_c, &count) ||
-        index >= count)
-      return 0;
-
-    if (ctx->index != index)
-      dev_ctx_c->state = STOP;
-
-    return 1;
-}
-
-unsigned char _rygel_upload (mediaCtxHandleT *ctx, const char *path, void (*oncompletion)(void*,int), void *closure) {
-
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
-    char *raw, *upload_id;
-
-    if (!dev_ctx_c)
-      return 0;
-
-    raw = _rygel_list_raw (dev_ctx_c, NULL);
-    if (!raw)
-      return 0;
-
-    /* for now, we always use the same upload container id */
-    upload_id = _rygel_find_upload_id (dev_ctx_c, raw);
-
-    return _rygel_start_uploading (dev_ctx_c, strdup(path), upload_id);
-}
-
-unsigned char _rygel_do (mediaCtxHandleT *ctx, State state, char *args) {
-
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)ctx->media_server;
-    unsigned int index = ctx->index;
-    unsigned int count;
-    char *raw, *id, *metadata, *uri;
-
-    if (!dev_ctx_c || dev_ctx_c->state == state)
-        return 0;
-
-    raw = _rygel_list_raw (dev_ctx_c, &count);
-    if (!raw || index >= count)
-      return 0;
-
-          id = _rygel_find_id_for_index (dev_ctx_c, raw, index);
-    metadata = _rygel_find_metadata_for_id (dev_ctx_c, id);
-         uri = _rygel_find_uri_for_metadata (dev_ctx_c, metadata);
-
-    return _rygel_start_doing (dev_ctx_c, uri, metadata, state, args);
-}
-
-/* --- LOCAL HELPER FUNCTIONS --- */
-
-char* _rygel_list_raw (dev_ctx_T* dev_ctx_c, unsigned int *count) {
-
-    GUPnPServiceProxy *content_dir_proxy;
-    struct timeval tv_start, tv_now;
-
-    dev_ctx_c->content_res = NULL;
-    dev_ctx_c->content_num = 0;
-    content_dir_proxy = GUPNP_SERVICE_PROXY (dev_ctx_c->content_dir);
-
-    gupnp_service_proxy_begin_action (content_dir_proxy, "Browse", _rygel_content_cb, dev_ctx_c,
-                                      "ObjectID", G_TYPE_STRING, "Filesystem",
-                                      "BrowseFlag", G_TYPE_STRING, "BrowseDirectChildren",
-                                      "Filter", G_TYPE_STRING, "@childCount",
-                                      "StartingIndex", G_TYPE_UINT, 0,
-                                      "RequestedCount", G_TYPE_UINT, 64,
-                                      "SortCriteria", G_TYPE_STRING, "",
-                                       NULL);
-
-    gettimeofday (&tv_start, NULL);
-    gettimeofday (&tv_now, NULL);
-    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
-
-        g_main_context_iteration (dev_ctx_c->loop, FALSE);
-
-        if (dev_ctx_c->content_res)
-            break;
-        gettimeofday (&tv_now, NULL);
-    }
-
-    if (count) *count = dev_ctx_c->content_num;
-    return dev_ctx_c->content_res;
-}
-
-char* _rygel_find_upload_id (dev_ctx_T* dev_ctx_c, char *raw) {
-
-    char *found;
-    char id[33];
-
-    found = strstr (raw, "parentID=\"");
-    found += 10;
-
-    /* IDs are 32-bit strings */
-    strncpy (id, found, 32);
-    id[32] = '\0';
-
-    return strdup (id);
-}
-
-char* _rygel_find_id_for_index (dev_ctx_T* dev_ctx_c, char *raw, unsigned int index) {
-
-    char *found = raw;
-    char id[33];
-    int i;
-
-    for (i = 0; i <= index; i++) {
-        found = strstr (found, "item id=");
-        found += 9;
-
-        if (i == index) {
-	    /* IDs are 32-bit strings */
-            strncpy (id, found, 32);
-            id[32] = '\0';
-        }
-    }
-
-    return strdup (id);
-}
-
-char* _rygel_find_metadata_for_id (dev_ctx_T* dev_ctx_c, char *id) {
-
-    GUPnPServiceProxy *content_dir_proxy;
-    struct timeval tv_start, tv_now;
-
-    dev_ctx_c->content_res = NULL;
-
-    content_dir_proxy = GUPNP_SERVICE_PROXY (dev_ctx_c->content_dir);
-
-    gupnp_service_proxy_begin_action (content_dir_proxy, "Browse", _rygel_metadata_cb, dev_ctx_c,
-                                      "ObjectID", G_TYPE_STRING, id,
-                                      "BrowseFlag", G_TYPE_STRING, "BrowseMetadata",
-                                      "Filter", G_TYPE_STRING, "*",
-                                      "StartingIndex", G_TYPE_UINT, 0,
-                                      "RequestedCount", G_TYPE_UINT, 0,
-                                      "SortCriteria", G_TYPE_STRING, "",
-                                       NULL);
-
-    gettimeofday (&tv_start, NULL);
-    gettimeofday (&tv_now, NULL);
-    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
-
-        g_main_context_iteration (dev_ctx_c->loop, FALSE);
-
-        if (dev_ctx_c->content_res)
-            break;
-        gettimeofday (&tv_now, NULL);
-    }
-
-    return dev_ctx_c->content_res;
-}
-
-char* _rygel_find_uri_for_metadata (dev_ctx_T* dev_ctx_c, char *metadata) {
-
-    char *start, *end, *uri = NULL;
-    int length;
-
-    /* position ourselves after the first "<res " tag */
-    start = strstr (metadata, "<res ");
-
-    while (start) {
-        start = strstr (start, "http://");
-	if (!start) break;
-	end = strstr (start, "</res>");
-	length = end - start;
-
-
-        uri = (char *)malloc (length + 1);
-	strncpy (uri, start, length);
-        uri[length] = '\0';
-        /* if the URI contains "primary_http", it is the main one ; stop here...*/
-        if (strstr (uri, "primary_http"))
-          break;
-
-        free (uri); start = end;
-    }
-
-    return uri;
-}
-
-char * _rygel_time_for_string (char *string) {
-
-    int total_seconds;
-    unsigned int hours, minutes, seconds;
-    char *time;
-
-    total_seconds = atoi (string);
-    hours = total_seconds / 3600;
-    minutes = (total_seconds / 60) - (hours * 60);
-    seconds = total_seconds - (hours * 3600) - (minutes * 60);
-
-    asprintf (&time, "%u:%02u:%02u", hours, minutes, seconds);
-
-    return time;
-}
-
-unsigned char _rygel_start_uploading (dev_ctx_T* dev_ctx_c, char *path, char *upload_id) {
-
-    GUPnPServiceProxy *content_dir_proxy;
-    GUPnPDIDLLiteWriter *didl_writer;
-    GUPnPDIDLLiteObject *didl_object;
-    char *didl, *content_type, *mime_type, *upnp_class;
-    struct timeval tv_start, tv_now;
-
-    didl_writer = gupnp_didl_lite_writer_new (NULL);
-    didl_object = GUPNP_DIDL_LITE_OBJECT (gupnp_didl_lite_writer_add_item (didl_writer));
-
-    /* create the metadata for the file */
-    gupnp_didl_lite_object_set_parent_id (didl_object, upload_id);
-    gupnp_didl_lite_object_set_id (didl_object, "");
-    gupnp_didl_lite_object_set_restricted (didl_object, FALSE);
-    gupnp_didl_lite_object_set_title (didl_object, g_path_get_basename (path));
-    /* deduce the UPnP class from the MIME type ("audio/ogg" e.g.) */
-    content_type = g_content_type_guess (path, NULL, 0, NULL);
-    mime_type = g_content_type_get_mime_type (content_type);
-    if (strstr (mime_type, "audio/"))
-      upnp_class = strdup ("object.item.audioItem.musicTrack");
-    else if (strstr (mime_type, "video/"))
-      upnp_class = strdup ("object.item.videoItem");
-    else if (strstr (mime_type, "image/"))
-      upnp_class = strdup ("object.item.imageItem");
-    else
-      upnp_class = strdup ("object.item");
-    gupnp_didl_lite_object_set_upnp_class (didl_object, upnp_class);
-    didl = gupnp_didl_lite_writer_get_string (didl_writer);
-
-    dev_ctx_c->transfer_path = path;
-    dev_ctx_c->transfer_started = 0;
-    content_dir_proxy = GUPNP_SERVICE_PROXY (dev_ctx_c->content_dir);
-
-    gupnp_service_proxy_begin_action (content_dir_proxy, "CreateObject", _rygel_upload_cb, dev_ctx_c,
-                                      "ContainerID", G_TYPE_STRING, upload_id,
-                                      "Elements", G_TYPE_STRING, didl,
-                                       NULL);
-
-    gettimeofday (&tv_start, NULL);
-    gettimeofday (&tv_now, NULL);
-    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
-
-      g_main_context_iteration (dev_ctx_c->loop, FALSE);
-
-      if (dev_ctx_c->transfer_started)
-        break;
-      gettimeofday (&tv_now, NULL);
-    }
-    if (!dev_ctx_c->transfer_started)
-      return 0;
-
-    return 1;
-}
-
-unsigned char _rygel_start_doing (dev_ctx_T* dev_ctx_c, char *uri, char *metadata, State state, char *args) {
-
-    GUPnPServiceProxy *av_transport_proxy;
-    struct timeval tv_start, tv_now;
-
-    if (!dev_ctx_c->av_transport) {
-      if (!_rygel_find_av_transport (dev_ctx_c))
-         return 0;
-    }
-    dev_ctx_c->target_state = state;
-    dev_ctx_c->action_args = args;
-    av_transport_proxy = GUPNP_SERVICE_PROXY (dev_ctx_c->av_transport);
-
-    gupnp_service_proxy_begin_action (av_transport_proxy, "SetAVTransportURI", _rygel_select_cb, dev_ctx_c,
-                                      "InstanceID", G_TYPE_UINT, 0,
-                                      "CurrentURI", G_TYPE_STRING, uri,
-                                      "CurrentURIMetaData", G_TYPE_STRING, metadata,
-                                       NULL);
-
-    gettimeofday (&tv_start, NULL);
-    gettimeofday (&tv_now, NULL);
-    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
-
-      g_main_context_iteration (dev_ctx_c->loop, FALSE);
-
-      if (dev_ctx_c->state == state)
-        break;
-      gettimeofday (&tv_now, NULL);
-    }
-    if (dev_ctx_c->state != state)
-      return 0;
-
-    return 1;
-}
-
-unsigned char _rygel_find_av_transport (dev_ctx_T* dev_ctx_c) {
-
-    GUPnPControlPoint *control_point;
-    gint handler_cb;
-    struct timeval tv_start, tv_now;
-
-    control_point = gupnp_control_point_new (dev_ctx_c->context, URN_MEDIA_RENDERER);
-
-    handler_cb = g_signal_connect (control_point, "device-proxy-available",
-                                   G_CALLBACK (_rygel_av_transport_cb), dev_ctx_c);
-
-    gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (control_point), TRUE);
-
-    gettimeofday (&tv_start, NULL);
-    gettimeofday (&tv_now, NULL);
-    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
-
-        g_main_context_iteration (dev_ctx_c->loop, FALSE);
-
-        if (dev_ctx_c->av_transport)
-            break;
-        gettimeofday (&tv_now, NULL);
-    }
-    g_signal_handler_disconnect (control_point, handler_cb);
-
-    if (!dev_ctx_c->av_transport)
-      return 0;
-
-    return 1;
-}
-
-
- /* ---- LOCAL CALLBACK FUNCTIONS ---- */
-
-static void _rygel_device_cb (GUPnPControlPoint *point, GUPnPDeviceProxy *proxy,
-                              gpointer data) {
-
-    mediaCtxHandleT *ctx = (mediaCtxHandleT*)data;
-    GUPnPDeviceInfo *device_info;
-    GUPnPServiceInfo *content_dir;
-    const char *device_name;
-
-    device_info = GUPNP_DEVICE_INFO (proxy);
-    device_name = gupnp_device_info_get_model_name (device_info);
-    content_dir = gupnp_device_info_get_service (device_info, URN_CONTENT_DIR);
-
-    if (strcmp (device_name, "Rygel") != 0)
-        return;
-    if (!content_dir)
-        return;
-
-    /* allocate the global array if it has not been not done */
-    if (!dev_ctx)
-        dev_ctx = (dev_ctx_T**) malloc (sizeof(dev_ctx_T));
-    else
-        dev_ctx = (dev_ctx_T**) realloc (dev_ctx, (client_count+1)*sizeof(dev_ctx_T));
-
-    /* create an element for the client in the global array */
-    dev_ctx[client_count] = (dev_ctx_T*) malloc (sizeof(dev_ctx_T));
-    dev_ctx[client_count]->device_info = device_info;
-    dev_ctx[client_count]->content_dir = content_dir;
-
-    /* make the client context aware of it */
-    ctx->media_server = (void*)dev_ctx[client_count];
-}
-
-static void _rygel_av_transport_cb (GUPnPControlPoint *point, GUPnPDeviceProxy *proxy,
-                                    gpointer data) {
-
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
-    GUPnPDeviceInfo *device_info;
-    GUPnPServiceInfo *av_transport;
-
-    device_info = GUPNP_DEVICE_INFO (proxy);
-    av_transport = gupnp_device_info_get_service (device_info, URN_AV_TRANSPORT);
-
-    dev_ctx_c->av_transport = av_transport;
-}
-
-static void _rygel_content_cb (GUPnPServiceProxy *content_dir, GUPnPServiceProxyAction *action,
-                               gpointer data) {
-
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
-    GUPnPServiceProxy *content_dir_proxy = GUPNP_SERVICE_PROXY (content_dir);
-    GError *error;
-    char *result;
-    guint32 number_returned;
-    guint32 total_matches;
-    char *found;
-    char subid[33];
-
-    gupnp_service_proxy_end_action (content_dir, action, &error,
-                                    "Result", G_TYPE_STRING, &result,
-                                    "NumberReturned", G_TYPE_UINT, &number_returned,
-                                    "TotalMatches", G_TYPE_UINT, &total_matches,
-                                     NULL);
-
-    if (number_returned == 0)
-        return;
-
-    if (number_returned == 1) {
-        found = strstr (result, "id=\"");	
-        found += 4;
-        strncpy (subid, found, 32); subid[32] = '\0';
-
-	gupnp_service_proxy_begin_action (content_dir_proxy, "Browse", _rygel_content_cb, dev_ctx_c,
-					  "ObjectID", G_TYPE_STRING, subid,
-					  "BrowseFlag", G_TYPE_STRING, "BrowseDirectChildren",
-					  "Filter", G_TYPE_STRING, "@childCount",
-					  "StartingIndex", G_TYPE_UINT, 0,
-					  "RequestedCount", G_TYPE_UINT, 64,
-					  "SortCriteria", G_TYPE_STRING, "",
-					   NULL);
-        return;
-    }
-
-    if (number_returned > 1) {
-        dev_ctx_c->content_res = result;
-        dev_ctx_c->content_num = number_returned;
-    }
-}
-
-static void _rygel_metadata_cb (GUPnPServiceProxy *content_dir, GUPnPServiceProxyAction *action,
-                                gpointer data) {
-
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
-    GError *error;
-    char *result;
-
-    gupnp_service_proxy_end_action (content_dir, action, &error,
-                                    "Result", G_TYPE_STRING, &result,
-				     NULL);
-
-    dev_ctx_c->content_res = result;
-}
-
-static void _rygel_select_cb (GUPnPServiceProxy *av_transport, GUPnPServiceProxyAction *action,
-                              gpointer data)
-{
-
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
-    GUPnPServiceProxy *av_transport_proxy;
-    GError *error;
-    char *time;
-    struct timeval tv_start, tv_now;
-
-    av_transport_proxy = GUPNP_SERVICE_PROXY (av_transport);
-
-    gupnp_service_proxy_end_action (av_transport, action, &error, NULL);
-
-    switch (dev_ctx_c->target_state) {
-        case PLAY:
-          gupnp_service_proxy_begin_action (av_transport_proxy, "Play", _rygel_do_cb, dev_ctx_c,
-                                           "InstanceID", G_TYPE_UINT, 0,
-                                           "Speed", G_TYPE_STRING, "1",
-                                            NULL);
-          break;
-       case PAUSE:
-          gupnp_service_proxy_begin_action (av_transport_proxy, "Pause", _rygel_do_cb, dev_ctx_c,
-                                           "InstanceID", G_TYPE_UINT, 0,
-                                            NULL);
-          break;
-       case STOP:
-          gupnp_service_proxy_begin_action (av_transport_proxy, "Stop", _rygel_do_cb, dev_ctx_c,
-                                           "InstanceID", G_TYPE_UINT, 0,
-                                            NULL);
-          break;
-       case SEEK:
-          time = _rygel_time_for_string (dev_ctx_c->action_args);
-          gupnp_service_proxy_begin_action (av_transport_proxy, "Seek", _rygel_do_cb, dev_ctx_c,
-                                           "InstanceID", G_TYPE_UINT, 0,
-                                           "Unit", G_TYPE_STRING, "ABS_TIME",
-                                           "Target", G_TYPE_STRING, time,
-                                            NULL);
-       default:
-	 break;
-    }
-
-    gettimeofday (&tv_start, NULL);
-    gettimeofday (&tv_now, NULL);
-    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
-
-        g_main_context_iteration (dev_ctx_c->loop, FALSE);
-
-        if (dev_ctx_c->state == dev_ctx_c->target_state)
-            break;
-        gettimeofday (&tv_now, NULL);
-    }
-}
-
-static void _rygel_upload_cb (GUPnPServiceProxy *content_dir, GUPnPServiceProxyAction *action,
-                              gpointer data)
-{
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
-    GUPnPServiceProxy *content_dir_proxy;
-    GError *error;
-    char *result, *start, *end, *dst_uri, *src_uri;
-    int length;
-    struct timeval tv_start, tv_now;
-
-    content_dir_proxy = GUPNP_SERVICE_PROXY (content_dir);
-
-    if (!gupnp_service_proxy_end_action (content_dir, action, &error,
-                                         "Result", G_TYPE_STRING, &result,
-                                          NULL))
-      return;
-
-    start = strstr (result, "<res importUri=\"");
-    if (!start)
-      return;
-
-    start += 16;
-    end = strstr (start, "\"");
-    length = end - start;
-
-    dst_uri = (char*) malloc(length+1);
-    strncpy (dst_uri, start, length);
-    dst_uri[length] = '\0';
-
-    asprintf (&src_uri, "http://%s:%u%s", gupnp_context_get_host_ip (dev_ctx_c->context),
-                                          gupnp_context_get_port (dev_ctx_c->context),
-                                          dev_ctx_c->transfer_path);
-
-    /* host the file */
-    gupnp_context_host_path (dev_ctx_c->context, dev_ctx_c->transfer_path,
-                                                 dev_ctx_c->transfer_path);
-
-    gupnp_service_proxy_begin_action (content_dir_proxy, "ImportResource", _rygel_transfer_cb, dev_ctx_c,
-                                      "SourceURI", G_TYPE_STRING, src_uri,
-                                      "DestinationURI", G_TYPE_STRING, dst_uri,
-                                       NULL);
-
-    gettimeofday (&tv_start, NULL);
-    gettimeofday (&tv_now, NULL);
-    while (tv_now.tv_sec - tv_start.tv_sec <= 5) {
-
-        g_main_context_iteration (dev_ctx_c->loop, FALSE);
-
-        if (dev_ctx_c->transfer_started)
-            break;
-        gettimeofday (&tv_now, NULL);
-    }
-}
-
-static void _rygel_transfer_cb (GUPnPServiceProxy *content_dir, GUPnPServiceProxyAction *action,
-                                gpointer data)
-{
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
-    GError *error;
-    guint transfer_id;
-
-    if (!gupnp_service_proxy_end_action (content_dir, action, &error,
-                                         "TransferID", G_TYPE_UINT, &transfer_id,
-                                          NULL))
-      return;
-
-    dev_ctx_c->transfer_started = 1;
-}
-
-static void _rygel_do_cb (GUPnPServiceProxy *av_transport, GUPnPServiceProxyAction *action,
-                          gpointer data)
-{
-    dev_ctx_T *dev_ctx_c = (dev_ctx_T*)data;
-    GError *error;
-
-    if (!gupnp_service_proxy_end_action (av_transport, action, &error,
-                                         NULL))
-      return;
-
-    dev_ctx_c->state = dev_ctx_c->target_state;
-}
diff --git a/plugins/media/media-rygel.h b/plugins/media/media-rygel.h
deleted file mode 100644
index 951c6b89..00000000
--- a/plugins/media/media-rygel.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MEDIA_RYGEL_H
-#define MEDIA_RYGEL_H
-
-/* --------------- MEDIA RYGEL DEFINITIONS ------------------ */
-
-#include <sys/time.h>
-#include <json-c/json.h>
-#include <libgupnp/gupnp-control-point.h>
-#include <libgupnp-av/gupnp-av.h>
-
-#include "media-api.h"
-
-#define URN_MEDIA_SERVER   "urn:schemas-upnp-org:device:MediaServer:1"
-#define URN_MEDIA_RENDERER "urn:schemas-upnp-org:device:MediaRenderer:1"
-#define URN_CONTENT_DIR    "urn:schemas-upnp-org:service:ContentDirectory"
-#define URN_AV_TRANSPORT   "urn:schemas-upnp-org:service:AVTransport"
-
-typedef enum { PLAY, PAUSE, STOP, SEEK } State;
-typedef struct dev_ctx dev_ctx_T;
-
-struct dev_ctx {
-    GMainContext *loop;
-    GUPnPContext *context;
-    GUPnPDeviceInfo *device_info;
-    GUPnPServiceInfo *content_dir;
-    GUPnPServiceInfo *av_transport;
-    char *content_res;
-    int content_num;
-    State state;
-    State target_state;
-    char *action_args;
-    char *transfer_path;
-    unsigned char transfer_started;
-};
-
-unsigned char _rygel_init (mediaCtxHandleT *);
-void _rygel_free (mediaCtxHandleT *);
-json_object* _rygel_list (mediaCtxHandleT *);
-unsigned char _rygel_select (mediaCtxHandleT *, unsigned int);
-unsigned char _rygel_upload (mediaCtxHandleT *ctx, const char *path, void (*oncompletion)(void*,int), void *closure);
-unsigned char _rygel_do (mediaCtxHandleT *, State, char *);
-
-char* _rygel_list_raw (dev_ctx_T *, unsigned int *);
-char* _rygel_find_upload_id (dev_ctx_T *, char *);
-char* _rygel_find_id_for_index (dev_ctx_T *, char *, unsigned int);
-char* _rygel_find_metadata_for_id (dev_ctx_T *, char *);
-char* _rygel_find_uri_for_metadata (dev_ctx_T *, char *);
-unsigned char _rygel_start_uploading (dev_ctx_T *, char *, char *);
-unsigned char _rygel_start_doing (dev_ctx_T *, char *, char *, State, char *);
-unsigned char _rygel_find_av_transport (dev_ctx_T *);
-#endif /* MEDIA_RYGEL_H */
diff --git a/plugins/radio/CMakeLists.txt b/plugins/radio/CMakeLists.txt
deleted file mode 100644
index 2aa765da..00000000
--- a/plugins/radio/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-INCLUDE(FindPkgConfig)
-PKG_CHECK_MODULES(librtlsdr librtlsdr>=0.5.0)
-
-IF(librtlsdr_FOUND)
-
-  MESSAGE(STATUS "librtlsdr found ; will compile Radio plugin... (PLUGIN)")
-  INCLUDE_DIRECTORIES(${include_dirs} ${librtlsdr_INCLUDE_DIRS})
-  ADD_LIBRARY(radio-api MODULE radio-api.c radio-rtlsdr.c)
-  SET_TARGET_PROPERTIES(radio-api PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
-  )
-  TARGET_LINK_LIBRARIES(radio-api ${link_libraries} ${librtlsdr_LIBRARIES} -lm)
-  INSTALL(TARGETS radio-api
-          LIBRARY DESTINATION ${plugin_install_dir})
-
-ENDIF(librtlsdr_FOUND)
diff --git a/plugins/radio/export.map b/plugins/radio/export.map
deleted file mode 100644
index e2da85ca..00000000
--- a/plugins/radio/export.map
+++ /dev/null
@@ -1 +0,0 @@
-{ global: pluginAfbV1Register; local: *; };
diff --git a/plugins/radio/radio-api.c b/plugins/radio/radio-api.c
deleted file mode 100644
index 0ed60e1c..00000000
--- a/plugins/radio/radio-api.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <strings.h>
-#include <json-c/json.h>
-
-#include "radio-api.h"
-#include "radio-rtlsdr.h"
-
-#include <afb/afb-plugin.h>
-#include <afb/afb-req-itf.h>
-
-/* ********************************************************
-
-   FULUP integration proposal with client session context
-
-   ******************************************************** */
-
-/* ------ LOCAL HELPER FUNCTIONS --------- */
-
-static pluginHandleT *the_radio = NULL;
-
-/* detect new radio devices */
-void updateRadioDevList(pluginHandleT *handle) {
-
-  int idx;  
-
-  // loop on existing radio if any
-  for (idx = 0; idx < _radio_dev_count(); idx++) {
-      if (idx == MAX_RADIO) break;
-      handle->radios[idx] = calloc(1, sizeof(radioDevT)); /* use calloc to set "used" to FALSE */
-      handle->radios[idx]->name = (char *) _radio_dev_name(idx);
-  }
-  handle->devCount = _radio_dev_count();
-}
-
-/* global plugin context creation ; at loading time [radio devices might not be visible] */
-static void initRadioPlugin() {
-
-  pluginHandleT *handle;
-
-  handle = calloc (1, sizeof(pluginHandleT));
-  updateRadioDevList (handle);
-  the_radio = handle;
-}
-
-/* private client context creation ; default values */
-static radioCtxHandleT* initRadioCtx () {
-
-    radioCtxHandleT *ctx;
-
-    ctx = malloc (sizeof(radioCtxHandleT));
-    ctx->radio = NULL;
-    ctx->idx = -1;
-    ctx->mode = FM;
-    ctx->freq = 100.0;
-    ctx->mute = 0;
-    ctx->is_playing = 0;
-
-    return ctx;
-}
-
-/* reserve a radio device for requesting client, power it on */
-unsigned char reserveRadio (pluginHandleT *handle, radioCtxHandleT *ctx) {
-
-    unsigned int idx;
-
-    /* loop on all devices, find an unused one */
-    for (idx = 0; idx < _radio_dev_count(); idx++) {
-        if (idx == MAX_RADIO) break;
-        if (handle->radios[idx]->used == FALSE) goto found_radio; /* found one */
-    }
-    return 0;
-
-  found_radio:
-    /* try to power it on, passing client context info such as frequency... */
-
-    _radio_on (idx, ctx);
-    /* TODO : try to re-iterate from the next ones if it failed ! */
-
-    /* globally mark it as reserved */
-    handle->radios[idx]->used = TRUE;
-
-    /* store relevant info to client context (direct pointer, index) */
-    ctx->radio = handle->radios[idx];
-    ctx->idx = idx;
-
-    return 1;
-}
-
-/* free a radio device from requesting client, power it off */
-unsigned char releaseRadio (pluginHandleT *handle, radioCtxHandleT *ctx) {
-
-    /* stop playing if it was doing this (blocks otherwise) */
-    if (ctx->is_playing) {
-        ctx->is_playing = 0;
-        _radio_stop (ctx->idx);
-    }
-
-    /* power it off */
-    _radio_off (ctx->idx);
-
-    /* globally mark it as free */
-    handle->radios[ctx->idx]->used = FALSE;
-
-    /* clean client context */
-    ctx->radio = NULL;
-    ctx->idx = -1;
-
-    return 1;
-}
-
-/* called when client session dies [e.g. client quits for more than 15mns] */
-static void freeRadio (void *context) {
-
-    releaseRadio (the_radio, context);
-    free (context);
-}
-
-
-/* ------ PUBLIC PLUGIN FUNCTIONS --------- */
-
-static void init (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    radioCtxHandleT *ctx = afb_req_context_get (request);
-    json_object *jresp;
-
-    /* create a global plugin handle */
-    if (!the_radio)
-        initRadioPlugin();
-
-    /* create a private client context */
-    if (!ctx) {
-        ctx = initRadioCtx();
-        afb_req_context_set (request, ctx, free);
-    }
-
-    jresp = json_object_new_object();
-    json_object_object_add(jresp, "init", json_object_new_string ("success"));
-    afb_req_success (request, jresp, "Radio initialized");
-}
-
-static void power (struct afb_req request) {       /* AFB_SESSION_CHECK */
-
-    pluginHandleT *handle = the_radio;
-    radioCtxHandleT *ctx = afb_req_context_get (request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp;
-
-	if (!ctx) {
-        afb_req_fail (request, "failed", "you must call 'init' first");
-        return;
-    }
-    jresp = json_object_new_object();
-
-    /* no "?value=" parameter : return current state */
-    if (!value) {
-        ctx->radio ?
-            json_object_object_add (jresp, "power", json_object_new_string ("on"))
-          : json_object_object_add (jresp, "power", json_object_new_string ("off"));
-        afb_req_success (request, jresp, "Radio - Power status obtained");
-        return;
-    }
-
-    /* "?value=" parameter is "1" or "true" */
-    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
-        if (!ctx->radio) {
-            if (!reserveRadio (handle, ctx)) {
-                afb_req_fail (request, "failed", "no more radio devices available");
-		        return;
-            }
-        }
-        json_object_object_add (jresp, "power", json_object_new_string ("on"));
-    }
-
-    /* "?value=" parameter is "0" or "false" */
-    else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
-        if (ctx->radio) {
-            if (!releaseRadio (handle, ctx)) {
-                afb_req_fail (request, "failed", "Unable to release radio device");
-		        return;
-            }
-        }
-        json_object_object_add (jresp, "power", json_object_new_string ("off"));
-    }
-    else
-        jresp = NULL;
-
-    afb_req_success (request, jresp, "Radio - Power set");
-}
-
-static void mode (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    radioCtxHandleT *ctx = afb_req_context_get (request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp;
-
-	if (!ctx) {
-        afb_req_fail (request, "failed", "you must call 'init' first");
-        return;
-    }
-    jresp = json_object_new_object();
-
-    /* no "?value=" parameter : return current state */
-    if (!value || !ctx->radio) {
-        ctx->mode ?
-            json_object_object_add (jresp, "mode", json_object_new_string ("AM"))
-          : json_object_object_add (jresp, "mode", json_object_new_string ("FM"));
-    }
-
-    /* "?value=" parameter is "1" or "AM" */
-    else if ( atoi(value) == 1 || !strcasecmp(value, "AM") ) {
-        ctx->mode = AM;
-        _radio_set_mode (ctx->idx, ctx->mode);
-        json_object_object_add (jresp, "mode", json_object_new_string ("AM"));
-    }
-
-    /* "?value=" parameter is "0" or "FM" */
-    else if ( atoi(value) == 0 || !strcasecmp(value, "FM") ) {
-        ctx->mode = FM;
-        _radio_set_mode (ctx->idx, ctx->mode);
-        json_object_object_add (jresp, "mode", json_object_new_string ("FM"));
-    }
-
-    afb_req_success (request, jresp, "Radio - Mode set");
-}
-
-static void freq (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    radioCtxHandleT *ctx = afb_req_context_get (request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp;
-    double freq;
-    char freq_str[256];
-
-	if (!ctx) {
-        afb_req_fail (request, "failed", "you must call 'init' first");
-        return;
-    }
-    jresp = json_object_new_object();
-
-    /* no "?value=" parameter : return current state */
-    if (!value || !ctx->radio) {
-        snprintf (freq_str, sizeof(freq_str), "%f", ctx->freq);
-        json_object_object_add (jresp, "freq", json_object_new_string (freq_str));
-    }
-
-    /* "?value=" parameter, set frequency */
-    else {
-        freq = strtod (value, NULL);
-        _radio_set_freq (ctx->idx, freq);
-        ctx->freq = (float)freq;
-
-        snprintf (freq_str, sizeof(freq_str), "%f", ctx->freq);
-        json_object_object_add (jresp, "freq", json_object_new_string (freq_str));
-    }
-
-    afb_req_success (request, jresp, "Radio - Frequency Set");
-}
-
-static void mute (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    radioCtxHandleT *ctx = afb_req_context_get (request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp = json_object_new_object();
-
-	if (!ctx) {
-        afb_req_fail (request, "failed", "you must call 'init' first");
-        return;
-    }
-
-    /* no "?value=" parameter : return current state */
-    if (!value || !ctx->radio) {
-        ctx->mute ?
-            json_object_object_add (jresp, "mute", json_object_new_string ("on"))
-          : json_object_object_add (jresp, "mute", json_object_new_string ("off"));
-    }
-
-    /* "?value=" parameter is "1" or "true" */
-    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
-        ctx->mute = 1;
-        _radio_set_mute (ctx->idx, ctx->mute);
-        json_object_object_add (jresp, "mute", json_object_new_string ("on"));
-    }
-
-    /* "?value=" parameter is "0" or "false" */
-    else if ( atoi(value) == 0 || !strcasecmp(value, "off") ) {
-        ctx->mute = 0;
-        _radio_set_mute (ctx->idx, ctx->mute);
-        json_object_object_add (jresp, "mute", json_object_new_string ("off"));
-    }
-
-    afb_req_success (request, jresp, "Radio - Mute set"); 
-}
-
-static void play (struct afb_req request) {        /* AFB_SESSION_CHECK */
-
-    radioCtxHandleT *ctx = afb_req_context_get (request);
-    const char *value = afb_req_value (request, "value");
-    json_object *jresp = json_object_new_object();
-
-	if (!ctx) {
-        afb_req_fail (request, "failed", "you must call 'init' first");
-        return;
-    }
-    
-    /* no "?value=" parameter : return current state */
-    if (!value || !ctx->radio) {
-        ctx->is_playing ?
-            json_object_object_add (jresp, "play", json_object_new_string ("on"))
-          : json_object_object_add (jresp, "play", json_object_new_string ("off"));
-    }
-
-    /* "?value=" parameter is "1" or "true" */
-    else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
-        /* radio playback */
-        ctx->is_playing = 1;
-        _radio_play (ctx->idx);
-        json_object_object_add (jresp, "play", json_object_new_string ("on"));
-    }
-
-    /* "?value=" parameter is "0" or "false" */
-    else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
-        /* radio stop */
-        ctx->is_playing = 0;
-        _radio_stop (ctx->idx);
-        json_object_object_add (jresp, "play", json_object_new_string ("off"));
-    }
-
-    afb_req_success (request, jresp, "Radio - Play succeeded");
-}
-
-static void ping (struct afb_req request) {         /* AFB_SESSION_NONE */
-    afb_req_success (request, NULL, "Radio - Ping succeeded");
-}
-
-
-static const struct AFB_verb_desc_v1 verbs[] = {
-  {"init"   , AFB_SESSION_CHECK,  init       , "Radio API - init"},
-  {"power"  , AFB_SESSION_CHECK,  power      , "Radio API - power"},
-  {"mode"   , AFB_SESSION_CHECK,  mode       , "Radio API - mode"},
-  {"freq"   , AFB_SESSION_CHECK,  freq       , "Radio API - freq"},
-  {"mute"   , AFB_SESSION_CHECK,  mute       , "Radio API - mute"},
-  {"play"   , AFB_SESSION_CHECK,  play       , "Radio API - play"},
-  {"ping"   , AFB_SESSION_NONE,   ping       , "Radio API - ping"},
-  {NULL}
-};
-
-static const struct AFB_plugin pluginDesc = {
-    .type  = AFB_PLUGIN_VERSION_1,
-    .v1 = {
-        .info  = "Application Framework Binder - Radio plugin",
-        .prefix  = "radio",
-        .verbs  = verbs
-    }
-};
-
-const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
-{
-	return &pluginDesc;
-}
diff --git a/plugins/radio/radio-api.h b/plugins/radio/radio-api.h
deleted file mode 100644
index 9b91ec69..00000000
--- a/plugins/radio/radio-api.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RADIO_API_H
-#define RADIO_API_H
-
-/* -------------- PLUGIN DEFINITIONS ----------------- */
-
-#define MAX_RADIO 10
-typedef enum { FM, AM } Mode;
-
-/* structure holding one radio device with current usage status */
-typedef struct {
-    int   idx;
-    char *name;
-    int  used;
-} radioDevT;
-
-/* global plugin handle, should store everything we may need */
-typedef struct {
-  radioDevT *radios[MAX_RADIO];  // pointer to existing radio
-  unsigned int devCount;
-} pluginHandleT;
-
-/* private client context [will be destroyed when client leaves] */
-typedef struct {
-    radioDevT *radio;         /* pointer to client radio            */
-    int idx;                  /* radio index within global array    */
-    Mode mode;                /* radio mode: AM/FM                  */
-    float freq;               /* radio frequency (Mhz)              */
-    unsigned char mute;       /* radio muted: 0(false)/1(true)      */
-    unsigned char is_playing; /* radio is playing: 0(false)/1(true) */
-} radioCtxHandleT;
-
-#endif /* RADIO_API_H */
diff --git a/plugins/radio/radio-rtlsdr.c b/plugins/radio/radio-rtlsdr.c
deleted file mode 100644
index 7f76306e..00000000
--- a/plugins/radio/radio-rtlsdr.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "radio-api.h"
-#include "radio-rtlsdr.h"
-
-static void* _dongle_thread_fn (void *);
-static void* _demod_thread_fn (void *);
-static void* _output_thread_fn (void *);
-
-static unsigned int init_dev_count = 0;
-static struct dev_ctx **dev_ctx = NULL;
-
-/* ------------- RADIO RTLSDR IMPLEMENTATION ---------------- */
-
-/* --- PUBLIC FUNCTIONS --- */
-
-/* Radio initialization should be done only when user start the radio and not at plugin initialization
-   Making this call too early would impose to restart the binder to detect a radio */
-unsigned char _radio_on (unsigned int num, radioCtxHandleT *ctx) {
- 
-    if (num >= _radio_dev_count())
-        return 0;
-    
-    if (init_dev_count < _radio_dev_count()) {
-        init_dev_count = _radio_dev_count();
-        dev_ctx = (dev_ctx_T**) realloc (dev_ctx, init_dev_count * sizeof(dev_ctx_T*));           
-    }
-
-    dev_ctx[num] = (dev_ctx_T*) malloc (sizeof(dev_ctx_T));
-    dev_ctx[num]->dev = NULL;
-    dev_ctx[num]->mode = ctx->mode;
-    dev_ctx[num]->freq = ctx->freq;
-    dev_ctx[num]->mute = ctx->mute;
-    dev_ctx[num]->should_run = 0;
-    dev_ctx[num]->dongle = NULL;
-    dev_ctx[num]->demod = NULL;
-    dev_ctx[num]->output = NULL;
-    _radio_dev_init (dev_ctx[num], num);
-
-    return 1;
-}
-
-void _radio_off (unsigned int num) {
-
-    if (num >= _radio_dev_count())
-        return;
-
-    if (dev_ctx[num]) {
-        _radio_dev_free (dev_ctx[num]);
-        free (dev_ctx[num]);
-    }
-    
-    /* free(dev_ctx); */
-}
-
-void _radio_set_mode (unsigned int num, Mode mode) {
-    if (!dev_ctx || !dev_ctx[num])
-        return;
-
-    dev_ctx[num]->mode = mode;
-    _radio_apply_params (dev_ctx[num]);
-}
-
-void _radio_set_freq (unsigned int num, double freq) {
-    if (!dev_ctx || !dev_ctx[num])
-        return;
-
-    dev_ctx[num]->freq = (float)freq;
-    _radio_apply_params (dev_ctx[num]);
-}
-
-void _radio_set_mute (unsigned int num, unsigned char mute) {
-    if (!dev_ctx || !dev_ctx[num])
-        return;
-
-    dev_ctx[num]->mute = mute;
-    _radio_apply_params (dev_ctx[num]);
-}
-
-void _radio_play (unsigned int num) {
-    if (!dev_ctx || !dev_ctx[num])
-        return;
-
-    _radio_start_threads (dev_ctx[num]);
-}
-
-void _radio_stop (unsigned int num) {
-    if (!dev_ctx || !dev_ctx[num])
-        return;
-
-    _radio_stop_threads (dev_ctx[num]);
-}
-
-unsigned int _radio_dev_count () {
-    return rtlsdr_get_device_count();
-}
-
-const char* _radio_dev_name (unsigned int num) {
-    return rtlsdr_get_device_name (num);
-}
-
-
-/* --- LOCAL HELPER FUNCTIONS --- */
-
-unsigned char _radio_dev_init (dev_ctx_T *dev_ctx, unsigned int num) {
-    rtlsdr_dev_t *dev = dev_ctx->dev;
-
-    if (rtlsdr_open (&dev, num) < 0)
-        return 0;
-
-    rtlsdr_set_tuner_gain_mode (dev, 0);
-
-    if (rtlsdr_reset_buffer (dev) < 0)
-        return 0;
-
-    dev_ctx->dev = dev;
-
-    _radio_apply_params (dev_ctx);
-
-    return 1;
-}
-
-unsigned char _radio_dev_free (dev_ctx_T *dev_ctx) {
-    rtlsdr_dev_t *dev = dev_ctx->dev;
-
-    if (rtlsdr_close (dev) < 0)
-        return 0;
-    dev = NULL;
-
-    dev_ctx->dev = dev;
-
-    return 1;
-}
-
-void _radio_apply_params (dev_ctx_T *dev_ctx) {
-    rtlsdr_dev_t *dev = dev_ctx->dev;
-    Mode mode = dev_ctx->mode;
-    float freq = dev_ctx->freq;
-    int rate;
-
-    freq *= 1000000;
-    rate = ((1000000 / 200000) + 1) * 200000;
-
-    if (mode == FM)
-        freq += 16000;
-    freq += rate / 4;
-
-    rtlsdr_set_center_freq (dev, freq);
-    rtlsdr_set_sample_rate (dev, rate);
-
-    dev_ctx->dev = dev;
-}
-
-void _radio_start_threads (dev_ctx_T *dev_ctx) {
-    dev_ctx->dongle = (dongle_ctx*) malloc (sizeof(dongle_ctx));
-    dev_ctx->demod = (demod_ctx*) malloc (sizeof(demod_ctx));
-    dev_ctx->output = (output_ctx*) malloc (sizeof(output_ctx));
-
-    dongle_ctx *dongle = dev_ctx->dongle;
-    demod_ctx *demod = dev_ctx->demod;
-    output_ctx *output = dev_ctx->output;
-
-    pthread_rwlock_init (&demod->lck, NULL);
-    pthread_cond_init (&demod->ok, NULL);
-    pthread_mutex_init (&demod->ok_m, NULL);
-    pthread_rwlock_init (&output->lck, NULL);
-    pthread_cond_init (&output->ok, NULL);
-    pthread_mutex_init (&output->ok_m, NULL);
-
-    dev_ctx->should_run = 1;
-
-     /* dongle thread */
-    dongle->thr_finished = 0;
-    pthread_create (&dongle->thr, NULL, _dongle_thread_fn, (void*)dev_ctx);
-
-     /* demod thread */
-    demod->pre_r = demod->pre_j = 0;
-    demod->now_r = demod->now_j = 0;
-    demod->index = demod->pre_index = demod->now_index = 0;
-    demod->thr_finished = 0;
-    pthread_create (&demod->thr, NULL, _demod_thread_fn, (void*)dev_ctx);
-
-     /* output thread */
-    output->thr_finished = 0;
-    pthread_create (&output->thr, NULL, _output_thread_fn, (void*)dev_ctx);
-}
-
-void _radio_stop_threads (dev_ctx_T *dev_ctx) {
-    rtlsdr_dev_t *dev = dev_ctx->dev;
-    dongle_ctx *dongle = dev_ctx->dongle;
-    demod_ctx *demod = dev_ctx->demod;
-    output_ctx *output = dev_ctx->output;
-
-    if (!dongle || !demod || !output)
-        return;
-
-     /* stop each "while" loop in threads */
-    dev_ctx->should_run = 0;
-
-    rtlsdr_cancel_async (dev);
-    pthread_signal (&demod->ok, &demod->ok_m);
-    pthread_signal (&output->ok, &output->ok_m);
-
-    while (!dongle->thr_finished ||
-           !demod->thr_finished ||
-           !output->thr_finished)
-        usleep (100000);
-
-    pthread_join (dongle->thr, NULL);
-    pthread_join (demod->thr, NULL);
-    pthread_join (output->thr, NULL);
-    pthread_rwlock_destroy (&demod->lck);
-    pthread_cond_destroy (&demod->ok);
-    pthread_mutex_destroy (&demod->ok_m);
-    pthread_rwlock_destroy (&output->lck);
-    pthread_cond_destroy (&output->ok);
-    pthread_mutex_destroy (&output->ok_m);
-
-    free (dongle); dev_ctx->dongle = NULL;
-    free (demod); dev_ctx->demod = NULL;
-    free (output); dev_ctx->output = NULL;
-}
-
- /* ---- LOCAL THREADED FUNCTIONS ---- */
-
-static void _rtlsdr_callback (unsigned char *buf, uint32_t len, void *ctx) {
-    dev_ctx_T *dev_ctx = (dev_ctx_T *)ctx;
-    dongle_ctx *dongle = dev_ctx->dongle;
-    demod_ctx *demod = dev_ctx->demod;
-    unsigned char tmp;
-    int i;
-
-    if (!dev_ctx->should_run)
-        return;
-
-     /* rotate 90° */
-    for (i = 0; i < (int)len; i += 8) {
-        tmp = 255 - buf[i+3];
-        buf[i+3] = buf[i+2];
-        buf[i+2] = tmp;
-
-        buf[i+4] = 255 - buf[i+4];
-        buf[i+5] = 255 - buf[i+5];
-
-        tmp = 255 - buf[i+6];
-        buf[i+6] = buf[i+7];
-        buf[i+7] = tmp;
-    }
-
-     /* write data */
-    for (i = 0; i < (int)len; i++)
-        dongle->buf[i] = (int16_t)buf[i] - 127;
-
-     /* lock demod thread, write to it, unlock */
-       pthread_rwlock_wrlock (&demod->lck);
-    memcpy (demod->buf, dongle->buf, 2 * len);
-    demod->buf_len = len;
-       pthread_rwlock_unlock (&demod->lck);
-       pthread_signal (&demod->ok, &demod->ok_m);
-}
- /**/
-static void* _dongle_thread_fn (void *ctx) {
-    dev_ctx_T *dev_ctx = (dev_ctx_T *)ctx;
-    dongle_ctx *dongle = dev_ctx->dongle;
-
-    rtlsdr_read_async (dev_ctx->dev, _rtlsdr_callback, dev_ctx, 0, 0);
-
-    dongle->thr_finished = 1;
-    return 0;
-}
-
-static void _lowpass_demod (void *ctx) {
-    demod_ctx *demod = (demod_ctx *)ctx;
-    int i=0, i2=0;
-
-    while (i < demod->buf_len) {
-        demod->now_r += demod->buf[i];
-        demod->now_j += demod->buf[i+1];
-        i += 2;
-        demod->index++;
-        if (demod->index < ((1000000 / 200000) + 1))
-            continue;
-        demod->buf[i2] = demod->now_r;
-        demod->buf[i2+1] = demod->now_j;
-        demod->index = 0;
-        demod->now_r = demod->now_j = 0;
-        i2 += 2;
-    }
-    demod->buf_len = i2;
-}
- /**/
-static void _lowpassreal_demod (void *ctx) {
-    demod_ctx *demod = (demod_ctx *)ctx;
-    int i=0, i2=0;
-    int fast = 200000;
-    int slow = 48000;
-
-    while (i < demod->res_len) {
-        demod->now_index += demod->res[i];
-        i++;
-        demod->pre_index += slow;
-        if (demod->pre_index < fast)
-            continue;
-        demod->res[i2] = (int16_t)(demod->now_index / (fast/slow));
-        demod->pre_index -= fast;
-        demod->now_index = 0;
-        i2 += 1;
-    }
-    demod->res_len = i2;
-}
- /**/
-static void _multiply (int ar, int aj, int br, int bj, int *cr, int *cj) {
-    *cr = ar*br - aj*bj;
-    *cj = aj*br + ar*bj;
-}
- /**/
-static int _polar_discriminant (int ar, int aj, int br, int bj) {
-    int cr, cj;
-    double angle;
-    _multiply (ar, aj, br, -bj, &cr, &cj);
-    angle = atan2 ((double)cj, (double)cr);
-    return (int)(angle / 3.14159 * (1<<14));
-}
- /**/
-static void _fm_demod (void *ctx) {
-    demod_ctx *demod = (demod_ctx *)ctx;
-    int16_t *buf = demod->buf;
-    int buf_len = demod->buf_len;
-    int pcm, i;
-
-    pcm = _polar_discriminant (buf[0], buf[1], demod->pre_r, demod->pre_j);
-    demod->res[0] = (int16_t)pcm;
-
-    for (i = 2; i < (buf_len-1); i += 2) {
-        pcm = _polar_discriminant (buf[i], buf[i+1], buf[i-2], buf[i-1]);
-        demod->res[i/2] = (int16_t)pcm;
-    }
-    demod->pre_r = buf[buf_len - 2];
-    demod->pre_j = buf[buf_len - 1];
-    demod->res_len = buf_len/2;
-}
- /**/
-static void _am_demod (void *ctx) {
-    demod_ctx *demod = (demod_ctx *)ctx;
-    int16_t *buf = demod->buf;
-    int buf_len = demod->buf_len;
-    int pcm, i;
-
-    for (i = 0; i < buf_len; i += 2) {
-        pcm = buf[i] * buf[i];
-        pcm += buf[i+1] * buf[i+1];
-        demod->res[i/2] = (int16_t)sqrt(pcm);
-    }
-    demod->res_len = buf_len/2;
-}
- /**/
-static void* _demod_thread_fn (void *ctx) {
-    dev_ctx_T *dev_ctx = (dev_ctx_T *)ctx;
-    demod_ctx *demod = dev_ctx->demod;
-    output_ctx *output = dev_ctx->output;
-
-    while(dev_ctx->should_run) {
-            pthread_wait (&demod->ok, &demod->ok_m);
-            pthread_rwlock_wrlock (&demod->lck);
-        _lowpass_demod (demod);
-        if (dev_ctx->mode == FM)
-            _fm_demod (demod);
-        else
-            _am_demod (demod);
-        _lowpassreal_demod (demod);
-           pthread_rwlock_unlock (&demod->lck);
-
-         /* lock demod thread, write to it, unlock */
-           pthread_rwlock_wrlock (&output->lck);
-        memcpy (output->buf, demod->res, 2 * demod->res_len);
-        output->buf_len = demod->res_len;
-           pthread_rwlock_unlock (&output->lck);
-           pthread_signal (&output->ok, &output->ok_m);
-    }
-
-    demod->thr_finished = 1;
-    return 0;
-}
-
-static void* _output_thread_fn (void *ctx) {
-    dev_ctx_T *dev_ctx = (dev_ctx_T *)ctx;
-    output_ctx *output = dev_ctx->output;
-    FILE *file;
-
-    file = fopen (AUDIO_BUFFER, "wb");
-
-    while (dev_ctx->should_run) {
-           pthread_wait (&output->ok, &output->ok_m);
-           pthread_rwlock_rdlock (&output->lck);
-           if (!dev_ctx->mute && file) {
-               fwrite (output->buf, 2, output->buf_len, file);
-               fflush (file);
-               fseek (file, 0, SEEK_SET);
-           }
-           pthread_rwlock_unlock (&output->lck);
-    }
-    if (file) fclose(file);
-    unlink (AUDIO_BUFFER);
-
-    output->thr_finished = 1;
-    return 0;
-}
diff --git a/plugins/radio/radio-rtlsdr.h b/plugins/radio/radio-rtlsdr.h
deleted file mode 100644
index 2308f27e..00000000
--- a/plugins/radio/radio-rtlsdr.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Manuel Bachmann"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RADIO_RTLSDR_H
-#define RADIO_RTLSDR_H
-
-/* -------------- RADIO RTLSDR DEFINITIONS ------------------ */
-
-#include <math.h>
-#include <pthread.h>
-#include <rtl-sdr.h>
-
-#include "radio-api.h"
-
-#define pthread_signal(n, m) pthread_mutex_lock(m); pthread_cond_signal(n); pthread_mutex_unlock(m)
-#define pthread_wait(n, m) pthread_mutex_lock(m); pthread_cond_wait(n, m); pthread_mutex_unlock(m)
-#define BUF_LEN 16*16384
-#define AUDIO_BUFFER "/tmp/audio_buf"
-
-typedef struct dongle_ctx dongle_ctx;
-typedef struct demod_ctx demod_ctx;
-typedef struct output_ctx output_ctx;
-typedef struct dev_ctx dev_ctx_T;
-
-struct dongle_ctx {
-    pthread_t thr;
-    unsigned char thr_finished;
-    uint16_t buf[BUF_LEN];
-    uint32_t buf_len;
-};
-
-struct demod_ctx {
-    pthread_t thr;
-    unsigned char thr_finished;
-    pthread_rwlock_t lck;
-    pthread_cond_t ok;
-    pthread_mutex_t ok_m;
-    int pre_r, pre_j, now_r, now_j, index;
-    int pre_index, now_index;
-    int16_t buf[BUF_LEN];
-    int buf_len;
-    int16_t res[BUF_LEN];
-    int res_len;
-};
-
-struct output_ctx {
-    pthread_t thr;
-    unsigned char thr_finished;
-    pthread_rwlock_t lck;
-    pthread_cond_t ok;
-    pthread_mutex_t ok_m;
-    int16_t buf[BUF_LEN];
-    int buf_len;
-};
-
-struct dev_ctx {
-    int used;  /* TODO: radio is free ??? */
-    rtlsdr_dev_t* dev;
-    Mode mode;
-    float freq;
-    unsigned char mute;
-    unsigned char should_run;
-     /* thread contexts */
-    dongle_ctx *dongle;
-    demod_ctx *demod;
-    output_ctx *output;
-};
-
-unsigned int _radio_dev_count (void);
-const char* _radio_dev_name (unsigned int);
-
-unsigned char _radio_on (unsigned int, radioCtxHandleT *);
-void _radio_off (unsigned int);
-void _radio_stop (unsigned int);
-void _radio_play (unsigned int);
-void _radio_set_mode (unsigned int, Mode);
-void _radio_set_freq (unsigned int, double);
-void _radio_set_mute (unsigned int, unsigned char);
-
-unsigned char _radio_dev_init (struct dev_ctx *, unsigned int);
-unsigned char _radio_dev_free (struct dev_ctx *);
-void _radio_apply_params (struct dev_ctx *);
-void _radio_start_threads (struct dev_ctx *);
-void _radio_stop_threads (struct dev_ctx *);
-
-#endif /* RADIO_RTLSDR_H */
diff --git a/plugins/samples/AuthLogin.c b/plugins/samples/AuthLogin.c
deleted file mode 100644
index efecf240..00000000
--- a/plugins/samples/AuthLogin.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Fulup Ar Foll"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <json-c/json.h>
-
-#include <afb/afb-plugin.h>
-
-// Dummy sample of Client Application Context
-typedef struct {
-  int  something;       
-  void *whateveryouwant;
-} MyClientApplicationHandle;
-
-
-// This function is call when Client Session Context is removed
-// Note: when freeCtxCB==NULL standard free/malloc is called
-static void clientContextFree(void *context) {
-    fprintf (stderr,"Plugin[token] Closing Session\n");
-    free (context);
-}
-
-// Request Creation of new context if it does not exist
-static void clientContextConnect (struct afb_req request)
-{
-    json_object *jresp;
-
-    // add an application specific client context to session
-    afb_req_context_set(request, malloc (sizeof (MyClientApplicationHandle)), clientContextFree);
-
-    // do something intelligent to check if we should or not update level of assurance from 0(anonymous) to 1(logged)
-    afb_req_session_set_LOA(request, 1);
-    
-    // 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"));
-
-    afb_req_success(request, jresp, NULL);
-    
-}
-
-// Before entering here token will be check and renew
-static void clientContextRefresh (struct afb_req request) {
-    json_object *jresp;
-
-  
-    jresp = json_object_new_object();
-    json_object_object_add(jresp, "token", json_object_new_string ("Token was refreshed"));              
-    
-    afb_req_success(request, jresp, NULL);
-}
-
-
-// Session token will we verified before entering here
-static void clientContextCheck (struct afb_req request) {
-    
-    json_object *jresp = json_object_new_object();    
-    json_object_object_add(jresp, "isvalid", json_object_new_boolean (TRUE));       
-        
-    afb_req_success(request, jresp, NULL);
-}
-
-
-// Close and Free context
-static void clientContextLogout (struct afb_req request) {
-    json_object *jresp;
-   
-    /* after this call token will be reset
-     *  - no further access to API will be possible 
-     *  - every context from any used plugin will be freed
-     */
-    
-    jresp = json_object_new_object();
-    json_object_object_add(jresp, "info", json_object_new_string ("Token and all resources are released"));
-    
-    // WARNING: if you free context resource manually here do not forget to set *request.context=NULL; 
-    afb_req_success(request, jresp, NULL);
-    
-    afb_req_session_set_LOA(request, 0);
-}
-// Close and Free context
-static void clientGetPing (struct afb_req request) {
-    static int count=0;
-    json_object *jresp;
-
-    jresp = json_object_new_object();
-    json_object_object_add(jresp, "count", json_object_new_int (count ++));
-    
-    afb_req_success(request, jresp, NULL);
-}
-
-
-static const struct AFB_verb_desc_v1 verbs[]= {
-  {"ping"    , AFB_SESSION_NONE                        , clientGetPing       ,"Ping Rest Test Service"},
-  {"connect" , AFB_SESSION_LOA_EQ_0 | AFB_SESSION_RENEW, clientContextConnect,"Connect/Login Client"},
-  {"refresh" , AFB_SESSION_LOA_GE_1 | AFB_SESSION_RENEW, clientContextRefresh,"Refresh Client Authentication Token"},
-  {"check"   , AFB_SESSION_LOA_GE_1                    , clientContextCheck  ,"Check Client Authentication Token"},
-  {"logout"  , AFB_SESSION_LOA_GE_1 | AFB_SESSION_CLOSE, clientContextLogout ,"Logout Client and Free resources"},
-  {NULL}
-};
-
-static const struct AFB_plugin plugin_desc = {
-	.type = AFB_PLUGIN_VERSION_1,
-	.v1 = {
-		.info = "Application Framework Binder Authentication sample",
-		.prefix = "auth",
-		.verbs = verbs
-	}
-};
-
-const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
-{
-	return &plugin_desc;
-}
diff --git a/plugins/samples/CMakeLists.txt b/plugins/samples/CMakeLists.txt
deleted file mode 100644
index eb6e0112..00000000
--- a/plugins/samples/CMakeLists.txt
+++ /dev/null
@@ -1,63 +0,0 @@
-
-INCLUDE_DIRECTORIES(${include_dirs})
-
-##################################################
-# AuthLogin
-##################################################
-ADD_LIBRARY(authLogin MODULE AuthLogin.c)
-SET_TARGET_PROPERTIES(authLogin PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
-)
-TARGET_LINK_LIBRARIES(authLogin ${link_libraries})
-INSTALL(TARGETS authLogin
-        LIBRARY DESTINATION ${plugin_install_dir})
-
-##################################################
-# DemoContext
-##################################################
-ADD_LIBRARY(demoContext MODULE DemoContext.c)
-SET_TARGET_PROPERTIES(demoContext PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
-)
-TARGET_LINK_LIBRARIES(demoContext ${link_libraries})
-INSTALL(TARGETS demoContext
-        LIBRARY DESTINATION ${plugin_install_dir})
-
-##################################################
-# DemoPost
-##################################################
-ADD_LIBRARY(demoPost MODULE DemoPost.c)
-SET_TARGET_PROPERTIES(demoPost PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
-)
-TARGET_LINK_LIBRARIES(demoPost ${link_libraries})
-INSTALL(TARGETS demoPost
-        LIBRARY DESTINATION ${plugin_install_dir})
-
-##################################################
-# HelloWorld
-##################################################
-ADD_LIBRARY(helloWorld MODULE HelloWorld.c)
-SET_TARGET_PROPERTIES(helloWorld PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
-)
-TARGET_LINK_LIBRARIES(helloWorld ${link_libraries})
-INSTALL(TARGETS helloWorld
-        LIBRARY DESTINATION ${plugin_install_dir})
-
-##################################################
-# tic-tac-toe
-##################################################
-ADD_LIBRARY(tic-tac-toe MODULE tic-tac-toe.c)
-SET_TARGET_PROPERTIES(tic-tac-toe PROPERTIES
-	PREFIX ""
-	LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/export.map"
-)
-TARGET_LINK_LIBRARIES(tic-tac-toe ${link_libraries})
-INSTALL(TARGETS tic-tac-toe
-        LIBRARY DESTINATION ${plugin_install_dir})
-
diff --git a/plugins/samples/DemoContext.c b/plugins/samples/DemoContext.c
deleted file mode 100644
index ef703759..00000000
--- a/plugins/samples/DemoContext.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Fulup Ar Foll"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <json-c/json.h>
-
-#include <afb/afb-plugin.h>
-
-typedef struct {
-  /* 
-   * client context is attached a session but private to a each plugin.
-   * Context is passed to each API under request->context
-   * 
-   * Note:
-   *  -client context is free when a session is closed. Developer should not
-   *   forget that even if context is private to each plugin, session is unique
-   *   to a client. When session close, every plugin are notified to free there
-   *   private context.
-   *  -by default standard "free" function from libc is used to free context.
-   *   Developer may define it own under plugin->freeCB. This call received
-   *   FreeCtxCb(void *ClientCtx, void*PluginHandle, char*SessionUUID) if
-   *   FreeCtxCb=(void*)-1 then context wont be free by session manager.
-   *  -when an API use AFB_SESSION_RESET this close the session and each plugin
-   *   will be notified to free ressources.
-   */
-    
-  int  count;
-  char *abcd;
-  
-} MyClientContextT;
-
-// This function is call at session open time. Any client trying to 
-// call it with an already open session will be denied.
-// Ex: http://localhost:1234/api/context/create?token=123456789
-static void myCreate (struct afb_req request)
-{
-    MyClientContextT *ctx = malloc (sizeof (MyClientContextT));
-
-    // store something in our plugin private client context
-    ctx->count = 0;
-    ctx->abcd  = "SomeThingUseful";        
-
-    afb_req_context_set(request, ctx, free);
-    afb_req_success_f(request, NULL, "SUCCESS: create client context for plugin [%s]", ctx->abcd);
-}
-
-// This function can only be called with a valid token. Token should be renew before
-// session timeout a standard renew api is avaliable at /api/token/renew this API
-// can be called automatically with <token-renew> HTML5 widget.
-// ex: http://localhost:1234/api/context/action?token=xxxxxx-xxxxxx-xxxxx-xxxxx-xxxxxx
-static void myAction (struct afb_req request)
-{
-    MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request);
-    
-    // store something in our plugin private client context
-    ctx->count++;
-    afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Check=[%d]\n", ctx->abcd, ctx->count);
-}
-
-// After execution of this function, client session will be close and if they
-// created a context [request->context != NULL] every plugins will be notified
-// that they should free context resources.
-// ex: http://localhost:1234/api/context/close?token=xxxxxx-xxxxxx-xxxxx-xxxxx-xxxxxx
-static void myClose (struct afb_req request)
-{
-    MyClientContextT *ctx = (MyClientContextT*) afb_req_context_get(request);
-    
-    // store something in our plugin private client context
-    ctx->count++;
-    afb_req_success_f(request, NULL, "SUCCESS: plugin [%s] Close=[%d]\n", ctx->abcd, ctx->count);
-}
-
-// Set the LOA
-static void setLOA(struct afb_req request, unsigned loa)
-{
-    if (afb_req_session_set_LOA(request, loa))
-	afb_req_success_f(request, NULL, "loa set to %u", loa);
-    else
-	afb_req_fail_f(request, "failed", "can't set loa to %u", loa);
-}
-
-static void clientSetLOA0(struct afb_req request)
-{
-    setLOA(request, 0);
-}
-
-static void clientSetLOA1(struct afb_req request)
-{
-    setLOA(request, 1);
-}
-
-static void clientSetLOA2(struct afb_req request)
-{
-    setLOA(request, 2);
-}
-
-static void clientSetLOA3(struct afb_req request)
-{
-    setLOA(request, 3);
-}
-
-static void clientCheckLOA(struct afb_req request)
-{
-    afb_req_success(request, NULL, "LOA checked and okay");
-}
-
-// NOTE: this sample does not use session to keep test a basic as possible
-//       in real application most APIs should be protected with AFB_SESSION_CHECK
-static const struct AFB_verb_desc_v1 verbs[]= {
-  {"create", AFB_SESSION_CREATE, myCreate  , "Create a new session"},
-  {"action", AFB_SESSION_CHECK , myAction  , "Use Session Context"},
-  {"close" , AFB_SESSION_CLOSE , myClose   , "Free Context"},
-  {"set_loa_0", AFB_SESSION_RENEW, clientSetLOA0       ,"Set level of assurance to 0"},
-  {"set_loa_1", AFB_SESSION_RENEW, clientSetLOA1       ,"Set level of assurance to 1"},
-  {"set_loa_2", AFB_SESSION_RENEW, clientSetLOA2       ,"Set level of assurance to 2"},
-  {"set_loa_3", AFB_SESSION_RENEW, clientSetLOA3       ,"Set level of assurance to 3"},
-  {"check_loa_ge_0", AFB_SESSION_LOA_GE_0, clientCheckLOA ,"Check whether level of assurance is greater or equal to 0"},
-  {"check_loa_ge_1", AFB_SESSION_LOA_GE_1, clientCheckLOA ,"Check whether level of assurance is greater or equal to 1"},
-  {"check_loa_ge_2", AFB_SESSION_LOA_GE_2, clientCheckLOA ,"Check whether level of assurance is greater or equal to 2"},
-  {"check_loa_ge_3", AFB_SESSION_LOA_GE_3, clientCheckLOA ,"Check whether level of assurance is greater or equal to 3"},
-  {"check_loa_le_0", AFB_SESSION_LOA_LE_0, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 0"},
-  {"check_loa_le_1", AFB_SESSION_LOA_LE_1, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 1"},
-  {"check_loa_le_2", AFB_SESSION_LOA_LE_2, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 2"},
-  {"check_loa_le_3", AFB_SESSION_LOA_LE_3, clientCheckLOA ,"Check whether level of assurance is lesser or equal to 3"},
-  {"check_loa_eq_0", AFB_SESSION_LOA_EQ_0, clientCheckLOA ,"Check whether level of assurance is equal to 0"},
-  {"check_loa_eq_1", AFB_SESSION_LOA_EQ_1, clientCheckLOA ,"Check whether level of assurance is equal to 1"},
-  {"check_loa_eq_2", AFB_SESSION_LOA_EQ_2, clientCheckLOA ,"Check whether level of assurance is equal to 2"},
-  {"check_loa_eq_3", AFB_SESSION_LOA_EQ_3, clientCheckLOA ,"Check whether level of assurance is equal to 3"},
-  {NULL}
-};
-
-static const struct AFB_plugin plugin_desc = {
-	.type = AFB_PLUGIN_VERSION_1,
-	.v1 = {
-		.info = "Sample of Client Context Usage",
-		.prefix = "context",
-		.verbs = verbs,
-	}
-};
-
-const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
-{
-	return &plugin_desc;
-}
-
diff --git a/plugins/samples/DemoPost.c b/plugins/samples/DemoPost.c
deleted file mode 100644
index b61b91c4..00000000
--- a/plugins/samples/DemoPost.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Fulup Ar Foll"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <json-c/json.h>
-
-#include <afb/afb-plugin.h>
-
-
-// Sample Generic Ping Debug API
-static void getPingTest(struct afb_req request)
-{
-    static int pingcount = 0;
-    json_object *query = afb_req_json(request);
-
-    afb_req_success_f(request, query, "Ping Binder Daemon count=%d", ++pingcount);
-}
-
-// With content-type=json data are directly avaliable in request->post->data
-static void GetJsonByPost (struct afb_req request)
-{
-    struct afb_arg arg;
-    json_object* jresp;
-    json_object *query = afb_req_json(request);
-
-    arg = afb_req_get(request, "");
-    jresp = arg.value ? json_tokener_parse(arg.value) : NULL;
-    afb_req_success_f(request, jresp, "GetJsonByPost query={%s}", json_object_to_json_string(query));
-}
-
-// Upload a file and execute a function when upload is done
-static void Uploads (struct afb_req request, const char *destination)
-{
-   struct afb_arg a = afb_req_get(request, "file");
-   if (a.value == NULL || *a.value == 0)
-     afb_req_fail(request, "failed", "no file selected");
-   else
-     afb_req_success_f(request, NULL, "uploaded file %s of path %s for destination %s", a.value, a.path, destination);
-}
-
-// Upload a file and execute a function when upload is done
-static void UploadAppli (struct afb_req request)
-{
-    Uploads(request, "applications");
-}
-
-// Simples Upload case just upload a file
-static void UploadMusic (struct afb_req request)
-{
-    Uploads(request, "musics");
-}
-
-// PostForm callback is called multiple times (one or each key within form, or once per file buffer)
-// When file has been fully uploaded call is call with item==NULL 
-static void UploadImage (struct afb_req request)
-{
-    Uploads(request, "images");
-}
-
-
-// NOTE: this sample does not use session to keep test a basic as possible
-//       in real application upload-xxx should be protected with AFB_SESSION_CHECK
-static const struct AFB_verb_desc_v1 verbs[]= {
-  {"ping"         , AFB_SESSION_NONE  , getPingTest    ,"Ping Rest Test Service"},
-  {"upload-json"  , AFB_SESSION_NONE  , GetJsonByPost  ,"Demo for Json Buffer on Post"},
-  {"upload-image" , AFB_SESSION_NONE  , UploadImage    ,"Demo for file upload"},
-  {"upload-music" , AFB_SESSION_NONE  , UploadMusic    ,"Demo for file upload"},
-  {"upload-appli" , AFB_SESSION_NONE  , UploadAppli    ,"Demo for file upload"},
-  {NULL}
-};
-
-static const struct AFB_plugin plugin_desc = {
-	.type = AFB_PLUGIN_VERSION_1,
-	.v1 = {
-		.info = "Sample with Post Upload Files",
-		.prefix = "post",
-		.verbs = verbs
-	}
-};
-
-const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
-{
-    return &plugin_desc;
-};
diff --git a/plugins/samples/HelloWorld.c b/plugins/samples/HelloWorld.c
deleted file mode 100644
index b6f49b78..00000000
--- a/plugins/samples/HelloWorld.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2015, 2016 "IoT.bzh"
- * Author "Fulup Ar Foll"
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <json-c/json.h>
-
-#include <afb/afb-plugin.h>
-
-const struct AFB_interface *interface;
-
-struct event
-{
-	struct event *next;
-	struct afb_event event;
-	char tag[1];
-};
-
-static struct event *events = 0;
-
-/* searchs the event of tag */
-static struct event *event_get(const char *tag)
-{
-	struct event *e = events;
-	while(e && strcmp(e->tag, tag))
-		e = e->next;
-	return e;
-}
-
-/* deletes the event of tag */
-static int event_del(const char *tag)
-{
-	struct event *e, **p;
-
-	/* check exists */
-	e = event_get(tag);
-	if (!e) return -1;
-
-	/* unlink */
-	p = &events;
-	while(*p != e) p = &(*p)->next;
-	*p = e->next;
-
-	/* destroys */
-	afb_event_drop(e->event);
-	free(e);
-	return 0;
-}
-
-/* creates the event of tag */
-static int event_add(const char *tag, const char *name)
-{
-	struct event *e;
-
-	/* check valid tag */
-	e = event_get(tag);
-	if (e) return -1;
-
-	/* creation */
-	e = malloc(strlen(tag) + sizeof *e);
-	if (!e) return -1;
-	strcpy(e->tag, tag);
-
-	/* make the event */
-	e->event = afb_daemon_make_event(interface->daemon, name);
-	if (!e->event.closure) { free(e); return -1; }
-
-	/* link */
-	e->next = events;
-	events = e;
-	return 0;
-}
-
-static int event_subscribe(struct afb_req request, const char *tag)
-{
-	struct event *e;
-	e = event_get(tag);
-	return e ? afb_req_subscribe(request, e->event) : -1;
-}
-
-static int event_unsubscribe(struct afb_req request, const char *tag)
-{
-	struct event *e;
-	e = event_get(tag);
-	return e ? afb_req_unsubscribe(request, e->event) : -1;
-}
-
-static int event_push(struct json_object *args, const char *tag)
-{
-	struct event *e;
-	e = event_get(tag);
-	return e ? afb_event_push(e->event, json_object_get(args)) : -1;
-}
-
-// Sample Generic Ping Debug API
-static void ping(struct afb_req request, json_object *jresp, const char *tag)
-{
-	static int pingcount = 0;
-	json_object *query = afb_req_json(request);
-	afb_req_success_f(request, jresp, "Ping Binder Daemon tag=%s count=%d query=%s", tag, ++pingcount, json_object_to_json_string(query));
-}
-
-static void pingSample (struct afb_req request)
-{
-	ping(request, json_object_new_string ("Some String"), "pingSample");
-}
-
-static void pingFail (struct afb_req request)
-{
-	afb_req_fail(request, "failed", "Ping Binder Daemon fails");
-}
-
-static void pingNull (struct afb_req request)
-{
-	ping(request, NULL, "pingNull");
-}
-
-static void pingBug (struct afb_req request)
-{
-	ping((struct afb_req){NULL,NULL,NULL}, NULL, "pingBug");
-}
-
-static void pingEvent(struct afb_req request)
-{
-	json_object *query = afb_req_json(request);
-	afb_daemon_broadcast_event(interface->daemon, "event", json_object_get(query));
-	ping(request, json_object_get(query), "event");
-}
-
-
-// For samples https://linuxprograms.wordpress.com/2010/05/20/json-c-libjson-tutorial/
-static void pingJson (struct afb_req request) {
-    json_object *jresp, *embed;    
-    
-    jresp = json_object_new_object();
-    json_object_object_add(jresp, "myString", json_object_new_string ("Some String"));
-    json_object_object_add(jresp, "myInt", json_object_new_int (1234));
-     
-    embed  = json_object_new_object();
-    json_object_object_add(embed, "subObjString", json_object_new_string ("Some String"));
-    json_object_object_add(embed, "subObjInt", json_object_new_int (5678));
-    
-    json_object_object_add(jresp,"eobj", embed);
-
-    ping(request, jresp, "pingJson");
-}
-
-static void subcallcb (void *prequest, int iserror, json_object *object)
-{
-	struct afb_req request = afb_req_unstore(prequest);
-	if (iserror)
-		afb_req_fail(request, "failed", json_object_to_json_string(object));
-	else
-		afb_req_success(request, object, NULL);
-	afb_req_unref(request);
-}
-
-static void subcall (struct afb_req request)
-{
-	const char *api = afb_req_value(request, "api");
-	const char *verb = afb_req_value(request, "verb");
-	const char *args = afb_req_value(request, "args");
-	json_object *object = api && verb && args ? json_tokener_parse(args) : NULL;
-
-	if (object == NULL)
-		afb_req_fail(request, "failed", "bad arguments");
-	else
-		afb_req_subcall(request, api, verb, object, subcallcb, afb_req_store(request));
-}
-
-static void eventadd (struct afb_req request)
-{
-	const char *tag = afb_req_value(request, "tag");
-	const char *name = afb_req_value(request, "name");
-
-	if (tag == NULL || name == NULL)
-		afb_req_fail(request, "failed", "bad arguments");
-	else if (0 != event_add(tag, name))
-		afb_req_fail(request, "failed", "creation error");
-	else
-		afb_req_success(request, NULL, NULL);
-}
-
-static void eventdel (struct afb_req request)
-{
-	const char *tag = afb_req_value(request, "tag");
-
-	if (tag == NULL)
-		afb_req_fail(request, "failed", "bad arguments");
-	else if (0 != event_del(tag))
-		afb_req_fail(request, "failed", "deletion error");
-	else
-		afb_req_success(request, NULL, NULL);
-}
-
-static void eventsub (struct afb_req request)
-{
-	const char *tag = afb_req_value(request, "tag");
-
-	if (tag == NULL)
-		afb_req_fail(request, "failed", "bad arguments");
-	else if (0 != event_subscribe(request, tag))
-		afb_req_fail(request, "failed", "subscription error");
-	else
-		afb_req_success(request, NULL, NULL);
-}
-
-static void eventunsub (struct afb_req request)
-{
-	const char *tag = afb_req_value(request, "tag");
-
-	if (tag == NULL)
-		afb_req_fail(request, "failed", "bad arguments");
-	else if (0 != event_unsubscribe(request, tag))
-		afb_req_fail(request, "failed", "unsubscription error");
-	else
-		afb_req_success(request, NULL, NULL);
-}
-
-static void eventpush (struct afb_req request)
-{
-	const char *tag = afb_req_value(request, "tag");
-	const char *data = afb_req_value(request, "data");
-	json_object *object = data ? json_tokener_parse(data) : NULL;
-
-	if (tag == NULL)
-		afb_req_fail(request, "failed", "bad arguments");
-	else if (0 > event_push(object, tag))
-		afb_req_fail(request, "failed", "push error");
-	else
-		afb_req_success(request, NULL, NULL);
-}
-
-// NOTE: this sample does not use session to keep test a basic as possible
-//       in real application most APIs should be protected with AFB_SESSION_CHECK
-static const struct AFB_verb_desc_v1 verbs[]= {
-  {"ping"     , AFB_SESSION_NONE, pingSample  , "Ping Application Framework"},
-  {"pingfail" , AFB_SESSION_NONE, pingFail    , "Fails"},
-  {"pingnull" , AFB_SESSION_NONE, pingNull    , "Return NULL"},
-  {"pingbug"  , AFB_SESSION_NONE, pingBug     , "Do a Memory Violation"},
-  {"pingJson" , AFB_SESSION_NONE, pingJson    , "Return a JSON object"},
-  {"pingevent", AFB_SESSION_NONE, pingEvent   , "Send an event"},
-  {"subcall",   AFB_SESSION_NONE, subcall     , "Call api/verb(args)"},
-  {"eventadd",  AFB_SESSION_NONE, eventadd    , "adds the event of 'name' for the 'tag'"},
-  {"eventdel",  AFB_SESSION_NONE, eventdel    , "deletes the event of 'tag'"},
-  {"eventsub",  AFB_SESSION_NONE, eventsub    , "subscribes to the event of 'tag'"},
-  {"eventunsub",AFB_SESSION_NONE, eventunsub  , "unsubscribes to the event of 'tag'"},
-  {"eventpush", AFB_SESSION_NONE, eventpush   , "pushs the event of 'tag' with the 'data'"},
-  {NULL}
-};
-
-static const struct AFB_plugin plugin_desc = {
-	.type = AFB_PLUGIN_VERSION_1,
-	.v1 = {
-		.info = "Minimal Hello World Sample",
-		.prefix = "hello",
-		.verbs = verbs
-	}
-};
-
-const struct AFB_plugin *pluginAfbV1Register (const struct AFB_interface *itf)
-{
-	interface = itf;
-	return &plugin_desc;
-}
diff --git a/plugins/samples/export.map b/plugins/samples/export.map
deleted file mode 100644
index e2da85ca..00000000
--- a/plugins/samples/export.map
+++ /dev/null
@@ -1 +0,0 @@
-{ global: pluginAfbV1Register; local: *; };
diff --git a/plugins/samples/tic-tac-toe.c b/plugins/samples/tic-tac-toe.c
deleted file mode 100644
index 31682d94..00000000
--- a/plugins/samples/tic-tac-toe.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author José Bollo <jose.bollo@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <json-c/json.h>
-
-#include <afb/afb-plugin.h>
-
-/*
- * the interface to afb-daemon
- */
-const struct AFB_interface *afbitf;
-
-/*
- * definition of waiters
- */
-struct waiter
-{
-	struct waiter *next;
-	struct afb_req req;
-};
-
-/*
- * definition of a board
- */
-struct board
-{
-	struct board *next;
-	int use_count;
-	int moves;
-	int history[9];
-	int id;
-	int level;
-	char board[9];
-	struct waiter *waiters;
-};
-
-/*
- * list of boards
- */
-static struct board *all_boards;
-
-/*
- * Searchs a board having the 'id'.
- * Returns it if found or NULL otherwise.
- */
-static struct board *search_board(int id)
-{
-	struct board *board = all_boards;
-	while (board != NULL && board->id != id)
-		board = board->next;
-	return board;
-}
-
-/*
- * Creates a new board and returns it.
- */
-static struct board *get_new_board()
-{
-	/* allocation */
-	struct board *board = calloc(1, sizeof *board);
-
-	/* initialisation */
-	memset(board->board, ' ', sizeof board->board);
-	board->use_count = 1;
-	board->level = 1;
-	board->moves = 0;
-	do {
-		board->id = (rand() >> 2) % 1000;
-	} while(board->id == 0 || search_board(board->id) != NULL);
-
-	/* link */
-	board->next = all_boards;
-	all_boards = board;
-	return board;
-}
-
-/*
- * Release a board
- */
-static void release_board(struct board *board)
-{
-	/* decrease the reference count ... */
-	if (--board->use_count == 0) {
-		/* ... no more use */
-		/* unlink from the list of boards */
-		struct board **prv = &all_boards;
-		while (*prv != NULL && *prv != board)
-			prv = &(*prv)->next;
-		if (*prv != NULL)
-			*prv = board->next;
-		/* release the used memory */
-		free(board);
-	}
-}
-
-/*
- * Checks who wins
- * Returns zero if there is no winner
- * Returns the char of the winner if a player won
- */
-static char winner(const char b[9])
-{
-	int i;
-	char c;
-
-	/* check diagonals */
-	c = b[4];
-	if (c != ' ') {
-		if (b[0] == c && b[8] == c)
-			return c;
-		if (b[2] == c && b[6] == c)
-			return c;
-	}
-
-	/* check lines */
-	for (i = 0 ; i <= 6 ; i += 3) {
-		c = b[i];
-		if (c != ' ' && b[i+1] == c && b[i+2] == c)
-			return c;
-	}
-
-	/* check columns */
-	for (i = 0 ; i <= 2 ; i++) {
-		c = b[i];
-		if (c != ' ' && b[i+3] == c && b[i+6] == c)
-			return c;
-	}
-
-	return 0;
-}
-
-/* get the color (X or 0) of the move of index 'move' */
-static char color(int move)
-{
-	return (move & 1) == 0 ? 'X' : '0';
-}
-
-/* adds the move to the board */
-static void add_move(struct board *board, int index)
-{
-	int imove = board->moves++;
-	board->history[imove] = index;
-	board->board[index] = color(imove);
-}
-
-/* get a random possible move index from the board described by 'b' */
-static int get_random_move(char b[9])
-{
-	int index = rand() % 9;
-	while (b[index] != ' ')
-		index = (index + 1) % 9;
-	return index;
-}
-
-/*
- * Scores the position described by 'b'
- * for the player of color 'c' using an analysis of 'depth'.
- * Returns 1 if player 'c' will win.
- * Returns -1 if opponent of player 'c' will win.
- * returns 0 otherwise.
- */
-static int score_position(char b[9], char c, int depth)
-{
-	int i, t, r;
-
-	/* check if winner */
-	if (winner(b) == c)
-		return 1;
-
-	/* when depth of analysis is reached return unknown case */
-	if (--depth == 0)
-		return 0;
-
-	/* switch to the opponent */
-	c = (char)('O' + 'X' - c);
-
-	/* inspect opponent moves */
-	r = 1;
-	for (i = 0 ; i < 9 ; i++) {
-		if (b[i] == ' ') {
-			b[i] = c;
-			t = score_position(b, c, depth);
-			b[i] = ' ';
-			if (t > 0)
-				return -1; /* opponent will win */
-
-			if (t == 0)
-				r = 0; /* something not clear */
-		}
-	}
-	return r;
-}
-
-/* get one move: return the computed index of the move */
-static int get_move(struct board *board)
-{
-	int index, depth, t, f;
-	char c;
-	char b[9];
-
-	/* compute the depth */
-	depth = board->level - 1;
-	if (board->moves + depth > 9)
-		depth = 9 - board->moves;
-
-	/* case of null depth */
-	if (depth == 0)
-		return get_random_move(board->board);
-
-	/* depth and more */
-	memcpy(b, board->board, 9);
-	c = color(board->moves);
-	f = 0;
-	for (index = 0 ; index < 9 ; index++) {
-		if (board->board[index] == ' ') {
-			board->board[index] = c;
-			t = score_position(board->board, c, depth);
-			board->board[index] = ' ';
-			if (t > 0)
-				return index;
-			if (t < 0)
-				b[index] = '+';
-			else
-				f = 1;
-		}
-	}
-	return get_random_move(f ? b : board->board);
-}
-
-/*
- * get the board description
- */
-static struct json_object *describe(struct board *board)
-{
-	int i;
-	char w;
-	struct json_object *resu, *arr;
-
-	resu = json_object_new_object();
-
-	json_object_object_add(resu, "boardid", json_object_new_int(board->id));
-	json_object_object_add(resu, "level", json_object_new_int(board->level));
-
-	arr = json_object_new_array();
-	json_object_object_add(resu, "board", arr);
-	for (i = 0 ; i < 9 ; i++)
-		json_object_array_add(arr,
-				json_object_new_string_len(&board->board[i], 1));
-
-	arr = json_object_new_array();
-	json_object_object_add(resu, "history", arr);
-	for (i = 0 ; i < board->moves ; i++)
-		json_object_array_add(arr, json_object_new_int(board->history[i]));
-
-	w = winner(board->board);
-	if (w)
-		json_object_object_add(resu, "winner", json_object_new_string_len(&w, 1));
-	else if (board->moves == 9)
-		json_object_object_add(resu, "winner", json_object_new_string("none"));
-
-	return resu;
-}
-
-/*
- * signals a change of the board
- */
-static void changed(struct board *board, const char *reason)
-{
-	struct waiter *waiter, *next;
-	struct json_object *description;
-
-	/* get the description */
-	description = describe(board);
-
-	waiter = board->waiters;
-	board->waiters = NULL;
-	while (waiter != NULL) {
-		next = waiter->next;
-		afb_req_success(waiter->req, json_object_get(description), reason);
-		afb_req_unref(waiter->req);
-		free(waiter);
-		waiter = next;
-	}
-
-	afb_daemon_broadcast_event(afbitf->daemon, reason, description);
-}
-
-/*
- * retrieves the board of the request
- */
-static inline struct board *board_of_req(struct afb_req req)
-{
-	return afb_req_context(req, (void*)get_new_board, (void*)release_board);
-}
-
-/*
- * start a new game
- */
-static void new(struct afb_req req)
-{
-	struct board *board;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'new' called for boardid %d", board->id);
-
-	/* reset the game */
-	memset(board->board, ' ', sizeof board->board);
-	board->moves = 0;
-
-	/* replies */
-	afb_req_success(req, NULL, NULL);
-
-	/* signal change */
-	changed(board, "new");
-}
-
-/*
- * get the board
- */
-static void board(struct afb_req req)
-{
-	struct board *board;
-	struct json_object *description;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'board' called for boardid %d", board->id);
-
-	/* describe the board */
-	description = describe(board);
-
-	/* send the board's description */
-	afb_req_success(req, description, NULL);
-}
-
-/*
- * move a piece
- */
-static void move(struct afb_req req)
-{
-	struct board *board;
-	int i;
-	const char *index;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'move' called for boardid %d", board->id);
-
-	/* retrieves the arguments of the move */
-	index = afb_req_value(req, "index");
-	i = index == NULL ? -1 : atoi(index);
-
-	/* checks validity of arguments */
-	if (i < 0 || i > 8) {
-		WARNING(afbitf, "can't move to %s: %s", index?:"?", index?"wrong value":"not set");
-		afb_req_fail(req, "error", "bad request");
-		return;
-	}
-
-	/* checks validity of the state */
-	if (winner(board->board) != 0) {
-		WARNING(afbitf, "can't move to %s: game is terminated", index);
-		afb_req_fail(req, "error", "game terminated");
-		return;
-	}
-
-	/* checks validity of the move */
-	if (board->board[i] != ' ') {
-		WARNING(afbitf, "can't move to %s: room occupied", index);
-		afb_req_fail(req, "error", "occupied");
-		return;
-	}
-
-	/* applies the move */
-	INFO(afbitf, "method 'move' for boardid %d, index=%s", board->id, index);
-	add_move(board, i);
-
-	/* replies */
-	afb_req_success(req, NULL, NULL);
-
-	/* signals change */
-	changed(board, "move");
-}
-
-/*
- * set the level
- */
-static void level(struct afb_req req)
-{
-	struct board *board;
-	int l;
-	const char *level;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'level' called for boardid %d", board->id);
-
-	/* retrieves the arguments */
-	level = afb_req_value(req, "level");
-	l = level == NULL ? -1 : atoi(level);
-
-	/* check validity of arguments */
-	if (l < 1 || l > 10) {
-		WARNING(afbitf, "can't set level to %s: %s", level?:"?", level?"wrong value":"not set");
-		afb_req_fail(req, "error", "bad request");
-		return;
-	}
-
-	/* set the level */
-	INFO(afbitf, "method 'level' for boardid %d, level=%d", board->id, l);
-	board->level = l;
-
-	/* replies */
-	afb_req_success(req, NULL, NULL);
-
-	/* signals change */
-	changed(board, "level");
-}
-
-/*
- * Join a board
- */
-static void join(struct afb_req req)
-{
-	struct board *board, *new_board;
-	const char *id;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'join' called for boardid %d", board->id);
-
-	/* retrieves the arguments */
-	id = afb_req_value(req, "boardid");
-	if (id == NULL)
-		goto bad_request;
-
-	/* none is a special id for joining a new session */
-	if (strcmp(id, "none") == 0) {
-		new_board = get_new_board();
-		goto success;
-	}
-
-	/* searchs the board to join */
-	new_board = search_board(atoi(id));
-	if (new_board == NULL)
-		goto bad_request;
-
-	/*
-	 * joining its board is stupid but possible
-	 * however when called with the same stored pointer
-	 * afb_req_context_set will not call the release
-	 * function 'release_board'. So the use_count MUST not
-	 * be incremented.
-	 */
-	if (new_board != board)
-		new_board->use_count++;
-
-success:
-	/* set the new board (and leaves the previous one) */
-	afb_req_context_set(req, new_board, (void*)release_board);
-
-	/* replies */
-	afb_req_success(req, NULL, NULL);
-	return;
-
-bad_request:
-	WARNING(afbitf, "can't join boardid %s: %s", id ? : "?", !id ? "no boardid" : atoi(id) ? "not found" : "bad boardid");
-	afb_req_fail(req, "error", "bad request");
-	return;
-}
-
-/*
- * Undo the last move
- */
-static void undo(struct afb_req req)
-{
-	struct board *board;
-	int i;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'undo' called for boardid %d", board->id);
-
-	/* checks the state */
-	if (board->moves == 0) {
-		WARNING(afbitf, "can't undo");
-		afb_req_fail(req, "error", "bad request");
-		return;
-	}
-
-	/* undo the last move */
-	i = board->history[--board->moves];
-	board->board[i] = ' ';
-
-	/* replies */
-	afb_req_success(req, NULL, NULL);
-
-	/* signals change */
-	changed(board, "undo");
-}
-
-/*
- * computer plays
- */
-static void play(struct afb_req req)
-{
-	struct board *board;
-	int index;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'play' called for boardid %d", board->id);
-
-	/* checks validity of the state */
-	if (winner(board->board) != 0 || board->moves == 9) {
-		WARNING(afbitf, "can't play: game terminated (%s)", winner(board->board) ? "has winner" : "no room left");
-		afb_req_fail(req, "error", "game terminated");
-		return;
-	}
-
-	/* gets the move and plays it */
-	index = get_move(board);
-	add_move(board, index);
-
-	/* replies */
-	afb_req_success(req, describe(board), NULL);
-
-	/* signals change */
-	changed(board, "play");
-}
-
-static void wait(struct afb_req req)
-{
-	struct board *board;
-	struct waiter *waiter;
-
-	/* retrieves the context for the session */
-	board = board_of_req(req);
-	INFO(afbitf, "method 'wait' called for boardid %d", board->id);
-
-	/* creates the waiter and enqueues it */
-	waiter = calloc(1, sizeof *waiter);
-	waiter->req = req;
-	waiter->next = board->waiters;
-	afb_req_addref(req);
-	board->waiters = waiter;
-}
-
-/*
- * array of the verbs exported to afb-daemon
- */
-static const struct AFB_verb_desc_v1 plugin_verbs[] = {
-   /* VERB'S NAME     SESSION MANAGEMENT          FUNCTION TO CALL  SHORT DESCRIPTION */
-   { .name= "new",   .session= AFB_SESSION_NONE, .callback= new,   .info= "Starts a new game" },
-   { .name= "play",  .session= AFB_SESSION_NONE, .callback= play,  .info= "Asks the server to play" },
-   { .name= "move",  .session= AFB_SESSION_NONE, .callback= move,  .info= "Tells the client move" },
-   { .name= "board", .session= AFB_SESSION_NONE, .callback= board, .info= "Get the current board" },
-   { .name= "level", .session= AFB_SESSION_NONE, .callback= level, .info= "Set the server level" },
-   { .name= "join",  .session= AFB_SESSION_CHECK,.callback= join,  .info= "Join a board" },
-   { .name= "undo",  .session= AFB_SESSION_NONE, .callback= undo,  .info= "Undo the last move" },
-   { .name= "wait",  .session= AFB_SESSION_NONE, .callback= wait,  .info= "Wait for a change" },
-   { .name= NULL } /* marker for end of the array */
-};
-
-/*
- * description of the plugin for afb-daemon
- */
-static const struct AFB_plugin plugin_description =
-{
-   /* description conforms to VERSION 1 */
-   .type= AFB_PLUGIN_VERSION_1,
-   .v1= {				/* fills the v1 field of the union when AFB_PLUGIN_VERSION_1 */
-      .prefix= "tictactoe",		/* the API name (or plugin name or prefix) */
-      .info= "Sample tac-tac-toe game",	/* short description of of the plugin */
-      .verbs = plugin_verbs		/* the array describing the verbs of the API */
-   }
-};
-
-/*
- * activation function for registering the plugin called by afb-daemon
- */
-const struct AFB_plugin *pluginAfbV1Register(const struct AFB_interface *itf)
-{
-   afbitf = itf;         // records the interface for accessing afb-daemon
-   return &plugin_description;  // returns the description of the plugin
-}
-
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6abc8736..915da89d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,7 +1,7 @@
 
 INCLUDE(FindPkgConfig)
 
-ADD_DEFINITIONS(-DPLUGIN_INSTALL_DIR="${plugin_install_dir}")
+ADD_DEFINITIONS(-DBINDING_INSTALL_DIR="${binding_install_dir}")
 
 CHECK_INCLUDE_FILES(magic.h HAVE_MAGIC_H)
 CHECK_LIBRARY_EXISTS(magic magic_load "" HAVE_LIBMAGIC_SO)
diff --git a/src/afb-api-dbus.c b/src/afb-api-dbus.c
index 4c5d9083..b781f54f 100644
--- a/src/afb-api-dbus.c
+++ b/src/afb-api-dbus.c
@@ -26,7 +26,6 @@
 #include <systemd/sd-bus.h>
 #include <json-c/json.h>
 
-#include <afb/afb-plugin.h>
 #include <afb/afb-req-itf.h>
 
 #include "afb-common.h"
diff --git a/src/afb-api-so.c b/src/afb-api-so.c
index 168d9a6d..39a6e9b1 100644
--- a/src/afb-api-so.c
+++ b/src/afb-api-so.c
@@ -16,7 +16,7 @@
  */
 
 #define _GNU_SOURCE
-#define NO_PLUGIN_VERBOSE_MACRO
+#define NO_BINDING_VERBOSE_MACRO
 
 #include <stdio.h>
 #include <assert.h>
@@ -28,7 +28,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <afb/afb-plugin.h>
+#include <afb/afb-binding.h>
 #include <afb/afb-req-itf.h>
 #include <afb/afb-event-itf.h>
 
@@ -43,14 +43,14 @@
 #include "verbose.h"
 
 /*
- * Description of a plugin
+ * Description of a binding
  */
 struct api_so_desc {
-	struct AFB_plugin *plugin;	/* descriptor */
+	struct afb_binding *binding;	/* descriptor */
 	size_t apilength;		/* length of the API name */
 	void *handle;			/* context of dlopen */
 	struct afb_svc *service;	/* handler for service started */
-	struct AFB_interface interface;	/* interface for the plugin */
+	struct afb_binding_interface interface;	/* interface for the binding */
 };
 
 struct monitoring {
@@ -58,9 +58,9 @@ struct monitoring {
 	void (*action)(struct afb_req);
 };
 
-static const char plugin_register_function_v1[] = "pluginAfbV1Register";
-static const char plugin_service_init_function_v1[] = "pluginAfbV1ServiceInit";
-static const char plugin_service_event_function_v1[] = "pluginAfbV1ServiceEvent";
+static const char binding_register_function_v1[] = "afbBindingV1Register";
+static const char binding_service_init_function_v1[] = "afbBindingV1ServiceInit";
+static const char binding_service_event_function_v1[] = "afbBindingV1ServiceEvent";
 
 static int api_timeout = 15;
 
@@ -83,10 +83,10 @@ static struct afb_event afb_api_so_event_make(struct api_so_desc *desc, const ch
 	char *event;
 
 	/* makes the event name */
-	assert(desc->plugin != NULL);
+	assert(desc->binding != NULL);
 	length = strlen(name);
 	event = alloca(length + 2 + desc->apilength);
-	memcpy(event, desc->plugin->v1.prefix, desc->apilength);
+	memcpy(event, desc->binding->v1.prefix, desc->apilength);
 	event[desc->apilength] = '/';
 	memcpy(event + desc->apilength + 1, name, length + 1);
 
@@ -100,10 +100,10 @@ static int afb_api_so_event_broadcast(struct api_so_desc *desc, const char *name
 	char *event;
 
 	/* makes the event name */
-	assert(desc->plugin != NULL);
+	assert(desc->binding != NULL);
 	length = strlen(name);
 	event = alloca(length + 2 + desc->apilength);
-	memcpy(event, desc->plugin->v1.prefix, desc->apilength);
+	memcpy(event, desc->binding->v1.prefix, desc->apilength);
 	event[desc->apilength] = '/';
 	memcpy(event + desc->apilength + 1, name, length + 1);
 
@@ -117,7 +117,7 @@ static void afb_api_so_vverbose(struct api_so_desc *desc, int level, const char
 	if (vasprintf(&p, fmt, args) < 0)
 		vverbose(level, file, line, fmt, args);
 	else {
-		verbose(level, file, line, "%s {plugin %s}", p, desc->plugin->v1.prefix);
+		verbose(level, file, line, "%s {binding %s}", p, desc->binding->v1.prefix);
 		free(p);
 	}
 }
@@ -130,7 +130,7 @@ static void monitored_call(int signum, struct monitoring *data)
 		data->action(data->req);
 }
 
-static void call_check(struct afb_req req, struct afb_context *context, const struct AFB_verb_desc_v1 *verb)
+static void call_check(struct afb_req req, struct afb_context *context, const struct afb_verb_desc_v1 *verb)
 {
 	struct monitoring data;
 
@@ -184,15 +184,15 @@ static void call_check(struct afb_req req, struct afb_context *context, const st
 
 static void call(struct api_so_desc *desc, struct afb_req req, struct afb_context *context, const char *verb, size_t lenverb)
 {
-	const struct AFB_verb_desc_v1 *v;
+	const struct afb_verb_desc_v1 *v;
 
-	v = desc->plugin->v1.verbs;
+	v = desc->binding->v1.verbs;
 	while (v->name && (strncasecmp(v->name, verb, lenverb) || v->name[lenverb]))
 		v++;
 	if (v->name)
 		call_check(req, context, v);
 	else
-		afb_req_fail_f(req, "unknown-verb", "verb %.*s unknown within api %s", (int)lenverb, verb, desc->plugin->v1.prefix);
+		afb_req_fail_f(req, "unknown-verb", "verb %.*s unknown within api %s", (int)lenverb, verb, desc->binding->v1.prefix);
 }
 
 static int service_start(struct api_so_desc *desc, int share_session, int onneed)
@@ -207,28 +207,28 @@ static int service_start(struct api_so_desc *desc, int share_session, int onneed
 			return 0;
 
 		/* already started: it is an error */
-		ERROR("Service %s already started", desc->plugin->v1.prefix);
+		ERROR("Service %s already started", desc->binding->v1.prefix);
 		return -1;
 	}
 
 	/* get the initialisation */
-	init = dlsym(desc->handle, plugin_service_init_function_v1);
+	init = dlsym(desc->handle, binding_service_init_function_v1);
 	if (init == NULL) {
 		/* not an error when onneed */
 		if (onneed != 0)
 			return 0;
 
 		/* no initialisation method */
-		ERROR("Binding %s is not a service", desc->plugin->v1.prefix);
+		ERROR("Binding %s is not a service", desc->binding->v1.prefix);
 		return -1;
 	}
 
 	/* get the event handler if any */
-	onevent = dlsym(desc->handle, plugin_service_event_function_v1);
+	onevent = dlsym(desc->handle, binding_service_event_function_v1);
 	desc->service = afb_svc_create(share_session, init, onevent);
 	if (desc->service == NULL) {
 		/* starting error */
-		ERROR("Starting service %s failed", desc->plugin->v1.prefix);
+		ERROR("Starting service %s failed", desc->binding->v1.prefix);
 		return -1;
 	}
 
@@ -240,28 +240,28 @@ void afb_api_so_set_timeout(int to)
 	api_timeout = to;
 }
 
-int afb_api_so_add_plugin(const char *path)
+int afb_api_so_add_binding(const char *path)
 {
 	int rc;
 	void *handle;
 	struct api_so_desc *desc;
-	struct AFB_plugin *(*pluginAfbV1RegisterFct) (const struct AFB_interface *interface);
+	struct afb_binding *(*register_function) (const struct afb_binding_interface *interface);
 
-	// This is a loadable library let's check if it's a plugin
+	// This is a loadable library let's check if it's a binding
 	rc = 0;
 	handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
 	if (handle == NULL) {
-		ERROR("plugin [%s] not loadable", path);
+		ERROR("binding [%s] not loadable", path);
 		goto error;
 	}
 
 	/* retrieves the register function */
-	pluginAfbV1RegisterFct = dlsym(handle, plugin_register_function_v1);
-	if (!pluginAfbV1RegisterFct) {
-		ERROR("plugin [%s] is not an AFB plugin", path);
+	register_function = dlsym(handle, binding_register_function_v1);
+	if (!register_function) {
+		ERROR("binding [%s] is not an AFB binding", path);
 		goto error2;
 	}
-	INFO("plugin [%s] is a valid AFB plugin", path);
+	INFO("binding [%s] is a valid AFB binding", path);
 	rc = -1;
 
 	/* allocates the description */
@@ -278,46 +278,46 @@ int afb_api_so_add_plugin(const char *path)
 	desc->interface.daemon.itf = &daemon_itf;
 	desc->interface.daemon.closure = desc;
 
-	/* init the plugin */
-	NOTICE("plugin [%s] calling registering function %s", path, plugin_register_function_v1);
-	desc->plugin = pluginAfbV1RegisterFct(&desc->interface);
-	if (desc->plugin == NULL) {
-		ERROR("plugin [%s] register function failed. continuing...", path);
+	/* init the binding */
+	NOTICE("binding [%s] calling registering function %s", path, binding_register_function_v1);
+	desc->binding = register_function(&desc->interface);
+	if (desc->binding == NULL) {
+		ERROR("binding [%s] register function failed. continuing...", path);
 		goto error3;
 	}
 
 	/* check the returned structure */
-	if (desc->plugin->type != AFB_PLUGIN_VERSION_1) {
-		ERROR("plugin [%s] invalid type %d...", path, desc->plugin->type);
+	if (desc->binding->type != AFB_BINDING_VERSION_1) {
+		ERROR("binding [%s] invalid type %d...", path, desc->binding->type);
 		goto error3;
 	}
-	if (desc->plugin->v1.prefix == NULL || *desc->plugin->v1.prefix == 0) {
-		ERROR("plugin [%s] bad prefix...", path);
+	if (desc->binding->v1.prefix == NULL || *desc->binding->v1.prefix == 0) {
+		ERROR("binding [%s] bad prefix...", path);
 		goto error3;
 	}
-	if (!afb_apis_is_valid_api_name(desc->plugin->v1.prefix)) {
-		ERROR("plugin [%s] invalid prefix...", path);
+	if (!afb_apis_is_valid_api_name(desc->binding->v1.prefix)) {
+		ERROR("binding [%s] invalid prefix...", path);
 		goto error3;
 	}
-	if (desc->plugin->v1.info == NULL || *desc->plugin->v1.info == 0) {
-		ERROR("plugin [%s] bad description...", path);
+	if (desc->binding->v1.info == NULL || *desc->binding->v1.info == 0) {
+		ERROR("binding [%s] bad description...", path);
 		goto error3;
 	}
-	if (desc->plugin->v1.verbs == NULL) {
-		ERROR("plugin [%s] no APIs...", path);
+	if (desc->binding->v1.verbs == NULL) {
+		ERROR("binding [%s] no APIs...", path);
 		goto error3;
 	}
 
-	/* records the plugin */
-	desc->apilength = strlen(desc->plugin->v1.prefix);
-	if (afb_apis_add(desc->plugin->v1.prefix, (struct afb_api){
+	/* records the binding */
+	desc->apilength = strlen(desc->binding->v1.prefix);
+	if (afb_apis_add(desc->binding->v1.prefix, (struct afb_api){
 			.closure = desc,
 			.call = (void*)call,
 			.service_start = (void*)service_start }) < 0) {
-		ERROR("plugin [%s] can't be registered...", path);
+		ERROR("binding [%s] can't be registered...", path);
 		goto error3;
 	}
-	NOTICE("plugin %s loaded with API prefix %s", path, desc->plugin->v1.prefix);
+	NOTICE("binding %s loaded with API prefix %s", path, desc->binding->v1.prefix);
 	return 0;
 
 error3:
@@ -337,10 +337,10 @@ static int adddirs(char path[PATH_MAX], size_t end)
 	/* open the DIR now */
 	dir = opendir(path);
 	if (dir == NULL) {
-		ERROR("can't scan plugin directory %s, %m", path);
+		ERROR("can't scan binding directory %s, %m", path);
 		return -1;
 	}
-	INFO("Scanning dir=[%s] for plugins", path);
+	INFO("Scanning dir=[%s] for bindings", path);
 
 	/* scan each entry */
 	if (end)
@@ -352,7 +352,7 @@ static int adddirs(char path[PATH_MAX], size_t end)
 
 		len = strlen(ent.d_name);
 		if (len + end >= PATH_MAX) {
-			ERROR("path too long while scanning plugins for %s", ent.d_name);
+			ERROR("path too long while scanning bindings for %s", ent.d_name);
 			continue;
 		}
 		memcpy(&path[end], ent.d_name, len+1);
@@ -369,7 +369,7 @@ static int adddirs(char path[PATH_MAX], size_t end)
 			/* case of files */
 			if (!strstr(ent.d_name, ".so"))
 				continue;
-			if (afb_api_so_add_plugin(path) < 0)
+			if (afb_api_so_add_binding(path) < 0)
 				return -1;
 		}
 	}
@@ -399,13 +399,13 @@ int afb_api_so_add_path(const char *path)
 
 	rc = stat(path, &st);
 	if (rc < 0)
-		ERROR("Invalid plugin path [%s]: %m", path);
+		ERROR("Invalid binding path [%s]: %m", path);
 	else if (S_ISDIR(st.st_mode))
 		rc = afb_api_so_add_directory(path);
 	else if (strstr(path, ".so"))
-		rc = afb_api_so_add_plugin(path);
+		rc = afb_api_so_add_binding(path);
 	else
-		INFO("not a plugin [%s], skipped", path);
+		INFO("not a binding [%s], skipped", path);
 	return rc;
 }
 
diff --git a/src/afb-api-so.h b/src/afb-api-so.h
index 143b7a05..d2ffbc8f 100644
--- a/src/afb-api-so.h
+++ b/src/afb-api-so.h
@@ -20,7 +20,7 @@
 
 extern void afb_api_so_set_timeout(int to);
 
-extern int afb_api_so_add_plugin(const char *path);
+extern int afb_api_so_add_binding(const char *path);
 
 extern int afb_api_so_add_directory(const char *path);
 
diff --git a/src/main.c b/src/main.c
index ce957352..7c457217 100644
--- a/src/main.c
+++ b/src/main.c
@@ -17,7 +17,7 @@
  */
 
 #define _GNU_SOURCE
-#define NO_PLUGIN_VERBOSE_MACRO
+#define NO_BINDING_VERBOSE_MACRO
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -42,10 +42,10 @@
 #include "verbose.h"
 #include "afb-common.h"
 
-#include <afb/afb-plugin.h>
+#include <afb/afb-binding.h>
 
-#if !defined(PLUGIN_INSTALL_DIR)
-#error "you should define PLUGIN_INSTALL_DIR"
+#if !defined(BINDING_INSTALL_DIR)
+#error "you should define BINDING_INSTALL_DIR"
 #endif
 
 #define AFB_VERSION    "0.5"
@@ -77,7 +77,7 @@
 
 #define DBUS_CLIENT        20
 #define DBUS_SERVICE       21
-#define SO_PLUGIN          22
+#define SO_BINDING         22
 
 #define SET_SESSIONMAX     23
 
@@ -103,13 +103,13 @@ static  AFB_options cliOptions [] = {
   {SET_ROOT_API     ,1,"rootapi"         , "HTML Root API URL [default /api]"},
   {SET_ALIAS        ,1,"alias"           , "Muliple url map outside of rootdir [eg: --alias=/icons:/usr/share/icons]"},
   
-  {SET_APITIMEOUT   ,1,"apitimeout"      , "Plugin API timeout in seconds [default 10]"},
+  {SET_APITIMEOUT   ,1,"apitimeout"      , "Binding API timeout in seconds [default 10]"},
   {SET_CNTXTIMEOUT  ,1,"cntxtimeout"     , "Client Session Context Timeout [default 900]"},
   {SET_CACHE_TIMEOUT,1,"cache-eol"       , "Client cache end of live [default 3600]"},
   
   {SET_SESSION_DIR  ,1,"sessiondir"      , "Sessions file path [default rootdir/sessions]"},
 
-  {SET_LDPATH       ,1,"ldpaths"         , "Load Plugins from dir1:dir2:... [default = PLUGIN_INSTALL_DIR"},
+  {SET_LDPATH       ,1,"ldpaths"         , "Load bindingss from dir1:dir2:... [default = "BINDING_INSTALL_DIR"]"},
   {SET_AUTH_TOKEN   ,1,"token"           , "Initial Secret [default=no-session, --token="" for session without authentication]"},
   
   {DISPLAY_VERSION  ,0,"version"         , "Display version and copyright"},
@@ -120,7 +120,7 @@ static  AFB_options cliOptions [] = {
 
   {DBUS_CLIENT      ,1,"dbus-client"     , "bind to an afb service through dbus"},
   {DBUS_SERVICE     ,1,"dbus-server"     , "provides an afb service through dbus"},
-  {SO_PLUGIN        ,1,"plugin"          , "load the plugin of path"},
+  {SO_BINDING       ,1,"binding"         , "load the binding of path"},
 
   {SET_SESSIONMAX   ,1,"session-max"     , "max count of session simultaneously [default 10]"},
 
@@ -164,7 +164,7 @@ static void printHelp(FILE *file, const char *name)
          fprintf (file, "  --%-15s %s\n", command, cliOptions[ind].help);
       }
     }
-    fprintf (file, "Example:\n  %s\\\n  --verbose --port=1234 --token='azerty' --ldpaths=build/plugins:/usr/lib64/agl/plugins\n", name);
+    fprintf (file, "Example:\n  %s\\\n  --verbose --port=1234 --token='azerty' --ldpaths=build/bindings:/usr/lib64/agl/bindings\n", name);
 }
 
 // load config from disk and merge with CLI option
@@ -174,7 +174,7 @@ static void config_set_default (struct afb_config * config)
    if (config->httpdPort == 0)
 	config->httpdPort = 1234;
    
-   // default Plugin API timeout
+   // default binding API timeout
    if (config->apiTimeout == 0)
 	config->apiTimeout = DEFLT_API_TIMEOUT;
    
@@ -213,7 +213,7 @@ static void config_set_default (struct afb_config * config)
        config->rootapi = "/api";
 
    if  (config->ldpaths == NULL)
-       config->ldpaths = PLUGIN_INSTALL_DIR;
+       config->ldpaths = BINDING_INSTALL_DIR;
 
    // if no session dir create a default path from rootdir
    if  (config->sessiondir == NULL) {
@@ -384,7 +384,7 @@ static void parse_arguments(int argc, char *argv[], struct afb_config *config)
 
     case DBUS_CLIENT:
     case DBUS_SERVICE:
-    case SO_PLUGIN:
+    case SO_BINDING:
        if (optarg == 0) goto needValueForOption;
        add_item(config, optc, optarg);
        break;
@@ -559,9 +559,9 @@ static void start_items(struct afb_config_item *item)
 	exit(1);
       }
       break;
-    case SO_PLUGIN:
-      if (afb_api_so_add_plugin(item->value) < 0) {
-        ERROR("can't start the plugin of path %s",item->value);
+    case SO_BINDING:
+      if (afb_api_so_add_binding(item->value) < 0) {
+        ERROR("can't start the binding of path %s",item->value);
 	exit(1);
       }
       break;
@@ -601,7 +601,7 @@ int main(int argc, char *argv[])  {
   afb_api_so_set_timeout(config->apiTimeout);
   if (config->ldpaths) {
     if (afb_api_so_add_pathset(config->ldpaths) < 0) {
-      ERROR("initialisation of plugins within %s failed", config->ldpaths);
+      ERROR("initialisation of bindings within %s failed", config->ldpaths);
       exit(1);
     }
   }
-- 
cgit