From 757c9b407938b65b1e31ccc62217910d4f942dcb Mon Sep 17 00:00:00 2001 From: Jonathan Aillet Date: Mon, 11 Jun 2018 01:45:57 +0200 Subject: Update 4a-hal to work with new 4a-softmixer Update 4a-hal to work with new 4a-softmixer version : - Update audio configuration files to match the configuration format expected by the mixer. - Parse mixer attach response to get information about 'streams', 'playbacks', and 'captures'. store them in new field of controller hal data structure. - Create verb for each returned stream, but only one playback/capture verb even if threre are multiple playbacks/captures returned by the mixer attch verb. - Return 'streams', 'playbacks', and 'captures' when info verb is called. - If info verb is called with a json request, the request is transfered to the mixer. Change-Id: I65593281c34aa91ad87afbf8bebff755cc5cc6d0 Signed-off-by: Jonathan Aillet --- .../4a-hal-controllers-mixer-handler.c | 266 +++++++++++++++------ 1 file changed, 198 insertions(+), 68 deletions(-) (limited to '4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.c') diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.c b/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.c index cb4ea93..ffb1bf2 100644 --- a/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.c +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.c @@ -21,6 +21,8 @@ #include #include +#include + #include "../4a-hal-utilities/4a-hal-utilities-appfw-responses-handler.h" #include "../4a-hal-utilities/4a-hal-utilities-data.h" #include "../4a-hal-utilities/4a-hal-utilities-verbs-loader.h" @@ -34,70 +36,137 @@ * HAL controllers handle mixer calls functions * ******************************************************************************/ -int HalCtlsHandleMixerAttachResponse(AFB_ApiT apiHandle, struct CtlHalMixerDataT *currentHalStreamsData, json_object *mixerResponseJ) +int HalCtlsHandleMixerData(AFB_ApiT apiHandle, struct CtlHalMixerDataT *currentMixerDataT, json_object *currentDataJ, enum MixerDataType dataType) { + int idx, verbStart, size; int err = (int) MIXER_NO_ERROR; - unsigned int idx; - - char *currentStreamName, *currentStreamCardId; - struct HalUtlApiVerb *CtlHalDynApiStreamVerbs; + char *currentDataVerbName, *currentStreamCardId; - json_object *currentStreamJ; - - if(! apiHandle) { - AFB_ApiError(apiHandle, "%s: Can't get current hal api handle", __func__); - return (int) MIXER_ERROR_API_UNAVAILABLE; - } + json_object *currentJ; - switch(json_object_get_type(mixerResponseJ)) { + switch(json_object_get_type(currentDataJ)) { case json_type_object: - currentHalStreamsData->count = 1; + currentMixerDataT->count = 1; break; case json_type_array: - currentHalStreamsData->count = json_object_array_length(mixerResponseJ); + currentMixerDataT->count = json_object_array_length(currentDataJ); break; default: - currentHalStreamsData->count = 0; - AFB_ApiWarning(apiHandle, "%s: no streams returned", __func__); - return (int) MIXER_ERROR_NO_STREAMS; + currentMixerDataT->count = 0; + AFB_ApiError(apiHandle, "%s: no data returned", __func__); + return (int) MIXER_ERROR_DATA_EMPTY; } - currentHalStreamsData->data = (struct CtlHalMixerData *) calloc(currentHalStreamsData->count, sizeof(struct CtlHalMixerData)); + currentMixerDataT->data = (struct CtlHalMixerData *) calloc(currentMixerDataT->count, sizeof(struct CtlHalMixerData)); - CtlHalDynApiStreamVerbs = alloca((currentHalStreamsData->count + 1) * sizeof(struct HalUtlApiVerb)); - memset(CtlHalDynApiStreamVerbs, '\0', (currentHalStreamsData->count + 1) * sizeof(struct HalUtlApiVerb)); - CtlHalDynApiStreamVerbs[currentHalStreamsData->count].verb = NULL; - - for(idx = 0; idx < currentHalStreamsData->count; idx++) { - if(currentHalStreamsData->count > 1) - currentStreamJ = json_object_array_get_idx(mixerResponseJ, (int) idx); + for(idx = 0; idx < currentMixerDataT->count; idx++) { + if(currentMixerDataT->count > 1) + currentJ = json_object_array_get_idx(currentDataJ, (int) idx); else - currentStreamJ = mixerResponseJ; + currentJ = currentDataJ; - if(wrap_json_unpack(currentStreamJ, "{s:s}", "uid", ¤tStreamName)) { - AFB_ApiError(apiHandle, "%s: can't find name in current stream object", __func__); - err += (int) MIXER_ERROR_STREAM_NAME_UNAVAILABLE; + if(wrap_json_unpack(currentJ, "{s:s}", "verb", ¤tDataVerbName)) { + AFB_ApiError(apiHandle, "%s: can't find verb in current data object", __func__); + err += (int) MIXER_ERROR_DATA_NAME_UNAVAILABLE; } - else if(wrap_json_unpack(currentStreamJ, "{s:s}", "alsa", ¤tStreamCardId)) { - AFB_ApiError(apiHandle, "%s: can't find card id in current stream object", __func__); - err += (int) MIXER_ERROR_STREAM_CARDID_UNAVAILABLE; + else if(dataType == MIXER_DATA_STREAMS && wrap_json_unpack(currentJ, "{s:s}", "alsa", ¤tStreamCardId)) { + AFB_ApiError(apiHandle, "%s: can't find card id in current data object", __func__); + err += (int) MIXER_ERROR_DATA_CARDID_UNAVAILABLE; } else { - currentHalStreamsData->data[idx].name = strdup(currentStreamName); - currentHalStreamsData->data[idx].streamCardId = strdup(currentStreamCardId); + currentMixerDataT->data[idx].verbToCall = strdup(currentDataVerbName); + + if(dataType == MIXER_DATA_STREAMS) { + currentMixerDataT->data[idx].streamCardId = strdup(currentStreamCardId); + + size = (int) strlen(currentDataVerbName); + for(verbStart = 0; verbStart < size; verbStart++) { + if(currentDataVerbName[verbStart] == ':') + break; + } + + if(verbStart == size) + verbStart = 0; + else + verbStart++; + + currentMixerDataT->data[idx].verb = strdup(¤tDataVerbName[verbStart]); + + if(afb_dynapi_add_verb(apiHandle, + currentMixerDataT->data[idx].verb, + "Stream action transferred to mixer", + HalCtlsActionOnCall, + (void *) ¤tMixerDataT->data[idx], + NULL, + 0)) { + AFB_ApiError(apiHandle, "%s: error while creating verbs for stream : '%s'", __func__, currentMixerDataT->data[idx].verb); + err += (int) MIXER_ERROR_STREAM_VERB_NOT_CREATED; + } + } + else if(dataType == MIXER_DATA_PLAYBACKS) { + currentMixerDataT->data[idx].verb = strdup(HAL_PLAYBACK_VERB); + } + else if(dataType == MIXER_DATA_CAPTURES) { + currentMixerDataT->data[idx].verb = strdup(HAL_CAPTURE_VERB); + } + } + } + + if(dataType == MIXER_DATA_PLAYBACKS) { + if(afb_dynapi_add_verb(apiHandle, + HAL_PLAYBACK_VERB, + "Playback action transferred to mixer", + HalCtlsActionOnCall, + (void *) currentMixerDataT->data, + NULL, + 0)) { + AFB_ApiError(apiHandle, "%s: error while creating verb for playbacks : '%s'", __func__, HAL_PLAYBACK_VERB); + err += (int) MIXER_ERROR_PLAYBACK_VERB_NOT_CREATED; + } + } - CtlHalDynApiStreamVerbs[idx].verb = currentStreamName; - CtlHalDynApiStreamVerbs[idx].callback = HalCtlsActionOnStream; - CtlHalDynApiStreamVerbs[idx].info = "Peform action on this stream"; + if(dataType == MIXER_DATA_CAPTURES) { + if(afb_dynapi_add_verb(apiHandle, + HAL_CAPTURE_VERB, + "Capture action transferred to mixer", + HalCtlsActionOnCall, + (void *) currentMixerDataT->data, + NULL, + 0)) { + AFB_ApiError(apiHandle, "%s: error while creating verb for captures : '%s'", __func__, HAL_CAPTURE_VERB); + err += (int) MIXER_ERROR_CAPTURE_VERB_NOT_CREATED; } } - if(HalUtlLoadVerbs(apiHandle, CtlHalDynApiStreamVerbs)) { - AFB_ApiError(apiHandle, "%s: error while creating verbs for streams", __func__); - err += (int) MIXER_ERROR_COULDNT_ADD_STREAMS_AS_VERB; + return err; +} + +int HalCtlsHandleMixerAttachResponse(AFB_ApiT apiHandle, struct CtlHalSpecificData *currentHalSpecificData, json_object *mixerResponseJ) +{ + int err = (int) MIXER_NO_ERROR; + + json_object *mixerStreamsJ = NULL, *mixerPlaybacksJ = NULL, *mixerCapturesJ = NULL; + + if(! apiHandle) { + AFB_ApiError(apiHandle, "%s: Can't get current hal api handle", __func__); + return (int) MIXER_ERROR_API_UNAVAILABLE; } + if(wrap_json_unpack(mixerResponseJ, "{s:o s:o s:o}", "streams", &mixerStreamsJ, "playbacks", &mixerPlaybacksJ, "captures", &mixerCapturesJ)) { + AFB_ApiError(apiHandle, "%s: Can't get streams|playbacks|captures object in '%s'", __func__, json_object_get_string(mixerResponseJ)); + return (int) MIXER_ERROR_DATA_UNAVAILABLE; + } + + if((err += HalCtlsHandleMixerData(apiHandle, ¤tHalSpecificData->ctlHalStreamsData, mixerStreamsJ, MIXER_DATA_STREAMS))) + AFB_ApiError(apiHandle, "%s: Error during handling response mixer streams data '%s'", __func__, json_object_get_string(mixerStreamsJ)); + + if((err += HalCtlsHandleMixerData(apiHandle, ¤tHalSpecificData->ctlHalPlaybacksData, mixerPlaybacksJ, MIXER_DATA_PLAYBACKS))) + AFB_ApiError(apiHandle, "%s: Error during handling response mixer playbacks data '%s'", __func__, json_object_get_string(mixerPlaybacksJ)); + + if((err += HalCtlsHandleMixerData(apiHandle, ¤tHalSpecificData->ctlHalCapturesData, mixerCapturesJ, MIXER_DATA_CAPTURES))) + AFB_ApiError(apiHandle, "%s: Error during handling response mixer captures data '%s'", __func__, json_object_get_string(mixerCapturesJ)); + return err; } @@ -116,19 +185,36 @@ int HalCtlsAttachToMixer(AFB_ApiT apiHandle) json_object *returnJ, *toReturnJ; + if(! apiHandle) { + AFB_ApiError(apiHandle, "%s: Can't get current hal api handle", __func__); + return -1; + } + ctrlConfig = (CtlConfigT *) afb_dynapi_get_userdata(apiHandle); if(! ctrlConfig) { AFB_ApiError(apiHandle, "%s: Can't get current hal controller config", __func__); - return -1; + return -2; } currentCtlHalData = (struct SpecificHalData *) ctrlConfig->external; if(! currentCtlHalData) { AFB_ApiError(apiHandle, "%s: Can't get current hal controller data", __func__); - return -2; + return -3; + } + + switch(currentCtlHalData->status) { + case HAL_STATUS_UNAVAILABLE: + AFB_ApiError(apiHandle, "%s: Seems that the hal corresponding card was not found by alsacore at startup", __func__); + return -4; + + case HAL_STATUS_READY: + AFB_ApiNotice(apiHandle, "%s: Seems that the hal mixer is already initialized", __func__); + return 1; + + case HAL_STATUS_AVAILABLE: + break; } - // TODO JAI : add a test to see if the hal card id is already used firstHalData = HalMngGetFirstHalData(); if((concurentHalData = HalUtlSearchReadyHalDataByCarId(firstHalData, currentCtlHalData->sndCardId))) { AFB_ApiError(apiHandle, @@ -137,41 +223,28 @@ int HalCtlsAttachToMixer(AFB_ApiT apiHandle) currentCtlHalData->apiName, currentCtlHalData->sndCardId, concurentHalData->apiName); - return -3; + return -5; } apiToCall = currentCtlHalData->ctlHalSpecificData->mixerApiName; if(! apiToCall) { AFB_ApiError(apiHandle, "%s: Can't get mixer api", __func__); - return -4; - } - - switch(currentCtlHalData->status) { - case HAL_STATUS_UNAVAILABLE: - AFB_ApiError(apiHandle, "%s: Seems that the hal corresponding card was not found by alsacore at startup", __func__); - return -5; - - case HAL_STATUS_READY: - AFB_ApiNotice(apiHandle, "%s: Seems that the hal mixer is already initialized", __func__); - return 1; - - case HAL_STATUS_AVAILABLE: - break; + return -6; } if(AFB_ServiceSync(apiHandle, apiToCall, MIXER_ATTACH_VERB, json_object_get(currentCtlHalData->ctlHalSpecificData->halMixerJ), &returnJ)) { returnedError = HalUtlHandleAppFwCallError(apiHandle, apiToCall, MIXER_ATTACH_VERB, returnJ, &returnedStatus, &returnedInfo); - AFB_ApiWarning(apiHandle, - "Error %i during call to verb %s of %s api with status '%s' and info '%s'", - (int) returnedError, - apiToCall, - MIXER_ATTACH_VERB, - returnedStatus ? returnedStatus : "not returned", - returnedInfo ? returnedInfo : "not returned"); - return -6; + AFB_ApiError(apiHandle, + "Error %i during call to verb %s of %s api with status '%s' and info '%s'", + (int) returnedError, + apiToCall, + MIXER_ATTACH_VERB, + returnedStatus ? returnedStatus : "not returned", + returnedInfo ? returnedInfo : "not returned"); + return -7; } else if(json_object_object_get_ex(returnJ, "response", &toReturnJ)) { - err = HalCtlsHandleMixerAttachResponse(apiHandle, ¤tCtlHalData->ctlHalSpecificData->ctlHalStreamsData, toReturnJ); + err = HalCtlsHandleMixerAttachResponse(apiHandle, currentCtlHalData->ctlHalSpecificData, toReturnJ); if(err != (int) MIXER_NO_ERROR) { AFB_ApiError(apiHandle, "%s: Seems that %s call to api %s succeed but this warning was risen by response decoder : %i '%s'", @@ -180,7 +253,7 @@ int HalCtlsAttachToMixer(AFB_ApiT apiHandle) apiToCall, err, json_object_get_string(toReturnJ)); - return -7; + return -8; } AFB_ApiNotice(apiHandle, @@ -199,6 +272,63 @@ int HalCtlsAttachToMixer(AFB_ApiT apiHandle) MIXER_ATTACH_VERB, apiToCall, json_object_get_string(returnJ)); + return -9; + } + + return 0; +} + +int HalCtlsGetInfoFromMixer(AFB_ApiT apiHandle, char *apiToCall, json_object *requestJson, json_object **toReturnJ) +{ + char *returnedStatus = NULL, *returnedInfo = NULL; + + enum CallError returnedError; + + json_object *returnJ, *responseJ; + + if(! apiHandle) { + AFB_ApiError(apiHandle, "%s: Can't get current hal api handle", __func__); + return -1; + } + + if(! apiToCall) { + AFB_ApiError(apiHandle, "Can't get mixer api"); + return -2; + } + + if(! requestJson) { + AFB_ApiError(apiHandle, "Can't get request json"); + return -3; + } + + if(AFB_ServiceSync(apiHandle, apiToCall, MIXER_INFO_VERB, json_object_get(requestJson), &returnJ)) { + returnedError = HalUtlHandleAppFwCallError(apiHandle, apiToCall, MIXER_INFO_VERB, returnJ, &returnedStatus, &returnedInfo); + AFB_ApiError(apiHandle, + "Error %i during call to verb %s of %s api with status '%s' and info '%s'", + (int) returnedError, + apiToCall, + MIXER_INFO_VERB, + returnedStatus ? returnedStatus : "not returned", + returnedInfo ? returnedInfo : "not returned"); + return -4; + } + else if(json_object_object_get_ex(returnJ, "response", &responseJ)) { + AFB_ApiNotice(apiHandle, + "%s: Seems that %s call to api %s succeed with no warning raised : '%s'", + __func__, + MIXER_INFO_VERB, + apiToCall, + json_object_get_string(responseJ)); + + *toReturnJ = responseJ; + } + else { + AFB_ApiError(apiHandle, + "%s: Seems that %s call to api %s succeed, but response is not valid : '%s'", + __func__, + MIXER_INFO_VERB, + apiToCall, + json_object_get_string(returnJ)); return -8; } -- cgit 1.2.3-korg