diff options
Diffstat (limited to 'alsa-binding/Alsa-RegEvt.c')
-rw-r--r-- | alsa-binding/Alsa-RegEvt.c | 188 |
1 files changed, 177 insertions, 11 deletions
diff --git a/alsa-binding/Alsa-RegEvt.c b/alsa-binding/Alsa-RegEvt.c index ce81721..be46c17 100644 --- a/alsa-binding/Alsa-RegEvt.c +++ b/alsa-binding/Alsa-RegEvt.c @@ -37,8 +37,10 @@ typedef struct { } sndHandleT; typedef struct { + int cardid; char *devid; char *apiprefix; + char *drivername; char *shortname; char *longname; } cardRegistryT; @@ -247,20 +249,32 @@ OnErrorExit: STATIC json_object *alsaProbeCardId(afb_req request) { char devid [10]; - const char *ctlName, *shortname, *longname; - int card, err, index, idx; - json_object *responseJ; + const char *ctlName, *shortname, *longname, *mixername, *drivername; + int done, mode, card, err, index, idx; + json_object *responseJ, *tmpJ; snd_ctl_t *ctlDev; snd_ctl_card_info_t *cardinfo; - const char *sndname = afb_req_value(request, "sndname"); - if (sndname == NULL) { + json_object* queryJ = afb_req_json(request); + + done = json_object_object_get_ex(queryJ, "sndname", &tmpJ); + if (!done || json_object_get_type(tmpJ) != json_type_string) { afb_req_fail_f(request, "argument-missing", "sndname=SndCardName missing"); goto OnErrorExit; } + const char *sndname = json_object_get_string(tmpJ); + + done = json_object_object_get_ex(queryJ, "mode", &tmpJ); + if (!done) { + mode = 0; + } else { + mode = json_object_get_int(tmpJ); + } + // loop on potential card number snd_ctl_card_info_alloca(&cardinfo); + char *driverId = NULL; // when not name match use drivername as backup plan for (card = 0; card < MAX_SND_CARD; card++) { // build card devid and probe it @@ -276,26 +290,60 @@ STATIC json_object *alsaProbeCardId(afb_req request) { ctlName = snd_ctl_card_info_get_id(cardinfo); shortname = snd_ctl_card_info_get_name(cardinfo); longname = snd_ctl_card_info_get_longname(cardinfo); + mixername = snd_ctl_card_info_get_mixername(cardinfo); + drivername = snd_ctl_card_info_get_driver(cardinfo); snd_ctl_close(ctlDev); // check if short|long name match - if (!strcmp(sndname, ctlName)) break; - if (!strcmp(sndname, shortname)) break; - if (!strcmp(sndname, longname)) break; + if (!strcasecmp(sndname, ctlName)) break; + if (!strcasecmp(sndname, shortname)) break; + if (!strcasecmp(sndname, drivername) && driverId==NULL) { + driverId=strdup(devid); + } + if (!strcasecmp(sndname, longname)) break; } if (card == MAX_SND_CARD) { - afb_req_fail_f(request, "ctlDev-notfound", "Fail to find card with name=%s", sndname); - goto OnErrorExit; + if (!driverId) { + afb_req_fail_f(request, "ctlDev-notfound", "Fail to find card with name=%s", sndname); + goto OnErrorExit; + } + + + err = snd_ctl_open(&ctlDev, driverId, SND_CTL_READONLY); + if (err < 0) { + afb_req_fail_f(request, "ctlDev-notfound", "Fail to find card with name=%s devid=%s", sndname, devid); + goto OnErrorExit; + } + + + // Sound not found by name, backup to driver name + snd_ctl_card_info(ctlDev, cardinfo); + index = snd_ctl_card_info_get_card(cardinfo); + ctlName = snd_ctl_card_info_get_id(cardinfo); + shortname = snd_ctl_card_info_get_name(cardinfo); + longname = snd_ctl_card_info_get_longname(cardinfo); + mixername = snd_ctl_card_info_get_mixername(cardinfo); + drivername = snd_ctl_card_info_get_driver(cardinfo); + AFB_WARNING("alsaProbeCardId Fallbak to HAL=%s ==> devid=%s name=%s long=%s\n ", drivername, driverId, shortname, longname); + free(driverId); + snd_ctl_close(ctlDev); } // proxy ctlevent as a binder event responseJ = json_object_new_object(); json_object_object_add(responseJ, "index", json_object_new_int(index)); + json_object_object_add(responseJ, "cardid", json_object_new_int(card)); json_object_object_add(responseJ, "devid", json_object_new_string(devid)); json_object_object_add(responseJ, "shortname", json_object_new_string(shortname)); - json_object_object_add(responseJ, "longname", json_object_new_string(longname)); + + if (mode > 0) { + json_object_object_add(responseJ, "longname", json_object_new_string(longname)); + json_object_object_add(responseJ, "mixername", json_object_new_string(mixername)); + json_object_object_add(responseJ, "drivername", json_object_new_string(drivername)); + + } // search for a HAL binder card mapping name to api prefix for (idx = 0; (idx < MAX_SND_CARD && cardRegistry[idx]); idx++) { @@ -319,6 +367,29 @@ PUBLIC void alsaGetCardId(afb_req request) { if (responseJ) afb_req_success(request, responseJ, NULL); } + +// Return HAL information about a given sound card ID + +STATIC int getHalFromCardId(int cardid, json_object *responseJ) { + + for (int idx = 0; idx < MAX_SND_CARD; idx++) { + if (!cardRegistry[idx]) goto OnErrorExit; + + if (cardRegistry[idx]->cardid == cardid) { + json_object_object_add(responseJ, "api", json_object_new_string(cardRegistry[idx]->apiprefix)); + if (cardRegistry[idx]->shortname)json_object_object_add(responseJ, "shortname", json_object_new_string(cardRegistry[idx]->shortname)); + if (cardRegistry[idx]->longname) json_object_object_add(responseJ, "longname", json_object_new_string(cardRegistry[idx]->longname)); + break; + } + } + + return 0; + +OnErrorExit: + return -1; +} + + // Return list of active resgistrated HAL with corresponding sndcard PUBLIC void alsaActiveHal(afb_req request) { @@ -331,6 +402,7 @@ PUBLIC void alsaActiveHal(afb_req request) { json_object_object_add(haldevJ, "api", json_object_new_string(cardRegistry[idx]->apiprefix)); if (cardRegistry[idx]->devid) json_object_object_add(haldevJ, "devid", json_object_new_string(cardRegistry[idx]->devid)); if (cardRegistry[idx]->shortname)json_object_object_add(haldevJ, "shortname", json_object_new_string(cardRegistry[idx]->shortname)); + if (cardRegistry[idx]->drivername)json_object_object_add(haldevJ, "drivername", json_object_new_string(cardRegistry[idx]->drivername)); if (cardRegistry[idx]->longname) json_object_object_add(haldevJ, "longname", json_object_new_string(cardRegistry[idx]->longname)); json_object_array_add(responseJ, haldevJ); } @@ -372,11 +444,18 @@ PUBLIC void alsaRegisterHal(afb_req request) { cardRegistry[index] = malloc(sizeof (cardRegistry)); cardRegistry[index]->apiprefix = strdup(apiPrefix); cardRegistry[index]->shortname = strdup(shortname); + + json_object_object_get_ex(responseJ, "cardid", &tmpJ); + cardRegistry[index]->cardid = json_object_get_int(tmpJ); done = json_object_object_get_ex(responseJ, "devid", &tmpJ); if (done) cardRegistry[index]->devid = strdup(json_object_get_string(tmpJ)); else cardRegistry[index]->devid = NULL; + done = json_object_object_get_ex(responseJ, "drivername", &tmpJ); + if (done) cardRegistry[index]->drivername = strdup(json_object_get_string(tmpJ)); + else cardRegistry[index]->drivername = NULL; + done = json_object_object_get_ex(responseJ, "longname", &tmpJ); if (done) cardRegistry[index]->longname = strdup(json_object_get_string(tmpJ)); else cardRegistry[index]->longname = NULL; @@ -395,3 +474,90 @@ OnErrorExit: return; } +PUBLIC void alsaPcmInfo (struct afb_req request) { + int done, mode, err; + json_object *tmpJ, *responseJ = NULL; + snd_pcm_t *pcmHandle = NULL; + snd_pcm_info_t * pcmInfo = NULL; + + json_object* queryJ = afb_req_json(request); + + done = json_object_object_get_ex(queryJ, "name", &tmpJ); + if (!done || json_object_get_type(tmpJ) != json_type_string) { + afb_req_fail_f(request, "name:invalid", "PCM 'name:xxx' missing or not a string query='%s'", json_object_get_string(queryJ)); + goto OnErrorExit; + } + const char *pcmName = json_object_get_string(tmpJ); + + done = json_object_object_get_ex(queryJ, "stream", &tmpJ); + if (done && json_object_get_type(tmpJ) != json_type_int) { + afb_req_fail_f(request, "stream:invalid", "PCM 'stream:SND_PCM_STREAM_PLAYBACK/SND_PCM_STREAM_CAPTURE' should be integer query='%s'", json_object_get_string(queryJ)); + goto OnErrorExit; + } + snd_pcm_stream_t pcmStream = json_object_get_int(tmpJ); + + done = json_object_object_get_ex(queryJ, "mode", &tmpJ); + if (!done) { + mode = 0; + } else { + mode = json_object_get_int(tmpJ); + } + + // open PCM from its name + err= snd_pcm_open(&pcmHandle, pcmName, pcmStream, 0); + if (err < 0) { + afb_req_fail_f(request, "pcm:invalid", "PCM 'name:%s' does cannot open error=%s", pcmName, snd_strerror(err)); + goto OnErrorExit; + } + + // get pcm info + snd_pcm_info_alloca(&pcmInfo); + err = snd_pcm_info(pcmHandle,pcmInfo); + if (err < 0) { + afb_req_fail_f(request, "pcm:error", "PCM 'name:%s' fail to retrieve info error=%s", pcmName, snd_strerror(err)); + goto OnErrorExit; + } + + // get sub-device number + int cardId = snd_pcm_info_get_card(pcmInfo); + if (cardId < 0 ) { + afb_req_fail_f(request, "pcm:error", "PCM 'name:%s' fail to retrieve sndcard device error=%s", pcmName, snd_strerror(cardId)); + goto OnErrorExit; + } + + // prepare an object for response + responseJ = json_object_new_object(); + + err = getHalFromCardId (cardId, responseJ); + if (err < 0 ) { + afb_req_fail_f(request, "pcm:error", "PCM 'name:%s' snddev=hw:%d fail to retrieve hal API", pcmName, cardId); + goto OnErrorExit; + } + + json_object_object_add(responseJ, "type", json_object_new_int(snd_pcm_type(pcmHandle))); + + // in mode mode we return full info about PCM + if (mode > 0) { + json_object_object_add(responseJ, "stream", json_object_new_int(snd_pcm_info_get_stream (pcmInfo))); + json_object_object_add(responseJ, "cardid", json_object_new_int(snd_pcm_info_get_card(pcmInfo))); + json_object_object_add(responseJ, "devid" , json_object_new_int(snd_pcm_info_get_device (pcmInfo))); + json_object_object_add(responseJ, "subid" , json_object_new_int(snd_pcm_info_get_subdevice (pcmInfo))); + } + + // in super mode we also return information about snd card + if (mode > 1) { + + json_object_object_add(responseJ, "id" , json_object_new_string(snd_pcm_info_get_id (pcmInfo))); + json_object_object_add(responseJ, "name" , json_object_new_string(snd_pcm_info_get_name (pcmInfo))); + json_object_object_add(responseJ, "subdev" , json_object_new_string(snd_pcm_info_get_subdevice_name (pcmInfo))); + } + + afb_req_success(request, responseJ, NULL); + snd_pcm_close (pcmHandle); + return; + +OnErrorExit: + if (responseJ) json_object_put (responseJ); + if (pcmHandle) snd_pcm_close (pcmHandle); + return; +} |