diff options
author | Jonathan Aillet <jonathan.aillet@iot.bzh> | 2019-09-19 15:05:59 +0200 |
---|---|---|
committer | Jonathan Aillet <jonathan.aillet@iot.bzh> | 2019-10-01 10:56:54 +0200 |
commit | 2be5e4462b36b9ccc7562a83047de81dffe7e899 (patch) | |
tree | 53eb2e38859c80e79a48fdb705979b124418a405 | |
parent | b829ccf57c83d0cad0b285fdd9a25e823ce2bbcd (diff) |
Rework subscription handling
Rework subscription handling to :
- use an "event" key to select which event type we want to
subscribe to, this will allow an easier integration of new events.
- merge 'soundcard-added' and 'soundcard-removed' cards events into
one 'cards-monitoring' event. Will ease unsubscription.
- remove concept of 'mode' in json sent by event, this will allow
to avoid 'mode' conflicts when several bindings are subscribed
to the same event.
Also, normalize some syntax issues.
SPEC-2832
Change-Id: Ief8b3065a3e18dc710ef5b951053f96459c65e0b
Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
-rw-r--r-- | alsa-binding/Alsa-RegEvt.c | 518 |
1 files changed, 279 insertions, 239 deletions
diff --git a/alsa-binding/Alsa-RegEvt.c b/alsa-binding/Alsa-RegEvt.c index 7962963..a60ffc8 100644 --- a/alsa-binding/Alsa-RegEvt.c +++ b/alsa-binding/Alsa-RegEvt.c @@ -30,16 +30,17 @@ #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) #define INOTIFY_EVENT_BUF_LEN (1024 * (INOTIFY_EVENT_SIZE + 16)) -#define DIR_TO_WATCH "/dev/snd/by-path" +#define CARD_DIR_TO_WATCH "/dev/snd/by-path" #ifndef MAX_SND_HAL #define MAX_SND_HAL 10 #endif typedef enum { - SUBSCRIPTION_CARD_ADDED_EVENTS = 0, - SUBSCRIPTION_CARD_REMOVED_EVENTS = 1 -} SubscriptionCardEventTypeT; + UNKNOWN_EVENT = 0, + CARD_CONTROL_CHANGE_EVENTS = 1, + CARD_MONITORING_EVENTS = 2 +} EventTypeT; typedef struct { int fd; @@ -53,7 +54,6 @@ typedef struct { struct pollfd pfds; sd_event_source *src; snd_ctl_t *ctlDev; - int mode; afb_event_t afbevt; } ctrlEvtHandleT; @@ -64,8 +64,7 @@ typedef struct { typedef struct { sndHandleT sndHandles[MAX_SND_CARD]; - sndCardEvtHandleT *cardAdded; - sndCardEvtHandleT *cardRemoved; + sndCardEvtHandleT *cardMonitoring; afb_api_t apiHandle; } sndCardsT; @@ -95,6 +94,33 @@ STATIC int getHalIdxFromCardid (int cardid) { return -1; } +STATIC EventTypeT alsaGetDevIdFromString(char *eventTypeString) +{ + if(! eventTypeString) + return UNKNOWN_EVENT; + + if(! strcasecmp(eventTypeString, "controls")) + return CARD_CONTROL_CHANGE_EVENTS; + + if(! strcasecmp(eventTypeString, "cards")) + return CARD_MONITORING_EVENTS; + + return UNKNOWN_EVENT; +} + +STATIC EventTypeT alsaGetEventTypeFromQuery(json_object *queryJ) +{ + char *eventTypeString = NULL; + + if(wrap_json_unpack(queryJ, "{s:s}", "event", &eventTypeString)) + return UNKNOWN_EVENT; + + if(! eventTypeString) + return UNKNOWN_EVENT; + + return alsaGetDevIdFromString(eventTypeString); +} + PUBLIC char *alsaGetDevIdFromQuery(json_object *queryJ) { char *devId = NULL; @@ -115,34 +141,89 @@ PUBLIC queryModeE alsaGetModeFromQuery(json_object *queryJ) return mode; } -STATIC void updateSelectedAlsaCardsAvailabilityAndFireEvents(sndCardsT *sndCards, int first, int last) { +STATIC void freeSndCardHandle(sndCardEvtHandleT **cardMonitoringHandle) +{ + sndCardEvtHandleT *cardMonitoringHandleToFree; + + if(! cardMonitoringHandle || ! *cardMonitoringHandle) + return; + + cardMonitoringHandleToFree = *cardMonitoringHandle; + + if(cardMonitoringHandleToFree->src) + sd_event_source_unref(cardMonitoringHandleToFree->src); + + if(afb_event_is_valid(cardMonitoringHandleToFree->afbevt)) + afb_event_unref(cardMonitoringHandleToFree->afbevt); + + if(cardMonitoringHandleToFree->fd != -1 && cardMonitoringHandleToFree->wd != -1) + inotify_rm_watch(cardMonitoringHandleToFree->fd, cardMonitoringHandleToFree->wd); + + if(cardMonitoringHandleToFree->fd != -1) + close(cardMonitoringHandleToFree->fd); + + free(cardMonitoringHandleToFree); + + *cardMonitoringHandle = NULL; +} + +STATIC void freeCardAlsaControlHandle(ctrlEvtHandleT **cardControlHandle) +{ + ctrlEvtHandleT *cardControlHandleToFree; + + if(! cardControlHandle || ! *cardControlHandle) + return; + + cardControlHandleToFree = *cardControlHandle; + + if(cardControlHandleToFree->src) + sd_event_source_unref(cardControlHandleToFree->src); + + if(afb_event_is_valid(cardControlHandleToFree->afbevt)) + afb_event_unref(cardControlHandleToFree->afbevt); + + if(cardControlHandleToFree->ctlDev) + snd_ctl_close(cardControlHandleToFree->ctlDev); + + free(cardControlHandleToFree); + + *cardControlHandle = NULL; +} + +STATIC void updateSelectedAlsaCardsAvailabilityAndFireEvents(sndCardsT *sndCards, int first, int last) +{ int idx, available; char *cardId; - if (first < 0 || first >= MAX_SND_CARD) + json_object *generatedEventJ = NULL; + + if(first < 0 || first >= MAX_SND_CARD) return; - if (last < 0 || last >= MAX_SND_CARD) + if(last < 0 || last >= MAX_SND_CARD) return; - if (last < first) + if(last < first) return; - for (idx = first; idx < (last + 1); idx++) { + for(idx = first; idx < (last + 1); idx++) { available = snd_card_load(idx); - if (available && ! sndCards->sndHandles[idx].available) { - sndCards->sndHandles[idx].available = 1; + if(available && ! sndCards->sndHandles[idx].available) { + sndCards->sndHandles[idx].available = 1; - if (sndCards->cardAdded) - afb_event_push(sndCards->cardAdded->afbevt, getCardInfo(idx)); + if(sndCards->cardMonitoring && + ! wrap_json_pack(&generatedEventJ, "{s:o}", "cardAdded", getCardInfo(idx))) + afb_event_push(sndCards->cardMonitoring->afbevt, generatedEventJ); } - else if (! available && sndCards->sndHandles[idx].available) { + else if(! available && sndCards->sndHandles[idx].available) { sndCards->sndHandles[idx].available = 0; - if (sndCards->cardRemoved && (asprintf(&cardId, "hw:%i", idx) > 0)) - afb_event_push(sndCards->cardRemoved->afbevt, json_object_new_string(cardId)); + if(sndCards->cardMonitoring && + (asprintf(&cardId, "hw:%i", idx) > 0) && + ! wrap_json_pack(&generatedEventJ, "{s:s}", "cardRemoved", cardId)) + afb_event_push(sndCards->cardMonitoring->afbevt, generatedEventJ); - if (sndCards->sndHandles[idx].evtHandle) { + if(sndCards->sndHandles[idx].evtHandle) { sd_event_source_unref(sndCards->sndHandles[idx].evtHandle->src); afb_event_unref(sndCards->sndHandles[idx].evtHandle->afbevt); snd_ctl_close(sndCards->sndHandles[idx].evtHandle->ctlDev); @@ -158,7 +239,8 @@ STATIC void updateAllAlsaCardsAvailabilityAndFireEvents(sndCardsT *sndCards) { } // This routine is called every few microseconds to verify when the newly created sound card file will be openable (using timer event firing) -STATIC int sndCardTimerForCreatedFileCB(TimerHandleT *context) { +STATIC int sndCardTimerForCreatedFileCB(TimerHandleT *context) +{ int createdFileCardNb; sndCardCardFileEventHandleT *createdFileHandle = (sndCardCardFileEventHandleT *) context->context; @@ -182,7 +264,8 @@ STATIC int sndCardTimerForCreatedFileCB(TimerHandleT *context) { } // This routine is called when sound cards are added/removed (when inotify '/dev/snd/by-path' events are fired) -STATIC int sndCardEventCB(sd_event_source* src, int fd, uint32_t revents, void* userData) { +STATIC int sndCardEventCB(sd_event_source* src, int fd, uint32_t revents, void* userData) +{ ssize_t length, i = 0; char buffer[INOTIFY_EVENT_BUF_LEN]; char *createdFile; @@ -194,40 +277,31 @@ STATIC int sndCardEventCB(sd_event_source* src, int fd, uint32_t revents, void* sndCardsT *sndCards = (sndCardsT *) userData; - if (revents & EPOLLERR) { + if(revents & EPOLLERR) { AFB_ERROR("An error has been send by event loop polling, prevent new errors to be fired by deleting event src"); - - sd_event_source_unref(src); - - afb_event_unref(sndCards->cardAdded->afbevt); - afb_event_unref(sndCards->cardRemoved->afbevt); - - inotify_rm_watch(sndCards->cardAdded->fd, sndCards->cardAdded->wd); - close(sndCards->cardAdded->fd); - - free(sndCards->cardAdded); - free(sndCards->cardRemoved); - - sndCards->cardAdded = NULL; - sndCards->cardRemoved = NULL; - - goto OnErrorExit; + freeSndCardHandle(&sndCards->cardMonitoring); + return -1; } - if (revents & EPOLLIN) { + if(revents & EPOLLIN) { length = read(fd, buffer, INOTIFY_EVENT_BUF_LEN); - if (length < 0) { + if(length < 0) { AFB_ERROR("Nothing read using inotify"); - goto OnErrorExit; + freeSndCardHandle(&sndCards->cardMonitoring); + return -2; } - while (i < length) { + while(i < length) { event = (struct inotify_event *) &buffer[i]; - if(event->len && - (event->mask & IN_CREATE) && + i += INOTIFY_EVENT_SIZE + event->len; + + if(! event->len) + continue; + + if((event->mask & IN_CREATE) && ! (event->mask & IN_ISDIR) && - (asprintf(&createdFile, "%s/%s", DIR_TO_WATCH, event->name) > 0)) { + (asprintf(&createdFile, "%s/%s", CARD_DIR_TO_WATCH, event->name) > 0)) { createdFileHandle = calloc(1, sizeof(sndCardCardFileEventHandleT)); createdFileHandle->createdFileName = strdup(createdFile); createdFileHandle->sndCards = sndCards; @@ -241,201 +315,162 @@ STATIC int sndCardEventCB(sd_event_source* src, int fd, uint32_t revents, void* TimerEvtStart(sndCards->apiHandle, createdFileTimerHandle, sndCardTimerForCreatedFileCB, (void *) createdFileHandle); } - if(event->len && (event->mask & IN_DELETE) && ! (event->mask & IN_ISDIR)) + if((event->mask & IN_DELETE) && ! (event->mask & IN_ISDIR)) updateAllAlsaCardsAvailabilityAndFireEvents(sndCards); - - i += INOTIFY_EVENT_SIZE + event->len; } } return 0; - -OnErrorExit: - return -1; } // This routine is called when ALSA control events are fired -STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* userData) { +STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* userData) +{ int err, ctlNumid; - sndHandleT *sndHandle = (sndHandleT *) userData; - ctrlEvtHandleT *evtHandle = (ctrlEvtHandleT*) sndHandle->evtHandle; - snd_ctl_event_t *eventId; - json_object *ctlEventJ; unsigned int mask; - int iface; - int device; - int subdev; - const char*ctlName; - ctlRequestT ctlRequest; + snd_ctl_elem_id_t *elemId; + snd_ctl_event_t *eventId; + + sndHandleT *sndHandle = (sndHandleT *) userData; + ctlRequestT ctlRequest; - if ((revents & EPOLLERR) != 0) { + json_object *ctlEventJ, *ctlEventAdditionalInfoJ; + + if((revents & EPOLLERR) != 0) { AFB_ERROR("An error has been send by event loop polling, prevent new errors to be fired by deleting event src"); - sd_event_source_unref(src); - afb_event_unref(sndHandle->evtHandle->afbevt); - snd_ctl_close(sndHandle->evtHandle->ctlDev); - free(sndHandle->evtHandle); - sndHandle->evtHandle = NULL; - goto OnErrorExit; + freeCardAlsaControlHandle(&sndHandle->evtHandle); + return -1; } - if ((revents & EPOLLHUP) != 0) { + if((revents & EPOLLHUP) != 0) { AFB_NOTICE("SndCtl hanghup [car disconnected]"); - goto ExitOnSucess; + return 0; } - if ((revents & EPOLLIN) != 0) { + if((revents & EPOLLIN) != 0) { // initialise event structure on stack snd_ctl_event_alloca(&eventId); snd_ctl_elem_id_alloca(&elemId); - err = snd_ctl_read(evtHandle->ctlDev, eventId); - if (err < 0) goto OnErrorExit; + err = snd_ctl_read(sndHandle->evtHandle->ctlDev, eventId); + if(err < 0) { + AFB_ERROR("Did not succeed to read control event"); + freeCardAlsaControlHandle(&sndHandle->evtHandle); + return -2; + } // we only process sndctrl element - if (snd_ctl_event_get_type(eventId) != SND_CTL_EVENT_ELEM) goto ExitOnSucess; + if(snd_ctl_event_get_type(eventId) != SND_CTL_EVENT_ELEM) + return 0; // we only process value changed events mask = snd_ctl_event_elem_get_mask(eventId); - if (!(mask & SND_CTL_EVENT_MASK_VALUE)) goto ExitOnSucess; + if(! (mask & SND_CTL_EVENT_MASK_VALUE)) + return 0; snd_ctl_event_elem_get_id(eventId, elemId); - err = alsaGetSingleCtl(evtHandle->ctlDev, elemId, &ctlRequest, evtHandle->mode); - if (err) goto OnErrorExit; + err = alsaGetSingleCtl(sndHandle->evtHandle->ctlDev, elemId, &ctlRequest, QUERY_FULL); + if(err) { + AFB_ERROR("Did not succeed to get control info and values"); + freeCardAlsaControlHandle(&sndHandle->evtHandle); + return -3; + } // If CTL as a value use it as container for response - if (ctlRequest.valuesJ) ctlEventJ = ctlRequest.valuesJ; + if(ctlRequest.valuesJ) { + ctlEventJ = ctlRequest.valuesJ; + } else { ctlEventJ = json_object_new_object(); ctlNumid = snd_ctl_event_elem_get_numid(eventId); json_object_object_add(ctlEventJ, "id", json_object_new_int(ctlNumid)); } - if (evtHandle->mode >= QUERY_COMPACT) { - ctlName = snd_ctl_event_elem_get_name(eventId); - json_object_object_add(ctlEventJ, "name", json_object_new_string(ctlName)); - } - - if (evtHandle->mode >= QUERY_VERBOSE) { - iface = snd_ctl_event_elem_get_interface(eventId); - device = snd_ctl_event_elem_get_device(eventId); - subdev = snd_ctl_event_elem_get_subdevice(eventId); - json_object_object_add(ctlEventJ, "ifc", json_object_new_int(iface)); - json_object_object_add(ctlEventJ, "dev", json_object_new_int(device)); - json_object_object_add(ctlEventJ, "sub", json_object_new_int(subdev)); - } + err = wrap_json_pack(&ctlEventAdditionalInfoJ, + "{s:s, s:i, s:i, s:i}", + "name", snd_ctl_event_elem_get_name(eventId), + "card", snd_ctl_event_elem_get_interface(eventId), + "dev", snd_ctl_event_elem_get_device(eventId), + "sub", snd_ctl_event_elem_get_subdevice(eventId)); + if(! err) + wrap_json_object_add(ctlEventJ, ctlEventAdditionalInfoJ); AFB_DEBUG("sndCtlEventCB=%s", json_object_get_string(ctlEventJ)); - afb_event_push(evtHandle->afbevt, ctlEventJ); + + afb_event_push(sndHandle->evtHandle->afbevt, ctlEventJ); } -ExitOnSucess: return 0; - -OnErrorExit: - AFB_WARNING("sndCtlEventCB: Error detected"); - return -1; } // Subscribe to each time a sound card is added/removed (using inotify '/dev/snd/by-path' events) -STATIC afb_event_t alsaEvtSubscribeSoundCardEvent(afb_req_t request, sndCardsT *sndCards, SubscriptionCardEventTypeT subscriptionType) { - int fd = -1, wd = -1, err; - - // Update card list - updateAllAlsaCardsAvailabilityAndFireEvents(sndCards); - - if (! sndCards->cardAdded && ! sndCards->cardRemoved) { - fd = inotify_init(); - if (fd < 0) { - afb_req_fail_f(request, "inotify-init", "Error %s happened while getting file descriptor for inotify", strerror(errno)); - goto OnErrorExit; - } - - wd = inotify_add_watch(fd, DIR_TO_WATCH, IN_CREATE | IN_DELETE); - if (wd < 0) { - afb_req_fail_f(request, - "inotify-watch", - "Error %s happened while setting watchdog on '%s' directory using inotify", - strerror(errno), - DIR_TO_WATCH); - goto OnErrorExit; - } - - sndCards->cardAdded = malloc(sizeof (sndCardEvtHandleT)); - if (! sndCards->cardAdded) { - afb_req_fail(request, "card-added-event", "Error while allocating card added event handle"); - goto OnErrorExit; - } - - sndCards->cardRemoved = malloc(sizeof (sndCardEvtHandleT)); - if (! sndCards->cardRemoved) { - afb_req_fail(request, "card-removed-event", "Error while allocating card removed event handle"); - goto OnErrorExit; - } - - sndCards->cardAdded->fd = fd; - sndCards->cardRemoved->fd = fd; - - sndCards->cardAdded->wd = wd; - sndCards->cardRemoved->wd = wd; +STATIC afb_event_t alsaEvtSubscribeSoundCardEvent(afb_req_t request, + sndCardsT *sndCards) +{ + int err; - sndCards->cardAdded->afbevt = afb_daemon_make_event("soundcard-added"); - if (!afb_event_is_valid(sndCards->cardAdded->afbevt)) { - afb_req_fail_f(request, "register-event", "Cannot register new binder event name=%s", "soundcard-added"); - goto OnErrorExit; - } + if(sndCards->cardMonitoring) + return sndCards->cardMonitoring->afbevt; - sndCards->cardRemoved->afbevt = afb_daemon_make_event("soundcard-removed"); - if (!afb_event_is_valid(sndCards->cardRemoved->afbevt)) { - afb_req_fail_f(request, "register-event", "Cannot register new binder event name=%s", "soundcard-added"); - goto OnErrorExit; - } - - // register sound event to binder main loop - err = sd_event_add_io(afb_daemon_get_event_loop(), - &sndCards->cardAdded->src, - fd, - EPOLLIN, - sndCardEventCB, - sndCards); - if (err < 0) { - afb_req_fail_f(request, "register-mainloop", "Cannot hook sound card events to mainloop err=%d", err); - goto OnErrorExit; - } + updateAllAlsaCardsAvailabilityAndFireEvents(sndCards); - sndCards->cardRemoved->src = sndCards->cardAdded->src; + sndCards->cardMonitoring = malloc(sizeof (sndCardEvtHandleT)); + if(! sndCards->cardMonitoring) { + afb_req_fail(request, "card-monitoring-event", "Error while allocating card added monitoring handle"); + return NULL; } - if(subscriptionType == SUBSCRIPTION_CARD_ADDED_EVENTS) - return sndCards->cardAdded->afbevt; - - if(subscriptionType == SUBSCRIPTION_CARD_REMOVED_EVENTS) - return sndCards->cardRemoved->afbevt; - - return NULL; + sndCards->cardMonitoring->fd = -1; + sndCards->cardMonitoring->wd = -1; -OnErrorExit: - if(afb_event_is_valid(sndCards->cardRemoved->afbevt)) - afb_event_unref(sndCards->cardRemoved->afbevt); - - if(afb_event_is_valid(sndCards->cardAdded->afbevt)) - afb_event_unref(sndCards->cardAdded->afbevt); + sndCards->cardMonitoring->fd = inotify_init(); + if(sndCards->cardMonitoring->fd < 0) { + afb_req_fail_f(request, "inotify-init", "Error %s happened while getting file descriptor for inotify", strerror(errno)); + freeSndCardHandle(&sndCards->cardMonitoring); + return NULL; + } - free(sndCards->cardRemoved); - free(sndCards->cardAdded); + sndCards->cardMonitoring->wd = inotify_add_watch(sndCards->cardMonitoring->fd, CARD_DIR_TO_WATCH, IN_CREATE | IN_DELETE); + if(sndCards->cardMonitoring->wd < 0) { + afb_req_fail_f(request, + "inotify-watch", + "Error %s happened while setting watcher on '%s' directory using inotify", + strerror(errno), + CARD_DIR_TO_WATCH); + freeSndCardHandle(&sndCards->cardMonitoring); + return NULL; + } - if (wd != -1) - inotify_rm_watch(fd, wd); + sndCards->cardMonitoring->afbevt = afb_daemon_make_event("card-monitoring"); + if(! afb_event_is_valid(sndCards->cardMonitoring->afbevt)) { + afb_req_fail_f(request, "card-monitoring-event", "Cannot register new binder card-monitoring event"); + freeSndCardHandle(&sndCards->cardMonitoring); + return NULL; + } - if (fd != -1) - close(fd); + // register sound event to binder main loop + err = sd_event_add_io(afb_daemon_get_event_loop(), + &sndCards->cardMonitoring->src, + sndCards->cardMonitoring->fd, + EPOLLIN, + sndCardEventCB, + sndCards); + if(err < 0) { + afb_req_fail_f(request, "register-mainloop", "Cannot hook sound card events to mainloop err=%d", err); + freeSndCardHandle(&sndCards->cardMonitoring); + return NULL; + } - return NULL; + return sndCards->cardMonitoring->afbevt; } // Subscribe to every Alsa CtlEvent send by a given board -STATIC afb_event_t alsaEvtSubscribeAlsaControlEvent(afb_req_t request, sndCardsT *sndCards, char* devId, queryModeE mode) { +STATIC afb_event_t alsaEvtSubscribeAlsaControlEvent(afb_req_t request, + sndCardsT *sndCards, + char* devId) +{ sndHandleT *currentSndHandle = NULL; snd_ctl_t *ctlDev = NULL; int err, cardId; @@ -443,80 +478,77 @@ STATIC afb_event_t alsaEvtSubscribeAlsaControlEvent(afb_req_t request, sndCardsT // open control interface for devid err = snd_ctl_open(&ctlDev, devId, SND_CTL_READONLY); - if (err < 0) { + if(err < 0) { afb_req_fail_f(request, "devid-unknown", "SndCard devid=%s Not Found err=%s", devId, snd_strerror(err)); - goto OnErrorExit; + return NULL; } snd_ctl_card_info_alloca(&cardinfo); err = snd_ctl_card_info(ctlDev, cardinfo); - if (err < 0) { + if(err < 0) { afb_req_fail_f(request, "devid-invalid", "SndCard devid=%s Not Found err=%s", devId, snd_strerror(err)); - goto OnErrorExit; + snd_ctl_close(ctlDev); + return NULL; } cardId = snd_ctl_card_info_get_card(cardinfo); if(cardId < 0 || cardId >= MAX_SND_CARD) { afb_req_fail_f(request, "devid-invalid", "SndCard cardId=%i invalid", cardId); - goto OnErrorExit; + snd_ctl_close(ctlDev); + return NULL; } currentSndHandle = &sndCards->sndHandles[cardId]; - // if not subscription exist for the event let's create one - if (! currentSndHandle->evtHandle) { - currentSndHandle->evtHandle = malloc(sizeof (ctrlEvtHandleT)); - currentSndHandle->evtHandle->ctlDev = ctlDev; - currentSndHandle->evtHandle->mode = mode; + if(currentSndHandle->evtHandle) { + snd_ctl_close(ctlDev); + return currentSndHandle->evtHandle->afbevt; + } - // subscribe for sndctl events attached to devid - err = snd_ctl_subscribe_events(currentSndHandle->evtHandle->ctlDev, 1); - if (err < 0) { - afb_req_fail_f(request, "subscribe-fail", "Cannot subscribe events from devid=%s err=%d", devId, err); - goto OnErrorExit; - } + currentSndHandle->evtHandle = malloc(sizeof (ctrlEvtHandleT)); + currentSndHandle->evtHandle->ctlDev = ctlDev; - // get pollfd attach to this sound board - snd_ctl_poll_descriptors(currentSndHandle->evtHandle->ctlDev, ¤tSndHandle->evtHandle->pfds, 1); + // subscribe for sndctl events attached to devid + err = snd_ctl_subscribe_events(currentSndHandle->evtHandle->ctlDev, 1); + if(err < 0) { + afb_req_fail_f(request, "alsa-ctl-subscribe-fail", "Cannot subscribe events from devid=%s err=%d", devId, err); + freeCardAlsaControlHandle(¤tSndHandle->evtHandle); + return NULL; + } - // register sound event to binder main loop - err = sd_event_add_io(afb_daemon_get_event_loop(), - ¤tSndHandle->evtHandle->src, - currentSndHandle->evtHandle->pfds.fd, - EPOLLIN, - sndCtlEventCB, - currentSndHandle); - if (err < 0) { - afb_req_fail_f(request, "register-mainloop", "Cannot hook events to mainloop devid=%s err=%d", devId, err); - goto OnErrorExit; - } + // get pollfd attach to this sound board + snd_ctl_poll_descriptors(currentSndHandle->evtHandle->ctlDev, ¤tSndHandle->evtHandle->pfds, 1); - // create binder event attached to devid name - currentSndHandle->evtHandle->afbevt = afb_daemon_make_event(devId); - if (!afb_event_is_valid(currentSndHandle->evtHandle->afbevt)) { - afb_req_fail_f(request, "register-event", "Cannot register new binder event name=%s", devId); - goto OnErrorExit; - } + // register sound event to binder main loop + err = sd_event_add_io(afb_daemon_get_event_loop(), + ¤tSndHandle->evtHandle->src, + currentSndHandle->evtHandle->pfds.fd, + EPOLLIN, + sndCtlEventCB, + currentSndHandle); + if(err < 0) { + afb_req_fail_f(request, "register-mainloop", "Cannot hook events to mainloop devid=%s err=%d", devId, err); + freeCardAlsaControlHandle(¤tSndHandle->evtHandle); + return NULL; } - else if (ctlDev) { - snd_ctl_close(ctlDev); + + // create binder event attached to devid name + currentSndHandle->evtHandle->afbevt = afb_daemon_make_event(devId); + if(! afb_event_is_valid(currentSndHandle->evtHandle->afbevt)) { + afb_req_fail_f(request, "register-event", "Cannot register new binder event name=%s", devId); + freeCardAlsaControlHandle(¤tSndHandle->evtHandle); + return NULL; } return currentSndHandle->evtHandle->afbevt; - -OnErrorExit: - if (ctlDev) - snd_ctl_close(ctlDev); - - return NULL; } // Subscribe to alsacore event PUBLIC void alsaEvtSubcribe(afb_req_t request) { int err; - queryModeE mode; + EventTypeT eventType; char *devId = NULL; @@ -533,26 +565,34 @@ PUBLIC void alsaEvtSubcribe(afb_req_t request) { queryJ = afb_req_json(request); - devId = alsaGetDevIdFromQuery(queryJ); - if (!devId) { - afb_req_fail_f(request, "devid-missing", "Invalid query='%s'", json_object_get_string(queryJ)); - return; - } + eventType = alsaGetEventTypeFromQuery(queryJ); + switch(eventType) { + case CARD_CONTROL_CHANGE_EVENTS: + devId = alsaGetDevIdFromQuery(queryJ); + if(! devId) { + afb_req_fail_f(request, "devid-missing", "Invalid query='%s'", json_object_get_string(queryJ)); + return; + } + + eventToSubscribe = alsaEvtSubscribeAlsaControlEvent(request, sndCards, devId); + break; - mode = alsaGetModeFromQuery(queryJ); - if(! strcasecmp(devId, "added")) - eventToSubscribe = alsaEvtSubscribeSoundCardEvent(request, sndCards, SUBSCRIPTION_CARD_ADDED_EVENTS); - else if(! strcasecmp(devId, "removed")) - eventToSubscribe = alsaEvtSubscribeSoundCardEvent(request, sndCards, SUBSCRIPTION_CARD_REMOVED_EVENTS); - else - eventToSubscribe = alsaEvtSubscribeAlsaControlEvent(request, sndCards, devId, mode); + case CARD_MONITORING_EVENTS: + eventToSubscribe = alsaEvtSubscribeSoundCardEvent(request, sndCards); + break; + + case UNKNOWN_EVENT: + default: + afb_req_fail_f(request, "unknown-event", "Invalid query='%s'", json_object_get_string(queryJ)); + return; + } if(! eventToSubscribe) return; // subscribe to binder event err = afb_req_subscribe(request, eventToSubscribe); - if (err) { + if(err) { afb_req_fail_f(request, "register-eventname", "Cannot subscribe binder event"); return; } |