diff options
m--------- | afb-utilities | 0 | ||||
m--------- | conf.d/app-templates | 0 | ||||
-rw-r--r-- | hook-plugin/PolicyHookCb.c | 72 | ||||
-rw-r--r-- | hook-plugin/README.md | 108 |
4 files changed, 126 insertions, 54 deletions
diff --git a/afb-utilities b/afb-utilities -Subproject fd86e75feab42c0d0676a80e9aa415fa507e9a5 +Subproject 77c12fc3a44ce4fd1f4a83019547190d0f44549 diff --git a/conf.d/app-templates b/conf.d/app-templates -Subproject 6230618d8e66dc4902e43e7e85fa03317f209a0 +Subproject c881d86fc8852a2b2215856d3503aba192c0f4e diff --git a/hook-plugin/PolicyHookCb.c b/hook-plugin/PolicyHookCb.c index b751ed6..1ca6670 100644 --- a/hook-plugin/PolicyHookCb.c +++ b/hook-plugin/PolicyHookCb.c @@ -30,6 +30,8 @@ #define _GNU_SOURCE #include <stdio.h> +#include <alloca.h> + #include <alsa/asoundlib.h> #include <alsa/conf.h> #include <alsa/pcm.h> @@ -65,15 +67,12 @@ // Currently not implemented #define UNUSED_ARG(x) UNUSED_ ## x __attribute__((__unused__)) -static void OnSuccessCB(void* UNUSED_ARG(handle) , void* UNUSED_ARG(request), struct json_object* UNUSED_ARG(reslt), const char* UNUSED_ARG(info)) {} -static void OnFailureCB(void* UNUSED_ARG(closure), void* UNUSED_ARG(request), const char *UNUSED_ARG(status), const char *UNUSED_ARG(info)) {} typedef struct { const char *openVerb; const char *closeVerb; json_object *queryJ; long timeout; - size_t length; sd_event_source *evtSource; char *callIdTag; @@ -169,46 +168,55 @@ OnErrorExit: return; } - -/* the callback interface for pws */ -static struct afb_proto_ws_client_itf itf = { - .on_reply_success = OnSuccessCB, - .on_reply_fail = OnFailureCB, - .on_event_create = NULL, - .on_event_remove = NULL, - .on_event_subscribe = NULL, - .on_event_unsubscribe = NULL, - .on_event_push = OnEventCB, - .on_event_broadcast = NULL, - .on_subcall = NULL, -}; - -void OnResponseCB(void *handle, struct afb_wsj1_msg *msg) { +static void OnSuccessCB(void* UNUSED_ARG(ctx) , void* handle, json_object* responseJ, const char* info) { + afbRequestT *afbRequest= (afbRequestT*)handle; afbClientT *afbClient=(afbClientT*)afbRequest->afbClient; - if (afbClient->verbose) printf("ON-RESPONSE call=%s response=%s\n", afbRequest->callIdTag, afb_wsj1_msg_object_s(msg)); + if (afbClient->verbose) printf("OnSuccessCB callid='%s' response='%s' info='%s'\n", afbRequest->callIdTag, json_object_get_string(responseJ), info); // Cancel timeout for this request sd_event_source_unref(afbRequest->evtSource); - - if (! afb_wsj1_msg_is_reply_ok(msg)) goto OnErrorExit; + free(afbRequest->callIdTag); // When not more waiting call release semaphore afbClient->count--; if (afbClient->count == 0) { - if (afbClient->verbose) printf("ON-RESPONSE No More Waiting Request\n"); + if (afbClient->verbose) printf("OnSuccessCB No More Waiting Request\n"); afbClient->error=0; sem_post (&afbClient->semaphore); } - return; +} -OnErrorExit: - fprintf(stderr, "ON-RESPONSE ERROR call=%s response=%s\n", afbRequest->callIdTag, afb_wsj1_msg_object_s(msg)); - afbClient->error=1; +static void OnFailureCB(void* UNUSED_ARG(ctx), void* handle, const char *status, const char *info) { + + afbRequestT *afbRequest= (afbRequestT*)handle; + afbClientT *afbClient=(afbClientT*)afbRequest->afbClient; + + if (afbClient->verbose) printf("OnFailureCB callid='%s' status='%s' info='%s'\n", afbRequest->callIdTag, status, info); + + // Cancel timeout for this request + sd_event_source_unref(afbRequest->evtSource); + free(afbRequest->callIdTag); + + afbClient->error=1; sem_post (&afbClient->semaphore); } + +/* the callback interface for pws */ +static struct afb_proto_ws_client_itf itf = { + .on_reply_success = OnSuccessCB, + .on_reply_fail = OnFailureCB, + .on_event_create = NULL, + .on_event_remove = NULL, + .on_event_subscribe = NULL, + .on_event_unsubscribe = NULL, + .on_event_push = OnEventCB, + .on_event_broadcast = NULL, + .on_subcall = NULL, +}; + int OnTimeoutCB (sd_event_source* source, uint64_t timer, void* handle) { afbClientT *afbClient= (afbClientT*)handle; @@ -240,9 +248,11 @@ static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int c else apiVerb= afbRequest->openVerb; // release action is optional - if (apiVerb) { + if (apiVerb) { + char * sessionId; + (void) asprintf(&sessionId, "alsa-hook-pid:%d", getpid()); if (afbClient->verbose) printf("CALL-REQUEST verb=%s tag=%s\n", apiVerb, afbRequest->callIdTag); - err = afb_proto_ws_client_call(afbClient->pws, apiVerb, afbRequest->queryJ, "xxxx", afbRequest); + err = afb_proto_ws_client_call(afbClient->pws, apiVerb, afbRequest->queryJ, sessionId, afbRequest); if (err < 0 ) goto OnErrorExit; } // save client handle in request @@ -372,7 +382,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { continue; } - if (strcmp(id, "request") == 0) { + if (strcmp(id, "controls") == 0) { const char *callConf, *callLabel; snd_config_type_t ctype; snd_config_iterator_t currentCall, follow; @@ -469,7 +479,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { } continue; } - if (strcmp(id, "event") == 0) { + if (strcmp(id, "events") == 0) { const char *callConf, *callLabel; snd_config_type_t ctype; snd_config_iterator_t currentCall, follow; @@ -541,7 +551,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { return 0; OnErrorExit: - fprintf(stderr, "\nAlsaPcmHook Plugin Install Fail PCM=%s\n", snd_pcm_name(pcm)); + fprintf(stderr, "\nAlsaPcmHook Plugin Policy Control Fail PCM=%s\n", snd_pcm_name(pcm)); if (h_close) snd_pcm_hook_remove(h_close); diff --git a/hook-plugin/README.md b/hook-plugin/README.md index 748f66f..4297498 100644 --- a/hook-plugin/README.md +++ b/hook-plugin/README.md @@ -20,43 +20,104 @@ Test Config ``` -# Define sharelib location and entry point -# ----------------------------------------- -pcm_hook_type.MyHookPlugin { - install "AlsaInstallHook" - lib "/home/fulup/Workspace/AGL-AppFW/audio-bindings-dev/build/Alsa-Plugin/Alsa-Hook-Callback/alsa_hook_cb.so" +# +# Author: Fulup Ar Foll +# Object: PCM hook type +# +# Test : Note: Jabra_USB=hw:v1340 +# Check SoundCard ==> speaker-test -Dhw:v1340 -c2 -twav +# Check MixerPCM ==> speaker-test -DSpeakers -c2 -twav +# Check SoftVol ==> speaker-test -DMusicPCM -c2 -twav +# Check Plugin ==> speaker-test -DMultimedia -c2 -twav +# MultiMedia aplay -DDMyNavPCM /usr/share/sounds/alsa/test.wav +# +# Bug/Feature: when softvol control is initialised from plugin and not +# from AGL binding. At 1st run ctl has invalid TLV and cannot be +# use. Bypass Solution: +# * start audio-binder before playing sound (binding create control before softvol plugin) +# * run a dummy aplay -DMyNavPCM "" to get a clean control +# +# References: https://www.spinics.net/lists/alsa-devel/msg54235.html +# -------------------------------------------------------------------- + +# ------------------------------------------------------ +# Mixer PCM allow to play multiple stream simultaneously +# ------------------------------------------------------ +pcm.Speakers { + type dmix + slave {pcm "hw:v1340"} #Jabra Solmate 1 + ipc_key 1001 # ipc_key should be unique to each dmix +} + +# ----------------------------------------------------- +# Register ControllerHookPlugin (ToiBeFix fullpath) +# ----------------------------------------------------- +pcm_hook_type.CtlHookPlugin { + install "AlsaInstallHook" + lib "/home/fulup/Workspace/Audio-4a/alsa-4a/build/hook-plugin/policy_hook_cb.so" } -# Create PCM HOOK with corresponding request calls to AGL Audio Agent -# -------------------------------------------------------------------- -pcm.MyNavigationHook { - type hooks - slave.pcm "MyMixerPCM" - # Defined used hook sharelib and provide arguments/config to install func +# ------------------------------------------------------- +# Define one Audio Virtual Channel per Audio Roles +# ------------------------------------------------------- +pcm.MusicPCM { + type softvol + + # Point Slave on HOOK for policies control + slave.pcm "Speakers" + + # name should match with HAL definition + control.name "Playback Multimedia" +} + +pcm.NavPCM { + type softvol + + # Point Slave on HOOK for policies control + slave.pcm "Speakers" + + # name should match with HAL definition + control.name "Playback Navigation" +} + +pcm.UrgentPCM { + type softvol + + # Point Slave on HOOK for policies control + slave.pcm "Speakers" + + # name should match with HAL definition + control.name "Playback Emergency" +} + +# ---------------------------------------------------- +# Define one hooked PCM channel per Audio Roles +# ---------------------------------------------------- +pcm.Multimedia { + type hooks + slave {pcm "MusicPCM"} hooks.0 { - type "MyHookPlugin" + comment "Defined used hook sharelib and provide arguments/config to install func" + type "CtlHookPlugin" hook_args { - verbose true # print few log messages (default false); - # Every Call should return OK in order PCM to open (default timeout 100ms) - uri "ws://localhost:1234/api?token='audio-agent-token'" + # print few log messages (default false) + verbose true + + # uri to audio-4a policy engine ws-client="unix:/var/tmp/pol4a" - request { + + # api subcall to request a role + controls { # Request authorisation to write on navigation navigation-ctl { request "navigation-role" release "release-role" args "{'uid':'alsa-hook-navigation'}" } - # subscribe to Audio Agent Event map them to signal - subscribe-evt { - api "pol4a" - verb "subscribe" - } } - # map event reception to self generated signal - event { + events { # map event reception to self generated signal pause 30 resume 31 stop 3 @@ -65,6 +126,7 @@ pcm.MyNavigationHook { } } + ``` NOTE: |