diff options
-rw-r--r-- | 4a-hal-cfg-example/hal-4a-2ch-generic-usb.json | 75 | ||||
-rw-r--r-- | lib/4a-hal-utilities/4a-hal-utilities-alsa-data.h | 10 | ||||
-rw-r--r-- | lib/4a-hal-utilities/4a-hal-utilities-data.c | 53 | ||||
-rw-r--r-- | lib/4a-hal-utilities/4a-hal-utilities-data.h | 2 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-alsacore-link.c | 2 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-cb.c | 325 |
6 files changed, 337 insertions, 130 deletions
diff --git a/4a-hal-cfg-example/hal-4a-2ch-generic-usb.json b/4a-hal-cfg-example/hal-4a-2ch-generic-usb.json index ea7c00f..9fe4c1d 100644 --- a/4a-hal-cfg-example/hal-4a-2ch-generic-usb.json +++ b/4a-hal-cfg-example/hal-4a-2ch-generic-usb.json @@ -1,13 +1,13 @@ { "$schema": "http://iot.bzh/download/public/schema/json/ctl-schema.json", "metadata": { - "uid": "/dev/snd/by-id/usb-0d8c_USB_Sound_Device-00", - "version": "0.9", + "uid": "GENERIC-USB-4A-HAL", + "version": "0.99", "api": "4a-hal-2ch-generic-usb", "require": [ "alsacore", "smixer" ], "info": "4a hal for 2ch generic USB device", "author": "Jonathan Aillet", - "date": "2018-06-13" + "date": "2019-06-25" }, "resources": [ { @@ -15,13 +15,13 @@ "info": "Bluealsa hal plugin", "params": { "sco": { - "mic": "2CH-GENERIC-USB", + "mic": "CSL-CM106-8CH-USB", "zone": "full-stereo", "delayms": 800 }, "a2dp": { - "zone": "full-stereo", - "delayms": 500 + "zone": "full-stereo", + "delayms": 500 } }, "libs": ["hal-bluealsa.ctlso"] @@ -34,34 +34,45 @@ "action": "api://4a-hal-manager#ping" } ], + "haldependencies" : { + "uid" : "generic-usb", + "class" : "mandatory", + "cardPath" : "/dev/snd/by-id/usb-0d8c_USB_Sound_Device-00" + }, "halmap": [ { - "uid": "agl-master-playback-volume", - "alsa": { - "name": "Speaker Playback Volume", - "value": 80 - } - }, - { - "uid": "agl-master-playback-switch", - "alsa": { - "name": "Speaker Playback Switch", - "value": 1 - } - }, - { - "uid": "agl-mic-capture-volume", - "alsa": { - "name": "Mic Capture Volume", - "value": 80 - } - }, - { - "uid": "agl-mic-capture-switch", - "alsa": { - "name": "Mic Capture Switch", - "value": 1 - } + "uid" : "halmap-generic-usb", + "target" : "generic-usb", + "controls" : [ + { + "uid": "agl-master-playback-volume", + "alsa": { + "name": "Speaker Playback Volume", + "value": 80 + } + }, + { + "uid": "agl-master-playback-switch", + "alsa": { + "name": "Speaker Playback Switch", + "value": 1 + } + }, + { + "uid": "agl-master-capture-volume", + "alsa": { + "name": "Mic Capture Volume", + "value": 80 + } + }, + { + "uid": "agl-mic-capture-switch", + "alsa": { + "name": "Mic Capture Switch", + "value": 1 + } + } + ] } ], "halmixer": { diff --git a/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.h b/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.h index d548c73..b387468 100644 --- a/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.h +++ b/lib/4a-hal-utilities/4a-hal-utilities-alsa-data.h @@ -30,6 +30,8 @@ #include <ctl-config.h> +#define HAL_UNKNOWN_DEVICE -1 + struct InternalHalAlsaDBScale { int min; int max; @@ -44,7 +46,7 @@ struct InternalHalAlsaCtlProperties { int maxval; int step; // TBD JAI : use them - const char **enums; + char **enums; struct InternalHalAlsaDBScale *dbscale; }; @@ -58,6 +60,12 @@ struct InternalHalAlsaCtl { }; struct InternalHalAlsaMap { + char *targetUid; + char *targetInfo; + + char *targetedDependency; + int cardNb; + char *uid; char *info; diff --git a/lib/4a-hal-utilities/4a-hal-utilities-data.c b/lib/4a-hal-utilities/4a-hal-utilities-data.c index cebc223..b6d8abb 100644 --- a/lib/4a-hal-utilities/4a-hal-utilities-data.c +++ b/lib/4a-hal-utilities/4a-hal-utilities-data.c @@ -68,6 +68,7 @@ void *HalUtlAddNodeInList(struct cds_list_head *listHead, enum LinkedListType li if(! returned) return NULL; nodeToAdd = &((struct InternalHalAlsaMap *) returned)->node; + ((struct InternalHalAlsaMap *) returned)->cardNb = HAL_UNKNOWN_DEVICE; break; case LINKED_LIST_FOR_HAL_DATA: @@ -871,12 +872,18 @@ json_object *HalUtlGetJsonArrayForAllMixersData(afb_api_t apiHandle, struct cds_ void HalUtlFreeSelectedHalMapDataAllocation(struct InternalHalAlsaMap *halMapDataToFree) { + free(halMapDataToFree->targetUid); + free(halMapDataToFree->targetInfo); + + free(halMapDataToFree->targetedDependency); + free(halMapDataToFree->uid); free(halMapDataToFree->info); free(halMapDataToFree->action); - free(halMapDataToFree->ctl.name); + if(halMapDataToFree->ctl.name != halMapDataToFree->uid) + free(halMapDataToFree->ctl.name); if(halMapDataToFree->ctl.alsaCtlCreation) { free(halMapDataToFree->ctl.alsaCtlCreation->enums); @@ -918,7 +925,7 @@ json_object *HalUtGetJsonArrayForSpecificHalMapControl(afb_api_t apiHandle, { int wrapRet; - json_object *currentAlsaMapDataJ; + json_object *currentAlsaMapInfoJ, *additionalInfoJ; if(! apiHandle) { AFB_API_ERROR(apiHandle, "Can't get current internal hal api handle"); @@ -930,16 +937,48 @@ json_object *HalUtGetJsonArrayForSpecificHalMapControl(afb_api_t apiHandle, return NULL; } - wrapRet = wrap_json_pack(¤tAlsaMapDataJ, - "{s:s s:s}", + wrapRet = wrap_json_pack(¤tAlsaMapInfoJ, + "{s:s s:s s:s}", "name", currentHalMapData->uid, - "info", currentHalMapData->info ? currentHalMapData->info : "none"); + "info", currentHalMapData->info ? currentHalMapData->info : "none", + "target", currentHalMapData->targetedDependency); if(wrapRet) { - AFB_API_ERROR(apiHandle, "Didn't succeed to allocate current streams json object"); + AFB_API_ERROR(apiHandle, "Didn't succeed to allocate current halmap control first part of info json object"); return NULL; } - return currentAlsaMapDataJ; + if(currentHalMapData->cardNb == HAL_UNKNOWN_DEVICE || + ! currentHalMapData->ctl.alsaCtlProperties) { + json_object_object_add(currentAlsaMapInfoJ, "available", json_object_new_boolean(0)); + } + else { + wrapRet = wrap_json_pack(&additionalInfoJ, + "{s:b s:i s:s}", + "available", 1, + "cardNb", currentHalMapData->cardNb, + "cardControlName", currentHalMapData->ctl.name ? currentHalMapData->ctl.name : "'N/A'"); + if(wrapRet) { + AFB_API_ERROR(apiHandle, "Didn't succeed to allocate current halmap control second part of info json object"); + json_object_put(currentAlsaMapInfoJ); + return NULL; + } + + wrap_json_object_add(currentAlsaMapInfoJ, additionalInfoJ); + } + + wrapRet = wrap_json_pack(&additionalInfoJ, + "{s:s s:s}", + "halmap-uid", currentHalMapData->targetUid, + "halmap-info", currentHalMapData->targetInfo ? currentHalMapData->targetInfo : "none"); + if(wrapRet) { + AFB_API_ERROR(apiHandle, "Didn't succeed to allocate current halmap control third part of info json object"); + json_object_put(currentAlsaMapInfoJ); + return NULL; + } + + wrap_json_object_add(currentAlsaMapInfoJ, additionalInfoJ); + + return currentAlsaMapInfoJ; } json_object *HalUtGetJsonArrayForAllHalMapControls(afb_api_t apiHandle, struct cds_list_head *halMapListHead) diff --git a/lib/4a-hal-utilities/4a-hal-utilities-data.h b/lib/4a-hal-utilities/4a-hal-utilities-data.h index 1ecfe00..bea92dd 100644 --- a/lib/4a-hal-utilities/4a-hal-utilities-data.h +++ b/lib/4a-hal-utilities/4a-hal-utilities-data.h @@ -30,8 +30,6 @@ #include "4a-hal-utilities-alsa-data.h" -#define HAL_UNKNOWN_DEVICE -1 - #define HAL_STREAM_UPDATES_EVENT_NAME "stream-updates" // Enum for linked list type diff --git a/src/4a-internals-hal/4a-internals-hal-alsacore-link.c b/src/4a-internals-hal/4a-internals-hal-alsacore-link.c index 0243a7b..6a56e78 100644 --- a/src/4a-internals-hal/4a-internals-hal-alsacore-link.c +++ b/src/4a-internals-hal/4a-internals-hal-alsacore-link.c @@ -582,7 +582,7 @@ void InternalHalActionOnAlsaCtl(afb_req_t request) return; } - snprintf(cardIdString, 6, "hw:%i", currentHalData->sndCardId); + snprintf(cardIdString, 6, "hw:%i", currentAlsaCtl->cardNb); if(InternalHalGetAlsaCtlValues(apiHandle, cardIdString, ¤tAlsaCtl->ctl, &previousControlValuesJ)) { afb_req_fail(request, "previous_values", "Error when trying to get unchanged alsa control values"); 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; |