summaryrefslogtreecommitdiffstats
path: root/alsa-binding
diff options
context:
space:
mode:
Diffstat (limited to 'alsa-binding')
-rw-r--r--alsa-binding/Alsa-ApiHat.c3
-rw-r--r--alsa-binding/Alsa-ApiHat.h20
-rw-r--r--alsa-binding/Alsa-RegEvt.c74
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) {