diff options
-rw-r--r-- | 4a-hal-cfg-example/hal-4a-example.json | 2 | ||||
-rw-r--r-- | lib/4a-hal-utilities/4a-hal-utilities-data.c | 81 | ||||
-rw-r--r-- | lib/4a-hal-utilities/4a-hal-utilities-data.h | 17 | ||||
-rw-r--r-- | lib/4a-hal-utilities/4a-hal-utilities-ping.c | 2 | ||||
-rw-r--r-- | src/4a-hal-manager/4a-hal-manager-cb.c | 87 | ||||
-rw-r--r-- | src/4a-hal-manager/4a-hal-manager-cb.h | 2 | ||||
-rw-r--r-- | src/4a-hal-manager/4a-hal-manager.c | 19 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-alsacore-link.c | 320 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-alsacore-link.h | 47 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-api-loader.c | 90 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-api-loader.h | 2 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-cb.c | 1457 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-cb.h | 44 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-mixer-link.c | 96 | ||||
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-mixer-link.h | 4 |
15 files changed, 1536 insertions, 734 deletions
diff --git a/4a-hal-cfg-example/hal-4a-example.json b/4a-hal-cfg-example/hal-4a-example.json index 9314b7b..4b23a4f 100644 --- a/4a-hal-cfg-example/hal-4a-example.json +++ b/4a-hal-cfg-example/hal-4a-example.json @@ -87,7 +87,7 @@ "step": 1 } }, - "action": "api://4a-hal-csl-cm106-8ch-usb#ping" + "action": "api://4a-hal-example#ping" } ] }, diff --git a/lib/4a-hal-utilities/4a-hal-utilities-data.c b/lib/4a-hal-utilities/4a-hal-utilities-data.c index 6d1afd0..865bebb 100644 --- a/lib/4a-hal-utilities/4a-hal-utilities-data.c +++ b/lib/4a-hal-utilities/4a-hal-utilities-data.c @@ -313,6 +313,26 @@ int HalUtlGetNumberOfProbedDevicesInList(struct cds_list_head *probedDevicesList return HalUtlGetNumberOfNodesInList(probedDevicesListHead); } +int HalUtlGetNumberOfDynamicProbedDevicesInList(struct cds_list_head *probedDevicesListHead) +{ + int numberOfDynamicProbedDevicesInList = 0; + + struct InternalHalProbedDevice *currentProbedDevice; + + if(! probedDevicesListHead) + return -1; + + if(cds_list_empty(probedDevicesListHead)) + return 0; + + cds_list_for_each_entry(currentProbedDevice, probedDevicesListHead, node) { + if(currentProbedDevice->deviceClass == DYNAMIC_PROBED_DEVICE) + numberOfDynamicProbedDevicesInList++; + } + + return numberOfDynamicProbedDevicesInList; +} + struct InternalHalProbedDevice *HalUtlSearchProbedDeviceDataById(struct cds_list_head *probedDevicesListHead, char *uid) { @@ -467,8 +487,9 @@ json_object *HalUtlGetCompactJsonForSpecificDependencies(afb_api_t apiHandle, cardNb = requestedProbedDevice->deviceData->extendedCardNb; wrapRet = wrap_json_pack(&requestedProbedDeviceJ, - "{s:s s:s}", + "{s:s, s:b, s:s}", "uid", requestedProbedDevice->uid, + "available", cardNb ? 1 : 0, "cardNb", cardNb ? cardNb : "none"); if(wrapRet) { AFB_API_ERROR(apiHandle, @@ -771,6 +792,64 @@ json_object *HalUtlGetJsonArrayForAllDependencies(afb_api_t apiHandle, return requestedDependenciesInfoJ; } +json_object *HalUtlGetJsonArrayForAllDependenciesInfoWithHandledDependency(afb_api_t apiHandle, + struct cds_list_head *probedDevicesListHead, + enum DependencyInfoJsonFormat jsonFormat, + char *handledProbedDeviceUid) +{ + int err; + size_t idx, dependencyNb; + char *currentDependencyObjectUidString = NULL; + + json_object *requestedDependenciesInfoJ, *currentDependencyObject; + + if(! apiHandle) { + AFB_API_ERROR(apiHandle, "Api handle is not valid"); + return NULL; + } + + if(! probedDevicesListHead) { + AFB_API_ERROR(apiHandle, "Probed device list is not valid"); + return NULL; + } + + if(cds_list_empty(probedDevicesListHead)) { + AFB_API_INFO(apiHandle, "Probed device list is empty"); + return NULL; + } + + if(! handledProbedDeviceUid) { + AFB_API_ERROR(apiHandle, "Probed device uid is not valid"); + return NULL; + } + + requestedDependenciesInfoJ = HalUtlGetJsonArrayForAllDependencies(apiHandle, + probedDevicesListHead, + jsonFormat); + if(! requestedDependenciesInfoJ) { + AFB_API_ERROR(apiHandle, "Didn't succeed get all devices (dependencies) info"); + return NULL; + } + + dependencyNb = json_object_array_length(requestedDependenciesInfoJ); + for(idx = 0; idx < dependencyNb; idx++) { + currentDependencyObject = json_object_array_get_idx(requestedDependenciesInfoJ, idx); + + err = wrap_json_unpack(currentDependencyObject, "{s:s}", "uid", ¤tDependencyObjectUidString); + if(err) { + AFB_API_ERROR(apiHandle, "Dependency object is malformed (no uid key)"); + return NULL; + } + + if(! strcmp(handledProbedDeviceUid, currentDependencyObjectUidString)) + json_object_object_add(currentDependencyObject, "handled", json_object_new_boolean(1)); + else + json_object_object_add(currentDependencyObject, "handled", json_object_new_boolean(0)); + } + + return requestedDependenciesInfoJ; +} + /******************************************************************************* * Internal Hal - Streams data handling functions * ******************************************************************************/ diff --git a/lib/4a-hal-utilities/4a-hal-utilities-data.h b/lib/4a-hal-utilities/4a-hal-utilities-data.h index a2b28dd..69ba747 100644 --- a/lib/4a-hal-utilities/4a-hal-utilities-data.h +++ b/lib/4a-hal-utilities/4a-hal-utilities-data.h @@ -56,6 +56,16 @@ enum ProbedDeviceClasses { MANDATORY_PROBED_DEVICE = 3 }; +// Enum for dependencies mixer link status +enum DependencyMixerStatus { + DEPENDENCY_NO_MIXER_LINK = 0, + DEPENDENCY_MIXER_LINK_USELESS = 1, + DEPENDENCY_MIXER_ATTACH_SUCCEED = 2, + DEPENDENCY_MIXER_ATTACH_FAILED = 3, + DEPENDENCY_MIXER_DETACH_SUCCEED = 4, + DEPENDENCY_MIXER_DETACH_FAILED = 5 +}; + // Enum for probed devices (dependencies) info format requested enum DependencyInfoJsonFormat { DEPENDENCY_COMPACT_JSON = 0, @@ -91,6 +101,7 @@ struct InternalHalProbedDevice { json_object *requestedDeviceJ; struct InternalHalDeviceData *deviceData; + enum DependencyMixerStatus mixerLinkStatus; struct cds_list_head node; }; @@ -153,11 +164,13 @@ struct HalMgrData { // Internal Hal - Probed devices structure handling functions enum ProbedDeviceClasses HalUtlGetProbedDeviceClassFromString(char *probedDeviceString); char *HalUtlGetProbedDeviceClassString(enum ProbedDeviceClasses deviceClass); +void HalUtlFreeSelectedProbedDeviceDataAllocation(struct InternalHalDeviceData *probedDeviceDataToFree); struct InternalHalProbedDevice *HalUtlAddProbedDeviceToProbedDeviceList(struct cds_list_head *probedDevicesListHead); int HalUtlRemoveSelectedProbedDeviceFromList(struct cds_list_head *probedDevicesListHead, struct InternalHalProbedDevice *probedDeviceToRemove); int HalUtlRemoveAllProbedDevicesFromList(struct cds_list_head *probedDevicesListHead); int HalUtlGetNumberOfProbedDevicesInList(struct cds_list_head *probedDevicesListHead); +int HalUtlGetNumberOfDynamicProbedDevicesInList(struct cds_list_head *probedDevicesListHead); struct InternalHalProbedDevice *HalUtlSearchProbedDeviceDataById(struct cds_list_head *probedDevicesListHead, char *uid); int HalUtlGetProbedDeviceCardNbUsingUid(struct cds_list_head *probedDevicesListHead, char *uid); @@ -175,6 +188,10 @@ json_object *HalUtlGetJsonArrayForAvailableDependencies(afb_api_t apiHandle, json_object *HalUtlGetJsonArrayForAllDependencies(afb_api_t apiHandle, struct cds_list_head *probedDevicesListHead, enum DependencyInfoJsonFormat jsonFormat); +json_object *HalUtlGetJsonArrayForAllDependenciesInfoWithHandledDependency(afb_api_t apiHandle, + struct cds_list_head *probedDevicesListHead, + enum DependencyInfoJsonFormat jsonFormat, + char *handledProbedDeviceUid); // Internal Hal - Streams data handling functions struct InternalHalMixerData *HalUtlAddMixerDataToMixerDataList(struct cds_list_head *mixerDataListHead); diff --git a/lib/4a-hal-utilities/4a-hal-utilities-ping.c b/lib/4a-hal-utilities/4a-hal-utilities-ping.c index a40254f..4a3fc25 100644 --- a/lib/4a-hal-utilities/4a-hal-utilities-ping.c +++ b/lib/4a-hal-utilities/4a-hal-utilities-ping.c @@ -47,6 +47,4 @@ void HalUtlPing(afb_req_t request) } afb_req_success(request, countJ, "Ping count"); - - return; }
\ No newline at end of file diff --git a/src/4a-hal-manager/4a-hal-manager-cb.c b/src/4a-hal-manager/4a-hal-manager-cb.c index 771ff50..67f46a9 100644 --- a/src/4a-hal-manager/4a-hal-manager-cb.c +++ b/src/4a-hal-manager/4a-hal-manager-cb.c @@ -26,6 +26,8 @@ #include "4a-hal-utilities-data.h" +#include "../4a-internals-hal/4a-internals-hal-cb.h" + #include "4a-hal-manager-cb.h" /******************************************************************************* @@ -127,6 +129,91 @@ void HalMgrLoaded(afb_req_t request) afb_req_success(request, requestAnswer, "Requested data"); } +void HalMgrInfo(afb_req_t request) +{ + int err, wrapRet = 0; + + afb_api_t apiHandle; + struct HalMgrData *halMgrData; + struct HalData *currentHalData; + + json_object *requestJson, *toReturnJ, *returnedInfoJ, *transferredJson = NULL; + + apiHandle = afb_req_get_api(request); + if(! apiHandle) { + afb_req_fail(request, "api_handle", "Can't get hal manager api handle"); + return; + } + + halMgrData = (struct HalMgrData *) afb_api_get_userdata(apiHandle); + if(! halMgrData) { + afb_req_fail(request, "hal_manager_data", "Can't get hal manager data"); + return; + } + + if(cds_list_empty(&halMgrData->halDataListHead)) { + afb_req_success(request, NULL, "No Hal Api loaded"); + return; + } + + requestJson = afb_req_json(request); + if(! requestJson) { + AFB_REQ_NOTICE(request, "Can't get request json, will use default verbose"); + wrapRet = wrap_json_pack(&transferredJson, "{s:i}", "verbose", 0); + if(wrapRet) { + afb_req_fail(request, "json_request", "Didn't succeed to generate default json request"); + return; + } + } + else { + AFB_REQ_DEBUG(request, + "Received request json ('%s') will be transferred to each hal 'info' verb", + json_object_get_string(requestJson)); + transferredJson = requestJson; + } + + toReturnJ = json_object_new_array(); + if(! toReturnJ) { + afb_req_fail(request, + "response_json_array", + "Didn't succeed to allocate response json array"); + if(! requestJson) + json_object_put(transferredJson); + return; + } + + cds_list_for_each_entry(currentHalData, &halMgrData->halDataListHead, node) { + if(! currentHalData->internalHalData) { + AFB_REQ_INFO(request, + "'%s' hal is an external hal, will not be able to get info about it", + currentHalData->apiName); + continue; + } + + err = GenerateInternalHalInfoJson(apiHandle, + currentHalData, + transferredJson, + &returnedInfoJ); + if(err){ + AFB_REQ_INFO(request, + "Error %i happened when tried to generate hal '%s' information json", + err, + currentHalData->apiName); + json_object_put(toReturnJ); + if(! requestJson) + json_object_put(transferredJson); + return; + } + + json_object_array_add(toReturnJ, returnedInfoJ); + } + + if(! requestJson) + json_object_put(transferredJson); + + afb_req_success(request, toReturnJ, "Requested data"); +} + void HalMgrLoad(afb_req_t request) { char *apiName, *uid, *info = NULL, *author = NULL, *version = NULL, *date = NULL; diff --git a/src/4a-hal-manager/4a-hal-manager-cb.h b/src/4a-hal-manager/4a-hal-manager-cb.h index e0e144f..d35f83e 100644 --- a/src/4a-hal-manager/4a-hal-manager-cb.h +++ b/src/4a-hal-manager/4a-hal-manager-cb.h @@ -26,8 +26,8 @@ void HalMgrDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json_object *eventJ); // Exported verbs callbacks -void HalMgrPing(afb_req_t request); void HalMgrLoaded(afb_req_t request); +void HalMgrInfo(afb_req_t request); void HalMgrLoad(afb_req_t request); void HalMgrUnload(afb_req_t request); void HalMgrSubscribeEvent(afb_req_t request); diff --git a/src/4a-hal-manager/4a-hal-manager.c b/src/4a-hal-manager/4a-hal-manager.c index da33db8..e21b948 100644 --- a/src/4a-hal-manager/4a-hal-manager.c +++ b/src/4a-hal-manager/4a-hal-manager.c @@ -41,6 +41,7 @@ afb_verb_t HalManagerApiStaticVerbs[] = /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */ { .verb = "ping", .callback = HalUtlPing, .info = "Ping for test"}, { .verb = "loaded", .callback = HalMgrLoaded, .info = "Show loaded HAL"}, + { .verb = "info", .callback = HalMgrInfo, .info = "List available dependencies/controls/streams for all hals"}, { .verb = "load", .callback = HalMgrLoad, .info = "Load an external HAL to HAL Manager"}, { .verb = "unload", .callback = HalMgrUnload, .info = "Unload an external HAL to HAL Manager"}, { .verb = "subscribe", .callback = HalMgrSubscribeEvent, .info = "Subscribe to an event"}, @@ -78,30 +79,26 @@ static int HalMgrInitApi(afb_api_t apiHandle) if(afb_api_require_api(apiHandle, currentHalData->apiName, 1) || currentHalData->status == HAL_STATUS_INIT_FAILED) { - AFB_API_ERROR(apiHandle, - "Error caught during '%s' api initialization, this api won't be reachable", - currentHalData->apiName); + AFB_API_INFO(apiHandle, + "Error caught during '%s' api initialization, this api won't be reachable", + currentHalData->apiName); toDeleteApiName = strdup(currentHalData->apiName); if(! toDeleteApiName) { AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'apiName' string"); - return -5; + return -4; } - err = HalUtlRemoveHalDataAndDeleteHalApi(apiHandle, currentHalData, &halMgrData->halDataListHead); + err = InternalHalDeleteApi(apiHandle, &halMgrData->halDataListHead, currentHalData); if(err) { AFB_API_ERROR(apiHandle, - "Error %i happened while trying to delete '%s' api and to remove all its data", + "Error %i happened when tried to delete %s api", err, toDeleteApiName); free(toDeleteApiName); - return -6; + return -5; } - AFB_API_ERROR(apiHandle, - "Api '%s' and all its data has been deleted", - toDeleteApiName); - free(toDeleteApiName); } } 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 bb1c4c9..353383e 100644 --- a/src/4a-internals-hal/4a-internals-hal-alsacore-link.c +++ b/src/4a-internals-hal/4a-internals-hal-alsacore-link.c @@ -66,6 +66,177 @@ snd_ctl_elem_type_t InternalHalMapsAlsaTypeToEnum(const char *label) } /******************************************************************************* + * Internals HAL - Alsacore events handler function * + ******************************************************************************/ + +enum aslacoreEventType InternalHalGetAlsaCoreEventType(const char *evtLabel) +{ + if(! evtLabel) + return ALSACORE_UNRECOGNIZED_EVENT; + + if(! strncmp(&evtLabel[ALSACORE_EVENT_NAME_BEGIN], + ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX, + ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX_LENGTH)) + return ALSACORE_EVENT_CARD_CONTROL_CHANGE; + + return ALSACORE_UNRECOGNIZED_EVENT; +} + +int InternalHalHandleAlsaCoreCardControlEvent(afb_api_t apiHandle, + const char *evtLabel, + json_object *eventJ, + struct HalData *currentHalData) +{ + int numid, cardidx, controlsUsingCardCount = 0, controlUsedCount = 0; + + char cardNbString[6]; + + json_object *valuesJ, *normalizedValuesJ; + + CtlSourceT source; + + struct InternalHalAlsaMap *currentHalMapControl; + + if(! apiHandle || ! evtLabel || ! eventJ || ! currentHalData) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); + return -1; + } + + if(sscanf(&evtLabel[ALSACORE_CARD_CONTROL_EVENT_BEGIN], "%d", &cardidx) != 1) { + AFB_API_ERROR(apiHandle, + "Did not succeed to get ALSA card number of the modified control : evtname=%s [msg=%s]", + evtLabel, + json_object_get_string(eventJ)); + return -2; + } + + if(wrap_json_unpack(eventJ, "{s:i s:o}", "id", &numid, "val", &valuesJ)) { + AFB_API_ERROR(apiHandle, + "Invalid alsacore modified control event received label=%s value=%s", + evtLabel, + json_object_get_string(eventJ)); + return -3; + } + + if(cds_list_empty(¤tHalData->internalHalData->halMapListHead)) { + AFB_API_ERROR(apiHandle, + "No halmap data is available, cannot handle alsacore event label=%s value=%s", + evtLabel, + json_object_get_string(eventJ)); + return -4; + } + + // 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->cardNb == cardidx) + controlsUsingCardCount++; + + if(currentHalMapControl->cardNb != cardidx || + ! currentHalMapControl->ctl.alsaCtlProperties || + currentHalMapControl->ctl.numid != numid) + continue; + + if(currentHalMapControl->action) { + memset(&source, 0, sizeof(CtlSourceT)); + source.uid = currentHalMapControl->action->uid; + source.api = currentHalMapControl->action->api; + + ActionExecOne(&source, currentHalMapControl->action, valuesJ); + } + else if(currentHalMapControl->actionJ) { + AFB_API_WARNING(apiHandle, + "The alsa control id '%i' is corresponding to a known control which " + "has a registered action, but action is not ready to be executed", + numid); + } + else { + AFB_API_NOTICE(apiHandle, + "The alsa control id '%i' is corresponding to a known control " + "but without any action registered", + numid); + } + + if(! currentHalMapControl->alsaControlEvent || + InternalHalConvertJsonValues(apiHandle, + currentHalMapControl->ctl.alsaCtlProperties, + valuesJ, + &normalizedValuesJ, + CONVERSION_ALSACORE_TO_NORMALIZED) || + (afb_event_push(currentHalMapControl->alsaControlEvent, normalizedValuesJ) < 0)) { + AFB_API_ERROR(apiHandle, + "Couldn't generate an event for known halmap %s (alsa control id %i)", + currentHalMapControl->uid, + currentHalMapControl->ctl.numid); + } + + controlUsedCount++; + } + + if(! controlsUsingCardCount) { + AFB_API_INFO(apiHandle, + "Receiving events from not handle card %i, unscubscribe from these events", + cardidx); + snprintf(cardNbString, sizeof(cardNbString), "hw:%i", cardidx); + InternalHalUnsubscribeFromAlsacoreCardEvent(apiHandle, cardNbString); + return 1; + } + + if(controlUsedCount) + return 0; + + AFB_API_INFO(apiHandle, + "Alsacore event with an unrecognized numid: %i, evtname=%s [msg=%s]", + numid, + evtLabel, + json_object_get_string(eventJ)); + + return 2; + +} + +int InternalHalHandleAlsaCoreEvents(afb_api_t apiHandle, + const char *evtLabel, + json_object *eventJ, + struct HalData *currentHalData) +{ + int returned; + + if(! apiHandle || ! evtLabel || ! eventJ || ! currentHalData) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); + return -1; + } + + switch(InternalHalGetAlsaCoreEventType(evtLabel)) { + case ALSACORE_EVENT_CARD_CONTROL_CHANGE: + returned = InternalHalHandleAlsaCoreCardControlEvent(apiHandle, evtLabel, eventJ, currentHalData); + if(returned < 0) { + AFB_API_ERROR(apiHandle, + "Error %i caught when tried to handle alsacore card control event evtname=%s [msg=%s]", + returned, + evtLabel, + json_object_get_string(eventJ)); + return -2; + } + else if(returned > 0) { + AFB_API_INFO(apiHandle, + "Warning %i raised when tried to handle alsacore card control event evtname=%s [msg=%s]", + returned, + evtLabel, + json_object_get_string(eventJ)); + } + return 0; + + case ALSACORE_UNRECOGNIZED_EVENT: + default: + AFB_API_NOTICE(apiHandle, + "Alsacore event with an unrecognized evtname=%s [msg=%s]", + evtLabel, + json_object_get_string(eventJ)); + return 1; + } +} + +/******************************************************************************* * Internals HAL - Alsacore calls funtions * ******************************************************************************/ @@ -102,33 +273,31 @@ int InternalHalGetCardInfo(afb_api_t apiHandle, json_object *requestJ, json_obje return errorToReturn; } -int InternalHalSubscribeToAlsaCardEvent(afb_api_t apiHandle, char *cardId) +int InternalHalSubscribeUnscubscribeToAlsacoreEvent(afb_api_t apiHandle, + json_object *subscribeQueryJ, + enum AlsacoreSubscribeUnsubscribeType subscriptionType) { - int err = 0, wrapRet; + int err = 0; char *returnedError = NULL, *returnedInfo = NULL; - json_object *subscribeQueryJ, *responseJ = NULL; + json_object *responseJ = NULL; - wrapRet = wrap_json_pack(&subscribeQueryJ, - "{s:s, s:s}", - "event", ALSACORE_CARD_CONTROL_EVENT_NAME, - "devid", cardId); - if(wrapRet) { - AFB_API_ERROR(apiHandle, "Didn't succeed to allocate subscription query json object"); + if(! apiHandle || ! subscribeQueryJ) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); return -1; } if(afb_api_call_sync(apiHandle, ALSACORE_API, - ALSACORE_SUBSCRIBE_VERB, + (subscriptionType == ALSACORE_SUBSCRIPTION) ? ALSACORE_SUBSCRIBE_VERB : ALSACORE_UNSUBSCRIBE_VERB, subscribeQueryJ, &responseJ, &returnedError, &returnedInfo)) { AFB_API_ERROR(apiHandle, "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'", - ALSACORE_SUBSCRIBE_VERB, + (subscriptionType == ALSACORE_SUBSCRIPTION) ? ALSACORE_SUBSCRIBE_VERB : ALSACORE_UNSUBSCRIBE_VERB, ALSACORE_API, returnedError ? returnedError : "not returned", returnedInfo ? returnedInfo : "not returned"); @@ -144,6 +313,47 @@ int InternalHalSubscribeToAlsaCardEvent(afb_api_t apiHandle, char *cardId) return err; } +int InternalHalSubscribeUnscubscribeToAlsacoreCardEvent(afb_api_t apiHandle, + char *cardId, + enum AlsacoreSubscribeUnsubscribeType subscriptionType) +{ + int err, wrapRet; + + json_object *subscribeQueryJ = NULL; + + wrapRet = wrap_json_pack(&subscribeQueryJ, + "{s:s, s:s}", + "event", ALSACORE_CARD_CONTROL_EVENT_NAME, + "devid", cardId); + if(wrapRet) { + AFB_API_ERROR(apiHandle, "Didn't succeed to allocate subscription query json object"); + return -1; + } + + err = InternalHalSubscribeUnscubscribeToAlsacoreEvent(apiHandle, subscribeQueryJ, subscriptionType); + if(err) { + AFB_API_ERROR(apiHandle, + "Error %i happened when tried to subscribe to %s card event", + err, + ALSACORE_API); + if(! subscribeQueryJ) + json_object_put(subscribeQueryJ); + return -2; + } + + return 0; +} + +int InternalHalSubscribeToAlsacoreCardEvent(afb_api_t apiHandle, char *cardId) +{ + return InternalHalSubscribeUnscubscribeToAlsacoreCardEvent(apiHandle, cardId, ALSACORE_SUBSCRIPTION); +} + +int InternalHalUnsubscribeFromAlsacoreCardEvent(afb_api_t apiHandle, char *cardId) +{ + return InternalHalSubscribeUnscubscribeToAlsacoreCardEvent(apiHandle, cardId, ALSACORE_UNSUBSCRIPTION); +} + int InternalHalGetAlsaCtlInfo(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *currentAlsaCtl, json_object **returnedDataJ) { int wrapRet; @@ -407,7 +617,7 @@ int InternalHalCreateAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalH } if(! alsaCtlToCreate->alsaCtlCreation) { - AFB_API_ERROR(apiHandle, "Alsa control data for creation structure is not available"); + AFB_API_ERROR(apiHandle, "Alsa control data structure for control creation is not available"); return -4; } @@ -469,6 +679,92 @@ int InternalHalCreateAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalH return err; } +int InternalHalDeleteAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *alsaCtlToDelete) +{ + int err = 0, wrapRet; + + char *returnedError = NULL, *returnedInfo = NULL, *removedControlName = NULL; + + json_object *queryJ, *responseJ = NULL; + + if(! apiHandle) { + AFB_API_ERROR(apiHandle, "Api handle not available"); + return -1; + } + + if(! cardId) { + AFB_API_ERROR(apiHandle, "Card id is not available"); + return -2; + } + + if(! alsaCtlToDelete) { + AFB_API_ERROR(apiHandle, "Alsa control data structure is not available"); + return -3; + } + + if(! alsaCtlToDelete->alsaCtlCreation) { + AFB_API_ERROR(apiHandle, "Alsa control data structure for deletion is not available"); + return -4; + } + + if(alsaCtlToDelete->alsaCtlCreation != alsaCtlToDelete->alsaCtlProperties) { + AFB_API_ERROR(apiHandle, "Alsa control was not previously created"); + return -5; + } + + wrapRet = wrap_json_pack(&queryJ, + "{s:s s:{s:s}}", + "devid", cardId, + "ctl", + "name", alsaCtlToDelete->name); + if(wrapRet) { + AFB_API_ERROR(apiHandle, "Didn't succeed to allocate delete ALSA control query json object"); + return -6; + } + + if(afb_api_call_sync(apiHandle, + ALSACORE_API, + ALSACORE_REMOVECTL_VERB, + queryJ, + &responseJ, + &returnedError, + &returnedInfo)) { + AFB_API_ERROR(apiHandle, + "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'", + ALSACORE_REMOVECTL_VERB, + ALSACORE_API, + returnedError ? returnedError : "not returned", + returnedInfo ? returnedInfo : "not returned"); + err = -6; + } + else if(! responseJ) { + AFB_API_ERROR(apiHandle, + "Seems that %s call to api %s succeed but no response was returned", + ALSACORE_REMOVECTL_VERB, + ALSACORE_API); + err = -7; + } + else if(wrap_json_unpack(responseJ, "{s:{s:s}}", "removed", "ctlName", &removedControlName)) { + AFB_API_ERROR(apiHandle, + "Can't get removed ALSA control name %s of %s api", + ALSACORE_REMOVECTL_VERB, + ALSACORE_API); + err = -8; + } + + AFB_API_DEBUG(apiHandle, "Control %s successfully removed", removedControlName); + + alsaCtlToDelete->alsaCtlProperties = NULL; + + if(responseJ) + json_object_put(responseJ); + + free(returnedError); + free(returnedInfo); + + return err; +} + /******************************************************************************* * Internals HAL - Alsacore controls request callback * ******************************************************************************/ diff --git a/src/4a-internals-hal/4a-internals-hal-alsacore-link.h b/src/4a-internals-hal/4a-internals-hal-alsacore-link.h index dccf266..39b535d 100644 --- a/src/4a-internals-hal/4a-internals-hal-alsacore-link.h +++ b/src/4a-internals-hal/4a-internals-hal-alsacore-link.h @@ -19,6 +19,7 @@ #define _INTERNALS_HAL_ALSACORE_LINK_INCLUDE_ #include <stdio.h> +#include <string.h> #include <wrap-json.h> @@ -29,26 +30,56 @@ #include <ctl-config.h> #include "4a-hal-utilities-alsa-data.h" +#include "4a-hal-utilities-data.h" -#define ALSACORE_API "alsacore" +#define ALSACORE_API "alsacore" +#define ALSACORE_API_NAME_LENGTH strlen(ALSACORE_API) -#define ALSACORE_SUBSCRIBE_VERB "subscribe" -#define ALSACORE_GETINFO_VERB "infoget" -#define ALSACORE_CTLGET_VERB "ctlget" -#define ALSACORE_CTLSET_VERB "ctlset" -#define ALSACORE_ADDCTL_VERB "addcustomctl" +#define ALSACORE_SUBSCRIBE_VERB "subscribe" +#define ALSACORE_UNSUBSCRIBE_VERB "unsubscribe" +#define ALSACORE_GETINFO_VERB "infoget" +#define ALSACORE_CTLGET_VERB "ctlget" +#define ALSACORE_CTLSET_VERB "ctlset" +#define ALSACORE_ADDCTL_VERB "addcustomctl" +#define ALSACORE_REMOVECTL_VERB "removecustomctl" -#define ALSACORE_CARD_CONTROL_EVENT_NAME "controls" +#define ALSACORE_CARD_CONTROL_EVENT_NAME "controls" + +#define ALSACORE_EVENT_NAME_BEGIN (ALSACORE_API_NAME_LENGTH + 1) +#define ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX "hw:" +#define ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX_LENGTH strlen(ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX) +#define ALSACORE_CARD_CONTROL_EVENT_BEGIN (ALSACORE_EVENT_NAME_BEGIN + ALSACORE_CARD_CONTROL_EVENT_NAME_PREFIX_LENGTH) + +// Enum for handled alsacore events + +enum aslacoreEventType { + ALSACORE_EVENT_CARD_CONTROL_CHANGE = 0, + ALSACORE_UNRECOGNIZED_EVENT = 1 +}; + +// Enum for the type of subscription/unsubscription to do with alsacore +enum AlsacoreSubscribeUnsubscribeType { + ALSACORE_SUBSCRIPTION = 0, + ALSACORE_UNSUBSCRIPTION = 1 +}; // Alsa control types map from string function snd_ctl_elem_type_t InternalHalMapsAlsaTypeToEnum(const char *label); +// Internals HAL alsacore events handler function +int InternalHalHandleAlsaCoreEvents(afb_api_t apiHandle, + const char *evtLabel, + json_object *eventJ, + struct HalData *currentHalData); + // Internals HAL alsacore calls funtions int InternalHalGetCardInfo(afb_api_t apiHandle, json_object *requestJ, json_object **responseJ); -int InternalHalSubscribeToAlsaCardEvent(afb_api_t apiHandle, char *cardId); +int InternalHalSubscribeToAlsacoreCardEvent(afb_api_t apiHandle, char *cardId); +int InternalHalUnsubscribeFromAlsacoreCardEvent(afb_api_t apiHandle, char *cardId); int InternalHalUpdateAlsaCtlProperties(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *currentAlsaCtl); int InternalHalSetAlsaCtlValue(afb_api_t apiHandle, char *cardId, int ctlId, json_object *valuesJ); int InternalHalCreateAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *alsaCtlToCreate); +int InternalHalDeleteAlsaCtl(afb_api_t apiHandle, char *cardId, struct InternalHalAlsaCtl *alsaCtlToDelete); // Internals HAL alsacore controls request callback void InternalHalActionOnAlsaCtl(afb_req_t request); diff --git a/src/4a-internals-hal/4a-internals-hal-api-loader.c b/src/4a-internals-hal/4a-internals-hal-api-loader.c index 5334bdf..b41c7b2 100644 --- a/src/4a-internals-hal/4a-internals-hal-api-loader.c +++ b/src/4a-internals-hal/4a-internals-hal-api-loader.c @@ -62,7 +62,7 @@ static afb_verb_t InternalHalApiStaticVerbs[] = { /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */ { .verb = "ping", .callback = HalUtlPing, .info = "Ping for test"}, - { .verb = "info", .callback = InternalHalInfo, .info = "List available streams/controls for this api" }, + { .verb = "info", .callback = InternalHalInfoVerb, .info = "List available dependencies/streams/controls for this api" }, { .verb = "subscribe", .callback = InternalHalSubscribe, .info = "Subscribe to event(s) for values changes (streams/controls) for this api" }, { .verb = "unsubscribe", .callback = InternalHalUnsubscribe, .info = "Unsubscribe to event(s) for values changes (streams/controls) for this api" }, { .verb = HAL_ALL_STREAMS_VERB, .callback = HalUtlActionOnAllStream, .info = "Send a stream action on all streams" }, @@ -199,6 +199,55 @@ int InternalHalCreateApi(afb_api_t apiHandle, char *path, struct HalMgrData *hal return 0; } +int InternalHalDeleteApi(afb_api_t apiHandle, struct cds_list_head *halDataListHead, struct HalData *toDeleteHalData) +{ + int err; + + char *toDeleteApiName; + + if(! apiHandle || ! toDeleteHalData) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); + return -1; + } + + err = InternalHalUnmanageAllHalMap(toDeleteHalData->internalHalData->apiHandle, + &toDeleteHalData->internalHalData->halMapListHead, + &toDeleteHalData->internalHalData->probedDevicesListHead); + if(err) { + AFB_API_ERROR(apiHandle, + "Error %i happened while trying to unmanage all halmap of '%s' hal api", + err, + toDeleteHalData->apiName); + return -2; + } + + toDeleteApiName = strdup(toDeleteHalData->apiName); + if(! toDeleteApiName) { + AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'apiName' string"); + return -3; + } + + err = HalUtlRemoveHalDataAndDeleteHalApi(toDeleteHalData->internalHalData->apiHandle, + toDeleteHalData, + halDataListHead); + if(err) { + AFB_API_ERROR(apiHandle, + "Error %i happened while trying to delete '%s' api and to remove all its data", + err, + toDeleteApiName); + free(toDeleteApiName); + return -4; + } + + AFB_API_NOTICE(apiHandle, + "Api '%s' and all its data has been deleted", + toDeleteApiName); + + free(toDeleteApiName); + + return 0; +} + int InternalHalCreateAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData) { int index; @@ -242,4 +291,43 @@ int InternalHalCreateAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData) } return 0; +} + +int InternalHalDeleteAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData) +{ + int err; + + char *toDeleteApiName; + + struct HalData *currentHalData; + + if(! apiHandle || ! halMgrData) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); + return -1; + } + + cds_list_for_each_entry(currentHalData, &halMgrData->halDataListHead, node) { + if(! currentHalData->apiName) + return -2; + + toDeleteApiName = strdup(currentHalData->apiName); + if(! toDeleteApiName) { + AFB_API_ERROR(apiHandle, "Didn't succeed to store (allocate) 'apiName' string"); + return -3; + } + + err = InternalHalDeleteApi(apiHandle, &halMgrData->halDataListHead, currentHalData); + if(err) { + AFB_API_ERROR(apiHandle, + "Error %i happened when tried to delete %s api", + err, + toDeleteApiName); + free(toDeleteApiName); + return -4; + } + + free(toDeleteApiName); + } + + return 0; }
\ No newline at end of file diff --git a/src/4a-internals-hal/4a-internals-hal-api-loader.h b/src/4a-internals-hal/4a-internals-hal-api-loader.h index fa878e2..2a47555 100644 --- a/src/4a-internals-hal/4a-internals-hal-api-loader.h +++ b/src/4a-internals-hal/4a-internals-hal-api-loader.h @@ -26,6 +26,8 @@ // Verbs that can be use to create api int InternalHalCreateApi(afb_api_t apiHandle, char *path, struct HalMgrData *halMgrData); +int InternalHalDeleteApi(afb_api_t apiHandle, struct cds_list_head *halDataListHead, struct HalData *toDeleteHalData); int InternalHalCreateAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData); +int InternalHalDeleteAllApi(afb_api_t apiHandle, struct HalMgrData *halMgrData); #endif /* _INTERNALS_HAL_API_LOADER_INCLUDE_ */
\ No newline at end of file diff --git a/src/4a-internals-hal/4a-internals-hal-cb.c b/src/4a-internals-hal/4a-internals-hal-cb.c index a81871c..c1078a9 100644 --- a/src/4a-internals-hal/4a-internals-hal-cb.c +++ b/src/4a-internals-hal/4a-internals-hal-cb.c @@ -37,15 +37,11 @@ void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json_object *eventJ) { - int numid, idx = 0, cardidx; + int error; CtlConfigT *ctrlConfig; - CtlSourceT source; struct HalData *currentHalData; - struct InternalHalAlsaMap *currentHalMapControl; - - json_object *valuesJ, *normalizedValuesJ; AFB_API_DEBUG(apiHandle, "Evtname=%s [msg=%s]", evtLabel, json_object_get_string(eventJ)); @@ -61,79 +57,31 @@ void InternalHalDispatchApiEvent(afb_api_t apiHandle, const char *evtLabel, json return; } - // Extract sound card index from event - while(evtLabel[idx] != '\0' && evtLabel[idx] != ':') - idx++; - - if(evtLabel[idx] != '\0' && - (sscanf(&evtLabel[idx + 1], "%d", &cardidx) == 1)) { - if(wrap_json_unpack(eventJ, "{s:i s:o}", "id", &numid, "val", &valuesJ)) { + if((strlen(evtLabel) > ALSACORE_API_NAME_LENGTH) && + ! strncmp(evtLabel, ALSACORE_API, ALSACORE_API_NAME_LENGTH)) { + error = InternalHalHandleAlsaCoreEvents(apiHandle, evtLabel, eventJ, currentHalData); + if(error < 0) { AFB_API_ERROR(apiHandle, - "Invalid alsacore event received label=%s value=%s", + "Error %i caught when tried to handle alsacore event evtname=%s [msg=%s]", + error, evtLabel, json_object_get_string(eventJ)); return; } - - if(cds_list_empty(¤tHalData->internalHalData->halMapListHead)) { - AFB_API_ERROR(apiHandle, "No halmap data is available, cannot handle alsacore event"); - return; + else if(error > 0) { + AFB_API_INFO(apiHandle, + "Warning %i raised when tried to handle alsacore event evtname=%s [msg=%s]", + error, + evtLabel, + json_object_get_string(eventJ)); } - - // 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->cardNb == cardidx && - currentHalMapControl->ctl.alsaCtlProperties && - currentHalMapControl->ctl.numid == numid) { - if(currentHalMapControl->action) { - memset(&source, 0, sizeof(CtlSourceT)); - source.uid = currentHalMapControl->action->uid; - source.api = currentHalMapControl->action->api; - - (void) ActionExecOne(&source, currentHalMapControl->action, valuesJ); - } - else if(currentHalMapControl->actionJ) { - AFB_API_WARNING(apiHandle, - "The alsa control id '%i' is corresponding to a known control which " - "has a registered action, but action is not ready to be executed", - numid); - return; - } - else { - AFB_API_NOTICE(apiHandle, - "The alsa control id '%i' is corresponding to a known control " - "but without any action registered", - numid); - } - - if(! currentHalMapControl->alsaControlEvent || - InternalHalConvertJsonValues(apiHandle, - currentHalMapControl->ctl.alsaCtlProperties, - valuesJ, - &normalizedValuesJ, - CONVERSION_ALSACORE_TO_NORMALIZED) || - (afb_event_push(currentHalMapControl->alsaControlEvent, normalizedValuesJ) < 0)) { - AFB_API_ERROR(apiHandle, - "Couldn't generate an event for known halmap %s (alsa control id %i)", - currentHalMapControl->uid, - currentHalMapControl->ctl.numid); - } - - return; - } + else { + return; } - - AFB_API_WARNING(apiHandle, - "Alsacore event with an unrecognized numid: %i, evtname=%s [msg=%s]", - numid, - evtLabel, - json_object_get_string(eventJ)); - - return; } AFB_API_INFO(apiHandle, - "Not an alsacore event '%s' [msg=%s]", + "Not an internally handled event '%s' [msg=%s]", evtLabel, json_object_get_string(eventJ)); @@ -141,559 +89,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 = calloc(1, 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 -10; - } - - 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 * ******************************************************************************/ @@ -1084,21 +479,17 @@ int InternalHalHandleInfoGetResponse(afb_api_t apiHandle, json_object *currentRe return ret; } -int InternalHalHandleOneHalDependencies(afb_api_t apiHandle, struct InternalHalProbedDevice **halDeviceToProbe) +int InternalHalHandleOneHalDependencies(afb_api_t apiHandle, struct InternalHalProbedDevice *currentDeviceToProbe) { int ret, toReturn = 0; - struct InternalHalProbedDevice *currentDeviceToProbe; - json_object *probedDeviceGetInfoResponseJ = NULL; - if(! apiHandle || ! halDeviceToProbe || ! *halDeviceToProbe) { + if(! apiHandle || ! currentDeviceToProbe) { AFB_API_ERROR(apiHandle, "Invalid argument(s)"); return -1; } - currentDeviceToProbe = *halDeviceToProbe; - if(! currentDeviceToProbe->uid || ! currentDeviceToProbe->requestedDeviceJ) { AFB_API_ERROR(apiHandle, "Specified device to probe is not valid (uid or request is not specified)"); @@ -1155,7 +546,7 @@ int InternalHalHandleOneHalDependencies(afb_api_t apiHandle, struct InternalHalP int InternalHalHandleHalDependencies(afb_api_t apiHandle, struct HalData *currentHalData, struct cds_list_head *halDevicesToProbeListHead, - enum DependenciesHandlingType dependenciesHandlingType, + enum DependencySelectionType dependencySelectionType, char *uid) { int ret, validatedDepedency, validatedDependenciesNumber = 0; @@ -1172,7 +563,7 @@ int InternalHalHandleHalDependencies(afb_api_t apiHandle, return 0; } - if(dependenciesHandlingType == UID_CORRESPONDING_DEPENDENCIES && + if(dependencySelectionType == UID_CORRESPONDING_DEPENDENCIES && ! uid) { AFB_API_ERROR(apiHandle, "Invalid uid"); return -2; @@ -1181,7 +572,7 @@ int InternalHalHandleHalDependencies(afb_api_t apiHandle, cds_list_for_each_entry(halCurrentDeviceToProbe, halDevicesToProbeListHead, node) { validatedDepedency = 0; - switch(dependenciesHandlingType) { + switch(dependencySelectionType) { case ALL_DEPENDENCIES: validatedDepedency = 1; break; @@ -1197,7 +588,7 @@ int InternalHalHandleHalDependencies(afb_api_t apiHandle, } if(validatedDepedency) { - ret = InternalHalHandleOneHalDependencies(apiHandle, &halCurrentDeviceToProbe); + ret = InternalHalHandleOneHalDependencies(apiHandle, halCurrentDeviceToProbe); if(ret < 0) { AFB_API_ERROR(apiHandle, "Error %i happened when tried to handle device to probe with uid:'%s' and request:'%s'", @@ -1271,25 +662,765 @@ int InternalHalHalDependenciesConfig(afb_api_t apiHandle, CtlSectionT *section, } /******************************************************************************* - * Internals HAL verbs functions * + * Internals HAL - 'halmixer' section parsing/handling functions * ******************************************************************************/ -void InternalHalInfo(afb_req_t request) +int InternalHalHalMixerConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *MixerJ) { - char *apiToCall, *returnedError = NULL, *returnedInfo = NULL; + int err = 0, wrapRet; + + char *mixerApiName, *prefix = NULL; - afb_api_t apiHandle; CtlConfigT *ctrlConfig; + struct HalData *currentHalData; + struct InternalHalProbedDevice *currentProbedDevice; + + 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) { + cds_list_for_each_entry(currentProbedDevice, ¤tHalData->internalHalData->probedDevicesListHead, node) { + if(! currentProbedDevice->deviceData) { + currentProbedDevice->mixerLinkStatus = DEPENDENCY_MIXER_LINK_USELESS; + continue; + } + + if(currentProbedDevice->mixerLinkStatus == DEPENDENCY_MIXER_ATTACH_SUCCEED) { + AFB_API_WARNING(apiHandle, "Mixer status is already initialized, moving to next one"); + continue; + } + + err = InternalHalAttachDependencyToMixer(apiHandle, currentProbedDevice); + if(err) { + AFB_API_ERROR(apiHandle, "Error %i while attaching to mixer", err); + return -8; + } + } + + currentHalData->status = HAL_STATUS_READY; + } + + 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(InternalHalSubscribeToAlsacoreCardEvent(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 InternalHalUnmanageOneHalMapObject(afb_api_t apiHandle, struct InternalHalAlsaMap *halMapData) +{ + int err; + + char cardNbString[6]; + + if(! apiHandle || ! halMapData) { + AFB_API_ERROR(apiHandle, "Invalid argument(s)"); + return -1; + } + + snprintf(cardNbString, sizeof(cardNbString), "hw:%i", halMapData->cardNb); + + err = afb_api_del_verb(apiHandle, halMapData->uid, NULL); + if(err) + AFB_API_WARNING(apiHandle, + "Error %i returned when tried to remove halmap verb %s, " + "verb may have not been added before", + err, + halMapData->uid); + + free(halMapData->action); + halMapData->action = NULL; + + if(halMapData->ctl.alsaCtlCreation) { + err = InternalHalDeleteAlsaCtl(apiHandle, cardNbString, &halMapData->ctl); + if(err) + AFB_API_WARNING(apiHandle, + "Error %i returned when tried to custom ALSA control '%s', " + "custom control may have not been added before", + err, + halMapData->ctl.name); + } + else { + free(halMapData->ctl.alsaCtlProperties); + halMapData->ctl.alsaCtlProperties = NULL; + } + + if(afb_event_is_valid(halMapData->alsaControlEvent)) { + afb_event_unref(halMapData->alsaControlEvent); + halMapData->alsaControlEvent = NULL; + } + + halMapData->cardNb = HAL_UNKNOWN_DEVICE; + + return 0; +} + +int InternalHalProcessDependencyRelatedHalmap(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead, + char *targetedDependency, + enum DependencySelectionType halMapSelectionType, + enum HalMapProcessingType halMapProcessingType) +{ + int err = 0, validatedHalMap; + + struct InternalHalAlsaMap *currentHalMapData; + + if(cds_list_empty(halMapListHead)) { + AFB_API_ERROR(apiHandle, "HalMap list is empty, nothing to process"); + return 0; + } + + if(halMapSelectionType == UID_CORRESPONDING_DEPENDENCIES && + ! targetedDependency) { + AFB_API_ERROR(apiHandle, "Invalid targeted dependency"); + return -1; + } + + cds_list_for_each_entry(currentHalMapData, halMapListHead, node) { + validatedHalMap = 0; + switch(halMapSelectionType) { + 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 %s because corresponding " + "dependency ('%s') card is not available at the moment", + currentHalMapData->uid, + (halMapProcessingType == HANDLE_SELECTED_HALMAP) ? "handled" : "unmanaged", + currentHalMapData->targetedDependency); + continue; + } + + if(halMapProcessingType == HANDLE_SELECTED_HALMAP) + err = InternalHalHandleOneHalMapObject(apiHandle, currentHalMapData); + else + err = InternalHalUnmanageOneHalMapObject(apiHandle, currentHalMapData); + + if(err) { + AFB_API_ERROR(apiHandle, + "Error %i was returned when tried to %s halmap control with uid %s", + err, + (halMapProcessingType == HANDLE_SELECTED_HALMAP) ? "handle" : "unmanage", + currentHalMapData->uid); + return -3; + } + } + } + + return 0; +} + +int InternalHalHandleDependencyRelatedHalmap(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead, + char *targetedDependency) +{ + return InternalHalProcessDependencyRelatedHalmap(apiHandle, + halMapListHead, + halDevicesToProbeListHead, + targetedDependency, + UID_CORRESPONDING_DEPENDENCIES, + HANDLE_SELECTED_HALMAP); +} + +int InternalHalUnmanageDependencyRelatedHalmap(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead, + char *targetedDependency) +{ + return InternalHalProcessDependencyRelatedHalmap(apiHandle, + halMapListHead, + halDevicesToProbeListHead, + targetedDependency, + UID_CORRESPONDING_DEPENDENCIES, + UNMANAGE_SELECTED_HALMAP); +} + +int InternalHalHandleAllHalMap(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead) +{ + return InternalHalProcessDependencyRelatedHalmap(apiHandle, + halMapListHead, + halDevicesToProbeListHead, + NULL, + ALL_DEPENDENCIES, + HANDLE_SELECTED_HALMAP); +} + +int InternalHalUnmanageAllHalMap(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead) +{ + return InternalHalProcessDependencyRelatedHalmap(apiHandle, + halMapListHead, + halDevicesToProbeListHead, + NULL, + ALL_DEPENDENCIES, + UNMANAGE_SELECTED_HALMAP); +} + +int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *AlsaMapJ) +{ + CtlConfigT *ctrlConfig; struct HalData *currentHalData; - json_object *requestJson, + 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(InternalHalHandleAllHalMap(apiHandle, + ¤tHalData->internalHalData->halMapListHead, + ¤tHalData->internalHalData->probedDevicesListHead)) { + AFB_API_ERROR(apiHandle, "Failed to handle 'halmap' section"); + return -5; + } + + return 0; +} + +/******************************************************************************* + * Internals HAL verbs functions * + ******************************************************************************/ + +int GenerateInternalHalInfoJson(afb_api_t apiHandle, + struct HalData *currentHalData, + json_object *requestJ, + json_object **returnedJ) +{ + int wrapRet, verboseLevel = 2; + + char *apiToCall, *returnedError = NULL, *returnedInfo = NULL; + + json_object *mixerRequestJ = NULL, *toReturnJ = NULL, *requestAnswer, *streamsArray, *controlsArray, *dependenciesArray; + if(! apiHandle || ! currentHalData || ! returnedJ) + return -1; + + *returnedJ = NULL; + + if(requestJ) { + wrapRet = wrap_json_unpack(requestJ, + "{s?:i, s?:o !}", + "verbose", &verboseLevel, + "mixer", &mixerRequestJ); + if(wrapRet) + return -2; + } + + if(mixerRequestJ && + json_object_is_type(mixerRequestJ, json_type_object) && + json_object_get_object(mixerRequestJ)->count > 0) { + apiToCall = currentHalData->internalHalData->mixerApiName; + if(! apiToCall) + return-3; + + if(InternalHalGetInfoFromMixer(apiHandle, + apiToCall, + mixerRequestJ, + &toReturnJ, + &returnedError, + &returnedInfo)) + return -4; + + *returnedJ = toReturnJ; + return 0; + } + + requestAnswer = json_object_new_object(); + + if(verboseLevel >= 0) { + dependenciesArray = HalUtlGetJsonArrayForAllDependencies(apiHandle, + ¤tHalData->internalHalData->probedDevicesListHead, + DEPENDENCY_FULL_JSON); + if(dependenciesArray) + json_object_object_add(requestAnswer, "dependencies", dependenciesArray); + } + + if(verboseLevel >= 1) { + controlsArray = HalUtGetJsonArrayForAllHalMapControls(apiHandle, + ¤tHalData->internalHalData->halMapListHead); + if(controlsArray) + json_object_object_add(requestAnswer, "controls", controlsArray); + } + + if(verboseLevel >= 2) { + streamsArray = HalUtlGetJsonArrayForAllMixersData(apiHandle, + ¤tHalData->internalHalData->streamsDataListHead); + if(! streamsArray) + streamsArray = json_object_new_array(); // Always return an array for 4a-hl-api (to prevent segfault) + json_object_object_add(requestAnswer, "streams", streamsArray); + } + + if(! json_object_get_object(requestAnswer)->count) { + json_object_put(requestAnswer); + requestAnswer = NULL; + } + + *returnedJ = requestAnswer; + return 0; +} + +void InternalHalInfoVerb(afb_req_t request) +{ + int err; + + afb_api_t apiHandle; + CtlConfigT *ctrlConfig; + + struct HalData *currentHalData; + + json_object *requestJ, *toReturnJ; + apiHandle = afb_req_get_api(request); if(! apiHandle) { afb_req_fail(request, "api_handle", "Can't get current internal hal api handle"); @@ -1308,55 +1439,19 @@ void InternalHalInfo(afb_req_t request) return; } - requestJson = afb_req_json(request); - if(! requestJson) { - AFB_REQ_NOTICE(request, "Can't get request json"); - } - else if(json_object_is_type(requestJson, json_type_object) && json_object_get_object(requestJson)->count > 0) { - apiToCall = currentHalData->internalHalData->mixerApiName; - if(! apiToCall) { - afb_req_fail(request, "mixer_api", "Can't get mixer api"); - return; - } - - if(InternalHalGetInfoFromMixer(apiHandle, apiToCall, requestJson, &toReturnJ, &returnedError, &returnedInfo)) { - afb_req_fail_f(request, - "mixer_info", - "Call to mixer info verb didn't succeed with status '%s' and info '%s'", - returnedError ? returnedError : "not returned", - returnedInfo ? returnedInfo : "not returned"); - return; - } + requestJ = afb_req_json(request); - afb_req_success(request, toReturnJ, "Mixer requested data"); + err = GenerateInternalHalInfoJson(apiHandle, currentHalData, requestJ, &toReturnJ); + if(err) { + afb_req_fail_f(request, + "get_info_fail", + "Error %i happened when tried to get json info for request json '%s'", + err, + json_object_get_string(requestJ)); return; } - requestAnswer = json_object_new_object(); - - dependenciesArray = HalUtlGetJsonArrayForAllDependencies(apiHandle, - ¤tHalData->internalHalData->probedDevicesListHead, - DEPENDENCY_FULL_JSON); - if(dependenciesArray) - json_object_object_add(requestAnswer, "dependencies", dependenciesArray); - - streamsArray = HalUtlGetJsonArrayForAllMixersData(apiHandle, - ¤tHalData->internalHalData->streamsDataListHead); - if(! streamsArray) - streamsArray = json_object_new_array(); // Always return an array for 4a-hl-api (to prevent segfault) - json_object_object_add(requestAnswer, "streams", streamsArray); - - controlsArray = HalUtGetJsonArrayForAllHalMapControls(apiHandle, - ¤tHalData->internalHalData->halMapListHead); - if(controlsArray) - json_object_object_add(requestAnswer, "controls", controlsArray); - - if(! json_object_get_object(requestAnswer)->count) { - json_object_put(requestAnswer); - requestAnswer = NULL; - } - - afb_req_success(request, requestAnswer, "Requested data"); + afb_req_success(request, toReturnJ, "Requested data"); } void InternalHalSubscribeUnsubscribe(afb_req_t request, enum SubscribeUnsubscribeType subscribeUnsubscribeType) diff --git a/src/4a-internals-hal/4a-internals-hal-cb.h b/src/4a-internals-hal/4a-internals-hal-cb.h index 4864d46..2224046 100644 --- a/src/4a-internals-hal/4a-internals-hal-cb.h +++ b/src/4a-internals-hal/4a-internals-hal-cb.h @@ -24,12 +24,18 @@ #include <ctl-config.h> -// Enum for the type of dependencies handling -enum DependenciesHandlingType { +// Enum for to define which type of dependency selection we want to use +enum DependencySelectionType { ALL_DEPENDENCIES = 0, UID_CORRESPONDING_DEPENDENCIES = 1 }; +// Enum to define if to to handle or to unmanage a selected halmap +enum HalMapProcessingType { + HANDLE_SELECTED_HALMAP = 0, + UNMANAGE_SELECTED_HALMAP = 1 +}; + // Enum for the type of subscription enum SubscribeUnsubscribeType { SUBSCRIPTION = 0, @@ -39,22 +45,40 @@ 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, struct cds_list_head *halDevicesToProbeListHead, - enum DependenciesHandlingType dependenciesHandlingType, + enum DependencySelectionType dependenciesSelectionType, 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 InternalHalHandleDependencyRelatedHalmap(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead, + char *targetedDependency); +int InternalHalUnmanageDependencyRelatedHalmap(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead, + char *targetedDependency); +int InternalHalHandleAllHalMap(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead); +int InternalHalUnmanageAllHalMap(afb_api_t apiHandle, + struct cds_list_head *halMapListHead, + struct cds_list_head *halDevicesToProbeListHead); +int InternalHalHalMapConfig(afb_api_t apiHandle, CtlSectionT *section, json_object *halMapJ); + // Internals HAL verbs functions -void InternalHalInfo(afb_req_t request); +int GenerateInternalHalInfoJson(afb_api_t apiHandle, + struct HalData *currentHalData, + json_object *requestJ, + json_object **returnedJ); +void InternalHalInfoVerb(afb_req_t request); void InternalHalSubscribe(afb_req_t request); void InternalHalUnsubscribe(afb_req_t request); diff --git a/src/4a-internals-hal/4a-internals-hal-mixer-link.c b/src/4a-internals-hal/4a-internals-hal-mixer-link.c index 56dc840..19fb3a0 100644 --- a/src/4a-internals-hal/4a-internals-hal-mixer-link.c +++ b/src/4a-internals-hal/4a-internals-hal-mixer-link.c @@ -142,7 +142,7 @@ int InternalHalHandleMixerAttachResponse(afb_api_t apiHandle, struct InternalHal return 0; } -int InternalHalAttachToMixer(afb_api_t apiHandle) +int InternalHalAttachDependencyToMixer(afb_api_t apiHandle, struct InternalHalProbedDevice *probedDeviceToAttach) { int err = 0, mixerError; @@ -194,9 +194,10 @@ int InternalHalAttachToMixer(afb_api_t apiHandle) return -6; } - dependencyJ = HalUtlGetJsonArrayForAllDependencies(apiHandle, - ¤tHalData->internalHalData->probedDevicesListHead, - DEPENDENCY_COMPACT_JSON); + dependencyJ = HalUtlGetJsonArrayForAllDependenciesInfoWithHandledDependency(apiHandle, + ¤tHalData->internalHalData->probedDevicesListHead, + DEPENDENCY_COMPACT_JSON, + probedDeviceToAttach->uid); if(! dependencyJ) { AFB_API_ERROR(apiHandle, "Didn't succeed to generate available dependencies compact json array"); return -7; @@ -251,10 +252,14 @@ int InternalHalAttachToMixer(afb_api_t apiHandle) MIXER_ATTACH_VERB, apiToCall, json_object_get_string(responseJ)); - currentHalData->status = HAL_STATUS_READY; } } + if(err) + probedDeviceToAttach->mixerLinkStatus = DEPENDENCY_MIXER_ATTACH_FAILED; + else + probedDeviceToAttach->mixerLinkStatus = DEPENDENCY_MIXER_ATTACH_SUCCEED; + if(responseJ) json_object_put(responseJ); @@ -264,6 +269,87 @@ int InternalHalAttachToMixer(afb_api_t apiHandle) return err; } +int InternalHalDetachDependencyToMixer(afb_api_t apiHandle, struct InternalHalProbedDevice *probedDeviceToDetach) +{ + int err, toReturn = 0; + + char *apiToCall, *returnedError = NULL, *returnedInfo = NULL; + + CtlConfigT *ctrlConfig; + + struct HalData *currentHalData; + + json_object *requestJ, *dependencyJ, *responseJ = NULL; + + if(! apiHandle) { + AFB_API_ERROR(apiHandle, "Can't get current internal hal api handle"); + return -1; + } + + ctrlConfig = (CtlConfigT *) afb_api_get_userdata(apiHandle); + if(! ctrlConfig) { + AFB_API_ERROR(apiHandle, "Can't get current internal hal controller config"); + return -2; + } + + currentHalData = (struct HalData *) getExternalData(ctrlConfig); + if(! currentHalData) { + AFB_API_ERROR(apiHandle, "Can't get current internal hal controller data"); + return -3; + } + + apiToCall = currentHalData->internalHalData->mixerApiName; + if(! apiToCall) { + AFB_API_ERROR(apiHandle, "Can't get mixer api"); + return -4; + } + + dependencyJ = HalUtlGetJsonForSpecificDependenciesUsingUid(apiHandle, + ¤tHalData->internalHalData->probedDevicesListHead, + probedDeviceToDetach->uid, + DEPENDENCY_COMPACT_JSON); + if(! dependencyJ) { + AFB_API_ERROR(apiHandle, "Didn't succeed to get dependency %s compact json array", probedDeviceToDetach->uid); + return -5; + } + + err = wrap_json_pack(&requestJ, "{s:o}", "dependencies", dependencyJ); + if(err) { + AFB_API_ERROR(apiHandle, + "Didn't succeed to allocate detach dependency %s request json", probedDeviceToDetach->uid); + return -6; + } + + if(afb_api_call_sync(apiHandle, + apiToCall, + MIXER_DETACH_VERB, + requestJ, + &responseJ, + &returnedError, + &returnedInfo)) { + AFB_API_ERROR(apiHandle, + "Something went wrong during call to verb '%s' of api '%s' with error '%s' and info '%s'", + MIXER_DETACH_VERB, + apiToCall, + returnedError ? returnedError : "not returned", + returnedInfo ? returnedInfo : "not returned"); + toReturn = -7; + } + + if(toReturn) + probedDeviceToDetach->mixerLinkStatus = DEPENDENCY_MIXER_DETACH_FAILED; + else + probedDeviceToDetach->mixerLinkStatus = DEPENDENCY_MIXER_DETACH_SUCCEED; + + if(responseJ) + json_object_put(responseJ); + + free(returnedError); + free(returnedInfo); + + return toReturn; +} + int InternalHalGetInfoFromMixer(afb_api_t apiHandle, char *apiToCall, json_object *requestJson, diff --git a/src/4a-internals-hal/4a-internals-hal-mixer-link.h b/src/4a-internals-hal/4a-internals-hal-mixer-link.h index 7132aca..af80844 100644 --- a/src/4a-internals-hal/4a-internals-hal-mixer-link.h +++ b/src/4a-internals-hal/4a-internals-hal-mixer-link.h @@ -29,12 +29,14 @@ #include "4a-hal-utilities-data.h" #define MIXER_ATTACH_VERB "attach" +#define MIXER_DETACH_VERB "detach" #define MIXER_INFO_VERB "info" #define HAL_ALL_STREAMS_VERB "all-streams" // Internals HAL handle mixer calls functions -int InternalHalAttachToMixer(afb_api_t apiHandle); +int InternalHalAttachDependencyToMixer(afb_api_t apiHandle, struct InternalHalProbedDevice *probedDeviceToAttach); +int InternalHalDetachDependencyToMixer(afb_api_t apiHandle, struct InternalHalProbedDevice *probedDeviceToDetach); int InternalHalGetInfoFromMixer(afb_api_t apiHandle, char *apiToCall, json_object *requestJson, |