aboutsummaryrefslogtreecommitdiffstats
path: root/4a-hal/4a-hal-controllers
diff options
context:
space:
mode:
authorJonathan Aillet <jonathan.aillet@iot.bzh>2018-12-17 19:42:32 +0100
committerJonathan Aillet <jonathan.aillet@iot.bzh>2018-12-20 11:17:21 +0100
commitec6351b3cc30bb0d0db61fa1fe0e22908f5210a8 (patch)
tree8670cf22ac2fbb88db127c8eedf73727cbfc657b /4a-hal/4a-hal-controllers
parenta48048548e85244a66e830523ebcbeb7f709ad60 (diff)
Add streams events generation for each hal
Each hal will now have subscribe/unsubscribe verbs to allow other bindings to be notified when a modification (volume, mute, ...) happened on a stream. Bug-AGL: SPEC-1313 Change-Id: If68d3b4b4e39385c1fffdd04b9f3e2b7fa5ae108 Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
Diffstat (limited to '4a-hal/4a-hal-controllers')
-rw-r--r--4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.c2
-rw-r--r--4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c156
-rw-r--r--4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h8
-rw-r--r--4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.c8
-rw-r--r--4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.h1
5 files changed, 175 insertions, 0 deletions
diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.c b/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.c
index 390431e..cffc447 100644
--- a/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.c
+++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-api-loader.c
@@ -62,6 +62,8 @@ static AFB_ApiVerbs CtlHalApiStaticVerbs[] =
{
/* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */
{ .verb = "info", .callback = HalCtlsInfo, .info = "List available streams/playbacks/captures/controls for this api" },
+ { .verb = "subscribe", .callback = HalCtlsSubscribe, .info = "Subscribe to event(s) for values changes (streams/playbacks/captures/controls) for this api" },
+ { .verb = "unsubscribe", .callback = HalCtlsUnsubscribe, .info = "Unsubscribe to event(s) for values changes (streams/playbacks/captures/controls) for this api" },
{ .verb = NULL } // Marker for end of the array
};
diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c b/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c
index 9e25c61..1f51fba 100644
--- a/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c
+++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.c
@@ -501,6 +501,14 @@ void HalCtlsActionOnMixer(AFB_ReqT request, enum ActionOnMixerType actionType)
return;
}
+ // TBD JAI : When mixer events will be available, use them instead of generating events at calls
+ if((actionType == ACTION_ON_MIXER_STREAM ||
+ actionType == ACTION_ON_MIXER_ALL_STREAM) &&
+ ((! currentMixerData->event) ||
+ (AFB_EventPush(currentMixerData->event, json_object_get(responseJ)) < 0))) {
+ AFB_ApiError(apiHandle, "Couldn't generate an event for stream %s", currentMixerData->verb);
+ }
+
switch(actionType) {
case ACTION_ON_MIXER_STREAM:
toReturnJ = json_object_get(responseJ);
@@ -751,4 +759,152 @@ void HalCtlsInfo(AFB_ReqT request)
"controls", controlsArray);
AFB_ReqSuccess(request, requestAnswer, "Requested data");
+}
+
+void HalCtlsSubscribeUnsubscribe(AFB_ReqT request, enum SubscribeUnsubscribeType subscribeUnsubscribeType)
+{
+ int arrayIdx, searchIdx, count, subscriptionFound, subscriptionDoneNb = 0;
+
+ char *currentSubscriptionString;
+
+ AFB_ApiT apiHandle;
+ CtlConfigT *ctrlConfig;
+
+ struct SpecificHalData *currentCtlHalData;
+ struct CtlHalMixerDataT *halStreamsData;
+
+ json_object *requestJson, *requestedSubscriptionsJ, *requestedSubscriptionJ = NULL;
+ json_type requestJsonType;
+
+ apiHandle = (AFB_ApiT) AFB_ReqGetApi(request);
+ if(! apiHandle) {
+ AFB_ReqFail(request, "api_handle", "Can't get current hal controller api handle");
+ return;
+ }
+
+ ctrlConfig = (CtlConfigT *) AFB_ApiGetUserData(apiHandle);
+ if(! ctrlConfig) {
+ AFB_ReqFail(request, "hal_controller_config", "Can't get current hal controller config");
+ return;
+ }
+
+ currentCtlHalData = (struct SpecificHalData *) getExternalData(ctrlConfig);
+ if(! currentCtlHalData) {
+ AFB_ReqFail(request, "hal_controller_data", "Can't get current hal controller data");
+ return;
+ }
+
+ if(! currentCtlHalData->ctlHalSpecificData) {
+ AFB_ReqFail(request, "hal_controller_data", "Can't get current hal specific data");
+ return;
+ }
+
+ halStreamsData = &currentCtlHalData->ctlHalSpecificData->ctlHalStreamsData;
+
+ requestJson = AFB_ReqJson(request);
+ if(! requestJson) {
+ AFB_ReqFail(request, "request_json", "Can't get request json");
+ }
+
+ if(wrap_json_unpack(requestJson, "{s:o}", "events", &requestedSubscriptionsJ)) {
+ AFB_ReqFail(request, "request_json", "Request json invalid");
+ return;
+ }
+
+ requestJsonType = json_object_get_type(requestedSubscriptionsJ);
+ switch(requestJsonType) {
+ case json_type_string:
+ count = 1;
+ requestedSubscriptionJ = requestedSubscriptionsJ;
+ break;
+
+ case json_type_array:
+ count = (int) json_object_array_length(requestedSubscriptionsJ);
+ break;
+
+ default:
+ AFB_ReqFail(request, "request_json", "Request json invalid");
+ return;
+ }
+
+ for(arrayIdx = 0; arrayIdx < count; arrayIdx++) {
+ if(requestJsonType == json_type_array) {
+ requestedSubscriptionJ = json_object_array_get_idx(requestedSubscriptionsJ, arrayIdx);
+ if(! json_object_is_type(requestedSubscriptionJ, json_type_string)) {
+ AFB_ReqFailF(request, "request_json", "Request json number %i in array invalid", arrayIdx);
+ return;
+ }
+ }
+
+ subscriptionFound = 0;
+ currentSubscriptionString = (char *) json_object_get_string(requestedSubscriptionJ);
+
+ searchIdx = 0;
+ while((searchIdx < halStreamsData->count) &&
+ (! subscriptionFound)) {
+ if(! strcasecmp(currentSubscriptionString, halStreamsData->data[searchIdx].verb)) {
+ if(halStreamsData->data[searchIdx].event &&
+ subscribeUnsubscribeType == SUBSCRIPTION &&
+ afb_req_subscribe(request, halStreamsData->data[searchIdx].event)) {
+ AFB_ReqFailF(request,
+ "request_stream_event",
+ "Error while trying to subscribe to %s stream events",
+ halStreamsData->data[searchIdx].verb);
+ return;
+ }
+ else if(halStreamsData->data[searchIdx].event &&
+ subscribeUnsubscribeType == UNSUBSCRIPTION &&
+ afb_req_unsubscribe(request, halStreamsData->data[searchIdx].event)) {
+ AFB_ReqFailF(request,
+ "request_stream_event",
+ "Error while trying to unsubscribe to %s stream events",
+ halStreamsData->data[searchIdx].verb);
+ return;
+ }
+
+ subscriptionFound = 1;
+ subscriptionDoneNb++;
+
+ break;
+ }
+
+ searchIdx++;
+ }
+ }
+
+ if(subscriptionDoneNb == 0)
+ AFB_ReqFailF(request,
+ "events_not_found",
+ "%s failed, event(s) were not found",
+ subscribeUnsubscribeType == SUBSCRIPTION ? "Subscription" : "Unsubscription");
+ if(subscriptionDoneNb == count)
+ AFB_ReqSuccessF(request,
+ json_object_new_int(subscriptionDoneNb),
+ "%s succeed for all the %i events requested",
+ subscribeUnsubscribeType == SUBSCRIPTION ? "Subscription" : "Unsubscription",
+ subscriptionDoneNb);
+ else if(subscriptionDoneNb < count)
+ AFB_ReqSuccessF(request,
+ json_object_new_int(subscriptionDoneNb),
+ "%s succeed but only to %i events requested out of %i",
+ subscribeUnsubscribeType == SUBSCRIPTION ? "Subscription" : "Unsubscription",
+ subscriptionDoneNb,
+ count);
+ else
+ AFB_ReqSuccessF(request,
+ json_object_new_int(subscriptionDoneNb),
+ "%s succeed but to more events than requested (%i out of %i)",
+ subscribeUnsubscribeType == SUBSCRIPTION ? "Subscription" : "Unsubscription",
+ subscriptionDoneNb,
+ count);
+}
+
+void HalCtlsSubscribe(AFB_ReqT request)
+{
+ HalCtlsSubscribeUnsubscribe(request, SUBSCRIPTION);
+}
+
+void HalCtlsUnsubscribe(AFB_ReqT request)
+{
+ HalCtlsSubscribeUnsubscribe(request, UNSUBSCRIPTION);
} \ No newline at end of file
diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h b/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h
index f1766ae..d9b4411 100644
--- a/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h
+++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-cb.h
@@ -32,6 +32,12 @@ enum ActionOnMixerType {
ACTION_ON_MIXER_ALL_STREAM = 4
};
+// Enum for the type of subscription/subscription
+enum SubscribeUnsubscribeType {
+ SUBSCRIPTION = 1,
+ UNSUBSCRIPTION = 2
+};
+
// HAL controller event handler function
void HalCtlsDispatchApiEvent(AFB_ApiT apiHandle, const char *evtLabel, json_object *eventJ);
@@ -45,5 +51,7 @@ void HalCtlsActionOnPlayback(AFB_ReqT request);
void HalCtlsActionOnCapture(AFB_ReqT request);
void HalCtlsActionOnAllStream(AFB_ReqT request);
void HalCtlsInfo(AFB_ReqT request);
+void HalCtlsSubscribe(AFB_ReqT request);
+void HalCtlsUnsubscribe(AFB_ReqT request);
#endif /* _HALMGR_CB_INCLUDE_ */ \ No newline at end of file
diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.c b/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.c
index 165bb42..807dbb8 100644
--- a/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.c
+++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.c
@@ -107,6 +107,14 @@ int HalCtlsHandleMixerData(AFB_ApiT apiHandle, struct CtlHalMixerDataT *currentM
currentMixerDataT->data[idx].verb);
err += (int) MIXER_ERROR_STREAM_VERB_NOT_CREATED;
}
+
+ currentMixerDataT->data[idx].event = AFB_EventMake(apiHandle, currentMixerDataT->data[idx].verb);
+ if(! AFB_EventIsValid(currentMixerDataT->data[idx].event)) {
+ AFB_ApiError(apiHandle,
+ "Error while creating event for stream : '%s'",
+ currentMixerDataT->data[idx].verb);
+ err += (int) MIXER_ERROR_STREAM_EVENT_NOT_CREATED;
+ }
}
else if(dataType == MIXER_DATA_PLAYBACKS) {
currentMixerDataT->data[idx].verb = strdup(HAL_PLAYBACK_ID);
diff --git a/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.h b/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.h
index 7deef1b..165b70d 100644
--- a/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.h
+++ b/4a-hal/4a-hal-controllers/4a-hal-controllers-mixer-link.h
@@ -53,6 +53,7 @@ enum MixerStatus {
MIXER_ERROR_DATA_NAME_UNAVAILABLE=-10,
MIXER_ERROR_DATA_CARDID_UNAVAILABLE=-1000,
MIXER_ERROR_STREAM_VERB_NOT_CREATED =-100000,
+ MIXER_ERROR_STREAM_EVENT_NOT_CREATED =-10000000
};
// HAL controllers handle mixer calls functions