summaryrefslogtreecommitdiffstats
path: root/alsa-binding/Alsa-RegEvt.c
diff options
context:
space:
mode:
Diffstat (limited to 'alsa-binding/Alsa-RegEvt.c')
-rw-r--r--alsa-binding/Alsa-RegEvt.c150
1 files changed, 84 insertions, 66 deletions
diff --git a/alsa-binding/Alsa-RegEvt.c b/alsa-binding/Alsa-RegEvt.c
index 36bb590..c9ac5f1 100644
--- a/alsa-binding/Alsa-RegEvt.c
+++ b/alsa-binding/Alsa-RegEvt.c
@@ -32,15 +32,17 @@ typedef struct {
snd_ctl_t *ctlDev;
int mode;
afb_event_t afbevt;
-} evtHandleT;
+} ctrlEvtHandleT;
typedef struct {
- int ucount;
- int cardId;
- evtHandleT *evtHandle;
+ ctrlEvtHandleT *evtHandle;
} sndHandleT;
typedef struct {
+ sndHandleT sndHandles[MAX_SND_CARD];
+} sndCardsT;
+
+typedef struct {
int cardid;
char *devid;
char *apiprefix;
@@ -86,11 +88,12 @@ OnErrorExit:
return NULL;
}
-// This routine is called when ALSA event are fired
+// This routine is called when ALSA control events are fired
STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* userData) {
int err, ctlNumid;
- evtHandleT *evtHandle = (evtHandleT*) userData;
+ sndHandleT *sndHandle = (sndHandleT *) userData;
+ ctrlEvtHandleT *evtHandle = (ctrlEvtHandleT*) sndHandle->evtHandle;
snd_ctl_event_t *eventId;
json_object *ctlEventJ;
unsigned int mask;
@@ -104,7 +107,11 @@ STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* u
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);
- return -1;
+ afb_event_unref(sndHandle->evtHandle->afbevt);
+ snd_ctl_close(sndHandle->evtHandle->ctlDev);
+ free(sndHandle->evtHandle);
+ sndHandle->evtHandle = NULL;
+ goto OnErrorExit;
}
if ((revents & EPOLLHUP) != 0) {
@@ -113,7 +120,6 @@ STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* u
}
if ((revents & EPOLLIN) != 0) {
-
// initialise event structure on stack
snd_ctl_event_alloca(&eventId);
snd_ctl_elem_id_alloca(&elemId);
@@ -155,7 +161,6 @@ STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* u
json_object_object_add(ctlEventJ, "sub", json_object_new_int(subdev));
}
-
AFB_DEBUG("sndCtlEventCB=%s", json_object_get_string(ctlEventJ));
afb_event_push(evtHandle->afbevt, ctlEventJ);
}
@@ -164,105 +169,118 @@ ExitOnSucess:
return 0;
OnErrorExit:
- AFB_WARNING("sndCtlEventCB: ignored unsupported event type");
- return (0);
+ AFB_WARNING("sndCtlEventCB: Error detected");
+ return -1;
}
-// Subscribe to every Alsa CtlEvent send by a given board
-PUBLIC void alsaEvtSubcribe(afb_req_t request) {
- static sndHandleT sndHandles[MAX_SND_CARD];
- evtHandleT *evtHandle = NULL;
+// Subscribe to every Alsa CtlEvent send by a given board
+STATIC afb_event_t alsaEvtSubscribeAlsaControlEvent(afb_req_t request, sndCardsT *sndCards, queryValuesT *queryValues) {
+ sndHandleT *currentSndHandle = NULL;
snd_ctl_t *ctlDev = NULL;
- int err, idx, cardId, idxFree = -1;
+ int err, cardId;
snd_ctl_card_info_t *cardinfo;
- queryValuesT queryValues;
-
- json_object *queryJ = alsaCheckQuery(request, &queryValues);
- if (!queryJ) goto OnErrorExit;
// open control interface for devid
- err = snd_ctl_open(&ctlDev, queryValues.devid, SND_CTL_READONLY);
+ err = snd_ctl_open(&ctlDev, queryValues->devid, SND_CTL_READONLY);
if (err < 0) {
- afb_req_fail_f(request, "devid-unknown", "SndCard devid=%s Not Found err=%s", queryValues.devid, snd_strerror(err));
+ afb_req_fail_f(request, "devid-unknown", "SndCard devid=%s Not Found err=%s", queryValues->devid, snd_strerror(err));
goto OnErrorExit;
}
snd_ctl_card_info_alloca(&cardinfo);
- if ((err = snd_ctl_card_info(ctlDev, cardinfo)) < 0) {
- afb_req_fail_f(request, "devid-invalid", "SndCard devid=%s Not Found err=%s", queryValues.devid, snd_strerror(err));
+ err = snd_ctl_card_info(ctlDev, cardinfo);
+ if (err < 0) {
+ afb_req_fail_f(request, "devid-invalid", "SndCard devid=%s Not Found err=%s", queryValues->devid, snd_strerror(err));
goto OnErrorExit;
}
cardId = snd_ctl_card_info_get_card(cardinfo);
- // search for an existing subscription and mark 1st free slot
- for (idx = 0; idx < MAX_SND_CARD; idx++) {
- if (sndHandles[idx].ucount > 0 && cardId == sndHandles[idx].cardId) {
- evtHandle = sndHandles[idx].evtHandle;
- break;
- } else if (idxFree == -1) idxFree = idx;
- };
-
- // if not subscription exist for the event let's create one
- if (idx == MAX_SND_CARD) {
+ if(cardId < 0 || cardId >= MAX_SND_CARD) {
+ afb_req_fail_f(request, "devid-invalid", "SndCard cardId=%i invalid", cardId);
+ goto OnErrorExit;
+ }
- // reach MAX_SND_CARD event registration
- if (idxFree == -1) {
- afb_req_fail_f(request, "register-toomany", "Cannot register new event Maxcard==%d", idx);
- goto OnErrorExit;
- }
+ currentSndHandle = &sndCards->sndHandles[cardId];
- evtHandle = malloc(sizeof (evtHandleT));
- evtHandle->ctlDev = ctlDev;
- evtHandle->mode = queryValues.mode;
- sndHandles[idxFree].ucount = 0;
- sndHandles[idxFree].cardId = cardId;
- sndHandles[idxFree].evtHandle = evtHandle;
+ // 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 = queryValues->mode;
// subscribe for sndctl events attached to devid
- err = snd_ctl_subscribe_events(evtHandle->ctlDev, 1);
+ 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", queryValues.devid, err);
+ afb_req_fail_f(request, "subscribe-fail", "Cannot subscribe events from devid=%s err=%d", queryValues->devid, err);
goto OnErrorExit;
}
// get pollfd attach to this sound board
- snd_ctl_poll_descriptors(evtHandle->ctlDev, &evtHandle->pfds, 1);
+ snd_ctl_poll_descriptors(currentSndHandle->evtHandle->ctlDev, &currentSndHandle->evtHandle->pfds, 1);
// register sound event to binder main loop
- err = sd_event_add_io(afb_daemon_get_event_loop(), &evtHandle->src, evtHandle->pfds.fd, EPOLLIN, sndCtlEventCB, evtHandle);
+ 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", queryValues.devid, err);
+ afb_req_fail_f(request, "register-mainloop", "Cannot hook events to mainloop devid=%s err=%d", queryValues->devid, err);
goto OnErrorExit;
}
// create binder event attached to devid name
- evtHandle->afbevt = afb_daemon_make_event(queryValues.devid);
- if (!afb_event_is_valid(evtHandle->afbevt)) {
- afb_req_fail_f(request, "register-event", "Cannot register new binder event name=%s", queryValues.devid);
+ currentSndHandle->evtHandle->afbevt = afb_daemon_make_event(queryValues->devid);
+ if (!afb_event_is_valid(currentSndHandle->evtHandle->afbevt)) {
+ afb_req_fail_f(request, "register-event", "Cannot register new binder event name=%s", queryValues->devid);
goto OnErrorExit;
}
+ }
+ else if (ctlDev) {
+ snd_ctl_close(ctlDev);
+ }
+
+ return currentSndHandle->evtHandle->afbevt;
+
+OnErrorExit:
+ if (ctlDev)
+ snd_ctl_close(ctlDev);
- // everything looks OK let's move forward
- idx = idxFree;
+ return NULL;
+}
+
+// Subscribe to alsacore event
+PUBLIC void alsaEvtSubcribe(afb_req_t request) {
+ static sndCardsT *sndCards = NULL;
+ afb_event_t eventToSubscribe;
+ int err;
+ queryValuesT queryValues;
+
+ json_object *queryJ;
+
+ if(! sndCards) {
+ sndCards = calloc(1, sizeof(sndCardsT));
}
+ queryJ = alsaCheckQuery(request, &queryValues);
+ if (!queryJ) return;
+
+ eventToSubscribe = alsaEvtSubscribeAlsaControlEvent(request, sndCards, &queryValues);
+
+ if(! eventToSubscribe)
+ return;
+
// subscribe to binder event
- err = afb_req_subscribe(request, evtHandle->afbevt);
- if (err != 0) {
- afb_req_fail_f(request, "register-eventname", "Cannot subscribe binder event name=%s [invalid channel]", queryValues.devid);
- goto OnErrorExit;
+ err = afb_req_subscribe(request, eventToSubscribe);
+ if (err) {
+ afb_req_fail_f(request, "register-eventname", "Cannot subscribe binder event");
+ return;
}
- // increase usage count and return success
- sndHandles[idx].ucount++;
afb_req_success(request, NULL, NULL);
- return;
-
-OnErrorExit:
- if (ctlDev) snd_ctl_close(ctlDev);
- return;
}
// Subscribe to every Alsa CtlEvent send by a given board