diff options
Diffstat (limited to 'src/4a-internals-hal/4a-internals-hal-cb.c')
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-cb.c | 325 |
1 files changed, 238 insertions, 87 deletions
diff --git a/src/4a-internals-hal/4a-internals-hal-cb.c b/src/4a-internals-hal/4a-internals-hal-cb.c index 19a1d4a..5dc0a2e 100644 --- a/src/4a-internals-hal/4a-internals-hal-cb.c +++ b/src/4a-internals-hal/4a-internals-hal-cb.c @@ -75,15 +75,6 @@ void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json return; } - if(currentHalData->sndCardId != cardidx) { - AFB_API_NOTICE(apiHandle, - "The received alsacore event does not concern " - "current hal soundcard %i (it was about card %i)", - currentHalData->sndCardId, - cardidx); - return; - } - if(cds_list_empty(¤tHalData->internalHalData->halMapListHead)) { AFB_API_ERROR(apiHandle, "No halmap data is available, cannot handle alsacore event"); return; @@ -91,7 +82,8 @@ void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json // Search for corresponding numid in ALSA controls list, if found, launch callback (if available) cds_list_for_each_entry(currentHalMapControl, ¤tHalData->internalHalData->halMapListHead, node) { - if(currentHalMapControl->ctl.alsaCtlProperties && + if(currentHalMapControl->cardNb == cardidx && + currentHalMapControl->ctl.alsaCtlProperties && currentHalMapControl->ctl.numid == numid) { if(currentHalMapControl->action) { memset(&source, 0, sizeof(CtlSourceT)); @@ -207,57 +199,64 @@ int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_ob * Internals HAL - 'halmap' section parsing/handling functions * ******************************************************************************/ -int InternalHalProcessOneHalMapObject(afb_api_t apiHandle, struct InternalHalAlsaMap *halMapData, json_object *halMapJ) +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; - AFB_API_DEBUG(apiHandle, "halMapJ=%s", json_object_get_string(halMapJ)); + if(! apiHandle || ! halMapData || ! halMapControlJ) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); + return -1; + } - if(wrap_json_unpack(halMapJ, "{s:s s?:s s:o s?:s !}", - "uid", &uid, - "info", &info, - "alsa", &alsaJ, - "action", &action)) { + 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, map should only contains " - "[label]|[uid]|[tag]|[info]|[alsa]|[action] in : '%s'", - json_object_get_string(halMapJ)); - return -1; + "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 -2; + 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 -3; + 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)) { + 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 -4; + 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 -5; + return -6; } } @@ -266,7 +265,7 @@ int InternalHalProcessOneHalMapObject(afb_api_t apiHandle, struct InternalHalAls if(! halMapData->ctl.alsaCtlCreation) { AFB_API_ERROR(apiHandle, "Didn't succeed to allocate alsa properties data structure for control to create"); - return -6; + return -7; } if(wrap_json_unpack(createAlsaCtlJ, @@ -280,7 +279,7 @@ int InternalHalProcessOneHalMapObject(afb_api_t apiHandle, struct InternalHalAls "Parsing error, alsa creation json should only contains " "[type]|[count]|[minval]|[maxval]|[step] in : '%s'", json_object_get_string(alsaJ)); - return -7; + return -8; } if(typename) { @@ -290,12 +289,12 @@ int InternalHalProcessOneHalMapObject(afb_api_t apiHandle, struct InternalHalAls "Couldn't get alsa type from string %s in : '%s'", typename, json_object_get_string(alsaJ)); - return -8; + return -9; } } if(! halMapData->ctl.name) - halMapData->ctl.name = (char *) halMapData->uid; + halMapData->ctl.name = halMapData->uid; } else if(halMapData->ctl.name && halMapData->ctl.numid > 0) { AFB_API_ERROR(apiHandle, @@ -303,58 +302,161 @@ int InternalHalProcessOneHalMapObject(afb_api_t apiHandle, struct InternalHalAls halMapData->ctl.name, halMapData->ctl.numid, json_object_get_string(alsaJ)); - return -9; + 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 -10; + return -11; } if(action) - halMapData->actionJ = json_object_get(halMapJ); + halMapData->actionJ = json_object_get(halMapControlJ); return 0; } -int InternalHalProcessAllHalMap(afb_api_t apiHandle, json_object *halMapJ, struct cds_list_head *halMapListHead) +int InternalHalProcessOneHalMapObject(afb_api_t apiHandle, + json_object *halMapForTargetJ, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead) { - int idx, count, err = 0, halMapJsonIsAnArray = 0; + int idx, controlsCount, err = 0, halMapControlsJsonIsAnArray = 0; + + char *uid, *info = NULL, *target; struct InternalHalAlsaMap *currentHalMapData; - json_object *currentHalMapJ; + 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: - count = (int) json_object_array_length(halMapJ); + targetCount = (int) json_object_array_length(halMapJ); halMapJsonIsAnArray = 1; break; case json_type_object: - count = 1; + targetCount = 1; break; default: - AFB_API_ERROR(apiHandle, "Content of 'halmap' section is not valid ('%s')", json_object_get_string(halMapJ)); + AFB_API_ERROR(apiHandle, + "Content of 'halmap' section is not valid ('%s')", + json_object_get_string(halMapJ)); return -1; } - for(idx = 0; idx < count; idx++) { - currentHalMapJ = halMapJsonIsAnArray ? json_object_array_get_idx(halMapJ, idx) : halMapJ; + for(idx = 0; idx < targetCount; idx++) { + currentHalMapTargetJ = halMapJsonIsAnArray ? json_object_array_get_idx(halMapJ, idx) : halMapJ; - currentHalMapData = HalUtlAddHalMapDataToHalMapDataList(halMapListHead); - - err = InternalHalProcessOneHalMapObject(apiHandle, currentHalMapData, currentHalMapJ); + err = InternalHalProcessOneHalMapObject(apiHandle, + currentHalMapTargetJ, + halMapListHead, + halDevicesToProbeListHead); if(err) { AFB_API_ERROR(apiHandle, - "Error %i was returned when tried to proccess halmap object %i ('%s')", + "Error %i was returned when tried to proccess halmap target %i ('%s')", err, idx, - json_object_get_string(currentHalMapJ)); + json_object_get_string(currentHalMapTargetJ)); HalUtlRemoveAllHalMapData(halMapListHead); return -2; } @@ -363,10 +465,12 @@ int InternalHalProcessAllHalMap(afb_api_t apiHandle, json_object *halMapJ, struc return 0; } -int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaMap *halMapData) +int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, struct InternalHalAlsaMap *halMapData) { int err; + char cardNbString[6]; + json_object *valueJ, *convertedValueJ = NULL; CtlActionT *toLoadAction; @@ -374,13 +478,15 @@ int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, char *cardId, struct I halMapData->alsaControlEvent = afb_api_make_event(apiHandle, halMapData->uid); if(! halMapData->alsaControlEvent) { AFB_API_ERROR(apiHandle, - "Didn't succeed to create event for current alsa control to load action using alsa object : '%s'", - json_object_get_string(halMapData->actionJ)); + "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, cardId, &halMapData->ctl)) { + if(InternalHalCreateAlsaCtl(apiHandle, cardNbString, &halMapData->ctl)) { AFB_API_ERROR(apiHandle, "An error happened when trying to create a new alsa control"); return -2; } @@ -394,7 +500,7 @@ int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, char *cardId, struct I return -3; } - if(InternalHalUpdateAlsaCtlProperties(apiHandle, cardId, &halMapData->ctl)) { + 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; @@ -422,8 +528,8 @@ int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, char *cardId, struct I halMapData->action = toLoadAction; } - if(InternalHalSubscribeToAlsaCardEvent(apiHandle, cardId)) { - AFB_API_ERROR(apiHandle, "Error when trying to subscribe to alsacore event for audio card '%s'", cardId); + if(InternalHalSubscribeToAlsaCardEvent(apiHandle, cardNbString)) { + AFB_API_ERROR(apiHandle, "Error when trying to subscribe to alsacore event for audio card '%s'", cardNbString); return -7; } @@ -445,11 +551,11 @@ int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, char *cardId, struct I AFB_API_ERROR(apiHandle, "Error when trying to convert initiate value json '%s'", json_object_get_string(valueJ)); err = -9; } - else if(InternalHalSetAlsaCtlValue(apiHandle, cardId, halMapData->ctl.numid, convertedValueJ)) { + 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, - cardId, + cardNbString, json_object_get_string(valueJ)); err = -10; } @@ -463,45 +569,93 @@ int InternalHalHandleOneHalMapObject(afb_api_t apiHandle, char *cardId, struct I return err; } - if(afb_api_add_verb(apiHandle, halMapData->uid, halMapData->info, InternalHalActionOnAlsaCtl, (void *) halMapData, NULL, 0, 0)) { + 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 for current alsa control : '%s'", - json_object_get_string(halMapData->actionJ)); + "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 -10; } return 0; } -int InternalHalHandleAllHalMap(afb_api_t apiHandle, int sndCardId, struct cds_list_head *halMapListHead) +int InternalHalHandleSelectedHalMapWithValidatedDependency(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead, + char *targetedDependency, + enum DependenciesHandlingType halMapHandlingType) { - int err = 0; - - char cardIdString[6]; + int err = 0, validatedHalMap; struct InternalHalAlsaMap *currentHalMapData; - snprintf(cardIdString, 6, "hw:%i", sndCardId); - 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) { - err = InternalHalHandleOneHalMapObject(apiHandle, cardIdString, currentHalMapData); - if(err) { - AFB_API_ERROR(apiHandle, - "Error %i was returned when tried to handle halmap object :' %s'", - err, - json_object_get_string(currentHalMapData->actionJ)); - return -1; + 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; @@ -516,27 +670,24 @@ int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_obje return -2; if(AlsaMapJ) { - if(InternalHalProcessAllHalMap(apiHandle, AlsaMapJ, ¤tHalData->internalHalData->halMapListHead)) { + 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(currentHalData->status == HAL_STATUS_UNAVAILABLE) { - AFB_API_WARNING(apiHandle, "Hal is unavailable, 'halmap' section data can't be handle"); - return 1; - } - else if(currentHalData->sndCardId < 0) { - AFB_API_ERROR(apiHandle, "Hal alsa card id is not valid, 'halmap' section data can't be handle"); - return -5; - } else if(cds_list_empty(¤tHalData->internalHalData->halMapListHead)) { AFB_API_WARNING(apiHandle, "No alsa controls defined in 'halmap' section"); - return 2; + return 1; } - else if(InternalHalHandleAllHalMap(apiHandle, currentHalData->sndCardId, ¤tHalData->internalHalData->halMapListHead)) { + else if(InternalHalHandleAllHalMapWithValidatedDependency(apiHandle, + ¤tHalData->internalHalData->halMapListHead, + ¤tHalData->internalHalData->probedDevicesListHead)) { AFB_API_ERROR(apiHandle, "Failed to handle 'halmap' section"); - return -6; + return -5; } return 0; |