aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--alsa-binding/Alsa-RegEvt.c518
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, &currentSndHandle->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(&currentSndHandle->evtHandle);
+ return NULL;
+ }
- // register sound event to binder main loop
- err = sd_event_add_io(afb_daemon_get_event_loop(),
- &currentSndHandle->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, &currentSndHandle->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(),
+ &currentSndHandle->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(&currentSndHandle->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(&currentSndHandle->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;
}