diff options
Diffstat (limited to 'src/4a-internals-hal/4a-internals-hal-alsacore-link.c')
-rw-r--r-- | src/4a-internals-hal/4a-internals-hal-alsacore-link.c | 320 |
1 files changed, 308 insertions, 12 deletions
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 * ******************************************************************************/ |