From c326a053cdf8a4a9ce0fb02448293b45083d553c Mon Sep 17 00:00:00 2001 From: fulup Date: Sat, 1 Jul 2017 00:22:00 +0200 Subject: Ongoing work --- ALSA-afb/Alsa-AddCtl.c | 54 ++++- ALSA-afb/Alsa-ApiHat.c | 8 +- ALSA-afb/Alsa-ApiHat.h | 23 +- ALSA-afb/Alsa-RegEvt.c | 309 +++++++++++++++++++++++++++ ALSA-afb/Alsa-SetGet.c | 318 +--------------------------- ALSA-afb/Alsa-Ucm.c | 12 +- ALSA-afb/CMakeLists.txt | 2 +- CMakeLists.txt | 11 +- HAL-afb/CMakeLists.txt | 2 +- HAL-afb/HAL-interface/hal-interface.c | 112 ++++------ HAL-afb/HAL-interface/hal-interface.h | 12 +- HAL-afb/HDA-intel/IntelHdaHAL.c | 73 +++---- HAL-afb/Scarlett-Focusrite/CMakeLists.txt | 42 ++++ HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c | 74 +++++++ README.md | 17 +- conf.d/app-templates | 2 +- conf.d/autobuild/agl/autobuild | 47 ++++ conf.d/autobuild/linux/autobuild | 47 ++++ conf.d/cmake/config.cmake | 134 ++++++++++++ conf.d/config.cmake | 122 ----------- nbproject/configurations.xml | 58 +++-- 21 files changed, 887 insertions(+), 592 deletions(-) create mode 100644 ALSA-afb/Alsa-RegEvt.c create mode 100644 HAL-afb/Scarlett-Focusrite/CMakeLists.txt create mode 100644 HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c create mode 100755 conf.d/autobuild/agl/autobuild create mode 100755 conf.d/autobuild/linux/autobuild create mode 100644 conf.d/cmake/config.cmake delete mode 100644 conf.d/config.cmake diff --git a/ALSA-afb/Alsa-AddCtl.c b/ALSA-afb/Alsa-AddCtl.c index 7593f2d..2edec5f 100644 --- a/ALSA-afb/Alsa-AddCtl.c +++ b/ALSA-afb/Alsa-AddCtl.c @@ -67,7 +67,7 @@ STATIC int addOneSndCtl(afb_req request, snd_ctl_t *ctlDev, json_object *ctlJ) // set info event ID and get value snd_ctl_elem_info_alloca(&elemInfo); snd_ctl_elem_info_set_name (elemInfo, ctlName); // map ctlInfo to ctlId elemInfo is updated !!! - snd_ctl_elem_info_set_numid(elemInfo, ctlNumid); // map ctlInfo to ctlId elemInfo is updated !!! + snd_ctl_elem_info_set_numid(elemInfo, ctlNumid); // map ctlInfo to ctlId elemInfo is updated !!! if (snd_ctl_elem_info(ctlDev, elemInfo) >= 0) { afb_req_fail_f (request, "ctl-already-exist", "crl=%s name/numid not unique", json_object_to_json_string(ctlJ)); @@ -101,10 +101,58 @@ STATIC int addOneSndCtl(afb_req request, snd_ctl_t *ctlDev, json_object *ctlJ) afb_req_fail_f (request, "ctl-invalid-type", "crl=%s invalid/unknown type", json_object_to_json_string(ctlJ)); goto OnErrorExit; } - - + return 0; OnErrorExit: return -1; } + +PUBLIC void alsaAddCustomCtls(afb_req request) { + int err; + json_object *ctlsJ; + enum json_type; + snd_ctl_t *ctlDev=NULL; + const char *devid; + + devid = afb_req_value(request, "devid"); + if (devid == NULL) { + afb_req_fail_f (request, "devid-missing", "devid MUST be defined for alsaAddCustomCtls"); + goto OnErrorExit; + } + + // open control interface for devid + err = snd_ctl_open(&ctlDev, devid, SND_CTL_READONLY); + if (err < 0) { + afb_req_fail_f (request, "devid-unknown", "SndCard devid=[%s] Not Found err=%s", devid, snd_strerror(err)); + goto OnErrorExit; + } + + // extract sound controls and parse json + ctlsJ = json_tokener_parse (afb_req_value(request, "ctls")); + if (!ctlsJ) { + afb_req_fail_f (request, "ctls-missing", "ctls MUST be defined as a JSON array for alsaAddCustomCtls"); + goto OnErrorExit; + } + + switch (json_object_get_type(ctlsJ)) { + case json_type_object: + addOneSndCtl(request, ctlDev, ctlsJ); + break; + + case json_type_array: + for (int idx= 1; idx < json_object_array_length (ctlsJ); idx++) { + json_object *ctlJ = json_object_array_get_idx (ctlsJ, idx); + addOneSndCtl(request, ctlDev, ctlJ) ; + } + break; + + default: + afb_req_fail_f (request, "ctls-invalid","ctls=%s not valid JSON array", json_object_to_json_string(ctlsJ)); + goto OnErrorExit; + } + + OnErrorExit: + if (ctlDev) snd_ctl_close(ctlDev); + return; +} \ No newline at end of file diff --git a/ALSA-afb/Alsa-ApiHat.c b/ALSA-afb/Alsa-ApiHat.c index ced5d50..588e91b 100644 --- a/ALSA-afb/Alsa-ApiHat.c +++ b/ALSA-afb/Alsa-ApiHat.c @@ -31,13 +31,13 @@ /* * array of the verbs exported to afb-daemon */ -static const struct afb_verb_v2 binding_verbs[] = { +static const struct afb_verb_v2 api_verbs[] = { /* VERB'S NAME FUNCTION TO CALL */ { .verb= "ping" , .callback= pingtest }, { .verb= "getinfo", .callback= alsaGetInfo}, { .verb= "getctls", .callback= alsaGetCtls}, { .verb= "setctls", .callback= alsaSetCtls}, - { .verb= "subscribe", .callback= alsaSubcribe}, + { .verb= "subscribe", .callback= alsaEvtSubcribe}, { .verb= "getcardid", .callback= alsaGetCardId}, { .verb= "registerHal", .callback= alsaRegisterHal}, { .verb= "ucmquery", .callback= alsaUseCaseQuery}, @@ -45,7 +45,7 @@ static const struct afb_verb_v2 binding_verbs[] = { { .verb= "ucmget", .callback= alsaUseCaseGet}, { .verb= "ucmreset", .callback= alsaUseCaseReset}, { .verb= "ucmclose", .callback= alsaUseCaseClose}, - { .verb= "addctl", .callback= alsaAddCustomCtl}, + { .verb= "addcustomctl",.callback= alsaAddCustomCtls}, { .verb= NULL } /* marker for end of the array */ }; @@ -54,5 +54,5 @@ static const struct afb_verb_v2 binding_verbs[] = { */ const struct afb_binding_v2 afbBindingV2 = { .api = "alsacore", - .verbs = binding_verbs, + .verbs = api_verbs, }; diff --git a/ALSA-afb/Alsa-ApiHat.h b/ALSA-afb/Alsa-ApiHat.h index c33f92e..bd8518f 100644 --- a/ALSA-afb/Alsa-ApiHat.h +++ b/ALSA-afb/Alsa-ApiHat.h @@ -19,6 +19,9 @@ #ifndef ALSALIBMAPPING_H #define ALSALIBMAPPING_H + +#include +#include #include "audio-interface.h" typedef enum { @@ -34,17 +37,24 @@ typedef struct { int count; } queryValuesT; +// use to store crl numid user request +typedef struct { + unsigned int numId; + json_object *jToken; + json_object *jValues; + int used; +} ctlRequestT; + // import from AlsaAfbBinding extern const struct afb_binding_interface *afbIface; PUBLIC int alsaCheckQuery (struct afb_req request, queryValuesT *queryValues); // AlseCoreSetGet exports +PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, int quiet); PUBLIC void alsaGetInfo (struct afb_req request); PUBLIC void alsaGetCtls(struct afb_req request); PUBLIC void alsaSetCtls(struct afb_req request); -PUBLIC void alsaSubcribe (struct afb_req request); -PUBLIC void alsaGetCardId (struct afb_req request); -PUBLIC void alsaRegisterHal (struct afb_req request); + // AlsaUseCase exports PUBLIC void alsaUseCaseQuery(struct afb_req request); @@ -52,9 +62,12 @@ PUBLIC void alsaUseCaseSet(struct afb_req request); PUBLIC void alsaUseCaseGet(struct afb_req request); PUBLIC void alsaUseCaseClose(struct afb_req request); PUBLIC void alsaUseCaseReset(struct afb_req request); -PUBLIC void alsaAddCustomCtl(struct afb_req request); - +PUBLIC void alsaAddCustomCtls(struct afb_req request); +// AlsaRegEvt +PUBLIC void alsaEvtSubcribe (struct afb_req request); +PUBLIC void alsaGetCardId (struct afb_req request); +PUBLIC void alsaRegisterHal (struct afb_req request); #endif /* ALSALIBMAPPING_H */ diff --git a/ALSA-afb/Alsa-RegEvt.c b/ALSA-afb/Alsa-RegEvt.c new file mode 100644 index 0000000..e06cf87 --- /dev/null +++ b/ALSA-afb/Alsa-RegEvt.c @@ -0,0 +1,309 @@ +/* + * AlsaLibMapping -- provide low level interface with ALSA lib (extracted from alsa-json-gateway code) + * Copyright (C) 2015,2016,2017, Fulup Ar Foll fulup@iot.bzh + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + +*/ + +#define _GNU_SOURCE // needed for vasprintf + +#include "Alsa-ApiHat.h" + +// generic sndctrl event handle hook to event callback when pooling +typedef struct { + struct pollfd pfds; + sd_event_source *src; + snd_ctl_t *ctlDev; + int quiet; + struct afb_event afbevt; +} evtHandleT; + +typedef struct { + int ucount; + int cardId; + evtHandleT *evtHandle; +} sndHandleT; + +typedef struct { + char *apiprefix; + char *shortname; +}cardRegistryT; + +cardRegistryT *cardRegistry[MAX_SND_CARD+1]; + +// This routine is called when ALSA event are fired +STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void* userData) { + int err; + evtHandleT *evtHandle = (evtHandleT*)userData; + snd_ctl_event_t *eventId; + json_object *ctlEventJ; + unsigned int mask; + int iface; + int device; + int subdev; + const char*devname; + ctlRequestT ctlRequest; + snd_ctl_elem_id_t *elemId; + + if ((revents & EPOLLHUP) != 0) { + AFB_NOTICE( "SndCtl hanghup [car disconnected]"); + goto ExitOnSucess; + } + + 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; + + // we only process sndctrl element + if (snd_ctl_event_get_type(eventId) != SND_CTL_EVENT_ELEM) goto ExitOnSucess; + + // we only process value changed events + mask = snd_ctl_event_elem_get_mask(eventId); + if (!(mask & SND_CTL_EVENT_MASK_VALUE)) goto ExitOnSucess; + + snd_ctl_event_elem_get_id (eventId, elemId); + + err = alsaGetSingleCtl (evtHandle->ctlDev, elemId, &ctlRequest, evtHandle->quiet); + if (err) goto OnErrorExit; + + iface = snd_ctl_event_elem_get_interface(eventId); + device = snd_ctl_event_elem_get_device(eventId); + subdev = snd_ctl_event_elem_get_subdevice(eventId); + devname= snd_ctl_event_elem_get_name(eventId); + + // proxy ctlevent as a binder event + ctlEventJ = json_object_new_object(); + json_object_object_add(ctlEventJ, "device" ,json_object_new_int (device)); + json_object_object_add(ctlEventJ, "subdev" ,json_object_new_int (subdev)); + if (evtHandle->quiet < 2) { + json_object_object_add(ctlEventJ, "iface" ,json_object_new_int (iface)); + json_object_object_add(ctlEventJ, "devname",json_object_new_string (devname)); + } + if (ctlRequest.jValues) (json_object_object_add(ctlEventJ, "values" ,ctlRequest.jValues)); + AFB_DEBUG( "sndCtlEventCB=%s", json_object_get_string(ctlEventJ)); + afb_event_push(evtHandle->afbevt, ctlEventJ); + } + + ExitOnSucess: + return 0; + + OnErrorExit: + WARNING ("sndCtlEventCB: ignored unsupported event type"); + return (0); +} + +// Subscribe to every Alsa CtlEvent send by a given board +PUBLIC void alsaEvtSubcribe (afb_req request) { + static sndHandleT sndHandles[MAX_SND_CARD]; + evtHandleT *evtHandle; + snd_ctl_t *ctlDev; + int err, idx, cardId, idxFree=-1; + snd_ctl_card_info_t *cardinfo; + queryValuesT queryValues; + + + err = alsaCheckQuery (request, &queryValues); + if (err) goto OnErrorExit; + + + // open control interface for devid + err = snd_ctl_open(&ctlDev, queryValues.devid, SND_CTL_READONLY); + if (err < 0) { + ctlDev=NULL; + 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)); + 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) { + + // 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; + } + + evtHandle = malloc (sizeof(evtHandleT)); + evtHandle->ctlDev = ctlDev; + evtHandle->quiet = queryValues.quiet; + sndHandles[idxFree].ucount = 0; + sndHandles[idxFree].cardId = cardId; + sndHandles[idxFree].evtHandle = evtHandle; + + // subscribe for sndctl events attached to devid + err = snd_ctl_subscribe_events(evtHandle->ctlDev, 1); + if (err < 0) { + 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); + + // 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); + if (err < 0) { + 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); + goto OnErrorExit; + } + + // everything looks OK let's move forward + idx=idxFree; + } + + // 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; + } + + // 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 +PUBLIC void alsaGetCardId (afb_req request) { + char devid [10]; + const char *devname, *shortname, *longname; + int card, err, index, idx; + json_object *respJson; + snd_ctl_t *ctlDev; + snd_ctl_card_info_t *cardinfo; + + const char *sndname = afb_req_value(request, "sndname"); + if (sndname == NULL) { + afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing"); + goto OnErrorExit; + } + + // loop on potential card number + snd_ctl_card_info_alloca(&cardinfo); + for (card =0; card < MAX_SND_CARD; card++) { + + // build card devid and probe it + snprintf (devid, sizeof(devid), "hw:%i", card); + + // open control interface for devid + err = snd_ctl_open(&ctlDev, devid, SND_CTL_READONLY); + if (err < 0) continue; + + // extract sound card information + snd_ctl_card_info(ctlDev, cardinfo); + index = snd_ctl_card_info_get_card(cardinfo); + devname = snd_ctl_card_info_get_id(cardinfo); + shortname= snd_ctl_card_info_get_name(cardinfo); + longname = snd_ctl_card_info_get_longname(cardinfo); + + // check if short|long name match + if (!strcmp (sndname, devname)) break; + if (!strcmp (sndname, shortname)) break; + if (!strcmp (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; + } + + // proxy ctlevent as a binder event + respJson = json_object_new_object(); + json_object_object_add(respJson, "index" ,json_object_new_int (index)); + json_object_object_add(respJson, "devid" ,json_object_new_string (devid)); + json_object_object_add(respJson, "shortname" ,json_object_new_string (shortname)); + json_object_object_add(respJson, "longname" ,json_object_new_string (longname)); + + // search for a HAL binder card mapping name to api prefix + for (idx=0; idx < MAX_SND_CARD; idx++) { + if (!strcmp (cardRegistry[idx]->shortname, shortname)) break; + } + // if a match if found, then we have an HAL for this board let's return its value + if (idx < MAX_SND_CARD) json_object_object_add(respJson, "halapi",json_object_new_string (cardRegistry[idx]->apiprefix)); + + afb_req_success(request, respJson, NULL); + return; + + OnErrorExit: + return; +} + +// Register loaded HAL with board Name and API prefix +PUBLIC void alsaRegisterHal (afb_req request) { + static int index=0; + const char *shortname, *apiPrefix; + + apiPrefix = afb_req_value(request, "prefix"); + if (apiPrefix == NULL) { + afb_req_fail_f (request, "argument-missing", "prefix=BindingApiPrefix missing"); + goto OnErrorExit; + } + + shortname = afb_req_value(request, "sndname"); + if (shortname == NULL) { + afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing"); + goto OnErrorExit; + } + + if (index == MAX_SND_CARD) { + afb_req_fail_f (request, "alsahal-toomany", "Fail to register sndname=[%s]", shortname); + goto OnErrorExit; + } + + cardRegistry[index]= malloc (sizeof(cardRegistry)); + cardRegistry[index]->apiprefix=strdup(apiPrefix); + cardRegistry[index]->shortname=strdup(shortname); + index++;cardRegistry[index]=NULL; + + // If OK return sound card Alsa ID+Info + alsaGetCardId(request); + return; + + OnErrorExit: + return; +} + diff --git a/ALSA-afb/Alsa-SetGet.c b/ALSA-afb/Alsa-SetGet.c index d6cf50d..280078c 100644 --- a/ALSA-afb/Alsa-SetGet.c +++ b/ALSA-afb/Alsa-SetGet.c @@ -26,41 +26,8 @@ #define _GNU_SOURCE // needed for vasprintf -#include -#include - #include "Alsa-ApiHat.h" -// use to store crl numid user request -typedef struct { - unsigned int numId; - json_object *jToken; - json_object *jValues; - int used; -} ctlRequestT; - -// generic sndctrl event handle hook to event callback when pooling -typedef struct { - struct pollfd pfds; - sd_event_source *src; - snd_ctl_t *ctlDev; - int quiet; - struct afb_event afbevt; -} evtHandleT; - -typedef struct { - int ucount; - int cardId; - evtHandleT *evtHandle; -} sndHandleT; - -typedef struct { - char *apiprefix; - char *shortname; -}cardRegistryT; - -cardRegistryT *cardRegistry[MAX_SND_CARD+1]; - PUBLIC void NumidsListParse (queryValuesT *queryValues, ctlRequestT *ctlRequest) { json_object *jValues; int length; @@ -103,7 +70,7 @@ PUBLIC void NumidsListParse (queryValuesT *queryValues, ctlRequestT *ctlRequest) case json_type_object: // numid+values formated as {id:xxx, val:[aa,bb...,nn]} if (!json_object_object_get_ex (ctlRequest[idx].jToken,"id", &jId) || !json_object_object_get_ex (ctlRequest[idx].jToken,"val",&jVal)) { - NOTICE("Invalid Json=%s missing 'id'|'val'", json_object_get_string(ctlRequest[idx].jToken)); + AFB_NOTICE("Invalid Json=%s missing 'id'|'val'", json_object_get_string(ctlRequest[idx].jToken)); ctlRequest[idx].used=-1; } else { ctlRequest[idx].numId =json_object_get_int(jId); @@ -478,7 +445,7 @@ STATIC json_object *getControlAcl (snd_ctl_elem_info_t *info) { } // process ALSA control and store resulting value into ctlRequest -STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest) { +PUBLIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest) { snd_ctl_elem_value_t *elemData; snd_ctl_elem_info_t *elemInfo; int count, length, err, valueIsArray; @@ -490,13 +457,13 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe snd_ctl_elem_info_alloca(&elemInfo); snd_ctl_elem_info_set_id(elemInfo, elemId); // map ctlInfo to ctlId elemInfo is updated !!! if (snd_ctl_elem_info(ctlDev, elemInfo) < 0) { - NOTICE( "Fail to load ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues)); + AFB_NOTICE( "Fail to load ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues)); goto OnErrorExit; } snd_ctl_elem_info_get_id(elemInfo, elemId); // map ctlInfo to ctlId elemInfo is updated !!! if (!snd_ctl_elem_info_is_writable(elemInfo)) { - NOTICE( "Not Writable ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues)); + AFB_NOTICE( "Not Writable ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues)); goto OnErrorExit; } @@ -515,12 +482,13 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe break; default: count =0; + length = 0; break; } if (count == 0 || count < length) { - NOTICE( "Invalid values NUMID='%d' Values='%s' count='%d' wanted='%d'", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), length, count); + AFB_NOTICE( "Invalid values NUMID='%d' Values='%s' count='%d' wanted='%d'", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), length, count); goto OnErrorExit; } @@ -542,7 +510,7 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe err = snd_ctl_elem_write(ctlDev, elemData); if (err < 0) { - NOTICE( "Fail to write ALSA NUMID=%d Values=[%s] Error=%s", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), snd_strerror(err)); + AFB_NOTICE( "Fail to write ALSA NUMID=%d Values=[%s] Error=%s", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), snd_strerror(err)); goto OnErrorExit; } @@ -555,7 +523,7 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe } // process ALSA control and store then into ctlRequest -STATIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, int quiet) { +PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, int quiet) { snd_ctl_elem_type_t elemType; snd_ctl_elem_value_t *elemData; snd_ctl_elem_info_t *elemInfo; @@ -681,7 +649,7 @@ STATIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe } // assign multiple control to the same value -PUBLIC void alsaSetGetCtls (afb_req request, ActionSetGetT action) { +STATIC void alsaSetGetCtls (afb_req request, ActionSetGetT action) { ctlRequestT *ctlRequest; const char *warmsg=NULL; int err=0, status=0; @@ -736,7 +704,7 @@ PUBLIC void alsaSetGetCtls (afb_req request, ActionSetGetT action) { } else { int numid = snd_ctl_elem_list_get_numid(ctlList, ctlIndex); if (numid < 0) { - NOTICE("snd_ctl_elem_list_get_numid index=%d fail", ctlIndex); + AFB_NOTICE("snd_ctl_elem_list_get_numid index=%d fail", ctlIndex); continue; } // check if current control was requested in query numids list @@ -814,269 +782,3 @@ PUBLIC void alsaSetCtls (afb_req request) { } -// This routine is called when ALSA event are fired -STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void* userData) { - int err; - evtHandleT *evtHandle = (evtHandleT*)userData; - snd_ctl_event_t *eventId; - json_object *ctlEventJ; - unsigned int mask; - int iface; - int device; - int subdev; - const char*devname; - ctlRequestT ctlRequest; - snd_ctl_elem_id_t *elemId; - - if ((revents & EPOLLHUP) != 0) { - NOTICE( "SndCtl hanghup [car disconnected]"); - goto ExitOnSucess; - } - - 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; - - // we only process sndctrl element - if (snd_ctl_event_get_type(eventId) != SND_CTL_EVENT_ELEM) goto ExitOnSucess; - - // we only process value changed events - mask = snd_ctl_event_elem_get_mask(eventId); - if (!(mask & SND_CTL_EVENT_MASK_VALUE)) goto ExitOnSucess; - - snd_ctl_event_elem_get_id (eventId, elemId); - - err = alsaGetSingleCtl (evtHandle->ctlDev, elemId, &ctlRequest, evtHandle->quiet); - if (err) goto OnErrorExit; - - iface = snd_ctl_event_elem_get_interface(eventId); - device = snd_ctl_event_elem_get_device(eventId); - subdev = snd_ctl_event_elem_get_subdevice(eventId); - devname= snd_ctl_event_elem_get_name(eventId); - - // proxy ctlevent as a binder event - ctlEventJ = json_object_new_object(); - json_object_object_add(ctlEventJ, "device" ,json_object_new_int (device)); - json_object_object_add(ctlEventJ, "subdev" ,json_object_new_int (subdev)); - if (evtHandle->quiet < 2) { - json_object_object_add(ctlEventJ, "iface" ,json_object_new_int (iface)); - json_object_object_add(ctlEventJ, "devname",json_object_new_string (devname)); - } - if (ctlRequest.jValues) (json_object_object_add(ctlEventJ, "values" ,ctlRequest.jValues)); - DEBUG( "sndCtlEventCB=%s", json_object_get_string(ctlEventJ)); - afb_event_push(evtHandle->afbevt, ctlEventJ); - - } - - ExitOnSucess: - return 0; - - OnErrorExit: - WARNING ("sndCtlEventCB: ignored unsupported event type"); - return (0); -} - -// Subscribe to every Alsa CtlEvent send by a given board -PUBLIC void alsaSubcribe (afb_req request) { - static sndHandleT sndHandles[MAX_SND_CARD]; - evtHandleT *evtHandle; - snd_ctl_t *ctlDev; - int err, idx, cardId, idxFree=-1; - snd_ctl_card_info_t *cardinfo; - queryValuesT queryValues; - - - err = alsaCheckQuery (request, &queryValues); - if (err) goto OnErrorExit; - - - // open control interface for devid - err = snd_ctl_open(&ctlDev, queryValues.devid, SND_CTL_READONLY); - if (err < 0) { - ctlDev=NULL; - 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)); - 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) { - - // 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; - } - - evtHandle = malloc (sizeof(evtHandleT)); - evtHandle->ctlDev = ctlDev; - evtHandle->quiet = queryValues.quiet; - sndHandles[idxFree].ucount = 0; - sndHandles[idxFree].cardId = cardId; - sndHandles[idxFree].evtHandle = evtHandle; - - // subscribe for sndctl events attached to devid - err = snd_ctl_subscribe_events(evtHandle->ctlDev, 1); - if (err < 0) { - 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); - - // 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); - if (err < 0) { - 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); - goto OnErrorExit; - } - - // everything looks OK let's move forward - idx=idxFree; - } - - // 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; - } - - // 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 -PUBLIC void alsaGetCardId (afb_req request) { - char devid [10]; - const char *devname, *shortname, *longname; - int card, err, index, idx; - json_object *respJson; - snd_ctl_t *ctlDev; - snd_ctl_card_info_t *cardinfo; - - const char *sndname = afb_req_value(request, "sndname"); - if (sndname == NULL) { - afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing"); - goto OnErrorExit; - } - - // loop on potential card number - snd_ctl_card_info_alloca(&cardinfo); - for (card =0; card < MAX_SND_CARD; card++) { - - // build card devid and probe it - snprintf (devid, sizeof(devid), "hw:%i", card); - - // open control interface for devid - err = snd_ctl_open(&ctlDev, devid, SND_CTL_READONLY); - if (err < 0) continue; - - // extract sound card information - snd_ctl_card_info(ctlDev, cardinfo); - index = snd_ctl_card_info_get_card(cardinfo); - devname = snd_ctl_card_info_get_id(cardinfo); - shortname= snd_ctl_card_info_get_name(cardinfo); - longname = snd_ctl_card_info_get_longname(cardinfo); - - // check if short|long name match - if (!strcmp (sndname, devname)) break; - if (!strcmp (sndname, shortname)) break; - if (!strcmp (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; - } - - // proxy ctlevent as a binder event - respJson = json_object_new_object(); - json_object_object_add(respJson, "index" ,json_object_new_int (index)); - json_object_object_add(respJson, "devid" ,json_object_new_string (devid)); - json_object_object_add(respJson, "shortname" ,json_object_new_string (shortname)); - json_object_object_add(respJson, "longname" ,json_object_new_string (longname)); - - // search for a HAL binder card mapping name to api prefix - for (idx=0; idx < MAX_SND_CARD; idx++) { - if (!strcmp (cardRegistry[idx]->shortname, shortname)) break; - } - // if a match if found, then we have an HAL for this board let's return its value - if (idx < MAX_SND_CARD) json_object_object_add(respJson, "halapi",json_object_new_string (cardRegistry[idx]->apiprefix)); - - afb_req_success(request, respJson, NULL); - return; - - OnErrorExit: - return; -} - -// Register loaded HAL with board Name and API prefix -PUBLIC void alsaRegisterHal (afb_req request) { - static int index=0; - const char *shortname, *apiPrefix; - - apiPrefix = afb_req_value(request, "prefix"); - if (apiPrefix == NULL) { - afb_req_fail_f (request, "argument-missing", "prefix=BindingApiPrefix missing"); - goto OnErrorExit; - } - - shortname = afb_req_value(request, "name"); - if (shortname == NULL) { - afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing"); - goto OnErrorExit; - } - - if (index == MAX_SND_CARD) { - afb_req_fail_f (request, "alsahal-toomany", "Fail to register sndname=[%s]", shortname); - goto OnErrorExit; - } - - cardRegistry[index]= malloc (sizeof(cardRegistry)); - cardRegistry[index]->apiprefix=strdup(apiPrefix); - cardRegistry[index]->shortname=strdup(shortname); - index++;cardRegistry[index]=NULL; - - // when OK nothing to return - afb_req_success(request, NULL, NULL); - return; - - OnErrorExit: - return; -} - diff --git a/ALSA-afb/Alsa-Ucm.c b/ALSA-afb/Alsa-Ucm.c index 78a80ad..c9ee4f9 100644 --- a/ALSA-afb/Alsa-Ucm.c +++ b/ALSA-afb/Alsa-Ucm.c @@ -143,7 +143,7 @@ PUBLIC void alsaUseCaseQuery(struct afb_req request) { json_object_object_add (ucmJ, "verb", json_object_new_string(verbList[idx])); if (verbList[idx+1]) json_object_object_add (ucmJ, "info", json_object_new_string(verbList[idx+1])); - DEBUG (afbIface, "Verb[%d] Action=%s Info=%s", idx, verbList[idx], verbList[idx+1]); + AFB_DEBUG ("Verb[%d] Action=%s Info=%s", idx, verbList[idx], verbList[idx+1]); snprintf (identifier, sizeof(identifier), "_devices/%s", verbList[idx]); devCount = snd_use_case_get_list (ucmHandle, identifier, &devList); @@ -152,7 +152,7 @@ PUBLIC void alsaUseCaseQuery(struct afb_req request) { for (int jdx=0; jdx < devCount; jdx+=2) { json_object *devJ = json_object_new_object(); - DEBUG (afbIface, "device[%d] Action=%s Info=%s", jdx, devList[jdx], devList[jdx+1]); + AFB_DEBUG ("device[%d] Action=%s Info=%s", jdx, devList[jdx], devList[jdx+1]); json_object_object_add (devJ, "dev", json_object_new_string(devList[jdx])); if (devList[jdx+1]) json_object_object_add (devJ, "info", json_object_new_string(devList[jdx+1])); json_object_array_add (devsJ, devJ); @@ -168,7 +168,7 @@ PUBLIC void alsaUseCaseQuery(struct afb_req request) { for (int jdx=0; jdx < modCount; jdx+=2) { json_object *modJ = json_object_new_object(); - DEBUG (afbIface, "modifier[%d] Action=%s Info=%s", jdx, modList[jdx], modList[jdx+1]); + AFB_DEBUG ("modifier[%d] Action=%s Info=%s", jdx, modList[jdx], modList[jdx+1]); json_object_object_add (modJ, "mod", json_object_new_string(modList[jdx])); if (modList[jdx+1]) json_object_object_add (modJ, "info", json_object_new_string(modList[jdx+1])); json_object_array_add (modsJ, modJ); @@ -184,7 +184,7 @@ PUBLIC void alsaUseCaseQuery(struct afb_req request) { for (int jdx=0; jdx < tqCount; jdx+=2) { json_object *tqJ = json_object_new_object(); - DEBUG (afbIface, "toneqa[%d] Action=%s Info=%s", jdx, tqList[jdx], tqList[jdx+1]); + AFB_DEBUG ("toneqa[%d] Action=%s Info=%s", jdx, tqList[jdx], tqList[jdx+1]); json_object_object_add (tqJ, "tq", json_object_new_string(tqList[jdx])); if (tqList[jdx+1]) json_object_object_add (tqJ, "info", json_object_new_string(tqList[jdx+1])); json_object_array_add (tqsJ, tqJ); @@ -214,14 +214,14 @@ STATIC json_object *ucmGetValue (ucmHandleT *ucmHandle, const char *verb, const if (!verb) verb=""; if (!label) { - NOTICE (afbIface, "ucmGetValue cardname=[%s] value label missing", ucmHandle->cardName); + AFB_NOTICE ("ucmGetValue cardname=[%s] value label missing", ucmHandle->cardName); goto OnErrorExit; } snprintf (identifier, sizeof(identifier), "%s/%s/%s", label, mod, verb); err = snd_use_case_get (ucmHandle->ucm, identifier, (const char**)&value); // Note: value casting is a known "FEATURE" of AlsaUCM API if (err) { - DEBUG (afbIface, "ucmGetValue cardname=[%s] identifier=[%s] error=%s", ucmHandle->cardName, identifier, snd_strerror (err)); + AFB_DEBUG ("ucmGetValue cardname=[%s] identifier=[%s] error=%s", ucmHandle->cardName, identifier, snd_strerror (err)); goto OnErrorExit; } diff --git a/ALSA-afb/CMakeLists.txt b/ALSA-afb/CMakeLists.txt index 5c62149..4ca7158 100644 --- a/ALSA-afb/CMakeLists.txt +++ b/ALSA-afb/CMakeLists.txt @@ -20,7 +20,7 @@ PROJECT_TARGET_ADD(alsa-lowlevel) # Define project Targets - ADD_LIBRARY(alsa-lowlevel MODULE Alsa-ApiHat.c Alsa-SetGet.c Alsa-Ucm.c Alsa-AddCtl.c) + ADD_LIBRARY(alsa-lowlevel MODULE Alsa-ApiHat.c Alsa-SetGet.c Alsa-Ucm.c Alsa-AddCtl.c Alsa-RegEvt.c) # Binder exposes a unique public entry point SET_TARGET_PROPERTIES(alsa-lowlevel PROPERTIES diff --git a/CMakeLists.txt b/CMakeLists.txt index 38949e4..faef509 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,14 +15,7 @@ # See the License for the specific language governing permissions and # limitations under the License. ########################################################################### - CMAKE_MINIMUM_REQUIRED(VERSION 3.3) -include(${CMAKE_CURRENT_SOURCE_DIR}/conf.d/config.cmake) -include(${CMAKE_CURRENT_SOURCE_DIR}/conf.d/app-templates/cmake/common.cmake) - -project_subdirs_add("[^_]*") - -project_targets_populate() -project_package_build() -project_closing_msg() +# Do not change this file, config is located into conf.d +include(${CMAKE_CURRENT_SOURCE_DIR}/conf.d/cmake/config.cmake) diff --git a/HAL-afb/CMakeLists.txt b/HAL-afb/CMakeLists.txt index 1b8cc0e..b0c2e6a 100644 --- a/HAL-afb/CMakeLists.txt +++ b/HAL-afb/CMakeLists.txt @@ -19,5 +19,5 @@ # Include any directory starting with a Capital letter # ----------------------------------------------------- -PROJECT_SUBDIRS_ADD("*") +PROJECT_SUBDIRS_ADD(${PROJECT_SRC_DIR_PATTERN}) diff --git a/HAL-afb/HAL-interface/hal-interface.c b/HAL-afb/HAL-interface/hal-interface.c index 2c6595f..29c5e88 100644 --- a/HAL-afb/HAL-interface/hal-interface.c +++ b/HAL-afb/HAL-interface/hal-interface.c @@ -37,31 +37,11 @@ typedef struct { } shareHallMap_T; static shareHallMap_T *shareHallMap; +static alsaHalMapT *halCtls; // Force specific HAL to depend on ShareHalLib PUBLIC char* SharedHalLibVersion="1.0"; -// This callback when api/alsacore/subscribe returns -STATIC void alsaSubcribeCB(void *handle, int iserror, struct json_object *result) { - afb_req request = afb_req_unstore(handle); - struct json_object *x, *resp = NULL; - const char *info = NULL; - - if (result) { - INFO( "result=[%s]\n", json_object_to_json_string(result)); - if (json_object_object_get_ex(result, "request", &x) && json_object_object_get_ex(x, "info", &x)) - info = json_object_get_string(x); - if (!json_object_object_get_ex(result, "response", &resp)) resp = NULL; - } - - // push message respond - if (iserror) afb_req_fail_f(request, "Fail", info); - else afb_req_success(request, resp, info); - - // free calling request - afb_req_unref(request); -} - // Subscribe to AudioBinding events STATIC void halSubscribe(afb_req request) { const char *devid = afb_req_value(request, "devid"); @@ -125,7 +105,6 @@ STATIC int NormaliseValue(const alsaHalCtlMapT *halCtls, int valuein) { // receive controls for LowLevel remap them to hight level before returning them STATIC void halGetControlCB(void *handle, int iserror, struct json_object *result) { - alsaHalMapT *halCtls = alsaHalSndCard.ctls; struct json_object *response; // retrieve request and check for errors @@ -218,8 +197,8 @@ STATIC void halGetCtls(afb_req request) { ctl = json_object_array_get_idx(ctlsin, idx); control = (halCtlsEnumT) json_object_get_int(ctl); if (control >= EndHalCrlTag || control <= StartHalCrlTag) { - afb_req_fail_f(request, "ctl-invalid", "Invalid Control devid=%s sndcard=%s ctl=[%s] should be [%d-%d]" - , json_object_get_string(devid), alsaHalSndCard.name, json_object_get_string(ctl), StartHalCrlTag, EndHalCrlTag); + afb_req_fail_f(request, "ctl-invalid", "Invalid Control devid=%s ctl=[%s] should be [%d-%d]" + , json_object_get_string(devid), json_object_get_string(ctl), StartHalCrlTag, EndHalCrlTag); goto OnExit; } @@ -241,60 +220,69 @@ OnExit: // This receive all event this binding subscribe to -PUBLIC void afbServiceEvent(const char *evtname, struct json_object *object) { +PUBLIC void halServiceEvent(const char *evtname, struct json_object *object) { - NOTICE("afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object)); + AFB_NOTICE("afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object)); } // this is call when after all bindings are loaded -STATIC int afbServiceInit() { - int rc=0, err; - struct json_object *queryurl, *jResponse; - alsaHalMapT *halCtls = alsaHalSndCard.ctls; // Get sndcard specific HAL control mapping +PUBLIC int halServiceInit (const char *apiPrefix, alsaHalSndCardT *alsaHalSndCard) { + int ok, err; + struct json_object *queryurl, *responseJ, *devidJ, *tmpJ; + halCtls = alsaHalSndCard->ctls; // Get sndcard specific HAL control mapping - if (alsaHalSndCard.initCB) { - rc= (alsaHalSndCard.initCB)(); - if (rc != 0) goto OnErrorExit; - } - err= afb_daemon_require_api("alsacore", 1); + if (err) { + AFB_ERROR ("AlsaCore missing cannot use AlsaHAL"); + goto OnErrorExit; + } // register HAL with Alsa Low Level Binder queryurl = json_object_new_object(); - json_object_object_add(queryurl, "prefix", json_object_new_string(sndCardApiPrefix)); - json_object_object_add(queryurl, "name", json_object_new_string(alsaHalSndCard.name)); + json_object_object_add(queryurl, "prefix", json_object_new_string(apiPrefix)); + json_object_object_add(queryurl, "sndname", json_object_new_string(alsaHalSndCard->name)); - afb_service_call_sync("alsacore", "registerHal", queryurl, &jResponse); - err= afb_service_call_sync ("alsacore", "registerHal", queryurl, &jResponse); - if (err) { - ERROR ("Fail to register HAL to ALSA lowlevel binding"); + ok= afb_service_call_sync ("alsacore", "registerHal", queryurl, &responseJ); + json_object_put(queryurl); + if (!ok) { + NOTICE ("Fail to register HAL to ALSA lowlevel binding Response=[%s]", json_object_to_json_string(responseJ)); goto OnErrorExit; } - json_object_put(queryurl); - + + // extract sound devid from HAL registration + if (!json_object_object_get_ex(responseJ, "response", &tmpJ) || !json_object_object_get_ex(tmpJ, "devid", &devidJ)) { + AFB_ERROR ("Ooops: Internal error no devid return from HAL registration Response=[%s]", json_object_to_json_string(responseJ)); + goto OnErrorExit; + } + // for each Non Alsa Control callback create a custom control for (int idx = 0; halCtls[idx].alsa.numid != 0; idx++) { if (halCtls[idx].cb.callback != NULL) { queryurl = json_object_new_object(); - if (halCtls[idx].alsa.name) json_object_object_add(queryurl, "name" , json_object_new_string(halCtls[idx].alsa.name)); - if (halCtls[idx].alsa.numid) json_object_object_add(queryurl, "numid" , json_object_new_int(halCtls[idx].alsa.numid)); - if (halCtls[idx].alsa.minval) json_object_object_add(queryurl, "minval", json_object_new_int(halCtls[idx].alsa.minval)); - if (halCtls[idx].alsa.maxval) json_object_object_add(queryurl, "maxval", json_object_new_int(halCtls[idx].alsa.maxval)); - if (halCtls[idx].alsa.step) json_object_object_add(queryurl, "step" , json_object_new_int(halCtls[idx].alsa.step)); - if (halCtls[idx].alsa.type) json_object_object_add(queryurl, "type" , json_object_new_int(halCtls[idx].alsa.type)); + json_object_object_add(queryurl, "devid",devidJ); + tmpJ = json_object_new_object(); + if (halCtls[idx].alsa.name) json_object_object_add(tmpJ, "name" , json_object_new_string(halCtls[idx].alsa.name)); + if (halCtls[idx].alsa.numid) json_object_object_add(tmpJ, "numid" , json_object_new_int(halCtls[idx].alsa.numid)); + if (halCtls[idx].alsa.minval) json_object_object_add(tmpJ, "minval", json_object_new_int(halCtls[idx].alsa.minval)); + if (halCtls[idx].alsa.maxval) json_object_object_add(tmpJ, "maxval", json_object_new_int(halCtls[idx].alsa.maxval)); + if (halCtls[idx].alsa.step) json_object_object_add(tmpJ, "step" , json_object_new_int(halCtls[idx].alsa.step)); + if (halCtls[idx].alsa.type) json_object_object_add(tmpJ, "type" , json_object_new_int(halCtls[idx].alsa.type)); + json_object_object_add(queryurl, "ctls",tmpJ); - err= afb_service_call_sync ("alsacore", "addUserCtl", queryurl, &jResponse); - if (err) { - ERROR ("Fail to register Callback for ctrl=[%s]", halCtls[idx].alsa.name); + AFB_NOTICE("QUERY=%s", json_object_to_json_string(queryurl)); + + ok= afb_service_call_sync ("alsacore", "addcustomctl", queryurl, &responseJ); + if (!ok) { + AFB_ERROR ("Fail to add Customer Sound Control for ctrl=[%s] Response=[%s]", halCtls[idx].alsa.name, json_object_to_json_string(responseJ)); goto OnErrorExit; - } + } } } // finally register for alsa lowlevel event - err= afb_service_call_sync ("alsacore", "subscribe", queryurl, &jResponse); + err= afb_service_call_sync ("alsacore", "subscribe", queryurl, &responseJ); if (err) { - ERROR ("Fail subscribing to ALSA lowlevel events"); + AFB_ERROR ("Fail subscribing to ALSA lowlevel events"); goto OnErrorExit; } @@ -305,24 +293,12 @@ STATIC int afbServiceInit() { }; // Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT -STATIC afb_verb_v2 halSharedApi[] = { +PUBLIC afb_verb_v2 halServiceApi[] = { /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */ { .verb = "ping", .callback = pingtest}, { .verb = "getctls", .callback = halGetCtls}, { .verb = "setvol", .callback = halSetVol}, { .verb = "getvol", .callback = halGetVol}, { .verb = "subscribe", .callback = halSubscribe}, - { .verb = "monitor", .callback = halMonitor}, { .verb = NULL} /* marker for end of the array */ }; - - -PUBLIC const struct afb_binding_v2 afbBindingV2 = { - .api = sndCardApiPrefix, - .specification = NULL, - .verbs = halSharedApi, - .preinit = NULL, - .init = afbServiceInit, - .onevent = afbServiceEvent, - .noconcurrency = 0 -}; diff --git a/HAL-afb/HAL-interface/hal-interface.h b/HAL-afb/HAL-interface/hal-interface.h index e08ec18..16da901 100644 --- a/HAL-afb/HAL-interface/hal-interface.h +++ b/HAL-afb/HAL-interface/hal-interface.h @@ -39,9 +39,6 @@ typedef struct { // avoid compiler warning [Jose does not like typedef :) ] typedef struct afb_service alsaHalServiceT; -// static value for HAL sound card API prefix -extern const char sndCardApiPrefix[]; - typedef struct { struct json_object* (*callback)(alsaHalCtlMapT *control, void* handle); void* handle; @@ -57,12 +54,13 @@ typedef struct { typedef const struct { const char *name; const char *info; - alsaHalMapT *ctls; - int (*initCB) (void); - + alsaHalMapT *ctls; } alsaHalSndCardT; -PUBLIC alsaHalSndCardT alsaHalSndCard; +extern afb_verb_v2 halServiceApi[]; +PUBLIC void halServiceEvent(const char *evtname, struct json_object *object); +PUBLIC int halServiceInit (const char *apiPrefix, alsaHalSndCardT *alsaHalSndCard); + #endif /* SHAREHALLIB_H */ diff --git a/HAL-afb/HDA-intel/IntelHdaHAL.c b/HAL-afb/HDA-intel/IntelHdaHAL.c index 98ac442..f394fd6 100644 --- a/HAL-afb/HDA-intel/IntelHdaHAL.c +++ b/HAL-afb/HDA-intel/IntelHdaHAL.c @@ -13,42 +13,33 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. + * + * + * To find out which control your sound card uses + * aplay -l # Check sndcard name name in between [] + * amixer -D hw:xx controls # get supported controls + * amixer -D "hw:3" cget numid=xx # get control settings + * */ #define _GNU_SOURCE #include "hal-interface.h" #include "audio-interface.h" -// Init is call after all binding are loaded -STATIC int IntelHalInit (void) { - DEBUG ("IntelHalBinding Initialised"); - - return 0; // 0=OK -} - -STATIC void MasterOnOff (alsaHalCtlMapT *control, void* handle) { +STATIC struct json_object* MasterOnOff (alsaHalCtlMapT *control, void* handle) { static int powerStatus=0; if (! powerStatus) { powerStatus = 1; - DEBUG ("Power Set to On"); + AFB_DEBUG ("Power Set to On"); } else { powerStatus = 0; - DEBUG ("Power Set to Off"); + AFB_DEBUG ("Power Set to Off"); } + + return NULL; } -/****************************************************************************************** - * alsaCtlsMap link hight level sound control with low level Alsa numid ctls. - * - * To find out which control your sound card uses - * aplay -l - * amixer -D hw:xx controls - * amixer -D hw:xx contents - * amixer -D "hw:3" cget numid=xx - * - * When automatic mapping to Alsa numid is not enough a custom callback might be used - * .cb={.handle=xxxx, .callback=(json_object)MyCtlFunction(struct afb_service service, int controle, int value, const struct alsaHalCtlMapS *map)}; - ********************************************************************************************/ +// Map HAL hight sndctl with Alsa numid and optionally with a custom callback for non Alsa supported functionalities. STATIC alsaHalMapT alsaHalMap[]= { { .alsa={.control=Master_Playback_Volume,.numid=16, .name="Master-Vol" , .values=1,.minval=0,.maxval= 87 ,.step=0}, .info= "Master Playback Volume" }, { .alsa={.control=PCM_Playback_Volume ,.numid=27, .name="Play-Vol" , .values=2,.minval=0,.maxval= 255,.step=0}, .info= "PCM Playback Volume" }, @@ -58,26 +49,26 @@ STATIC alsaHalMapT alsaHalMap[]= { { .alsa={.numid=0}, .cb={.callback=NULL, .handle=NULL}} /* marker for end of the array */ } ; -/*********************************************************************************** - * AlsaHalSndT provides - * - cardname used to map a given card to its HAL - * - ctls previously defined AlsaHalMapT control maps - * - info free text - * - * WARNING: name should fit with 'aplay -l' as it used to map from devid to HAL - * you may also retreive shortname when AudioBinder is running from a browser - * http://localhost:1234/api/alsacore/getcardid?devid=hw:xxx - * - ***********************************************************************************/ - -// API prefix should be unique for each snd card -PUBLIC const char sndCardApiPrefix[] = "intel-hda"; - -// HAL sound card controls mapping -PUBLIC alsaHalSndCardT alsaHalSndCard = { - .name = "HDA Intel PCH", +// HAL sound card mapping info +STATIC alsaHalSndCardT alsaHalSndCard = { + .name = "HDA Intel PCH", // WARNING: name MUST match with 'aplay -l' .info = "Hardware Abstraction Layer for IntelHDA sound card", .ctls = alsaHalMap, - .initCB=IntelHalInit, // if NULL no initcallback }; + +STATIC int sndServiceInit () { + int err; + AFB_DEBUG ("IntelHalBinding Init"); + + err = halServiceInit (afbBindingV2.api, &alsaHalSndCard); + return err; +} + +// API prefix should be unique for each snd card +PUBLIC const struct afb_binding_v2 afbBindingV2 = { + .api = "intel-hda", + .init = sndServiceInit, + .verbs = halServiceApi, + .onevent = halServiceEvent, +}; diff --git a/HAL-afb/Scarlett-Focusrite/CMakeLists.txt b/HAL-afb/Scarlett-Focusrite/CMakeLists.txt new file mode 100644 index 0000000..a2ca912 --- /dev/null +++ b/HAL-afb/Scarlett-Focusrite/CMakeLists.txt @@ -0,0 +1,42 @@ +########################################################################### +# Copyright 2015, 2016, 2017 IoT.bzh +# +# author: Fulup Ar Foll +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################### + + +# Add target to project dependency list +PROJECT_TARGET_ADD(hal-scalett-usb) + + # Define project Targets + ADD_LIBRARY(hal-scalett-usb MODULE ScarlettUsbHAL.c) + + # Binder exposes a unique public entry point + SET_TARGET_PROPERTIES(hal-scalett-usb PROPERTIES + PREFIX "afb-" + LABELS "BINDING" + LINK_FLAGS ${BINDINGS_LINK_FLAG} + OUTPUT_NAME ${TARGET_NAME} + ) + + # Library dependencies (include updates automatically) + TARGET_LINK_LIBRARIES(hal-scalett-usb + hal-interface + audio-interface + ) + + # installation directory + INSTALL(TARGETS hal-scalett-usb + LIBRARY DESTINATION ${BINDINGS_INSTALL_DIR}) \ No newline at end of file diff --git a/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c b/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c new file mode 100644 index 0000000..1ff5320 --- /dev/null +++ b/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * To find out which control your sound card uses + * aplay -l # Check sndcard name name in between [] + * amixer -D hw:xx controls # get supported controls + * amixer -D "hw:3" cget numid=xx # get control settings + * + */ +#define _GNU_SOURCE +#include "hal-interface.h" +#include "audio-interface.h" + +STATIC struct json_object* MasterOnOff (alsaHalCtlMapT *control, void* handle) { + static int powerStatus=0; + + if (! powerStatus) { + powerStatus = 1; + AFB_DEBUG ("Power Set to On"); + } else { + powerStatus = 0; + AFB_DEBUG ("Power Set to Off"); + } + + return NULL; +} + +// Map HAL hight sndctl with Alsa numid and optionally with a custom callback for non Alsa supported functionalities. +STATIC alsaHalMapT alsaHalMap[]= { + { .alsa={.control=Master_Playback_Volume,.numid=16, .name="Master-Vol" , .values=1,.minval=0,.maxval= 87 ,.step=0}, .info= "Master Playback Volume" }, + { .alsa={.control=PCM_Playback_Volume ,.numid=27, .name="Play-Vol" , .values=2,.minval=0,.maxval= 255,.step=0}, .info= "PCM Playback Volume" }, + { .alsa={.control=PCM_Playback_Switch ,.numid=17, .name="Play-Switch" , .values=1,.minval=0,.maxval= 1 ,.step=0}, .info= "Master Playback Switch" }, + { .alsa={.control=Capture_Volume ,.numid=12, .name="Capt-vol" , .values=2,.minval=0,.maxval= 31 ,.step=0}, .info= "Capture Volume" }, + { .alsa={.control=Master_OnOff_Switch ,.numid=99, .name="Power-Switch"}, .cb={.callback=MasterOnOff, .handle=NULL}, .info= "OnOff Global Switch"}, + { .alsa={.numid=0}, .cb={.callback=NULL, .handle=NULL}} /* marker for end of the array */ +} ; + +// HAL sound card mapping info +STATIC alsaHalSndCardT alsaHalSndCard = { + .name = "Scarlett 18i8 USB", // WARNING: name MUST match with 'aplay -l' + .info = "Hardware Abstraction Layer for Scarlett Focusrite USB professional music sound card", + .ctls = alsaHalMap, +}; + + +STATIC int sndServiceInit () { + int err; + AFB_DEBUG ("IntelHalBinding Init"); + + err = halServiceInit (afbBindingV2.api, &alsaHalSndCard); + return err; +} + +// API prefix should be unique for each snd card +PUBLIC const struct afb_binding_v2 afbBindingV2 = { + .api = "scarlett-usb", + .init = sndServiceInit, + .verbs = halServiceApi, + .onevent = halServiceEvent, +}; diff --git a/README.md b/README.md index a694859..bd86da6 100644 --- a/README.md +++ b/README.md @@ -84,11 +84,22 @@ make install # From $INSTALL_PREFIX mkdir $INSTALL_PREFIX/share/wssocks afb-daemon --verbose --token="" --ldpaths=$INSTALL_PREFIX/lib/audio --port=1234 --roothttp=$INSTALL_PREFIX/htdocs/audio-bindings + +# Debug with GDB + In order your debugger to find bindings(sharelib) symbols ldpath and workdir should match with GDB solib-search-path + --workdir=. #default value: in this case solib-search-path is not requirer + --workdir=.. --ldpath=build in this case set (solib-search-path=build) should be used + + To debug from desktop directly within './build' directory use following commands +``` + cd ./build + gdb afb-daemon --args afb-daemon --ldpaths=. --port=1234 --workdir=. --roothttp=../htdocs --tracereq=common --token='' --verbose ``` -# replace hd:XX with your own sound card ID ex: "hw:0", "hw:PCH", ... -Start a browser on http://localhost:1234?devid=hw:XX -Start AlsaMixer and change volume you should see event in your browser +# replace hd:XX with your own sound card ID ex: "hw:0", "hw:PCH", ... +``` +- Start a browser on http://localhost:1234?devid=hw:XX +- Start AlsaMixer and change volume you should see event in your browser ``` alsamixer -D hw:0 ``` diff --git a/conf.d/app-templates b/conf.d/app-templates index 0d3bfaf..011277d 160000 --- a/conf.d/app-templates +++ b/conf.d/app-templates @@ -1 +1 @@ -Subproject commit 0d3bfaf0888cb350f8721db4a4115ecb8dc4f005 +Subproject commit 011277d2af3cfee674b50fa8a7362e91e8ad29e8 diff --git a/conf.d/autobuild/agl/autobuild b/conf.d/autobuild/agl/autobuild new file mode 100755 index 0000000..31e29f7 --- /dev/null +++ b/conf.d/autobuild/agl/autobuild @@ -0,0 +1,47 @@ +#!/usr/bin/make -f +# Copyright (C) 2015, 2016 "IoT.bzh" +# Author "Romain Forlot" +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +THISFILE := $(lastword $(MAKEFILE_LIST)) +BUILD_DIR := $(abspath $(dir $(THISFILE)/../../../../..)/build) + +.PHONY: all clean distclean configure build package + +all: build + +clean: + @([ -d ${BUILD_DIR} ] && make -C ${BUILD_DIR} clean) || echo Nothing to clean + +distclean: + @rm -rf ${BUILD_DIR} + +configure: ${BUILD_DIR}/Makefile + +build: configure + @cmake --build ${BUILD_DIR} ${BUILD_ARGS} --target all + +package: build + @mkdir -p ${BUILD_DIR}/$@/bin + @mkdir -p ${BUILD_DIR}/$@/etc + @mkdir -p ${BUILD_DIR}/$@/lib + @mkdir -p ${BUILD_DIR}/$@/htdocs + @mkdir -p ${BUILD_DIR}/$@/data + @[ "${DEST}" ] && mkdir -p ${DEST} + @cmake --build ${BUILD_DIR} --target widget + @[ "${DEST}" ] && cp ${BUILD_DIR}/*wgt ${DEST} + +${BUILD_DIR}/Makefile: + @[ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR} + @[ -f ${BUILD_DIR}/Makefile ] || (cd ${BUILD_DIR} && cmake ${CONFIGURE_ARGS} ..) diff --git a/conf.d/autobuild/linux/autobuild b/conf.d/autobuild/linux/autobuild new file mode 100755 index 0000000..31e29f7 --- /dev/null +++ b/conf.d/autobuild/linux/autobuild @@ -0,0 +1,47 @@ +#!/usr/bin/make -f +# Copyright (C) 2015, 2016 "IoT.bzh" +# Author "Romain Forlot" +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +THISFILE := $(lastword $(MAKEFILE_LIST)) +BUILD_DIR := $(abspath $(dir $(THISFILE)/../../../../..)/build) + +.PHONY: all clean distclean configure build package + +all: build + +clean: + @([ -d ${BUILD_DIR} ] && make -C ${BUILD_DIR} clean) || echo Nothing to clean + +distclean: + @rm -rf ${BUILD_DIR} + +configure: ${BUILD_DIR}/Makefile + +build: configure + @cmake --build ${BUILD_DIR} ${BUILD_ARGS} --target all + +package: build + @mkdir -p ${BUILD_DIR}/$@/bin + @mkdir -p ${BUILD_DIR}/$@/etc + @mkdir -p ${BUILD_DIR}/$@/lib + @mkdir -p ${BUILD_DIR}/$@/htdocs + @mkdir -p ${BUILD_DIR}/$@/data + @[ "${DEST}" ] && mkdir -p ${DEST} + @cmake --build ${BUILD_DIR} --target widget + @[ "${DEST}" ] && cp ${BUILD_DIR}/*wgt ${DEST} + +${BUILD_DIR}/Makefile: + @[ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR} + @[ -f ${BUILD_DIR}/Makefile ] || (cd ${BUILD_DIR} && cmake ${CONFIGURE_ARGS} ..) diff --git a/conf.d/cmake/config.cmake b/conf.d/cmake/config.cmake new file mode 100644 index 0000000..e9367bc --- /dev/null +++ b/conf.d/cmake/config.cmake @@ -0,0 +1,134 @@ +########################################################################### +# Copyright 2015, 2016, 2017 IoT.bzh +# +# author: Fulup Ar Foll +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################### + +# Project Info +# ------------------ +set(PROJECT_NAME unicens-agent) +set(PROJECT_VERSION "0.1") +set(PROJECT_PRETTY_NAME "Audio Agent") +set(PROJECT_DESCRIPTION "Expose Alsa through AGL AppFw") +set(PROJECT_URL "https://github.com/iotbzh/audio-bindings") +set(PROJECT_ICON "icon.png") +set(PROJECT_AUTHOR "Fulup, Ar Foll") +set(PROJECT_AUTHOR_MAIL "fulup@iot.bzh") +set(PROJECT_LICENCE "Apache-V2") +set(PROJECT_LANGUAGES,"C") + + +# Where are stored default templates files from submodule or subtree app-templates in your project tree +# relative to the root project directory +set(PROJECT_APP_TEMPLATES_DIR "conf.d/app-templates") + +# Use any directory that does not start with _ as valid source rep +set(PROJECT_SRC_DIR_PATTERN "[^_]*") + +# Compilation Mode (AFB_DEBUG, RELEASE) +# ---------------------------------- +set(CMAKE_BUILD_TYPE "AFB_DEBUG") + +# Static constante definition +# ----------------------------- +add_compile_options(-DMAX_SND_CARD=16) + +# Compiler selection if needed. Overload the detected compiler. +# ----------------------------------------------- +set (gcc_minimal_version 4.9) +#set(CMAKE_C_COMPILER "gcc") +#set(CMAKE_CXX_COMPILER "g++") + +# PKG_CONFIG required packages +# ----------------------------- +set (PKG_REQUIRED_LIST + alsa + libsystemd>=222 + libmicrohttpd>=0.9.54 + afb-daemon + json-c +) + +# LANG Specific compile flags set for all build types +# set(CMAKE_C_FLAGS "") +# set(CMAKE_CXX_FLAGS "") + +# Do not optimise when debugging +set(CMAKE_C_FLAGS_DEBUG "-g -ggdb -Wp,-U_FORTIFY_SOURCE") + +# Define CONTROL_CDEV_NAME should match MOST driver values +# --------------------------------------------------------- + add_compile_options(-DCONTROL_CDEV_TX="/dev/inic-usb-ctx") + add_compile_options(-DCONTROL_CDEV_RX="/dev/inic-usb-crx") + +# Print a helper message when every thing is finished +# ---------------------------------------------------- +set(CLOSING_MESSAGE "Debug in ./buid: afb-daemon --port=1234 --ldpaths=. --workdir=. --roothttp=../htdocs --tracereq=common --token='' --verbose") + +# (BUG!!!) as PKG_CONFIG_PATH does not work [should be an env variable] +# --------------------------------------------------------------------- +set(INSTALL_PREFIX $ENV{HOME}/opt) +set(CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig) +set(LD_LIBRARY_PATH ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib) + +# Optional dependencies order +# --------------------------- +#set(EXTRA_DEPENDENCIES_ORDER) + +# Optional Extra global include path +# ----------------------------------- +# set(EXTRA_INCLUDE_DIRS) + +# Optional extra libraries +# ------------------------- +# set(EXTRA_LINK_LIBRARIES) + +# Optional force binding installation +# ------------------------------------ +# set(BINDINGS_INSTALL_PREFIX PrefixPath ) + +# Optional force widget prefix generation +# ------------------------------------------------ +# set(WIDGET_PREFIX DestinationPath) + +# Optional Widget entry point file. +# --------------------------------------------------------- +# This is the file that will be executed, loaded,... +# at launch time by the application framework + +# set(WIDGET_ENTRY_POINT EntryPoint_Path) + +# Optional Widget Mimetype specification +# -------------------------------------------------- +# Choose between : +# - application/x-executable +# - application/vnd.agl.url +# - application/vnd.agl.service +# - application/vnd.agl.native +# - text/vnd.qt.qml +# - application/vnd.agl.qml +# - application/vnd.agl.qml.hybrid +# - application/vnd.agl.html.hybrid +# +set(WIDGET_TYPE application/vnd.agl.service) + +# Optional force binding Linking flag +# ------------------------------------ +# set(BINDINGS_LINK_FLAG LinkOptions ) + +# This include is mandatory and MUST happens at the end +# of this file, else you expose you to unexpected behavior +# ----------------------------------------------------------- +include(${PROJECT_APP_TEMPLATES_DIR}/cmake/common.cmake) diff --git a/conf.d/config.cmake b/conf.d/config.cmake deleted file mode 100644 index 8ced9f6..0000000 --- a/conf.d/config.cmake +++ /dev/null @@ -1,122 +0,0 @@ -########################################################################### -# Copyright 2015, 2016, 2017 IoT.bzh -# -# author: Fulup Ar Foll -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -########################################################################### - -# Project Info -# ------------------ -set(PROJECT_NAME unicens-agent) -set(PROJECT_VERSION "0.1") -set(PROJECT_PRETTY_NAME "Audio Agent") -set(PROJECT_DESCRIPTION "Expose Alsa through AGL AppFw") -set(PROJECT_URL "https://github.com/iotbzh/audio-bindings") -set(PROJECT_ICON "icon.png") -set(PROJECT_AUTHOR "Fulup, Ar Foll") -set(PROJECT_AUTHOR_MAIL "fulup@iot.bzh") -set(PROJECT_LICENCE "Apache-V2") -set(PROJECT_LANGUAGES,"C") - -# Where are stored default templates files from submodule or subtree app-templates in your project tree -# relative to the root project directory -set(PROJECT_APP_TEMPLATES_DIR "conf.d/app-templates") - -# Compilation Mode (DEBUG, RELEASE) -# ---------------------------------- -set(CMAKE_BUILD_TYPE "DEBUG") - -# Static constante definition -# ----------------------------- -add_compile_options(-DMAX_SND_CARD=16) - -# Compiler selection if needed. Overload the detected compiler. -# ----------------------------------------------- -set (gcc_minimal_version 4.9) -#set(CMAKE_C_COMPILER "gcc") -#set(CMAKE_CXX_COMPILER "g++") - -# PKG_CONFIG required packages -# ----------------------------- -set (PKG_REQUIRED_LIST - alsa - libsystemd>=222 - libmicrohttpd>=0.9.54 - afb-daemon - json-c -) - -# LANG Specific compile flags set for all build types -# set(CMAKE_C_FLAGS "") -# set(CMAKE_CXX_FLAGS "") - -# Define CONTROL_CDEV_NAME should match MOST driver values -# --------------------------------------------------------- - add_compile_options(-DCONTROL_CDEV_TX="/dev/inic-usb-ctx") - add_compile_options(-DCONTROL_CDEV_RX="/dev/inic-usb-crx") - -# Print a helper message when every thing is finished -# ---------------------------------------------------- -set(CLOSING_MESSAGE "Test with: afb-daemon --ldpaths=. --port=1234 --workdir=.. --roothttp=./htdocs --tracereq=common --token='' --verbose") - -# (BUG!!!) as PKG_CONFIG_PATH does not work [should be an env variable] -# --------------------------------------------------------------------- -set(INSTALL_PREFIX $ENV{HOME}/opt) -set(CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig) -set(LD_LIBRARY_PATH ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib) - -# Optional dependencies order -# --------------------------- -#set(EXTRA_DEPENDENCIES_ORDER) - -# Optional Extra global include path -# ----------------------------------- -# set(EXTRA_INCLUDE_DIRS) - -# Optional extra libraries -# ------------------------- -# set(EXTRA_LINK_LIBRARIES) - -# Optional force binding installation -# ------------------------------------ -# set(BINDINGS_INSTALL_PREFIX PrefixPath ) - -# Optional force widget prefix generation -# ------------------------------------------------ -# set(WIDGET_PREFIX DestinationPath) - -# Optional Widget entry point file. -# --------------------------------------------------------- -# This is the file that will be executed, loaded,... -# at launch time by the application framework - -# set(WIDGET_ENTRY_POINT EntryPoint_Path) - -# Optional Widget Mimetype specification -# -------------------------------------------------- -# Choose between : -# - application/x-executable -# - application/vnd.agl.url -# - application/vnd.agl.service -# - application/vnd.agl.native -# - text/vnd.qt.qml -# - application/vnd.agl.qml -# - application/vnd.agl.qml.hybrid -# - application/vnd.agl.html.hybrid -# -set(WIDGET_TYPE application/vnd.agl.service) - -# Optional force binding Linking flag -# ------------------------------------ -# set(BINDINGS_LINK_FLAG LinkOptions ) diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml index 02884db..c476dbc 100644 --- a/nbproject/configurations.xml +++ b/nbproject/configurations.xml @@ -5,6 +5,7 @@ Alsa-AddCtl.c Alsa-ApiHat.c + Alsa-RegEvt.c Alsa-SetGet.c Alsa-Ucm.c @@ -18,6 +19,9 @@ IntelHdaHAL.c + + ScarlettUsbHAL.c + HighLevelApiConf.c @@ -67,7 +71,8 @@ - + + true @@ -100,6 +105,14 @@ + + + + /usr/include/json-c + build/ALSA-afb + + + @@ -124,15 +137,22 @@ ex="false" tool="0" flavor2="3"> - + - + - + + + + + Shared-Interface ../../../opt/include @@ -141,7 +161,7 @@ - + /usr/include/json-c Shared-Interface @@ -214,11 +234,7 @@ - /usr/include/alsa - ../../../opt/include - /usr/include/json-c - HAL-afb/HAL-interface - Shared-Interface + ../../../opt/include/afb CONTROL_CDEV_RX="/dev/inic-usb-crx" @@ -230,6 +246,10 @@ + HAL-afb/HAL-interface + /usr/include/json-c + Shared-Interface + ../../../opt/include build/HAL-afb/HAL-interface @@ -237,11 +257,23 @@ + HAL-afb/HDA-intel + Shared-Interface + HAL-afb/HAL-interface + ../../../opt/include build/HAL-afb/HDA-intel - - hal_intel_hda_EXPORTS - + + + + + + HAL-afb/Scarlett-Focusrite + Shared-Interface + HAL-afb/HAL-interface + ../../../opt/include + build/HAL-afb/Scarlett-Focusrite + -- cgit 1.2.3-korg