diff options
Diffstat (limited to 'Alsa-Plugin/Alsa-Policy-Hook')
-rw-r--r-- | Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c | 135 |
1 files changed, 86 insertions, 49 deletions
diff --git a/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c b/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c index ae2a5a3..501ebf9 100644 --- a/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c +++ b/Alsa-Plugin/Alsa-Policy-Hook/PolicyHookCb.c @@ -62,7 +62,18 @@ #define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x void OnRequestCB(void* UNUSED(handle) , const char* UNUSED(api), const char* UNUSED(verb), struct afb_wsj1_msg*UNUSED(msg)) {} - typedef struct { +typedef struct { + const char *api; + const char *verb; + long timeout; + char *query; + + sd_event_source *evtSource; + char *callIdTag; + void *afbClient; +} afbRequestT; + +typedef struct { snd_pcm_t *pcm; const char *uri; struct afb_wsj1 *wsj1; @@ -71,18 +82,10 @@ void OnRequestCB(void* UNUSED(handle) , const char* UNUSED(api), const char* UNU sem_t semaphore; int count; int error; + afbRequestT **request; } afbClientT; -typedef struct { - const char *api; - const char *verb; - long timeout; - char *query; - - sd_event_source *evtSource; - char *callIdTag; - afbClientT *afbClient; -} afbRequestT; + static void *LoopInThread(void *handle) { afbClientT *afbClient = (afbClientT*) handle; @@ -110,6 +113,11 @@ static void OnHangupCB(void *handle, struct afb_wsj1 *wsj1) { if (err) exit(1); } +typedef enum { + HOOK_INSTALL, + HOOK_CLOSE, +} hookActionT; + // supported action typedef enum { ACTION_PAUSE, @@ -201,8 +209,9 @@ static struct afb_wsj1_itf itf = { void OnResponseCB(void *handle, struct afb_wsj1_msg *msg) { afbRequestT *afbRequest= (afbRequestT*)handle; + afbClientT *afbClient=(afbClientT*)afbRequest->afbClient; - if (afbRequest->afbClient->verbose) printf("ON-RESPONSE call=%s response=%s\n", afbRequest->callIdTag, afb_wsj1_msg_object_s(msg)); + if (afbClient->verbose) printf("ON-RESPONSE call=%s response=%s\n", afbRequest->callIdTag, afb_wsj1_msg_object_s(msg)); // Cancel timeout for this request sd_event_source_unref(afbRequest->evtSource); @@ -210,18 +219,18 @@ void OnResponseCB(void *handle, struct afb_wsj1_msg *msg) { if (! afb_wsj1_msg_is_reply_ok(msg)) goto OnErrorExit; // When not more waiting call release semaphore - afbRequest->afbClient->count--; - if (afbRequest->afbClient->count == 0) { - if (afbRequest->afbClient->verbose) printf("ON-RESPONSE No More Waiting Request\n"); - afbRequest->afbClient->error=0; - sem_post (&afbRequest->afbClient->semaphore); + afbClient->count--; + if (afbClient->count == 0) { + if (afbClient->verbose) printf("ON-RESPONSE 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)); - afbRequest->afbClient->error=1; - sem_post (&afbRequest->afbClient->semaphore); + afbClient->error=1; + sem_post (&afbClient->semaphore); } int OnTimeoutCB (sd_event_source* source, uint64_t timer, void* handle) { @@ -237,9 +246,10 @@ int OnTimeoutCB (sd_event_source* source, uint64_t timer, void* handle) { } // Call AGL binder asynchronously by with a timeout -static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int count) { +static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int count, hookActionT action) { uint64_t usec; int err; + const char *query; // create a unique tag for request (void) asprintf(&afbRequest->callIdTag, "%d:%s/%s", count, afbRequest->api, afbRequest->verb); @@ -248,7 +258,9 @@ static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int c sd_event_now(afbClient->sdLoop, CLOCK_MONOTONIC, &usec); sd_event_add_time(afbClient->sdLoop, &afbRequest->evtSource, CLOCK_MONOTONIC, usec+afbRequest->timeout*1000, 250, OnTimeoutCB, afbClient); - err = afb_wsj1_call_s(afbClient->wsj1, afbRequest->api, afbRequest->verb, afbRequest->query, OnResponseCB, afbRequest); + if (action == HOOK_INSTALL) query=afbRequest->query; + else query="{'closing': 1}"; + err = afb_wsj1_call_s(afbClient->wsj1, afbRequest->api, afbRequest->verb, query, OnResponseCB, afbRequest); if (err) goto OnErrorExit; // save client handle in request @@ -261,37 +273,40 @@ OnErrorExit: return -1; } -static int LaunchCallRequest(afbClientT *afbClient, afbRequestT **afbRequest) { +static int LaunchCallRequest(afbClientT *afbClient, hookActionT action) { pthread_t tid; int err, idx; + afbRequestT **afbRequest= afbClient->request; + + if (action == HOOK_INSTALL) { + // init waiting counting semaphore + if (sem_init(&afbClient->semaphore, 1, 0) == -1) { + fprintf(stderr, "LaunchCallRequest: Fail Semaphore Init: %s\n", afbClient->uri); + } - // init waiting counting semaphore - if (sem_init(&afbClient->semaphore, 1, 0) == -1) { - fprintf(stderr, "LaunchCallRequest: Fail Semaphore Init: %s\n", afbClient->uri); - } - - // Create a main loop - err = sd_event_default(&afbClient->sdLoop); - if (err < 0) { - fprintf(stderr, "LaunchCallRequest: Connection to default event loop failed: %s\n", strerror(-err)); - goto OnErrorExit; + // Create a main loop + err = sd_event_default(&afbClient->sdLoop); + if (err < 0) { + fprintf(stderr, "LaunchCallRequest: Connection to default event loop failed: %s\n", strerror(-err)); + goto OnErrorExit; + } + + // start a thread with a mainloop to monitor Audio-Agent + err = pthread_create(&tid, NULL, &LoopInThread, afbClient); + if (err) goto OnErrorExit; + + // connect the websocket wsj1 to the uri given by the first argument + afbClient->wsj1 = afb_ws_client_connect_wsj1(afbClient->sdLoop, afbClient->uri, &itf, afbClient); + if (afbClient->wsj1 == NULL) { + fprintf(stderr, "LaunchCallRequest: Connection to %s failed\n", afbClient->uri); + goto OnErrorExit; + } } - // start a thread with a mainloop to monitor Audio-Agent - err = pthread_create(&tid, NULL, &LoopInThread, afbClient); - if (err) goto OnErrorExit; - - // connect the websocket wsj1 to the uri given by the first argument - afbClient->wsj1 = afb_ws_client_connect_wsj1(afbClient->sdLoop, afbClient->uri, &itf, afbClient); - if (afbClient->wsj1 == NULL) { - fprintf(stderr, "LaunchCallRequest: Connection to %s failed\n", afbClient->uri); - goto OnErrorExit; - } - // send call request to audio-agent asynchronously (respond with thread mainloop context) for (idx = 0; afbRequest[idx] != NULL; idx++) { - err = CallWithTimeout(afbClient, afbRequest[idx], idx); + err = CallWithTimeout(afbClient, afbRequest[idx], idx, action); if (err) { fprintf(stderr, "LaunchCallRequest: Fail call %s//%s/%s&%s", afbClient->uri, afbRequest[idx]->api, afbRequest[idx]->verb, afbRequest[idx]->query); goto OnErrorExit; @@ -311,7 +326,25 @@ static int AlsaCloseHook(snd_pcm_hook_t *hook) { afbClientT *afbClient = (afbClientT*) snd_pcm_hook_get_private (hook); - if (afbClient->verbose) fprintf(stdout, "\nAlsaCloseHook pcm=%s\n", snd_pcm_name(afbClient->pcm)); + // launch call request and create a waiting mainloop thread + int err = LaunchCallRequest(afbClient, HOOK_CLOSE); + if (err < 0) { + fprintf (stderr, "PCM Fail to Enter Mainloop\n"); + goto OnErrorExit; + } + + // wait for all call request to return + sem_wait(&afbClient->semaphore); + if (afbClient->error) { + fprintf (stderr, "AlsaCloseHook: Audio Agent Fail to respond\n"); + goto OnErrorExit; + } + + if (afbClient->verbose) fprintf(stdout, "\nAlsaHook Close Success PCM=%s URI=%s\n", snd_pcm_name(afbClient->pcm), afbClient->uri); + return 0; + +OnErrorExit: + fprintf(stderr, "\nAlsaPcmHook Plugin Close Fail PCM=%s\n", snd_pcm_name(afbClient->pcm)); return 0; } @@ -327,7 +360,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { // start populating client handle afbClient->pcm = pcm; afbClient->verbose = 0; - + afbClient->request = afbRequest; // Get PCM arguments from asoundrc snd_config_for_each(it, next, conf) { @@ -393,18 +426,22 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { err = snd_config_search(ctlconfig, "api", &itemConf); if (!err) { - if (snd_config_get_string(itemConf, &afbRequest[callCount]->api) < 0) { + const char *api; + if (snd_config_get_string(itemConf, &api) < 0) { SNDERR("Invalid api string for %s", callLabel); goto OnErrorExit; } + afbRequest[callCount]->api=strdup(api); } err = snd_config_search(ctlconfig, "verb", &itemConf); if (!err) { - if (snd_config_get_string(itemConf, &afbRequest[callCount]->verb) < 0) { + const char *verb; + if (snd_config_get_string(itemConf, &verb) < 0) { SNDERR("Invalid verb string %s", id); goto OnErrorExit; } + afbRequest[callCount]->verb=strdup(verb); } err = snd_config_search(ctlconfig, "timeout", &itemConf); @@ -462,7 +499,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { if (err < 0) goto OnErrorExit; // launch call request and create a waiting mainloop thread - err = LaunchCallRequest(afbClient, afbRequest); + err = LaunchCallRequest(afbClient, HOOK_INSTALL); if (err < 0) { fprintf (stderr, "PCM Fail to Enter Mainloop\n"); goto OnErrorExit; |