aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Aillet <jonathan.aillet@iot.bzh>2018-06-11 01:45:57 +0200
committerJonathan Aillet <jonathan.aillet@iot.bzh>2018-10-08 15:52:51 +0200
commit757c9b407938b65b1e31ccc62217910d4f942dcb (patch)
treee64b7259dcd1ac8cc3f5b00b16e4dd2294495af1
parent611de9da40615bc5092eca407e399db3f3a2eaa6 (diff)
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 <jonathan.aillet@iot.bzh>
-rw-r--r--4a-hal-cfg-community/hal-4a-csl-cm106-8ch-usb.json255
-rw-r--r--4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c139
-rw-r--r--4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h2
-rw-r--r--4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.c266
-rw-r--r--4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-handler.h25
-rw-r--r--4a-hal/4a-hal-utilities/4a-hal-utilities-data.c3
-rw-r--r--4a-hal/4a-hal-utilities/4a-hal-utilities-data.h7
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", &currentHalData->ctlHalSpecificData->mixerApiName))
return -5;
- if(wrap_json_unpack(MixerJ, "{s:s}", "uid", &currentHalData->ctlHalSpecificData->mixerVerbName))
- return -6;
+ wrap_json_unpack(MixerJ, "{s?:s}", "prefix", &currentHalData->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(&currentMixerData,
+ "{s:s s:s}",
+ "name", currentMixerDataT->data[idx].verb,
+ "cardId", currentMixerDataT->data[idx].streamCardId);
+ }
+ else {
+ wrap_json_pack(&currentMixerData,
+ "{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, &currentCtlHalData->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(&currentStream,
- "{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, &currentCtlHalData->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, &currentCtlHalData->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 <string.h>
#include <stdbool.h>
+#include <wrap-json.h>
+
#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", &currentStreamName)) {
- 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", &currentDataVerbName)) {
+ 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", &currentStreamCardId)) {
- 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", &currentStreamCardId)) {
+ 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(&currentDataVerbName[verbStart]);
+
+ if(afb_dynapi_add_verb(apiHandle,
+ currentMixerDataT->data[idx].verb,
+ "Stream action transferred to mixer",
+ HalCtlsActionOnCall,
+ (void *) &currentMixerDataT->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, &currentHalSpecificData->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, &currentHalSpecificData->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, &currentHalSpecificData->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, &currentCtlHalData->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;