summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AlsaSound/CoreBinding/AlsaAfbBinding.c7
-rw-r--r--AlsaSound/CoreBinding/AlsaLibMapping.c1
-rw-r--r--AlsaSound/CoreBinding/AlsaLibMapping.h19
-rw-r--r--AlsaSound/HALayer/CMakeLists.txt11
-rw-r--r--AlsaSound/HALayer/IntelHda/CMakeLists.txt2
-rw-r--r--AlsaSound/HALayer/IntelHda/IntelHdaHAL.c60
-rw-r--r--AlsaSound/HALayer/Shared/SharedHalLib.c252
-rw-r--r--AlsaSound/HALayer/SharedHal/CMakeLists.txt (renamed from AlsaSound/HALayer/Shared/CMakeLists.txt)9
-rw-r--r--AlsaSound/HALayer/SharedHal/SharedHalLib.c341
-rw-r--r--AlsaSound/HALayer/SharedHal/SharedHalLib.h (renamed from AlsaSound/HALayer/include/AlsaHalIface.h)52
-rw-r--r--AlsaSound/HALayer/include/MiscHelpers.h33
-rw-r--r--AudioLogic/AudioLogicBinding.c21
-rw-r--r--AudioLogic/AudioLogicLib.c253
-rw-r--r--AudioLogic/AudioLogicLib.h24
-rw-r--r--CMakeLists.txt7
-rw-r--r--Common/AudioCommonLib.c101
-rw-r--r--Common/AudioCommonLib.h (renamed from AlsaSound/HALayer/include/AlsaHalCtls.h)19
-rw-r--r--Common/CMakeLists.txt31
-rw-r--r--nbproject/configurations.xml22
19 files changed, 729 insertions, 536 deletions
diff --git a/AlsaSound/CoreBinding/AlsaAfbBinding.c b/AlsaSound/CoreBinding/AlsaAfbBinding.c
index 4ae7ccc..a4433e8 100644
--- a/AlsaSound/CoreBinding/AlsaAfbBinding.c
+++ b/AlsaSound/CoreBinding/AlsaAfbBinding.c
@@ -30,17 +30,12 @@
PUBLIC const struct afb_binding_interface *afbIface;
-static void localping(struct afb_req request) {
- json_object *query = afb_req_json(request);
- afb_req_success(request, query, NULL);
-}
-
/*
* array of the verbs exported to afb-daemon
*/
static const struct afb_verb_desc_v1 binding_verbs[] = {
/* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */
- { .name= "ping" , .session= AFB_SESSION_NONE, .callback= localping, .info= "Ping Binding" },
+ { .name= "ping" , .session= AFB_SESSION_NONE, .callback= pingtest, .info= "Ping Binding" },
{ .name= "getinfo", .session= AFB_SESSION_NONE, .callback= alsaGetInfo, .info= "List All/One Sound Cards Info" },
{ .name= "getctl", .session= AFB_SESSION_NONE, .callback= alsaGetCtl, .info= "List All/One Controls from selected sndcard" },
{ .name= "subscribe", .session= AFB_SESSION_NONE, .callback= alsaSubcribe, .info= "Subscribe to events from selected sndcard" },
diff --git a/AlsaSound/CoreBinding/AlsaLibMapping.c b/AlsaSound/CoreBinding/AlsaLibMapping.c
index 900aa3d..58f52c2 100644
--- a/AlsaSound/CoreBinding/AlsaLibMapping.c
+++ b/AlsaSound/CoreBinding/AlsaLibMapping.c
@@ -27,7 +27,6 @@
#include <alsa/asoundlib.h>
#include "AlsaLibMapping.h"
-
#include <systemd/sd-event.h>
static struct afb_service srvitf;
diff --git a/AlsaSound/CoreBinding/AlsaLibMapping.h b/AlsaSound/CoreBinding/AlsaLibMapping.h
index e9e3a42..fb1d39a 100644
--- a/AlsaSound/CoreBinding/AlsaLibMapping.h
+++ b/AlsaSound/CoreBinding/AlsaLibMapping.h
@@ -15,28 +15,11 @@
* limitations under the License.
*/
-
-// few coding convention
-typedef int BOOL;
-#ifndef PUBLIC
- #define PUBLIC
-#endif
-#ifndef FALSE
- #define FALSE 0
-#endif
-#ifndef TRUE
- #define TRUE 1
-#endif
-#define STATIC static
#ifndef ALSALIBMAPPING_H
#define ALSALIBMAPPING_H
-#include <json-c/json.h>
-#include <afb/afb-binding.h>
-#include <afb/afb-service-itf.h>
-
-#include "MiscHelpers.h"
+#include "AudioCommonLib.h"
// import from AlsaAfbBinding
extern const struct afb_binding_interface *afbIface;
diff --git a/AlsaSound/HALayer/CMakeLists.txt b/AlsaSound/HALayer/CMakeLists.txt
index 0b12f62..4601c79 100644
--- a/AlsaSound/HALayer/CMakeLists.txt
+++ b/AlsaSound/HALayer/CMakeLists.txt
@@ -18,9 +18,14 @@
PROJECT(hadware-abstraction-layer C)
-# Fulup NOTE: this might have to be change for a formal static/dynamic lib
-set(halsharedlib ${CMAKE_CURRENT_SOURCE_DIR}/Shared/SharedHalLib.c)
+SET(include_dirs ${CMAKE_CURRENT_SOURCE_DIR}/SharedHal ${include_dirs})
+# Add ShareHalLib statically within each HAL bindings
+SET(link_libraries
+ ${CMAKE_BINARY_DIR}/AlsaSound/HALayer/SharedHal/libsharedhal.a
+ ${link_libraries}
+)
+
+ADD_SUBDIRECTORY(SharedHal)
ADD_SUBDIRECTORY(IntelHda)
-ADD_SUBDIRECTORY(Shared)
diff --git a/AlsaSound/HALayer/IntelHda/CMakeLists.txt b/AlsaSound/HALayer/IntelHda/CMakeLists.txt
index 77218e2..89665e4 100644
--- a/AlsaSound/HALayer/IntelHda/CMakeLists.txt
+++ b/AlsaSound/HALayer/IntelHda/CMakeLists.txt
@@ -22,7 +22,7 @@ INCLUDE_DIRECTORIES(${include_dirs})
##################################################
# Inte-HDA sound card Hardware Abstraction Layer
##################################################
-ADD_LIBRARY(intel-hda-hal MODULE IntelHdaHAL.c ${halsharedlib})
+ADD_LIBRARY(intel-hda-hal MODULE IntelHdaHAL.c )
SET_TARGET_PROPERTIES(intel-hda-hal PROPERTIES
PREFIX ""
diff --git a/AlsaSound/HALayer/IntelHda/IntelHdaHAL.c b/AlsaSound/HALayer/IntelHda/IntelHdaHAL.c
index b04b545..5d668ba 100644
--- a/AlsaSound/HALayer/IntelHda/IntelHdaHAL.c
+++ b/AlsaSound/HALayer/IntelHda/IntelHdaHAL.c
@@ -15,9 +15,20 @@
* limitations under the License.
*/
#define _GNU_SOURCE
-#include "AlsaHalIface.h" // Include Share Interface to Alsa Sound Card HAL
+#include "AudioCommonLib.h"
+#include "SharedHalLib.h" // Include Share Interface to Alsa Sound Card HAL
-/*****************************************************************************
+// Force a hard dependency to ShareHallLib
+PUBLIC char* SharedHalLibVersion;
+
+// Init is call after all binding are loaded
+STATIC int IntelHalInit (const struct afb_binding_interface *itf, struct afb_service service) {
+ DEBUG (itf, "IntelHalBinding Initialised");
+
+ return 0; // 0=OK
+}
+
+/******************************************************************************************
* alsaCtlsMap link hight level sound control with low level Alsa numid ctls.
*
* To find out which control your sound card uses
@@ -25,13 +36,16 @@
* amixer -D hw:xx controls
* amixer -D hw:xx contents
* amixer -D "hw:3" cget numid=xx
- *****************************************************************************/
-STATIC alsaHalCtlMapT alsaHalCtlsMap[]= {
- { .control=Master_Playback_Volume, .numid=16, .group=OUTVOL, .values=1, .minval=0, .maxval= 87 , .step=0, .acl=RW, .info= "Master Playback Volume" },
- { .control=PCM_Playback_Volume , .numid=27, .group=PCMVOL, .values=2, .minval=0, .maxval= 255, .step=0, .acl=RW, .info= "PCM Playback Volume" },
- { .control=PCM_Playback_Switch , .numid=17, .group=SWITCH, .values=1, .minval=0, .maxval= 1 , .step=0, .acl=RW, .info= "Master Playback Switch" },
- { .control=Capture_Volume , .numid=12, .group=INVOL , .values=2, .minval=0, .maxval= 31 , .step=0, .acl=RW, .info= "Capture Volume" },
- { .numid=0 } /* marker for end of the array */
+ *
+ * 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)};
+ ********************************************************************************************/
+STATIC alsaHalMapT alsaHalMap[]= {
+ { .alsa={.control=Master_Playback_Volume,.numid=16,.group=OUTVOL,.values=1,.minval=0,.maxval= 87 ,.step=0,.acl=RW}, .info= "Master Playback Volume" },
+ { .alsa={.control=PCM_Playback_Volume ,.numid=27,.group=PCMVOL,.values=2,.minval=0,.maxval= 255,.step=0,.acl=RW}, .info= "PCM Playback Volume" },
+ { .alsa={.control=PCM_Playback_Switch ,.numid=17,.group=SWITCH,.values=1,.minval=0,.maxval= 1 ,.step=0,.acl=RW}, .info= "Master Playback Switch" },
+ { .alsa={.control=Capture_Volume ,.numid=12,.group=INVOL ,.values=2,.minval=0,.maxval= 31 ,.step=0,.acl=RW}, .info= "Capture Volume" },
+ { .alsa={.numid=0}, .cb={.callback=NULL, .handle=NULL}} /* marker for end of the array */
} ;
/***********************************************************************************
@@ -46,29 +60,9 @@ STATIC alsaHalCtlMapT alsaHalCtlsMap[]= {
*
***********************************************************************************/
PUBLIC alsaHalSndCardT alsaHalSndCard = {
- .name = "HDA Intel PCH",
- .info = "Hardware Abstraction Layer for IntelHDA sound card",
- .ctls = alsaHalCtlsMap,
-};
-
-/***********************************************************************************
- * 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
- *
- ***********************************************************************************/
-PUBLIC struct afb_binding alsaHalBinding = {
- /* description conforms to VERSION 1 */
- .type= AFB_BINDING_VERSION_1,
- .v1= {
- .prefix= "intel-hda",
+ .name = "HDA Intel PCH",
.info = "Hardware Abstraction Layer for IntelHDA sound card",
- }
+ .ctls = alsaHalMap,
+ .prefix="intel-hda",
+ .initCB=IntelHalInit, // if NULL no initcallback
};
-
-
diff --git a/AlsaSound/HALayer/Shared/SharedHalLib.c b/AlsaSound/HALayer/Shared/SharedHalLib.c
deleted file mode 100644
index ffa25e0..0000000
--- a/AlsaSound/HALayer/Shared/SharedHalLib.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author 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.
- *
- * reference:
- * amixer contents; amixer controls;
- * http://www.tldp.org/HOWTO/Alsa-sound-6.html
- */
-#define _GNU_SOURCE // needed for vasprintf
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <math.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#include <json-c/json.h>
-#include <afb/afb-binding.h>
-#include <afb/afb-service-itf.h>
-
-#include "MiscHelpers.h"
-#include "AlsaHalIface.h"
-
-typdef struct {
- int numid;
-} shareHallMap_T;
-
-static struct afb_service srvitf;
-static const struct afb_binding_interface *afbIface;
-static shareHallMap_T *shareHallMap;
-
-
-STATIC void localping(struct afb_req request) {
- json_object *query = afb_req_json(request);
- afb_req_success(request, query, NULL);
-}
-
-// This callback when api/alsacore/subscribe returns
-STATIC void alsaSubcribeCB (void *handle, int iserror, struct json_object *result) {
- struct afb_req request = afb_req_unstore(handle);
- struct json_object *x, *resp = NULL;
- const char *info = NULL;
-
- if (result) {
- INFO (afbIface, "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);
-}
-
-// Create and subscribe to alsacore ctl events
-STATIC void halMonitor(struct afb_req request) {
-
- // save request in session as it might be used after return by callback
- struct afb_req *handle = afb_req_store(request);
-
- // push request to low level binding
- if (!handle) afb_req_fail(request, "error", "out of memory");
- else afb_service_call(srvitf, "alsacore", "subctl", json_object_get(afb_req_json(request)), alsaSubcribeCB, handle);
-
- // success/failure messages return from callback
-}
-
-// Subscribe to AudioBinding events
-STATIC void halSubscribe (struct afb_req request) {
- const char *devid = afb_req_value(request, "devid");
- if (devid == NULL) {
- afb_req_fail_f (request, "devid-missing", "devid=hw:xxx missing");
- }
-}
-
-// Call when all bindings are loaded and ready to accept request
-STATIC void halGetVol(struct afb_req request) {
-
- // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card
- afb_req_success (request, NULL, NULL);
- return;
-
-}
-
-STATIC void halSetVol(struct afb_req request) {
- const char *arg;
- const char *pcm;
-
- arg = afb_req_value(request, "vol");
- if (arg == NULL) {
- afb_req_fail_f (request, "argument-missing", "vol=[0,100] missing");
- goto OnErrorExit;
- }
-
- pcm = afb_req_value(request, "pcm");
- if (pcm == NULL) pcm="Master";
-
- // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card
- afb_req_success (request, NULL, NULL);
- return;
-
- OnErrorExit:
- return;
-
-}
-
-// this is call when after all bindings are loaded
-STATIC int halGetControl(struct afb_service service) {
- srvitf = service;
- struct json_object *queryin, *queryout, *ctls, *devid;
-
- // get query from request
- queryin = afb_req_json(request);
-
- // check devid was given
- devid= json_object_object_get(queryin,"devid");
- if (!ctls) {
- afb_req_fail_f(request, "devid-notfound", "No DevID given query=[%s]", json_object_get_string(queryin));
- goto OnErrorExit;
- }
-
- // loop on requested controls
- ctls= json_object_object_get(queryin,"ctls");
- if (!ctls || json_object_array_length(ctls) <= 0) {
- afb_req_fail_f(request, "ctls-notfound", "No Controls given query=[%s]", json_object_get_string(queryin));
- goto OnErrorExit;
- }
-
- for (int idx=0; idx< json_object_array_length(ctls), idx++) {
- struct json_object *ctl;
- halControlEnumT control;
- int value;
-
- // each controls should be halControlEnumT+value
- ctl = json_object_array_get_idx(ctls, idx);
- if (json_object_array_length(ctl != 2)) {
- afb_req_fail_f(request, "ctl-invalid", "Invalid Control devid=%s ctl=[%s]"json_object_get_string(devid), json_object_get_string(cls));
- goto OnErrorExit;
- }
-
- // As HAL and Business logic use the same AlsaMixerHal.h direct conversion is not an issue
- control = (halControlEnumT)json_object_get_int(json_object_array_get_idx(ctl,0));
- value = json_object_get_int(json_object_array_get_idx(ctl,0));
-
- if (control >= EndHalCrlTag || control <= StartHalCrlTag) {
- 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(cls)), StartHalCrlTag, EndHalCrlTag;
- goto OnErrorExit;
- }
-
-
- default:
- NOTICE (afbIface, "audioLogicOpenCB2 unknown HAL control=[%s]", json_object_get_string(ctl)):
- }
- }
-
-
- // register HAL with Alsa Low Level Binder devid=hw:0&numid=1&quiet=0
- queryurl=json_object_new_object();
- json_object_object_add(queryurl, "prefix",json_object_new_string(alsaHalBinding.v1.prefix));
- json_object_object_add(queryurl, "name" ,json_object_new_string(alsaHalSndCard.name));
- afb_service_call(srvitf, "alsacore", "registerHal", queryurl, halGetControlCB, queryurl);
-
-
- afb_req_success (request, sndctrls, NULL);
- return;
-
-OnErrorExit:
-
-};
-
-STATIC void halInitCB (void *handle, int iserror, struct json_object *result) {
- struct json_object *queryurl = (json_object*)handle;
-
- if (iserror) NOTICE (afbIface, "halInitCB: registration alsaHAL query=[%s] Fail", json_object_to_json_string(queryurl));
- else DEBUG(afbIface, "halInitCB: registration alsaHAL card=[%s] Success", json_object_to_json_string(queryurl));
-}
-
-// This receive all event this binding subscribe to
-PUBLIC void afbBindingV1ServiceEvent(const char *evtname, struct json_object *object) {
-
- NOTICE (afbIface, "afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object));
-}
-
-// this is call when after all bindings are loaded
-PUBLIC int afbBindingV1ServiceInit(struct afb_service service) {
- srvitf = service;
- struct json_object *queryurl;
-
- // API prefix is used as sndcard halname
- alsaHalBinding.v1.prefix= prefix;
-
- // register HAL with Alsa Low Level Binder
- queryurl=json_object_new_object();
- json_object_object_add(ctx->queryurl, "prefix",json_object_new_string(alsaHalBinding.v1.prefix));
- json_object_object_add(ctx->queryurl, "name" ,json_object_new_string(alsaHalSndCard.name));
- afb_service_call(srvitf, "alsacore", "registerHal", queryurl, halInitCB, NULL);
-
- return 0;
-};
-
-
-// Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT
-STATIC const struct afb_verb_desc_v1 halSharedApi[] = {
- /* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */
- { .name= "ping" , .session= AFB_SESSION_NONE, .callback= localping, .info= "Ping Binding" },
- { .name= "getcontrol", .session= AFB_SESSION_NONE, .callback= halGetControl,.info= "Get Control" },
- { .name= "setvolume", .session= AFB_SESSION_NONE, .callback= halSetVol, .info= "Set Volume" },
- { .name= "getvolume", .session= AFB_SESSION_NONE, .callback= halGetVol, .info= "Get Volume" },
- { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= halSubscribe, .info= "Subscribe AudioBinding Events" },
- { .name= NULL } /* marker for end of the array */
-};
-
-// Process HAL mapping from alsaHalSndCardT before registering HAL binder
-PUBLIC const struct afb_binding *afbBindingV1Register(const struct afb_binding_interface *itf) {
- int count;
- afbIface= itf; // need to keep a static trace of binder interface for avances functions
- alsaHalBinding.verbs=halSharedApi; // complete sndcard specific alsaHalBinding with standard HAL APIs
- alsaHalCtlMapT *alsaHalCtls = MapalsaHalSndCard.alsaHalCtlsMap; // Get sndcard specific HAL control mapping
-
- if (alsaHalCtls == NULL) {
- ERROR (afbIface, "afbBindingV1Register Fail alsaHalCtlsMap==NULL");
- return NULL;
- }
-
- // Create a zone to store HAL high/low level mapping
- shareHallMap = calloc (EndHalCrlTag * sizeof(shareHallMap_T));
- for (int idx= 0; alsaHalCtlsMap[idx].numid != 0; idx++) {
- shareHallMap[alsaHalCtlsMap[idx].]->numid = alsaHalCtlsMap[idx].numid;
- }
-
- return alsaHalBinding; /* returns the description of the binding */
-}
diff --git a/AlsaSound/HALayer/Shared/CMakeLists.txt b/AlsaSound/HALayer/SharedHal/CMakeLists.txt
index 27d93e0..d789367 100644
--- a/AlsaSound/HALayer/Shared/CMakeLists.txt
+++ b/AlsaSound/HALayer/SharedHal/CMakeLists.txt
@@ -16,15 +16,14 @@
# limitations under the License.
###########################################################################
-
INCLUDE_DIRECTORIES(${include_dirs})
##################################################
# Shared HAL(Hardware Abstraction Layer)
##################################################
-ADD_LIBRARY(shared-hal MODULE SharedHalLib.c)
-
-TARGET_LINK_LIBRARIES(shared-hal ${link_libraries})
-INSTALL(TARGETS shared-hal LIBRARY DESTINATION ${binding_install_dir})
+ADD_LIBRARY(sharedhal STATIC SharedHalLib.c)
+SET_TARGET_PROPERTIES(sharedhal PROPERTIES OUTPUT_NAME sharedhal)
+SET(link_libraries ${libefence_LIBRARIES} ${json-c_LIBRARIES})
+TARGET_LINK_LIBRARIES(sharedhal ${link_libraries})
diff --git a/AlsaSound/HALayer/SharedHal/SharedHalLib.c b/AlsaSound/HALayer/SharedHal/SharedHalLib.c
new file mode 100644
index 0000000..0b39f29
--- /dev/null
+++ b/AlsaSound/HALayer/SharedHal/SharedHalLib.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author 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.
+ *
+ * reference:
+ * amixer contents; amixer controls;
+ * http://www.tldp.org/HOWTO/Alsa-sound-6.html
+ */
+#define _GNU_SOURCE // needed for vasprintf
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <math.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "SharedHalLib.h"
+
+typedef struct {
+ int index;
+ int numid;
+} shareHallMap_T;
+
+static struct afb_service srvitf;
+static const struct afb_binding_interface *afbIface;
+static shareHallMap_T *shareHallMap;
+
+// 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) {
+ struct afb_req request = afb_req_unstore(handle);
+ struct json_object *x, *resp = NULL;
+ const char *info = NULL;
+
+ if (result) {
+ INFO(afbIface, "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);
+}
+
+// Create and subscribe to alsacore ctl events
+
+STATIC void halMonitor(struct afb_req request) {
+
+ // save request in session as it might be used after return by callback
+ struct afb_req *handle = afb_req_store(request);
+
+ // push request to low level binding
+ if (!handle) afb_req_fail(request, "error", "out of memory");
+ else afb_service_call(srvitf, "alsacore", "subctl", json_object_get(afb_req_json(request)), alsaSubcribeCB, handle);
+
+ // success/failure messages return from callback
+}
+
+// Subscribe to AudioBinding events
+
+STATIC void halSubscribe(struct afb_req request) {
+ const char *devid = afb_req_value(request, "devid");
+ if (devid == NULL) {
+ afb_req_fail_f(request, "devid-missing", "devid=hw:xxx missing");
+ }
+}
+
+// Call when all bindings are loaded and ready to accept request
+
+STATIC void halGetVol(struct afb_req request) {
+
+ // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card
+ afb_req_success(request, NULL, NULL);
+ return;
+
+}
+
+STATIC void halSetVol(struct afb_req request) {
+ const char *arg;
+ const char *pcm;
+
+ arg = afb_req_value(request, "vol");
+ if (arg == NULL) {
+ afb_req_fail_f(request, "argument-missing", "vol=[0,100] missing");
+ goto OnErrorExit;
+ }
+
+ pcm = afb_req_value(request, "pcm");
+ if (pcm == NULL) pcm = "Master";
+
+ // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card
+ afb_req_success(request, NULL, NULL);
+ return;
+
+OnErrorExit:
+ return;
+
+}
+
+// AudioLogic expect volume values to be 0-100%
+
+STATIC int NormaliseValue(const alsaHalCtlMapT *halCtls, int valuein) {
+ int valueout;
+
+ if (valuein > halCtls->maxval) valuein= halCtls->maxval;
+ if (valuein < halCtls->minval) valuein= halCtls->minval;
+
+ // volume are ajusted to 100% any else is ignored
+ switch (halCtls->group) {
+ case OUTVOL:
+ case PCMVOL:
+ case INVOL:
+ valueout = (valuein * 100) / (halCtls->maxval - halCtls->minval);
+ break;
+ default:
+ valueout = valuein;
+ }
+ return (valueout);
+}
+
+// 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
+ struct afb_req request = afb_req_unstore(handle);
+ if (!cbCheckResponse(request, iserror, result)) goto OnExit;
+
+ // Get response from object
+ json_object_object_get_ex(result, "response", &response);
+ if (!response) {
+ afb_req_fail_f(request, "response-notfound", "No Controls return from alsa/getcontrol result=[%s]", json_object_get_string(result));
+ goto OnExit;
+ }
+
+ // extract sounds controls information from received Object
+ struct json_object *ctls;
+ json_object_object_get_ex(result, "ctls", &ctls);
+ if (!ctls) {
+ afb_req_fail_f(request, "ctls-notfound", "No Controls return from alsa/getcontrol response=[%s]", json_object_get_string(response));
+ goto OnExit;
+ }
+
+ // make sure return controls have a valid type
+ if (json_object_get_type(ctls) != json_type_array) {
+ afb_req_fail_f(request, "ctls-notarray", "Invalid Controls return from alsa/getcontrol response=[%s]", json_object_get_string(response));
+ goto OnExit;
+ }
+
+ // loop on array and store values into client context
+ for (int idx = 0; idx < json_object_array_length(ctls); idx++) {
+ struct json_object *ctl;
+ int rawvalue, numid;
+
+ ctl = json_object_array_get_idx(ctls, idx);
+ if (json_object_array_length(ctl) != 2) {
+ afb_req_fail_f(request, "ctl-invalid", "Invalid Control return from alsa/getcontrol ctl=[%s]", json_object_get_string(ctl));
+ goto OnExit;
+ }
+
+ // As HAL and Business logic use the same AlsaMixerHal.h direct conversion is not an issue
+ numid = (halCtlsEnumT) json_object_get_int(json_object_array_get_idx(ctl, 0));
+ rawvalue = json_object_get_int(json_object_array_get_idx(ctl, 1));
+
+ for (int idx = 0; halCtls[idx].alsa.numid != 0; idx++) {
+ if (halCtls[idx].alsa.numid == numid) {
+ struct json_object *ctlAndValue = json_object_new_array();
+ json_object_array_add(ctlAndValue, json_object_new_int(idx)); // idx == high level control
+ json_object_array_add(ctlAndValue, json_object_new_int(NormaliseValue(&halCtls[idx].alsa, rawvalue)));
+ break;
+ }
+ }
+ if (shareHallMap[idx].numid == 0) {
+
+ afb_req_fail_f(request, "ctl-invalid", "Invalid Control numid from alsa/getcontrol ctl=[%s]", json_object_get_string(ctl));
+ goto OnExit;
+ }
+ }
+
+ OnExit:
+ return;
+}
+
+
+// Translate high level control to low level and call lower layer
+STATIC void halGetCtls(struct afb_req request) {
+
+ struct json_object *queryin, *queryout, *ctlsin, *devid;
+ struct json_object *ctlsout = json_object_new_array();
+
+ // get query from request
+ queryin = afb_req_json(request);
+
+ // check devid was given
+ if (!json_object_object_get_ex (queryin, "devid", &devid)) {
+ afb_req_fail_f(request, "devid-notfound", "No DevID given query=[%s]", json_object_get_string(queryin));
+ goto OnExit;
+ }
+
+ // loop on requested controls
+ if (!json_object_object_get_ex(queryin, "ctls", &ctlsin) || json_object_array_length(ctlsin) <= 0) {
+ afb_req_fail_f(request, "ctlsin-notfound", "No Controls given query=[%s]", json_object_get_string(queryin));
+ goto OnExit;
+ }
+
+ // loop on controls
+ for (int idx = 0; idx < json_object_array_length(ctlsin); idx++) {
+ struct json_object *ctl;
+ halCtlsEnumT control;
+
+ // each control should be halCtlsEnumT
+ 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);
+ goto OnExit;
+ }
+
+ // add corresponding lowlevel numid to querylist
+ json_object_array_add(ctlsout, json_object_new_int(shareHallMap[control].numid));
+ }
+
+ // register HAL with Alsa Low Level Binder devid=hw:0&numid=1&quiet=0
+ queryout = json_object_new_object();
+ json_object_object_add(queryout, "devid", devid);
+ json_object_object_add(queryout, "ctls", ctlsout);
+
+ // save request context dans call lowlevel API
+ struct afb_req *handle = afb_req_store(request);
+ afb_service_call(srvitf, "alsacore", "getctl", queryout, halGetControlCB, handle);
+
+OnExit:
+ // Under normal situation success/failure is set from callback
+ return;
+};
+
+STATIC void halInitCB(void *handle, int iserror, struct json_object *result) {
+ struct json_object *queryurl = (json_object*) handle;
+
+ if (iserror) NOTICE(afbIface, "halInitCB: registration alsaHAL query=[%s] Fail", json_object_to_json_string(queryurl));
+ else DEBUG(afbIface, "halInitCB: registration alsaHAL card=[%s] Success", json_object_to_json_string(queryurl));
+}
+
+// This receive all event this binding subscribe to
+PUBLIC void afbBindingV1ServiceEvent(const char *evtname, struct json_object *object) {
+
+ NOTICE(afbIface, "afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object));
+}
+
+// this is call when after all bindings are loaded
+PUBLIC int afbBindingV1ServiceInit(struct afb_service service) {
+ int rc=0;
+ srvitf = service;
+ struct json_object *queryurl;
+
+ if (alsaHalSndCard.initCB) {
+ rc= (alsaHalSndCard.initCB) (afbIface, service);
+ if (rc != 0) goto OnExit;
+ }
+
+ // register HAL with Alsa Low Level Binder
+ queryurl = json_object_new_object();
+ json_object_object_add(queryurl, "prefix", json_object_new_string(alsaHalSndCard.prefix));
+ json_object_object_add(queryurl, "name", json_object_new_string(alsaHalSndCard.name));
+ afb_service_call(srvitf, "alsacore", "registerHal", queryurl, halInitCB, NULL);
+
+ OnExit:
+ return (rc);
+};
+
+// Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT
+static const struct afb_verb_desc_v1 halSharedApi[] = {
+ /* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */
+ { .name = "ping", .session = AFB_SESSION_NONE, .callback = pingtest, .info = "Ping Binding"},
+ { .name = "getctls", .session = AFB_SESSION_NONE, .callback = halGetCtls, .info = "Get Control"},
+ { .name = "setvol", .session = AFB_SESSION_NONE, .callback = halSetVol, .info = "Set Volume"},
+ { .name = "getvol", .session = AFB_SESSION_NONE, .callback = halGetVol, .info = "Get Volume"},
+ { .name = "subscribe", .session = AFB_SESSION_NONE, .callback = halSubscribe,.info = "Subscribe Alsa Events"},
+ { .name = "monitor", .session = AFB_SESSION_NONE, .callback = halMonitor ,.info = "Monitor Alsa Events"},
+ { .name = NULL} /* marker for end of the array */
+};
+
+
+static struct afb_binding alsaHalBinding = {
+ /* description conforms to VERSION 1 */
+ .type= AFB_BINDING_VERSION_1,
+ .v1= {
+ .prefix= NULL,
+ .info = NULL,
+ .verbs = halSharedApi,
+ }
+};
+
+// Process HAL mapping from alsaHalSndCardT before registering HAL binder
+PUBLIC const struct afb_binding *afbBindingV1Register(const struct afb_binding_interface *itf) {
+
+ afbIface = itf; // need to keep a static trace of binder interface for avances functions
+ // alsaHalBinding.v1.verbs = halSharedApi; // complete sndcard specific alsaHalBinding with standard HAL APIs
+ alsaHalMapT *halCtls = alsaHalSndCard.ctls; // Get sndcard specific HAL control mapping
+
+ if (halCtls == NULL) {
+ ERROR(afbIface, "afbBindingV1Register Fail alsaHalCtlsMap==NULL");
+ return NULL;
+ }
+
+ // Create a zone to store HAL high/low level mapping
+ shareHallMap = malloc(EndHalCrlTag * sizeof (shareHallMap_T));
+ for (int idx = 0; (halCtls[idx].alsa.numid != 0 || halCtls[idx].cb.callback != NULL); idx++) {
+ if (halCtls[idx].alsa.numid == 0) halCtls[idx].alsa.numid =-1;
+ shareHallMap[halCtls[idx].alsa.control].numid = halCtls[idx].alsa.numid;
+ }
+
+ alsaHalBinding.v1.prefix= alsaHalSndCard.prefix;
+ alsaHalBinding.v1.info = alsaHalSndCard.info;
+ return &alsaHalBinding; /* returns the description of the binding */
+};
diff --git a/AlsaSound/HALayer/include/AlsaHalIface.h b/AlsaSound/HALayer/SharedHal/SharedHalLib.h
index 83ab57c..7cf4489 100644
--- a/AlsaSound/HALayer/include/AlsaHalIface.h
+++ b/AlsaSound/HALayer/SharedHal/SharedHalLib.h
@@ -15,38 +15,48 @@
* limitations under the License.
*/
-#ifndef SHAREDHALLIB_H
-#define SHAREDHALLIB_H
+#ifndef SHAREHALLIB_H
+#define SHAREHALLIB_H
#include <stdio.h>
-#include <afb/afb-binding.h>
-
-#include "MiscHelpers.h"
-#include "AlsaHalCtls.h"
-
-typedef const struct {
- halControlEnumT control;
- int numid;
- halGroupEnumT group;
- int values;
- int minval;
- int maxval;
- int step;
- char* info;
- halAclEnumT acl;
-
+#include "AudioCommonLib.h"
+
+typedef struct {
+ halCtlsEnumT control;
+ int numid;
+ halGroupEnumT group;
+ int values;
+ int minval;
+ int maxval;
+ int step;
+ halAclEnumT acl;
} alsaHalCtlMapT;
+// avoid compiler warning [Jose does not like typedef :) ]
+typedef struct afb_service alsaHalServiceT;
+
+typedef struct {
+ struct json_object* (*callback)(alsaHalServiceT service, int control, int value, alsaHalCtlMapT *map, void* handle);
+ void* handle;
+} alsaHalCbMapT;
+
+typedef struct {
+ alsaHalCtlMapT alsa;
+ alsaHalCbMapT cb;
+ char* info;
+} alsaHalMapT;
+
typedef struct {
const char *prefix;
const char *name;
const char *info;
- alsaHalCtlMapT *ctls;
+ alsaHalMapT *ctls;
+ int (*initCB) (const struct afb_binding_interface *itf, struct afb_service service);
} alsaHalSndCardT;
PUBLIC alsaHalSndCardT alsaHalSndCard;
-PUBLIC struct afb_binding alsaHalBinding;
+PUBLIC char* SharedHalLibVersion;
-#endif /* SHAREDHALLIB_H */
+#endif /* SHAREHALLIB_H */
diff --git a/AlsaSound/HALayer/include/MiscHelpers.h b/AlsaSound/HALayer/include/MiscHelpers.h
deleted file mode 100644
index 0181847..0000000
--- a/AlsaSound/HALayer/include/MiscHelpers.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * AlsaLibMapping -- provide low level interface with AUDIO 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.
- */
-
-#ifndef MISCHELPER_H
-#define MISCHELPER_H
-
-#ifndef PUBLIC
- #define PUBLIC
-#endif
-#ifndef FALSE
- #define FALSE 0
-#endif
-#ifndef TRUE
- #define TRUE 1
-#endif
-#define STATIC static
-
-#endif /* MISCHELPER_H */
-
diff --git a/AudioLogic/AudioLogicBinding.c b/AudioLogic/AudioLogicBinding.c
index 0c63d00..002ff42 100644
--- a/AudioLogic/AudioLogicBinding.c
+++ b/AudioLogic/AudioLogicBinding.c
@@ -30,10 +30,21 @@
PUBLIC const struct afb_binding_interface *afbIface;
-STATIC void localping(struct afb_req request) {
- json_object *query = afb_req_json(request);
- afb_req_success(request, query, NULL);
-}
+// Map HAL Enum to Labels
+typedef const struct {
+ halCtlsEnumT control;
+ char *label;
+} LogicControlT;
+
+// High Level Control Mapping to String for JSON & HTML5
+STATIC LogicControlT LogicControl[] = {
+ {.control= Master_Playback_Volume,.label= "Master_Volume"},
+ {.control= PCM_Playback_Volume, .label= "Playback_Volume"},
+ {.control= PCM_Playback_Switch, .label= "Playback_Switch"},
+ {.control= Capture_Volume, .label= "Capture_Volume"},
+
+ {.control= 0,.label= NULL} // closing convention
+};
/*
@@ -41,7 +52,7 @@ STATIC void localping(struct afb_req request) {
*/
STATIC const struct afb_verb_desc_v1 binding_verbs[] = {
/* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */
- { .name= "ping" , .session= AFB_SESSION_NONE, .callback= localping, .info= "Ping Binding" },
+ { .name= "ping" , .session= AFB_SESSION_NONE, .callback= pingtest, .info= "Ping Binding" },
{ .name= "setvolume", .session= AFB_SESSION_CHECK, .callback= audioLogicSetVol, .info= "Set Volume" },
{ .name= "getvolume", .session= AFB_SESSION_CHECK, .callback= audioLogicGetVol, .info= "Get Volume" },
{ .name= "subscribe", .session= AFB_SESSION_CHECK, .callback= audioLogicSubscribe, .info= "Subscribe AudioBinding Events" },
diff --git a/AudioLogic/AudioLogicLib.c b/AudioLogic/AudioLogicLib.c
index b45707a..e9d7104 100644
--- a/AudioLogic/AudioLogicLib.c
+++ b/AudioLogic/AudioLogicLib.c
@@ -30,45 +30,33 @@
static struct afb_service srvitf;
-STATIC int cbCheckResponse (struct afb_req request, int iserror, struct json_object *result) {
- struct json_object *response, *status, *info;
-
- if (iserror) { // on error proxy information we got from lower layer
- if (result) {
- if (json_object_object_get_ex(result, "request", &response)) {
- json_object_object_get_ex(response, "info" , &info);
- json_object_object_get_ex(response, "status", &status);
- afb_req_fail(request, json_object_get_string(status), json_object_get_string(info));
- goto OnExit;
- }
- } else {
- afb_req_fail(request, "cbCheckFail", "No Result inside API response" );
- }
- goto OnErrorExit;
- }
- return (0);
-
- OnErrorExit:
- return (1);
-}
+// This callback is fired when afb_service_call for api/alsacore/subctl returns
+STATIC void audioLogicSetVolCB(void *handle, int iserror, struct json_object *result) {
+ struct afb_req request = afb_req_unstore(handle);
+
+ if (!cbCheckResponse(request, iserror, result)) goto OnExit;
+OnExit:
+ return;
+}
PUBLIC void audioLogicSetVol(struct afb_req request) {
struct json_object *queryurl;
-
+ int volume=0; // FULUP TBD !!!!!!!!!!!!
+
// keep request for callback to respond
struct afb_req *handle = afb_req_store(request);
-
+
// get client context
AudioLogicCtxT *ctx = afb_req_context_get(request);
-
+
const char *vol = afb_req_value(request, "vol");
if (vol == NULL) {
- afb_req_fail_f (request, "argument-missing", "vol=+-%[0,100] missing");
+ afb_req_fail_f(request, "argument-missing", "vol=+-%[0,100] missing");
goto OnExit;
}
-
+
switch (vol[0]) {
case '+':
break;
@@ -76,99 +64,105 @@ PUBLIC void audioLogicSetVol(struct afb_req request) {
break;
case '%':
break;
-
+
default:
- afb_req_fail_f (request, "value-invalid", "volume should be (+-%[0-100]xxx) vol=%s", vol);
- goto OnExit;
+ afb_req_fail_f(request, "value-invalid", "volume should be (+-%[0-100]xxx) vol=%s", vol);
+ goto OnExit;
}
-
+
if (!ctx->halapi) {
afb_req_fail_f(request, "context-invalid", "No valid halapi in client context");
goto OnExit;
}
-
- // ********** Caluler le volume en % de manière intelligente
-
- queryurl=json_object_new_object();
- json_object_object_add(ctx->queryurl, "pcm",json_object_new_int(Master_Playback_Volume));
- json_object_object_add(ctx->queryurl, "value",json_object_new_int(volume));
-
+
+ // ********** Caluler le volume en % de manière intelligente
+ queryurl = json_object_new_object();
+ json_object_object_add(ctx->queryurl, "pcm", json_object_new_int(Master_Playback_Volume));
+ json_object_object_add(ctx->queryurl, "value", json_object_new_int(volume));
+
// subcontract HAL API to process volume
afb_service_call(srvitf, ctx->halapi, "volume", queryurl, audioLogicSetVolCB, handle);
-
+
// final success/failure messages handle from callback
- OnExit:
- return;
+OnExit:
+ return;
}
// This callback is fired when afb_service_call for api/alsacore/subctl returns
-STATIC void alsaSubcribeCB (void *handle, int iserror, struct json_object *result) {
+
+STATIC void alsaSubcribeCB(void *handle, int iserror, struct json_object *result) {
struct afb_req request = afb_req_unstore(handle);
- if (!cbCheckResponse (request, iserror, result)) goto OnExit
-
- OnExit:
+ if (!cbCheckResponse(request, iserror, result)) goto OnExit;
+
+OnExit:
return;
}
// Create and subscribe to alsacore ctl events
PUBLIC void audioLogicMonitor(struct afb_req request) {
-
- // keep request for callback to respond
- struct afb_req *handle = afb_req_store(request);
-
+
+
// get client context
AudioLogicCtxT *ctx = afb_req_context_get(request);
-
+ if (!ctx) {
+ afb_req_fail_f(request, "ctx-notfound", "No Client Context HAL/getcontrol devid=[%] name=[%s]", ctx->devid, ctx->shortname);
+ goto OnExit;
+ }
+
// push request to low level binding
- NOTICE (afbIface, "audioLogicMonitor ctx->devid=%s [ctx->queryurl=%s]", ctx->devid, json_object_to_json_string(ctx->queryurl));
-
+ NOTICE(afbIface, "audioLogicMonitor ctx->devid=%s [ctx->queryurl=%s]", ctx->devid, json_object_to_json_string(ctx->queryurl));
+
if (ctx->queryurl) {
- json_object_get (ctx->queryurl); // Make sure usage count does not fall to zero
+ json_object_get(ctx->queryurl); // Make sure usage count does not fall to zero
+ struct afb_req *handle = afb_req_store(request);
afb_service_call(srvitf, "alsacore", "subscribe", ctx->queryurl, alsaSubcribeCB, handle);
}
-
- else afb_req_fail_f(request, "context-invalid", "No valid queryurl in client context");
+ else afb_req_fail_f(request, "context-invalid", "No valid queryurl in client context");
- // success/failure messages return from callback
+ // success/failure messages return from callback
+OnExit:
+ return;
}
// Subscribe to AudioBinding events
-PUBLIC void audioLogicSubscribe (struct afb_req request) {
-
- return;
+
+PUBLIC void audioLogicSubscribe(struct afb_req request) {
+
+ return;
}
// Call when all bindings are loaded and ready to accept request
PUBLIC void audioLogicGetVol(struct afb_req request) {
-
+
// Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card
- afb_req_success (request, NULL, NULL);
+ afb_req_success(request, NULL, NULL);
return;
-
+
}
// This callback is fired when afb_service_call for api/alsacore/subctl returns
-STATIC void audioLogicOpenCB2 (void *handle, int iserror, struct json_object *result) {
+
+STATIC void audioLogicOpenCB2(void *handle, int iserror, struct json_object *result) {
struct json_object *response;
-
+
// Make sure we got a response from API
struct afb_req request = afb_req_unstore(handle);
- if (!cbCheckResponse (request, iserror, result)) goto OnExit
+ if (!cbCheckResponse(request, iserror, result)) goto OnExit;
+
+ // get client context
+ AudioLogicCtxT *ctx = afb_req_context_get(request);
+ if (!ctx) {
+ afb_req_fail_f(request, "ctx-notfound", "No Client Context HAL/getcontrol devid=[%] name=[%s]", ctx->devid, ctx->shortname);
+ goto OnExit;
+ }
// Get response from object
json_object_object_get_ex(result, "response", &response);
if (!response) {
afb_req_fail_f(request, "response-notfound", "No Controls return from HAL/getcontrol devid=[%] name=[%s]", ctx->devid, ctx->shortname);
- goto OnExit;
- }
-
- // get client context
- AudioLogicCtxT *ctx = afb_req_context_get(request);
- if (!ctx) {
- afb_req_fail_f(request, "ctx-notfound", "No Client Context HAL/getcontrol devid=[%] name=[%s]", ctx->devid, ctx->shortname);
- goto OnExit;
+ goto OnExit;
}
// extract sounds controls information from received Object
@@ -176,97 +170,97 @@ STATIC void audioLogicOpenCB2 (void *handle, int iserror, struct json_object *re
json_object_object_get_ex(response, "ctls", &ctls);
if (!ctls) {
afb_req_fail_f(request, "ctls-notfound", "No Controls return from HAL/getcontrol devid=[%] name=[%s]", ctx->devid, ctx->shortname);
- goto OnExit;
+ goto OnExit;
}
-
+
// make sure return controls have a valid type
- if (json_object_get_type (ctls) != json_type_array ) {
+ if (json_object_get_type(ctls) != json_type_array) {
afb_req_fail_f(request, "ctls-notarray", "Invalid Controls return from HAL/getcontrol devid=[%] name=[%s]", ctx->devid, ctx->shortname);
- goto OnExit;
+ goto OnExit;
}
-
+
// loop on array and store values into client context
- for (int idx=0; idx < json_object_array_length (ctls), idx++) {
+ for (int idx = 0; idx < json_object_array_length(ctls); idx++) {
struct json_object *ctl;
- halControlEnumT control;
+ halCtlsEnumT control;
int value;
-
+
ctl = json_object_array_get_idx(ctls, idx);
- if (json_object_array_length(ctl != 2)) {
+ if (json_object_array_length(ctl) != 2) {
afb_req_fail_f(request, "ctl-invalid", "Invalid Control return from HAL/getcontrol devid=[%] name=[%s] ctl=%s"
- , ctx->devid, ctx->shortname, json_object_get_string(ctl));
- goto OnExit;
+ , ctx->devid, ctx->shortname, json_object_get_string(ctl));
+ goto OnExit;
}
-
+
// As HAL and Business logic use the same AlsaMixerHal.h direct conversion is not an issue
- control = (halControlEnumT)json_object_get_int(json_object_array_get_idx(ctl,0));
- value = json_object_get_int(json_object_array_get_idx(ctl,0));
-
- switch(control) {
+ control = (halCtlsEnumT) json_object_get_int(json_object_array_get_idx(ctl, 0));
+ value = json_object_get_int(json_object_array_get_idx(ctl, 1));
+
+ switch (control) {
case Master_Playback_Volume:
ctx->volumes.masterPlaybackVolume = value;
break;
-
+
case PCM_Playback_Volume:
- ctx->volumes.pcmPlaybackVolume = value;
+ ctx->volumes.pcmPlaybackVolume = value;
break;
-
+
case PCM_Playback_Switch:
ctx->volumes.pcmPlaybackSwitch = value;
break;
-
+
case Capture_Volume:
ctx->volumes.captureVolume = value;
break;
-
+
default:
- NOTICE (afbIface, "audioLogicOpenCB2 unknown HAL control=[%s]", json_object_get_string(ctl)):
+ NOTICE(afbIface, "audioLogicOpenCB2 unknown HAL control=[%s]", json_object_get_string(ctl));
}
}
-
- OnExit:
+
+OnExit:
afb_req_context_set(request, ctx, free);
return;
}
// This callback is fired when afb_service_call for api/alsacore/subctl returns
-STATIC void audioLogicOpenCB1 (void *handle, int iserror, struct json_object *result) {
+STATIC void audioLogicOpenCB1(void *handle, int iserror, struct json_object *result) {
struct json_object *response, *subobj;
-
+
// Make sure we got a valid API response
struct afb_req request = afb_req_unstore(handle);
- if (!cbCheckResponse (request, iserror, result)) goto OnExit
-
+ if (!cbCheckResponse(request, iserror, result)) goto OnExit;
+
// Get response from object
json_object_object_get_ex(result, "response", &response);
if (!response) {
- afb_req_fail_f(request, "response-notfound", "No Controls return from HAL/getcontrol devid=[%] name=[%s]", ctx->devid, ctx->shortname);
- goto OnExit;
+ afb_req_fail_f(request, "response-notfound", "No Controls return from HAL/getcontrol");
+ goto OnExit;
}
// attach client context to session
- AudioLogicCtxT *ctx = malloc (sizeof(AudioLogicCtxT));
+ AudioLogicCtxT *ctx = malloc(sizeof (AudioLogicCtxT));
// extract information from Json Alsa Object
json_object_object_get_ex(response, "cardid", &subobj);
- if (subobj) ctx->cardid= json_object_get_int(subobj);
+ if (subobj) ctx->cardid = json_object_get_int(subobj);
// store devid as an object for further alsa request
json_object_object_get_ex(response, "devid", &subobj);
- if (subobj) ctx->devid= strdup(json_object_get_string(subobj));
+ if (subobj) ctx->devid = strdup(json_object_get_string(subobj));
json_object_object_get_ex(response, "halapi", &subobj);
- if (subobj) ctx->halapi= strdup(json_object_get_string(subobj));
+ if (subobj) ctx->halapi = strdup(json_object_get_string(subobj));
json_object_object_get_ex(response, "shortname", &subobj);
- if (subobj)ctx->shortname=strdup(json_object_get_string(subobj));
+ if (subobj)ctx->shortname = strdup(json_object_get_string(subobj));
json_object_object_get_ex(response, "longname", &subobj);
- if (subobj)ctx->longname=strdup(json_object_get_string(subobj));
+ if (subobj)ctx->longname = strdup(json_object_get_string(subobj));
// save queryurl with devid only for further ALSA request
- ctx->queryurl=json_object_new_object();
- json_object_object_add(ctx->queryurl, "devid",json_object_new_string(ctx->devid));
+ ctx->queryurl = json_object_new_object();
+ json_object_object_add(ctx->queryurl, "devid", json_object_new_string(ctx->devid));
afb_req_context_set(request, ctx, free);
@@ -274,25 +268,25 @@ STATIC void audioLogicOpenCB1 (void *handle, int iserror, struct json_object *re
if (!ctx->halapi) {
afb_req_fail_f(request, "hal-notfound", "No HAL found devid=[%] name=[%s]", ctx->devid, ctx->shortname);
goto OnExit;
- }
-
- struct json_object *queryurl =json_object_new_object();
- struct json_object *ctls =json_object_new_object();
+ }
+
+ struct json_object *queryurl = json_object_new_object();
+ struct json_object *ctls = json_object_new_array();
// add sound controls we want to keep track of into client session context
- json_object_object_add(ctls, json_object_new_int((int)Master_Playback_Volume));
- json_object_object_add(ctls, json_object_new_int((int)PCM_Playback_Volume));
- json_object_object_add(ctls, json_object_new_int((int)PCM_Playback_Switch));
- json_object_object_add(ctls, json_object_new_int((int)Capture_Volume));
+ json_object_array_add(ctls, json_object_new_int((int) Master_Playback_Volume));
+ json_object_array_add(ctls, json_object_new_int((int) PCM_Playback_Volume));
+ json_object_array_add(ctls, json_object_new_int((int) PCM_Playback_Switch));
+ json_object_array_add(ctls, json_object_new_int((int) Capture_Volume));
// send request to soundcard HAL binding
- json_object_array_add(queryurl, ctx->queryurl);
- json_object_object_add(queryurl, "ctls",ctls);
+ json_object_object_add(queryurl, "ctls", ctls);
+ handle = afb_req_store(request); // FULUP ???? Needed for 2nd Callback ????
afb_service_call(srvitf, ctx->halapi, "getControl", queryurl, audioLogicOpenCB2, handle);
-
+
afb_req_success(request, response, NULL);
-
- OnExit:
+
+OnExit:
// release original calling request
afb_req_unref(request);
return;
@@ -303,21 +297,20 @@ PUBLIC void audioLogicOpen(struct afb_req request) {
// Delegate query to lower level
struct afb_req *handle = afb_req_store(request);
- if (!handle) afb_req_fail(request, "error", "out of memory");
- else afb_service_call(srvitf, "alsacore", "getCardId", json_object_get(afb_req_json(request)), audioLogicOpenCB1, handle);
+ afb_service_call(srvitf, "alsacore", "getCardId", json_object_get(afb_req_json(request)), audioLogicOpenCB1, handle);
}
// Free client context create from audioLogicOpenCB
-PUBLIC void audioLogicClose (struct afb_req request) {
-
+PUBLIC void audioLogicClose(struct afb_req request) {
+
// retrieve current client context to print debug info
AudioLogicCtxT *ctx = (AudioLogicCtxT*) afb_req_context_get(request);
- DEBUG (afbIface, "audioLogicClose cardid=%d devid=%s shortname=%s longname=%s", ctx->cardid, ctx->devid, ctx->shortname, ctx->longname);
+ DEBUG(afbIface, "audioLogicClose cardid=%d devid=%s shortname=%s longname=%s", ctx->cardid, ctx->devid, ctx->shortname, ctx->longname);
}
// this function is call after all binder are loaded and initialised
-PUBLIC int audioLogicInit (struct afb_service service) {
- srvitf = service;
+PUBLIC int audioLogicInit(struct afb_service service) {
+ srvitf = service;
return 0;
}
diff --git a/AudioLogic/AudioLogicLib.h b/AudioLogic/AudioLogicLib.h
index 10e431d..77b8b7b 100644
--- a/AudioLogic/AudioLogicLib.h
+++ b/AudioLogic/AudioLogicLib.h
@@ -15,30 +15,14 @@
* limitations under the License.
*/
+#ifndef AUDIOLOGIC_H
+#define AUDIOLOGIC_H
-// few coding convention
-typedef int BOOL;
-#ifndef PUBLIC
- #define PUBLIC
-#endif
-#ifndef FALSE
- #define FALSE 0
-#endif
-#ifndef TRUE
- #define TRUE 1
-#endif
-#define STATIC static
-
-#ifndef AUDIOLIBMAPPING_H
-#define AUDIOLIBMAPPING_H
-
+#include "AudioCommonLib.h"
#include <json-c/json.h>
#include <afb/afb-binding.h>
#include <afb/afb-service-itf.h>
-#include "AlsaHalCtls.h" // Alsa Hardware Abstraction Layer Controls
-
-
// import from AlsaAfbBinding
extern const struct afb_binding_interface *afbIface;
@@ -69,5 +53,5 @@ PUBLIC void audioLogicClose(struct afb_req request);
PUBLIC void audioLogicSubscribe(struct afb_req request);
PUBLIC int audioLogicInit (struct afb_service service);
-#endif /* AUDIOLIBMAPPING_H */
+#endif /* AUDIOLOGIC_H */
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 006ff74..0bd639d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -98,18 +98,21 @@ ENDIF(CMAKE_BUILD_TYPE MATCHES Debug)
SET(include_dirs
${INCLUDE_DIRS}
- ${CMAKE_SOURCE_DIR}/AlsaSound/HALayer/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/Common
${json-c_INCLUDE_DIRS}
${afb-daemon_INCLUDE_DIRS}
)
-SET(link_libraries
+# AudioCommon is linked statically with each audiobindings
+SET(link_libraries
+ ${CMAKE_BINARY_DIR}/Common/libaudiocommon.a
${libefence_LIBRARIES}
${json-c_LIBRARIES}
)
# Bindings to compile
# --------------------
+add_subdirectory(Common)
add_subdirectory(AlsaSound)
add_subdirectory(AudioLogic)
add_subdirectory(htdocs)
diff --git a/Common/AudioCommonLib.c b/Common/AudioCommonLib.c
new file mode 100644
index 0000000..0517e8e
--- /dev/null
+++ b/Common/AudioCommonLib.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author 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 <json-c/json.h>
+#include <afb/afb-binding.h>
+#include <afb/afb-service-itf.h>
+#include <semaphore.h>
+#include <string.h>
+
+#include "AudioCommonLib.h"
+
+typedef struct {
+ int index;
+ int numid;
+} shareHallMap_T;
+
+
+PUBLIC int cbCheckResponse(struct afb_req request, int iserror, struct json_object *result) {
+ struct json_object *response, *status, *info;
+
+ if (iserror) { // on error proxy information we got from lower layer
+ if (result) {
+ if (json_object_object_get_ex(result, "request", &response)) {
+ json_object_object_get_ex(response, "info", &info);
+ json_object_object_get_ex(response, "status", &status);
+ afb_req_fail(request, json_object_get_string(status), json_object_get_string(info));
+ goto OnErrorExit;
+ }
+ } else {
+ afb_req_fail(request, "cbCheckFail", "No Result inside API response");
+ }
+ goto OnErrorExit;
+ }
+ return (0);
+
+OnErrorExit:
+ return (-1);
+}
+
+// This function should be part of Generic AGL Framework
+PUBLIC json_object* afb_service_call_sync(struct afb_service srvitf, struct afb_req request, char* api, char* verb, struct json_object* queryurl, void *handle) {
+ json_object* response = NULL;
+ int status = 0;
+ sem_t semid;
+
+ // Nested procedure are allow in GNU and allow us to keep caller stack valid
+
+ void callback(void *handle, int iserror, struct json_object * result) {
+
+ // Process Basic Error
+ if (!cbCheckResponse(request, iserror, result)) {
+ status = -1;
+ goto OnExitCB;
+ }
+
+ // Get response from object
+ json_object_object_get_ex(result, "response", &response);
+ if (!response) {
+ afb_req_fail_f(request, "response-notfound", "No Controls return from alsa/getcontrol result=[%s]", json_object_get_string(result));
+ goto OnExitCB;
+ }
+
+OnExitCB:
+ sem_post(&semid);
+ }
+
+ // Create an exclusive semaphore
+ status = sem_init(&semid, 0, 0);
+ if (status < 0) {
+ afb_req_fail_f(request, "error:seminit", "Fail to allocate semaphore err=[%s]", strerror(status));
+ goto OnExit;
+ }
+
+ // Call service and wait for call back to finish before moving any further
+ afb_service_call(srvitf, "alsacore", "getctl", queryurl, callback, handle);
+ sem_wait(&semid);
+
+OnExit:
+ return (response);
+}
+
+PUBLIC void pingtest(struct afb_req request) {
+ json_object *query = afb_req_json(request);
+ afb_req_success(request, query, NULL);
+}
diff --git a/AlsaSound/HALayer/include/AlsaHalCtls.h b/Common/AudioCommonLib.h
index a17315a..ebee389 100644
--- a/AlsaSound/HALayer/include/AlsaHalCtls.h
+++ b/Common/AudioCommonLib.h
@@ -19,10 +19,17 @@
* http://www.tldp.org/HOWTO/Alsa-sound-6.html
*/
+#ifndef AUDIOCOMMON_H
+#define AUDIOCOMMON_H
+#include <json-c/json.h>
+#include <afb/afb-binding.h>
+#include <afb/afb-service-itf.h>
-#ifndef ALSAMIXERMAP_H
-#define ALSAMIXERMAP_H
+#ifndef PUBLIC
+ #define PUBLIC
+#endif
+#define STATIC static
// Most controls are MIXER but some vendor specific are possible
typedef enum {
@@ -32,6 +39,7 @@ typedef enum {
SWITCH,
ROUTE,
CARD,
+ ENUM,
} halGroupEnumT;
typedef enum {
@@ -50,8 +58,11 @@ typedef enum {
Capture_Volume,
EndHalCrlTag // used to compute number of ctls
-} halControlEnumT;
+} halCtlsEnumT;
+PUBLIC int cbCheckResponse(struct afb_req request, int iserror, struct json_object *result) ;
+PUBLIC json_object* afb_service_call_sync(struct afb_service srvitf, struct afb_req request, char* api, char* verb, struct json_object* queryurl, void *handle);
+PUBLIC void pingtest(struct afb_req request);
-#endif /* ALSAMIXERMAP_H */
+#endif /* AUDIOCOMMON_H */
diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt
new file mode 100644
index 0000000..79ee8ac
--- /dev/null
+++ b/Common/CMakeLists.txt
@@ -0,0 +1,31 @@
+###########################################################################
+# Copyright 2015, 2016, 2017 IoT.bzh
+#
+# author: 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.
+###########################################################################
+
+PROJECT(audio-common C)
+
+INCLUDE_DIRECTORIES(${include_dirs})
+
+##################################################
+# AudioCommon is a local static Library
+##################################################
+ADD_LIBRARY(audiocommon STATIC AudioCommonLib.c)
+SET_TARGET_PROPERTIES(audiocommon PROPERTIES OUTPUT_NAME audiocommon)
+SET(link_libraries ${libefence_LIBRARIES} ${json-c_LIBRARIES})
+TARGET_LINK_LIBRARIES(audiocommon ${link_libraries})
+
+
diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml
index ee7b001..6db5cb9 100644
--- a/nbproject/configurations.xml
+++ b/nbproject/configurations.xml
@@ -6,7 +6,7 @@
<df name="HALayer">
<df name="include">
<in>AlsaHalIface.h</in>
- <in>MiscHelpers.h</in>
+ <in>AudioCommonLib.h</in>
</df>
</df>
</df>
@@ -65,16 +65,34 @@
<preBuildFirst>true</preBuildFirst>
</preBuild>
</makefileType>
+ <item path="AlsaSound/HALayer/Shared/ShareHalLib.h"
+ ex="false"
+ tool="3"
+ flavor2="0">
+ </item>
+ <item path="AlsaSound/HALayer/Shared/SharedHalLib.h"
+ ex="false"
+ tool="3"
+ flavor2="0">
+ </item>
<item path="AlsaSound/HALayer/include/AlsaHalIface.h"
ex="false"
tool="3"
flavor2="0">
</item>
- <item path="AlsaSound/HALayer/include/MiscHelpers.h"
+ <item path="AlsaSound/HALayer/include/AudioCommonLib.h"
ex="false"
tool="3"
flavor2="0">
</item>
+ <item path="Common/AudioCommonLib.h" ex="false" tool="3" flavor2="0">
+ </item>
+ <item path="Common/include/AudioCommonLib.h" ex="false" tool="3" flavor2="0">
+ </item>
+ <item path="Common/include/ShareHalLib.h" ex="false" tool="3" flavor2="0">
+ </item>
+ <item path="Common/include/SharedHalLib.h" ex="false" tool="3" flavor2="0">
+ </item>
<item path="MostVolume/DeviceContainer.cpp" ex="false" tool="1" flavor2="0">
</item>
<item path="MostVolume/DeviceValue.cpp" ex="false" tool="1" flavor2="0">