diff options
Diffstat (limited to 'alsa-binding')
-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; } |