diff options
-rw-r--r-- | alsa-binding/Alsa-ApiHat.c | 3 | ||||
-rw-r--r-- | alsa-binding/Alsa-ApiHat.h | 20 | ||||
-rw-r--r-- | alsa-binding/Alsa-RegEvt.c | 74 |
3 files changed, 70 insertions, 27 deletions
diff --git a/alsa-binding/Alsa-ApiHat.c b/alsa-binding/Alsa-ApiHat.c index 470467b..5575a9a 100644 --- a/alsa-binding/Alsa-ApiHat.c +++ b/alsa-binding/Alsa-ApiHat.c @@ -44,7 +44,8 @@ static const afb_verb_t api_verbs[] = { { .verb = "infoget", .callback = alsaGetInfo, .info="Return sound cards list"}, { .verb = "ctlget", .callback = alsaGetCtls, .info="Get one or many control values"}, { .verb = "ctlset", .callback = alsaSetCtls, .info="Set one control or more"}, - { .verb = "subscribe", .callback = alsaEvtSubcribe, .info="subscribe to alsa events"}, + { .verb = "subscribe", .callback = alsaEvtSubscribe, .info="subscribe to alsa events"}, + { .verb = "unsubscribe", .callback = alsaEvtUnsubscribe, .info="unsubscribe to alsa events"}, { .verb = "cardidget", .callback = alsaGetCardId, .info="get sound card id"}, { .verb = "halregister", .callback = alsaRegisterHal, .info="register a new HAL in alsacore"}, { .verb = "hallist", .callback = alsaActiveHal, .info="Get list of currently active HAL"}, diff --git a/alsa-binding/Alsa-ApiHat.h b/alsa-binding/Alsa-ApiHat.h index 209c65b..21aaa61 100644 --- a/alsa-binding/Alsa-ApiHat.h +++ b/alsa-binding/Alsa-ApiHat.h @@ -44,10 +44,10 @@ #define NO_SUBDEVICE_SELECTED -1 typedef enum { - QUERY_QUIET =0, - QUERY_COMPACT =1, - QUERY_VERBOSE =2, - QUERY_FULL =3, + QUERY_QUIET = 0, + QUERY_COMPACT = 1, + QUERY_VERBOSE = 2, + QUERY_FULL = 3, } queryModeE; typedef enum { @@ -60,6 +60,11 @@ typedef enum { CONTROL_REMOVE } ControlAddRemoveT; +typedef enum { + EVENT_SUBSCRIBE, + EVENT_UNSUBSCRIBE +} EventSubscribeUnsubscribeT; + // structure to store card typedef struct { int cardNb; @@ -77,8 +82,8 @@ typedef struct { // generic structure to pass parsed query values typedef struct { - json_object *numidsJ; - int count; + json_object *numidsJ; + int count; } controlQueryValuesT; // use to store crl numid user request @@ -114,7 +119,8 @@ PUBLIC void alsaAddCustomCtls(afb_req_t request); PUBLIC void alsaRemoveCustomCtls(afb_req_t request); // AlsaRegEvt -PUBLIC void alsaEvtSubcribe (afb_req_t request); +PUBLIC void alsaEvtSubscribe (afb_req_t request); +PUBLIC void alsaEvtUnsubscribe (afb_req_t request); PUBLIC void alsaGetCardId (afb_req_t request); PUBLIC void alsaRegisterHal (afb_req_t request); PUBLIC void alsaActiveHal (afb_req_t request); diff --git a/alsa-binding/Alsa-RegEvt.c b/alsa-binding/Alsa-RegEvt.c index a60ffc8..a9cce2b 100644 --- a/alsa-binding/Alsa-RegEvt.c +++ b/alsa-binding/Alsa-RegEvt.c @@ -192,7 +192,7 @@ STATIC void freeCardAlsaControlHandle(ctrlEvtHandleT **cardControlHandle) STATIC void updateSelectedAlsaCardsAvailabilityAndFireEvents(sndCardsT *sndCards, int first, int last) { - int idx, available; + int idx, available, subscriberCount = -1; char *cardId; json_object *generatedEventJ = NULL; @@ -213,7 +213,7 @@ STATIC void updateSelectedAlsaCardsAvailabilityAndFireEvents(sndCardsT *sndCards if(sndCards->cardMonitoring && ! wrap_json_pack(&generatedEventJ, "{s:o}", "cardAdded", getCardInfo(idx))) - afb_event_push(sndCards->cardMonitoring->afbevt, generatedEventJ); + subscriberCount = afb_event_push(sndCards->cardMonitoring->afbevt, generatedEventJ); } else if(! available && sndCards->sndHandles[idx].available) { sndCards->sndHandles[idx].available = 0; @@ -221,7 +221,7 @@ STATIC void updateSelectedAlsaCardsAvailabilityAndFireEvents(sndCardsT *sndCards if(sndCards->cardMonitoring && (asprintf(&cardId, "hw:%i", idx) > 0) && ! wrap_json_pack(&generatedEventJ, "{s:s}", "cardRemoved", cardId)) - afb_event_push(sndCards->cardMonitoring->afbevt, generatedEventJ); + subscriberCount = afb_event_push(sndCards->cardMonitoring->afbevt, generatedEventJ); if(sndCards->sndHandles[idx].evtHandle) { sd_event_source_unref(sndCards->sndHandles[idx].evtHandle->src); @@ -232,6 +232,11 @@ STATIC void updateSelectedAlsaCardsAvailabilityAndFireEvents(sndCardsT *sndCards } } } + + if(! subscriberCount) { + AFB_WARNING("Nobody listening for 'card-monitoring' events, stop monitoring from now on"); + freeSndCardHandle(&sndCards->cardMonitoring); + } } STATIC void updateAllAlsaCardsAvailabilityAndFireEvents(sndCardsT *sndCards) { @@ -326,7 +331,7 @@ STATIC int sndCardEventCB(sd_event_source* src, int fd, uint32_t revents, void* // 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; + int err, ctlNumid, subscriberCount = -1; unsigned int mask; snd_ctl_elem_id_t *elemId; @@ -398,21 +403,29 @@ STATIC int sndCtlEventCB(sd_event_source* src, int fd, uint32_t revents, void* u wrap_json_object_add(ctlEventJ, ctlEventAdditionalInfoJ); AFB_DEBUG("sndCtlEventCB=%s", json_object_get_string(ctlEventJ)); + subscriberCount = afb_event_push(sndHandle->evtHandle->afbevt, ctlEventJ); + } - afb_event_push(sndHandle->evtHandle->afbevt, ctlEventJ); + if(! subscriberCount) { + AFB_WARNING("Nobody listening for card %i control events, stop monitoring from now on", snd_ctl_event_elem_get_interface(eventId)); + freeCardAlsaControlHandle(&sndHandle->evtHandle); + return -4; } return 0; } // 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) +STATIC afb_event_t alsaEvtSubscribeUnsubscribeSoundCardEvent(afb_req_t request, + sndCardsT *sndCards, + EventSubscribeUnsubscribeT subscriptionType) { int err; if(sndCards->cardMonitoring) return sndCards->cardMonitoring->afbevt; + else if(subscriptionType == EVENT_UNSUBSCRIBE) + return NULL; updateAllAlsaCardsAvailabilityAndFireEvents(sndCards); @@ -467,9 +480,10 @@ STATIC afb_event_t alsaEvtSubscribeSoundCardEvent(afb_req_t request, } // Subscribe to every Alsa CtlEvent send by a given board -STATIC afb_event_t alsaEvtSubscribeAlsaControlEvent(afb_req_t request, - sndCardsT *sndCards, - char* devId) +STATIC afb_event_t alsaEvtSubscribeUnsubscribeAlsaControlEvent(afb_req_t request, + sndCardsT *sndCards, + char* devId, + EventSubscribeUnsubscribeT subscriptionType) { sndHandleT *currentSndHandle = NULL; snd_ctl_t *ctlDev = NULL; @@ -505,6 +519,10 @@ STATIC afb_event_t alsaEvtSubscribeAlsaControlEvent(afb_req_t request, snd_ctl_close(ctlDev); return currentSndHandle->evtHandle->afbevt; } + else if(subscriptionType == EVENT_UNSUBSCRIBE) { + snd_ctl_close(ctlDev); + return NULL; + } currentSndHandle->evtHandle = malloc(sizeof (ctrlEvtHandleT)); currentSndHandle->evtHandle->ctlDev = ctlDev; @@ -545,8 +563,9 @@ STATIC afb_event_t alsaEvtSubscribeAlsaControlEvent(afb_req_t request, } // Subscribe to alsacore event -PUBLIC void alsaEvtSubcribe(afb_req_t request) { - int err; +PUBLIC void alsaEvtSubscribeUnsubscribe(afb_req_t request, EventSubscribeUnsubscribeT subscriptionType) +{ + int err = -1; EventTypeT eventType; @@ -554,7 +573,7 @@ PUBLIC void alsaEvtSubcribe(afb_req_t request) { static sndCardsT *sndCards = NULL; - afb_event_t eventToSubscribe; + afb_event_t eventToSubscribeUnsubscribe; json_object *queryJ; @@ -574,11 +593,11 @@ PUBLIC void alsaEvtSubcribe(afb_req_t request) { return; } - eventToSubscribe = alsaEvtSubscribeAlsaControlEvent(request, sndCards, devId); + eventToSubscribeUnsubscribe = alsaEvtSubscribeUnsubscribeAlsaControlEvent(request, sndCards, devId, subscriptionType); break; case CARD_MONITORING_EVENTS: - eventToSubscribe = alsaEvtSubscribeSoundCardEvent(request, sndCards); + eventToSubscribeUnsubscribe = alsaEvtSubscribeUnsubscribeSoundCardEvent(request, sndCards, subscriptionType); break; case UNKNOWN_EVENT: @@ -587,19 +606,36 @@ PUBLIC void alsaEvtSubcribe(afb_req_t request) { return; } - if(! eventToSubscribe) + if(! eventToSubscribeUnsubscribe) return; - // subscribe to binder event - err = afb_req_subscribe(request, eventToSubscribe); + // subscribe/unsubscribe to binder event + if(subscriptionType == EVENT_SUBSCRIBE) + err = afb_req_subscribe(request, eventToSubscribeUnsubscribe); + else if(subscriptionType == EVENT_UNSUBSCRIBE) + err = afb_req_unsubscribe(request, eventToSubscribeUnsubscribe); + if(err) { - afb_req_fail_f(request, "register-eventname", "Cannot subscribe binder event"); + afb_req_fail_f(request, + "register-eventname", + "Cannot %s binder event", + (subscriptionType == EVENT_SUBSCRIBE) ? "subscribe" : "unsubscribe"); return; } afb_req_success(request, NULL, NULL); } +PUBLIC void alsaEvtSubscribe(afb_req_t request) +{ + alsaEvtSubscribeUnsubscribe(request, EVENT_SUBSCRIBE); +} + +PUBLIC void alsaEvtUnsubscribe(afb_req_t request) +{ + alsaEvtSubscribeUnsubscribe(request, EVENT_UNSUBSCRIBE); +} + // Subscribe to every Alsa CtlEvent send by a given board STATIC json_object *alsaProbeCardId(afb_req_t request) { |