summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/4a-internals-hal/4a-internals-hal-cb.c1106
-rw-r--r--src/4a-internals-hal/4a-internals-hal-cb.h12
2 files changed, 559 insertions, 559 deletions
diff --git a/src/4a-internals-hal/4a-internals-hal-cb.c b/src/4a-internals-hal/4a-internals-hal-cb.c
index 0f32bfb..c5f19a2 100644
--- a/src/4a-internals-hal/4a-internals-hal-cb.c
+++ b/src/4a-internals-hal/4a-internals-hal-cb.c
@@ -141,559 +141,6 @@ void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json
}
/*******************************************************************************
- * Internals HAL - 'halmixer' section parsing/handling functions *
- ******************************************************************************/
-
-int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *MixerJ)
-{
- int err = 0, wrapRet;
-
- char *mixerApiName, *prefix = NULL;
-
- CtlConfigT *ctrlConfig;
- struct HalData *currentHalData;
-
- if(! apiHandle || ! section)
- return -1;
-
- ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
- if(! ctrlConfig)
- return -2;
-
- currentHalData = (struct HalData *) getExternalData(ctrlConfig);
- if(! currentHalData)
- return -3;
-
- if(MixerJ) {
- if(json_object_is_type(MixerJ, json_type_object))
- currentHalData->internalHalData->halMixerJ = MixerJ;
- else
- return -4;
-
- wrapRet = wrap_json_unpack(MixerJ, "{s:s s?:s}", "mixerapi", &mixerApiName, "prefix", &prefix);
- if(wrapRet)
- return -5;
-
- currentHalData->internalHalData->mixerApiName = strdup(mixerApiName);
- if(! currentHalData->internalHalData->mixerApiName)
- return -6;
-
- if(prefix) {
- currentHalData->internalHalData->prefix = strdup(prefix);
- if(! currentHalData->internalHalData->prefix)
- return -7;
- }
- }
- else if(currentHalData->status == HAL_STATUS_AVAILABLE) {
- err = InternalHalAttachToMixer(apiHandle);
- if(err) {
- AFB_API_ERROR(apiHandle, "Error %i while attaching to mixer", err);
- return -8;
- }
- }
-
- return 0;
-}
-
-/*******************************************************************************
- * Internals HAL - 'halmap' section parsing/handling functions *
- ******************************************************************************/
-
-int InternalHalProcessOneHalMapControl(afb_api_t apiHandle,
- struct InternalHalAlsaMap *halMapData,
- json_object *halMapControlJ)
-{
- char *uid, *info = NULL, *action = NULL, *name = NULL, *typename = NULL;
-
- json_object *alsaJ = NULL, *createAlsaCtlJ = NULL;
-
- if(! apiHandle || ! halMapData || ! halMapControlJ) {
- AFB_API_ERROR(apiHandle, "Invalid argument(s)");
- return -1;
- }
-
- if(wrap_json_unpack(halMapControlJ,
- "{s:s s?:s s:o s?:s !}",
- "uid", &uid,
- "info", &info,
- "alsa", &alsaJ,
- "action", &action)) {
- AFB_API_ERROR(apiHandle,
- "Parsing error, control json should only contains "
- "[uid]|[info]|[alsa] in : '%s'",
- json_object_get_string(halMapControlJ));
- return -2;
- }
-
- halMapData->uid = strdup(uid);
- if(! halMapData->uid) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'uid' string");
- return -3;
- }
-
- if(info) {
- halMapData->info = strdup(info);
- if(! halMapData->info) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'info' string");
- return -4;
- }
- }
-
- if(wrap_json_unpack(alsaJ,
- "{s?:s s?:i s?:i s?:o !}",
- "name", &name,
- "numid", &halMapData->ctl.numid,
- "value", &halMapData->ctl.value,
- "create", &createAlsaCtlJ)) {
- AFB_API_ERROR(apiHandle,
- "Parsing error, alsa json should only contains "
- "[name]|[numid]||[value]|[create] in : '%s'",
- json_object_get_string(alsaJ));
- return -5;
- }
-
- if(name) {
- halMapData->ctl.name = strdup(name);
- if(! halMapData->ctl.name) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'info' string");
- return -6;
- }
- }
-
- if(createAlsaCtlJ) {
- halMapData->ctl.alsaCtlCreation = calloc(1, sizeof(struct InternalHalAlsaCtlProperties));
- if(! halMapData->ctl.alsaCtlCreation) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to allocate alsa properties data structure for control to create");
- return -7;
- }
-
- if(wrap_json_unpack(createAlsaCtlJ,
- "{s:s s:i s:i s:i s:i !}",
- "type", &typename,
- "count", &halMapData->ctl.alsaCtlCreation->count,
- "minval", &halMapData->ctl.alsaCtlCreation->minval,
- "maxval", &halMapData->ctl.alsaCtlCreation->maxval,
- "step", &halMapData->ctl.alsaCtlCreation->step)) {
- AFB_API_ERROR(apiHandle,
- "Parsing error, alsa creation json should only contains "
- "[type]|[count]|[minval]|[maxval]|[step] in : '%s'",
- json_object_get_string(alsaJ));
- return -8;
- }
-
- if(typename) {
- halMapData->ctl.alsaCtlCreation->type = InternalHalMapsAlsaTypeToEnum(typename);
- if(halMapData->ctl.alsaCtlCreation->type == SND_CTL_ELEM_TYPE_NONE) {
- AFB_API_ERROR(apiHandle,
- "Couldn't get alsa type from string %s in : '%s'",
- typename,
- json_object_get_string(alsaJ));
- return -9;
- }
- }
-
- if(! halMapData->ctl.name)
- halMapData->ctl.name = halMapData->uid;
- }
- else if(halMapData->ctl.name && halMapData->ctl.numid > 0) {
- AFB_API_ERROR(apiHandle,
- "Can't have both a control name (%s) and a control uid (%i) in alsa object : '%s'",
- halMapData->ctl.name,
- halMapData->ctl.numid,
- json_object_get_string(alsaJ));
- return -10;
- }
- else if(! halMapData->ctl.name && halMapData->ctl.numid <= 0) {
- AFB_API_ERROR(apiHandle,
- "Need at least a control name or a control uid in alsa object : '%s'",
- json_object_get_string(alsaJ));
- return -11;
- }
-
- if(action)
- halMapData->actionJ = json_object_get(halMapControlJ);
-
- return 0;
-}
-
-int InternalHalProcessOneHalMapObject(afb_api_t apiHandle,
- json_object *halMapForTargetJ,
- struct cds_list_head *halMapListHead,
- struct cds_list_head *halDevicesToProbeListHead)
-{
- int idx, controlsCount, err = 0, halMapControlsJsonIsAnArray = 0;
-
- char *uid, *info = NULL, *target;
-
- struct InternalHalAlsaMap *currentHalMapData;
-
- json_object *controlsJ, *currentHalMapControlJ;
- json_type halMapControlsType;
-
- AFB_API_DEBUG(apiHandle, "halMapForTargetJ='%s'", json_object_get_string(halMapForTargetJ));
-
- if(wrap_json_unpack(halMapForTargetJ,
- "{s:s s?:s s:s s:o !}",
- "uid", &uid,
- "info", &info,
- "target", &target,
- "controls", &controlsJ)) {
- AFB_API_ERROR(apiHandle,
- "Parsing error, map should only contains "
- "[uid]|[info]|[target]|[controls] in : '%s'",
- json_object_get_string(halMapForTargetJ));
- return -1;
- }
-
- if(! HalUtlSearchProbedDeviceDataById(halDevicesToProbeListHead, target)) {
- AFB_API_ERROR(apiHandle,
- "Content of 'halmap' section is not valid because targeted dependency ('%s') is not present "
- "in 'haldependencies' section, json configuration file correction is needed",
- target);
- return -2;
- }
-
- halMapControlsType = json_object_get_type(controlsJ);
- switch(halMapControlsType) {
- case json_type_array:
- controlsCount = (int) json_object_array_length(controlsJ);
- halMapControlsJsonIsAnArray = 1;
- break;
-
- case json_type_object:
- controlsCount = 1;
- break;
-
- default:
- AFB_API_ERROR(apiHandle,
- "Content of 'halmap' controls section is not valid ('%s')",
- json_object_get_string(controlsJ));
- return -3;
- }
-
- for(idx = 0; idx < controlsCount; idx++) {
- currentHalMapControlJ = halMapControlsJsonIsAnArray ? json_object_array_get_idx(controlsJ, idx) : controlsJ;
-
- currentHalMapData = HalUtlAddHalMapDataToHalMapDataList(halMapListHead);
-
- currentHalMapData->targetUid = strdup(uid);
- if(! currentHalMapData->targetUid) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetUid' string");
- return -4;
- }
-
- if(info) {
- currentHalMapData->targetInfo = strdup(info);
- if(! currentHalMapData->targetInfo) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetInfo' string");
- return -5;
- }
- }
-
- currentHalMapData->targetedDependency = strdup(target);
- if(! currentHalMapData->targetedDependency) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetedDependency' string");
- return -6;
- }
-
- err = InternalHalProcessOneHalMapControl(apiHandle,
- currentHalMapData,
- currentHalMapControlJ);
- if(err) {
- AFB_API_ERROR(apiHandle,
- "Error %i was returned when tried to proccess halmap control %i ('%s')",
- err,
- idx,
- json_object_get_string(currentHalMapControlJ));
- HalUtlRemoveSelectedHalMapData(halMapListHead, currentHalMapData);
- return -7;
- }
- }
-
- return 0;
-}
-
-int InternalHalProcessAllHalMap(afb_api_t apiHandle,
- json_object *halMapJ,
- struct cds_list_head *halMapListHead,
- struct cds_list_head *halDevicesToProbeListHead)
-{
- int idx, targetCount, err = 0, halMapJsonIsAnArray = 0;
-
- json_object *currentHalMapTargetJ;
- json_type alsaMapType;
-
- AFB_API_DEBUG(apiHandle, "halMapJ='%s'", json_object_get_string(halMapJ));
-
- alsaMapType = json_object_get_type(halMapJ);
- switch(alsaMapType) {
- case json_type_array:
- targetCount = (int) json_object_array_length(halMapJ);
- halMapJsonIsAnArray = 1;
- break;
-
- case json_type_object:
- targetCount = 1;
- break;
-
- default:
- AFB_API_ERROR(apiHandle,
- "Content of 'halmap' section is not valid ('%s')",
- json_object_get_string(halMapJ));
- return -1;
- }
-
- for(idx = 0; idx < targetCount; idx++) {
- currentHalMapTargetJ = halMapJsonIsAnArray ? json_object_array_get_idx(halMapJ, idx) : halMapJ;
-
- err = InternalHalProcessOneHalMapObject(apiHandle,
- currentHalMapTargetJ,
- halMapListHead,
- halDevicesToProbeListHead);
- if(err) {
- AFB_API_ERROR(apiHandle,
- "Error %i was returned when tried to proccess halmap target %i ('%s')",
- err,
- idx,
- json_object_get_string(currentHalMapTargetJ));
- HalUtlRemoveAllHalMapData(halMapListHead);
- return -2;
- }
- }
-
- return 0;
-}
-
-int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, struct InternalHalAlsaMap *halMapData)
-{
- int err;
-
- char cardNbString[6];
-
- json_object *valueJ, *convertedValueJ = NULL;
-
- CtlActionT *toLoadAction;
-
- halMapData->alsaControlEvent = afb_api_make_event(apiHandle, halMapData->uid);
- if(! halMapData->alsaControlEvent) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to create event for alsa control with uid %s",
- halMapData->uid);
- return -1;
- }
-
- snprintf(cardNbString, sizeof(cardNbString), "hw:%i", halMapData->cardNb);
-
- if(halMapData->ctl.alsaCtlCreation) {
- if(InternalHalCreateAlsaCtl(apiHandle, cardNbString, &halMapData->ctl)) {
- AFB_API_ERROR(apiHandle, "An error happened when trying to create a new alsa control");
- return -2;
- }
- halMapData->ctl.alsaCtlProperties = halMapData->ctl.alsaCtlCreation;
- }
- else {
- halMapData->ctl.alsaCtlProperties = calloc(1, sizeof(struct InternalHalAlsaCtlProperties));
- if(! halMapData->ctl.alsaCtlProperties) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to allocate alsa properties data structure for control");
- return -3;
- }
-
- if(InternalHalUpdateAlsaCtlProperties(apiHandle, cardNbString, &halMapData->ctl)) {
- AFB_API_ERROR(apiHandle, "An error happened when trying to get existing alsa control info");
- free(halMapData->ctl.alsaCtlProperties);
- halMapData->ctl.alsaCtlProperties = NULL;
- return -4;
- }
- }
-
- if(halMapData->actionJ) {
- toLoadAction = malloc(sizeof(CtlActionT));
- if(! toLoadAction) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to allocate structure used to store action to perform "
- "when the corresponding ALSA control is detected");
- return -5;
- }
-
- if(ActionLoadOne(apiHandle, toLoadAction, halMapData->actionJ, 0)) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to load action using alsa object : '%s'",
- json_object_get_string(halMapData->actionJ));
- free(toLoadAction);
- return -6;
- }
-
- halMapData->action = toLoadAction;
- }
-
- if(InternalHalSubscribeToAlsaCardEvent(apiHandle, cardNbString)) {
- AFB_API_ERROR(apiHandle, "Error when trying to subscribe to alsacore event for audio card '%s'", cardNbString);
- return -7;
- }
-
- if(halMapData->ctl.value) {
- // TBD JAI : handle alsa controls type
- valueJ = json_object_new_int(halMapData->ctl.value);
- if(! valueJ) {
- AFB_API_ERROR(apiHandle, "Didn't succeed to allocate ALSA control value json string");
- return -8;
- }
-
- err = 0;
-
- if(InternalHalConvertJsonValues(apiHandle,
- halMapData->ctl.alsaCtlProperties,
- valueJ,
- &convertedValueJ,
- CONVERSION_NORMALIZED_TO_ALSACORE)) {
- AFB_API_ERROR(apiHandle, "Error when trying to convert initiate value json '%s'", json_object_get_string(valueJ));
- err = -9;
- }
- else if(InternalHalSetAlsaCtlValue(apiHandle, cardNbString, halMapData->ctl.numid, convertedValueJ)) {
- AFB_API_ERROR(apiHandle,
- "Error while trying to set initial value on alsa control %i, device '%s', value '%s'",
- halMapData->ctl.numid,
- cardNbString,
- json_object_get_string(valueJ));
- err = -10;
- }
-
- json_object_put(valueJ);
-
- if(convertedValueJ)
- json_object_put(convertedValueJ);
-
- if(err)
- return err;
- }
-
- if(afb_api_add_verb(apiHandle, halMapData->uid, NULL, InternalHalActionOnAlsaCtl, (void *) halMapData, NULL, 0, 0)) {
- AFB_API_ERROR(apiHandle,
- "Didn't succeed to create verb %s for alsa control named %s on card %i",
- halMapData->uid,
- halMapData->ctl.name ? halMapData->ctl.name : "'N/A'",
- halMapData->cardNb);
- return -11;
- }
-
- return 0;
-}
-
-int InternalHalHandleSelectedHalMapWithValidatedDependency(afb_api_t apiHandle,
- struct cds_list_head *halMapListHead,
- struct cds_list_head *halDevicesToProbeListHead,
- char *targetedDependency,
- enum DependenciesHandlingType halMapHandlingType)
-{
- int err = 0, validatedHalMap;
-
- struct InternalHalAlsaMap *currentHalMapData;
-
- if(cds_list_empty(halMapListHead)) {
- AFB_API_ERROR(apiHandle, "HalMap list is empty, nothing to handle");
- return 0;
- }
-
- if(halMapHandlingType == UID_CORRESPONDING_DEPENDENCIES &&
- ! targetedDependency) {
- AFB_API_ERROR(apiHandle, "Invalid targeted dependency");
- return -1;
- }
-
- cds_list_for_each_entry(currentHalMapData, halMapListHead, node) {
- validatedHalMap = 0;
- switch(halMapHandlingType) {
- case ALL_DEPENDENCIES:
- validatedHalMap = 1;
- break;
-
- case UID_CORRESPONDING_DEPENDENCIES:
- if(! strcmp(targetedDependency, currentHalMapData->targetedDependency))
- validatedHalMap = 1;
- break;
-
- default:
- AFB_API_ERROR(apiHandle, "Invalid dependencies enum type");
- return -2;
- }
-
- if(validatedHalMap) {
- currentHalMapData->cardNb = HalUtlGetProbedDeviceCardNbUsingUid(halDevicesToProbeListHead,
- currentHalMapData->targetedDependency);
- if(currentHalMapData->cardNb == HAL_UNKNOWN_DEVICE) {
- AFB_API_WARNING(apiHandle,
- "Current halmap control %s can't be handled because corresponding "
- "dependency ('%s') card is not available at the moment",
- currentHalMapData->uid,
- currentHalMapData->targetedDependency);
- continue;
- }
-
- err = InternalHalHandleOneHalMapObject(apiHandle, currentHalMapData);
- if(err) {
- AFB_API_ERROR(apiHandle,
- "Error %i was returned when tried to handle halmap control with uid %s",
- err,
- currentHalMapData->uid);
- return -3;
- }
- }
- }
-
- return 0;
-}
-
-int InternalHalHandleAllHalMapWithValidatedDependency(afb_api_t apiHandle,
- struct cds_list_head *halMapListHead,
- struct cds_list_head *halDevicesToProbeListHead)
-{
- return InternalHalHandleSelectedHalMapWithValidatedDependency(apiHandle,
- halMapListHead,
- halDevicesToProbeListHead,
- NULL,
- ALL_DEPENDENCIES);
-}
-
-int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *AlsaMapJ)
-{
- CtlConfigT *ctrlConfig;
- struct HalData *currentHalData;
-
- ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
- if(! ctrlConfig)
- return -1;
-
- currentHalData = (struct HalData *) getExternalData(ctrlConfig);
- if(! currentHalData)
- return -2;
-
- if(AlsaMapJ) {
- if(InternalHalProcessAllHalMap(apiHandle,
- AlsaMapJ,
- &currentHalData->internalHalData->halMapListHead,
- &currentHalData->internalHalData->probedDevicesListHead)) {
- AFB_API_ERROR(apiHandle, "Failed to process 'halmap' section");
- HalUtlRemoveAllHalMapData(&currentHalData->internalHalData->halMapListHead);
- return -4;
- }
- }
- else if(cds_list_empty(&currentHalData->internalHalData->halMapListHead)) {
- AFB_API_WARNING(apiHandle, "No alsa controls defined in 'halmap' section");
- return 1;
- }
- else if(InternalHalHandleAllHalMapWithValidatedDependency(apiHandle,
- &currentHalData->internalHalData->halMapListHead,
- &currentHalData->internalHalData->probedDevicesListHead)) {
- AFB_API_ERROR(apiHandle, "Failed to handle 'halmap' section");
- return -5;
- }
-
- return 0;
-}
-
-/*******************************************************************************
* Internals HAL - 'haldependencies' section parsing/handling functions *
******************************************************************************/
@@ -1267,6 +714,559 @@ int InternalHalHalDependenciesConfig(afb_api_t apiHandle, CtlSectionT *section,
}
/*******************************************************************************
+ * Internals HAL - 'halmixer' section parsing/handling functions *
+ ******************************************************************************/
+
+int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *MixerJ)
+{
+ int err = 0, wrapRet;
+
+ char *mixerApiName, *prefix = NULL;
+
+ CtlConfigT *ctrlConfig;
+ struct HalData *currentHalData;
+
+ if(! apiHandle || ! section)
+ return -1;
+
+ ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
+ if(! ctrlConfig)
+ return -2;
+
+ currentHalData = (struct HalData *) getExternalData(ctrlConfig);
+ if(! currentHalData)
+ return -3;
+
+ if(MixerJ) {
+ if(json_object_is_type(MixerJ, json_type_object))
+ currentHalData->internalHalData->halMixerJ = MixerJ;
+ else
+ return -4;
+
+ wrapRet = wrap_json_unpack(MixerJ, "{s:s s?:s}", "mixerapi", &mixerApiName, "prefix", &prefix);
+ if(wrapRet)
+ return -5;
+
+ currentHalData->internalHalData->mixerApiName = strdup(mixerApiName);
+ if(! currentHalData->internalHalData->mixerApiName)
+ return -6;
+
+ if(prefix) {
+ currentHalData->internalHalData->prefix = strdup(prefix);
+ if(! currentHalData->internalHalData->prefix)
+ return -7;
+ }
+ }
+ else if(currentHalData->status == HAL_STATUS_AVAILABLE) {
+ err = InternalHalAttachToMixer(apiHandle);
+ if(err) {
+ AFB_API_ERROR(apiHandle, "Error %i while attaching to mixer", err);
+ return -8;
+ }
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Internals HAL - 'halmap' section parsing/handling functions *
+ ******************************************************************************/
+
+int InternalHalProcessOneHalMapControl(afb_api_t apiHandle,
+ struct InternalHalAlsaMap *halMapData,
+ json_object *halMapControlJ)
+{
+ char *uid, *info = NULL, *action = NULL, *name = NULL, *typename = NULL;
+
+ json_object *alsaJ = NULL, *createAlsaCtlJ = NULL;
+
+ if(! apiHandle || ! halMapData || ! halMapControlJ) {
+ AFB_API_ERROR(apiHandle, "Invalid argument(s)");
+ return -1;
+ }
+
+ if(wrap_json_unpack(halMapControlJ,
+ "{s:s s?:s s:o s?:s !}",
+ "uid", &uid,
+ "info", &info,
+ "alsa", &alsaJ,
+ "action", &action)) {
+ AFB_API_ERROR(apiHandle,
+ "Parsing error, control json should only contains "
+ "[uid]|[info]|[alsa] in : '%s'",
+ json_object_get_string(halMapControlJ));
+ return -2;
+ }
+
+ halMapData->uid = strdup(uid);
+ if(! halMapData->uid) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'uid' string");
+ return -3;
+ }
+
+ if(info) {
+ halMapData->info = strdup(info);
+ if(! halMapData->info) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'info' string");
+ return -4;
+ }
+ }
+
+ if(wrap_json_unpack(alsaJ,
+ "{s?:s s?:i s?:i s?:o !}",
+ "name", &name,
+ "numid", &halMapData->ctl.numid,
+ "value", &halMapData->ctl.value,
+ "create", &createAlsaCtlJ)) {
+ AFB_API_ERROR(apiHandle,
+ "Parsing error, alsa json should only contains "
+ "[name]|[numid]||[value]|[create] in : '%s'",
+ json_object_get_string(alsaJ));
+ return -5;
+ }
+
+ if(name) {
+ halMapData->ctl.name = strdup(name);
+ if(! halMapData->ctl.name) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) control 'info' string");
+ return -6;
+ }
+ }
+
+ if(createAlsaCtlJ) {
+ halMapData->ctl.alsaCtlCreation = calloc(1, sizeof(struct InternalHalAlsaCtlProperties));
+ if(! halMapData->ctl.alsaCtlCreation) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to allocate alsa properties data structure for control to create");
+ return -7;
+ }
+
+ if(wrap_json_unpack(createAlsaCtlJ,
+ "{s:s s:i s:i s:i s:i !}",
+ "type", &typename,
+ "count", &halMapData->ctl.alsaCtlCreation->count,
+ "minval", &halMapData->ctl.alsaCtlCreation->minval,
+ "maxval", &halMapData->ctl.alsaCtlCreation->maxval,
+ "step", &halMapData->ctl.alsaCtlCreation->step)) {
+ AFB_API_ERROR(apiHandle,
+ "Parsing error, alsa creation json should only contains "
+ "[type]|[count]|[minval]|[maxval]|[step] in : '%s'",
+ json_object_get_string(alsaJ));
+ return -8;
+ }
+
+ if(typename) {
+ halMapData->ctl.alsaCtlCreation->type = InternalHalMapsAlsaTypeToEnum(typename);
+ if(halMapData->ctl.alsaCtlCreation->type == SND_CTL_ELEM_TYPE_NONE) {
+ AFB_API_ERROR(apiHandle,
+ "Couldn't get alsa type from string %s in : '%s'",
+ typename,
+ json_object_get_string(alsaJ));
+ return -9;
+ }
+ }
+
+ if(! halMapData->ctl.name)
+ halMapData->ctl.name = halMapData->uid;
+ }
+ else if(halMapData->ctl.name && halMapData->ctl.numid > 0) {
+ AFB_API_ERROR(apiHandle,
+ "Can't have both a control name (%s) and a control uid (%i) in alsa object : '%s'",
+ halMapData->ctl.name,
+ halMapData->ctl.numid,
+ json_object_get_string(alsaJ));
+ return -10;
+ }
+ else if(! halMapData->ctl.name && halMapData->ctl.numid <= 0) {
+ AFB_API_ERROR(apiHandle,
+ "Need at least a control name or a control uid in alsa object : '%s'",
+ json_object_get_string(alsaJ));
+ return -11;
+ }
+
+ if(action)
+ halMapData->actionJ = json_object_get(halMapControlJ);
+
+ return 0;
+}
+
+int InternalHalProcessOneHalMapObject(afb_api_t apiHandle,
+ json_object *halMapForTargetJ,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead)
+{
+ int idx, controlsCount, err = 0, halMapControlsJsonIsAnArray = 0;
+
+ char *uid, *info = NULL, *target;
+
+ struct InternalHalAlsaMap *currentHalMapData;
+
+ json_object *controlsJ, *currentHalMapControlJ;
+ json_type halMapControlsType;
+
+ AFB_API_DEBUG(apiHandle, "halMapForTargetJ='%s'", json_object_get_string(halMapForTargetJ));
+
+ if(wrap_json_unpack(halMapForTargetJ,
+ "{s:s s?:s s:s s:o !}",
+ "uid", &uid,
+ "info", &info,
+ "target", &target,
+ "controls", &controlsJ)) {
+ AFB_API_ERROR(apiHandle,
+ "Parsing error, map should only contains "
+ "[uid]|[info]|[target]|[controls] in : '%s'",
+ json_object_get_string(halMapForTargetJ));
+ return -1;
+ }
+
+ if(! HalUtlSearchProbedDeviceDataById(halDevicesToProbeListHead, target)) {
+ AFB_API_ERROR(apiHandle,
+ "Content of 'halmap' section is not valid because targeted dependency ('%s') is not present "
+ "in 'haldependencies' section, json configuration file correction is needed",
+ target);
+ return -2;
+ }
+
+ halMapControlsType = json_object_get_type(controlsJ);
+ switch(halMapControlsType) {
+ case json_type_array:
+ controlsCount = (int) json_object_array_length(controlsJ);
+ halMapControlsJsonIsAnArray = 1;
+ break;
+
+ case json_type_object:
+ controlsCount = 1;
+ break;
+
+ default:
+ AFB_API_ERROR(apiHandle,
+ "Content of 'halmap' controls section is not valid ('%s')",
+ json_object_get_string(controlsJ));
+ return -3;
+ }
+
+ for(idx = 0; idx < controlsCount; idx++) {
+ currentHalMapControlJ = halMapControlsJsonIsAnArray ? json_object_array_get_idx(controlsJ, idx) : controlsJ;
+
+ currentHalMapData = HalUtlAddHalMapDataToHalMapDataList(halMapListHead);
+
+ currentHalMapData->targetUid = strdup(uid);
+ if(! currentHalMapData->targetUid) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetUid' string");
+ return -4;
+ }
+
+ if(info) {
+ currentHalMapData->targetInfo = strdup(info);
+ if(! currentHalMapData->targetInfo) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetInfo' string");
+ return -5;
+ }
+ }
+
+ currentHalMapData->targetedDependency = strdup(target);
+ if(! currentHalMapData->targetedDependency) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'targetedDependency' string");
+ return -6;
+ }
+
+ err = InternalHalProcessOneHalMapControl(apiHandle,
+ currentHalMapData,
+ currentHalMapControlJ);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i was returned when tried to proccess halmap control %i ('%s')",
+ err,
+ idx,
+ json_object_get_string(currentHalMapControlJ));
+ HalUtlRemoveSelectedHalMapData(halMapListHead, currentHalMapData);
+ return -7;
+ }
+ }
+
+ return 0;
+}
+
+int InternalHalProcessAllHalMap(afb_api_t apiHandle,
+ json_object *halMapJ,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead)
+{
+ int idx, targetCount, err = 0, halMapJsonIsAnArray = 0;
+
+ json_object *currentHalMapTargetJ;
+ json_type alsaMapType;
+
+ AFB_API_DEBUG(apiHandle, "halMapJ='%s'", json_object_get_string(halMapJ));
+
+ alsaMapType = json_object_get_type(halMapJ);
+ switch(alsaMapType) {
+ case json_type_array:
+ targetCount = (int) json_object_array_length(halMapJ);
+ halMapJsonIsAnArray = 1;
+ break;
+
+ case json_type_object:
+ targetCount = 1;
+ break;
+
+ default:
+ AFB_API_ERROR(apiHandle,
+ "Content of 'halmap' section is not valid ('%s')",
+ json_object_get_string(halMapJ));
+ return -1;
+ }
+
+ for(idx = 0; idx < targetCount; idx++) {
+ currentHalMapTargetJ = halMapJsonIsAnArray ? json_object_array_get_idx(halMapJ, idx) : halMapJ;
+
+ err = InternalHalProcessOneHalMapObject(apiHandle,
+ currentHalMapTargetJ,
+ halMapListHead,
+ halDevicesToProbeListHead);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i was returned when tried to proccess halmap target %i ('%s')",
+ err,
+ idx,
+ json_object_get_string(currentHalMapTargetJ));
+ HalUtlRemoveAllHalMapData(halMapListHead);
+ return -2;
+ }
+ }
+
+ return 0;
+}
+
+int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, struct InternalHalAlsaMap *halMapData)
+{
+ int err;
+
+ char cardNbString[6];
+
+ json_object *valueJ, *convertedValueJ = NULL;
+
+ CtlActionT *toLoadAction;
+
+ halMapData->alsaControlEvent = afb_api_make_event(apiHandle, halMapData->uid);
+ if(! halMapData->alsaControlEvent) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to create event for alsa control with uid %s",
+ halMapData->uid);
+ return -1;
+ }
+
+ snprintf(cardNbString, sizeof(cardNbString), "hw:%i", halMapData->cardNb);
+
+ if(halMapData->ctl.alsaCtlCreation) {
+ if(InternalHalCreateAlsaCtl(apiHandle, cardNbString, &halMapData->ctl)) {
+ AFB_API_ERROR(apiHandle, "An error happened when trying to create a new alsa control");
+ return -2;
+ }
+ halMapData->ctl.alsaCtlProperties = halMapData->ctl.alsaCtlCreation;
+ }
+ else {
+ halMapData->ctl.alsaCtlProperties = calloc(1, sizeof(struct InternalHalAlsaCtlProperties));
+ if(! halMapData->ctl.alsaCtlProperties) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to allocate alsa properties data structure for control");
+ return -3;
+ }
+
+ if(InternalHalUpdateAlsaCtlProperties(apiHandle, cardNbString, &halMapData->ctl)) {
+ AFB_API_ERROR(apiHandle, "An error happened when trying to get existing alsa control info");
+ free(halMapData->ctl.alsaCtlProperties);
+ halMapData->ctl.alsaCtlProperties = NULL;
+ return -4;
+ }
+ }
+
+ if(halMapData->actionJ) {
+ toLoadAction = malloc(sizeof(CtlActionT));
+ if(! toLoadAction) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to allocate structure used to store action to perform "
+ "when the corresponding ALSA control is detected");
+ return -5;
+ }
+
+ if(ActionLoadOne(apiHandle, toLoadAction, halMapData->actionJ, 0)) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to load action using alsa object : '%s'",
+ json_object_get_string(halMapData->actionJ));
+ free(toLoadAction);
+ return -6;
+ }
+
+ halMapData->action = toLoadAction;
+ }
+
+ if(InternalHalSubscribeToAlsaCardEvent(apiHandle, cardNbString)) {
+ AFB_API_ERROR(apiHandle, "Error when trying to subscribe to alsacore event for audio card '%s'", cardNbString);
+ return -7;
+ }
+
+ if(halMapData->ctl.value) {
+ // TBD JAI : handle alsa controls type
+ valueJ = json_object_new_int(halMapData->ctl.value);
+ if(! valueJ) {
+ AFB_API_ERROR(apiHandle, "Didn't succeed to allocate ALSA control value json string");
+ return -8;
+ }
+
+ err = 0;
+
+ if(InternalHalConvertJsonValues(apiHandle,
+ halMapData->ctl.alsaCtlProperties,
+ valueJ,
+ &convertedValueJ,
+ CONVERSION_NORMALIZED_TO_ALSACORE)) {
+ AFB_API_ERROR(apiHandle, "Error when trying to convert initiate value json '%s'", json_object_get_string(valueJ));
+ err = -9;
+ }
+ else if(InternalHalSetAlsaCtlValue(apiHandle, cardNbString, halMapData->ctl.numid, convertedValueJ)) {
+ AFB_API_ERROR(apiHandle,
+ "Error while trying to set initial value on alsa control %i, device '%s', value '%s'",
+ halMapData->ctl.numid,
+ cardNbString,
+ json_object_get_string(valueJ));
+ err = -10;
+ }
+
+ json_object_put(valueJ);
+
+ if(convertedValueJ)
+ json_object_put(convertedValueJ);
+
+ if(err)
+ return err;
+ }
+
+ if(afb_api_add_verb(apiHandle, halMapData->uid, NULL, InternalHalActionOnAlsaCtl, (void *) halMapData, NULL, 0, 0)) {
+ AFB_API_ERROR(apiHandle,
+ "Didn't succeed to create verb %s for alsa control named %s on card %i",
+ halMapData->uid,
+ halMapData->ctl.name ? halMapData->ctl.name : "'N/A'",
+ halMapData->cardNb);
+ return -11;
+ }
+
+ return 0;
+}
+
+int InternalHalHandleSelectedHalMapWithValidatedDependency(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead,
+ char *targetedDependency,
+ enum DependenciesHandlingType halMapHandlingType)
+{
+ int err = 0, validatedHalMap;
+
+ struct InternalHalAlsaMap *currentHalMapData;
+
+ if(cds_list_empty(halMapListHead)) {
+ AFB_API_ERROR(apiHandle, "HalMap list is empty, nothing to handle");
+ return 0;
+ }
+
+ if(halMapHandlingType == UID_CORRESPONDING_DEPENDENCIES &&
+ ! targetedDependency) {
+ AFB_API_ERROR(apiHandle, "Invalid targeted dependency");
+ return -1;
+ }
+
+ cds_list_for_each_entry(currentHalMapData, halMapListHead, node) {
+ validatedHalMap = 0;
+ switch(halMapHandlingType) {
+ case ALL_DEPENDENCIES:
+ validatedHalMap = 1;
+ break;
+
+ case UID_CORRESPONDING_DEPENDENCIES:
+ if(! strcmp(targetedDependency, currentHalMapData->targetedDependency))
+ validatedHalMap = 1;
+ break;
+
+ default:
+ AFB_API_ERROR(apiHandle, "Invalid dependencies enum type");
+ return -2;
+ }
+
+ if(validatedHalMap) {
+ currentHalMapData->cardNb = HalUtlGetProbedDeviceCardNbUsingUid(halDevicesToProbeListHead,
+ currentHalMapData->targetedDependency);
+ if(currentHalMapData->cardNb == HAL_UNKNOWN_DEVICE) {
+ AFB_API_WARNING(apiHandle,
+ "Current halmap control %s can't be handled because corresponding "
+ "dependency ('%s') card is not available at the moment",
+ currentHalMapData->uid,
+ currentHalMapData->targetedDependency);
+ continue;
+ }
+
+ err = InternalHalHandleOneHalMapObject(apiHandle, currentHalMapData);
+ if(err) {
+ AFB_API_ERROR(apiHandle,
+ "Error %i was returned when tried to handle halmap control with uid %s",
+ err,
+ currentHalMapData->uid);
+ return -3;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int InternalHalHandleAllHalMapWithValidatedDependency(afb_api_t apiHandle,
+ struct cds_list_head *halMapListHead,
+ struct cds_list_head *halDevicesToProbeListHead)
+{
+ return InternalHalHandleSelectedHalMapWithValidatedDependency(apiHandle,
+ halMapListHead,
+ halDevicesToProbeListHead,
+ NULL,
+ ALL_DEPENDENCIES);
+}
+
+int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *AlsaMapJ)
+{
+ CtlConfigT *ctrlConfig;
+ struct HalData *currentHalData;
+
+ ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle);
+ if(! ctrlConfig)
+ return -1;
+
+ currentHalData = (struct HalData *) getExternalData(ctrlConfig);
+ if(! currentHalData)
+ return -2;
+
+ if(AlsaMapJ) {
+ if(InternalHalProcessAllHalMap(apiHandle,
+ AlsaMapJ,
+ &currentHalData->internalHalData->halMapListHead,
+ &currentHalData->internalHalData->probedDevicesListHead)) {
+ AFB_API_ERROR(apiHandle, "Failed to process 'halmap' section");
+ HalUtlRemoveAllHalMapData(&currentHalData->internalHalData->halMapListHead);
+ return -4;
+ }
+ }
+ else if(cds_list_empty(&currentHalData->internalHalData->halMapListHead)) {
+ AFB_API_WARNING(apiHandle, "No alsa controls defined in 'halmap' section");
+ return 1;
+ }
+ else if(InternalHalHandleAllHalMapWithValidatedDependency(apiHandle,
+ &currentHalData->internalHalData->halMapListHead,
+ &currentHalData->internalHalData->probedDevicesListHead)) {
+ AFB_API_ERROR(apiHandle, "Failed to handle 'halmap' section");
+ return -5;
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
* Internals HAL verbs functions *
******************************************************************************/
diff --git a/src/4a-internals-hal/4a-internals-hal-cb.h b/src/4a-internals-hal/4a-internals-hal-cb.h
index 4864d46..d7b998c 100644
--- a/src/4a-internals-hal/4a-internals-hal-cb.h
+++ b/src/4a-internals-hal/4a-internals-hal-cb.h
@@ -39,12 +39,6 @@ enum SubscribeUnsubscribeType {
// Internals HAL event handler function
void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json_object *eventJ);
-// Internals HAL - 'halmixer' section parsing/handling functions
-int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *MixerJ);
-
-// Internals HAL - 'halmap' section parsing/handling functions
-int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *halMapJ);
-
// Internals HAL - 'haldependencies' section parsing/handling functions
int InternalHalHandleHalDependencies(afb_api_t apiHandle,
struct HalData *currentHalData,
@@ -53,6 +47,12 @@ int InternalHalHandleHalDependencies(afb_api_t apiHandle,
char *uid);
int InternalHalHalDependenciesConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *DependenciesJ);
+// Internals HAL - 'halmixer' section parsing/handling functions
+int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *MixerJ);
+
+// Internals HAL - 'halmap' section parsing/handling functions
+int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *halMapJ);
+
// Internals HAL verbs functions
void InternalHalInfo(afb_req_t request);
void InternalHalSubscribe(afb_req_t request);