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-cfg-community/hal-4a-csl-cm106-8ch-usb.json | 255 +++++++++++++------- 4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c | 139 +++++++---- 4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h | 2 +- .../4a-hal-controllers-mixer-handler.c | 266 +++++++++++++++------ .../4a-hal-controllers-mixer-handler.h | 25 +- 4a-hal/4a-hal-utilities/4a-hal-utilities-data.c | 3 +- 4a-hal/4a-hal-utilities/4a-hal-utilities-data.h | 7 +- 7 files changed, 483 insertions(+), 214 deletions(-) diff --git a/4a-hal-cfg-community/hal-4a-csl-cm106-8ch-usb.json b/4a-hal-cfg-community/hal-4a-csl-cm106-8ch-usb.json index 95274eb..dde69d6 100644 --- a/4a-hal-cfg-community/hal-4a-csl-cm106-8ch-usb.json +++ b/4a-hal-cfg-community/hal-4a-csl-cm106-8ch-usb.json @@ -4,7 +4,7 @@ "uid": "/dev/snd/by-id/usb-0d8c_USB_Sound_Device-00", "version": "0.9", "api": "4a-hal-csl-cm106-8ch-usb", - "require": [ "alsacore", "softmixer" ], + "require": [ "alsacore", "smixer" ], "info": "4a hal for Jon's CSL CM106 8ch USB device", "author": "Jonathan Aillet", "date": "2018-06-09" @@ -64,91 +64,111 @@ ], "halmixer": { "uid": "csl-cm106-8ch-usb", - "mixerapi": "softmixer", - "backend": { + "mixerapi": "smixer", + "prefix": "cm106", + "ramps": [ + { + "uid": "ramp-fast", + "delay": 50, + "up": 10, + "down": 3 + }, + { + "uid": "ramp-slow", + "delay": 250, + "up": 3, + "down": 1 + }, + { + "uid": "ramp-normal", + "delay": 100, + "up": 6, + "down": 2 + } + ], + "playbacks" : { "uid": "CSL-CM106-8CH-USB", - "devpath": "/dev/snd/by-id/usb-0d8c_USB_Sound_Device-00", - "sink": [ - { - "uid": "front-right", - "port": 0 - }, - { - "uid": "front-left", - "port": 1 - } - ] - }, - "frontend" : { - "uid": "Alsa-Loop", - "devpath": "/dev/snd/by-path/platform-snd_aloop.0", + "path": "/dev/snd/by-id/usb-0d8c_USB_Sound_Device-00", "params": { "rate": 48000 }, - "ramps": [ - { - "uid": "ramp-fast", - "delay": 50, - "up": 10, - "down": 3 - }, - { - "uid": "ramp-slow", - "delay": 250, - "up": 3, - "down": 1 + "sink": { + "controls": { + "volume": { + "name": "Speaker Playback Volume", + "value": 80 + }, + "mute": { + "name": "Speaker Playback Switch" + } }, - { - "uid": "ramp-normal", - "delay": 100, - "up": 6, - "down": 2 - } - ], - "devices": { - "playback": 0, - "capture": 1 + "channels": [ + { + "uid": "front-right", + "port": 0 + }, + { + "uid": "front-left", + "port": 1 + }, + { + "uid": "middle-right", + "port": 2 + }, + { + "uid": "middle-left", + "port": 3 + }, + { + "uid": "back-right", + "port": 4 + }, + { + "uid": "back-left", + "port": 5 + }, + { + "uid": "center-right", + "port": 6 + }, + { + "uid": "center-left", + "port": 7 + } + ] + } + }, + "captures": { + "uid": "CSL-CM106-8CH-USB", + "path": "/dev/snd/by-id/usb-0d8c_USB_Sound_Device-00", + "params": { + "rate": 48000 }, - "subdevs": [ - { - "subdev": 0, - "numid": 51 - }, - { - "subdev": 1, - "numid": 57 - }, - { - "subdev": 2, - "numid": 63 - }, - { - "subdev": 3, - "numid": 69 - }, - { - "subdev": 4, - "numid": 75 - }, - { - "subdev": 5, - "numid": 81 - }, - { - "subdev": 6, - "numid": 87 + "source": { + "controls": { + "volume": { + "name": "Capture Volume" + }, + "mute": { + "name": "Capture Switch" + } }, - { - "subdev": 7, - "numid": 93 - } - ] + "channels": [ + { + "uid": "mic-right", + "port": 0 + }, + { + "uid": "mic-left", + "port": 1 + } + ] + } }, "zones": [ { "uid": "full-stereo", - "type": "playback", - "mapping": [ + "sink": [ { "target": "front-right", "channel": 0 @@ -156,13 +176,28 @@ { "target": "front-left", "channel": 1 + }, + { + "target": "middle-right", + "channel": 0 + }, + { + "target": "middle-left", + "channel": 1 + }, + { + "target": "back-right", + "channel": 0 + }, + { + "target": "back-left", + "channel": 1 } ] }, { "uid": "front-seats", - "type": "playback", - "mapping": [ + "sink": [ { "target": "front-right", "channel": 0 @@ -172,29 +207,75 @@ "channel": 1 } ] + }, + { + "uid": "middle-seats", + "sink": [ + { + "target": "middle-right", + "channel": 0 + }, + { + "target": "middle-left", + "channel": 1 + } + ] + }, + { + "uid": "back-seats", + "sink": [ + { + "target": "back-right", + "channel": 0 + }, + { + "target": "back-left", + "channel": 1 + } + ] } ], "streams": [ { - "uid": "multimedia", + "uid": "stream-multimedia", + "verb": "multimedia", "zone": "full-stereo", - "ramp": "ramp-slow", "volume": 60, - "mute": false + "mute": false, + "params": { + "rate": 48000 + } }, { - "uid": "navigation", + "uid": "stream-navigation", + "verb": "navigation", "zone": "front-seats", - "ramp": "ramp-normal", "volume": 70, - "mute": false + "mute": false, + "params": { + "rate": 48000 + } }, { - "uid": "emergency", + "uid": "stream-emergency", + "verb": "emergency", "zone": "front-seats", - "ramp": "ramp-fast", - "volume": 80, - "mute": false + "volume": 60, + "mute": false, + "params": { + "rate": 48000 + } + }, + { + "uid": "stream-pulseaudio", + "verb": "legacy", + "zone": "back-seats", + "source": "loop-legacy", + "volume": 50, + "mute": false, + "params": { + "rate": 48000 + } } ] } 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 ded6118..bf676bb 100644 --- a/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c @@ -144,8 +144,7 @@ int HalCtlsHalMixerConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object if(wrap_json_unpack(MixerJ, "{s:s}", "mixerapi", ¤tHalData->ctlHalSpecificData->mixerApiName)) return -5; - if(wrap_json_unpack(MixerJ, "{s:s}", "uid", ¤tHalData->ctlHalSpecificData->mixerVerbName)) - return -6; + wrap_json_unpack(MixerJ, "{s?:s}", "prefix", ¤tHalData->ctlHalSpecificData->prefix); } return 0; @@ -379,18 +378,17 @@ int HalCtlsHalMapConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *A * HAL controllers verbs functions * ******************************************************************************/ -void HalCtlsActionOnStream(AFB_ReqT request) +void HalCtlsActionOnCall(AFB_ReqT request) { - int verbToCallSize; - - char *apiToCall, *mixerVerbName, *verbToCall; + char *apiToCall; AFB_ApiT apiHandle; CtlConfigT *ctrlConfig; struct SpecificHalData *currentCtlHalData; + struct CtlHalMixerData *currentMixerData; - json_object *requestJson, *returnJ, *toReturnJ; + json_object *requestJson, *returnJ; apiHandle = (AFB_ApiT) afb_request_get_dynapi(request); if(! apiHandle) { @@ -404,6 +402,12 @@ void HalCtlsActionOnStream(AFB_ReqT request) return; } + currentMixerData = (struct CtlHalMixerData *) afb_request_get_vcbdata(request); + if(! currentMixerData) { + AFB_ReqFail(request, "hal_call_data", "Can't get current call data"); + return; + } + currentCtlHalData = (struct SpecificHalData *) ctrlConfig->external; if(! currentCtlHalData) { AFB_ReqFail(request, "hal_controller_data", "Can't get current hal controller data"); @@ -422,54 +426,76 @@ void HalCtlsActionOnStream(AFB_ReqT request) return; } - mixerVerbName = currentCtlHalData->ctlHalSpecificData->mixerVerbName; - if(! mixerVerbName) { - AFB_ReqFail(request, "hal_softmixer_verb", "Can't get hal mixer verb prefix"); - return; - } - if(currentCtlHalData->status != HAL_STATUS_READY) { AFB_ReqFail(request, "hal_not_ready", "Seems that hal is not ready"); return; } - // TODO JAI : remove verb to call prefix, each hal should have its own api in softmixer, and each streams should be created as verb by mixer - verbToCallSize = (int) strlen(mixerVerbName) + (int) strlen(request->verb) + 2; - verbToCall = (char *) alloca(verbToCallSize * sizeof(char)); - verbToCall[0] = '\0'; - verbToCall[verbToCallSize - 1] = '\0'; + // TBD JAI : handle the case of there is multiple 'playbacks' or 'captures' entries (call them all) + + if(AFB_ServiceSync(apiHandle, apiToCall, currentMixerData->verbToCall, json_object_get(requestJson), &returnJ)) { + HalUtlHandleAppFwCallErrorInRequest(request, apiToCall, currentMixerData->verbToCall, returnJ, "call_action"); + } + + AFB_ReqSuccessF(request, + NULL, + "Action %s correctly transferred to %s without any error raised", + currentMixerData->verbToCall, + apiToCall); +} + +json_object *HalCtlsGetJsonArrayForMixerDataTable(AFB_ApiT apiHandle, struct CtlHalMixerDataT *currentMixerDataT, enum MixerDataType dataType) +{ + unsigned int idx; - strcat(verbToCall, mixerVerbName); - strcat(verbToCall, "/"); - strcat(verbToCall, request->verb); + json_object *mixerDataArray, *currentMixerData; - if(AFB_ServiceSync(apiHandle, apiToCall, verbToCall, json_object_get(requestJson), &returnJ)) { - HalUtlHandleAppFwCallErrorInRequest(request, apiToCall, verbToCall, returnJ, "stream_action"); + if(! apiHandle) { + AFB_ApiError(apiHandle, "Can't get current hal controller api handle"); + return NULL; } - else if(json_object_object_get_ex(returnJ, "response", &toReturnJ)){ - AFB_ReqSuccessF(request, - toReturnJ, - "Action %s correctly transferred to %s without any error raised", - verbToCall, - apiToCall); + + if(! currentMixerDataT) { + AFB_ApiError(apiHandle, "Can't get mixer data table to handle"); + return NULL; } - else { - AFB_ReqFailF(request, "invalid_response", "Action %s correctly transferred to %s, but response is not valid", - verbToCall, - apiToCall); + + mixerDataArray = json_object_new_array(); + if(! mixerDataArray) { + AFB_ApiError(apiHandle, "Can't generate json mixer data array"); + return NULL; } + + for(idx = 0; idx < currentMixerDataT->count; idx++) { + if(dataType == MIXER_DATA_STREAMS) { + wrap_json_pack(¤tMixerData, + "{s:s s:s}", + "name", currentMixerDataT->data[idx].verb, + "cardId", currentMixerDataT->data[idx].streamCardId); + } + else { + wrap_json_pack(¤tMixerData, + "{s:s s:s}", + "name", currentMixerDataT->data[idx].verb, + "mixer-name", currentMixerDataT->data[idx].verbToCall, + "uid", currentMixerDataT->data[idx].streamCardId ? currentMixerDataT->data[idx].streamCardId : "none"); + } + json_object_array_add(mixerDataArray, currentMixerData); + } + + return mixerDataArray; } void HalCtlsInfo(AFB_ReqT request) { - unsigned int idx; + char *apiToCall; AFB_ApiT apiHandle; CtlConfigT *ctrlConfig; struct SpecificHalData *currentCtlHalData; - json_object *requestJson, *requestAnswer, *streamsArray, *currentStream; + json_object *requestJson, *toReturnJ = NULL, *requestAnswer, *streamsArray, *playbacksArray, *capturesArray; apiHandle = (AFB_ApiT) afb_request_get_dynapi(request); if(! apiHandle) { @@ -489,34 +515,47 @@ void HalCtlsInfo(AFB_ReqT request) return; } - if(! currentCtlHalData->ctlHalSpecificData->ctlHalStreamsData.count) { - AFB_ReqSuccess(request, NULL, "No data to answer, no streams found"); + requestJson = AFB_ReqJson(request); + if(! requestJson) { + AFB_ReqFail(request, "info_data", "Can't get request json"); return; } - requestJson = AFB_ReqJson(request); - if(! requestJson) { - AFB_ReqFail(request, "request_json", "Can't get request json"); + if(json_object_is_type(requestJson, json_type_object)) { + apiToCall = currentCtlHalData->ctlHalSpecificData->mixerApiName; + if(! apiToCall) { + AFB_ReqFail(request, "mixer_api", "Can't get mixer api"); + return; + } + + if(HalCtlsGetInfoFromMixer(apiHandle, apiToCall, requestJson, &toReturnJ)) { + AFB_ReqFail(request, "mixer_info", "Call to mixer info verb didn't succeed"); + return; + } + + AFB_ReqSuccess(request, toReturnJ, "Mixer requested data"); return; } - streamsArray = json_object_new_array(); + streamsArray = HalCtlsGetJsonArrayForMixerDataTable(apiHandle, ¤tCtlHalData->ctlHalSpecificData->ctlHalStreamsData, MIXER_DATA_STREAMS); if(! streamsArray) { - AFB_ReqFail(request, "json_answer", "Can't generate par of json answer"); + AFB_ReqFail(request, "streams_data", "Didn't succeed to generate streams data array"); return; } - for(idx = 0; idx < currentCtlHalData->ctlHalSpecificData->ctlHalStreamsData.count; idx++) { - wrap_json_pack(¤tStream, - "{s:s s:s}", - "name", currentCtlHalData->ctlHalSpecificData->ctlHalStreamsData.data[idx].name, - "cardId", currentCtlHalData->ctlHalSpecificData->ctlHalStreamsData.data[idx].streamCardId); - json_object_array_add(streamsArray, currentStream); + playbacksArray = HalCtlsGetJsonArrayForMixerDataTable(apiHandle, ¤tCtlHalData->ctlHalSpecificData->ctlHalPlaybacksData, MIXER_DATA_PLAYBACKS); + if(! playbacksArray) { + AFB_ReqFail(request, "playbacks_data", "Didn't succeed to generate playbacks data array"); + return; } - // TODO JAI : Add playback and capture with their card id to the response + capturesArray = HalCtlsGetJsonArrayForMixerDataTable(apiHandle, ¤tCtlHalData->ctlHalSpecificData->ctlHalCapturesData, MIXER_DATA_CAPTURES); + if(! capturesArray) { + AFB_ReqFail(request, "captures_data", "Didn't succeed to generate captures data array"); + return; + } - wrap_json_pack(&requestAnswer, "{s:o}", "streams", streamsArray); + wrap_json_pack(&requestAnswer, "{s:o s:o s:o}", "streams", streamsArray, "playbacks", playbacksArray, "captures", capturesArray); AFB_ReqSuccess(request, requestAnswer, "Requested data"); } \ No newline at end of file diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h b/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h index 2db6186..cfb72b4 100644 --- a/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h @@ -32,7 +32,7 @@ int HalCtlsHalMixerConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object int HalCtlsHalMapConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *StreamControlsJ); // HAL controllers verbs functions -void HalCtlsActionOnStream(AFB_ReqT request); +void HalCtlsActionOnCall(AFB_ReqT request); void HalCtlsInfo(AFB_ReqT request); #endif /* _HALMGR_CB_INCLUDE_ */ \ No newline at end of file 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; } diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.h b/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.h index 74bca88..9218ed4 100644 --- a/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.h +++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.h @@ -26,19 +26,34 @@ #include "../4a-hal-utilities/4a-hal-utilities-data.h" -#define MIXER_ATTACH_VERB "create" +#define MIXER_ATTACH_VERB "attach" +#define MIXER_INFO_VERB "info" + +#define HAL_PLAYBACK_VERB "playback" +#define HAL_CAPTURE_VERB "capture" + +// Enum for the type of object sent back by the mixer +enum MixerDataType { + MIXER_DATA_STREAMS = 1, + MIXER_DATA_PLAYBACKS = 2, + MIXER_DATA_CAPTURES = 3 +}; // Enum for the type of error detected enum MixerStatus { MIXER_NO_ERROR=0, MIXER_ERROR_API_UNAVAILABLE=-1, - MIXER_ERROR_NO_STREAMS=-2, - MIXER_ERROR_STREAM_NAME_UNAVAILABLE=-10, - MIXER_ERROR_STREAM_CARDID_UNAVAILABLE=-1000, - MIXER_ERROR_COULDNT_ADD_STREAMS_AS_VERB =-100000, + MIXER_ERROR_DATA_UNAVAILABLE=-2, + MIXER_ERROR_DATA_EMPTY =-3, + MIXER_ERROR_DATA_NAME_UNAVAILABLE=-10, + MIXER_ERROR_DATA_CARDID_UNAVAILABLE=-1000, + MIXER_ERROR_STREAM_VERB_NOT_CREATED =-100000, + MIXER_ERROR_PLAYBACK_VERB_NOT_CREATED =-4, + MIXER_ERROR_CAPTURE_VERB_NOT_CREATED =-5 }; // HAL controllers handle mixer calls functions int HalCtlsAttachToMixer(AFB_ApiT apiHandle); +int HalCtlsGetInfoFromMixer(AFB_ApiT apiHandle, char *apiToCall, json_object *requestJson, json_object **toReturnJ); #endif /* _HAL_CTLS_SOFTMIXER_LINK_INCLUDE_ */ \ No newline at end of file diff --git a/4a-hal/4a-hal-utilities/4a-hal-utilities-data.c b/4a-hal/4a-hal-utilities/4a-hal-utilities-data.c index e8f54a2..aa4fabc 100644 --- a/4a-hal/4a-hal-utilities/4a-hal-utilities-data.c +++ b/4a-hal/4a-hal-utilities/4a-hal-utilities-data.c @@ -42,7 +42,8 @@ uint8_t HalUtlRemoveAllCtlHalStreamsData(struct CtlHalMixerDataT *ctlHalStreamsD return -2; for(cpt = 0; cpt < ctlHalStreamsData->count; cpt++) { - free(ctlHalStreamsData->data[cpt].name); + free(ctlHalStreamsData->data[cpt].verb); + free(ctlHalStreamsData->data[cpt].verbToCall); free(ctlHalStreamsData->data[cpt].streamCardId); } diff --git a/4a-hal/4a-hal-utilities/4a-hal-utilities-data.h b/4a-hal/4a-hal-utilities/4a-hal-utilities-data.h index 244546f..c33f90d 100644 --- a/4a-hal/4a-hal-utilities/4a-hal-utilities-data.h +++ b/4a-hal/4a-hal-utilities/4a-hal-utilities-data.h @@ -38,7 +38,8 @@ enum HalStatus { // Structure to store stream data struct CtlHalMixerData { - char *name; + char *verb; + char *verbToCall; char *streamCardId; }; @@ -51,10 +52,12 @@ struct CtlHalMixerDataT { // Structure to store specific controller hal data struct CtlHalSpecificData { char *mixerApiName; - char *mixerVerbName; + char *prefix; json_object *halMixerJ; struct CtlHalMixerDataT ctlHalStreamsData; + struct CtlHalMixerDataT ctlHalPlaybacksData; + struct CtlHalMixerDataT ctlHalCapturesData; struct CtlHalAlsaMapT *ctlHalAlsaMapT; AFB_ApiT apiHandle; -- cgit 1.2.3-korg