diff options
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-cb.c | 1106 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-cb.h | 12 |
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, - ¤tHalData->internalHalData->halMapListHead, - ¤tHalData->internalHalData->probedDevicesListHead)) { - AFB_API_ERROR(apiHandle, "Failed to process 'halmap' section"); - HalUtlRemoveAllHalMapData(¤tHalData->internalHalData->halMapListHead); - return -4; - } - } - else if(cds_list_empty(¤tHalData->internalHalData->halMapListHead)) { - AFB_API_WARNING(apiHandle, "No alsa controls defined in 'halmap' section"); - return 1; - } - else if(InternalHalHandleAllHalMapWithValidatedDependency(apiHandle, - ¤tHalData->internalHalData->halMapListHead, - ¤tHalData->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, + ¤tHalData->internalHalData->halMapListHead, + ¤tHalData->internalHalData->probedDevicesListHead)) { + AFB_API_ERROR(apiHandle, "Failed to process 'halmap' section"); + HalUtlRemoveAllHalMapData(¤tHalData->internalHalData->halMapListHead); + return -4; + } + } + else if(cds_list_empty(¤tHalData->internalHalData->halMapListHead)) { + AFB_API_WARNING(apiHandle, "No alsa controls defined in 'halmap' section"); + return 1; + } + else if(InternalHalHandleAllHalMapWithValidatedDependency(apiHandle, + ¤tHalData->internalHalData->halMapListHead, + ¤tHalData->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); |