diff options
Diffstat (limited to '4a-hal-utilities/4a-hal-utilities-hal-streams-handler.c')
-rw-r--r-- | 4a-hal-utilities/4a-hal-utilities-hal-streams-handler.c | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.c b/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.c new file mode 100644 index 0000000..4dbe35c --- /dev/null +++ b/4a-hal-utilities/4a-hal-utilities-hal-streams-handler.c @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2019 "IoT.bzh" + * Author Jonathan Aillet <jonathan.aillet@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. + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <json-c/json.h> + +#include <afb-definitions.h> + +#include <ctl-config.h> + +#include "4a-hal-utilities-data.h" +#include "4a-hal-utilities-appfw-responses-handler.h" +#include "4a-hal-utilities-hal-streams-handler.h" + +/******************************************************************************* + * Actions to be call when a stream verb is called * + ******************************************************************************/ + +void HalUtlActionOnMixer(AFB_ReqT request, enum ActionOnMixerType actionType) +{ + int idx, count; + + char *apiToCall; + + AFB_ApiT apiHandle; + CtlConfigT *ctrlConfig; + + struct SpecificHalData *currentCtlHalData; + struct CtlHalMixerData *currentMixerData = NULL; + + json_object *requestJson, *returnJ = NULL, *responseJ, *toReturnJ = NULL; + + apiHandle = (AFB_ApiT) AFB_ReqGetApi(request); + if(! apiHandle) { + AFB_ReqFail(request, "api_handle", "Can't get current hal controller api handle"); + return; + } + + ctrlConfig = (CtlConfigT *) AFB_ApiGetUserData(apiHandle); + if(! ctrlConfig) { + AFB_ReqFail(request, "hal_controller_config", "Can't get current hal controller config"); + return; + } + + currentCtlHalData = (struct SpecificHalData *) getExternalData(ctrlConfig); + if(! currentCtlHalData) { + AFB_ReqFail(request, "hal_controller_data", "Can't get current hal controller data"); + return; + } + + requestJson = AFB_ReqJson(request); + if(! requestJson) { + AFB_ReqFail(request, "request_json", "Can't get request json"); + return; + } + + if(json_object_is_type(requestJson, json_type_object) && json_object_get_object(requestJson)->count > 0) + json_object_object_add(requestJson, "verbose", json_object_new_boolean(1)); + + apiToCall = currentCtlHalData->ctlHalSpecificData->mixerApiName; + if(! apiToCall) { + AFB_ReqFail(request, "mixer_api", "Can't get mixer api"); + return; + } + + if(currentCtlHalData->status != HAL_STATUS_READY) { + AFB_ReqFail(request, "hal_not_ready", "Seems that hal is not ready"); + return; + } + + if(! (currentMixerData = (struct CtlHalMixerData *) AFB_ReqVCBData(request))) { + AFB_ReqFail(request, "hal_call_data", "Can't get current call data"); + return; + } + + switch(actionType) { + case ACTION_ON_MIXER_STREAM: + count = 1; + break; + + case ACTION_ON_MIXER_PLAYBACK: + case ACTION_ON_MIXER_CAPTURE: + case ACTION_ON_MIXER_ALL_STREAM: + count = (int) HalUtlGetNumberOfMixerDataInList(¤tMixerData); + toReturnJ = json_object_new_object(); + break; + + default: + AFB_ReqFail(request, "hal_call_data", "Can't get current call data"); + return; + } + + for(idx = 0; idx < count; idx++) { + if(AFB_ServiceSync(apiHandle, + apiToCall, + currentMixerData->verbToCall, + json_object_get(requestJson), + &returnJ)) { + HalUtlHandleAppFwCallErrorInRequest(request, apiToCall, currentMixerData->verbToCall, returnJ, "call_action"); + json_object_put(returnJ); + if(toReturnJ) + json_object_put(toReturnJ); + return; + } + + if(wrap_json_unpack(returnJ, "{s:o}", "response", &responseJ)) { + AFB_ReqFailF(request, + "Seems that %s call to api %s succeed, but no response was found in : '%s'", + currentMixerData->verbToCall, + apiToCall, + json_object_get_string(returnJ)); + json_object_put(returnJ); + if(toReturnJ) + json_object_put(toReturnJ); + return; + } + + // TBD JAI : When mixer events will be available, use them instead of generating events at calls + if((actionType == ACTION_ON_MIXER_STREAM || + actionType == ACTION_ON_MIXER_ALL_STREAM) && + ((! currentMixerData->event) || + (AFB_EventPush(currentMixerData->event, json_object_get(responseJ)) < 0))) { + AFB_ApiError(apiHandle, "Couldn't generate an event for stream %s", currentMixerData->verb); + } + + switch(actionType) { + case ACTION_ON_MIXER_STREAM: + toReturnJ = json_object_get(responseJ); + break; + + case ACTION_ON_MIXER_PLAYBACK: + case ACTION_ON_MIXER_CAPTURE: + json_object_object_add(toReturnJ, currentMixerData->verbToCall, json_object_get(responseJ)); + break; + + case ACTION_ON_MIXER_ALL_STREAM: + json_object_object_add(toReturnJ, currentMixerData->verb, json_object_get(responseJ)); + break; + + default: + break; + } + + json_object_put(returnJ); + + switch(actionType) { + case ACTION_ON_MIXER_PLAYBACK: + case ACTION_ON_MIXER_CAPTURE: + case ACTION_ON_MIXER_ALL_STREAM: + currentMixerData = currentMixerData->next; + break; + + default: + break; + } + } + + switch(actionType) { + case ACTION_ON_MIXER_STREAM: + AFB_ReqSuccessF(request, + toReturnJ, + "Action %s correctly transferred to %s without any error raised", + currentMixerData->verbToCall, + apiToCall); + break; + + case ACTION_ON_MIXER_PLAYBACK: + AFB_ReqSuccess(request, + toReturnJ, + "Actions correctly transferred to all playbacks without any error raised"); + break; + + case ACTION_ON_MIXER_CAPTURE: + AFB_ReqSuccess(request, + toReturnJ, + "Actions correctly transferred to all captures without any error raised"); + break; + + case ACTION_ON_MIXER_ALL_STREAM: + AFB_ReqSuccess(request, + toReturnJ, + "Actions correctly transferred to all streams without any error raised"); + break; + + default: + break; + } +} + +void HalUtlActionOnStream(AFB_ReqT request) +{ + HalUtlActionOnMixer(request, ACTION_ON_MIXER_STREAM); +} + +void HalUtlActionOnPlayback(AFB_ReqT request) +{ + HalUtlActionOnMixer(request, ACTION_ON_MIXER_PLAYBACK); +} + +void HalUtlActionOnCapture(AFB_ReqT request) +{ + HalUtlActionOnMixer(request, ACTION_ON_MIXER_CAPTURE); +} + +void HalUtlActionOnAllStream(AFB_ReqT request) +{ + HalUtlActionOnMixer(request, ACTION_ON_MIXER_ALL_STREAM); +} + +/******************************************************************************* + * Add stream data and verb function * + ******************************************************************************/ + +struct CtlHalMixerData *HalUtlAddStreamDataAndCreateStreamVerb(AFB_ApiT apiHandle, + char *verb, + char *verbToCall, + char *streamCardId) +{ + CtlConfigT *ctrlConfig; + + struct SpecificHalData *currentSpecificHalData; + struct CtlHalMixerData *createdStreamData; + + if(! apiHandle || ! verb || ! verbToCall || ! streamCardId) + return NULL; + + if((! (ctrlConfig = (CtlConfigT *) AFB_ApiGetUserData(apiHandle))) || + (! (currentSpecificHalData = (struct SpecificHalData *) getExternalData(ctrlConfig))) || + (! currentSpecificHalData->ctlHalSpecificData)) + return NULL; + + if(! (createdStreamData = HalUtlAddMixerDataToMixerDataList(¤tSpecificHalData->ctlHalSpecificData->ctlHalStreamsData))) + return NULL; + + createdStreamData->verb = strdup(verb); + createdStreamData->verbToCall = strdup(verbToCall); + createdStreamData->streamCardId = strdup(streamCardId); + + if((! createdStreamData->verb) || + (! createdStreamData->verbToCall) || + (! createdStreamData->streamCardId)) { + HalUtlRemoveSelectedMixerData(¤tSpecificHalData->ctlHalSpecificData->ctlHalStreamsData, createdStreamData); + return NULL; + } + + createdStreamData->event = AFB_EventMake(apiHandle, createdStreamData->verb); + if(! AFB_EventIsValid(createdStreamData->event)) { + HalUtlRemoveSelectedMixerData(¤tSpecificHalData->ctlHalSpecificData->ctlHalStreamsData, createdStreamData); + return NULL; + } + + if(AFB_ApiAddVerb(apiHandle, + createdStreamData->verb, + "Stream action transferred to mixer", + HalUtlActionOnStream, + (void *) createdStreamData, + NULL, + 0, + 0)) { + AFB_ApiError(apiHandle,"Error while creating verb for stream : '%s'", createdStreamData->verb); + HalUtlRemoveSelectedMixerData(¤tSpecificHalData->ctlHalSpecificData->ctlHalStreamsData, createdStreamData); + return NULL; + } + + return createdStreamData; +} + +int8_t HalUtlRemoveStreamDataAndDeleteStreamVerb(AFB_ApiT apiHandle, + char *verb, + char *verbToCall, + char *streamCardId) +{ + int8_t returnedErr = 0; + + CtlConfigT *ctrlConfig; + + struct SpecificHalData *currentSpecificHalData; + struct CtlHalMixerData *toRemoveStreamData; + + if(! apiHandle || ! verb || ! verbToCall || ! streamCardId) + return -1; + + if((! (ctrlConfig = (CtlConfigT *) AFB_ApiGetUserData(apiHandle))) || + (! (currentSpecificHalData = (struct SpecificHalData *) getExternalData(ctrlConfig))) || + (! currentSpecificHalData->ctlHalSpecificData)) + return -2; + + if(! (toRemoveStreamData = HalUtlSearchMixerDataByProperties(¤tSpecificHalData->ctlHalSpecificData->ctlHalStreamsData, + verb, + verbToCall, + streamCardId))) + return -3; + + if(afb_api_del_verb(apiHandle, verb, NULL)) { + AFB_ApiError(apiHandle,"Error while deleting verb for stream : '%s'", verb); + return -4; + } + + if((returnedErr = HalUtlRemoveSelectedMixerData(¤tSpecificHalData->ctlHalSpecificData->ctlHalStreamsData, toRemoveStreamData))) { + AFB_ApiError(apiHandle,"Error %i while removing data for stream : '%s'", returnedErr, verb); + return -5; + } + + return 0; +}
\ No newline at end of file |