aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ALSA-afb/Alsa-ApiHat.h2
-rw-r--r--ALSA-afb/CMakeLists.txt2
-rw-r--r--Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c135
-rw-r--r--Audio-Common/CMakeLists.txt (renamed from Shared-Interface/CMakeLists.txt)4
-rw-r--r--Audio-Common/audio-common.c (renamed from Shared-Interface/audio-interface.c)2
-rw-r--r--Audio-Common/audio-common.h (renamed from Shared-Interface/audio-interface.h)0
-rw-r--r--Audio-Common/wrap-json.c939
-rw-r--r--Audio-Common/wrap-json.h46
-rw-r--r--Audio-Common/wrap-json.md305
-rw-r--r--Controler-afb/CMakeLists.txt (renamed from PolicyCtl-afb/CMakeLists.txt)12
-rw-r--r--Controler-afb/ctl-apidef.h128
-rw-r--r--Controler-afb/ctl-apidef.json281
-rw-r--r--Controler-afb/ctl-binding.c74
-rw-r--r--Controler-afb/ctl-binding.h96
-rw-r--r--Controler-afb/ctl-events.c (renamed from PolicyCtl-afb/polctl-binding.c)101
-rw-r--r--Controler-afb/ctl-lua.c380
-rw-r--r--Controler-afb/ctl-policy.c196
-rw-r--r--HAL-afb/HAL-interface/CMakeLists.txt2
-rw-r--r--HAL-afb/HAL-interface/hal-interface.h2
-rw-r--r--HAL-afb/HDA-intel/CMakeLists.txt2
-rw-r--r--HAL-afb/HDA-intel/IntelHdaHAL.c2
-rw-r--r--HAL-afb/Jabra-Solemate/CMakeLists.txt2
-rw-r--r--HAL-afb/Jabra-Solemate/JabraUsbHAL.c2
-rw-r--r--HAL-afb/Scarlett-Focusrite/CMakeLists.txt2
-rw-r--r--HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c2
-rw-r--r--PolicyCtl-afb/polctl-apidef.h90
-rw-r--r--PolicyCtl-afb/polctl-apidef.json175
-rw-r--r--conf.d/cmake/config.cmake18
-rw-r--r--data/CMakeLists.txt46
-rw-r--r--data/helloworld-lua-script.lua41
-rw-r--r--data/onload-control-policy.json90
-rw-r--r--data/onload-control-script.lua51
-rw-r--r--htdocs/audio-control.html40
-rw-r--r--htdocs/docs/AAAA-architecture.odgbin27998 -> 28177 bytes
-rw-r--r--htdocs/docs/AAAA-architecture.pdfbin36392 -> 36596 bytes
-rw-r--r--htdocs/index.html2
-rw-r--r--nbproject/configurations.xml285
37 files changed, 3024 insertions, 533 deletions
diff --git a/ALSA-afb/Alsa-ApiHat.h b/ALSA-afb/Alsa-ApiHat.h
index 6e50e11..b05cfbe 100644
--- a/ALSA-afb/Alsa-ApiHat.h
+++ b/ALSA-afb/Alsa-ApiHat.h
@@ -22,7 +22,7 @@
#include <alsa/asoundlib.h>
#include <systemd/sd-event.h>
-#include "audio-interface.h"
+#include "audio-common.h"
typedef enum {
ACTION_SET,
diff --git a/ALSA-afb/CMakeLists.txt b/ALSA-afb/CMakeLists.txt
index 443acbd..876e837 100644
--- a/ALSA-afb/CMakeLists.txt
+++ b/ALSA-afb/CMakeLists.txt
@@ -32,7 +32,7 @@ PROJECT_TARGET_ADD(alsa-lowlevel)
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
- audio-interface
+ audio-common
${link_libraries}
)
diff --git a/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c b/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c
index ae2a5a3..501ebf9 100644
--- a/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c
+++ b/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c
@@ -62,7 +62,18 @@
#define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x
void OnRequestCB(void* UNUSED(handle) , const char* UNUSED(api), const char* UNUSED(verb), struct afb_wsj1_msg*UNUSED(msg)) {}
- typedef struct {
+typedef struct {
+ const char *api;
+ const char *verb;
+ long timeout;
+ char *query;
+
+ sd_event_source *evtSource;
+ char *callIdTag;
+ void *afbClient;
+} afbRequestT;
+
+typedef struct {
snd_pcm_t *pcm;
const char *uri;
struct afb_wsj1 *wsj1;
@@ -71,18 +82,10 @@ void OnRequestCB(void* UNUSED(handle) , const char* UNUSED(api), const char* UNU
sem_t semaphore;
int count;
int error;
+ afbRequestT **request;
} afbClientT;
-typedef struct {
- const char *api;
- const char *verb;
- long timeout;
- char *query;
-
- sd_event_source *evtSource;
- char *callIdTag;
- afbClientT *afbClient;
-} afbRequestT;
+
static void *LoopInThread(void *handle) {
afbClientT *afbClient = (afbClientT*) handle;
@@ -110,6 +113,11 @@ static void OnHangupCB(void *handle, struct afb_wsj1 *wsj1) {
if (err) exit(1);
}
+typedef enum {
+ HOOK_INSTALL,
+ HOOK_CLOSE,
+} hookActionT;
+
// supported action
typedef enum {
ACTION_PAUSE,
@@ -201,8 +209,9 @@ static struct afb_wsj1_itf itf = {
void OnResponseCB(void *handle, struct afb_wsj1_msg *msg) {
afbRequestT *afbRequest= (afbRequestT*)handle;
+ afbClientT *afbClient=(afbClientT*)afbRequest->afbClient;
- if (afbRequest->afbClient->verbose) printf("ON-RESPONSE call=%s response=%s\n", afbRequest->callIdTag, afb_wsj1_msg_object_s(msg));
+ if (afbClient->verbose) printf("ON-RESPONSE call=%s response=%s\n", afbRequest->callIdTag, afb_wsj1_msg_object_s(msg));
// Cancel timeout for this request
sd_event_source_unref(afbRequest->evtSource);
@@ -210,18 +219,18 @@ void OnResponseCB(void *handle, struct afb_wsj1_msg *msg) {
if (! afb_wsj1_msg_is_reply_ok(msg)) goto OnErrorExit;
// When not more waiting call release semaphore
- afbRequest->afbClient->count--;
- if (afbRequest->afbClient->count == 0) {
- if (afbRequest->afbClient->verbose) printf("ON-RESPONSE No More Waiting Request\n");
- afbRequest->afbClient->error=0;
- sem_post (&afbRequest->afbClient->semaphore);
+ afbClient->count--;
+ if (afbClient->count == 0) {
+ if (afbClient->verbose) printf("ON-RESPONSE No More Waiting Request\n");
+ afbClient->error=0;
+ sem_post (&afbClient->semaphore);
}
return;
OnErrorExit:
fprintf(stderr, "ON-RESPONSE ERROR call=%s response=%s\n", afbRequest->callIdTag, afb_wsj1_msg_object_s(msg));
- afbRequest->afbClient->error=1;
- sem_post (&afbRequest->afbClient->semaphore);
+ afbClient->error=1;
+ sem_post (&afbClient->semaphore);
}
int OnTimeoutCB (sd_event_source* source, uint64_t timer, void* handle) {
@@ -237,9 +246,10 @@ int OnTimeoutCB (sd_event_source* source, uint64_t timer, void* handle) {
}
// Call AGL binder asynchronously by with a timeout
-static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int count) {
+static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int count, hookActionT action) {
uint64_t usec;
int err;
+ const char *query;
// create a unique tag for request
(void) asprintf(&afbRequest->callIdTag, "%d:%s/%s", count, afbRequest->api, afbRequest->verb);
@@ -248,7 +258,9 @@ static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int c
sd_event_now(afbClient->sdLoop, CLOCK_MONOTONIC, &usec);
sd_event_add_time(afbClient->sdLoop, &afbRequest->evtSource, CLOCK_MONOTONIC, usec+afbRequest->timeout*1000, 250, OnTimeoutCB, afbClient);
- err = afb_wsj1_call_s(afbClient->wsj1, afbRequest->api, afbRequest->verb, afbRequest->query, OnResponseCB, afbRequest);
+ if (action == HOOK_INSTALL) query=afbRequest->query;
+ else query="{'closing': 1}";
+ err = afb_wsj1_call_s(afbClient->wsj1, afbRequest->api, afbRequest->verb, query, OnResponseCB, afbRequest);
if (err) goto OnErrorExit;
// save client handle in request
@@ -261,37 +273,40 @@ OnErrorExit:
return -1;
}
-static int LaunchCallRequest(afbClientT *afbClient, afbRequestT **afbRequest) {
+static int LaunchCallRequest(afbClientT *afbClient, hookActionT action) {
pthread_t tid;
int err, idx;
+ afbRequestT **afbRequest= afbClient->request;
+
+ if (action == HOOK_INSTALL) {
+ // init waiting counting semaphore
+ if (sem_init(&afbClient->semaphore, 1, 0) == -1) {
+ fprintf(stderr, "LaunchCallRequest: Fail Semaphore Init: %s\n", afbClient->uri);
+ }
- // init waiting counting semaphore
- if (sem_init(&afbClient->semaphore, 1, 0) == -1) {
- fprintf(stderr, "LaunchCallRequest: Fail Semaphore Init: %s\n", afbClient->uri);
- }
-
- // Create a main loop
- err = sd_event_default(&afbClient->sdLoop);
- if (err < 0) {
- fprintf(stderr, "LaunchCallRequest: Connection to default event loop failed: %s\n", strerror(-err));
- goto OnErrorExit;
+ // Create a main loop
+ err = sd_event_default(&afbClient->sdLoop);
+ if (err < 0) {
+ fprintf(stderr, "LaunchCallRequest: Connection to default event loop failed: %s\n", strerror(-err));
+ goto OnErrorExit;
+ }
+
+ // start a thread with a mainloop to monitor Audio-Agent
+ err = pthread_create(&tid, NULL, &LoopInThread, afbClient);
+ if (err) goto OnErrorExit;
+
+ // connect the websocket wsj1 to the uri given by the first argument
+ afbClient->wsj1 = afb_ws_client_connect_wsj1(afbClient->sdLoop, afbClient->uri, &itf, afbClient);
+ if (afbClient->wsj1 == NULL) {
+ fprintf(stderr, "LaunchCallRequest: Connection to %s failed\n", afbClient->uri);
+ goto OnErrorExit;
+ }
}
- // start a thread with a mainloop to monitor Audio-Agent
- err = pthread_create(&tid, NULL, &LoopInThread, afbClient);
- if (err) goto OnErrorExit;
-
- // connect the websocket wsj1 to the uri given by the first argument
- afbClient->wsj1 = afb_ws_client_connect_wsj1(afbClient->sdLoop, afbClient->uri, &itf, afbClient);
- if (afbClient->wsj1 == NULL) {
- fprintf(stderr, "LaunchCallRequest: Connection to %s failed\n", afbClient->uri);
- goto OnErrorExit;
- }
-
// send call request to audio-agent asynchronously (respond with thread mainloop context)
for (idx = 0; afbRequest[idx] != NULL; idx++) {
- err = CallWithTimeout(afbClient, afbRequest[idx], idx);
+ err = CallWithTimeout(afbClient, afbRequest[idx], idx, action);
if (err) {
fprintf(stderr, "LaunchCallRequest: Fail call %s//%s/%s&%s", afbClient->uri, afbRequest[idx]->api, afbRequest[idx]->verb, afbRequest[idx]->query);
goto OnErrorExit;
@@ -311,7 +326,25 @@ static int AlsaCloseHook(snd_pcm_hook_t *hook) {
afbClientT *afbClient = (afbClientT*) snd_pcm_hook_get_private (hook);
- if (afbClient->verbose) fprintf(stdout, "\nAlsaCloseHook pcm=%s\n", snd_pcm_name(afbClient->pcm));
+ // launch call request and create a waiting mainloop thread
+ int err = LaunchCallRequest(afbClient, HOOK_CLOSE);
+ if (err < 0) {
+ fprintf (stderr, "PCM Fail to Enter Mainloop\n");
+ goto OnErrorExit;
+ }
+
+ // wait for all call request to return
+ sem_wait(&afbClient->semaphore);
+ if (afbClient->error) {
+ fprintf (stderr, "AlsaCloseHook: Audio Agent Fail to respond\n");
+ goto OnErrorExit;
+ }
+
+ if (afbClient->verbose) fprintf(stdout, "\nAlsaHook Close Success PCM=%s URI=%s\n", snd_pcm_name(afbClient->pcm), afbClient->uri);
+ return 0;
+
+OnErrorExit:
+ fprintf(stderr, "\nAlsaPcmHook Plugin Close Fail PCM=%s\n", snd_pcm_name(afbClient->pcm));
return 0;
}
@@ -327,7 +360,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) {
// start populating client handle
afbClient->pcm = pcm;
afbClient->verbose = 0;
-
+ afbClient->request = afbRequest;
// Get PCM arguments from asoundrc
snd_config_for_each(it, next, conf) {
@@ -393,18 +426,22 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) {
err = snd_config_search(ctlconfig, "api", &itemConf);
if (!err) {
- if (snd_config_get_string(itemConf, &afbRequest[callCount]->api) < 0) {
+ const char *api;
+ if (snd_config_get_string(itemConf, &api) < 0) {
SNDERR("Invalid api string for %s", callLabel);
goto OnErrorExit;
}
+ afbRequest[callCount]->api=strdup(api);
}
err = snd_config_search(ctlconfig, "verb", &itemConf);
if (!err) {
- if (snd_config_get_string(itemConf, &afbRequest[callCount]->verb) < 0) {
+ const char *verb;
+ if (snd_config_get_string(itemConf, &verb) < 0) {
SNDERR("Invalid verb string %s", id);
goto OnErrorExit;
}
+ afbRequest[callCount]->verb=strdup(verb);
}
err = snd_config_search(ctlconfig, "timeout", &itemConf);
@@ -462,7 +499,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) {
if (err < 0) goto OnErrorExit;
// launch call request and create a waiting mainloop thread
- err = LaunchCallRequest(afbClient, afbRequest);
+ err = LaunchCallRequest(afbClient, HOOK_INSTALL);
if (err < 0) {
fprintf (stderr, "PCM Fail to Enter Mainloop\n");
goto OnErrorExit;
diff --git a/Shared-Interface/CMakeLists.txt b/Audio-Common/CMakeLists.txt
index 107a0cb..7544fe6 100644
--- a/Shared-Interface/CMakeLists.txt
+++ b/Audio-Common/CMakeLists.txt
@@ -17,10 +17,10 @@
###########################################################################
# Add target to project dependency list
-PROJECT_TARGET_ADD(audio-interface)
+PROJECT_TARGET_ADD(audio-common)
# Define targets
- ADD_LIBRARY(${TARGET_NAME} STATIC audio-interface.c)
+ ADD_LIBRARY(${TARGET_NAME} STATIC audio-common.c wrap-json.c)
# Library properties
SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
diff --git a/Shared-Interface/audio-interface.c b/Audio-Common/audio-common.c
index 3386460..ae41dde 100644
--- a/Shared-Interface/audio-interface.c
+++ b/Audio-Common/audio-common.c
@@ -16,7 +16,7 @@
*
*/
#define _GNU_SOURCE // needed for vasprintf
-#include "audio-interface.h"
+#include "audio-common.h"
PUBLIC const char *halCtlsLabels[] = {
diff --git a/Shared-Interface/audio-interface.h b/Audio-Common/audio-common.h
index 7bf258a..7bf258a 100644
--- a/Shared-Interface/audio-interface.h
+++ b/Audio-Common/audio-common.h
diff --git a/Audio-Common/wrap-json.c b/Audio-Common/wrap-json.c
new file mode 100644
index 0000000..164e127
--- /dev/null
+++ b/Audio-Common/wrap-json.c
@@ -0,0 +1,939 @@
+/*
+ Copyright (C) 2016, 2017 "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.
+*/
+
+#include <string.h>
+
+#include "wrap-json.h"
+
+#define STACKCOUNT 32
+#define STRCOUNT 8
+
+enum {
+ wrap_json_error_none,
+ wrap_json_error_null_object,
+ wrap_json_error_truncated,
+ wrap_json_error_internal_error,
+ wrap_json_error_out_of_memory,
+ wrap_json_error_invalid_character,
+ wrap_json_error_too_long,
+ wrap_json_error_too_deep,
+ wrap_json_error_null_spec,
+ wrap_json_error_null_key,
+ wrap_json_error_null_string,
+ wrap_json_error_out_of_range,
+ wrap_json_error_incomplete,
+ wrap_json_error_missfit_type,
+ wrap_json_error_key_not_found,
+ _wrap_json_error_count_
+};
+
+static const char ignore_all[] = " \t\n\r,:";
+static const char pack_accept_arr[] = "][{snbiIfoO";
+static const char pack_accept_key[] = "s}";
+#define pack_accept_any (&pack_accept_arr[1])
+
+static const char unpack_accept_arr[] = "*!][{snbiIfFoO";
+static const char unpack_accept_key[] = "*!s}";
+#define unpack_accept_any (&unpack_accept_arr[3])
+
+static const char *pack_errors[_wrap_json_error_count_] =
+{
+ [wrap_json_error_none] = "unknown error",
+ [wrap_json_error_null_object] = "null object",
+ [wrap_json_error_truncated] = "truncated",
+ [wrap_json_error_internal_error] = "internal error",
+ [wrap_json_error_out_of_memory] = "out of memory",
+ [wrap_json_error_invalid_character] = "invalid character",
+ [wrap_json_error_too_long] = "too long",
+ [wrap_json_error_too_deep] = "too deep",
+ [wrap_json_error_null_spec] = "spec is NULL",
+ [wrap_json_error_null_key] = "key is NULL",
+ [wrap_json_error_null_string] = "string is NULL",
+ [wrap_json_error_out_of_range] = "array too small",
+ [wrap_json_error_incomplete] = "incomplete container",
+ [wrap_json_error_missfit_type] = "missfit of type",
+ [wrap_json_error_key_not_found] = "key not found"
+};
+
+int wrap_json_get_error_position(int rc)
+{
+ if (rc < 0)
+ rc = -rc;
+ return (rc >> 4) + 1;
+}
+
+int wrap_json_get_error_code(int rc)
+{
+ if (rc < 0)
+ rc = -rc;
+ return rc & 15;
+}
+
+const char *wrap_json_get_error_string(int rc)
+{
+ rc = wrap_json_get_error_code(rc);
+ if (rc >= sizeof pack_errors / sizeof *pack_errors)
+ rc = 0;
+ return pack_errors[rc];
+}
+
+
+
+static inline const char *skip(const char *d)
+{
+ while (*d && strchr(ignore_all, *d))
+ d++;
+ return d;
+}
+
+int wrap_json_vpack(struct json_object **result, const char *desc, va_list args)
+{
+ /* TODO: the case of structs with key being single char should be optimized */
+ int nstr, notnull, nullable, rc;
+ size_t sz, dsz, ssz;
+ char *s;
+ char c;
+ const char *d;
+ char buffer[256];
+ struct { const char *str; size_t sz; } strs[STRCOUNT];
+ struct { struct json_object *cont, *key; const char *acc; char type; } stack[STACKCOUNT], *top;
+ struct json_object *obj;
+
+ ssz = sizeof buffer;
+ s = buffer;
+ top = stack;
+ top->key = NULL;
+ top->cont = NULL;
+ top->acc = pack_accept_any;
+ top->type = 0;
+ d = desc;
+ if (!d)
+ goto null_spec;
+ d = skip(d);
+ for(;;) {
+ c = *d;
+ if (!c)
+ goto truncated;
+ if (!strchr(top->acc, c))
+ goto invalid_character;
+ d = skip(++d);
+ switch(c) {
+ case 's':
+ nullable = 0;
+ notnull = 0;
+ nstr = 0;
+ sz = 0;
+ for (;;) {
+ strs[nstr].str = va_arg(args, const char*);
+ if (strs[nstr].str)
+ notnull = 1;
+ if (*d == '?') {
+ d = skip(++d);
+ nullable = 1;
+ }
+ switch(*d) {
+ case '%': strs[nstr].sz = va_arg(args, size_t); d = skip(++d); break;
+ case '#': strs[nstr].sz = (size_t)va_arg(args, int); d = skip(++d); break;
+ default: strs[nstr].sz = strs[nstr].str ? strlen(strs[nstr].str) : 0; break;
+ }
+ sz += strs[nstr++].sz;
+ if (*d == '?') {
+ d = skip(++d);
+ nullable = 1;
+ }
+ if (*d != '+')
+ break;
+ if (nstr >= STRCOUNT)
+ goto too_long;
+ d = skip(++d);
+ }
+ if (*d == '*')
+ nullable = 1;
+ if (notnull) {
+ if (sz > ssz) {
+ ssz += ssz;
+ if (ssz < sz)
+ ssz = sz;
+ s = alloca(sz);
+ }
+ dsz = sz;
+ while (nstr) {
+ nstr--;
+ dsz -= strs[nstr].sz;
+ memcpy(&s[dsz], strs[nstr].str, strs[nstr].sz);
+ }
+ obj = json_object_new_string_len(s, (int)sz);
+ if (!obj)
+ goto out_of_memory;
+ } else if (nullable)
+ obj = NULL;
+ else
+ goto null_string;
+ break;
+ case 'n':
+ obj = NULL;
+ break;
+ case 'b':
+ obj = json_object_new_boolean(va_arg(args, int));
+ if (!obj)
+ goto out_of_memory;
+ break;
+ case 'i':
+ obj = json_object_new_int(va_arg(args, int));
+ if (!obj)
+ goto out_of_memory;
+ break;
+ case 'I':
+ obj = json_object_new_int64(va_arg(args, int64_t));
+ if (!obj)
+ goto out_of_memory;
+ break;
+ case 'f':
+ obj = json_object_new_double(va_arg(args, double));
+ if (!obj)
+ goto out_of_memory;
+ break;
+ case 'o':
+ case 'O':
+ obj = va_arg(args, struct json_object*);
+ if (*d == '?')
+ d = skip(++d);
+ else if (*d != '*' && !obj)
+ goto null_object;
+ if (c == 'O')
+ json_object_get(obj);
+ break;
+ case '[':
+ case '{':
+ if (++top >= &stack[STACKCOUNT])
+ goto too_deep;
+ top->key = NULL;
+ if (c == '[') {
+ top->type = ']';
+ top->acc = pack_accept_arr;
+ top->cont = json_object_new_array();
+ } else {
+ top->type = '}';
+ top->acc = pack_accept_key;
+ top->cont = json_object_new_object();
+ }
+ if (!top->cont)
+ goto out_of_memory;
+ continue;
+ case '}':
+ case ']':
+ if (c != top->type || top <= stack)
+ goto internal_error;
+ obj = (top--)->cont;
+ if (*d == '*' && !(c == '}' ? json_object_object_length(obj) : json_object_array_length(obj))) {
+ json_object_put(obj);
+ obj = NULL;
+ }
+ break;
+ default:
+ goto internal_error;
+ }
+ switch (top->type) {
+ case 0:
+ if (top != stack)
+ goto internal_error;
+ if (*d)
+ goto invalid_character;
+ *result = obj;
+ return 0;
+ case ']':
+ if (obj || *d != '*')
+ json_object_array_add(top->cont, obj);
+ if (*d == '*')
+ d = skip(++d);
+ break;
+ case '}':
+ if (!obj)
+ goto null_key;
+ top->key = obj;
+ top->acc = pack_accept_any;
+ top->type = ':';
+ break;
+ case ':':
+ if (obj || *d != '*')
+ json_object_object_add(top->cont, json_object_get_string(top->key), obj);
+ if (*d == '*')
+ d = skip(++d);
+ json_object_put(top->key);
+ top->key = NULL;
+ top->acc = pack_accept_key;
+ top->type = '}';
+ break;
+ default:
+ goto internal_error;
+ }
+ }
+
+null_object:
+ rc = wrap_json_error_null_object;
+ goto error;
+truncated:
+ rc = wrap_json_error_truncated;
+ goto error;
+internal_error:
+ rc = wrap_json_error_internal_error;
+ goto error;
+out_of_memory:
+ rc = wrap_json_error_out_of_memory;
+ goto error;
+invalid_character:
+ rc = wrap_json_error_invalid_character;
+ goto error;
+too_long:
+ rc = wrap_json_error_too_long;
+ goto error;
+too_deep:
+ rc = wrap_json_error_too_deep;
+ goto error;
+null_spec:
+ rc = wrap_json_error_null_spec;
+ goto error;
+null_key:
+ rc = wrap_json_error_null_key;
+ goto error;
+null_string:
+ rc = wrap_json_error_null_string;
+ goto error;
+error:
+ do {
+ json_object_put(top->key);
+ json_object_put(top->cont);
+ } while (--top >= stack);
+ *result = NULL;
+ rc = rc | (int)((d - desc) << 4);
+ return -rc;
+}
+
+int wrap_json_pack(struct json_object **result, const char *desc, ...)
+{
+ int rc;
+ va_list args;
+
+ va_start(args, desc);
+ rc = wrap_json_vpack(result, desc, args);
+ va_end(args);
+ return rc;
+}
+
+static int vunpack(struct json_object *object, const char *desc, va_list args, int store)
+{
+ int rc = 0, optionnal, ignore;
+ char c, xacc[2] = { 0, 0 };
+ const char *acc;
+ const char *d, *fit = NULL;
+ const char *key = NULL;
+ const char **ps = NULL;
+ double *pf = NULL;
+ int *pi = NULL;
+ int64_t *pI = NULL;
+ size_t *pz = NULL;
+ struct { struct json_object *parent; const char *acc; int index, count; char type; } stack[STACKCOUNT], *top;
+ struct json_object *obj;
+ struct json_object **po;
+
+ xacc[0] = 0;
+ ignore = 0;
+ top = NULL;
+ acc = unpack_accept_any;
+ d = desc;
+ if (!d)
+ goto null_spec;
+ d = skip(d);
+ obj = object;
+ for(;;) {
+ fit = d;
+ c = *d;
+ if (!c)
+ goto truncated;
+ if (!strchr(acc, c))
+ goto invalid_character;
+ d = skip(++d);
+ switch(c) {
+ case 's':
+ if (xacc[0] == '}') {
+ /* expects a key */
+ key = va_arg(args, const char *);
+ if (!key)
+ goto null_key;
+ if (*d != '?')
+ optionnal = 0;
+ else {
+ optionnal = 1;
+ d = skip(++d);
+ }
+ if (ignore)
+ ignore++;
+ else {
+ if (json_object_object_get_ex(top->parent, key, &obj)) {
+ /* found */
+ top->index++;
+ } else {
+ /* not found */
+ if (!optionnal)
+ goto key_not_found;
+ ignore = 1;
+ obj = NULL;
+ }
+ }
+ xacc[0] = ':';
+ acc = unpack_accept_any;
+ continue;
+ }
+ /* get a string */
+ if (store)
+ ps = va_arg(args, const char **);
+ if (!ignore) {
+ if (!json_object_is_type(obj, json_type_string))
+ goto missfit;
+ if (store && ps)
+ *ps = json_object_get_string(obj);
+ }
+ if (*d == '%') {
+ d = skip(++d);
+ if (store) {
+ pz = va_arg(args, size_t *);
+ if (!ignore && pz)
+ *pz = (size_t)json_object_get_string_len(obj);
+ }
+ }
+ break;
+ case 'n':
+ if (!ignore && !json_object_is_type(obj, json_type_null))
+ goto missfit;
+ break;
+ case 'b':
+ if (store)
+ pi = va_arg(args, int *);
+
+ if (!ignore) {
+ if (!json_object_is_type(obj, json_type_boolean))
+ goto missfit;
+ if (store && pi)
+ *pi = json_object_get_boolean(obj);
+ }
+ break;
+ case 'i':
+ if (store)
+ pi = va_arg(args, int *);
+
+ if (!ignore) {
+ if (!json_object_is_type(obj, json_type_int))
+ goto missfit;
+ if (store && pi)
+ *pi = json_object_get_int(obj);
+ }
+ break;
+ case 'I':
+ if (store)
+ pI = va_arg(args, int64_t *);
+
+ if (!ignore) {
+ if (!json_object_is_type(obj, json_type_int))
+ goto missfit;
+ if (store && pI)
+ *pI = json_object_get_int64(obj);
+ }
+ break;
+ case 'f':
+ case 'F':
+ if (store)
+ pf = va_arg(args, double *);
+
+ if (!ignore) {
+ if (!(json_object_is_type(obj, json_type_double) || (c == 'F' && json_object_is_type(obj, json_type_int))))
+ goto missfit;
+ if (store && pf)
+ *pf = json_object_get_double(obj);
+ }
+ break;
+ case 'o':
+ case 'O':
+ if (store) {
+ po = va_arg(args, struct json_object **);
+ if (!ignore && po) {
+ if (c == 'O')
+ obj = json_object_get(obj);
+ *po = obj;
+ }
+ }
+ break;
+
+ case '[':
+ case '{':
+ if (!top)
+ top = stack;
+ else if (++top >= &stack[STACKCOUNT])
+ goto too_deep;
+
+ top->acc = acc;
+ top->type = xacc[0];
+ top->index = 0;
+ top->parent = obj;
+ if (ignore)
+ ignore++;
+ if (c == '[') {
+ if (!ignore) {
+ if (!json_object_is_type(obj, json_type_array))
+ goto missfit;
+ top->count = json_object_array_length(obj);
+ }
+ xacc[0] = ']';
+ acc = unpack_accept_arr;
+ } else {
+ if (!ignore) {
+ if (!json_object_is_type(obj, json_type_object))
+ goto missfit;
+ top->count = json_object_object_length(obj);
+ }
+ xacc[0] = '}';
+ acc = unpack_accept_key;
+ continue;
+ }
+ break;
+ case '}':
+ case ']':
+ if (!top || c != xacc[0])
+ goto internal_error;
+ acc = top->acc;
+ xacc[0] = top->type;
+ top = top == stack ? NULL : top - 1;
+ if (ignore)
+ ignore--;
+ break;
+ case '!':
+ if (*d != xacc[0])
+ goto invalid_character;
+ if (!ignore && top->index != top->count)
+ goto incomplete;
+ /*@fallthrough@*/
+ case '*':
+ acc = xacc;
+ continue;
+ default:
+ goto internal_error;
+ }
+ switch (xacc[0]) {
+ case 0:
+ if (top)
+ goto internal_error;
+ if (*d)
+ goto invalid_character;
+ return 0;
+ case ']':
+ if (!ignore) {
+ key = strchr(unpack_accept_arr, *d);
+ if (key && key >= unpack_accept_any) {
+ if (top->index >= top->count)
+ goto out_of_range;
+ obj = json_object_array_get_idx(top->parent, top->index++);
+ }
+ }
+ break;
+ case ':':
+ acc = unpack_accept_key;
+ xacc[0] = '}';
+ if (ignore)
+ ignore--;
+ break;
+ default:
+ goto internal_error;
+ }
+ }
+truncated:
+ rc = wrap_json_error_truncated;
+ goto error;
+internal_error:
+ rc = wrap_json_error_internal_error;
+ goto error;
+invalid_character:
+ rc = wrap_json_error_invalid_character;
+ goto error;
+too_deep:
+ rc = wrap_json_error_too_deep;
+ goto error;
+null_spec:
+ rc = wrap_json_error_null_spec;
+ goto error;
+null_key:
+ rc = wrap_json_error_null_key;
+ goto error;
+out_of_range:
+ rc = wrap_json_error_out_of_range;
+ goto error;
+incomplete:
+ rc = wrap_json_error_incomplete;
+ goto error;
+missfit:
+ rc = wrap_json_error_missfit_type;
+ goto errorfit;
+key_not_found:
+ rc = wrap_json_error_key_not_found;
+ goto error;
+errorfit:
+ d = fit;
+error:
+ rc = rc | (int)((d - desc) << 4);
+ return -rc;
+}
+
+int wrap_json_vcheck(struct json_object *object, const char *desc, va_list args)
+{
+ return vunpack(object, desc, args, 0);
+}
+
+int wrap_json_check(struct json_object *object, const char *desc, ...)
+{
+ int rc;
+ va_list args;
+
+ va_start(args, desc);
+ rc = vunpack(object, desc, args, 0);
+ va_end(args);
+ return rc;
+}
+
+int wrap_json_vmatch(struct json_object *object, const char *desc, va_list args)
+{
+ return !vunpack(object, desc, args, 0);
+}
+
+int wrap_json_match(struct json_object *object, const char *desc, ...)
+{
+ int rc;
+ va_list args;
+
+ va_start(args, desc);
+ rc = vunpack(object, desc, args, 0);
+ va_end(args);
+ return !rc;
+}
+
+int wrap_json_vunpack(struct json_object *object, const char *desc, va_list args)
+{
+ return vunpack(object, desc, args, 1);
+}
+
+int wrap_json_unpack(struct json_object *object, const char *desc, ...)
+{
+ int rc;
+ va_list args;
+
+ va_start(args, desc);
+ rc = vunpack(object, desc, args, 1);
+ va_end(args);
+ return rc;
+}
+
+static void object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
+{
+ struct json_object_iterator it = json_object_iter_begin(object);
+ struct json_object_iterator end = json_object_iter_end(object);
+ while (!json_object_iter_equal(&it, &end)) {
+ callback(closure, json_object_iter_peek_value(&it), json_object_iter_peek_name(&it));
+ json_object_iter_next(&it);
+ }
+}
+
+static void array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
+{
+ int n = json_object_array_length(object);
+ int i = 0;
+ while(i < n)
+ callback(closure, json_object_array_get_idx(object, i++));
+}
+
+void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
+{
+ if (json_object_is_type(object, json_type_array))
+ array_for_all(object, callback, closure);
+ else
+ callback(closure, object);
+}
+
+void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure)
+{
+ if (json_object_is_type(object, json_type_array))
+ array_for_all(object, callback, closure);
+}
+
+void wrap_json_object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
+{
+ if (json_object_is_type(object, json_type_object))
+ object_for_all(object, callback, closure);
+}
+
+void wrap_json_optobject_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
+{
+ if (json_object_is_type(object, json_type_object))
+ object_for_all(object, callback, closure);
+ else
+ callback(closure, object, NULL);
+}
+
+void wrap_json_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure)
+{
+ if (!object)
+ /* do nothing */;
+ else if (json_object_is_type(object, json_type_object))
+ object_for_all(object, callback, closure);
+ else if (!json_object_is_type(object, json_type_array))
+ callback(closure, object, NULL);
+ else {
+ int n = json_object_array_length(object);
+ int i = 0;
+ while(i < n)
+ callback(closure, json_object_array_get_idx(object, i++), NULL);
+ }
+}
+
+#if defined(WRAP_JSON_TEST)
+#include <stdio.h>
+
+void p(const char *desc, ...)
+{
+ int rc;
+ va_list args;
+ struct json_object *result;
+
+ va_start(args, desc);
+ rc = wrap_json_vpack(&result, desc, args);
+ va_end(args);
+ if (!rc)
+ printf(" SUCCESS %s\n\n", json_object_to_json_string(result));
+ else
+ printf(" ERROR[char %d err %d] %s\n\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc));
+ json_object_put(result);
+}
+
+const char *xs[10];
+int *xi[10];
+int64_t *xI[10];
+double *xf[10];
+struct json_object *xo[10];
+size_t xz[10];
+
+void u(const char *value, const char *desc, ...)
+{
+ unsigned m, k;
+ int rc;
+ va_list args;
+ struct json_object *obj, *o;
+
+ memset(xs, 0, sizeof xs);
+ memset(xi, 0, sizeof xi);
+ memset(xI, 0, sizeof xI);
+ memset(xf, 0, sizeof xf);
+ memset(xo, 0, sizeof xo);
+ memset(xz, 0, sizeof xz);
+ obj = json_tokener_parse(value);
+ va_start(args, desc);
+ rc = wrap_json_vunpack(obj, desc, args);
+ va_end(args);
+ if (rc)
+ printf(" ERROR[char %d err %d] %s\n\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc));
+ else {
+ value = NULL;
+ printf(" SUCCESS");
+ va_start(args, desc);
+ k = m = 0;
+ while(*desc) {
+ switch(*desc) {
+ case '{': m = (m << 1) | 1; k = 1; break;
+ case '}': m = m >> 1; k = m&1; break;
+ case '[': m = m << 1; k = 0; break;
+ case ']': m = m >> 1; k = m&1; break;
+ case 's': printf(" s:%s", k ? va_arg(args, const char*) : *(va_arg(args, const char**)?:&value)); k ^= m&1; break;
+ case '%': printf(" %%:%zu", *va_arg(args, size_t*)); k = m&1; break;
+ case 'n': printf(" n"); k = m&1; break;
+ case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break;
+ case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break;
+ case 'I': printf(" I:%lld", *va_arg(args, int64_t*)); k = m&1; break;
+ case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break;
+ case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break;
+ case 'o': printf(" o:%s", json_object_to_json_string(*va_arg(args, struct json_object**))); k = m&1; break;
+ case 'O': o = *va_arg(args, struct json_object**); printf(" O:%s", json_object_to_json_string(o)); json_object_put(o); k = m&1; break;
+ default: break;
+ }
+ desc++;
+ }
+ va_end(args);
+ printf("\n\n");
+ }
+ json_object_put(obj);
+}
+
+#define P(...) do{ printf("pack(%s)\n",#__VA_ARGS__); p(__VA_ARGS__); } while(0)
+#define U(...) do{ printf("unpack(%s)\n",#__VA_ARGS__); u(__VA_ARGS__); } while(0)
+
+int main()
+{
+ char buffer[4] = {'t', 'e', 's', 't'};
+
+ P("n");
+ P("b", 1);
+ P("b", 0);
+ P("i", 1);
+ P("I", (uint64_t)0x123456789abcdef);
+ P("f", 3.14);
+ P("s", "test");
+ P("s?", "test");
+ P("s?", NULL);
+ P("s#", "test asdf", 4);
+ P("s%", "test asdf", (size_t)4);
+ P("s#", buffer, 4);
+ P("s%", buffer, (size_t)4);
+ P("s++", "te", "st", "ing");
+ P("s#+#+", "test", 1, "test", 2, "test");
+ P("s%+%+", "test", (size_t)1, "test", (size_t)2, "test");
+ P("{}", 1.0);
+ P("[]", 1.0);
+ P("o", json_object_new_int(1));
+ P("o?", json_object_new_int(1));
+ P("o?", NULL);
+ P("O", json_object_new_int(1));
+ P("O?", json_object_new_int(1));
+ P("O?", NULL);
+ P("{s:[]}", "foo");
+ P("{s+#+: []}", "foo", "barbar", 3, "baz");
+ P("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
+ P("{s:**}", "a", NULL);
+ P("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
+ P("[i,i,i]", 0, 1, 2);
+ P("[s,o,O]", NULL, NULL, NULL);
+ P("[**]", NULL);
+ P("[s*,o*,O*]", NULL, NULL, NULL);
+ P(" s ", "test");
+ P("[ ]");
+ P("[ i , i, i ] ", 1, 2, 3);
+ P("{\n\n1");
+ P("[}");
+ P("{]");
+ P("[");
+ P("{");
+ P("[i]a", 42);
+ P("ia", 42);
+ P("s", NULL);
+ P("+", NULL);
+ P(NULL);
+ P("{s:i}", NULL, 1);
+ P("{ {}: s }", "foo");
+ P("{ s: {}, s:[ii{} }", "foo", "bar", 12, 13);
+ P("[[[[[ [[[[[ [[[[ }]]]] ]]]] ]]]]]");
+
+ U("true", "b", &xi[0]);
+ U("false", "b", &xi[0]);
+ U("null", "n");
+ U("42", "i", &xi[0]);
+ U("123456789", "I", &xI[0]);
+ U("3.14", "f", &xf[0]);
+ U("12345", "F", &xf[0]);
+ U("3.14", "F", &xf[0]);
+ U("\"foo\"", "s", &xs[0]);
+ U("\"foo\"", "s%", &xs[0], &xz[0]);
+ U("{}", "{}");
+ U("[]", "[]");
+ U("{}", "o", &xo[0]);
+ U("{}", "O", &xo[0]);
+ U("{\"foo\":42}", "{si}", "foo", &xi[0]);
+ U("[1,2,3]", "[i,i,i]", &xi[0], &xi[1], &xi[2]);
+ U("{\"a\":1,\"b\":2,\"c\":3}", "{s:i, s:i, s:i}", "a", &xi[0], "b", &xi[1], "c", &xi[2]);
+ U("42", "z");
+ U("null", "[i]");
+ U("[]", "[}");
+ U("{}", "{]");
+ U("[]", "[");
+ U("{}", "{");
+ U("[42]", "[i]a", &xi[0]);
+ U("42", "ia", &xi[0]);
+ U("[]", NULL);
+ U("\"foo\"", "s", NULL);
+ U("42", "s", NULL);
+ U("42", "n");
+ U("42", "b", NULL);
+ U("42", "f", NULL);
+ U("42", "[i]", NULL);
+ U("42", "{si}", "foo", NULL);
+ U("\"foo\"", "n");
+ U("\"foo\"", "b", NULL);
+ U("\"foo\"", "i", NULL);
+ U("\"foo\"", "I", NULL);
+ U("\"foo\"", "f", NULL);
+ U("\"foo\"", "F", NULL);
+ U("true", "s", NULL);
+ U("true", "n");
+ U("true", "i", NULL);
+ U("true", "I", NULL);
+ U("true", "f", NULL);
+ U("true", "F", NULL);
+ U("[42]", "[ii]", &xi[0], &xi[1]);
+ U("{\"foo\":42}", "{si}", NULL, &xi[0]);
+ U("{\"foo\":42}", "{si}", "baz", &xi[0]);
+ U("[1,2,3]", "[iii!]", &xi[0], &xi[1], &xi[2]);
+ U("[1,2,3]", "[ii!]", &xi[0], &xi[1]);
+ U("[1,2,3]", "[ii]", &xi[0], &xi[1]);
+ U("[1,2,3]", "[ii*]", &xi[0], &xi[1]);
+ U("{\"foo\":42,\"baz\":45}", "{sisi}", "baz", &xi[0], "foo", &xi[1]);
+ U("{\"foo\":42,\"baz\":45}", "{sisi*}", "baz", &xi[0], "foo", &xi[1]);
+ U("{\"foo\":42,\"baz\":45}", "{sisi!}", "baz", &xi[0], "foo", &xi[1]);
+ U("{\"foo\":42,\"baz\":45}", "{si}", "baz", &xi[0], "foo", &xi[1]);
+ U("{\"foo\":42,\"baz\":45}", "{si*}", "baz", &xi[0], "foo", &xi[1]);
+ U("{\"foo\":42,\"baz\":45}", "{si!}", "baz", &xi[0], "foo", &xi[1]);
+ U("[1,{\"foo\":2,\"bar\":null},[3,4]]", "[i{sisn}[ii]]", &xi[0], "foo", &xi[1], "bar", &xi[2], &xi[3]);
+ U("[1,2,3]", "[ii!i]", &xi[0], &xi[1], &xi[2]);
+ U("[1,2,3]", "[ii*i]", &xi[0], &xi[1], &xi[2]);
+ U("{\"foo\":1,\"bar\":2}", "{si!si}", "foo", &xi[1], "bar", &xi[2]);
+ U("{\"foo\":1,\"bar\":2}", "{si*si}", "foo", &xi[1], "bar", &xi[2]);
+ U("{\"foo\":{\"baz\":null,\"bar\":null}}", "{s{sn!}}", "foo", "bar");
+ U("[[1,2,3]]", "[[ii!]]", &xi[0], &xi[1]);
+ U("{}", "{s?i}", "foo", &xi[0]);
+ U("{\"foo\":1}", "{s?i}", "foo", &xi[0]);
+ U("{}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
+ U("{\"foo\":[1,2]}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
+ U("{\"bar\":{\"baz\":{\"quux\":15}}}", "{s?[ii]s?{s{si!}}}", "foo", &xi[0], &xi[1], "bar", "baz", "quux", &xi[2]);
+ U("{\"foo\":{\"bar\":4}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
+ U("{\"foo\":{}}", "{s?{s?i}}", "foo", "bar", &xi[0]);
+ U("{}", "{s?{s?i}}", "foo", "bar", &xi[0]);
+ U("{\"foo\":42,\"baz\":45}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
+ U("{\"foo\":42}", "{s?isi!}", "baz", &xi[0], "foo", &xi[1]);
+ return 0;
+}
+
+#endif
+
+#if 0
+
+
+ /* Unpack the same item twice */
+ j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
+ if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
+ fail("json_unpack object with strict validation failed");
+ {
+ const char *possible_errors[] = {
+ "2 object item(s) left unpacked: baz, quux",
+ "2 object item(s) left unpacked: quux, baz"
+ };
+ check_errors(possible_errors, 2, "<validation>", 1, 10, 10);
+ }
+ json_decref(j);
+
+#endif
diff --git a/Audio-Common/wrap-json.h b/Audio-Common/wrap-json.h
new file mode 100644
index 0000000..cb2d0bf
--- /dev/null
+++ b/Audio-Common/wrap-json.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2016, 2017 "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>
+#include <json-c/json.h>
+
+extern int wrap_json_get_error_position(int rc);
+extern int wrap_json_get_error_code(int rc);
+extern const char *wrap_json_get_error_string(int rc);
+
+extern int wrap_json_vpack(struct json_object **result, const char *desc, va_list args);
+extern int wrap_json_pack(struct json_object **result, const char *desc, ...);
+
+extern int wrap_json_vunpack(struct json_object *object, const char *desc, va_list args);
+extern int wrap_json_unpack(struct json_object *object, const char *desc, ...);
+extern int wrap_json_vcheck(struct json_object *object, const char *desc, va_list args);
+extern int wrap_json_check(struct json_object *object, const char *desc, ...);
+extern int wrap_json_vmatch(struct json_object *object, const char *desc, va_list args);
+extern int wrap_json_match(struct json_object *object, const char *desc, ...);
+
+extern void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure);
+extern void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure);
+
+extern void wrap_json_optarray_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure);
+extern void wrap_json_array_for_all(struct json_object *object, void (*callback)(void*,struct json_object*), void *closure);
+extern void wrap_json_object_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure);
+extern void wrap_json_optobject_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure);
+extern void wrap_json_for_all(struct json_object *object, void (*callback)(void*,struct json_object*,const char*), void *closure);
+
diff --git a/Audio-Common/wrap-json.md b/Audio-Common/wrap-json.md
new file mode 100644
index 0000000..92940f1
--- /dev/null
+++ b/Audio-Common/wrap-json.md
@@ -0,0 +1,305 @@
+WRAP-JSON facility
+==================
+
+The facility wrap-json is based on the pack/unpack API on the
+libray jansson. The two chapters below are copied from the
+documentation of jansson library copyrighted by Petri Lehtinen
+(see at end).
+
+Building Values
+---------------
+
+This section describes functions that help to create, or *pack*, complex
+JSON values, especially nested objects and arrays. Value building is
+based on a *format string* that is used to tell the functions about the
+expected arguments.
+
+For example, the format string `"i"` specifies a single integer value,
+while the format string `"[ssb]"` or the equivalent `"[s, s, b]"`
+specifies an array value with two strings and a boolean as its items:
+
+ /* Create the JSON integer 42 */
+ wrap_json_pack(&result, "i", 42);
+
+ /* Create the JSON array ["foo", "bar", true] */
+ wrap_json_pack(&result, "[ssb]", "foo", "bar", 1);
+
+Here's the full list of format specifiers. The type in parentheses
+denotes the resulting JSON type, and the type in brackets (if any)
+denotes the C type that is expected as the corresponding argument or
+arguments.
+
+`s` (string) \[const char \*\]
+
+: Convert a null terminated UTF-8 string to a JSON string.
+
+`s?` (string) \[const char \*\]
+
+: Like `s`, but if the argument is *NULL*, output a JSON null value.
+
+`s*` (string) \[const char \*\]
+
+: Like `s`, but if the argument is *NULL*, do not output any value.
+ This format can only be used inside an object or an array. If used
+ inside an object, the corresponding key is additionally suppressed
+ when the value is omitted. See below for an example.
+
+`s#` (string) \[const char \*, int\]
+
+: Convert a UTF-8 buffer of a given length to a JSON string.
+
+`s%` (string) \[const char \*, size\_t\]
+
+: Like `s#` but the length argument is of type size\_t.
+
+`+` \[const char \*\]
+
+: Like `s`, but concatenate to the previous string. Only valid after
+ `s`, `s#`, `+` or `+#`.
+
+`+#` \[const char \*, int\]
+
+: Like `s#`, but concatenate to the previous string. Only valid after
+ `s`, `s#`, `+` or `+#`.
+
+`+%` (string) \[const char \*, size\_t\]
+
+: Like `+#` but the length argument is of type size\_t.
+
+`n` (null)
+
+: Output a JSON null value. No argument is consumed.
+
+`b` (boolean) \[int\]
+
+: Convert a C int to JSON boolean value. Zero is converted to `false`
+ and non-zero to `true`.
+
+`i` (integer) \[int\]
+
+: Convert a C int to JSON integer.
+
+`I` (integer) \[json\_int\_t\]
+
+: Convert a C json\_int\_t to JSON integer.
+
+`f` (real) \[double\]
+
+: Convert a C double to JSON real.
+
+`o` (any value) \[json\_t \*\]
+
+: Output any given JSON value as-is. If the value is added to an array
+ or object, the reference to the value passed to `o` is stolen by the
+ container.
+
+`O` (any value) \[json\_t \*\]
+
+: Like `o`, but the argument's reference count is incremented. This is
+ useful if you pack into an array or object and want to keep the
+ reference for the JSON value consumed by `O` to yourself.
+
+`o?`, `O?` (any value) \[json\_t \*\]
+
+: Like `o` and `O`, respectively, but if the argument is *NULL*,
+ output a JSON null value.
+
+`o*`, `O*` (any value) \[json\_t \*\]
+
+: Like `o` and `O`, respectively, but if the argument is *NULL*, do
+ not output any value. This format can only be used inside an object
+ or an array. If used inside an object, the corresponding key is
+ additionally suppressed. See below for an example.
+
+`[fmt]` (array)
+
+: Build an array with contents from the inner format string. `fmt` may
+ contain objects and arrays, i.e. recursive value building is
+ supported.
+
+`{fmt}` (object)
+
+: Build an object with contents from the inner format string `fmt`.
+ The first, third, etc. format specifier represent a key, and must be
+ a string (see `s`, `s#`, `+` and `+#` above), as object keys are
+ always strings. The second, fourth, etc. format specifier represent
+ a value. Any value may be an object or array, i.e. recursive value
+ building is supported.
+
+Whitespace, `:` and `,` are ignored.
+
+More examples:
+
+ /* Build an empty JSON object */
+ wrap_json_pack(&result, "{}");
+
+ /* Build the JSON object {"foo": 42, "bar": 7} */
+ wrap_json_pack(&result, "{sisi}", "foo", 42, "bar", 7);
+
+ /* Like above, ':', ',' and whitespace are ignored */
+ wrap_json_pack(&result, "{s:i, s:i}", "foo", 42, "bar", 7);
+
+ /* Build the JSON array [[1, 2], {"cool": true}] */
+ wrap_json_pack(&result, "[[i,i],{s:b}]", 1, 2, "cool", 1);
+
+ /* Build a string from a non-null terminated buffer */
+ char buffer[4] = {'t', 'e', 's', 't'};
+ wrap_json_pack(&result, "s#", buffer, 4);
+
+ /* Concatenate strings together to build the JSON string "foobarbaz" */
+ wrap_json_pack(&result, "s++", "foo", "bar", "baz");
+
+ /* Create an empty object or array when optional members are missing */
+ wrap_json_pack(&result, "{s:s*,s:o*,s:O*}", "foo", NULL, "bar", NULL, "baz", NULL);
+ wrap_json_pack(&result, "[s*,o*,O*]", NULL, NULL, NULL);
+
+Parsing and Validating Values
+-----------------------------
+
+This section describes functions that help to validate complex values
+and extract, or *unpack*, data from them. Like building values
+&lt;apiref-pack&gt;, this is also based on format strings.
+
+While a JSON value is unpacked, the type specified in the format string
+is checked to match that of the JSON value. This is the validation part
+of the process. In addition to this, the unpacking functions can also
+check that all items of arrays and objects are unpacked. This check be
+enabled with the format specifier `!` or by using the flag
+`JSON_STRICT`. See below for details.
+
+Here's the full list of format specifiers. The type in parentheses
+denotes the JSON type, and the type in brackets (if any) denotes the C
+type whose address should be passed.
+
+`s` (string) \[const char \*\]
+
+: Convert a JSON string to a pointer to a null terminated UTF-8
+ string. The resulting string is extracted by using
+ json\_string\_value() internally, so it exists as long as there are
+ still references to the corresponding JSON string.
+
+`s%` (string) \[const char \*, size\_t \*\]
+
+: Convert a JSON string to a pointer to a null terminated UTF-8 string
+ and its length.
+
+`n` (null)
+
+: Expect a JSON null value. Nothing is extracted.
+
+`b` (boolean) \[int\]
+
+: Convert a JSON boolean value to a C int, so that `true` is converted
+ to 1 and `false` to 0.
+
+`i` (integer) \[int\]
+
+: Convert a JSON integer to C int.
+
+`I` (integer) \[json\_int\_t\]
+
+: Convert a JSON integer to C json\_int\_t.
+
+`f` (real) \[double\]
+
+: Convert a JSON real to C double.
+
+`F` (integer or real) \[double\]
+
+: Convert a JSON number (integer or real) to C double.
+
+`o` (any value) \[json\_t \*\]
+
+: Store a JSON value with no conversion to a json\_t pointer.
+
+`O` (any value) \[json\_t \*\]
+
+: Like `O`, but the JSON value's reference count is incremented.
+
+`[fmt]` (array)
+
+: Convert each item in the JSON array according to the inner format
+ string. `fmt` may contain objects and arrays, i.e. recursive value
+ extraction is supported.
+
+`{fmt}` (object)
+
+: Convert each item in the JSON object according to the inner format
+ string `fmt`. The first, third, etc. format specifier represent a
+ key, and must be `s`. The corresponding argument to unpack functions
+ is read as the object key. The second fourth, etc. format specifier
+ represent a value and is written to the address given as the
+ corresponding argument. **Note** that every other argument is read
+ from and every other is written to.
+
+ `fmt` may contain objects and arrays as values, i.e. recursive value
+ extraction is supported.
+
+`!`
+
+: This special format specifier is used to enable the check that all
+ object and array items are accessed, on a per-value basis. It must
+ appear inside an array or object as the last format specifier before
+ the closing bracket or brace.
+
+`*`
+
+: This special format specifier is the opposite of `!`. This is the default.
+ It must appear inside an array or object as the last format specifier
+ before the closing bracket or brace.
+
+Whitespace, `:` and `,` are ignored.
+
+Examples:
+
+ /* root is the JSON integer 42 */
+ int myint;
+ wrap_json_unpack(root, "i", &myint);
+ assert(myint == 42);
+
+ /* root is the JSON object {"foo": "bar", "quux": true} */
+ const char *str;
+ int boolean;
+ wrap_json_unpack(root, "{s:s, s:b}", "foo", &str, "quux", &boolean);
+ assert(strcmp(str, "bar") == 0 && boolean == 1);
+
+ /* root is the JSON array [[1, 2], {"baz": null} */
+ wrap_json_check(root, "[[i,i], {s:n}]", "baz");
+ /* returns 0 for validation success, nothing is extracted */
+
+ /* root is the JSON array [1, 2, 3, 4, 5] */
+ int myint1, myint2;
+ wrap_json_unpack(root, "[ii!]", &myint1, &myint2);
+ /* returns -1 for failed validation */
+
+ /* root is an empty JSON object */
+ int myint = 0, myint2 = 0, myint3 = 0;
+ wrap_json_unpack(root, "{s?i, s?[ii]}",
+ "foo", &myint1,
+ "bar", &myint2, &myint3);
+ /* myint1, myint2 or myint3 is no touched as "foo" and "bar" don't exist */
+
+
+Copyright
+---------
+
+Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/PolicyCtl-afb/CMakeLists.txt b/Controler-afb/CMakeLists.txt
index d9776df..afebdf2 100644
--- a/PolicyCtl-afb/CMakeLists.txt
+++ b/Controler-afb/CMakeLists.txt
@@ -30,26 +30,28 @@ macro(SET_TARGET_GENSKEL TARGET_NAME API_DEF_NAME)
endmacro(SET_TARGET_GENSKEL)
# Add target to project dependency list
-PROJECT_TARGET_ADD(polctl-afb)
+PROJECT_TARGET_ADD(control-afb)
# Define project Targets
- ADD_LIBRARY(${TARGET_NAME} MODULE polctl-binding.c )
+ ADD_LIBRARY(${TARGET_NAME} MODULE ctl-binding.c ctl-events.c ctl-policy.c ctl-lua.c
+)
# Generate API-v2 hat from OpenAPI json definition
- SET_TARGET_GENSKEL(${TARGET_NAME} polctl-apidef)
+ SET_TARGET_GENSKEL(${TARGET_NAME} ctl-apidef)
# Binder exposes a unique public entry point
SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
PREFIX "afb-"
LABELS "BINDING"
LINK_FLAGS ${BINDINGS_LINK_FLAG}
- OUTPUT_NAME polctl
+ OUTPUT_NAME ${TARGET_NAME}
)
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
- audio-interface
+ audio-common
+ ${link_libraries}
)
# installation directory
diff --git a/Controler-afb/ctl-apidef.h b/Controler-afb/ctl-apidef.h
new file mode 100644
index 0000000..0ab4cd2
--- /dev/null
+++ b/Controler-afb/ctl-apidef.h
@@ -0,0 +1,128 @@
+
+static const char _afb_description_v2_control[] =
+ "{\"openapi\":\"3.0.0\",\"$schema\":\"http:iot.bzh/download/openapi/schem"
+ "a-3.0/default-schema.json\",\"info\":{\"description\":\"\",\"title\":\"p"
+ "olctl\",\"version\":\"1.0\",\"x-binding-c-generator\":{\"api\":\"control"
+ "\",\"version\":2,\"prefix\":\"ctlapi_\",\"postfix\":\"\",\"start\":null,"
+ "\"onevent\":null,\"init\":\"CtlBindingInit\",\"scope\":\"\",\"private\":"
+ "false}},\"servers\":[{\"url\":\"ws://{host}:{port}/api/polctl\",\"descri"
+ "ption\":\"Unicens2 API.\",\"variables\":{\"host\":{\"default\":\"localho"
+ "st\"},\"port\":{\"default\":\"1234\"}},\"x-afb-events\":[{\"$ref\":\"#/c"
+ "omponents/schemas/afb-event\"}]}],\"components\":{\"schemas\":{\"afb-rep"
+ "ly\":{\"$ref\":\"#/components/schemas/afb-reply-v2\"},\"afb-event\":{\"$"
+ "ref\":\"#/components/schemas/afb-event-v2\"},\"afb-reply-v2\":{\"title\""
+ ":\"Generic response.\",\"type\":\"object\",\"required\":[\"jtype\",\"req"
+ "uest\"],\"properties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-r"
+ "eply\"},\"request\":{\"type\":\"object\",\"required\":[\"status\"],\"pro"
+ "perties\":{\"status\":{\"type\":\"string\"},\"info\":{\"type\":\"string\""
+ "},\"token\":{\"type\":\"string\"},\"uuid\":{\"type\":\"string\"},\"reqid"
+ "\":{\"type\":\"string\"}}},\"response\":{\"type\":\"object\"}}},\"afb-ev"
+ "ent-v2\":{\"type\":\"object\",\"required\":[\"jtype\",\"event\"],\"prope"
+ "rties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-event\"},\"event"
+ "\":{\"type\":\"string\"},\"data\":{\"type\":\"object\"}}}},\"x-permissio"
+ "ns\":{\"monitor\":{\"permission\":\"urn:AGL:permission:audio:public:moni"
+ "tor\"},\"multimedia\":{\"permission\":\"urn:AGL:permission:audio:public:"
+ "monitor\"},\"navigation\":{\"permission\":\"urn:AGL:permission:audio:pub"
+ "lic:monitor\"},\"emergency\":{\"permission\":\"urn:AGL:permission:audio:"
+ "public:emergency\"}},\"responses\":{\"200\":{\"description\":\"A complex"
+ " object array response\",\"content\":{\"application/json\":{\"schema\":{"
+ "\"$ref\":\"#/components/schemas/afb-reply\"}}}}}},\"paths\":{\"/monitor\""
+ ":{\"description\":\"Subcribe Audio Agent Policy Control End\",\"get\":{\""
+ "x-permissions\":{\"$ref\":\"#/components/x-permissions/monitor\"},\"para"
+ "meters\":[{\"in\":\"query\",\"name\":\"event_patern\",\"required\":true,"
+ "\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/"
+ "components/responses/200\"}}}},\"/event_test\":{\"description\":\"Pause "
+ "Resume Test\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-perm"
+ "issions/monitor\"},\"parameters\":[{\"in\":\"query\",\"name\":\"delay\","
+ "\"required\":false,\"schema\":{\"type\":\"interger\"}},{\"in\":\"query\""
+ ",\"name\":\"count\",\"required\":false,\"schema\":{\"type\":\"interger\""
+ "}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},"
+ "\"/navigation\":{\"description\":\"Request Access to Navigation Audio Ch"
+ "annel.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissio"
+ "ns/navigation\"},\"parameters\":[{\"in\":\"query\",\"name\":\"zone\",\"r"
+ "equired\":false,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\""
+ ":{\"$ref\":\"#/components/responses/200\"}}}},\"/lua_docall\":{\"descrip"
+ "tion\":\"Execute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref"
+ "\":\"#/components/x-permissions/navigation\"},\"parameters\":[{\"in\":\""
+ "query\",\"name\":\"func\",\"required\":true,\"schema\":{\"type\":\"strin"
+ "g\"}},{\"in\":\"query\",\"name\":\"args\",\"required\":false,\"schema\":"
+ "{\"type\":\"array\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/r"
+ "esponses/200\"}}}},\"/lua_dostring\":{\"description\":\"Execute LUA stri"
+ "ng script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permi"
+ "ssions/navigation\"},\"parameters\":[{\"in\":\"query\",\"required\":true"
+ ",\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#"
+ "/components/responses/200\"}}}},\"/lua_doscript\":{\"description\":\"Exe"
+ "cute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/compo"
+ "nents/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"na"
+ "me\":\"filename\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\""
+ "responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}}}}"
+;
+
+static const struct afb_auth _afb_auths_v2_control[] = {
+ { .type = afb_auth_Permission, .text = "urn:AGL:permission:audio:public:monitor" }
+};
+
+ void ctlapi_monitor(struct afb_req req);
+ void ctlapi_event_test(struct afb_req req);
+ void ctlapi_navigation(struct afb_req req);
+ void ctlapi_lua_docall(struct afb_req req);
+ void ctlapi_lua_dostring(struct afb_req req);
+ void ctlapi_lua_doscript(struct afb_req req);
+
+static const struct afb_verb_v2 _afb_verbs_v2_control[] = {
+ {
+ .verb = "monitor",
+ .callback = ctlapi_monitor,
+ .auth = &_afb_auths_v2_control[0],
+ .info = NULL,
+ .session = AFB_SESSION_NONE_V2
+ },
+ {
+ .verb = "event_test",
+ .callback = ctlapi_event_test,
+ .auth = &_afb_auths_v2_control[0],
+ .info = NULL,
+ .session = AFB_SESSION_NONE_V2
+ },
+ {
+ .verb = "navigation",
+ .callback = ctlapi_navigation,
+ .auth = &_afb_auths_v2_control[0],
+ .info = NULL,
+ .session = AFB_SESSION_NONE_V2
+ },
+ {
+ .verb = "lua_docall",
+ .callback = ctlapi_lua_docall,
+ .auth = &_afb_auths_v2_control[0],
+ .info = NULL,
+ .session = AFB_SESSION_NONE_V2
+ },
+ {
+ .verb = "lua_dostring",
+ .callback = ctlapi_lua_dostring,
+ .auth = &_afb_auths_v2_control[0],
+ .info = NULL,
+ .session = AFB_SESSION_NONE_V2
+ },
+ {
+ .verb = "lua_doscript",
+ .callback = ctlapi_lua_doscript,
+ .auth = &_afb_auths_v2_control[0],
+ .info = NULL,
+ .session = AFB_SESSION_NONE_V2
+ },
+ { .verb = NULL }
+};
+
+const struct afb_binding_v2 afbBindingV2 = {
+ .api = "control",
+ .specification = _afb_description_v2_control,
+ .info = NULL,
+ .verbs = _afb_verbs_v2_control,
+ .preinit = NULL,
+ .init = CtlBindingInit,
+ .onevent = NULL,
+ .noconcurrency = 0
+};
+
diff --git a/Controler-afb/ctl-apidef.json b/Controler-afb/ctl-apidef.json
new file mode 100644
index 0000000..fddf301
--- /dev/null
+++ b/Controler-afb/ctl-apidef.json
@@ -0,0 +1,281 @@
+{
+ "openapi": "3.0.0",
+ "$schema": "http:iot.bzh/download/openapi/schema-3.0/default-schema.json",
+ "info": {
+ "description": "",
+ "title": "polctl",
+ "version": "1.0",
+ "x-binding-c-generator": {
+ "api": "control",
+ "version": 2,
+ "prefix": "ctlapi_",
+ "postfix": "",
+ "start": null,
+ "onevent": null,
+ "init": "CtlBindingInit",
+ "scope": "",
+ "private": false
+ }
+ },
+ "servers": [
+ {
+ "url": "ws://{host}:{port}/api/polctl",
+ "description": "Unicens2 API.",
+ "variables": {
+ "host": {
+ "default": "localhost"
+ },
+ "port": {
+ "default": "1234"
+ }
+ },
+ "x-afb-events": [
+ {
+ "$ref": "#/components/schemas/afb-event"
+ }
+ ]
+ }
+ ],
+ "components": {
+ "schemas": {
+ "afb-reply": {
+ "$ref": "#/components/schemas/afb-reply-v2"
+ },
+ "afb-event": {
+ "$ref": "#/components/schemas/afb-event-v2"
+ },
+ "afb-reply-v2": {
+ "title": "Generic response.",
+ "type": "object",
+ "required": ["jtype", "request"],
+ "properties": {
+ "jtype": {
+ "type": "string",
+ "const": "afb-reply"
+ },
+ "request": {
+ "type": "object",
+ "required": ["status"],
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "info": {
+ "type": "string"
+ },
+ "token": {
+ "type": "string"
+ },
+ "uuid": {
+ "type": "string"
+ },
+ "reqid": {
+ "type": "string"
+ }
+ }
+ },
+ "response": {
+ "type": "object"
+ }
+ }
+ },
+ "afb-event-v2": {
+ "type": "object",
+ "required": ["jtype", "event"],
+ "properties": {
+ "jtype": {
+ "type": "string",
+ "const": "afb-event"
+ },
+ "event": {
+ "type": "string"
+ },
+ "data": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "x-permissions": {
+ "monitor": {
+ "permission": "urn:AGL:permission:audio:public:monitor"
+ },
+ "multimedia": {
+ "permission": "urn:AGL:permission:audio:public:monitor"
+ },
+ "navigation": {
+ "permission": "urn:AGL:permission:audio:public:monitor"
+ },
+ "emergency": {
+ "permission": "urn:AGL:permission:audio:public:emergency"
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "A complex object array response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/afb-reply"
+ }
+ }
+ }
+ }
+ }
+ },
+ "paths": {
+ "/monitor": {
+ "description": "Subcribe Audio Agent Policy Control End",
+ "get": {
+ "x-permissions": {
+ "$ref": "#/components/x-permissions/monitor"
+ },
+ "parameters": [
+ {
+ "in": "query",
+ "name": "event_patern",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/components/responses/200"
+ }
+ }
+ }
+ },
+ "/event_test": {
+ "description": "Pause Resume Test",
+ "get": {
+ "x-permissions": {
+ "$ref": "#/components/x-permissions/monitor"
+ },
+ "parameters": [
+ {
+ "in": "query",
+ "name": "delay",
+ "required": false,
+ "schema": {
+ "type": "interger"
+ }
+ },
+ {
+ "in": "query",
+ "name": "count",
+ "required": false,
+ "schema": {
+ "type": "interger"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/components/responses/200"
+ }
+ }
+ }
+ },
+ "/navigation": {
+ "description": "Request Access to Navigation Audio Channel.",
+ "get": {
+ "x-permissions": {
+ "$ref": "#/components/x-permissions/navigation"
+ },
+ "parameters": [
+ {
+ "in": "query",
+ "name": "zone",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/components/responses/200"
+ }
+ }
+ }
+ },
+ "/lua_docall": {
+ "description": "Execute LUA string script.",
+ "get": {
+ "x-permissions": {
+ "$ref": "#/components/x-permissions/navigation"
+ },
+ "parameters": [
+ {
+ "in": "query",
+ "name": "func",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "in": "query",
+ "name": "args",
+ "required": false,
+ "schema": {
+ "type": "array"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/components/responses/200"
+ }
+ }
+ }
+ },
+ "/lua_dostring": {
+ "description": "Execute LUA string script.",
+ "get": {
+ "x-permissions": {
+ "$ref": "#/components/x-permissions/navigation"
+ },
+ "parameters": [
+ {
+ "in": "query",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/components/responses/200"
+ }
+ }
+ }
+ },
+ "/lua_doscript": {
+ "description": "Execute LUA string script.",
+ "get": {
+ "x-permissions": {
+ "$ref": "#/components/x-permissions/navigation"
+ },
+ "parameters": [
+ {
+ "in": "query",
+ "name": "filename",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/components/responses/200"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Controler-afb/ctl-binding.c b/Controler-afb/ctl-binding.c
new file mode 100644
index 0000000..45c4e1c
--- /dev/null
+++ b/Controler-afb/ctl-binding.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author Fulup Ar Foll <fulup@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 <time.h>
+
+#include "audio-common.h"
+#include "ctl-binding.h"
+
+
+
+// Include Binding Stub generated from Json OpenAPI
+#include "ctl-apidef.h"
+
+
+PUBLIC void ctlapi_navigation (afb_req request) {
+
+ ctlapi_authorize (CTLAPI_NAVIGATION, request);
+}
+
+PUBLIC void ctlapi_multimedia (afb_req request) {
+
+ ctlapi_authorize (CTLAPI_MULTIMEDIA, request);
+}
+
+PUBLIC void ctlapi_emergency (afb_req request) {
+
+ ctlapi_authorize (CTLAPI_EMERGENCY, request);
+}
+
+PUBLIC void ctlapi_monitor (afb_req request) {
+
+ // subscribe Client to event
+ int err = afb_req_subscribe(request, TimerEvtGet());
+ if (err != 0) {
+ afb_req_fail_f(request, "register-event", "Fail to subscribe binder event");
+ goto OnErrorExit;
+ }
+
+ afb_req_success(request, NULL, NULL);
+
+ OnErrorExit:
+ return;
+}
+
+// Create Binding Event at Init
+PUBLIC int CtlBindingInit () {
+
+ int errcount=0;
+
+ errcount += TimerEvtInit();
+ errcount += PolicyInit();
+ errcount += LuaLibInit();
+
+ AFB_DEBUG ("Audio Policy Control Binding Done errcount=%d", errcount);
+ return errcount;
+}
+
diff --git a/Controler-afb/ctl-binding.h b/Controler-afb/ctl-binding.h
new file mode 100644
index 0000000..e53d2ca
--- /dev/null
+++ b/Controler-afb/ctl-binding.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author Fulup Ar Foll <fulup@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.
+ */
+#include <systemd/sd-event.h>
+
+#include "audio-common.h"
+
+#ifndef CONTROLER_BINDING_INCLUDE
+#define CONTROLER_BINDING_INCLUDE
+
+// polctl-binding.c
+PUBLIC int CtlBindingInit ();
+
+// ctl-timerevt.c
+// ----------------------
+#define DEFAULT_PAUSE_DELAY 3000
+#define DEFAULT_TEST_COUNT 1
+typedef int (*timerCallbackT)(void *context);
+typedef struct {
+ int value;
+ const char *label;
+} AutoTestCtxT;
+
+typedef struct TimerHandleS {
+ int count;
+ int delay;
+ AutoTestCtxT *context;
+ timerCallbackT callback;
+ sd_event_source *evtSource;
+} TimerHandleT;
+
+PUBLIC int TimerEvtInit (void);
+PUBLIC afb_event TimerEvtGet(void);
+PUBLIC void ctlapi_event_test (afb_req request);
+
+// ctl-policy
+// -----------
+
+typedef struct PolicyActionS{
+ const char* label;
+ const char* api;
+ const char* verb;
+ json_object *argsJ;
+ const char *info;
+ int timeout;
+ json_object* (*actionCB)(struct PolicyActionS *action,json_object *response, void *context);
+} PolicyActionT;
+
+typedef struct {
+ const char* label;
+ const char *info;
+ const char *version;
+ void *context;
+} PolicyHandleT;
+
+typedef struct {
+ char *sharelib;
+ void *dlHandle;
+ PolicyHandleT **handle;
+ PolicyActionT **onload;
+ PolicyActionT **events;
+ PolicyActionT **controls;
+} PolicyCtlConfigT;
+
+typedef enum {
+ CTLAPI_NAVIGATION,
+ CTLAPI_MULTIMEDIA,
+ CTLAPI_EMERGENCY,
+
+ CTL_NONE=-1
+} PolicyCtlEnumT;
+
+PUBLIC int PolicyInit(void);
+PUBLIC json_object* ScanForConfig (char* searchPath, char * pre, char *ext);
+PUBLIC void ctlapi_authorize (PolicyCtlEnumT control, afb_req request);
+
+// ctl-lua.c
+PUBLIC int LuaLibInit ();
+PUBLIC void ctlapi_lua_docall (afb_req request);
+PUBLIC void ctlapi_lua_dostring (afb_req request);
+PUBLIC void ctlapi_lua_doscript (afb_req request);
+
+#endif
diff --git a/PolicyCtl-afb/polctl-binding.c b/Controler-afb/ctl-events.c
index d24b036..f444848 100644
--- a/PolicyCtl-afb/polctl-binding.c
+++ b/Controler-afb/ctl-events.c
@@ -21,35 +21,10 @@
#include <time.h>
#include <systemd/sd-event.h>
-#include "audio-interface.h"
-
-STATIC int polctl_init ();
-
-// Include Binding Stub generated from Json OpenAPI
-#include "polctl-apidef.h"
-
-#define DEFAULT_PAUSE_DELAY 3000
-#define DEFAULT_TEST_COUNT 1
-
-typedef int (*timerCallbackT)(void *context);
-
-
-typedef struct {
- int value;
- const char *label;
-} AutoTestCtxT;
-
-typedef struct TimerHandleS {
- int count;
- int delay;
- AutoTestCtxT *context;
- timerCallbackT callback;
- sd_event_source *evtSource;
-} TimerHandleT;
+#include "ctl-binding.h"
static afb_event afbevt;
-
STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
TimerHandleT *timerHandle = (TimerHandleT*) handle;
int done;
@@ -71,23 +46,12 @@ STATIC int TimerNext (sd_event_source* source, uint64_t timer, void* handle) {
return 0;
OnErrorExit:
- AFB_WARNING("TimerNext Fail tag=%s", timerHandle->context->label);
+ AFB_WARNING("TimerNext Callback Fail Tag=%s", timerHandle->context->label);
return -1;
}
-STATIC void TimerStart(TimerHandleT *timerHandle, timerCallbackT callback, void *context) {
- uint64_t usec;
-
- // populate CB handle
- timerHandle->callback=callback;
- timerHandle->context=context;
-
- // set a timer with ~250us accuracy
- sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec);
- sd_event_add_time(afb_daemon_get_event_loop(), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay, 250, TimerNext, timerHandle);
-}
-STATIC int DoPauseResumeCB (void *context) {
+STATIC int DoSendEvent (void *context) {
AutoTestCtxT *ctx= (AutoTestCtxT*)context;
json_object *ctlEventJ;
@@ -99,18 +63,41 @@ STATIC int DoPauseResumeCB (void *context) {
json_object_object_add(ctlEventJ,"value" , json_object_new_int(ctx->value));
int done = afb_event_push(afbevt, ctlEventJ);
- AFB_NOTICE ("DoPauseResumeCB {action: '%s', value:%d} status=%d", ctx->label, ctx->value, done);
+ AFB_NOTICE ("DoSendEvent {action: '%s', value:%d} status=%d", ctx->label, ctx->value, done);
return (done);
}
-PUBLIC void polctl_event_test (afb_req request) {
+STATIC void TimerEvtStart(TimerHandleT *timerHandle, void *context) {
+ uint64_t usec;
+
+ // populate CB handle
+ timerHandle->callback=DoSendEvent;
+ timerHandle->context=context;
+
+ // set a timer with ~250us accuracy
+ sd_event_now(afb_daemon_get_event_loop(), CLOCK_MONOTONIC, &usec);
+ sd_event_add_time(afb_daemon_get_event_loop(), &timerHandle->evtSource, CLOCK_MONOTONIC, usec+timerHandle->delay, 250, TimerNext, timerHandle);
+}
+
+PUBLIC afb_event TimerEvtGet(void) {
+ return afbevt;
+}
+
+
+// Generated some fake event based on watchdog/counter
+PUBLIC void ctlapi_event_test (afb_req request) {
json_object *queryJ, *tmpJ;
TimerHandleT *timerHandle = malloc (sizeof (TimerHandleT));
AutoTestCtxT *context = calloc (1, sizeof (AutoTestCtxT));
int done;
queryJ= afb_req_json(request);
+
+ // Closing call only has one parameter
+ done=json_object_object_get_ex(queryJ, "closing", &tmpJ);
+ if (done) return;
+
done=json_object_object_get_ex(queryJ, "label", &tmpJ);
if (!done) {
afb_req_fail_f(request, "TEST-LABEL-MISSING", "label is mandatory for event_test");
@@ -127,7 +114,7 @@ PUBLIC void polctl_event_test (afb_req request) {
if (timerHandle->count == 0) timerHandle->count=DEFAULT_TEST_COUNT;
// start a lool timer
- TimerStart (timerHandle, DoPauseResumeCB, context);
+ TimerEvtStart (timerHandle, context);
afb_req_success(request, NULL, NULL);
return;
@@ -136,39 +123,17 @@ PUBLIC void polctl_event_test (afb_req request) {
return;
}
-
-PUBLIC void polctl_navigation (afb_req request) {
-
- AFB_NOTICE ("Enter polctl_navigation");
- afb_req_success(request, NULL, NULL);
-}
-
-PUBLIC void polctl_monitor (afb_req request) {
-
- // subscribe Client to event
- int err = afb_req_subscribe(request, afbevt);
- if (err != 0) {
- afb_req_fail_f(request, "register-event", "Fail to subscribe binder event");
- goto OnErrorExit;
- }
-
- afb_req_success(request, NULL, NULL);
-
- OnErrorExit:
- return;
-}
-
// Create Binding Event at Init
-PUBLIC int polctl_init () {
- AFB_DEBUG ("Audio Policy Control Binding Init");
+PUBLIC int TimerEvtInit () {
// create binder event to send test pause/resume
afbevt = afb_daemon_make_event("request");
if (!afb_event_is_valid(afbevt)) {
- AFB_ERROR ("POLCTL_INIT: Cannot register polctl event");
- return (1);
+ AFB_ERROR ("POLCTL_INIT: Cannot register ctl-events");
+ return 1;
}
+ AFB_DEBUG ("Audio Control-Events Init Done");
return 0;
}
diff --git a/Controler-afb/ctl-lua.c b/Controler-afb/ctl-lua.c
new file mode 100644
index 0000000..0e44bc9
--- /dev/null
+++ b/Controler-afb/ctl-lua.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author Fulup Ar Foll <fulup@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.
+ * ref:
+ * http://www.troubleshooters.com/codecorn/lua/lua_c_calls_lua.htm#_Anatomy_of_a_Lua_Call
+ * http://acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+#include "ctl-binding.h"
+#include "wrap-json.h"
+
+
+static lua_State* luaState;
+
+typedef enum {
+ LUA_DOCALL,
+ LUA_DOSTRING,
+ LUA_DOSCRIPT,
+} LuaDoActionT;
+
+// List Avaliable Configuration Files
+PUBLIC json_object* ScanForConfig (char* searchPath, char *pre, char *ext) {
+ json_object *responseJ;
+ DIR *dirHandle;
+ char *dirPath;
+ char* dirList= strdup(searchPath);
+ size_t extLen = strlen(ext);
+
+ responseJ = json_object_new_array();
+ for (dirPath= strtok(dirList, ":"); dirPath && *dirPath; dirPath=strtok(NULL,":")) {
+ struct dirent *dirEnt;
+
+ dirHandle = opendir (dirPath);
+ if (!dirHandle) {
+ AFB_NOTICE ("CONFIG-SCANNING dir=%s not readable", dirPath);
+ continue;
+ }
+
+ AFB_NOTICE ("CONFIG-SCANNING:ctl_listconfig scanning: %s", dirPath);
+ while ((dirEnt = readdir(dirHandle)) != NULL) {
+ // Unknown type is accepted to support dump filesystems
+ if (dirEnt->d_type == DT_REG || dirEnt->d_type == DT_UNKNOWN) {
+
+ // check prefix and extention
+ size_t extIdx=strlen(dirEnt->d_name) - extLen;
+ if (extIdx <= 0) continue;
+ if (pre && !strcasestr (dirEnt->d_name, pre)) continue;
+ if (ext && strcasecmp (ext, &dirEnt->d_name[extIdx])) continue;
+
+ struct json_object *pathJ = json_object_new_object();
+ json_object_object_add(pathJ, "dirpath", json_object_new_string(dirPath));
+ json_object_object_add(pathJ, "filename", json_object_new_string(dirEnt->d_name));
+ json_object_array_add(responseJ, pathJ);
+ }
+ }
+ }
+
+ free (dirList);
+ return (responseJ);
+}
+
+STATIC int LuaPrintNotice(lua_State* luaState) {
+ int count = lua_gettop(luaState);
+
+ for (int idx=1; idx <= count; ++idx) {
+ const char *str = lua_tostring(luaState, idx); // Get string
+
+ // Output string.
+ AFB_NOTICE (str);
+ }
+
+ return 0; // no value return
+}
+
+STATIC int LuaPushArgument (json_object *arg) {
+
+ switch (json_object_get_type(arg)) {
+ case json_type_object:
+ lua_newtable (luaState);
+ json_object_object_foreach (arg, key, val) {
+ int done = LuaPushArgument (val);
+ if (done) {
+ lua_pushstring(luaState, key); // table.key = val
+ lua_settable(luaState, -3);
+ }
+ }
+
+ break;
+ case json_type_int:
+ lua_pushinteger(luaState, json_object_get_int(arg));
+ break;
+ case json_type_string:
+ lua_pushstring(luaState, json_object_get_string(arg));
+ break;
+ case json_type_boolean:
+ lua_pushboolean(luaState, json_object_get_boolean(arg));
+ break;
+ case json_type_double:
+ lua_pushnumber(luaState, json_object_get_double(arg));
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+// Generated some fake event based on watchdog/counter
+PUBLIC void LuaDoAction (LuaDoActionT action, afb_req request) {
+
+ int err, count=0;
+
+ json_object* queryJ = afb_req_json(request);
+
+ switch (action) {
+
+ case LUA_DOSTRING: {
+ const char *script = json_object_get_string(queryJ);
+ err=luaL_loadstring(luaState, script);
+ if (err) {
+ AFB_ERROR ("LUA-DO-COMPILE:FAIL String=%s err=%s", script, lua_tostring(luaState,-1) );
+ goto OnErrorExit;
+ }
+ break;
+ }
+
+ case LUA_DOCALL: {
+ const char *func;
+ json_object *args;
+ err= wrap_json_unpack (queryJ, "{s:s, s?o !}", "func", &func,"args", &args);
+ if (err) {
+ AFB_ERROR ("LUA-DOCALL-SYNTAX missing func|args args=%s", json_object_get_string(queryJ));
+ goto OnErrorExit;
+ }
+
+ // load function (should exist in CONTROL_PATH_LUA
+ lua_getglobal(luaState, func);
+
+ // push arguments on the stack
+ if (json_object_get_type(args) != json_type_array) {
+ count= LuaPushArgument (args);
+ } else {
+ for (int idx=0; idx<json_object_array_length(args); idx++) {
+ count += LuaPushArgument (json_object_array_get_idx(args, idx));
+ if (err) break;
+ }
+ }
+
+ break;
+ }
+
+ case LUA_DOSCRIPT: {
+ const char *script;
+ json_object *args;
+ int index;
+
+ // scan luascript search path once
+ static json_object *luaScriptPathJ =NULL;
+ if (!luaScriptPathJ) luaScriptPathJ= ScanForConfig(CONTROL_PATH_LUA , NULL, "lua");
+
+ err= wrap_json_unpack (queryJ, "{s:s, s?o s?o !}", "script", &script,"args", &args, "arg", &args);
+ if (err) {
+ AFB_ERROR ("LUA-DOCALL-SYNTAX missing script|(args,arg) args=%s", json_object_get_string(queryJ));
+ goto OnErrorExit;
+ }
+
+ // push arguments on the stack
+ if (json_object_get_type(args) != json_type_array) {
+ lua_createtable(luaState, 1, 0);
+ count= LuaPushArgument (args);
+ } else {
+ int length= json_object_array_length(args);
+ lua_createtable(luaState, length, 0);
+ for (int idx=0; idx < length; idx++) {
+ count += LuaPushArgument (json_object_array_get_idx(args, idx));
+ if (err) break;
+ }
+ }
+
+ for (index=0; index < json_object_array_length(luaScriptPathJ); index++) {
+ char *filename; char*dirpath;
+ json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index);
+
+ err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "dirpath", &dirpath,"filename", &filename);
+ if (err) {
+ AFB_ERROR ("LUA-DOSCRIPT HOOPs invalid LUA script path = %s", json_object_get_string(entryJ));
+ goto OnErrorExit;
+ }
+
+ if (strcmp(filename, script)) continue;
+
+ char filepath[255];
+ strncpy(filepath, dirpath, sizeof(filepath));
+ strncat(filepath, "/", sizeof(filepath));
+ strncat(filepath, filename, sizeof(filepath));
+ err= luaL_loadfile(luaState, filepath);
+ if (err) {
+ AFB_ERROR ("LUA-DOSCRIPT HOOPs Error in LUA loading scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
+ goto OnErrorExit;
+ }
+ break;
+ }
+
+ if (index == json_object_array_length(luaScriptPathJ)) {
+ AFB_ERROR ("LUA-DOSCRIPT HOOPs script=%s not in path=%s", script, CONTROL_PATH_LUA);
+ goto OnErrorExit;
+
+ }
+
+ //lua_setglobal(luaState, "args");
+ count=1;
+
+ break;
+ }
+
+ default:
+ AFB_ERROR ("LUA-DOCALL-ACTION unknown query=%s", json_object_get_string(queryJ));
+ goto OnErrorExit;
+ }
+
+ // effectively exec LUA code
+// err=lua_pcall(luaState, count, LUA_MULTRET, 0);
+ err=lua_pcall(luaState, count, LUA_MULTRET, 0);
+ if (err) {
+ AFB_ERROR ("LUA-DO-EXEC:FAIL query=%s err=%s", json_object_get_string(queryJ), lua_tostring(luaState,-1) );
+ goto OnErrorExit;
+ }
+
+ // number of return values
+ count=lua_gettop(luaState);
+
+ // Check status return true=OK false=fail
+ if (count == 0 || !lua_isboolean(luaState, 1)) {
+ AFB_ERROR ("LUA-DO-RETURN:INVALID 1st return argument not boolean query=%s", json_object_get_string(queryJ) );
+ goto OnErrorExit;
+ }
+
+ // get return fail/ok status
+ const int returnStatus=lua_toboolean(luaState, 1);
+
+ // loop on remaining return arguments
+ json_object *returnArgs = json_object_new_array();
+ for (int idx=2; idx <= count; idx++) {
+
+ // push on stack return value (Fulup in LUA-5.3 the two functions are combined)
+ int valueType=lua_type (luaState, idx);
+
+ switch(valueType) {
+ case LUA_TNUMBER:
+ json_object_array_add(returnArgs, json_object_new_double(lua_tonumber(luaState, idx)));
+ break;
+ case LUA_TBOOLEAN:
+ json_object_array_add(returnArgs, json_object_new_boolean(lua_toboolean(luaState, idx)));
+ break;
+ case LUA_TSTRING:
+ json_object_array_add(returnArgs, json_object_new_string(lua_tostring(luaState, idx)));
+ break;
+ case LUA_TTABLE:
+ default:
+ AFB_NOTICE ("script returned Unknown/Unsupported type: ");
+ }
+
+ }
+
+ // pop stack including Func/String/Script call
+ lua_pop(luaState, count+1);
+
+ if(returnStatus)
+ afb_req_success(request, returnArgs, NULL);
+ else
+ afb_req_fail(request, "LUA-DOACTION-FAIL", json_object_get_string(returnArgs));
+
+ return;
+
+ OnErrorExit:
+ afb_req_fail(request,"LUA:ERROR", lua_tostring(luaState,-1));
+ return;
+}
+
+PUBLIC void ctlapi_lua_dostring (afb_req request) {
+
+ LuaDoAction (LUA_DOSTRING, request);
+}
+
+PUBLIC void ctlapi_lua_docall (afb_req request) {
+
+ LuaDoAction (LUA_DOCALL, request);
+}
+
+PUBLIC void ctlapi_lua_doscript (afb_req request) {
+
+ LuaDoAction (LUA_DOSCRIPT, request);
+}
+
+
+// Create Binding Event at Init
+PUBLIC int LuaLibInit () {
+ int err, index;
+
+ // search for default policy config file
+ json_object *luaScriptPathJ = ScanForConfig(CONTROL_PATH_LUA , "onload", "lua");
+
+ // open a new LUA interpretor
+ luaState = luaL_newstate();
+ if (!luaState) {
+ AFB_ERROR ("LUA_INIT: Fail to open lua interpretor");
+ goto OnErrorExit;
+ }
+
+ // load auxiliary libraries
+ luaL_openlibs(luaState);
+
+ // redirect print to AFB_NOTICE
+ lua_register(luaState,"print", LuaPrintNotice );
+ //lua_register(lauHandle,"AFB_DEBUG", LuaAFBDebug);
+
+ // load+exec any file found in LUA search path
+ for (index=0; index < json_object_array_length(luaScriptPathJ); index++) {
+ json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index);
+
+ char *filename; char*dirpath;
+ err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "dirpath", &dirpath,"filename", &filename);
+ if (err) {
+ AFB_ERROR ("LUA-INIT HOOPs invalid config file path = %s", json_object_get_string(entryJ));
+ goto OnErrorExit;
+ }
+
+ char filepath[255];
+ strncpy(filepath, dirpath, sizeof(filepath));
+ strncat(filepath, "/", sizeof(filepath));
+ strncat(filepath, filename, sizeof(filepath));
+ err= luaL_loadfile(luaState, filepath);
+ if (err) {
+ AFB_ERROR ("LUA-LOAD HOOPs Error in LUA loading scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
+ goto OnErrorExit;
+ }
+
+ // exec/compil script
+ err = lua_pcall(luaState, 0, 0, 0);
+ if (err) {
+ AFB_ERROR ("LUA-LOAD HOOPs Error in LUA exec scripts=%s err=%s", filepath, lua_tostring(luaState,-1));
+ goto OnErrorExit;
+ }
+
+ }
+
+ // no policy config found remove control API from binder
+ if (index == 0) {
+ AFB_WARNING ("POLICY-INIT:WARNING No Control LUA file in path=[%s]", CONTROL_PATH_LUA);
+ }
+
+
+ AFB_DEBUG ("Audio control-LUA Init Done");
+ return 0;
+
+ OnErrorExit:
+ return -1;
+}
+ \ No newline at end of file
diff --git a/Controler-afb/ctl-policy.c b/Controler-afb/ctl-policy.c
new file mode 100644
index 0000000..7ad73fa
--- /dev/null
+++ b/Controler-afb/ctl-policy.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author Fulup Ar Foll <fulup@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, something 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_object.h>
+
+#include "wrap-json.h"
+#include "ctl-binding.h"
+
+STATIC PolicyCtlConfigT *ctlHandle = NULL;
+
+
+PUBLIC void ctlapi_authorize (PolicyCtlEnumT control, afb_req request) {
+ json_object*tmpJ;
+
+ json_object* argsJ= afb_req_json(request);
+ int done=json_object_object_get_ex(argsJ, "closing", &tmpJ);
+ if (done) return;
+
+}
+
+
+// List Avaliable Configuration Files
+PUBLIC void ctlapi_config (struct afb_req request) {
+ json_object*tmpJ;
+ char *dirList;
+
+ json_object* argsJ = afb_req_json(request);
+ if (argsJ && json_object_object_get_ex (argsJ, "cfgpath" , &tmpJ)) {
+ dirList = strdup (json_object_get_string(tmpJ));
+ } else {
+ dirList = strdup (CONTROL_PATH_POLICY);
+ AFB_NOTICE ("CONFIG-MISSING: use default CONTROL_PATH_POLICY=%s", CONTROL_PATH_POLICY);
+ }
+
+ // get list of config file
+ struct json_object *responseJ = ScanForConfig(dirList, "onload", "json");
+
+ if (json_object_array_length(responseJ) == 0) {
+ afb_req_fail(request, "CONFIGPATH:EMPTY", "No Config Found in CONTROL_PATH_POLICY");
+ } else {
+ afb_req_success(request, responseJ, NULL);
+ }
+
+ return;
+}
+
+STATIC PolicyActionT *PolicyLoadActions (json_object *actionsJ) {
+ int err;
+ PolicyActionT *actions;
+ char *callback; // need to search in DL lib
+
+ // unpack individual action object
+ int actionUnpack (json_object *actionJ, PolicyActionT *action) {
+
+ err= wrap_json_unpack(actionJ, "{ss,s?s,s?o,s?s,s?s,s?s !}"
+ , "label",&action->label, "info",&action->info, "callback",&callback, "args",&action->argsJ, "api",&action->api, "verb", &action->verb);
+ if (err) {
+ AFB_ERROR ("POLICY-LOAD-ACTION Missing something label|info|callback|api|verb|args in %s", json_object_get_string(actionJ));
+ return -1;
+ }
+ if (!callback || !(action->api && action->verb)) {
+ AFB_ERROR ("POLICY-LOAD-ACTION Missing something callback|(api+verb) in %s", json_object_get_string(actionJ));
+ return -1;
+ }
+ return 0;
+ };
+
+ // action array is close with a nullvalue;
+ if (json_object_get_type(actionsJ) == json_type_array) {
+ int count = json_object_array_length(actionsJ);
+ actions = calloc (count+1, sizeof(PolicyActionT));
+
+ for (int idx=0; idx < count; idx++) {
+ json_object *actionJ = json_object_array_get_idx(actionsJ, idx);
+ err = actionUnpack (actionJ, &actions[idx]);
+ if (err) goto OnErrorExit;
+ }
+
+ } else {
+ actions = calloc (2, sizeof(PolicyActionT));
+ err = actionUnpack (actionsJ, &actions[0]);
+ if (err) goto OnErrorExit;
+ }
+
+ return actions;
+
+ OnErrorExit:
+ return NULL;
+
+}
+
+// load control policy from file using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values
+STATIC PolicyCtlConfigT *PolicyLoadConfig (const char* filepath) {
+ json_object *policyConfigJ, *ignoreJ, *actionsJ;
+ PolicyCtlConfigT *policyConfig = calloc (1, sizeof(PolicyCtlConfigT));
+ int err;
+
+ // Load JSON file
+ policyConfigJ= json_object_from_file(filepath);
+ if (!policyConfigJ) goto OnErrorExit;
+
+ json_object *metadataJ, *onloadJ, *controlsJ, *eventsJ;
+ err= wrap_json_unpack(policyConfigJ, "{s?o,so,s?o,so,so !}", "$schema", &ignoreJ, "metadata",&metadataJ, "onload",&onloadJ, "controls",&controlsJ, "events",&eventsJ);
+ if (err) {
+ AFB_ERROR ("POLICY-LOAD-ERRROR Missing something metadata|onload|controls|events in %s", json_object_get_string(policyConfigJ));
+ goto OnErrorExit;
+ }
+
+ PolicyHandleT *policyHandle = calloc (1, sizeof(PolicyHandleT));
+ err= wrap_json_unpack(metadataJ, "{so,s?s,s?s !}", "label", &policyHandle->label, "info",&policyHandle->info, "version",&policyHandle->version);
+ if (err) {
+ AFB_ERROR ("POLICY-LOAD-CONFIG Missing something label|info|version in %s", json_object_get_string(metadataJ));
+ goto OnErrorExit;
+ }
+
+ if (onloadJ) {
+ err= wrap_json_unpack(onloadJ, "{s?o,s?s,s?s !}", "info",&ignoreJ, "label",&ignoreJ, "actions",&actionsJ);
+ if (err) {
+ AFB_ERROR ("POLICY-LOAD-CONFIG Missing something label|info|plugin|actions in %s", json_object_get_string(metadataJ));
+ goto OnErrorExit;
+ }
+ policyConfig->onload= PolicyLoadActions (actionsJ);
+ }
+
+ return policyConfig;
+
+OnErrorExit:
+ return NULL;
+}
+
+// Load default config file at init
+PUBLIC int PolicyInit () {
+ int index, err;
+
+
+ // search for default policy config file
+ json_object* responseJ = ScanForConfig(CONTROL_PATH_POLICY, "onload", "json");
+ return 0;
+
+ for (index=0; index < json_object_array_length(responseJ); index++) {
+ json_object *entryJ=json_object_array_get_idx(responseJ, index);
+
+ char *filename; char*dirpath;
+ err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "dirpath", &dirpath,"filename", &filename);
+ if (err) {
+ AFB_ERROR ("POLICY-INIT HOOPs invalid config file path = %s", json_object_get_string(entryJ));
+ goto OnErrorExit;
+ }
+
+ if (strcasestr(filename, CONTROL_FILE_POLICY)) {
+ char filepath[255];
+ strncpy(filepath, dirpath, sizeof(filepath));
+ strncat(filepath, "/", sizeof(filepath));
+ strncat(filepath, filename, sizeof(filepath));
+ ctlHandle = PolicyLoadConfig (filepath);
+ if (!ctlHandle) {
+ AFB_ERROR ("POLICY-INIT:ERROR No File to load [%s]", filepath);
+ goto OnErrorExit;
+ }
+ break;
+ }
+ }
+
+ // no policy config found remove control API from binder
+ if (index == 0) {
+ AFB_WARNING ("POLICY-INIT:WARNING No Control policy file [%s]", CONTROL_FILE_POLICY);
+ }
+
+ AFB_NOTICE ("POLICY-INIT:SUCCES: Audio Control Policy Init");
+ return 0;
+
+OnErrorExit:
+ AFB_NOTICE ("POLICY-INIT:ERROR: Audio Control Policy Init");
+ return 1;
+}
+
+
+
diff --git a/HAL-afb/HAL-interface/CMakeLists.txt b/HAL-afb/HAL-interface/CMakeLists.txt
index d20a283..37d82de 100644
--- a/HAL-afb/HAL-interface/CMakeLists.txt
+++ b/HAL-afb/HAL-interface/CMakeLists.txt
@@ -28,7 +28,7 @@ PROJECT_TARGET_ADD(hal-interface)
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
- audio-interface
+ audio-common
)
# Define target includes
diff --git a/HAL-afb/HAL-interface/hal-interface.h b/HAL-afb/HAL-interface/hal-interface.h
index a6310e7..c210f02 100644
--- a/HAL-afb/HAL-interface/hal-interface.h
+++ b/HAL-afb/HAL-interface/hal-interface.h
@@ -21,7 +21,7 @@
#include <stdio.h>
#include <alsa/asoundlib.h>
-#include "audio-interface.h"
+#include "audio-common.h"
#include <systemd/sd-event.h>
typedef enum {
diff --git a/HAL-afb/HDA-intel/CMakeLists.txt b/HAL-afb/HDA-intel/CMakeLists.txt
index efe244d..37e277b 100644
--- a/HAL-afb/HDA-intel/CMakeLists.txt
+++ b/HAL-afb/HDA-intel/CMakeLists.txt
@@ -34,7 +34,7 @@ PROJECT_TARGET_ADD(hal-intel-hda)
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
hal-interface
- audio-interface
+ audio-common
)
# installation directory
diff --git a/HAL-afb/HDA-intel/IntelHdaHAL.c b/HAL-afb/HDA-intel/IntelHdaHAL.c
index f5c260e..ab822ca 100644
--- a/HAL-afb/HDA-intel/IntelHdaHAL.c
+++ b/HAL-afb/HDA-intel/IntelHdaHAL.c
@@ -23,7 +23,7 @@
*/
#define _GNU_SOURCE
#include "hal-interface.h"
-#include "audio-interface.h"
+#include "audio-common.h"
// Default Values for MasterVolume Ramping
diff --git a/HAL-afb/Jabra-Solemate/CMakeLists.txt b/HAL-afb/Jabra-Solemate/CMakeLists.txt
index 9504175..973e95d 100644
--- a/HAL-afb/Jabra-Solemate/CMakeLists.txt
+++ b/HAL-afb/Jabra-Solemate/CMakeLists.txt
@@ -34,7 +34,7 @@ PROJECT_TARGET_ADD(hal-jabra-usb)
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
hal-interface
- audio-interface
+ audio-common
)
# installation directory
diff --git a/HAL-afb/Jabra-Solemate/JabraUsbHAL.c b/HAL-afb/Jabra-Solemate/JabraUsbHAL.c
index f3753ec..7eeab90 100644
--- a/HAL-afb/Jabra-Solemate/JabraUsbHAL.c
+++ b/HAL-afb/Jabra-Solemate/JabraUsbHAL.c
@@ -24,7 +24,7 @@
*/
#define _GNU_SOURCE
#include "hal-interface.h"
-#include "audio-interface.h"
+#include "audio-common.h"
// Define few private tag for not standard functions
#define PCM_Volume_Multimedia 1000
diff --git a/HAL-afb/Scarlett-Focusrite/CMakeLists.txt b/HAL-afb/Scarlett-Focusrite/CMakeLists.txt
index 93752a7..48d5964 100644
--- a/HAL-afb/Scarlett-Focusrite/CMakeLists.txt
+++ b/HAL-afb/Scarlett-Focusrite/CMakeLists.txt
@@ -34,7 +34,7 @@ PROJECT_TARGET_ADD(hal-scalett-usb)
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
hal-interface
- audio-interface
+ audio-common
)
# installation directory
diff --git a/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c b/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c
index 9b31c96..94bfa4f 100644
--- a/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c
+++ b/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c
@@ -24,7 +24,7 @@
*/
#define _GNU_SOURCE
#include "hal-interface.h"
-#include "audio-interface.h"
+#include "audio-common.h"
// Default Values for MasterVolume Ramping
STATIC halVolRampT volRampMaster= {
diff --git a/PolicyCtl-afb/polctl-apidef.h b/PolicyCtl-afb/polctl-apidef.h
deleted file mode 100644
index 9e2b1a7..0000000
--- a/PolicyCtl-afb/polctl-apidef.h
+++ /dev/null
@@ -1,90 +0,0 @@
-
-static const char _afb_description_v2_polctl[] =
- "{\"openapi\":\"3.0.0\",\"$schema\":\"http:iot.bzh/download/openapi/schem"
- "a-3.0/default-schema.json\",\"info\":{\"description\":\"\",\"title\":\"p"
- "olctl\",\"version\":\"1.0\",\"x-binding-c-generator\":{\"api\":\"polctl\""
- ",\"version\":2,\"prefix\":\"polctl_\",\"postfix\":\"\",\"start\":null,\""
- "onevent\":null,\"init\":\"polctl_init\",\"scope\":\"\",\"private\":false"
- "}},\"servers\":[{\"url\":\"ws://{host}:{port}/api/polctl\",\"description"
- "\":\"Unicens2 API.\",\"variables\":{\"host\":{\"default\":\"localhost\"}"
- ",\"port\":{\"default\":\"1234\"}},\"x-afb-events\":[{\"$ref\":\"#/compon"
- "ents/schemas/afb-event\"}]}],\"components\":{\"schemas\":{\"afb-reply\":"
- "{\"$ref\":\"#/components/schemas/afb-reply-v2\"},\"afb-event\":{\"$ref\""
- ":\"#/components/schemas/afb-event-v2\"},\"afb-reply-v2\":{\"title\":\"Ge"
- "neric response.\",\"type\":\"object\",\"required\":[\"jtype\",\"request\""
- "],\"properties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-reply\""
- "},\"request\":{\"type\":\"object\",\"required\":[\"status\"],\"propertie"
- "s\":{\"status\":{\"type\":\"string\"},\"info\":{\"type\":\"string\"},\"t"
- "oken\":{\"type\":\"string\"},\"uuid\":{\"type\":\"string\"},\"reqid\":{\""
- "type\":\"string\"}}},\"response\":{\"type\":\"object\"}}},\"afb-event-v2"
- "\":{\"type\":\"object\",\"required\":[\"jtype\",\"event\"],\"properties\""
- ":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-event\"},\"event\":{\"t"
- "ype\":\"string\"},\"data\":{\"type\":\"object\"}}}},\"x-permissions\":{\""
- "monitor\":{\"permission\":\"urn:AGL:permission:audio:public:monitor\"},\""
- "multimedia\":{\"permission\":\"urn:AGL:permission:audio:public:monitor\""
- "},\"navigation\":{\"permission\":\"urn:AGL:permission:audio:public:monit"
- "or\"},\"emergency\":{\"permission\":\"urn:AGL:permission:audio:public:em"
- "ergency\"}},\"responses\":{\"200\":{\"description\":\"A complex object a"
- "rray response\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":"
- "\"#/components/schemas/afb-reply\"}}}}}},\"paths\":{\"/monitor\":{\"desc"
- "ription\":\"Subcribe Audio Agent Policy Control End\",\"get\":{\"x-permi"
- "ssions\":{\"$ref\":\"#/components/x-permissions/monitor\"},\"parameters\""
- ":[{\"in\":\"query\",\"name\":\"event_patern\",\"required\":true,\"schema"
- "\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/componen"
- "ts/responses/200\"}}}},\"/event_test\":{\"description\":\"Pause Resume T"
- "est\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/"
- "monitor\"},\"parameters\":[{\"in\":\"query\",\"name\":\"delay\",\"requir"
- "ed\":false,\"schema\":{\"type\":\"interger\"}},{\"in\":\"query\",\"name\""
- ":\"count\",\"required\":false,\"schema\":{\"type\":\"interger\"}}],\"res"
- "ponses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/naviga"
- "tion\":{\"description\":\"Request Access to Navigation Audio Channel.\","
- "\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/naviga"
- "tion\"},\"parameters\":[{\"in\":\"query\",\"name\":\"zone\",\"required\""
- ":false,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref"
- "\":\"#/components/responses/200\"}}}}}}"
-;
-
-static const struct afb_auth _afb_auths_v2_polctl[] = {
- { .type = afb_auth_Permission, .text = "urn:AGL:permission:audio:public:monitor" }
-};
-
- void polctl_monitor(struct afb_req req);
- void polctl_event_test(struct afb_req req);
- void polctl_navigation(struct afb_req req);
-
-static const struct afb_verb_v2 _afb_verbs_v2_polctl[] = {
- {
- .verb = "monitor",
- .callback = polctl_monitor,
- .auth = &_afb_auths_v2_polctl[0],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "event_test",
- .callback = polctl_event_test,
- .auth = &_afb_auths_v2_polctl[0],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "navigation",
- .callback = polctl_navigation,
- .auth = &_afb_auths_v2_polctl[0],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- { .verb = NULL }
-};
-
-const struct afb_binding_v2 afbBindingV2 = {
- .api = "polctl",
- .specification = _afb_description_v2_polctl,
- .info = NULL,
- .verbs = _afb_verbs_v2_polctl,
- .preinit = NULL,
- .init = polctl_init,
- .onevent = NULL,
- .noconcurrency = 0
-};
-
diff --git a/PolicyCtl-afb/polctl-apidef.json b/PolicyCtl-afb/polctl-apidef.json
deleted file mode 100644
index 65fe0ec..0000000
--- a/PolicyCtl-afb/polctl-apidef.json
+++ /dev/null
@@ -1,175 +0,0 @@
-{
- "openapi": "3.0.0",
- "$schema": "http:iot.bzh/download/openapi/schema-3.0/default-schema.json",
- "info": {
- "description": "",
- "title": "polctl",
- "version": "1.0",
- "x-binding-c-generator": {
- "api": "polctl",
- "version": 2,
- "prefix": "polctl_",
- "postfix": "",
- "start": null ,
- "onevent": null,
- "init": "polctl_init",
- "scope": "",
- "private": false
- }
- },
- "servers": [
- {
- "url": "ws://{host}:{port}/api/polctl",
- "description": "Unicens2 API.",
- "variables": {
- "host": {
- "default": "localhost"
- },
- "port": {
- "default": "1234"
- }
- },
- "x-afb-events": [
- {
- "$ref": "#/components/schemas/afb-event"
- }
- ]
- }
- ],
- "components": {
- "schemas": {
- "afb-reply": {
- "$ref": "#/components/schemas/afb-reply-v2"
- },
- "afb-event": {
- "$ref": "#/components/schemas/afb-event-v2"
- },
- "afb-reply-v2": {
- "title": "Generic response.",
- "type": "object",
- "required": [ "jtype", "request" ],
- "properties": {
- "jtype": {
- "type": "string",
- "const": "afb-reply"
- },
- "request": {
- "type": "object",
- "required": [ "status" ],
- "properties": {
- "status": { "type": "string" },
- "info": { "type": "string" },
- "token": { "type": "string" },
- "uuid": { "type": "string" },
- "reqid": { "type": "string" }
- }
- },
- "response": { "type": "object" }
- }
- },
- "afb-event-v2": {
- "type": "object",
- "required": [ "jtype", "event" ],
- "properties": {
- "jtype": {
- "type": "string",
- "const": "afb-event"
- },
- "event": { "type": "string" },
- "data": { "type": "object" }
- }
- }
- },
- "x-permissions": {
- "monitor": {
- "permission": "urn:AGL:permission:audio:public:monitor"
- },
- "multimedia": {
- "permission": "urn:AGL:permission:audio:public:monitor"
- },
- "navigation": {
- "permission": "urn:AGL:permission:audio:public:monitor"
- },
- "emergency": {
- "permission": "urn:AGL:permission:audio:public:emergency"
- }
- },
- "responses": {
- "200": {
- "description": "A complex object array response",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/afb-reply"
- }
- }
- }
- }
- }
- },
- "paths": {
- "/monitor": {
- "description": "Subcribe Audio Agent Policy Control End",
- "get": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/monitor"
- },
- "parameters": [
- {
- "in": "query",
- "name": "event_patern",
- "required": true,
- "schema": { "type": "string" }
- }
- ],
- "responses": {
- "200": {"$ref": "#/components/responses/200"}
- }
- }
- },
- "/event_test": {
- "description": "Pause Resume Test",
- "get": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/monitor"
- },
- "parameters": [
- {
- "in": "query",
- "name": "delay",
- "required": false,
- "schema": { "type": "interger" }
- },
- {
- "in": "query",
- "name": "count",
- "required": false,
- "schema": { "type": "interger" }
- }
- ],
- "responses": {
- "200": {"$ref": "#/components/responses/200"}
- }
- }
- },
- "/navigation": {
- "description": "Request Access to Navigation Audio Channel.",
- "get": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/navigation"
- },
- "parameters": [
- {
- "in": "query",
- "name": "zone",
- "required": false,
- "schema": { "type": "string" }
- }
- ],
- "responses": {
- "200": {"$ref": "#/components/responses/200"}
- }
- }
- }
- }
-}
diff --git a/conf.d/cmake/config.cmake b/conf.d/cmake/config.cmake
index 1a53d8a..6fad621 100644
--- a/conf.d/cmake/config.cmake
+++ b/conf.d/cmake/config.cmake
@@ -62,6 +62,7 @@ set (PKG_REQUIRED_LIST
afb-daemon
json-c
libafbwsc
+ lua>=5.3
)
# LANG Specific compile flags set for all build types
@@ -71,20 +72,23 @@ set (PKG_REQUIRED_LIST
# Do not optimise when debugging
set(CMAKE_C_FLAGS_DEBUG "-g -ggdb -Wp,-U_FORTIFY_SOURCE")
+# (BUG!!!) as PKG_CONFIG_PATH does not work [should be an env variable]
+# ---------------------------------------------------------------------
+set(CMAKE_INSTALL_PREFIX $ENV{HOME}/opt)
+set(CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
+set(LD_LIBRARY_PATH ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib)
+
# Define CONTROL_CDEV_NAME should match MOST driver values
# ---------------------------------------------------------
- add_compile_options(-DCONTROL_CDEV_TX="/dev/inic-usb-ctx")
- add_compile_options(-DCONTROL_CDEV_RX="/dev/inic-usb-crx")
+ add_compile_options(-DCONTROL_FILE_POLICY="onload-control-policy.json")
+ add_compile_options(-DCONTROL_PATH_POLICY="/etc/default/audio-agent/policy:$ENV{HOME}/.config/audio-agent:${CMAKE_INSTALL_PREFIX}/audio-agent/policy:${CMAKE_SOURCE_DIR}/data")
+ add_compile_options(-DCONTROL_PATH_LUA="/etc/default/audio-agent/policy:$ENV{HOME}/.config/audio-agent:${CMAKE_INSTALL_PREFIX}/audio-agent/policy:${CMAKE_SOURCE_DIR}/data")
+
# Print a helper message when every thing is finished
# ----------------------------------------------------
set(CLOSING_MESSAGE "Debug in ./buid: afb-daemon --port=1234 --ldpaths=. --workdir=. --roothttp=../htdocs --tracereq=common --token='' --verbose")
-# (BUG!!!) as PKG_CONFIG_PATH does not work [should be an env variable]
-# ---------------------------------------------------------------------
-set(CMAKE_INSTALL_PREFIX $ENV{HOME}/opt)
-set(CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
-set(LD_LIBRARY_PATH ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib)
# Optional dependencies order
# ---------------------------
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
new file mode 100644
index 0000000..55ee664
--- /dev/null
+++ b/data/CMakeLists.txt
@@ -0,0 +1,46 @@
+###########################################################################
+# Copyright 2017 IoT.bzh
+#
+# author: Fulup Ar Foll <fulup@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.
+###########################################################################
+
+
+
+##################################################
+# Control Policy Config file
+##################################################
+PROJECT_TARGET_ADD(Control_config)
+
+ file(GLOB XML_FILES "*.json")
+
+ add_custom_target(${TARGET_NAME}
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
+ )
+
+ # check XML schema before pushing config
+ add_custom_command(
+ DEPENDS ${XML_FILES}
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ # COMMAND xmllint -schema ${XML_SCHEMA} ${XML_FILES} --noout (Fulup we miss this for JSON)
+ COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
+ COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
+ COMMAND cp -r ${XML_FILES} ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
+ )
+
+ SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
+ LABELS "DATA"
+ OUTPUT_NAME ${TARGET_NAME}
+ )
diff --git a/data/helloworld-lua-script.lua b/data/helloworld-lua-script.lua
new file mode 100644
index 0000000..8386bc0
--- /dev/null
+++ b/data/helloworld-lua-script.lua
@@ -0,0 +1,41 @@
+--[[
+ Copyright (C) 2016 "IoT.bzh"
+ Author Fulup Ar Foll <fulup@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.
+
+
+ Simple API script
+--]]
+
+ -- retrieve calling arguments
+ args= ...
+
+ print ("Helloworld script arguments:")
+
+
+ for key,value in pairs(args)
+ do
+ print("args: ", key,value)
+ end
+
+ -- loop on script arguments
+ --for i=1,#args
+ --do
+ -- print(" -- ", i, args[i])
+ --end
+
+
+ -- return two arguments on top of status
+ return true, 1234, "ABCD"
+
diff --git a/data/onload-control-policy.json b/data/onload-control-policy.json
new file mode 100644
index 0000000..d910893
--- /dev/null
+++ b/data/onload-control-policy.json
@@ -0,0 +1,90 @@
+{
+ "$schema": "ToBeDone",
+ "metadata": {
+ "label": "sample-audio-policy",
+ "info": "Provide Default Audio Policy for Multimedia, Navigation and Emergency",
+ "version": "1.0"
+ },
+ "onload": {
+ "info": "controler initialisation config",
+ "plugin": "sample-audio-policy.so",
+ "actions": [
+ {
+ "info": "Call policy sharelib install entrypoint",
+ "callback": "SamplePolicyInstall",
+ "args": {"arg1" : "first_arg", "nextarg": "second arg value"}
+ }, {
+ "info": "Assert AlsaCore Presence",
+ "api": "alsacore",
+ "verb": "ping"
+ }
+ ]
+ },
+ "controls":
+ [{
+ "label": "multimedia",
+ "actions": [
+ {
+ "label": "multimedia-policy-cb",
+ "info": "Call Sharelib Sample Callback",
+ "callback": "samplePolicyCB",
+ "args": {
+ "arg1": "snoopy",
+ "arg2": "toto"
+ }
+ }, {
+ "label": "multimedia-policy-ucm",
+ "info": "Subcall AlSA UCM navigation",
+ "api": "alsacore",
+ "verb": "ucmset",
+ "args": {
+ "verb": "multimedia"
+ }
+ }
+ ]
+ },
+ {
+ "label":"navigation",
+ "action" : {
+ "api": "alsacore",
+ "verb": "ucmset",
+ "args": {
+ "verb": "navigation"
+ },
+ "optional": true,
+ "timeout": 100
+ }
+ }, {
+ "label":"emergency",
+ "action": {
+ "api": "alsacore",
+ "verb": "ucmset",
+ "args": {
+ "verb": "emergency"
+ }
+ }
+ }]
+ ,
+ "events": [
+ {
+ "label": "SampleEvent",
+ "comment": "define action when receiving a given event",
+ "actions": [
+ {
+ "info": "Event Callback-1",
+ "callback": "ProcessEventCB",
+ "args": {
+ "arg": "action-1"
+ }
+ }, {
+ "info": "Event Callback-2",
+ "callback": "ProcessEventCB",
+ "args": {
+ "arg": "action-2"
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/data/onload-control-script.lua b/data/onload-control-script.lua
new file mode 100644
index 0000000..7ded3be
--- /dev/null
+++ b/data/onload-control-script.lua
@@ -0,0 +1,51 @@
+--[[
+ Copyright (C) 2016 "IoT.bzh"
+ Author Fulup Ar Foll <fulup@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.
+
+
+ Provide sample policy function for AGL Advance Audio Agent
+--]]
+
+count=0
+
+-- Adjust Volume function of vehicle speed
+function Adjust_Volume_Speed (speed_meters_second)
+
+ message= string.format("**** Adjust_Volume_Speed speed=%d count=%d", speed_meters_second, count);
+ print (message);
+
+ -- compute volume
+ volume = speed_meters_second * 2
+ count=count+1
+
+ return true, volume, count
+end
+
+function Ping_Test(...)
+
+ print ("Ping_Test script arguments:");
+
+ for i,v in ipairs(arg)
+ do
+ print(" -- ", tostring(v))
+ end
+
+
+ -- return two arguments on top of status
+ return true, 1234, "ABCD"
+
+end
+
+
diff --git a/htdocs/audio-control.html b/htdocs/audio-control.html
new file mode 100644
index 0000000..3be1ef7
--- /dev/null
+++ b/htdocs/audio-control.html
@@ -0,0 +1,40 @@
+<html>
+<head>
+ <title>Basic Audio Hardware Abstraction Layer Test</title>
+ <link rel="stylesheet" href="AudioBinding.css">
+ <script type="text/javascript" src="AFB-websock.js"></script>
+ <script type="text/javascript" src="AudioBinding.js"></script>
+</head>
+
+
+<body onload="init('hal_registry','alsacore', 'hallist')">
+
+ <h1>Simple Audio Control test</h1>
+ <button id="connected" onclick="init('alsa_registry','alsacore', 'getinfo');">Binder WS Fail</button>
+ <br><br>
+
+ <b>API Verbosity </b>
+ <select id='api_verbosity' onclick='mode=this.value'>
+ <option value='0'>Quiet</option>
+ <option value='1'>Compact</option>
+ <option value='2'>Verbose</option>
+ <option value='3'>Full</option>
+ </select>
+ <br>
+
+ <br>
+ <ol>
+
+ <li><button onclick="callbinder('control','lua_dostring','print(\'Bonjours\'); return true, 4567');">LUA string</button></li>
+ <li><button onclick="callbinder('control','lua_docall' , {'func':'Adjust_Volume_Speed', 'args':[20]});">LUA function</button></li>
+ <li><button onclick="callbinder('control','lua_doscript', {'script':'helloworld-lua-script.lua', args:[{'arg1':'abcd'}, {'next':7890}, {'last':'xyz'}]});">LUA script</button></li>
+
+ </ol>
+
+ <div id="main" style="visibility:hidden">
+ <ol>
+ <li>Question <pre id="question"></pre>
+ <li>Response <pre id="output"></pre>
+ <li>Events: <pre id="outevt"></pre>
+ </ol>
+ </div>
diff --git a/htdocs/docs/AAAA-architecture.odg b/htdocs/docs/AAAA-architecture.odg
index 1ebdb1c..90a2486 100644
--- a/htdocs/docs/AAAA-architecture.odg
+++ b/htdocs/docs/AAAA-architecture.odg
Binary files differ
diff --git a/htdocs/docs/AAAA-architecture.pdf b/htdocs/docs/AAAA-architecture.pdf
index a9d0605..3b6280d 100644
--- a/htdocs/docs/AAAA-architecture.pdf
+++ b/htdocs/docs/AAAA-architecture.pdf
Binary files differ
diff --git a/htdocs/index.html b/htdocs/index.html
index 2d2b4ae..4b842c1 100644
--- a/htdocs/index.html
+++ b/htdocs/index.html
@@ -6,4 +6,4 @@
<ol>
<li><a href="alsa-core.html">AlsaCore Low Level Binding</a>
<li><a href="alsa-hal.html" >AlsaHAL Hardware Abstraction Layer</a>
- <li><a href="audio-logic.html">AudioLogic High level business API</a>
+ <li><a href="audio-control.html">AudioControl Control/Policy API</a>
diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml
index e955bcb..0207747 100644
--- a/nbproject/configurations.xml
+++ b/nbproject/configurations.xml
@@ -21,6 +21,10 @@
<in>PolicyHookCb.c</in>
</df>
</df>
+ <df name="Audio-Common">
+ <in>audio-common.c</in>
+ <in>wrap-json.c</in>
+ </df>
<df name="build">
<df name="CMakeFiles">
<df name="3.5.2">
@@ -38,6 +42,12 @@
<df name="Common">
<in>AudioCommonLib.c</in>
</df>
+ <df name="Controler-afb">
+ <in>ctl-binding.c</in>
+ <in>ctl-events.c</in>
+ <in>ctl-lua.c</in>
+ <in>ctl-policy.c</in>
+ </df>
<df name="HAL-afb">
<df name="HAL-interface">
<in>hal-interface.c</in>
@@ -83,12 +93,6 @@
<in>Mediator.cpp</in>
<in>libmostvolume.cpp</in>
</df>
- <df name="PolicyCtl-afb">
- <in>polctl-binding.c</in>
- </df>
- <df name="Shared-Interface">
- <in>audio-interface.c</in>
- </df>
</df>
<logicalFolder name="ExternalFiles"
displayName="Important Files"
@@ -163,10 +167,34 @@
<cTool flags="1">
</cTool>
</item>
+ <item path="Audio-Common/audio-common.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="1">
+ </cTool>
+ </item>
+ <item path="Audio-Common/wrap-json.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="1">
+ </cTool>
+ </item>
<item path="Common/AudioCommonLib.c" ex="false" tool="0" flavor2="2">
<cTool flags="0">
</cTool>
</item>
+ <item path="Controler-afb/ctl-binding.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="1">
+ </cTool>
+ </item>
+ <item path="Controler-afb/ctl-events.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="1">
+ </cTool>
+ </item>
+ <item path="Controler-afb/ctl-lua.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="1">
+ </cTool>
+ </item>
+ <item path="Controler-afb/ctl-policy.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="1">
+ </cTool>
+ </item>
<item path="HAL-afb/HAL-interface/hal-interface.c"
ex="false"
tool="0"
@@ -278,14 +306,6 @@
</item>
<item path="MostVolume/libmostvolume.cpp" ex="false" tool="1" flavor2="4">
</item>
- <item path="PolicyCtl-afb/polctl-binding.c" ex="false" tool="0" flavor2="3">
- <cTool flags="1">
- </cTool>
- </item>
- <item path="Shared-Interface/audio-interface.c" ex="false" tool="0" flavor2="3">
- <cTool flags="1">
- </cTool>
- </item>
<folder path="0/ALSA-afb">
<cTool>
<incDir>
@@ -293,15 +313,15 @@
<pElem>../../../opt/include/alsa</pElem>
<pElem>/usr/include/p11-kit-1</pElem>
<pElem>/usr/include/json-c</pElem>
- <pElem>Shared-Interface</pElem>
+ <pElem>Audio-Common</pElem>
<pElem>build/ALSA-afb</pElem>
</incDir>
<preprocessorList>
- <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem>
- <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem>
+ <Elem>CONTROL_FILE_POLICY="onload-control-policy.json"</Elem>
+ <Elem>CONTROL_PATH_LUA="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>CONTROL_PATH_POLICY="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
<Elem>MAX_LINEAR_DB_SCALE=24</Elem>
<Elem>MAX_SND_CARD=16</Elem>
- <Elem>NATIVE_LINUX</Elem>
<Elem>TLV_BYTE_SIZE=256</Elem>
<Elem>alsa_lowlevel_EXPORTS</Elem>
</preprocessorList>
@@ -317,17 +337,37 @@
<pElem>build/Alsa-Plugin/Alsa-Policy-Hook</pElem>
</incDir>
<preprocessorList>
- <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem>
- <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem>
+ <Elem>CONTROL_FILE_POLICY="onload-control-policy.json"</Elem>
+ <Elem>CONTROL_PATH_LUA="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>CONTROL_PATH_POLICY="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
<Elem>MAX_LINEAR_DB_SCALE=24</Elem>
<Elem>MAX_SND_CARD=16</Elem>
- <Elem>NATIVE_LINUX</Elem>
<Elem>PIC</Elem>
<Elem>TLV_BYTE_SIZE=256</Elem>
<Elem>policy_hook_cb_EXPORTS</Elem>
</preprocessorList>
</cTool>
</folder>
+ <folder path="0/Audio-Common">
+ <cTool>
+ <incDir>
+ <pElem>../../../opt/include</pElem>
+ <pElem>../../../opt/include/alsa</pElem>
+ <pElem>/usr/include/p11-kit-1</pElem>
+ <pElem>/usr/include/json-c</pElem>
+ <pElem>Audio-Common</pElem>
+ <pElem>build/Audio-Common</pElem>
+ </incDir>
+ <preprocessorList>
+ <Elem>CONTROL_FILE_POLICY="onload-control-policy.json"</Elem>
+ <Elem>CONTROL_PATH_LUA="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>CONTROL_PATH_POLICY="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>MAX_LINEAR_DB_SCALE=24</Elem>
+ <Elem>MAX_SND_CARD=16</Elem>
+ <Elem>TLV_BYTE_SIZE=256</Elem>
+ </preprocessorList>
+ </cTool>
+ </folder>
<folder path="0/Common">
<cTool>
<incDir>
@@ -344,6 +384,28 @@
</preprocessorList>
</cTool>
</folder>
+ <folder path="0/Controler-afb">
+ <cTool>
+ <incDir>
+ <pElem>../../../opt/include</pElem>
+ <pElem>../../../opt/include/alsa</pElem>
+ <pElem>/usr/include/p11-kit-1</pElem>
+ <pElem>/usr/include/json-c</pElem>
+ <pElem>/usr/include/lua5.3</pElem>
+ <pElem>Audio-Common</pElem>
+ <pElem>build/Controler-afb</pElem>
+ </incDir>
+ <preprocessorList>
+ <Elem>CONTROL_FILE_POLICY="onload-control-policy.json"</Elem>
+ <Elem>CONTROL_PATH_LUA="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>CONTROL_PATH_POLICY="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>MAX_LINEAR_DB_SCALE=24</Elem>
+ <Elem>MAX_SND_CARD=16</Elem>
+ <Elem>TLV_BYTE_SIZE=256</Elem>
+ <Elem>control_afb_EXPORTS</Elem>
+ </preprocessorList>
+ </cTool>
+ </folder>
<folder path="0/HAL-afb">
<cTool>
<incDir>
@@ -351,8 +413,6 @@
<pElem>../../../opt/include/afb</pElem>
</incDir>
<preprocessorList>
- <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem>
- <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem>
<Elem>MAX_SND_CARD=16</Elem>
</preprocessorList>
</cTool>
@@ -365,12 +425,14 @@
<pElem>/usr/include/p11-kit-1</pElem>
<pElem>/usr/include/json-c</pElem>
<pElem>HAL-afb/HAL-interface</pElem>
- <pElem>Shared-Interface</pElem>
+ <pElem>Audio-Common</pElem>
<pElem>build/HAL-afb/HAL-interface</pElem>
</incDir>
<preprocessorList>
+ <Elem>CONTROL_FILE_POLICY="onload-control-policy.json"</Elem>
+ <Elem>CONTROL_PATH_LUA="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>CONTROL_PATH_POLICY="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
<Elem>MAX_LINEAR_DB_SCALE=24</Elem>
- <Elem>NATIVE_LINUX</Elem>
<Elem>TLV_BYTE_SIZE=256</Elem>
</preprocessorList>
</cTool>
@@ -381,6 +443,10 @@
<pElem>HAL-afb/HAL-plugin</pElem>
<pElem>../../../opt/include/alsa</pElem>
</incDir>
+ <preprocessorList>
+ <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem>
+ <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem>
+ </preprocessorList>
</cTool>
</folder>
<folder path="0/HAL-afb/HDA-intel">
@@ -391,12 +457,14 @@
<pElem>/usr/include/p11-kit-1</pElem>
<pElem>/usr/include/json-c</pElem>
<pElem>HAL-afb/HAL-interface</pElem>
- <pElem>Shared-Interface</pElem>
+ <pElem>Audio-Common</pElem>
<pElem>build/HAL-afb/HDA-intel</pElem>
</incDir>
<preprocessorList>
+ <Elem>CONTROL_FILE_POLICY="onload-control-policy.json"</Elem>
+ <Elem>CONTROL_PATH_LUA="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>CONTROL_PATH_POLICY="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
<Elem>MAX_LINEAR_DB_SCALE=24</Elem>
- <Elem>NATIVE_LINUX</Elem>
<Elem>TLV_BYTE_SIZE=256</Elem>
<Elem>hal_intel_hda_EXPORTS</Elem>
</preprocessorList>
@@ -410,12 +478,14 @@
<pElem>/usr/include/p11-kit-1</pElem>
<pElem>/usr/include/json-c</pElem>
<pElem>HAL-afb/HAL-interface</pElem>
- <pElem>Shared-Interface</pElem>
+ <pElem>Audio-Common</pElem>
<pElem>build/HAL-afb/Jabra-Solemate</pElem>
</incDir>
<preprocessorList>
+ <Elem>CONTROL_FILE_POLICY="onload-control-policy.json"</Elem>
+ <Elem>CONTROL_PATH_LUA="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>CONTROL_PATH_POLICY="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
<Elem>MAX_LINEAR_DB_SCALE=24</Elem>
- <Elem>NATIVE_LINUX</Elem>
<Elem>TLV_BYTE_SIZE=256</Elem>
<Elem>hal_jabra_usb_EXPORTS</Elem>
</preprocessorList>
@@ -429,12 +499,14 @@
<pElem>/usr/include/p11-kit-1</pElem>
<pElem>/usr/include/json-c</pElem>
<pElem>HAL-afb/HAL-interface</pElem>
- <pElem>Shared-Interface</pElem>
+ <pElem>Audio-Common</pElem>
<pElem>build/HAL-afb/Scarlett-Focusrite</pElem>
</incDir>
<preprocessorList>
+ <Elem>CONTROL_FILE_POLICY="onload-control-policy.json"</Elem>
+ <Elem>CONTROL_PATH_LUA="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
+ <Elem>CONTROL_PATH_POLICY="/etc/default/audio-agent/policy:/home/fulup/.config/audio-agent:/home/fulup/opt/audio-agent/policy:/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/data"</Elem>
<Elem>MAX_LINEAR_DB_SCALE=24</Elem>
- <Elem>NATIVE_LINUX</Elem>
<Elem>TLV_BYTE_SIZE=256</Elem>
<Elem>hal_scalett_usb_EXPORTS</Elem>
</preprocessorList>
@@ -446,6 +518,10 @@
<pElem>HAL-afb/Unicens-USB</pElem>
<pElem>/usr/include/json-c</pElem>
</incDir>
+ <preprocessorList>
+ <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem>
+ <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem>
+ </preprocessorList>
</cTool>
</folder>
<folder path="0/HighLevel-afb">
@@ -464,47 +540,6 @@
</incDir>
</cTool>
</folder>
- <folder path="0/PolicyCtl-afb">
- <cTool>
- <incDir>
- <pElem>../../../opt/include</pElem>
- <pElem>../../../opt/include/alsa</pElem>
- <pElem>/usr/include/p11-kit-1</pElem>
- <pElem>/usr/include/json-c</pElem>
- <pElem>Shared-Interface</pElem>
- <pElem>build/PolicyCtl-afb</pElem>
- </incDir>
- <preprocessorList>
- <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem>
- <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem>
- <Elem>MAX_LINEAR_DB_SCALE=24</Elem>
- <Elem>MAX_SND_CARD=16</Elem>
- <Elem>NATIVE_LINUX</Elem>
- <Elem>TLV_BYTE_SIZE=256</Elem>
- <Elem>polctl_afb_EXPORTS</Elem>
- </preprocessorList>
- </cTool>
- </folder>
- <folder path="0/Shared-Interface">
- <cTool>
- <incDir>
- <pElem>../../../opt/include</pElem>
- <pElem>../../../opt/include/alsa</pElem>
- <pElem>/usr/include/p11-kit-1</pElem>
- <pElem>/usr/include/json-c</pElem>
- <pElem>Shared-Interface</pElem>
- <pElem>build/Shared-Interface</pElem>
- </incDir>
- <preprocessorList>
- <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem>
- <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem>
- <Elem>MAX_LINEAR_DB_SCALE=24</Elem>
- <Elem>MAX_SND_CARD=16</Elem>
- <Elem>NATIVE_LINUX</Elem>
- <Elem>TLV_BYTE_SIZE=256</Elem>
- </preprocessorList>
- </cTool>
- </folder>
</conf>
<conf name="Laptop" type="0">
<toolsSet>
@@ -595,6 +630,10 @@
<cTool flags="3">
</cTool>
</item>
+ <item path="Audio-Common/audio-common.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="3">
+ </cTool>
+ </item>
<item path="Common/AudioCommonLib.c" ex="false" tool="0" flavor2="2">
<cTool flags="0">
</cTool>
@@ -722,10 +761,6 @@
</item>
<item path="MostVolume/libmostvolume.cpp" ex="false" tool="1" flavor2="4">
</item>
- <item path="Shared-Interface/audio-interface.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
- </cTool>
- </item>
<folder path="0/ALSA-afb">
<cTool>
<incDir>
@@ -746,6 +781,16 @@
</incDir>
</cTool>
</folder>
+ <folder path="0/Audio-Common">
+ <cTool>
+ <incDir>
+ <pElem>../../../opt/include/afb</pElem>
+ <pElem>Shared-Interface</pElem>
+ <pElem>/usr/include/json-c</pElem>
+ <pElem>build/Shared-Interface</pElem>
+ </incDir>
+ </cTool>
+ </folder>
<folder path="0/Common">
<cTool>
<incDir>
@@ -856,16 +901,6 @@
</incDir>
</cTool>
</folder>
- <folder path="0/Shared-Interface">
- <cTool>
- <incDir>
- <pElem>../../../opt/include/afb</pElem>
- <pElem>Shared-Interface</pElem>
- <pElem>/usr/include/json-c</pElem>
- <pElem>build/Shared-Interface</pElem>
- </incDir>
- </cTool>
- </folder>
</conf>
<conf name="Aplay_Multimedia" type="0">
<toolsSet>
@@ -966,8 +1001,16 @@
tool="0"
flavor2="2">
</item>
+ <item path="Audio-Common/audio-common.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="1">
+ </cTool>
+ </item>
<item path="Common/AudioCommonLib.c" ex="false" tool="0" flavor2="2">
</item>
+ <item path="Controler-afb/ctl-binding.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="0">
+ </cTool>
+ </item>
<item path="HAL-afb/HAL-interface/hal-interface.c"
ex="false"
tool="0"
@@ -1074,14 +1117,6 @@
</item>
<item path="MostVolume/libmostvolume.cpp" ex="false" tool="1" flavor2="4">
</item>
- <item path="PolicyCtl-afb/polctl-binding.c" ex="false" tool="0" flavor2="3">
- <cTool flags="0">
- </cTool>
- </item>
- <item path="Shared-Interface/audio-interface.c" ex="false" tool="0" flavor2="3">
- <cTool flags="1">
- </cTool>
- </item>
<item path="build/CMakeFiles/3.5.2/CompilerIdC/CMakeCCompilerId.c"
ex="false"
tool="0"
@@ -1125,6 +1160,37 @@
</preprocessorList>
</cTool>
</folder>
+ <folder path="0/Audio-Common">
+ <cTool>
+ <incDir>
+ <pElem>../../../opt/include/afb</pElem>
+ <pElem>Shared-Interface</pElem>
+ <pElem>/usr/include/json-c</pElem>
+ <pElem>build/Shared-Interface</pElem>
+ </incDir>
+ </cTool>
+ </folder>
+ <folder path="0/Controler-afb">
+ <cTool>
+ <incDir>
+ <pElem>../../../opt/include</pElem>
+ <pElem>../../../opt/include/alsa</pElem>
+ <pElem>/usr/include/p11-kit-1</pElem>
+ <pElem>/usr/include/json-c</pElem>
+ <pElem>Shared-Interface</pElem>
+ <pElem>build/PolicyCtl-afb</pElem>
+ </incDir>
+ <preprocessorList>
+ <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem>
+ <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem>
+ <Elem>MAX_LINEAR_DB_SCALE=24</Elem>
+ <Elem>MAX_SND_CARD=16</Elem>
+ <Elem>NATIVE_LINUX</Elem>
+ <Elem>TLV_BYTE_SIZE=256</Elem>
+ <Elem>polctl_afb_EXPORTS</Elem>
+ </preprocessorList>
+ </cTool>
+ </folder>
<folder path="0/HAL-afb/HAL-interface">
<cTool>
<incDir>
@@ -1187,37 +1253,6 @@
</incDir>
</cTool>
</folder>
- <folder path="0/PolicyCtl-afb">
- <cTool>
- <incDir>
- <pElem>../../../opt/include</pElem>
- <pElem>../../../opt/include/alsa</pElem>
- <pElem>/usr/include/p11-kit-1</pElem>
- <pElem>/usr/include/json-c</pElem>
- <pElem>Shared-Interface</pElem>
- <pElem>build/PolicyCtl-afb</pElem>
- </incDir>
- <preprocessorList>
- <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem>
- <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem>
- <Elem>MAX_LINEAR_DB_SCALE=24</Elem>
- <Elem>MAX_SND_CARD=16</Elem>
- <Elem>NATIVE_LINUX</Elem>
- <Elem>TLV_BYTE_SIZE=256</Elem>
- <Elem>polctl_afb_EXPORTS</Elem>
- </preprocessorList>
- </cTool>
- </folder>
- <folder path="0/Shared-Interface">
- <cTool>
- <incDir>
- <pElem>../../../opt/include/afb</pElem>
- <pElem>Shared-Interface</pElem>
- <pElem>/usr/include/json-c</pElem>
- <pElem>build/Shared-Interface</pElem>
- </incDir>
- </cTool>
- </folder>
</conf>
</confs>
</configurationDescriptor>