/* * 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 "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 HalCtlsConvertJsonValueForIntegerControl(AFB_ApiT apiHandle, struct CtlHalAlsaCtlProperties *alsaCtlProperties, json_object *toConvertJ, json_object **ConvertedJ, enum ConversionType requestedConversion) { int initialValue, convertedValue; if(! json_object_is_type(toConvertJ, json_type_int)) { AFB_ApiError(apiHandle, "Can't convert json value, unrecognized json format (must be an integer) : '%s'", json_object_get_string(toConvertJ)); return -1; } initialValue = json_object_get_int(toConvertJ); switch(requestedConversion) { case CONVERSION_NORMALIZED_TO_ALSACORE: if(initialValue < 0 || initialValue > 100) { AFB_ApiError(apiHandle, "Cannot convert '%i' value, value should be between 0 and 100 ('%s')", initialValue, json_object_get_string(toConvertJ)); return -2; } convertedValue = HalCtlsConvertPercentageToValue(initialValue, alsaCtlProperties->minval, alsaCtlProperties->maxval); if(convertedValue == -INT_MAX) { AFB_ApiError(apiHandle, "Didn't succeed to convert %i (using min %i et max %i)", initialValue, alsaCtlProperties->minval, alsaCtlProperties->maxval); return -3; } if(alsaCtlProperties->step) { // Round value to the nearest step convertedValue = (int) round((double) convertedValue / (double) alsaCtlProperties->step); convertedValue *= alsaCtlProperties->step; } break; case CONVERSION_ALSACORE_TO_NORMALIZED: convertedValue = HalCtlsConvertValueToPercentage(initialValue, alsaCtlProperties->minval, alsaCtlProperties->maxval); if(convertedValue == -INT_MAX) { AFB_ApiError(apiHandle, "Didn't succeed to convert %i (using min %i et max %i)", initialValue, alsaCtlProperties->minval, alsaCtlProperties->maxval); return -4; } break; default: AFB_ApiError(apiHandle, "Can't convert '%i' value, unrecognized conversion type : '%i'", initialValue, (int) requestedConversion); *ConvertedJ = NULL; return -5; } *ConvertedJ = json_object_new_int(convertedValue); return 0; } int HalCtlsConvertJsonValueForBooleanControl(AFB_ApiT apiHandle, struct CtlHalAlsaCtlProperties *alsaCtlProperties, json_object *toConvertJ, json_object **ConvertedJ, enum ConversionType requestedConversion) { int initialValue; switch(json_object_get_type(toConvertJ)) { case json_type_int: initialValue = json_object_get_int(toConvertJ); break; case json_type_boolean: initialValue = json_object_get_boolean(toConvertJ); break; default: AFB_ApiError(apiHandle, "Can't convert json value, unrecognized format (must be an integer or a boolean) : '%s'", json_object_get_string(toConvertJ)); return -1; } if(initialValue < 0 || initialValue > 1) { AFB_ApiError(apiHandle, "Cannot convert '%i' value, value should be 0 or 1 ('%s')", initialValue, json_object_get_string(toConvertJ)); return -2; } switch(requestedConversion) { case CONVERSION_NORMALIZED_TO_ALSACORE: *ConvertedJ = json_object_new_int(initialValue); break; case CONVERSION_ALSACORE_TO_NORMALIZED: *ConvertedJ = json_object_new_boolean(initialValue); break; default: AFB_ApiError(apiHandle, "Can't convert '%i' value, unrecognized conversion type : '%i'", initialValue, (int) requestedConversion); *ConvertedJ = NULL; return -3; } return 0; } int HalCtlsConvertJsonValues(AFB_ApiT apiHandle, struct CtlHalAlsaCtlProperties *alsaCtlProperties, json_object *toConvertJ, json_object **ConvertedJ, enum ConversionType requestedConversion) { int conversionError = 0, idx, count; json_type toConvertType; json_object *toConvertObjectJ, *convertedValueJ, *convertedArrayJ; *ConvertedJ = NULL; toConvertType = json_object_get_type(toConvertJ); count = (toConvertType == json_type_array) ? (int) json_object_array_length(toConvertJ) : 1; convertedArrayJ = json_object_new_array(); for(idx = 0; idx < count; idx++) { if(toConvertType == json_type_array) 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((conversionError = HalCtlsConvertJsonValueForIntegerControl(apiHandle, alsaCtlProperties, toConvertObjectJ, &convertedValueJ, requestedConversion))) { AFB_ApiError(apiHandle, "Error %i happened in when trying to convert index %i for integer control ('%s')", conversionError, idx, json_object_get_string(toConvertObjectJ)); json_object_put(convertedArrayJ); return -(idx + 1); } break; case SND_CTL_ELEM_TYPE_BOOLEAN: if((conversionError = HalCtlsConvertJsonValueForBooleanControl(apiHandle, alsaCtlProperties, toConvertObjectJ, &convertedValueJ, requestedConversion))) { AFB_ApiError(apiHandle, "Error %i happened in when trying to convert index %i for boolean control ('%s')", conversionError, idx, json_object_get_string(toConvertObjectJ)); json_object_put(convertedArrayJ); return -(idx + 1); } break; default: AFB_ApiError(apiHandle, "Conversion not handle for the alsa control type %i", (int) alsaCtlProperties->type); json_object_put(convertedArrayJ); return -(idx + 1); } json_object_array_put_idx(convertedArrayJ, idx, convertedValueJ); } *ConvertedJ = convertedArrayJ; return 0; }