/* * 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-utilities-alsa-data.h" #include "4a-hal-utilities-data.h" #include "4a-internals-hal-alsacore-link.h" #include "4a-internals-hal-value-handler.h" /******************************************************************************* * Map to alsa control types * ******************************************************************************/ static const char *const snd_ctl_elem_type_names[] = { [SND_CTL_ELEM_TYPE_NONE] = "NONE", [SND_CTL_ELEM_TYPE_BOOLEAN] = "BOOLEAN", [SND_CTL_ELEM_TYPE_INTEGER] = "INTEGER", [SND_CTL_ELEM_TYPE_ENUMERATED] = "ENUMERATED", [SND_CTL_ELEM_TYPE_BYTES] = "BYTES", [SND_CTL_ELEM_TYPE_IEC958] = "IEC958", [SND_CTL_ELEM_TYPE_INTEGER64] = "INTEGER64", }; /******************************************************************************* * Alsa control types map from string function * ******************************************************************************/ snd_ctl_elem_type_t InternalHalMapsAlsaTypeToEnum(const char *label) { int idx; static int length = sizeof(snd_ctl_elem_type_names) / sizeof(char *); for(idx = 0; idx < length; idx++) { if(! strcasecmp(label, snd_ctl_elem_type_names[idx])) return (snd_ctl_elem_type_t) idx; } return SND_CTL_ELEM_TYPE_NONE; } /******************************************************************************* * Internals HAL - Alsacore events handler function * ******************************************************************************/ enum aslacoreEventType InternalHalGetAlsaCoreEventType(const char *evtLabel) { if(! evtLabel) return ALSACORE_UNRECOGNIZED_EVENT; if(! strncmp(&evtLabel[ALSACORE_EVENT_NAME_BEGIN], ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX, ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX_LENGTH)) return ALSACORE_EVENT_CARD_CONTROL_CHANGE; return ALSACORE_UNRECOGNIZED_EVENT; } int InternalHalHandleAlsaCoreCardControlEvent(afb_api_t apiHandle, const char *evtLabel, json_object *eventJ, struct HalData *currentHalData) { int numid, cardidx, controlsUsingCardCount = 0, controlUsedCount = 0; char cardNbString[6]; json_object *valuesJ, *normalizedValuesJ; CtlSourceT source; struct InternalHalAlsaMap *currentHalMapControl; if(! apiHandle || ! evtLabel || ! eventJ || ! currentHalData) { AFB_API_ERROR(apiHandle, "Invalid argument(s)"); return -1; } if(sscanf(&evtLabel[ALSACORE_CARD_CONTROL_EVENT_BEGIN], "%d", &cardidx) != 1) { AFB_API_ERROR(apiHandle, "Did not succeed to get ALSA card number of the modified control : evtname=%s [msg=%s]", evtLabel, json_object_get_string(eventJ)); return -2; } if(wrap_json_unpack(eventJ, "{s:i s:o}", "id", &numid, "val", &valuesJ)) { AFB_API_ERROR(apiHandle, "Invalid alsacore modified control event received label=%s value=%s", evtLabel, json_object_get_string(eventJ)); return -3; } if(cds_list_empty(¤tHalData->internalHalData->halMapListHead)) { AFB_API_ERROR(apiHandle, "No halmap data is available, cannot handle alsacore event label=%s value=%s", evtLabel, json_object_get_string(eventJ)); return -4; } // Search for corresponding numid in ALSA controls list, if found, launch callback (if available) cds_list_for_each_entry(currentHalMapControl, ¤tHalData->internalHalData->halMapListHead, node) { if(currentHalMapControl->cardNb == cardidx) controlsUsingCardCount++; if(currentHalMapControl->cardNb != cardidx || ! currentHalMapControl->ctl.alsaCtlProperties || currentHalMapControl->ctl.numid != numid) continue; if(currentHalMapControl->action) { memset(&source, 0, sizeof(CtlSourceT)); source.uid = currentHalMapControl->action->uid; source.api = currentHalMapControl->action->api; ActionExecOne(&source, currentHalMapControl->action, valuesJ); } else if(currentHalMapControl->actionJ) { AFB_API_WARNING(apiHandle, "The alsa control id '%i' is corresponding to a known control which " "has a registered action, but action is not ready to be executed", numid); } else { AFB_API_NOTICE(apiHandle, "The alsa control id '%i' is corresponding to a known control " "but without any action registered", numid); } if(! currentHalMapControl->alsaControlEvent || InternalHalConvertJsonValues(apiHandle, currentHalMapControl->ctl.alsaCtlProperties, valuesJ, &normalizedValuesJ, CONVERSION_ALSACORE_TO_NORMALIZED) || (afb_event_push(currentHalMapControl->alsaControlEvent, normalizedValuesJ) < 0)) { AFB_API_ERROR(apiHandle, "Couldn't generate an event for known halmap %s (alsa control id %i)", currentHalMapControl->uid, currentHalMapControl->ctl.numid); } controlUsedCount++; } if(! controlsUsingCardCount) { AFB_API_INFO(apiHandle, "Receiving events from not handle card %i, unscubscribe from these events", cardidx); snprintf(cardNbString, sizeof(cardNbString), "hw:%i", cardidx); InternalHalUnsubscribeFromAlsacoreCardEvent(apiHandle, cardNbString); return 1; } if(controlUsedCount) return 0; AFB_API_INFO(apiHandle, "Alsacore event with an unrecognized numid: %i, evtname=%s [msg=%s]", numid, evtLabel, json_object_get_string(eventJ)); return 2; } int InternalHalHandleAlsaCoreEvents(afb_api_t apiHandle, const char *evtLabel, json_object *eventJ, struct HalData *currentHalData) { int returned; if(! apiHandle || ! evtLabel || ! eventJ || ! currentHalData) { AFB_API_ERROR(apiHandle, "Invalid argument(s)"); return -1; } switch(InternalHalGetAlsaCoreEventType(evtLabel)) { case ALSACORE_EVENT_CARD_CONTROL_CHANGE: returned = InternalHalHandleAlsaCoreCardControlEvent(apiHandle, evtLabel, eventJ, currentHalData); if(returned < 0) { AFB_API_ERROR(apiHandle, "Error %i caught when tried to handle alsacore card control event evtname=%s [msg=%s]", returned, evtLabel, json_object_get_string(eventJ)); return -2; } else if(returned > 0) { AFB_API_INFO(apiHandle, "Warning %i raised when tried to handle alsacore card control event evtname=%s [msg=%s]", returned, evtLabel, json_object_get_string(eventJ)); } return 0; case ALSACORE_UNRECOGNIZED_EVENT: default: AFB_API_NOTICE(apiHandle, "Alsacore event with an unrecognized evtname=%s [msg=%s]", evtLabel, json_object_get_string(eventJ)); return 1; } } /******************************************************************************* * Internals HAL - Alsacore calls funtions * ******************************************************************************/ int InternalHalGetCardInfo(afb_api_t apiHandle, json_object *requestJ, json_object **responseJ) { int errorToReturn = 0; char *returnedError = NULL, *returnedInfo = NULL; if(! apiHandle || ! requestJ || ! responseJ) { AFB_API_ERROR(apiHandle, "Invalid argument(s)"); return -1; } if(afb_api_call_sync(apiHandle, ALSACORE_API, ALSACORE_GETINFO_VERB, requestJ, responseJ, &returnedError, &returnedInfo)) { AFB_API_ERROR(apiHandle, "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'", ALSACORE_GETINFO_VERB, ALSACORE_API, returnedError ? returnedError : "none", returnedInfo ? returnedInfo : "none"); errorToReturn = -2; } free(returnedError); free(returnedInfo); return errorToReturn; } int InternalHalSubscribeUnscubscribeToAlsacoreEvent(afb_api_t apiHandle, json_object *subscribeQueryJ, enum AlsacoreSubscribeUnsubscribeType subscriptionType) { int err = 0; char *returnedError = NULL, *returnedInfo = NULL; json_object *responseJ = NULL; if(! apiHandle || ! subscribeQueryJ) { AFB_API_ERROR(apiHandle, "Invalid argument(s)"); return -1; } if(afb_api_call_sync(apiHandle, ALSACORE_API, (subscriptionType == ALSACORE_SUBSCRIPTION) ? ALSACORE_SUBSCRIBE_VERB : ALSACORE_UNSUBSCRIBE_VERB, subscribeQueryJ, &responseJ, &returnedError, &returnedInfo)) { AFB_API_ERROR(apiHandle, "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'", (subscriptionType == ALSACORE_SUBSCRIPTION) ? ALSACORE_SUBSCRIBE_VERB : ALSACORE_UNSUBSCRIBE_VERB, ALSACORE_API, returnedError ? returnedError : "not returned", returnedInfo ? returnedInfo : "not returned"); err = -2; } if(responseJ) json_object_put(responseJ); free(returnedError); free(returnedInfo); return err; } int InternalHalSubscribeUnscubscribeToAlsacoreCardEvent(afb_api_t apiHandle, char *cardId, enum AlsacoreSubscribeUnsubscribeType subscriptionType) { int err, wrapRet; json_object *subscribeQueryJ = NULL; wrapRet = wrap_json_pack(&subscribeQueryJ, "{s:s, s:s}", "event", ALSACORE_CARD_CONTROL_EVENT_NAME, "devid", cardId); if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate subscription query json object"); return -1; } err = InternalHalSubscribeUnscubscribeToAlsacoreEvent(apiHandle, subscribeQueryJ, subscriptionType); if(err) { AFB_API_ERROR(apiHandle, "Error %i happened when tried to subscribe to %s card event", err, ALSACORE_API); if(! subscribeQueryJ) json_object_put(subscribeQueryJ); return -2; } return 0; } int InternalHalSubscribeToAlsacoreCardEvent(afb_api_t apiHandle, char *cardId) { return InternalHalSubscribeUnscubscribeToAlsacoreCardEvent(apiHandle, cardId, ALSACORE_SUBSCRIPTION); } int InternalHalUnsubscribeFromAlsacoreCardEvent(afb_api_t apiHandle, char *cardId) { return InternalHalSubscribeUnscubscribeToAlsacoreCardEvent(apiHandle, cardId, ALSACORE_UNSUBSCRIPTION); } int InternalHalGetAlsaCtlInfo(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *currentAlsaCtl, json_object **returnedDataJ) { int wrapRet; char *returnedError = NULL, *returnedInfo = NULL; json_object *queryJ, *responseJ = NULL; *returnedDataJ = NULL; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle not available"); return -1; } if(! cardId) { AFB_API_ERROR(apiHandle, "Card id is not available"); return -2; } if(! currentAlsaCtl) { AFB_API_ERROR(apiHandle, "Alsa control data structure is not available"); return -3; } if(currentAlsaCtl->name && currentAlsaCtl->numid > 0) { AFB_API_DEBUG(apiHandle, "Both a control name (%s) and a control id (%i) are specified, control id will be used", currentAlsaCtl->name, currentAlsaCtl->numid); } if(currentAlsaCtl->numid > 0) { wrapRet = wrap_json_pack(&queryJ, "{s:s s:i s:i}", "devid", cardId, "ctl", currentAlsaCtl->numid, "mode", 3); } else if(currentAlsaCtl->name) { wrapRet = wrap_json_pack(&queryJ, "{s:s s:s s:i}", "devid", cardId, "ctl", currentAlsaCtl->name, "mode", 3); } else { AFB_API_ERROR(apiHandle, "Need at least a control name or a control id"); return -4; } if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate get ALSA control query json object"); return -5; } if(afb_api_call_sync(apiHandle, ALSACORE_API, ALSACORE_CTLGET_VERB, queryJ, &responseJ, &returnedError, &returnedInfo)) { AFB_API_ERROR(apiHandle, "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'", ALSACORE_CTLGET_VERB, ALSACORE_API, returnedError ? returnedError : "not returned", returnedInfo ? returnedInfo : "not returned"); free(returnedError); free(returnedInfo); return -6; } else if(! responseJ) { AFB_API_ERROR(apiHandle, "Seems that %s call to api %s succeed but no response was returned", ALSACORE_CTLGET_VERB, ALSACORE_API); return -7; } *returnedDataJ = responseJ; return 0; } int InternalHalUpdateAlsaCtlProperties(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *currentAlsaCtl) { int err; char *name; json_object *returnedDataJ = NULL; if(! currentAlsaCtl->alsaCtlProperties) { AFB_API_ERROR(apiHandle, "Data structure to store alsa control properties is not allocated"); return -8; } err = InternalHalGetAlsaCtlInfo(apiHandle, cardId, currentAlsaCtl, &returnedDataJ); if(err) { return err; } // TBD JAI : get dblinear/dbminmax/... values else if(wrap_json_unpack(returnedDataJ, "{s:i s:s s:{s?:i s?:i s?:i s?:i s?:i}}", "id", ¤tAlsaCtl->numid, "name", &name, "ctl", "type", (int *) ¤tAlsaCtl->alsaCtlProperties->type, "count", ¤tAlsaCtl->alsaCtlProperties->count, "min", ¤tAlsaCtl->alsaCtlProperties->minval, "max", ¤tAlsaCtl->alsaCtlProperties->maxval, "step", ¤tAlsaCtl->alsaCtlProperties->step)) { AFB_API_ERROR(apiHandle, "Didn't succeed to get control %i properties on device '%s' : '%s'", currentAlsaCtl->numid, cardId, json_object_get_string(returnedDataJ)); err = -9; } else { currentAlsaCtl->name = strdup(name); if(! currentAlsaCtl->name) { AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'name' string"); err = -10; } } if(returnedDataJ) json_object_put(returnedDataJ); return err; } int InternalHalGetAlsaCtlValues(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *currentAlsaCtl, json_object **returnedValuesJ) { int err = 0; json_object *returnedDataJ = NULL, *returnedValuesArrayJ; *returnedValuesJ = NULL; err = InternalHalGetAlsaCtlInfo(apiHandle, cardId, currentAlsaCtl, &returnedDataJ); if(err) { return err; } else if(wrap_json_unpack(returnedDataJ, "{s:o}", "val", &returnedValuesArrayJ)) { AFB_API_ERROR(apiHandle, "Didn't succeed to get control %i values on device '%s' : '%s'", currentAlsaCtl->numid, cardId, json_object_get_string(returnedValuesArrayJ)); err = -8; } else if(! json_object_is_type(returnedValuesArrayJ, json_type_array)) { AFB_API_ERROR(apiHandle, "Json returned by control %i values on device '%s' are not an array ('%s')", currentAlsaCtl->numid, cardId, json_object_get_string(returnedValuesArrayJ)); err = -9; } if(! err) *returnedValuesJ = json_object_get(returnedValuesArrayJ); if(returnedDataJ) json_object_put(returnedDataJ); return err; } int InternalHalSetAlsaCtlValue(afb_api_t apiHandle, char *cardId, int ctlId, json_object *valuesJ) { int err = 0, wrapRet; char *returnedError = NULL, *returnedInfo = NULL; json_object *queryJ, *responseJ = NULL; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle not available"); return -1; } if(! cardId) { AFB_API_ERROR(apiHandle, "Card id is not available"); return -2; } if(ctlId <= 0) { AFB_API_ERROR(apiHandle, "Alsa control id is not valid"); return -3; } if(! valuesJ) { AFB_API_ERROR(apiHandle, "Values to set json is not available"); return -4; } wrapRet = wrap_json_pack(&queryJ, "{s:s s:{s:i s:o}}", "devid", cardId, "ctl", "id", ctlId, "val", json_object_get(valuesJ)); if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate set ALSA control query json object"); return -5; } if(afb_api_call_sync(apiHandle, ALSACORE_API, ALSACORE_CTLSET_VERB, queryJ, &responseJ, &returnedError, &returnedInfo)) { AFB_API_ERROR(apiHandle, "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'", ALSACORE_CTLSET_VERB, ALSACORE_API, returnedError ? returnedError : "not returned", returnedInfo ? returnedInfo : "not returned"); err = -6; } if(responseJ) json_object_put(responseJ); free(returnedError); free(returnedInfo); return err; } int InternalHalCreateAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *alsaCtlToCreate) { int err = 0, wrapRet; char *returnedError = NULL, *returnedInfo = NULL; json_object *queryJ, *responseJ = NULL; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle not available"); return -1; } if(! cardId) { AFB_API_ERROR(apiHandle, "Card id is not available"); return -2; } if(! alsaCtlToCreate) { AFB_API_ERROR(apiHandle, "Alsa control data structure is not available"); return -3; } if(! alsaCtlToCreate->alsaCtlCreation) { AFB_API_ERROR(apiHandle, "Alsa control data structure for control creation is not available"); return -4; } wrapRet = wrap_json_pack(&queryJ, "{s:s s:{s:i s:s s?:i s?:i s?:i s:i s:i}}", "devid", cardId, "ctl", "ctl", -1, "name", alsaCtlToCreate->name, "min", alsaCtlToCreate->alsaCtlCreation->minval, "max", alsaCtlToCreate->alsaCtlCreation->maxval, "step", alsaCtlToCreate->alsaCtlCreation->step, "type", (int) alsaCtlToCreate->alsaCtlCreation->type, "count", alsaCtlToCreate->alsaCtlCreation->count); if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate create ALSA control query json object"); return -5; } if(afb_api_call_sync(apiHandle, ALSACORE_API, ALSACORE_ADDCTL_VERB, queryJ, &responseJ, &returnedError, &returnedInfo)) { AFB_API_ERROR(apiHandle, "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'", ALSACORE_ADDCTL_VERB, ALSACORE_API, returnedError ? returnedError : "not returned", returnedInfo ? returnedInfo : "not returned"); err = -6; } else if(! responseJ) { AFB_API_ERROR(apiHandle, "Seems that %s call to api %s succeed but no response was returned", ALSACORE_ADDCTL_VERB, ALSACORE_API); err = -7; } else if(wrap_json_unpack(responseJ, "{s:i}", "id", &alsaCtlToCreate->numid)) { AFB_API_ERROR(apiHandle, "Can't get create id from %s of %s api", ALSACORE_ADDCTL_VERB, ALSACORE_API); err = -8; } else if(wrap_json_unpack(responseJ, "{s:o}", "ctl", NULL)) { AFB_API_WARNING(apiHandle, "Control %s was already present but has been updated", alsaCtlToCreate->name); } if(responseJ) json_object_put(responseJ); free(returnedError); free(returnedInfo); return err; } int InternalHalDeleteAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *alsaCtlToDelete) { int err = 0, wrapRet; char *returnedError = NULL, *returnedInfo = NULL, *removedControlName = NULL; json_object *queryJ, *responseJ = NULL; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Api handle not available"); return -1; } if(! cardId) { AFB_API_ERROR(apiHandle, "Card id is not available"); return -2; } if(! alsaCtlToDelete) { AFB_API_ERROR(apiHandle, "Alsa control data structure is not available"); return -3; } if(! alsaCtlToDelete->alsaCtlCreation) { AFB_API_ERROR(apiHandle, "Alsa control data structure for deletion is not available"); return -4; } if(alsaCtlToDelete->alsaCtlCreation != alsaCtlToDelete->alsaCtlProperties) { AFB_API_ERROR(apiHandle, "Alsa control was not previously created"); return -5; } wrapRet = wrap_json_pack(&queryJ, "{s:s s:{s:s}}", "devid", cardId, "ctl", "name", alsaCtlToDelete->name); if(wrapRet) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate delete ALSA control query json object"); return -6; } if(afb_api_call_sync(apiHandle, ALSACORE_API, ALSACORE_REMOVECTL_VERB, queryJ, &responseJ, &returnedError, &returnedInfo)) { AFB_API_ERROR(apiHandle, "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'", ALSACORE_REMOVECTL_VERB, ALSACORE_API, returnedError ? returnedError : "not returned", returnedInfo ? returnedInfo : "not returned"); err = -6; } else if(! responseJ) { AFB_API_ERROR(apiHandle, "Seems that %s call to api %s succeed but no response was returned", ALSACORE_REMOVECTL_VERB, ALSACORE_API); err = -7; } else if(wrap_json_unpack(responseJ, "{s:{s:s}}", "removed", "ctlName", &removedControlName)) { AFB_API_ERROR(apiHandle, "Can't get removed ALSA control name %s of %s api", ALSACORE_REMOVECTL_VERB, ALSACORE_API); err = -8; } AFB_API_DEBUG(apiHandle, "Control %s successfully removed", removedControlName); alsaCtlToDelete->alsaCtlProperties = NULL; if(responseJ) json_object_put(responseJ); free(returnedError); free(returnedInfo); return err; } /******************************************************************************* * Internals HAL - Alsacore controls request callback * ******************************************************************************/ void InternalHalActionOnAlsaCtl(afb_req_t request) { int wrapRet; char cardIdString[6]; afb_api_t apiHandle; CtlConfigT *ctrlConfig; struct HalData *currentHalData; struct InternalHalAlsaMap *currentAlsaCtl; json_object *requestJson, *valueJ, *convertedJ, *answerJ, *previousControlValuesJ, *normalizedPreviousControlValuesJ, *appliedControlValuesJ, *normalizedAppliedControlValuesJ; apiHandle = afb_req_get_api(request); if(! apiHandle) { afb_req_fail(request, "api_handle", "Can't get current internal hal api handle"); return; } ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle); if(! ctrlConfig) { afb_req_fail(request, "hal_controller_config", "Can't get current internal hal controller config"); return; } currentHalData = (struct HalData *) getExternalData(ctrlConfig); if(! currentHalData) { afb_req_fail(request, "hal_controller_data", "Can't get current internal hal controller data"); return; } if(currentHalData->status == HAL_STATUS_UNAVAILABLE) { afb_req_fail(request, "hal_unavailable", "Seems that hal is not available"); return; } currentAlsaCtl = (struct InternalHalAlsaMap *) afb_req_get_vcbdata(request); if(! currentAlsaCtl) { afb_req_fail(request, "alsa_control_data", "Can't get current alsa control data"); return; } if(currentAlsaCtl->ctl.numid <= 0) { afb_req_fail(request, "alsa_control_id", "Alsa control id is not valid"); return; } if(! currentAlsaCtl->ctl.alsaCtlProperties) { afb_req_fail(request, "alsa_control_not_available", "Alsa control is not available"); return; } snprintf(cardIdString, 6, "hw:%i", currentAlsaCtl->cardNb); if(InternalHalGetAlsaCtlValues(apiHandle, cardIdString, ¤tAlsaCtl->ctl, &previousControlValuesJ)) { afb_req_fail(request, "previous_values", "Error when trying to get unchanged alsa control values"); return; } else if(InternalHalConvertJsonValues(apiHandle, currentAlsaCtl->ctl.alsaCtlProperties, previousControlValuesJ, &normalizedPreviousControlValuesJ, CONVERSION_ALSACORE_TO_NORMALIZED)) { afb_req_fail_f(request, "request_json", "Error when trying to normalize unchanged alsa control values json '%s'", json_object_get_string(previousControlValuesJ)); json_object_put(previousControlValuesJ); return; } requestJson = afb_req_json(request); if(! requestJson) { wrapRet = wrap_json_pack(&answerJ, "{s:o}", "current", normalizedPreviousControlValuesJ); if(wrapRet) { afb_req_fail(request, "currentvalues_json_object", "Didn't succeed to allocate ALSA control current values response json object"); return; } afb_req_success(request, answerJ, "Current controls values"); json_object_put(previousControlValuesJ); return; } if(! json_object_is_type(requestJson, json_type_object)) { afb_req_fail_f(request, "request_json", "Request json is not valid '%s'", json_object_get_string(requestJson)); json_object_put(previousControlValuesJ); json_object_put(normalizedPreviousControlValuesJ); return; } if(wrap_json_unpack(requestJson, "{s:o}", "value", &valueJ)) { afb_req_fail_f(request, "request_json", "Error when trying to get request value object inside request '%s'", json_object_get_string(requestJson)); json_object_put(previousControlValuesJ); json_object_put(normalizedPreviousControlValuesJ); return; } if((! json_object_is_type(valueJ, json_type_string)) && InternalHalConvertJsonValues(apiHandle, currentAlsaCtl->ctl.alsaCtlProperties, valueJ, &convertedJ, CONVERSION_NORMALIZED_TO_ALSACORE)) { afb_req_fail_f(request, "request_json", "Error when trying to convert request values '%s'", json_object_get_string(valueJ)); json_object_put(previousControlValuesJ); json_object_put(normalizedPreviousControlValuesJ); return; } else if(json_object_is_type(valueJ, json_type_string) && InternalHalChangePreviousValuesUsingJson(apiHandle, currentAlsaCtl->ctl.alsaCtlProperties, valueJ, previousControlValuesJ, &convertedJ)) { afb_req_fail_f(request, "previous_values", "Error when trying to generate changed alsa control values (values : '%s', previous :'%s')", json_object_get_string(valueJ), json_object_get_string(previousControlValuesJ)); json_object_put(previousControlValuesJ); json_object_put(normalizedPreviousControlValuesJ); return; } json_object_put(previousControlValuesJ); if(InternalHalSetAlsaCtlValue(apiHandle, cardIdString, currentAlsaCtl->ctl.numid, convertedJ)) { afb_req_fail_f(request, "alsa_control_call_error", "Error while trying to set value on alsa control %i, device '%s', converted message '%s'", currentAlsaCtl->ctl.numid, cardIdString, json_object_get_string(convertedJ)); json_object_put(convertedJ); json_object_put(normalizedPreviousControlValuesJ); return; } json_object_put(convertedJ); if(InternalHalGetAlsaCtlValues(apiHandle, cardIdString, ¤tAlsaCtl->ctl, &appliedControlValuesJ)) { afb_req_fail(request, "applied_values", "Error when trying to get applied alsa control values"); json_object_put(normalizedPreviousControlValuesJ); return; } else if(InternalHalConvertJsonValues(apiHandle, currentAlsaCtl->ctl.alsaCtlProperties, appliedControlValuesJ, &normalizedAppliedControlValuesJ, CONVERSION_ALSACORE_TO_NORMALIZED)) { afb_req_fail_f(request, "request_json", "Error when trying to normalize applied values json '%s'", json_object_get_string(appliedControlValuesJ)); json_object_put(normalizedPreviousControlValuesJ); json_object_put(appliedControlValuesJ); return; } json_object_put(appliedControlValuesJ); wrapRet = wrap_json_pack(&answerJ, "{s:o, s:o}", "previous", normalizedPreviousControlValuesJ, "current", normalizedAppliedControlValuesJ); if(wrapRet) { afb_req_fail(request, "values_json_object", "Didn't succeed to allocate ALSA control previous and current values response json object"); return; } afb_req_success(request, answerJ, "Values correctly applied on alsa control"); }