summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfulup <fulup.arfoll@iot.bzh>2017-07-23 01:23:37 +0200
committerfulup <fulup.arfoll@iot.bzh>2017-07-23 01:23:37 +0200
commita7a6ae4be87ee9178905ab784d84a4c0a8303f9b (patch)
treee5aa96fba9c7ed59f60dd1641fc30c2eeb512e50
parent044828c43097362973c82088a7afee760eab06ec (diff)
Added TLV->DBscale into HAL control
1st Working version of HAL ctl-get with TLV Cleanup HTML5 test pages WIP Only
-rw-r--r--.vscode/c_cpp_properties.json65
-rw-r--r--ALSA-afb/Alsa-AddCtl.c33
-rw-r--r--ALSA-afb/Alsa-ApiHat.c4
-rw-r--r--ALSA-afb/Alsa-ApiHat.h4
-rw-r--r--ALSA-afb/Alsa-RegEvt.c8
-rw-r--r--ALSA-afb/Alsa-SetGet.c189
-rw-r--r--ALSA-afb/Alsa-Ucm.c2
-rw-r--r--ALSA-afb/README.md4
-rw-r--r--HAL-afb/HAL-interface/CMakeLists.txt2
-rw-r--r--HAL-afb/HAL-interface/hal-interface.c194
-rw-r--r--HAL-afb/HAL-interface/hal-interface.h17
-rw-r--r--HAL-afb/HAL-interface/hal-volmap.c96
-rw-r--r--HAL-afb/HAL-plugin/HalPlugCtl.c2
-rw-r--r--README.md146
-rw-r--r--Shared-Interface/audio-interface.h7
-rw-r--r--conf.d/cmake/config.cmake3
-rw-r--r--htdocs/AFB-websock.js7
-rw-r--r--htdocs/AudioBinding.css7
-rw-r--r--htdocs/AudioBinding.js74
-rw-r--r--htdocs/alsa-core.html68
-rw-r--r--htdocs/alsa-hal.html31
-rw-r--r--htdocs/audio-logic.html26
-rw-r--r--nbproject/configurations.xml109
23 files changed, 765 insertions, 333 deletions
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000..cd13c94
--- /dev/null
+++ b/.vscode/c_cpp_properties.json
@@ -0,0 +1,65 @@
+{
+ "configurations": [
+ {
+ "name": "Mac",
+ "includePath": [
+ "/usr/include",
+ "/usr/local/include",
+ "${workspaceRoot}"
+ ],
+ "defines": [],
+ "intelliSenseMode": "clang-x64",
+ "browse": {
+ "path": [
+ "/usr/include",
+ "/usr/local/include",
+ "${workspaceRoot}"
+ ],
+ "limitSymbolsToIncludedHeaders": true,
+ "databaseFilename": ""
+ }
+ },
+ {
+ "name": "Linux",
+ "includePath": [
+ "/usr/include/c++/5",
+ "/usr/local/include",
+ "/usr/include",
+ "${workspaceRoot}"
+ ],
+ "defines": [],
+ "intelliSenseMode": "clang-x64",
+ "browse": {
+ "path": [
+ "/usr/include/c++/5",
+ "/usr/local/include",
+ "/usr/include",
+ "${workspaceRoot}"
+ ],
+ "limitSymbolsToIncludedHeaders": true,
+ "databaseFilename": ""
+ }
+ },
+ {
+ "name": "Win32",
+ "includePath": [
+ "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include",
+ "${workspaceRoot}"
+ ],
+ "defines": [
+ "_DEBUG",
+ "UNICODE"
+ ],
+ "intelliSenseMode": "msvc-x64",
+ "browse": {
+ "path": [
+ "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*",
+ "${workspaceRoot}"
+ ],
+ "limitSymbolsToIncludedHeaders": true,
+ "databaseFilename": ""
+ }
+ }
+ ],
+ "version": 2
+} \ No newline at end of file
diff --git a/ALSA-afb/Alsa-AddCtl.c b/ALSA-afb/Alsa-AddCtl.c
index 25e2a31..4635503 100644
--- a/ALSA-afb/Alsa-AddCtl.c
+++ b/ALSA-afb/Alsa-AddCtl.c
@@ -37,11 +37,11 @@ static const unsigned int *allocate_bool_elem_set_tlv (void) {
return tlv;
}
-STATIC json_object * addOneSndCtl(afb_req request, snd_ctl_t *ctlDev, json_object *ctlJ) {
+STATIC json_object * addOneSndCtl(afb_req request, snd_ctl_t *ctlDev, json_object *ctlJ, halQueryMode queryMode) {
int err, ctlNumid;
json_object *tmpJ;
- ctlRequestT ctlRequest;
const char *ctlName;
+ ctlRequestT ctlRequest;
int ctlMax, ctlMin, ctlStep, ctlCount, ctlSubDev, ctlSndDev;
snd_ctl_elem_type_t ctlType;
snd_ctl_elem_info_t *elemInfo;
@@ -68,10 +68,14 @@ STATIC json_object * addOneSndCtl(afb_req request, snd_ctl_t *ctlDev, json_obje
snd_ctl_elem_info_set_interface (elemInfo, SND_CTL_ELEM_IFACE_MIXER);
err = snd_ctl_elem_info(ctlDev, elemInfo);
if (!err) {
- AFB_NOTICE ("ctlName=%s numid=%d already exit", snd_ctl_elem_info_get_name(elemInfo), snd_ctl_elem_info_get_numid(elemInfo));
snd_ctl_elem_id_alloca(&elemId);
- snd_ctl_elem_info_get_id(elemInfo, elemId);
- goto OnSucessExit;
+ snd_ctl_elem_info_get_id(elemInfo, elemId);
+ if (ctlNumid) goto OnSucessExit; // hardware control nothing todo
+ else { // user created kcontrol should be removable
+ err = snd_ctl_elem_remove(ctlDev, elemId);
+ AFB_NOTICE ("ctlName=%s numid=%d fail to reset", snd_ctl_elem_info_get_name(elemInfo), snd_ctl_elem_info_get_numid(elemInfo));
+ goto OnErrorExit;
+ }
}
// default for json_object_get_int is zero
@@ -177,7 +181,7 @@ STATIC json_object * addOneSndCtl(afb_req request, snd_ctl_t *ctlDev, json_obje
// return newly created as a JSON object
OnSucessExit:
- alsaGetSingleCtl (ctlDev, elemId, &ctlRequest, 0);
+ alsaGetSingleCtl (ctlDev, elemId, &ctlRequest, queryMode);
if (ctlRequest.used < 0) goto OnErrorExit;
return ctlRequest.jValues;
@@ -190,7 +194,7 @@ PUBLIC void alsaAddCustomCtls(afb_req request) {
json_object *ctlsJ, *ctlsValues, *ctlValues;
enum json_type;
snd_ctl_t *ctlDev=NULL;
- const char *devid;
+ const char *devid, *mode;
devid = afb_req_value(request, "devid");
if (devid == NULL) {
@@ -204,9 +208,16 @@ PUBLIC void alsaAddCustomCtls(afb_req request) {
afb_req_fail_f (request, "devid-unknown", "SndCard devid=[%s] Not Found err=%s", devid, snd_strerror(err));
goto OnErrorExit;
}
-
+
+ // get verbosity level
+ halQueryMode queryMode = QUERY_QUIET;
+ mode = afb_req_value(request, "mode");
+ if (mode != NULL) {
+ sscanf(mode,"%i", (int*)&queryMode);
+ }
+
// extract sound controls and parse json
- ctlsJ = json_tokener_parse (afb_req_value(request, "ctls"));
+ ctlsJ = json_tokener_parse (afb_req_value(request, "ctl"));
if (!ctlsJ) {
afb_req_fail_f (request, "ctls-missing", "ctls MUST be defined as a JSON array for alsaAddCustomCtls");
goto OnErrorExit;
@@ -214,7 +225,7 @@ PUBLIC void alsaAddCustomCtls(afb_req request) {
switch (json_object_get_type(ctlsJ)) {
case json_type_object:
- ctlsValues= addOneSndCtl(request, ctlDev, ctlsJ);
+ ctlsValues= addOneSndCtl(request, ctlDev, ctlsJ, queryMode);
break;
@@ -222,7 +233,7 @@ PUBLIC void alsaAddCustomCtls(afb_req request) {
ctlsValues= json_object_new_array();
for (int idx= 0; idx < json_object_array_length (ctlsJ); idx++) {
json_object *ctlJ = json_object_array_get_idx (ctlsJ, idx);
- ctlValues= addOneSndCtl(request, ctlDev, ctlJ) ;
+ ctlValues= addOneSndCtl(request, ctlDev, ctlJ, queryMode) ;
if (ctlValues) json_object_array_add (ctlsValues, ctlValues);
}
break;
diff --git a/ALSA-afb/Alsa-ApiHat.c b/ALSA-afb/Alsa-ApiHat.c
index 5256fb4..9797d3c 100644
--- a/ALSA-afb/Alsa-ApiHat.c
+++ b/ALSA-afb/Alsa-ApiHat.c
@@ -35,8 +35,8 @@ static const struct afb_verb_v2 api_verbs[] = {
/* VERB'S NAME FUNCTION TO CALL */
{ .verb= "ping" , .callback= pingtest },
{ .verb= "getinfo", .callback= alsaGetInfo},
- { .verb= "getctls", .callback= alsaGetCtls},
- { .verb= "setctls", .callback= alsaSetCtls},
+ { .verb= "getctl", .callback= alsaGetCtls},
+ { .verb= "setctl", .callback= alsaSetCtls},
{ .verb= "subscribe", .callback= alsaEvtSubcribe},
{ .verb= "getcardid", .callback= alsaGetCardId},
{ .verb= "halregister", .callback= alsaRegisterHal},
diff --git a/ALSA-afb/Alsa-ApiHat.h b/ALSA-afb/Alsa-ApiHat.h
index 46f18de..6c9f4c3 100644
--- a/ALSA-afb/Alsa-ApiHat.h
+++ b/ALSA-afb/Alsa-ApiHat.h
@@ -33,7 +33,7 @@ typedef enum {
typedef struct {
const char *devid;
json_object *jNumIds;
- int quiet;
+ halQueryMode mode;
int count;
} queryValuesT;
@@ -50,7 +50,7 @@ extern const struct afb_binding_interface *afbIface;
PUBLIC int alsaCheckQuery (struct afb_req request, queryValuesT *queryValues);
// AlseCoreSetGet exports
-PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, int quiet);
+PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, halQueryMode queryMode);
PUBLIC void alsaGetInfo (struct afb_req request);
PUBLIC void alsaGetCtls(struct afb_req request);
PUBLIC void alsaSetCtls(struct afb_req request);
diff --git a/ALSA-afb/Alsa-RegEvt.c b/ALSA-afb/Alsa-RegEvt.c
index 6344e2d..7b0a722 100644
--- a/ALSA-afb/Alsa-RegEvt.c
+++ b/ALSA-afb/Alsa-RegEvt.c
@@ -25,7 +25,7 @@ typedef struct {
struct pollfd pfds;
sd_event_source *src;
snd_ctl_t *ctlDev;
- int quiet;
+ int mode;
struct afb_event afbevt;
} evtHandleT;
@@ -81,7 +81,7 @@ STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void*
snd_ctl_event_elem_get_id (eventId, elemId);
- err = alsaGetSingleCtl (evtHandle->ctlDev, elemId, &ctlRequest, evtHandle->quiet);
+ err = alsaGetSingleCtl (evtHandle->ctlDev, elemId, &ctlRequest, evtHandle->mode);
if (err) goto OnErrorExit;
iface = snd_ctl_event_elem_get_interface(eventId);
@@ -93,7 +93,7 @@ STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void*
ctlEventJ = json_object_new_object();
json_object_object_add(ctlEventJ, "device" ,json_object_new_int (device));
json_object_object_add(ctlEventJ, "subdev" ,json_object_new_int (subdev));
- if (evtHandle->quiet < 2) {
+ if (evtHandle->mode < 2) {
json_object_object_add(ctlEventJ, "iface" ,json_object_new_int (iface));
json_object_object_add(ctlEventJ, "devname",json_object_new_string (devname));
}
@@ -158,7 +158,7 @@ PUBLIC void alsaEvtSubcribe (afb_req request) {
evtHandle = malloc (sizeof(evtHandleT));
evtHandle->ctlDev = ctlDev;
- evtHandle->quiet = queryValues.quiet;
+ evtHandle->mode = queryValues.mode;
sndHandles[idxFree].ucount = 0;
sndHandles[idxFree].cardId = cardId;
sndHandles[idxFree].evtHandle = evtHandle;
diff --git a/ALSA-afb/Alsa-SetGet.c b/ALSA-afb/Alsa-SetGet.c
index 31406f3..0815f35 100644
--- a/ALSA-afb/Alsa-SetGet.c
+++ b/ALSA-afb/Alsa-SetGet.c
@@ -90,17 +90,17 @@ PUBLIC int alsaCheckQuery (afb_req request, queryValuesT *queryValues) {
const char *numids;
json_object *jNumIds;
- const char *rqtQuiet = afb_req_value(request, "quiet");
- if (!rqtQuiet) queryValues->quiet=99; // default super quiet
- else if (rqtQuiet && ! sscanf (rqtQuiet, "%d", &queryValues->quiet)) {
+ const char *rqtmode = afb_req_value(request, "mode");
+ if (!rqtmode) queryValues->mode=QUERY_QUIET; // default quiet
+ else if (rqtmode && ! sscanf (rqtmode, "%d", (int)&queryValues->mode)) {
json_object *query = afb_req_json(request);
- afb_req_fail_f (request, "quiet-notinteger","Query=%s Quiet not integer &quiet=%s&", json_object_get_string(query), rqtQuiet);
+ afb_req_fail_f (request, "mode-notinteger","Query=%s mode not integer &mode=%s&", json_object_get_string(query), rqtmode);
goto OnErrorExit;
};
// no NumId is interpreted as ALL for get and error for set
- numids = afb_req_value(request, "numids");
+ numids = afb_req_value(request, "numid");
if (numids == NULL) {
queryValues->count=0;
goto OnExit;
@@ -153,7 +153,7 @@ STATIC json_object *DB2StringJsonOject (long dB) {
// Direct port from amixer TLV decode routine. This code is too complex for me.
// I hopefully did not break it when porting it.
-STATIC json_object *decodeTlv(unsigned int *tlv, unsigned int tlv_size) {
+STATIC json_object *decodeTlv(unsigned int *tlv, unsigned int tlv_size, int mode) {
char label[20];
unsigned int type = tlv[0];
unsigned int size;
@@ -187,7 +187,7 @@ STATIC json_object *decodeTlv(unsigned int *tlv, unsigned int tlv_size) {
fprintf(stderr, "TLV size error in compound!\n");
return NULL;
}
- embedJson = decodeTlv(tlv + idx, tlv[idx + 1] + 8);
+ embedJson = decodeTlv(tlv + idx, tlv[idx + 1] + 8, mode);
json_object_array_add(containerJson, embedJson);
idx += (unsigned int) (2 + (tlv[idx + 1] + sizeof (unsigned int) - 1) / sizeof (unsigned int));
}
@@ -202,15 +202,25 @@ STATIC json_object *decodeTlv(unsigned int *tlv, unsigned int tlv_size) {
if (size != 2 * sizeof (unsigned int)) {
json_object * arrayJson = json_object_new_array();
while (size > 0) {
- snprintf(label, sizeof (label), "0x%08x,", tlv[idx++]);
- json_object_array_add(arrayJson, json_object_new_string(label));
+ if (mode >= QUERY_VERBOSE) {
+ snprintf(label, sizeof (label), "0x%08x,", tlv[idx++]);
+ json_object_array_add(arrayJson, json_object_new_string(label));
+ } else {
+ json_object_array_add(arrayJson, json_object_new_int(tlv[idx++]));
+ }
size -= (unsigned int) sizeof (unsigned int);
}
json_object_object_add(dbscaleJson, "array", arrayJson);
} else {
- json_object_object_add(dbscaleJson, "min", DB2StringJsonOject((int) tlv[2]));
- json_object_object_add(dbscaleJson, "step", DB2StringJsonOject(tlv[3] & 0xffff));
- json_object_object_add(dbscaleJson, "mute", DB2StringJsonOject((tlv[3] >> 16) & 1));
+ if (mode >= QUERY_VERBOSE) {
+ json_object_object_add(dbscaleJson, "min", DB2StringJsonOject((int) tlv[2]));
+ json_object_object_add(dbscaleJson, "step", DB2StringJsonOject(tlv[3] & 0xffff));
+ json_object_object_add(dbscaleJson, "mute", DB2StringJsonOject((tlv[3] >> 16) & 1));
+ } else {
+ json_object_object_add(dbscaleJson, "min", json_object_new_int((int) tlv[2]));
+ json_object_object_add(dbscaleJson, "step", json_object_new_int(tlv[3] & 0xffff));
+ json_object_object_add(dbscaleJson, "mute", json_object_new_int((tlv[3] >> 16) & 1));
+ }
}
json_object_object_add(decodeTlvJson, "dbscale", dbscaleJson);
break;
@@ -224,14 +234,23 @@ STATIC json_object *decodeTlv(unsigned int *tlv, unsigned int tlv_size) {
if (size != 2 * sizeof (unsigned int)) {
json_object * arrayJson = json_object_new_array();
while (size > 0) {
- snprintf(label, sizeof (label), "0x%08x,", tlv[idx++]);
- json_object_array_add(arrayJson, json_object_new_string(label));
+ if (mode >= QUERY_VERBOSE) {
+ snprintf(label, sizeof (label), "0x%08x,", tlv[idx++]);
+ json_object_array_add(arrayJson, json_object_new_string(label));
+ } else {
+ json_object_array_add(arrayJson, json_object_new_int(tlv[idx++]));
+ }
size -= (unsigned int) sizeof (unsigned int);
}
json_object_object_add(dbLinearJson, "offset", arrayJson);
} else {
- json_object_object_add(dbLinearJson, "min", DB2StringJsonOject((int) tlv[2]));
- json_object_object_add(dbLinearJson, "max", DB2StringJsonOject((int) tlv[3]));
+ if (mode >= QUERY_VERBOSE) {
+ json_object_object_add(dbLinearJson, "min", DB2StringJsonOject((int) tlv[2]));
+ json_object_object_add(dbLinearJson, "max", DB2StringJsonOject((int) tlv[3]));
+ } else {
+ json_object_object_add(dbLinearJson, "min", json_object_new_int((int) tlv[2]));
+ json_object_object_add(dbLinearJson, "max", json_object_new_int((int) tlv[3]));
+ }
}
json_object_object_add(decodeTlvJson, "dblinear", dbLinearJson);
break;
@@ -246,8 +265,12 @@ STATIC json_object *decodeTlv(unsigned int *tlv, unsigned int tlv_size) {
if ((size % (6 * sizeof (unsigned int))) != 0) {
json_object *arrayJson = json_object_new_array();
while (size > 0) {
- snprintf(label, sizeof (label), "0x%08x,", tlv[idx++]);
- json_object_array_add(arrayJson, json_object_new_string(label));
+ if (mode >= QUERY_VERBOSE) {
+ snprintf(label, sizeof (label), "0x%08x,", tlv[idx++]);
+ json_object_array_add(arrayJson, json_object_new_string(label));
+ } else {
+ json_object_array_add(arrayJson, json_object_new_int(tlv[idx++]));
+ }
size -= (unsigned int) sizeof (unsigned int);
}
json_object_object_add(dbRangeJson, "dbrange", arrayJson);
@@ -255,11 +278,9 @@ STATIC json_object *decodeTlv(unsigned int *tlv, unsigned int tlv_size) {
}
while (size > 0) {
json_object * embedJson = json_object_new_object();
- snprintf(label, sizeof (label), "%i,", tlv[idx++]);
- json_object_object_add(embedJson, "rangemin", json_object_new_string(label));
- snprintf(label, sizeof (label), "%i", tlv[idx++]);
- json_object_object_add(embedJson, "rangemax", json_object_new_string(label));
- embedJson = decodeTlv(tlv + idx, 4 * sizeof (unsigned int));
+ json_object_object_add(embedJson, "rangemin", json_object_new_int(tlv[idx++]));
+ json_object_object_add(embedJson, "rangemax", json_object_new_int(tlv[idx++]));
+ embedJson = decodeTlv(tlv + idx, 4 * sizeof (unsigned int), mode);
json_object_object_add(embedJson, "tlv", embedJson);
idx += 4;
size -= (unsigned int) (6 * sizeof (unsigned int));
@@ -278,15 +299,24 @@ STATIC json_object *decodeTlv(unsigned int *tlv, unsigned int tlv_size) {
if (size != 2 * sizeof (unsigned int)) {
json_object * arrayJson = json_object_new_array();
while (size > 0) {
- snprintf(label, sizeof (label), "0x%08x,", tlv[idx++]);
- json_object_array_add(arrayJson, json_object_new_string(label));
+ if (mode >= QUERY_VERBOSE) {
+ snprintf(label, sizeof (label), "0x%08x,", tlv[idx++]);
+ json_object_array_add(arrayJson, json_object_new_string(label));
+ } else {
+ json_object_array_add(arrayJson, json_object_new_int(tlv[idx++]));
+ }
size -= (unsigned int) sizeof (unsigned int);
}
json_object_object_add(dbMinMaxJson, "array", arrayJson);
} else {
- json_object_object_add(dbMinMaxJson, "min", DB2StringJsonOject((int) tlv[2]));
- json_object_object_add(dbMinMaxJson, "max", DB2StringJsonOject((int) tlv[3]));
+ if (mode >= QUERY_VERBOSE) {
+ json_object_object_add(dbMinMaxJson, "min", DB2StringJsonOject((int) tlv[2]));
+ json_object_object_add(dbMinMaxJson, "max", DB2StringJsonOject((int) tlv[3]));
+ } else {
+ json_object_object_add(dbMinMaxJson, "min", json_object_new_int((int) tlv[2]));
+ json_object_object_add(dbMinMaxJson, "max", json_object_new_int((int) tlv[3]));
+ }
}
if (type == SND_CTL_TLVT_DB_MINMAX_MUTE) {
@@ -350,7 +380,7 @@ STATIC json_object* alsaCardProbe (const char *rqtSndId) {
int err;
if ((err = snd_ctl_open(&handle, rqtSndId, 0)) < 0) {
- AFB_INFO ("SndCard [%s] Not Found", rqtSndId);
+ AFB_INFO ("alsaCardProbe [%s] Not Found", rqtSndId);
return NULL;
}
@@ -522,7 +552,7 @@ PUBLIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe
}
// process ALSA control and store then into ctlRequest
-PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, int quiet) {
+PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, halQueryMode queryMode) {
snd_ctl_elem_type_t elemType;
snd_ctl_elem_value_t *elemData;
snd_ctl_elem_info_t *elemInfo;
@@ -548,9 +578,9 @@ PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe
ctlRequest->jValues= json_object_new_object();
json_object_object_add (ctlRequest->jValues,"numid" , json_object_new_int(numid));
- if (quiet < 2) json_object_object_add (ctlRequest->jValues,"name" , json_object_new_string(snd_ctl_elem_id_get_name (elemId)));
- if (quiet < 1) json_object_object_add (ctlRequest->jValues,"iface" , json_object_new_string(snd_ctl_elem_iface_name(snd_ctl_elem_id_get_interface(elemId))));
- if (quiet < 3) json_object_object_add (ctlRequest->jValues,"actif", json_object_new_boolean(!snd_ctl_elem_info_is_inactive(elemInfo)));
+ if (queryMode >= 1) json_object_object_add (ctlRequest->jValues,"name" , json_object_new_string(snd_ctl_elem_id_get_name (elemId)));
+ if (queryMode >= 2) json_object_object_add (ctlRequest->jValues,"iface" , json_object_new_string(snd_ctl_elem_iface_name(snd_ctl_elem_id_get_interface(elemId))));
+ if (queryMode >= 3) json_object_object_add (ctlRequest->jValues,"actif", json_object_new_boolean(!snd_ctl_elem_info_is_inactive(elemInfo)));
json_object *jsonValuesCtl = json_object_new_array();
for (idx = 0; idx < count; idx++) { // start from one in amixer.c !!!
@@ -590,54 +620,55 @@ PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe
}
json_object_object_add (ctlRequest->jValues,"val",jsonValuesCtl);
- if (!quiet) { // in simple mode do not print usable values
+ if (queryMode >= 1) { // in simple mode do not print usable values
json_object *jsonClassCtl = json_object_new_object();
json_object_object_add (jsonClassCtl,"type" , json_object_new_int(elemType));
- json_object_object_add (jsonClassCtl,"count", json_object_new_int(count));
-
- switch (elemType) {
- case SND_CTL_ELEM_TYPE_INTEGER:
- json_object_object_add (jsonClassCtl,"min", json_object_new_int((int)snd_ctl_elem_info_get_min(elemInfo)));
- json_object_object_add (jsonClassCtl,"max", json_object_new_int((int)snd_ctl_elem_info_get_max(elemInfo)));
- json_object_object_add (jsonClassCtl,"step", json_object_new_int((int)snd_ctl_elem_info_get_step(elemInfo)));
- break;
- case SND_CTL_ELEM_TYPE_INTEGER64:
- json_object_object_add (jsonClassCtl,"min", json_object_new_int64(snd_ctl_elem_info_get_min64(elemInfo)));
- json_object_object_add (jsonClassCtl,"max", json_object_new_int64(snd_ctl_elem_info_get_max64(elemInfo)));
- json_object_object_add (jsonClassCtl,"step", json_object_new_int64(snd_ctl_elem_info_get_step64(elemInfo)));
- break;
- case SND_CTL_ELEM_TYPE_ENUMERATED: {
- unsigned int item, items = snd_ctl_elem_info_get_items(elemInfo);
- json_object *jsonEnum = json_object_new_array();
-
- for (item = 0; item < items; item++) {
- snd_ctl_elem_info_set_item(elemInfo, item);
- if ((err = snd_ctl_elem_info(ctlDev, elemInfo)) >= 0) {
- json_object_array_add (jsonEnum, json_object_new_string(snd_ctl_elem_info_get_item_name(elemInfo)));
- }
- }
- json_object_object_add (jsonClassCtl, "enums",jsonEnum);
- break;
- }
- default: break; // ignore any unknown type
- }
-
- // add collected class info with associated ACLs
- json_object_object_add (ctlRequest->jValues,"ctrl", jsonClassCtl);
- json_object_object_add (ctlRequest->jValues,"acl" , getControlAcl (elemInfo));
-
- // check for tlv [direct port from amixer.c]
- if (snd_ctl_elem_info_is_tlv_readable(elemInfo)) {
- unsigned int *tlv;
- tlv = malloc(4096);
- if ((err = snd_ctl_elem_info(ctlDev, elemInfo)) < 0) {
- fprintf (stderr, "Control %s element TLV read error\n", snd_strerror(err));
- free(tlv);
- } else {
- json_object_object_add (ctlRequest->jValues,"tlv", decodeTlv (tlv, 4096));
- }
- }
+ json_object_object_add (jsonClassCtl,"count", json_object_new_int(count));
+
+ switch (elemType) {
+ case SND_CTL_ELEM_TYPE_INTEGER:
+ json_object_object_add (jsonClassCtl,"min", json_object_new_int((int)snd_ctl_elem_info_get_min(elemInfo)));
+ json_object_object_add (jsonClassCtl,"max", json_object_new_int((int)snd_ctl_elem_info_get_max(elemInfo)));
+ json_object_object_add (jsonClassCtl,"step", json_object_new_int((int)snd_ctl_elem_info_get_step(elemInfo)));
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER64:
+ json_object_object_add (jsonClassCtl,"min", json_object_new_int64(snd_ctl_elem_info_get_min64(elemInfo)));
+ json_object_object_add (jsonClassCtl,"max", json_object_new_int64(snd_ctl_elem_info_get_max64(elemInfo)));
+ json_object_object_add (jsonClassCtl,"step", json_object_new_int64(snd_ctl_elem_info_get_step64(elemInfo)));
+ break;
+ case SND_CTL_ELEM_TYPE_ENUMERATED: {
+ unsigned int item, items = snd_ctl_elem_info_get_items(elemInfo);
+ json_object *jsonEnum = json_object_new_array();
+
+ for (item = 0; item < items; item++) {
+ snd_ctl_elem_info_set_item(elemInfo, item);
+ if ((err = snd_ctl_elem_info(ctlDev, elemInfo)) >= 0) {
+ json_object_array_add (jsonEnum, json_object_new_string(snd_ctl_elem_info_get_item_name(elemInfo)));
+ }
+ }
+ json_object_object_add (jsonClassCtl, "enums",jsonEnum);
+ break;
+ }
+ default: break; // ignore any unknown type
+ }
+
+ // add collected class info with associated ACLs
+ json_object_object_add (ctlRequest->jValues,"ctl", jsonClassCtl);
+
+ if (queryMode >= QUERY_FULL) json_object_object_add (ctlRequest->jValues,"acl" , getControlAcl (elemInfo));
+
+ // check for tlv [direct port from amixer.c]
+ if (snd_ctl_elem_info_is_tlv_readable(elemInfo)) {
+ unsigned int *tlv = alloca(4096);
+ if ((err = snd_ctl_elem_tlv_read(ctlDev, elemId, tlv, 4096)) < 0) {
+ fprintf (stderr, "Control %s element TLV read error\n", snd_strerror(err));
+ goto OnErrorExit;
+ } else {
+ json_object_object_add (ctlRequest->jValues,"tlv", decodeTlv (tlv, 4096, queryMode));
+ }
+ }
}
+
ctlRequest->used=1;
return 0;
@@ -722,7 +753,7 @@ STATIC void alsaSetGetCtls (afb_req request, ActionSetGetT action) {
snd_ctl_elem_list_get_id (ctlList, ctlIndex, elemId);
switch (action) {
case ACTION_GET:
- err = alsaGetSingleCtl (ctlDev, elemId, &ctlRequest[jdx], queryValues.quiet);
+ err = alsaGetSingleCtl (ctlDev, elemId, &ctlRequest[jdx], queryValues.mode);
break;
case ACTION_SET:
@@ -749,7 +780,7 @@ STATIC void alsaSetGetCtls (afb_req request, ActionSetGetT action) {
if (ctlRequest[jdx].numId == -1) json_object_object_add (failctl, "info", json_object_new_string ("Invalid NumID"));
else {
- if (ctlRequest[jdx].used == 0) json_object_object_add (failctl, "info", json_object_new_string ("Does Not Exist"));
+ if (ctlRequest[jdx].used == 0) json_object_object_add (failctl, "info", json_object_new_string ("Does Not Exist"));
if (ctlRequest[jdx].used == -1) json_object_object_add (failctl, "info", json_object_new_string ("Invalid Value"));
}
json_object_array_add (warnings, failctl);
diff --git a/ALSA-afb/Alsa-Ucm.c b/ALSA-afb/Alsa-Ucm.c
index b2039be..f512417 100644
--- a/ALSA-afb/Alsa-Ucm.c
+++ b/ALSA-afb/Alsa-Ucm.c
@@ -364,7 +364,7 @@ PUBLIC void alsaUseCaseSet(struct afb_req request) {
// label are requested transfert request to get
if (afb_req_value(request, "values")) return alsaUseCaseGet(request);
- if (queryValues.quiet <= 3) {
+ if (queryValues.mode <= 3) {
json_object *jValue;
jValue = ucmGetValue (&ucmHandles[ucmIdx], verb, dev, "OutputDspName");
diff --git a/ALSA-afb/README.md b/ALSA-afb/README.md
index a4b0395..93d2d4d 100644
--- a/ALSA-afb/README.md
+++ b/ALSA-afb/README.md
@@ -18,8 +18,8 @@ Testing: (from project directory bindings)
# Get all controls from a given sound card
http://localhost:1234/api/alsacore/getctl?devid=hw:0
- # Get detail on a given control (optional quiet=0=verbose,1,2)
- http://localhost:1234/api/alsacore/getctl?devid=hw:0&numid=1&quiet=0
+ # Get detail on a given control (optional mode=0=verbose,1,2)
+ http://localhost:1234/api/alsacore/getctl?devid=hw:0&numid=1&mode=0
# Debug event with afb-client-demo
```
diff --git a/HAL-afb/HAL-interface/CMakeLists.txt b/HAL-afb/HAL-interface/CMakeLists.txt
index d4dba4b..c367c5c 100644
--- a/HAL-afb/HAL-interface/CMakeLists.txt
+++ b/HAL-afb/HAL-interface/CMakeLists.txt
@@ -21,7 +21,7 @@
PROJECT_TARGET_ADD(hal-interface)
# Define targets
- ADD_LIBRARY(${TARGET_NAME} STATIC hal-interface.c)
+ ADD_LIBRARY(${TARGET_NAME} STATIC hal-volmap.c hal-interface.c)
# Library properties
SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES OUTPUT_NAME halinterface)
diff --git a/HAL-afb/HAL-interface/hal-interface.c b/HAL-afb/HAL-interface/hal-interface.c
index dd00d1c..1f39a81 100644
--- a/HAL-afb/HAL-interface/hal-interface.c
+++ b/HAL-afb/HAL-interface/hal-interface.c
@@ -19,16 +19,7 @@
* http://www.tldp.org/HOWTO/Alsa-sound-6.html
*/
#define _GNU_SOURCE // needed for vasprintf
-#include <stdio.h>
#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <math.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
#include "hal-interface.h"
static alsaHalMapT *halCtls;
@@ -61,72 +52,30 @@ STATIC void halSubscribe(afb_req request) {
}
}
-// HAL normalise volume values to 0-100%
-STATIC struct json_object *UnNormaliseValue(const alsaHalCtlMapT *halCtls, struct json_object *valuesJ) {
- int length;
- // assert response as the right length
- length = json_object_array_length(valuesJ);
- if (length != halCtls->count) {
- AFB_WARNING ("NormaliseValue invalid ctl='%s' values count=%d len=%d", halCtls->name, halCtls->count, length);
- return NULL;
- }
-
- json_object *normalisedJ= json_object_new_array();
- for (int idx=0; idx <length; idx++) {
- json_object *valueJ = json_object_array_get_idx (valuesJ, idx);
- int value = json_object_get_int(valueJ);
-
- // cleanup and normalise value
- if (value > halCtls->maxval) value= halCtls->maxval;
- if (value < halCtls->minval) value= halCtls->minval;
-
- // If Integer scale to 0/100
- if (halCtls->type == SND_CTL_ELEM_TYPE_INTEGER) {
- value = (value * 100) / (halCtls->maxval - halCtls->minval);
- }
-
- json_object_array_add(normalisedJ, json_object_new_int(value));
+
+// Map HAL ctlName to ctlLabel
+STATIC int halCtlStringToIndex (const char* label) {
+
+ for (int idx = 0; halCtls[idx].ctl.numid; idx++) {
+ if (!strcmp (halCtls[idx].label, label)) return idx;
}
- return (normalisedJ);
+ // not found
+ return -1;
}
+STATIC int halCtlTagToIndex (halCtlsEnumT tag) {
-
-// HAL normalise volume values to 0-100%
-STATIC struct json_object *NormaliseValue(const alsaHalCtlMapT *halCtls, struct json_object *valuesJ) {
- int length;
-
- // assert response as the right length
- length = json_object_array_length(valuesJ);
- if (length != halCtls->count) {
- AFB_WARNING ("NormaliseValue invalid ctl=%s values count=%d len=%d", halCtls->name, halCtls->count, length);
- return NULL;
- }
-
- json_object *normalisedJ= json_object_new_array();
- for (int idx=0; idx <length; idx++) {
- json_object *valueJ = json_object_array_get_idx (valuesJ, idx);
- int value = json_object_get_int(valueJ);
-
- // cleanup and normalise value
- if (value > halCtls->maxval) value= halCtls->maxval;
- if (value < halCtls->minval) value= halCtls->minval;
-
- // If Integer scale to 0/100
- if (halCtls->type == SND_CTL_ELEM_TYPE_INTEGER) {
- value = (value * 100) / (halCtls->maxval - halCtls->minval);
- }
-
- json_object_array_add(normalisedJ, json_object_new_int(value));
+ for (int idx = 0; halCtls[idx].ctl.numid; idx++) {
+ if (halCtls[idx].tag == tag) return idx;
}
- return (normalisedJ);
+ // not found
+ return -1;
}
-
// Return ALL HAL snd controls
PUBLIC void halListCtls(afb_req request) {
struct json_object *ctlsHalJ = json_object_new_array();
@@ -144,26 +93,6 @@ PUBLIC void halListCtls(afb_req request) {
afb_req_success (request, ctlsHalJ, NULL);
}
-// Map HAL ctlName to ctlLabel
-STATIC int halCtlStringToIndex (const char* label) {
-
- for (int idx = 0; halCtls[idx].ctl.numid; idx++) {
- if (!strcmp (halCtls[idx].label, label)) return idx;
- }
-
- // not found
- return -1;
-}
-
-STATIC int halCtlTagToIndex (halCtlsEnumT tag) {
-
- for (int idx = 0; halCtls[idx].ctl.numid; idx++) {
- if (halCtls[idx].tag == tag) return idx;
- }
-
- // not found
- return -1;
-}
STATIC int halGetCtlIndex (afb_req request, struct json_object*ctlInJ) {
struct json_object *tmpJ;
@@ -200,6 +129,43 @@ STATIC int halGetCtlIndex (afb_req request, struct json_object*ctlInJ) {
return -1;
}
+// HAL normalise volume values to 0-100%
+STATIC struct json_object *UnNormaliseValue(const alsaHalCtlMapT *halCtls, struct json_object *valuesJ) {
+ int length;
+
+ // assert response as the right length
+ length = json_object_array_length(valuesJ);
+ if (length != halCtls->count) {
+ AFB_WARNING ("UnNormaliseValue invalid ctl='%s' values count=%d len=%d", halCtls->name, halCtls->count, length);
+ return NULL;
+ }
+
+ json_object *normalisedJ= json_object_new_array();
+ for (int idx=0; idx < halCtls->count; idx++) {
+ int value;
+
+ // use last value in array when number of values does not match with actual ctl count
+ if (idx < length) {
+ json_object *valueJ = json_object_array_get_idx (valuesJ, idx);
+ value = json_object_get_int(valueJ);
+
+ // cleanup and normalise value
+ if (value > halCtls->maxval) value= halCtls->maxval;
+ if (value < halCtls->minval) value= halCtls->minval;
+
+ // If Integer move from 0-100% to effective value
+ if (halCtls->type == SND_CTL_ELEM_TYPE_INTEGER) {
+ value = (value * (halCtls->maxval-halCtls->minval))/100;
+ }
+ }
+
+ // add unnormalised value into response
+ json_object_array_add(normalisedJ, json_object_new_int(value));
+ }
+
+ return (normalisedJ);
+}
+
// Translate high level control to low level and call lower layer
PUBLIC void halSetCtls(afb_req request) {
@@ -212,11 +178,11 @@ PUBLIC void halSetCtls(afb_req request) {
switch (json_object_get_type(ctlsInJ)) {
case json_type_object: {
- // control is in literal form {tag=xxx, label=xxx, val=xxxx}
+ // control is in literal form {tag=xxx, label=xxx, value=xxxx}
index = halGetCtlIndex (request, ctlsInJ);
if (index <=0) goto OnErrorExit;
- err= json_object_object_get_ex (ctlsInJ, "val" , &valuesJ);
+ err= json_object_object_get_ex (ctlsInJ, "value" , &valuesJ);
if (err) {
afb_req_fail_f(request, "ctl-invalid", "No val=[val1, ...] ctl='%s'", json_object_get_string(ctlsInJ));
goto OnErrorExit;
@@ -234,7 +200,7 @@ PUBLIC void halSetCtls(afb_req request) {
index= halGetCtlIndex (request, ctlInJ);
if (index<=0) goto OnErrorExit;
- err= json_object_object_get_ex (ctlInJ, "val" , &valuesJ);
+ err= json_object_object_get_ex (ctlInJ, "value" , &valuesJ);
if (err) {
afb_req_fail_f(request, "ctl-invalid", "No val=[val1, ...] ctl='%s'", json_object_get_string(ctlsInJ));
goto OnErrorExit;
@@ -257,7 +223,7 @@ PUBLIC void halSetCtls(afb_req request) {
// Call now level CTL
queryJ = json_object_new_object();
json_object_object_add(queryJ, "devid", json_object_new_string (halDevid));
- json_object_object_add(queryJ, "numids", ctlsOutJ);
+ json_object_object_add(queryJ, "numid", ctlsOutJ);
err= afb_service_call_sync("alsacore", "setctls", queryJ, &responseJ);
if (err) {
@@ -313,7 +279,7 @@ STATIC json_object *CtlGetPrepareResponse(afb_req request, struct json_object *c
struct json_object *halCtlJ = json_object_new_object();
json_object_object_add(halCtlJ, "label", json_object_new_string(halCtls[idx].label)); // idx+1 == HAL/NUMID
json_object_object_add(halCtlJ, "tag" , json_object_new_int(halCtls[idx].tag)); // idx+1 == HAL/NUMID
- json_object_object_add(halCtlJ, "val" , NormaliseValue(&halCtls[idx].ctl, valJ));
+ json_object_object_add(halCtlJ, "val" , GetNormaliseVolume(&halCtls[idx].ctl, valJ));
json_object_array_add(halResponseJ, halCtlJ);
break;
}
@@ -366,9 +332,9 @@ PUBLIC void halGetCtls(afb_req request) {
// Call now level CTL
queryJ = json_object_new_object();
json_object_object_add(queryJ, "devid", json_object_new_string (halDevid));
- json_object_object_add(queryJ, "numids", ctlsOutJ);
+ json_object_object_add(queryJ, "numid", ctlsOutJ);
- err= afb_service_call_sync("alsacore", "getctls", queryJ, &responseJ);
+ err= afb_service_call_sync("alsacore", "getctl", queryJ, &responseJ);
if (err) {
afb_req_fail_f(request, "subcall:alsacore/getctl", "%s", json_object_get_string(responseJ));
goto OnErrorExit;
@@ -418,17 +384,14 @@ PUBLIC void halServiceEvent(const char *evtname, struct json_object *eventJ) {
STATIC int UpdateOneSndCtl (alsaHalCtlMapT *ctl, struct json_object *sndCtlJ) {
struct json_object *tmpJ, *ctlJ;
- AFB_NOTICE ("*** %s, ", json_object_get_string(sndCtlJ));
-
- // make sure we face a valid Alsa Low level ctl
- if (!json_object_object_get_ex (sndCtlJ, "ctrl" , &ctlJ)) return -1;
-
json_object_object_get_ex (sndCtlJ, "name" , &tmpJ);
ctl->name = (char*)json_object_get_string(tmpJ);
json_object_object_get_ex (sndCtlJ, "numid" , &tmpJ);
ctl->numid = json_object_get_int(tmpJ);
+ // make sure we face a valid Alsa Low level ctl
+ if (!json_object_object_get_ex (sndCtlJ, "ctl" , &ctlJ)) goto OnErrorExit;
json_object_object_get_ex (ctlJ, "min" , &tmpJ);
ctl->minval = json_object_get_int(tmpJ);
@@ -445,7 +408,33 @@ STATIC int UpdateOneSndCtl (alsaHalCtlMapT *ctl, struct json_object *sndCtlJ) {
json_object_object_get_ex (ctlJ, "type" , &tmpJ);
ctl->type = (snd_ctl_elem_type_t)json_object_get_int(tmpJ);
+ // process dbscale TLV if any
+ if (json_object_object_get_ex (sndCtlJ, "tlv" , &tmpJ)) {
+ struct json_object *dbscaleJ;
+
+ if (!json_object_object_get_ex (tmpJ, "dbscale" , &dbscaleJ)) {
+ AFB_WARNING("TLV found but not DBscale attached ctl name=%s numid=%d", ctl->name, ctl->numid);
+ } else {
+ ctl->dbscale = malloc (sizeof (alsaHalDBscaleT));
+
+ json_object_object_get_ex (dbscaleJ, "min" , &tmpJ);
+ ctl->dbscale->min = (snd_ctl_elem_type_t)json_object_get_int(tmpJ);
+
+ json_object_object_get_ex (dbscaleJ, "max" , &tmpJ);
+ ctl->dbscale->max = (snd_ctl_elem_type_t)json_object_get_int(tmpJ);
+
+ json_object_object_get_ex (dbscaleJ, "step" , &tmpJ);
+ ctl->dbscale->step = (snd_ctl_elem_type_t)json_object_get_int(tmpJ);
+
+ json_object_object_get_ex (dbscaleJ, "mute" , &tmpJ);
+ ctl->dbscale->mute = (snd_ctl_elem_type_t)json_object_get_int(tmpJ);
+ }
+ }
+
return 0;
+
+ OnErrorExit:
+ return -1;
}
// this is call when after all bindings are loaded
@@ -510,7 +499,8 @@ PUBLIC int halServiceInit (const char *apiPrefix, alsaHalSndCardT *alsaHalSndCar
queryurl = json_object_new_object();
json_object_get(devidJ); // make sure devidJ does not get free by 1st call.
json_object_object_add(queryurl, "devid",devidJ);
- json_object_object_add(queryurl, "ctls",ctlsJ);
+ json_object_object_add(queryurl, "ctl",ctlsJ);
+ json_object_object_add(queryurl, "mode",json_object_new_int(QUERY_COMPACT));
err= afb_service_call_sync ("alsacore", "addcustomctl", queryurl, &responseJ);
if (err) {
AFB_ERROR ("Fail creating HAL Custom ALSA ctls Response='%s'", json_object_get_string(responseJ));
@@ -553,10 +543,10 @@ PUBLIC int halServiceInit (const char *apiPrefix, alsaHalSndCardT *alsaHalSndCar
// Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT
PUBLIC afb_verb_v2 halServiceApi[] = {
- /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */
- { .verb = "ping", .callback = pingtest},
- { .verb = "listctls", .callback = halListCtls},
- { .verb = "getctls", .callback = halGetCtls},
- { .verb = "subscribe", .callback = halSubscribe},
+ /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */
+ { .verb = "ping", .callback = pingtest},
+ { .verb = "ctl-list", .callback = halListCtls},
+ { .verb = "ctl-get", .callback = halGetCtls},
+ { .verb = "evt-sub", .callback = halSubscribe},
{ .verb = NULL} /* marker for end of the array */
};
diff --git a/HAL-afb/HAL-interface/hal-interface.h b/HAL-afb/HAL-interface/hal-interface.h
index 2cd3586..afe480e 100644
--- a/HAL-afb/HAL-interface/hal-interface.h
+++ b/HAL-afb/HAL-interface/hal-interface.h
@@ -24,15 +24,21 @@
#include "audio-interface.h"
typedef struct {
+ int min;
+ int max;
+ int step;
+ int mute;
+} alsaHalDBscaleT;
+
+typedef struct {
char* name;
int numid;
- int values;
+ snd_ctl_elem_type_t type;
+ int count;
int minval;
int maxval;
int step;
- int count;
- snd_ctl_elem_type_t type;
- halAclEnumT acl;
+ alsaHalDBscaleT *dbscale;
} alsaHalCtlMapT;
// avoid compiler warning [Jose does not like typedef :) ]
@@ -62,6 +68,9 @@ extern afb_verb_v2 halServiceApi[];
PUBLIC void halServiceEvent(const char *evtname, struct json_object *object);
PUBLIC int halServiceInit (const char *apiPrefix, alsaHalSndCardT *alsaHalSndCard);
+// hal-volmap.c
+PUBLIC struct json_object *GetNormaliseVolume(const alsaHalCtlMapT *halCtls, struct json_object *valuesJ);
+
#endif /* SHAREHALLIB_H */
diff --git a/HAL-afb/HAL-interface/hal-volmap.c b/HAL-afb/HAL-interface/hal-volmap.c
new file mode 100644
index 0000000..de99974
--- /dev/null
+++ b/HAL-afb/HAL-interface/hal-volmap.c
@@ -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.
+ *
+ * references:
+ * alsa-util/amixer.c + alsa-lib/simple.c
+ */
+
+#define _GNU_SOURCE // needed for vasprintf
+#include <math.h>
+#include "hal-interface.h"
+
+
+typedef enum {
+ DB_NORMALIZE_LINEAR,
+ DB_NORMALIZE_MATH,
+} enumRandeModeDB_T;
+
+// Return Value express from 0-100%
+STATIC int dbNormalizeVal (enumRandeModeDB_T normaliseMode, const alsaHalDBscaleT *dbscale, int value) {
+ double normalized, min_norm;
+
+ // To get real DB from TLV DB values should be divided by 100
+ switch (normaliseMode) {
+ case DB_NORMALIZE_LINEAR:
+ normalized = ((double)(value-dbscale->min)/(double)(dbscale->max-dbscale->min))*100;
+ break;
+
+ case DB_NORMALIZE_MATH:
+ normalized = exp10((double)(value - dbscale->max) / 6000.0);
+ if (dbscale->min != SND_CTL_TLV_DB_GAIN_MUTE) {
+ min_norm = exp10((double)(dbscale->min - dbscale->max) / 6000.0);
+ normalized = (normalized - min_norm) / (1 - min_norm);
+ }
+ break;
+
+ default:
+ normalized=0;
+ }
+
+ return (int)round(normalized*100);
+}
+
+// HAL normalise volume values to 0-100%
+PUBLIC struct json_object *GetNormaliseVolume(const alsaHalCtlMapT *halCtls, struct json_object *valuesJ) {
+ int useNormalizeDB;
+
+ // If not valid db_scale let's use raw_scale
+ if (!halCtls->dbscale || (halCtls->dbscale->min >= halCtls->dbscale->max)) {
+
+ // dbscale is invalid let's try raw range
+ if (halCtls->minval >= halCtls->maxval) goto ExitOnError;
+
+ // Use Raw Scale Model
+ useNormalizeDB= 0;
+
+ } else { // db_scale looks OK let's use it
+ if ((halCtls->dbscale->max - halCtls->dbscale->min) <= MAX_LINEAR_DB_SCALE * 100) useNormalizeDB= DB_NORMALIZE_LINEAR;
+ else useNormalizeDB = DB_NORMALIZE_MATH;
+
+ }
+
+ // loop on values to normalise
+ int length = json_object_array_length(valuesJ);
+ json_object *normalisedJ= json_object_new_array();
+ for (int idx=0; idx <length; idx++) {
+ json_object *valueJ = json_object_array_get_idx (valuesJ, idx);
+ int value = json_object_get_int(valueJ);
+
+ // If Integer scale to 0/100
+ if (halCtls->type == SND_CTL_ELEM_TYPE_INTEGER) {
+ if (useNormalizeDB) value = dbNormalizeVal (useNormalizeDB, halCtls->dbscale, value);
+ else value = 100* (value - halCtls->minval) / (halCtls->maxval - halCtls->minval);
+ }
+
+ json_object_array_add(normalisedJ, json_object_new_int(value));
+ }
+
+ return (normalisedJ);
+
+ ExitOnError:
+ return NULL;
+}
+ \ No newline at end of file
diff --git a/HAL-afb/HAL-plugin/HalPlugCtl.c b/HAL-afb/HAL-plugin/HalPlugCtl.c
index 181d4f8..3755876 100644
--- a/HAL-afb/HAL-plugin/HalPlugCtl.c
+++ b/HAL-afb/HAL-plugin/HalPlugCtl.c
@@ -291,7 +291,7 @@ SND_CTL_PLUGIN_DEFINE_FUNC(afbhal) {
continue;
}
- if (strcmp(id, "ctls") == 0) {
+ if (strcmp(id, "ctl") == 0) {
const char *ctlConf;
snd_config_type_t ctype;
snd_config_iterator_t currentCtl, follow;
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a746cbf
--- /dev/null
+++ b/README.md
@@ -0,0 +1,146 @@
+------------------------------------------------------------------------
+AGL-AUDIO bindings expose low+high level API through AGL framework
+------------------------------------------------------------------------
+
+Cloning Audio-Binding from Git
+-------------------------------------------------------
+
+```
+git clone --recurse-submodules https://github.com/iotbzh/audio-bindings
+cd audio-binding
+
+```
+
+AFB_daemon dependency on Standard Linux Distributions
+-------------------------------------------------------
+ # handle dependencies > (OpenSuse-42.2, Fedora-25, Ubuntu 16.04.2LTS)
+ gcc > 4.8
+ systemd-devel (libsystemd-dev>=222)
+ libuuid-devel
+ file-devel(OpenSuSe) or libmagic-dev(Ubuntu)
+ libjson-c-devel
+ alsa-devel
+ ElectricFence (BUG should not be mandatory)
+ libopenssl-devel libgcrypt-devel libgnutls-devel (optional but requested by libmicrohttpd for https)
+
+ OpenSuse >=42.2
+ zypper in gcc5 gdb gcc5-c++ git cmake make ElectricFence systemd-devel libopenssl-devel libuuid-devel alsa-devel libgcrypt-devel libgnutls-devel libjson-c-devel file-devel mxml-devel
+
+ Ubuntu >= 16.4 libuuid-devel
+ apt-get install cmake git electric-fence libsystemd-dev libssl-dev uuid-dev libasound2-dev libgcrypt20-dev libgnutls-dev libgnutls-dev libjson-c-dev libmagic-dev libmxml-dev
+
+ libmicrohttpd>=0.9.55 (as today OpenSuse-42.2 or Ubuntu-.16.4 ship older versions)
+ afb-daemon from AGL Gerrit git clone https://gerrit.automotivelinux.org/gerrit/src/app-framework-binder
+
+```
+ # Might want to add following variables into ~/.bashrc
+ echo "#---------- AGL options Start ---------" >>~/.bashrc
+ echo "# Object: AGL cmake option for binder/bindings" >>~/.bashrc
+ echo "# Date: `date`" >>~/.bashrc
+ echo 'export CC=gcc-5; export CXX=g++-5' >>~/.bashrc # if using gcc5
+ echo 'export INSTALL_PREFIX=$HOME/opt' >>~/.bashrc
+ echo 'export LD_LIBRARY_PATH=$INSTALL_PREFIX/lib64:$INSTALL_PREFIX/lib' >>~/.bashrc
+ echo 'export LIBRARY_PATH=$INSTALL_PREFIX/lib64:$INSTALL_PREFIX/lib' >>~/.bashrc
+ echo 'export PKG_CONFIG_PATH=$INSTALL_PREFIX/lib64/pkgconfig:$INSTALL_PREFIX/lib/pkgconfig' >>~/.bashrc
+ echo 'export PATH=$INSTALL_PREFIX/bin:$PATH' >>~/.bashrc
+ echo 'export RSYNC_TARGET=MY_TARGET_HOSTNAME' >>~/.bashrc
+ echo 'export RSYNC_PREFIX=./opt' >>~/.bashrc
+
+ echo "#---------- AGL options End ---------" >>~/.bashrc
+ source ~/.bashrc
+
+ # install LibMicroHttpd
+ LIB_MH_VERSION=0.9.55
+ wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-${LIB_MH_VERSION}.tar.gz
+ tar -xzf libmicrohttpd-${LIB_MH_VERSION}.tar.gz
+ cd libmicrohttpd-${LIB_MH_VERSION}
+ ./configure --prefix=${INSTALL_PREFIX}
+ make
+ sudo make install-strip
+
+ # retrieve last AFB_daemon from AGL
+ git clone https://gerrit.automotivelinux.org/gerrit/src/app-framework-binder
+
+ # Warning: previous GCC options should be set before initial cmake (clean Build/*)
+ cd app-framework-binder; mkdir -p build; cd build
+ cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX ..
+ make
+ make install
+```
+
+
+# Compile binding
+
+```
+ source ~/.bashrc # or any other file where your have place your compilation preferences
+ mkdir -p build
+ cd build
+ cmake -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX ..
+ make
+
+ afb-daemon --workdir=.. --ldpaths=build --port=1234 --roothttp=./htdocs --token="" --verbose
+```
+
+# Local Source Debug with GDB
+
+Warning: technically AGL bindings are shared libraries loaded thought 'dlopen'. GDB supports source debug of dynamically
+loaded libraries, but user should be warn that the actual path to sharelib symbols is directly inherited from DLOPEN.
+As a result if you change your directory after binder start with --workdir=xxx then GDB will not find symbols anymore
+
+
+```
+ Examples:
+
+ # WORK when running in direct
+ afb-daemon --workdir=.. --ldpaths=build --port=1234 --roothttp=./htdocs
+
+ # FAIL when using GDB with warning: Could not load shared library ....
+ gdb -args afb-daemon --workdir=.. --ldpaths=build --port=1234 --roothttp=./htdocs
+ ...
+ warning: Could not load shared library symbols for ./build/ucs2-afb/afb-ucs2.so.
+ Do you need "set solib-search-path" or "set sysroot"?
+ ...
+```
+
+To debug sharelib symbol path: start your binder under GDB. Then break your session after the binder has
+loaded its bindings. Finally use "info sharedlibrary" and check 'SymsRead'. If equal to 'No' then either you start GDB
+from the wrong relative directory, either you have to use 'set solib-search-path' to force the path.
+
+```
+ gdb -args afb-daemon --workdir=.. --ldpaths=build --port=1234 --roothttp=./htdocs
+ run
+ ...
+ NOTICE: API UNICENS added
+ NOTICE: Waiting port=1234 rootdir=.
+ NOTICE: Browser URL= http://localhost:1234
+ (hit Ctrl-C to break the execution)
+ info sharedlibrary afb-*
+```
+
+
+# Running an debugging on a target
+
+```
+export RSYNC_TARGET=root@xx.xx.xx.xx
+export RSYNC_PREFIX=/opt # WARNING: installation directory should exist
+
+mkdir $RSYNC_TARGET
+cd $RSYNC_TARGET
+
+cmake -DRSYNC_TARGET=$RSYNC_TARGET -DRSYNC_PREFIX=$RSYNC_PREFIX ..
+make remote-target-populate
+
+ ./build/target/start-${RSYNC_TARGET}.sh
+ firefox http://localhost:1234 # WARNING: do not forget firewall if any
+
+ ssh -tt ${RSYNC_TARGET} speaker-test -twav -D hw:ep01 -c 2
+```
+
+Note: remote-target-populate will
+ - create a script to remotely start the binder on the target in ./build/target/start-on-target-name.sh
+ - create a gdbinit file to transparently debug remotely in source code with gdb -x ./build/target/gdb-on-target-name.ini
+ - to run and debug directly from your IDE just configure the run and debug properties with the corresponding filename
+
+Note that Netbeans impose to set debug directory to ./build/pkgout or it won't find binding symbols for source debugging
+
+
diff --git a/Shared-Interface/audio-interface.h b/Shared-Interface/audio-interface.h
index 8cbea6f..09cb6c2 100644
--- a/Shared-Interface/audio-interface.h
+++ b/Shared-Interface/audio-interface.h
@@ -35,6 +35,13 @@
#endif
#define STATIC static
+typedef enum {
+ QUERY_QUIET =0,
+ QUERY_COMPACT =1,
+ QUERY_VERBOSE =2,
+ QUERY_FULL =3,
+} halQueryMode;
+
// Most controls are MIXER but some vendor specific are possible
typedef enum {
OUTVOL,
diff --git a/conf.d/cmake/config.cmake b/conf.d/cmake/config.cmake
index e703c80..97c4986 100644
--- a/conf.d/cmake/config.cmake
+++ b/conf.d/cmake/config.cmake
@@ -43,7 +43,8 @@ set(CMAKE_BUILD_TYPE "DEBUG")
# Static constante definition
# -----------------------------
-add_compile_options(-DMAX_SND_CARD=16)
+add_compile_options(-DMAX_SND_CARD=16) # should be more than enough even in luxury vehicule
+add_compile_options(-DMAX_LINEAR_DB_SCALE=24) # until 24db volume normalisation use a simple linear scale
# Compiler selection if needed. Overload the detected compiler.
# -----------------------------------------------
diff --git a/htdocs/AFB-websock.js b/htdocs/AFB-websock.js
index e77ec89..ff9fa60 100644
--- a/htdocs/AFB-websock.js
+++ b/htdocs/AFB-websock.js
@@ -1,7 +1,10 @@
+var urlws;
+var urlhttp;
+
AFB = function(base, initialtoken){
-var urlws = "ws://"+window.location.host+"/"+base;
-var urlhttp = "http://"+window.location.host+"/"+base;
+urlws = "ws://"+window.location.host+"/"+base;
+urlhttp = "http://"+window.location.host+"/"+base;
/*********************************************/
/**** ****/
diff --git a/htdocs/AudioBinding.css b/htdocs/AudioBinding.css
new file mode 100644
index 0000000..1052aa7
--- /dev/null
+++ b/htdocs/AudioBinding.css
@@ -0,0 +1,7 @@
+pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }
+.string { color: green; }
+.number { color: darkorange; }
+.boolean { color: blue; }
+.null { color: magenta; }
+.key { color: red; }
+
diff --git a/htdocs/AudioBinding.js b/htdocs/AudioBinding.js
index 7105b20..e000a70 100644
--- a/htdocs/AudioBinding.js
+++ b/htdocs/AudioBinding.js
@@ -1,8 +1,30 @@
var afb = new AFB("api", "mysecret");
var ws;
- var halapi="HALNotSelected";
+ var sndcard="HALNotSelected";
var evtidx=0;
+ function syntaxHighlight(json) {
+ if (typeof json !== 'string') {
+ json = JSON.stringify(json, undefined, 2);
+ }
+ json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+ return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
+ var cls = 'number';
+ if (/^"/.test(match)) {
+ if (/:$/.test(match)) {
+ cls = 'key';
+ } else {
+ cls = 'string';
+ }
+ } else if (/true|false/.test(match)) {
+ cls = 'boolean';
+ } else if (/null/.test(match)) {
+ cls = 'null';
+ }
+ return '<span class="' + cls + '">' + match + '</span>';
+ });
+ }
+
function getParameterByName(name, url) {
if (!url) {
url = window.location.href;
@@ -25,8 +47,8 @@
var sndname=getParameterByName("sndname");
if (!sndname) sndname="PCH";
- var quiet=getParameterByName("quiet");
- if (!quiet) quiet="99";
+ var mode=getParameterByName("mode");
+ if (!mode) mode="99";
@@ -54,12 +76,12 @@
function replyok(obj) {
console.log("replyok:" + JSON.stringify(obj));
- document.getElementById("output").innerHTML = "OK: "+JSON.stringify(obj);
+ document.getElementById("output").innerHTML = "OK: "+ syntaxHighlight(obj);
}
function replyerr(obj) {
console.log("replyerr:" + JSON.stringify(obj));
- document.getElementById("output").innerHTML = "ERROR: "+JSON.stringify(obj);
+ document.getElementById("output").innerHTML = "ERROR: "+ syntaxHighlight(obj);
}
function gotevent(obj) {
@@ -78,7 +100,8 @@
// On button click from HTML page
function callbinder(api, verb, query) {
console.log ("subscribe api="+api+" verb="+verb+" query=" +query);
- document.getElementById("question").innerHTML = "apicall: " + api+"/"+verb +" ("+ JSON.stringify(query)+")";
+ var question = urlws +"/" +api +"/" +verb + "?query=" + JSON.stringify(query);
+ document.getElementById("question").innerHTML = syntaxHighlight(question);
ws.call(api+"/"+verb, query).then(replyok, replyerr);
}
@@ -89,27 +112,38 @@
// onlick update selected HAL api
selectobj.onclick=function(){
- halapi= this.value;
- console.log ("New Default HAL=" + halapi);
+ sndcard= this.value;
+ console.log ("Default Selection=" + sndcard);
};
function gotit (result) {
- // display response as for normal onclick action
- replyok(result);
- var response=result.response;
+ // display response as for normal onclick action
+ replyok(result);
+ var response=result.response;
- // fulfill select with avaliable active HAL
- for (idx=0; idx<response.length; idx++) {
- console.log ("probeActiveHal =" + response[idx].shortname);
- var opt = document.createElement('option');
- opt.value = response[idx].api;
- opt.text = response[idx].shortname;
- selectobj.appendChild(opt);
- }
+ // fulfill select with avaliable active HAL
+ for (idx=0; idx<response.length; idx++) {
+ var opt = document.createElement('option');
+
+ // Alsa LowLevel selection mode
+ if (response[idx].name) opt.text = response[idx].name;
+ if (response[idx].devid) opt.value = response[idx].devid;
+
+ // HAL selection mode
+ if (response[idx].shortname) opt.text = response[idx].shortname;
+ if (response[idx].api) opt.value = response[idx].api;
+
+ selectobj.appendChild(opt);
+ }
- halapi= selectobj.value;
+ sndcard= selectobj.value;
}
+
+ console.log ("subscribe api="+api+" verb="+verb+" query=" +query);
+
+ var question = urlws +"/"+api +"/" +verb + "?query=" + JSON.stringify(query);
+ document.getElementById("question").innerHTML = syntaxHighlight(question);
// request lowlevel ALSA to get API list
ws.call(api+"/"+verb, query).then(gotit, replyerr);
diff --git a/htdocs/alsa-core.html b/htdocs/alsa-core.html
index 7fff3d8..9b6e214 100644
--- a/htdocs/alsa-core.html
+++ b/htdocs/alsa-core.html
@@ -1,50 +1,58 @@
<html>
<head>
- <title>Hello world test</title>
+ <link rel="stylesheet" href="AudioBinding.css">
+ <title>Alsa Low Level Simple Test</title>
+
<script type="text/javascript" src="AFB-websock.js"></script>
<script type="text/javascript" src="AudioBinding.js"></script>
+</head>
+
+<body onload="init('alsa_registry','alsacore', 'getinfo');">
<b> references</b>
- <ol>
- <li>http://localhost:1234/alsa-core.html?devid=hw:xx</li>
- <li>amixer -D hw:PCH controls</li>
- </ol>
-
-<body onload="init();">
- <h1>Hello world test</h1>
- <button id="connected" onclick="init()">Binder WS Fail</button></li>
+ <button id="connected" onclick="init('alsa_registry','alsacore', 'getinfo')">Binder WS Fail</button>
+ <br><br>
+ <b>Selected SndCard </b>
+ <select id='alsa_registry'></select>
+
+ <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>
+
+
<ol>
- <li><a href="api/alsacore/getinfo">getinfo: List Sound Cards</a>
- <li><button onclick="callbinder('alsacore','getinfo', {quiet:quiet})">Get All Sound Card info</button></li>
- <li><button onclick="callbinder('alsacore','getinfo', {devid:devid, quiet:quiet})">Get Sound Card info devid=xx</button></li>
- <li><button onclick="callbinder('alsacore','getctls', {devid:devid, quiet:quiet})">Get all Alsa Ctls for devid=xx</button></li>
- <li><button onclick="callbinder('alsacore','getctls', {devid:devid, quiet:quiet, numids:[4]})">Get Alsa Ctls numids:[4]</button></li>
- <li><button onclick="callbinder('alsacore','getctls', {devid:devid, quiet:quiet, numids:[1,2]})">Get Alsa Ctls numids:[1,2]</button></li>
- <li><button onclick="callbinder('alsacore','getctls', {devid:devid, quiet:quiet, numids:17})">Get Alsa Ctl numids:17</button></li>
+ <li><button onclick="callbinder('alsacore','getctl', {devid:sndcard, mode:mode})">Get all Alsa Ctls</button></li>
+ <li><button onclick="callbinder('alsacore','getctl', {devid:sndcard, mode:mode, numids:[6]})">Get Alsa Ctls numids:[6]</button></li>
+ <li><button onclick="callbinder('alsacore','getctl', {devid:sndcard, mode:mode, numids:[1,2]})">Get Alsa Ctls numids:[1,2]</button></li>
+ <li><button onclick="callbinder('alsacore','getctl', {devid:sndcard, mode:mode, numids:17})">Get Alsa Ctl numids:17</button></li>
<br>
- <li><button onclick="callbinder('alsacore','setctls', {devid:devid, quiet:quiet, numids:[[17,20]]})">Set Alsa Ctl numid:[[17,20]]</button></li>
- <li><button onclick="callbinder('alsacore','setctls', {devid:devid, quiet:quiet, numids:[{id:17,val:50}]})">Set Alsa Ctl numid:[{id:17,val:50}]}</button></li>
- <li><button onclick="callbinder('alsacore','setctls', {devid:devid, quiet:quiet, numids:[[1,[20,20]]]})">Set Alsa Ctl numids:[[1,[20,20]]]</button></li>
- <li><button onclick="callbinder('alsacore','setctls', {devid:devid, quiet:quiet, numids:[{id:1,val:[50,50]}]})">Set Alsa Ctl numids:[{id:1,val:[50,50]}]</button></li>
- <li><button onclick="callbinder('alsacore','setctls', {devid:devid, quiet:quiet, numids:[{id:1,val:[50,50]}, {id:17,val:50,50}]})">Set Alsa Ctl numids:[{id:1,val:[50,50]}, {id:17,val:50,50}]</button></li>
+ <li><button onclick="callbinder('alsacore','setctl', {devid:sndcard, mode:mode, numids:[[17,20]]})">Set Alsa Ctl numid:[[17,20]]</button></li>
+ <li><button onclick="callbinder('alsacore','setctl', {devid:sndcard, mode:mode, numids:[{id:17,val:50}]})">Set Alsa Ctl numid:[{id:17,val:50}]}</button></li>
+ <li><button onclick="callbinder('alsacore','setctl', {devid:sndcard, mode:mode, numids:[[1,[20,20]]]})">Set Alsa Ctl numids:[[1,[20,20]]]</button></li>
+ <li><button onclick="callbinder('alsacore','setctl', {devid:sndcard, mode:mode, numids:[{id:1,val:[50,50]}]})">Set Alsa Ctl numids:[{id:1,val:[50,50]}]</button></li>
+ <li><button onclick="callbinder('alsacore','setctl', {devid:sndcard, mode:mode, numids:[{id:1,val:[50,50]}, {id:17,val:50,50}]})">Set Alsa Ctl numids:[{id:1,val:[50,50]}, {id:17,val:50,50}]</button></li>
<br>
- <li><button onclick="callbinder('alsacore','ucmquery', {devid:devid, quiet:quiet})">List UCM verbs</button></li>
- <li><button onclick="callbinder('alsacore','ucmset' , {devid:devid, quiet:quiet, verb:'HiFi'})">Set UCM HiFi</button></li>
- <li><button onclick="callbinder('alsacore','ucmset' , {devid:devid, quiet:quiet, verb:'HiFi', dev:'Headphone'})">Set UCM HiFi+Headphone</button></li>
- <li><button onclick="callbinder('alsacore','ucmset' , {devid:devid, quiet:quiet, verb:'HiFi', dev:'Headphone', mod:'RecordMedia'})">Set UCM HiFi+Headphone+RecordMedia</button></li>
+ <li><button onclick="callbinder('alsacore','ucmquery', {devid:sndcard, mode:mode})">List UCM verbs</button></li>
+ <li><button onclick="callbinder('alsacore','ucmset' , {devid:sndcard, mode:mode, verb:'HiFi'})">Set UCM HiFi</button></li>
+ <li><button onclick="callbinder('alsacore','ucmset' , {devid:sndcard, mode:mode, verb:'HiFi', dev:'Headphone'})">Set UCM HiFi+Headphone</button></li>
+ <li><button onclick="callbinder('alsacore','ucmset' , {devid:sndcard, mode:mode, verb:'HiFi', dev:'Headphone', mod:'RecordMedia'})">Set UCM HiFi+Headphone+RecordMedia</button></li>
<br>
- <li><button onclick="callbinder('alsacore','ucmget' , {devid:devid, quiet:quiet, values:['OutputDspName','PlaybackPCM','CapturePCM']})">Get UCM OutputDspName+PlaybackPCM+CapturePCM (SET UCM)</button></li>
+ <li><button onclick="callbinder('alsacore','ucmget' , {devid:sndcard, mode:mode, values:['OutputDspName','PlaybackPCM','CapturePCM']})">Get UCM OutputDspName+PlaybackPCM+CapturePCM (SET UCM)</button></li>
<br>
- <li><button onclick="callbinder('alsacore','subscribe', {devid:devid})">Subscribe AlsaCtl Events</button></li>
+ <li><button onclick="callbinder('alsacore','subscribe', {devid:sndcard})">Subscribe AlsaCtl Events</button></li>
<br>
</ol>
<div id="main" style="visibility:hidden">
<ol>
- <li>Question <div id="question"></div>
- <li>Response <div id="output"></div>
- <li>Events: <div id="outevt"></div>
+ <li>Question <pre id="question"></pre>
+ <li>Response <pre id="output"></pre>
+ <li>Events: <pre id="outevt"></pre>
</ol>
</div>
diff --git a/htdocs/alsa-hal.html b/htdocs/alsa-hal.html
index ce48ff3..7a8655c 100644
--- a/htdocs/alsa-hal.html
+++ b/htdocs/alsa-hal.html
@@ -1,7 +1,7 @@
<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>
@@ -9,29 +9,40 @@
<body onload="init('hal_registry','alsacore', 'hallist')">
-<b> references</b>
-
<h1>Simple AlsaHAL tests</h1>
<button id="connected" onclick="init('hal_registry','alsacore', 'hallist')">Binder WS Fail</button>
<br><br>
<b>Selected HAL </b>
<select id='hal_registry'></select>
+
+ <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(halapi,'listctls')">List Selected HAL Controls </button></li>
- <li><button onclick="callbinder(halapi,'getctls', {label:'Master_Playback_Volume'})">Get {label:'Master_Playback_Volume'}</button></li>
- <li><button onclick="callbinder(halapi,'getctls', [{tag:4},{tag:5}])">Get[{tag:4},{tag:5}]</button></li>
- <li><button onclick="callbinder(halapi,'getctls', [4,5])">Get [4,5]</button></li>
+ <li><button onclick="callbinder(sndcard,'listctls')">List Selected HAL Controls </button></li>
+ <li><button onclick="callbinder(sndcard,'ctl-get', {label:'Master_Playback_Volume'})">Get {label:'Master_Playback_Volume'}</button></li>
+ <li><button onclick="callbinder(sndcard,'ctl-get', [{tag:4},{tag:5}])">Get[{tag:4},{tag:5}]</button></li>
+ <li><button onclick="callbinder(sndcard,'ctl-get', [4,5])">Get [4,5]</button></li>
+ <br>
+ <li><button onclick="callbinder(sndcard,'ctl-set', {label:'Master_Playback_Volume', value=[50]})">Set {label:'Master_Playback_Volume', value=[50]}</button></li>
+ <li><button onclick="callbinder(sndcard,'ctl-set', [{tag:4, value:25},{tag:5, value:25}])">Set[{tag:4, value:25},{tag:5, value:25}]</button></li>
+ <li><button onclick="callbinder(sndcard,'ctl-set', [{tag:4, value:[55,45]},{tag:5, value:[45,55]}])">Set[{tag:4, value:[55,45]},{tag:5, value:[45,55]}]]</button></li>
+ <li><button onclick="callbinder(sndcard,'ctl-set', [4,5])">Set [4,5]</button></li>
<br>
</ol>
<div id="main" style="visibility:hidden">
<ol>
- <li>Question <div id="question"></div>
- <li>Response <div id="output"></div>
- <li>Events: <div id="outevt"></div>
+ <li>Question <pre id="question"></pre>
+ <li>Response <pre id="output"></pre>
+ <li>Events: <pre id="outevt"></pre>
</ol>
</div>
diff --git a/htdocs/audio-logic.html b/htdocs/audio-logic.html
index 79ab114..c31282a 100644
--- a/htdocs/audio-logic.html
+++ b/htdocs/audio-logic.html
@@ -1,29 +1,9 @@
<html>
<head>
- <title>Hello world test</title>
+ <title>High Level API Simple Test Page</title>
<script type="text/javascript" src="AFB-websock.js"></script>
<script type="text/javascript" src="AudioBinding.js"></script>
-
-<body onload="init();">
- <h1>Hello world test</h1>
- <button id="connected">Binder WS Fail</button></li>
- <br>
- <ol>
- <li><button onclick="callbinder('audio','open',{sndname: sndname})">Open SndCard</button></li>
- <br>
- <li><button onclick="callbinder('audio','setvol', {pcm:'master', vol='+10'})">Increase +10 Master</button></li>
- <li><button onclick="callbinder('audio','setvol', {pcm:'master', vol='-10'})">Decrease -10 Master</button></li>
- <li><button onclick="callbinder('audio','setvol', {pcm:'master', vol='%50'})">SetVol %50 Master</button></li>
- <li><button onclick="callbinder('audio','getvol', {pcm:'master'})">GetVolume Master</button></li>
- <br>
- <li><button onclick="callbinder('audio','monitor')">Monitor LowLevel Events</button></li>
- <li><button onclick="callbinder('audio','subscribe')">Subscribe AudioBinding Events</button></li>
- <br>
- <li><button onclick="callbinder('audio','close')">Close SndCard</button></li>
+</head>
- <br>
- <div id="main" style="visibility:hidden">
- Server says... <div id="output"></div>
- Events: <div id="outevt"></div>
- </div>
+ToBeDone \ No newline at end of file
diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml
index adb9376..18d1e63 100644
--- a/nbproject/configurations.xml
+++ b/nbproject/configurations.xml
@@ -15,6 +15,8 @@
<df name="HAL-afb">
<df name="HAL-interface">
<in>hal-interface.c</in>
+ <in>hal-volmap.c</in>
+ <in>hal-volmap.h</in>
</df>
<df name="HAL-plugin">
<in>HalPlugCb.c</in>
@@ -80,9 +82,10 @@
</toolsSet>
<flagsDictionary>
<element flagsID="0" commonFlags="-g -fPIC -fPIC -g"/>
- <element flagsID="1" commonFlags="-mtune=generic -march=x86-64 -g -fPIC"/>
- <element flagsID="2" commonFlags="-mtune=generic -march=x86-64 -g -g -fPIC"/>
- <element flagsID="3"
+ <element flagsID="1" commonFlags="-g -ggdb -fPIC -fPIC -g -ggdb"/>
+ <element flagsID="2" commonFlags="-mtune=generic -march=x86-64 -g -fPIC"/>
+ <element flagsID="3" commonFlags="-mtune=generic -march=x86-64 -g -g -fPIC"/>
+ <element flagsID="4"
commonFlags="-mtune=generic -march=x86-64 -g -ggdb -g -ggdb -fPIC"/>
</flagsDictionary>
<codeAssistance>
@@ -102,44 +105,51 @@
</preBuild>
</makefileType>
<item path="ALSA-afb/Alsa-AddCtl.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
<incDir>
<pElem>../../../opt/include/alsa</pElem>
<pElem>/usr/include/json-c</pElem>
+ <pElem>Shared-Interface</pElem>
+ <pElem>../../../opt/include</pElem>
<pElem>build/ALSA-afb</pElem>
</incDir>
</cTool>
</item>
<item path="ALSA-afb/Alsa-ApiHat.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
<incDir>
<pElem>build/ALSA-afb</pElem>
</incDir>
</cTool>
</item>
<item path="ALSA-afb/Alsa-RegEvt.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
<incDir>
<pElem>../../../opt/include/alsa</pElem>
<pElem>/usr/include/json-c</pElem>
+ <pElem>Shared-Interface</pElem>
+ <pElem>../../../opt/include</pElem>
<pElem>build/ALSA-afb</pElem>
</incDir>
</cTool>
</item>
<item path="ALSA-afb/Alsa-SetGet.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
<incDir>
<pElem>../../../opt/include/alsa</pElem>
<pElem>/usr/include/json-c</pElem>
+ <pElem>Shared-Interface</pElem>
+ <pElem>../../../opt/include</pElem>
<pElem>build/ALSA-afb</pElem>
</incDir>
</cTool>
</item>
<item path="ALSA-afb/Alsa-Ucm.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
<incDir>
<pElem>../../../opt/include/alsa</pElem>
<pElem>/usr/include/json-c</pElem>
+ <pElem>Shared-Interface</pElem>
<pElem>../../../opt/include</pElem>
<pElem>build/ALSA-afb</pElem>
</incDir>
@@ -153,72 +163,86 @@
ex="false"
tool="0"
flavor2="3">
- <cTool flags="3">
+ <cTool flags="1">
+ <incDir>
+ <pElem>../../../opt/include/afb</pElem>
+ <pElem>../../../opt/include</pElem>
+ <pElem>../../../opt/include/alsa</pElem>
+ <pElem>/usr/include/p11-kit-1</pElem>
+ <pElem>/usr/include/json-c</pElem>
+ <pElem>HAL-afb/HAL-interface</pElem>
+ <pElem>Shared-Interface</pElem>
+ <pElem>build/HAL-afb/HAL-interface</pElem>
+ </incDir>
</cTool>
</item>
- <item path="HAL-afb/HAL-plugin/HalPlugCb.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <item path="HAL-afb/HAL-interface/hal-volmap.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="1">
<incDir>
- <pElem>HAL-afb/HAL-plugin</pElem>
+ <pElem>../../../opt/include</pElem>
<pElem>../../../opt/include/alsa</pElem>
+ <pElem>/usr/include/p11-kit-1</pElem>
+ <pElem>/usr/include/json-c</pElem>
+ <pElem>HAL-afb/HAL-interface</pElem>
+ <pElem>Shared-Interface</pElem>
+ <pElem>build/HAL-afb/HAL-interface</pElem>
+ </incDir>
+ </cTool>
+ </item>
+ <item path="HAL-afb/HAL-plugin/HalPlugCb.c" ex="false" tool="0" flavor2="3">
+ <cTool flags="4">
+ <incDir>
<pElem>../../../opt/include</pElem>
<pElem>build/HAL-afb/HAL-plugin</pElem>
</incDir>
</cTool>
</item>
<item path="HAL-afb/HAL-plugin/HalPlugCtl.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
<incDir>
- <pElem>HAL-afb/HAL-plugin</pElem>
- <pElem>../../../opt/include/alsa</pElem>
<pElem>../../../opt/include</pElem>
<pElem>build/HAL-afb/HAL-plugin</pElem>
</incDir>
</cTool>
</item>
<item path="HAL-afb/HAL-plugin/HalPlugPcm.c" ex="false" tool="0" flavor2="3">
- <cTool flags="1">
+ <cTool flags="2">
<incDir>
- <pElem>../../../opt/include/afb</pElem>
- <pElem>HAL-afb/HAL-plugin</pElem>
- <pElem>../../../opt/include/alsa</pElem>
<pElem>build/HAL-afb/HAL-plugin</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>
</item>
<item path="HAL-afb/HDA-intel/IntelHdaHAL.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
</cTool>
</item>
<item path="HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c"
ex="false"
tool="0"
flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
</cTool>
</item>
<item path="HAL-afb/Unicens-USB/UnicensHAL.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
<incDir>
+ <pElem>Shared-Interface</pElem>
+ <pElem>HAL-afb/HAL-interface</pElem>
<pElem>../../../opt/include</pElem>
<pElem>build/HAL-afb/Unicens-USB</pElem>
</incDir>
</cTool>
</item>
<item path="HAL-afb/Unicens-USB/UnicensVol.c" ex="false" tool="0" flavor2="3">
- <cTool flags="3">
+ <cTool flags="4">
<incDir>
+ <pElem>HAL-afb/HAL-interface</pElem>
<pElem>build/HAL-afb/Unicens-USB</pElem>
</incDir>
</cTool>
</item>
<item path="HighLevel-afb/HighLevelApiConf.c" ex="false" tool="0" flavor2="3">
- <cTool flags="2">
+ <cTool flags="3">
<incDir>
<pElem>Shared-Interface</pElem>
<pElem>../../../opt/include</pElem>
@@ -227,7 +251,7 @@
</cTool>
</item>
<item path="HighLevel-afb/HighLevelBinding.c" ex="false" tool="0" flavor2="3">
- <cTool flags="2">
+ <cTool flags="3">
<incDir>
<pElem>/usr/include/json-c</pElem>
<pElem>Shared-Interface</pElem>
@@ -271,7 +295,7 @@
<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 flags="4">
</cTool>
</item>
<folder path="0/ALSA-afb">
@@ -311,13 +335,16 @@
</folder>
<folder path="0/HAL-afb/HAL-interface">
<cTool>
+ <preprocessorList>
+ <Elem>MAX_LINEAR_DB_SCALE=24</Elem>
+ </preprocessorList>
+ </cTool>
+ </folder>
+ <folder path="0/HAL-afb/HAL-plugin">
+ <cTool>
<incDir>
- <pElem>HAL-afb/HAL-interface</pElem>
+ <pElem>HAL-afb/HAL-plugin</pElem>
<pElem>../../../opt/include/alsa</pElem>
- <pElem>/usr/include/json-c</pElem>
- <pElem>Shared-Interface</pElem>
- <pElem>../../../opt/include</pElem>
- <pElem>build/HAL-afb/HAL-interface</pElem>
</incDir>
</cTool>
</folder>
@@ -350,8 +377,6 @@
<incDir>
<pElem>HAL-afb/Unicens-USB</pElem>
<pElem>../../../opt/include/alsa</pElem>
- <pElem>Shared-Interface</pElem>
- <pElem>HAL-afb/HAL-interface</pElem>
</incDir>
</cTool>
</folder>
@@ -457,6 +482,10 @@
<cTool flags="3">
</cTool>
</item>
+ <item path="HAL-afb/HAL-interface/hal-volmap.c" ex="false" tool="0" flavor2="0">
+ </item>
+ <item path="HAL-afb/HAL-interface/hal-volmap.h" ex="false" tool="3" flavor2="0">
+ </item>
<item path="HAL-afb/HAL-plugin/HalPlugCb.c" ex="false" tool="0" flavor2="3">
<cTool flags="3">
<incDir>
@@ -709,6 +738,10 @@
<cTool flags="1">
</cTool>
</item>
+ <item path="HAL-afb/HAL-interface/hal-volmap.c" ex="false" tool="0" flavor2="0">
+ </item>
+ <item path="HAL-afb/HAL-interface/hal-volmap.h" ex="false" tool="3" flavor2="0">
+ </item>
<item path="HAL-afb/HAL-plugin/HalPlugCb.c" ex="false" tool="0" flavor2="3">
<cTool flags="1">
<incDir>