aboutsummaryrefslogtreecommitdiffstats
path: root/src/4a-internals-hal/4a-internals-hal-alsacore-link.c
diff options
context:
space:
mode:
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.c320
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(&currentHalData->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, &currentHalData->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 *
******************************************************************************/