summaryrefslogtreecommitdiffstats
path: root/ahl-binding/ahl-config.c
diff options
context:
space:
mode:
Diffstat (limited to 'ahl-binding/ahl-config.c')
-rw-r--r--ahl-binding/ahl-config.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/ahl-binding/ahl-config.c b/ahl-binding/ahl-config.c
new file mode 100644
index 0000000..c60cb9c
--- /dev/null
+++ b/ahl-binding/ahl-config.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2017 "Audiokinetic Inc"
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <json-c/json.h>
+#include "wrap-json.h"
+#include "filescan-utils.h"
+
+#include "ahl-binding.h"
+
+extern AHLCtxT g_AHLCtx;
+
+static InterruptBehaviorT InterruptBehaviorToEnum(char * in_pInterruptBehaviorStr)
+{
+ g_assert_nonnull(in_pInterruptBehaviorStr);
+ if (strcasecmp(in_pInterruptBehaviorStr,AHL_INTERRUPTBEHAVIOR_CONTINUE)==0) {
+ return INTERRUPTBEHAVIOR_CONTINUE;
+ }
+ else if (strcasecmp(in_pInterruptBehaviorStr,AHL_INTERRUPTBEHAVIOR_CANCEL)==0) {
+ return INTERRUPTBEHAVIOR_CANCEL;
+ }
+ else if (strcasecmp(in_pInterruptBehaviorStr,AHL_INTERRUPTBEHAVIOR_PAUSE)==0) {
+ return INTERRUPTBEHAVIOR_PAUSE;
+ }
+ else
+ return INTERRUPTBEHAVIOR_MAXVALUE;
+}
+
+static json_object* CtlConfigScan(const char *dirList, const char *prefix) {
+ char controlFile [CONTROL_MAXPATH_LEN];
+ strncpy(controlFile, prefix, CONTROL_MAXPATH_LEN);
+ strncat(controlFile, GetBinderName(), CONTROL_MAXPATH_LEN);
+
+ // search for default dispatch config file
+ json_object* responseJ = ScanForConfig(dirList, CTL_SCAN_RECURSIVE, controlFile, ".json");
+
+ return responseJ;
+}
+
+static char* CtlConfigSearch(const char *dirList, const char *prefix) {
+ int index, err;
+
+ // search for default dispatch config file
+ json_object* responseJ = CtlConfigScan (dirList, prefix);
+ if (!responseJ) return NULL;
+
+ // We load 1st file others are just warnings
+ for (index = 0; index < json_object_array_length(responseJ); index++) {
+ json_object *entryJ = json_object_array_get_idx(responseJ, index);
+
+ char *filename;
+ char*fullpath;
+ err = wrap_json_unpack(entryJ, "{s:s, s:s !}", "fullpath", &fullpath, "filename", &filename);
+ if (err) {
+ AFB_ERROR("CTL-INIT HOOPs invalid JSON entry= %s", json_object_get_string(entryJ));
+ return NULL;
+ }
+
+ if (index == 0) {
+ char filepath[CONTROL_MAXPATH_LEN];
+ strncpy(filepath, fullpath, sizeof (filepath));
+ strncat(filepath, "/", sizeof (filepath));
+ strncat(filepath, filename, sizeof (filepath));
+ return (strdup(filepath));
+ }
+ }
+ // no config found
+ return NULL;
+}
+
+int ParseHLBConfig() {
+ char * versionStr = NULL;
+ json_object * jAudioRoles = NUL L;
+ json_object * jHALList = NULL;
+ char * policyModule = NULL;
+
+ const char *dirList=getenv("AAAA_CONFIG_PATH");
+ if (!dirList) dirList=CONTROL_CONFIG_PATH;
+
+ const char *configfile_path =CtlConfigSearch(dirList, "ahl-");
+ if (!configfile_path) {
+ AFB_ERROR("Error: No control-* config found invalid JSON %s ", dirList);
+ return 1;
+ }
+
+ AFB_INFO("High-level config file -> %s\n", configfile_path);
+
+ // Open configuration file
+ json_object *config_JFile=json_object_from_file(configfile_path);
+ if(config_JFile == NULL)
+ {
+ AFB_ERROR("Error: Can't open configuration file -> %s",configfile_path);
+ return AHL_FAIL;
+ }
+
+ int err = wrap_json_unpack(config_JFile, "{s:s,s:s,s:o,s:o}", "version", &versionStr,"policy_module", &policyModule,"audio_roles",&jAudioRoles,"hal_list",&jHALList);
+ if (err) {
+ AFB_ERROR("Invalid configuration file -> %s", configfile_path);
+ return AHL_FAIL;
+ }
+ AFB_INFO("High-level audio API version: %s", "1.0.0");
+ AFB_INFO("Config version: %s", versionStr);
+ AFB_INFO("Policy module: %s", policyModule);
+
+ int iHALListLength = json_object_array_length(jHALList);
+ g_AHLCtx.policyCtx.pHALList = g_ptr_array_new_with_free_func(g_free);
+ int iNumberOfRoles = json_object_array_length(jAudioRoles);
+ g_AHLCtx.policyCtx.pRoleInfo = g_hash_table_new(g_str_hash, g_str_equal);
+
+ for (int i = 0; i < iHALListLength; i++)
+ {
+ char * pHAL = NULL;
+ json_object * jHAL = json_object_array_get_idx(jHALList,i);
+ if (jHAL) {
+ pHAL = (char *)json_object_get_string(jHAL);
+ char * pHALName = g_strdup( pHAL );
+ g_ptr_array_add( g_AHLCtx.policyCtx.pHALList, pHALName );
+
+ // Set dependency on HAL specified
+ err = afb_daemon_require_api_v2(pHAL,1) ;
+ if( err != 0 )
+ {
+ AFB_ERROR("Audio high level API could not set dependency on API: %s",pHAL);
+ return AHL_FAIL;
+ }
+ }
+ }
+
+ for (int i = 0; i < iNumberOfRoles; i++)
+ {
+ int priority = 0;
+ json_object * jAudioRole = json_object_array_get_idx(jAudioRoles,i);
+ json_object * jOutputDevices = NULL;
+ json_object * jInputDevices = NULL;
+ json_object * jActions = NULL;
+ char * pRoleName = NULL;
+ char * pInteruptBehavior = NULL;
+
+ int iNumOutDevices = 0;
+ int iNumInDevices = 0;
+ int iNumActions = 0;
+
+ err = wrap_json_unpack(jAudioRole, "{s:s,s:i,s:s,s?o,s?o,s?o}",
+ "name", &pRoleName,
+ "priority",&priority,
+ "interupt_behavior",&pInteruptBehavior,
+ "output",&jOutputDevices,
+ "input",&jInputDevices,
+ "actions",&jActions
+ );
+ if (err) {
+ AFB_ERROR("Invalid audio role configuration : %s", json_object_to_json_string(jAudioRole));
+ return AHL_FAIL;
+ }
+
+ if (jOutputDevices)
+ iNumOutDevices = json_object_array_length(jOutputDevices);
+ if (jInputDevices)
+ iNumInDevices = json_object_array_length(jInputDevices);
+ if (jActions)
+ iNumActions = json_object_array_length(jActions);
+
+ RoleInfoT * pRoleInfo = (RoleInfoT*) malloc(sizeof(RoleInfoT));
+ memset(pRoleInfo,0,sizeof(RoleInfoT));
+ pRoleInfo->pRoleName = g_strdup( pRoleName );
+ pRoleInfo->iPriority = priority;
+ pRoleInfo->eInterruptBehavior = InterruptBehaviorToEnum(pInteruptBehavior);
+
+ // Actions
+ pRoleInfo->pActionList = g_ptr_array_new_with_free_func(g_free);
+ // Parse and validate list of available actions
+ for (int i = 0; i < iNumActions; i++)
+ {
+ json_object * jAction = json_object_array_get_idx(jActions,i);
+ char * pActionName = (char *)json_object_get_string(jAction);
+ if (pActionName)
+ g_ptr_array_add(pRoleInfo->pActionList, g_strdup(pActionName));
+ }
+
+ // Sources
+ pRoleInfo->pSourceEndpoints = g_ptr_array_new_with_free_func(g_free);
+ if (iNumInDevices) {
+ err = EnumerateDevices(jInputDevices,pRoleName,ENDPOINTTYPE_SOURCE,pRoleInfo->pSourceEndpoints);
+ if (err) {
+ AFB_ERROR("Invalid input devices : %s", json_object_to_json_string(jInputDevices));
+ return AHL_FAIL;
+ }
+ }
+ // Sinks
+ pRoleInfo->pSinkEndpoints = g_ptr_array_new_with_free_func(g_free);
+ if (iNumOutDevices) {
+ err = EnumerateDevices(jOutputDevices,pRoleName,ENDPOINTTYPE_SINK,pRoleInfo->pSinkEndpoints);
+ if (err) {
+ AFB_ERROR("Invalid output devices : %s", json_object_to_json_string(jOutputDevices));
+ return AHL_FAIL;
+ }
+ }
+
+ g_hash_table_insert(g_AHLCtx.policyCtx.pRoleInfo, pRoleInfo->pRoleName, pRoleInfo);
+ }
+
+ // Build lists of all device URI referenced in config file (input/output)
+ AFB_DEBUG ("Audio high-level - Parse high-level audio configuration done");
+ return AHL_SUCCESS;
+}