From cc1ec41093c3b0db3b8bdf8e8949ecdacceda190 Mon Sep 17 00:00:00 2001 From: Jonathan Aillet Date: Sat, 9 Jun 2018 00:22:05 +0200 Subject: Add value normalization of alsa control values Add functions that allows to normalize values that are requested to be sent with an alsa set control call (using alsacore). Change-Id: I5046a66d807c9b9b6751e036a47303ceddc0c16a Signed-off-by: Jonathan Aillet --- .../4a-hal-controllers-alsacore-link.c | 27 +++- 4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c | 32 ++-- .../4a-hal-controllers-value-handler.c | 161 +++++++++++++++++++++ .../4a-hal-controllers-value-handler.h | 34 +++++ 4 files changed, 236 insertions(+), 18 deletions(-) create mode 100644 4a-hal/4a-hal-controllers/4a-hal-controllers-value-handler.c create mode 100644 4a-hal/4a-hal-controllers/4a-hal-controllers-value-handler.h (limited to '4a-hal/4a-hal-controllers') diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-alsacore-link.c b/4a-hal/4a-hal-controllers/4a-hal-controllers-alsacore-link.c index 230cddd..47cfcc7 100644 --- a/4a-hal/4a-hal-controllers/4a-hal-controllers-alsacore-link.c +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-alsacore-link.c @@ -31,6 +31,7 @@ #include "../4a-hal-utilities/4a-hal-utilities-appfw-responses-handler.h" #include "4a-hal-controllers-alsacore-link.h" +#include "4a-hal-controllers-value-handler.h" /******************************************************************************* * Map to alsa control types * @@ -264,7 +265,7 @@ int HalCtlsSetAlsaCtlValue(AFB_ApiT apiHandle, char *cardId, int ctlId, json_obj return -4; } - wrap_json_pack(&queryJ, "{s:s s:{s:i s:o}}", "devid", cardId, "ctl", "id", ctlId, "val", valuesJ); + wrap_json_pack(&queryJ, "{s:s s:{s:i s:o}}", "devid", cardId, "ctl", "id", ctlId, "val", json_object_get(valuesJ)); if(AFB_ServiceSync(apiHandle, ALSACORE_API, ALSACORE_CTLSET_VERB, queryJ, &returnedJ)) { returnedError = HalUtlHandleAppFwCallError(apiHandle, ALSACORE_API, ALSACORE_CTLSET_VERB, returnedJ, &returnedStatus, &returnedInfo); @@ -386,7 +387,7 @@ void HalCtlsActionOnAlsaCtl(AFB_ReqT request) struct SpecificHalData *currentCtlHalData; struct CtlHalAlsaMap *currentAlsaCtl; - json_object *requestJson; + json_object *requestJson, *valueJ, *convertedJ; apiHandle = (AFB_ApiT) afb_request_get_dynapi(request); if(! apiHandle) { @@ -440,17 +441,29 @@ void HalCtlsActionOnAlsaCtl(AFB_ReqT request) snprintf(cardIdString, 6, "hw:%i", currentCtlHalData->sndCardId); - // TODO JAI: add weighting passing values on currentAlsaCtl->value (and put them into valueJ json) + if(wrap_json_unpack(requestJson, "{s:o}", "val", &valueJ)) { + AFB_ReqFailF(request, + "request_json", "Error when trying to get request value object inside request '%s'", + json_object_get_string(requestJson)); + return; + } - // TODO JAI : test it - if(HalCtlsSetAlsaCtlValue(apiHandle, cardIdString, currentAlsaCtl->ctl.numid, requestJson)) { + if(HalCtlsNormalizeJsonValues(apiHandle, ¤tAlsaCtl->ctl.alsaCtlProperties, valueJ, &convertedJ)) { + AFB_ReqFailF(request, "request_json", "Error when trying to convert request json '%s'", json_object_get_string(requestJson)); + return; + } + + if(HalCtlsSetAlsaCtlValue(apiHandle, cardIdString, currentAlsaCtl->ctl.numid, convertedJ)) { AFB_ReqFailF(request, "alsa_control_call_error", - "Error while trying to set value on alsa control %i, device '%s'", + "Error while trying to set value on alsa control %i, device '%s', message '%s'", currentAlsaCtl->ctl.numid, - cardIdString); + cardIdString, + json_object_get_string(requestJson)); return; } + json_object_put(convertedJ); + AFB_ReqSucess(request, NULL, "Action on alsa control correclty done"); } \ No newline at end of file diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c b/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c index e52639f..5b9f2a8 100644 --- a/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c @@ -27,8 +27,9 @@ #include "../4a-hal-utilities/4a-hal-utilities-appfw-responses-handler.h" #include "4a-hal-controllers-cb.h" -#include "4a-hal-controllers-mixer-handler.h" #include "4a-hal-controllers-alsacore-link.h" +#include "4a-hal-controllers-mixer-handler.h" +#include "4a-hal-controllers-value-handler.h" /******************************************************************************* * HAL controller event handler function * @@ -81,10 +82,14 @@ void HalCtlsDispatchApiEvent(afb_dynapi *apiHandle, const char *evtLabel, json_o source.api = currentHalAlsaCtlsT->ctls[idx].action->api; source.request = NULL; - // TODO JAI: add weighting passing values (new valueJ object) - (void) ActionExecOne(&source, currentHalAlsaCtlsT->ctls[idx].action, valuesJ); } + else { + AFB_ApiNotice(apiHandle, + "%s: The alsa control id '%i' is corresponding to a known control but without any action registered", + __func__, + numid); + } return; } @@ -219,7 +224,7 @@ int HalCtlsProcessOneHalMapObject(AFB_ApiT apiHandle, struct CtlHalAlsaMap *alsa int HalCtlsHandleOneHalMapObject(AFB_ApiT apiHandle, char *cardId, struct CtlHalAlsaMap *alsaMap) { - json_object *valueJ; + json_object *valueJ, *convertedValueJ; if(alsaMap->ctl.alsaCtlCreation) { if(HalCtlsCreateAlsaCtl(apiHandle, cardId, &alsaMap->ctl)) { @@ -237,16 +242,21 @@ int HalCtlsHandleOneHalMapObject(AFB_ApiT apiHandle, char *cardId, struct CtlHal } if(alsaMap->ctl.value) { - // TODO JAI: add weighting passing values on currentAlsaCtl->value (and put them into valueJ json) - + // TBD JAI : handle alsa controls type valueJ = json_object_new_int(alsaMap->ctl.value); - if(HalCtlsSetAlsaCtlValue(apiHandle, cardId, alsaMap->ctl.numid, valueJ)) { + + if(HalCtlsNormalizeJsonValues(apiHandle, &alsaMap->ctl.alsaCtlProperties, valueJ, &convertedValueJ)) { + AFB_ApiError(apiHandle, "Error when trying to convert initiate value json '%s'", json_object_get_string(valueJ)); + return -3; + } + + if(HalCtlsSetAlsaCtlValue(apiHandle, cardId, alsaMap->ctl.numid, convertedValueJ)) { AFB_ApiError(apiHandle, "Error while trying to set initial value on alsa control %i, device '%s', value '%s'", alsaMap->ctl.numid, cardId, json_object_get_string(valueJ)); - return -3; + return -4; } } @@ -257,7 +267,7 @@ int HalCtlsHandleOneHalMapObject(AFB_ApiT apiHandle, char *cardId, struct CtlHal "%s: Didn't succeed to load action using alsa object:\n-- %s", __func__, json_object_get_string(alsaMap->actionJ)); - return -4; + return -5; } } @@ -266,7 +276,7 @@ int HalCtlsHandleOneHalMapObject(AFB_ApiT apiHandle, char *cardId, struct CtlHal "%s: Didn't to create verb for current alsa control to load action using alsa object:\n-- %s", __func__, json_object_get_string(alsaMap->actionJ)); - return -5; + return -6; } return 0; @@ -291,7 +301,7 @@ int HalCtlsProcessAllHalMap(AFB_ApiT apiHandle, json_object *AlsaMapJ, struct Ct currentCtlHalAlsaMapT->ctlsCount = 0; currentCtlHalAlsaMapT->ctls = NULL; AFB_ApiWarning(apiHandle, "%s: couldn't get content of 'halmap' section in:\n-- %s", __func__, json_object_get_string(AlsaMapJ)); - return -3; + return -1; } ctlMaps = calloc(currentCtlHalAlsaMapT->ctlsCount, sizeof(struct CtlHalAlsaMap)); diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-value-handler.c b/4a-hal/4a-hal-controllers/4a-hal-controllers-value-handler.c new file mode 100644 index 0000000..f749521 --- /dev/null +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-value-handler.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author Jonathan Aillet + * + * 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 +#include +#include + +#include +#include + +#include + +#include "4a-hal-controllers-value-handler.h" +#include "4a-hal-controllers-alsacore-link.h" + +/******************************************************************************* + * Simple conversion value to/from percentage functions * + ******************************************************************************/ + +int HalCtlsConvertValueToPercentage(double val, double min, double max) +{ + double range; + + range = max - min; + if(range <= 0) + return -INT_MAX; + + val -= min; + + return (int) round(val / range * 100); +} + +int HalCtlsConvertPercentageToValue(int percentage, int min, int max) +{ + int range; + + range = max - min; + if(range <= 0) + return -INT_MAX; + + return (int) round((double) percentage * (double) range * 0.01 + (double) min); +} + +/******************************************************************************* + * Convert json object from percentage to value * + ******************************************************************************/ + +int HalCtlsNormalizeJsonValues(AFB_ApiT apiHandle, struct CtlHalAlsaCtlProperties *alsaCtlProperties, json_object *toConvertJ, json_object ** ConvertedJ) +{ + int err = 0, idx, count, initialValue, convertedValue; + + json_object *toConvertObjectJ, *convertedValueJ, *convertedArrayJ; + + switch(json_object_get_type(toConvertJ)) { + case json_type_array: + count = json_object_array_length(toConvertJ); + break; + + case json_type_null: + case json_type_object: + count = 0; + AFB_ApiWarning(apiHandle, "%s: can't normalize json values :\n-- %s", __func__, json_object_get_string(toConvertJ)); + *ConvertedJ = json_object_get(toConvertJ); + return -1; + + default: + count = 1; + break; + } + + convertedArrayJ = json_object_new_array(); + + for(idx = 0; idx < count; idx++) { + if(count > 1) + toConvertObjectJ = json_object_array_get_idx(toConvertJ, idx); + else + toConvertObjectJ = toConvertJ; + + switch(alsaCtlProperties->type) { + case SND_CTL_ELEM_TYPE_INTEGER: + case SND_CTL_ELEM_TYPE_INTEGER64: + if(! json_object_is_type(toConvertObjectJ, json_type_int)) { + err += -10*idx; + AFB_ApiWarning(apiHandle, + "%s: Try normalize an integer control but value sent in json is not an integer : '%s'", + __func__, + json_object_get_string(toConvertObjectJ)); + convertedValueJ = toConvertObjectJ; + break; + } + + initialValue = json_object_get_int(toConvertObjectJ); + convertedValue = HalCtlsConvertPercentageToValue(initialValue, alsaCtlProperties->minval, alsaCtlProperties->maxval); + if(convertedValue == -INT_MAX) { + AFB_ApiWarning(apiHandle, + "%s: Can't normalize %i (using min %i et max %i), value set to 0", + __func__, + initialValue, + alsaCtlProperties->minval, + alsaCtlProperties->maxval); + convertedValue = 0; + } + + if(alsaCtlProperties->step) { + // Round value to the nearest step + convertedValue = (int) round((double) convertedValue / (double) alsaCtlProperties->step); + convertedValue *= alsaCtlProperties->step; + } + + convertedValueJ = json_object_new_int(convertedValue); + break; + + case SND_CTL_ELEM_TYPE_BOOLEAN: + if(! (json_object_is_type(toConvertObjectJ, json_type_int) || + json_object_is_type(toConvertObjectJ, json_type_boolean))) { + err += -1000*idx; + AFB_ApiWarning(apiHandle, + "%s: Try normalize a boolean control but value sent in json is not a boolean/integer : '%s'", + __func__, + json_object_get_string(toConvertObjectJ)); + convertedValueJ = toConvertObjectJ; + break; + } + + initialValue = json_object_get_int(toConvertObjectJ); + convertedValueJ = json_object_new_int(initialValue ? 1 : 0); + break; + + default: + AFB_ApiWarning(apiHandle, + "%s: Normalization not handle for the alsa control type %i, sending back the object as it was '%s'", + __func__, + (int) alsaCtlProperties->type, + json_object_get_string(toConvertJ)); + convertedValueJ = toConvertObjectJ; + break; + } + + json_object_array_put_idx(convertedArrayJ, idx, convertedValueJ); + } + + *ConvertedJ = convertedArrayJ; + + return 0; +} \ No newline at end of file diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-value-handler.h b/4a-hal/4a-hal-controllers/4a-hal-controllers-value-handler.h new file mode 100644 index 0000000..5f91aaa --- /dev/null +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-value-handler.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 "IoT.bzh" + * Author Jonathan Aillet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HAL_CTLS_VALUE_NORMALIZATION_INCLUDE_ +#define _HAL_CTLS_VALUE_NORMALIZATION_INCLUDE_ + +#include + +#include + +#include "4a-hal-controllers-alsacore-link.h" + +// Simple conversion value to/from percentage functions +int HalCtlsConvertValueToPercentage(double val, double min, double max); +int HalCtlsConvertPercentageToValue(int percentage, int min, int max); + +// Convert json object from percentage to value +int HalCtlsNormalizeJsonValues(AFB_ApiT apiHandle, struct CtlHalAlsaCtlProperties *alsaCtlProperties, json_object *toConvertJ, json_object ** ConvertedJ); + +#endif /* _HAL_CTLS_VALUE_NORMALIZATION_INCLUDE_ */ \ No newline at end of file -- cgit 1.2.3-korg