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