summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFulup Ar Foll <fulup@iot.bzh>2017-10-30 21:18:41 +0100
committerFulup Ar Foll <fulup@iot.bzh>2017-10-30 21:18:41 +0100
commitc68316b787706d49bbddb387af45e25804678ce6 (patch)
tree828f3b2849e72646baf4c29fa1d5355e0c4fddd6 /src
parentc46955de2731563d1991691cd1a7986f05f019e3 (diff)
Code Reorganisation preparing transfer to gerrit
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt67
-rw-r--r--src/ahl-apidef.h305
-rw-r--r--src/ahl-apidef.json565
-rw-r--r--src/ahl-binding.c1577
-rw-r--r--src/ahl-binding.h94
-rw-r--r--src/ahl-config.c178
-rw-r--r--src/ahl-deviceenum.c331
-rw-r--r--src/ahl-interface.h99
-rw-r--r--src/ahl-policy-utils.c248
-rw-r--r--src/ahl-policy-utils.h177
-rw-r--r--src/ahl-policy.c1108
-rw-r--r--src/ahl-policy.h73
12 files changed, 0 insertions, 4822 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
deleted file mode 100644
index 4429b0b..0000000
--- a/src/CMakeLists.txt
+++ /dev/null
@@ -1,67 +0,0 @@
-###########################################################################
-# Copyright 2017 Audiokinetic.com
-#
-# author: Francois Thibault <fthibault@audiokinetic.com>
-#
-# 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.
-###########################################################################
-# Generate API-v2 hat from OpenAPI json definition
-macro(SET_TARGET_GENSKEL TARGET_NAME API_DEF_NAME)
- add_custom_command(OUTPUT ${API_DEF_NAME}.h
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- DEPENDS ${API_DEF_NAME}.json
- COMMAND afb-genskel ${API_DEF_NAME}.json >${API_DEF_NAME}.h
- )
- add_custom_target(${API_DEF_NAME}_OPENAPI DEPENDS ${API_DEF_NAME}.h)
- add_dependencies(${TARGET_NAME} ${API_DEF_NAME}_OPENAPI)
-
-endmacro(SET_TARGET_GENSKEL)
-
-FIND_PACKAGE(PkgConfig REQUIRED)
-PKG_CHECK_MODULES(GLIB_PKG REQUIRED glib-2.0)
-
-# get_cmake_property(_variableNames VARIABLES)
-# foreach (_variableName ${_variableNames})
-# message(STATUS "${_variableName}=${${_variableName}}")
-# endforeach()
-
-# Add target to project dependency list
-PROJECT_TARGET_ADD(audiohighlevel)
-
- # Define project Targets
- ADD_LIBRARY(${TARGET_NAME} MODULE ahl-binding.c ahl-deviceenum.c ahl-config.c ahl-policy-utils.c ahl-policy.c)
-
- # Generate API-v2 hat from OpenAPI json definition
- SET_TARGET_GENSKEL(${TARGET_NAME} ahl-apidef)
-
- # Binder exposes a unique public entry point
- SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
- PREFIX "afb-"
- LABELS "BINDING"
- LINK_FLAGS ${BINDINGS_LINK_FLAG}
- OUTPUT_NAME ${TARGET_NAME}
- )
-
- # Define target includes
- TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME}
- PUBLIC ${GLIB_PKG_INCLUDE_DIRS}
- )
-
- # Library dependencies (include updates automatically)
- # Find package for GLIB does not seem to export
- TARGET_LINK_LIBRARIES(${TARGET_NAME}
- afb-utilities
- ${GLIB_PKG_LIBRARIES}
- ${link_libraries}
- )
-
diff --git a/src/ahl-apidef.h b/src/ahl-apidef.h
deleted file mode 100644
index fd957ce..0000000
--- a/src/ahl-apidef.h
+++ /dev/null
@@ -1,305 +0,0 @@
-
-static const char _afb_description_v2_audiohl[] =
- "{\"openapi\":\"3.0.0\",\"info\":{\"description\":\"Audio high level API "
- "for AGL applications\",\"title\":\"audiohighlevel\",\"version\":\"1.0\","
- "\"x-binding-c-generator\":{\"api\":\"audiohl\",\"version\":2,\"prefix\":"
- "\"audiohlapi_\",\"postfix\":\"\",\"start\":null,\"onevent\":\"AhlOnEvent"
- "\",\"init\":\"AhlBindingInit\",\"scope\":\"\",\"private\":false}},\"serv"
- "ers\":[{\"url\":\"ws://{host}:{port}/api/audiohl\",\"description\":\"Aud"
- "io high level API for AGL applications.\",\"variables\":{\"host\":{\"def"
- "ault\":\"localhost\"},\"port\":{\"default\":\"1234\"}},\"x-afb-events\":"
- "[{\"$ref\":\"#/components/schemas/afb-event\"}]}],\"components\":{\"sche"
- "mas\":{\"afb-reply\":{\"$ref\":\"#/components/schemas/afb-reply-v2\"},\""
- "afb-event\":{\"$ref\":\"#/components/schemas/afb-event-v2\"},\"afb-reply"
- "-v2\":{\"title\":\"Generic response.\",\"type\":\"object\",\"required\":"
- "[\"jtype\",\"request\"],\"properties\":{\"jtype\":{\"type\":\"string\",\""
- "const\":\"afb-reply\"},\"request\":{\"type\":\"object\",\"required\":[\""
- "status\"],\"properties\":{\"status\":{\"type\":\"string\"},\"info\":{\"t"
- "ype\":\"string\"},\"token\":{\"type\":\"string\"},\"uuid\":{\"type\":\"s"
- "tring\"},\"reqid\":{\"type\":\"string\"}}},\"response\":{\"type\":\"obje"
- "ct\"}}},\"afb-event-v2\":{\"type\":\"object\",\"required\":[\"jtype\",\""
- "event\"],\"properties\":{\"jtype\":{\"type\":\"string\",\"const\":\"afb-"
- "event\"},\"event\":{\"type\":\"string\"},\"data\":{\"type\":\"object\"}}"
- "},\"endpoint_info\":{\"type\":\"object\",\"required\":[\"endpoint_id\",\""
- "type\",\"device_name\",\"device_uri\"],\"properties\":{\"endpoint_id\":{"
- "\"type\":\"int\"},\"type\":{\"type\":\"enum\"},\"device_name\":{\"type\""
- ":\"string\"},\"device_uri_type\":{\"type\":\"string\"}}},\"stream_info\""
- ":{\"type\":\"object\",\"required\":[\"stream_id\",\"state\",\"mute\",\"e"
- "ndpoint_info\"],\"properties\":{\"stream_id\":{\"type\":\"int\"},\"state"
- "\":{\"type\":\"int\"},\"mute\":{\"type\":\"int\"},\"device_uri\":{\"type"
- "\":\"string\"},\"$ref\":\"#/components/schemas/endpoint_info\"}}},\"x-pe"
- "rmissions\":{\"streamcontrol\":{\"permission\":\"urn:AGL:permission:audi"
- "o:public:streamcontrol\"},\"endpointcontrol\":{\"permission\":\"urn:AGL:"
- "permission:audio:public:endpointcontrol\"},\"audiostream\":{\"permission"
- "\":\"urn:AGL:permission:audio:public:audiostream\"},\"soundevent\":{\"pe"
- "rmission\":\"urn:AGL:permission:audio:public:soundevent\"}},\"responses\""
- ":{\"200\":{\"description\":\"A complex object array response\",\"content"
- "\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/af"
- "b-reply\"}}}},\"400\":{\"description\":\"Invalid arguments\"}}},\"paths\""
- ":{\"/get_sources\":{\"description\":\"Retrieve array of available audio "
- "sources\",\"get\":{\"parameters\":[{\"in\":\"query\",\"name\":\"audio_ro"
- "le\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\"responses\":"
- "{\"200\":{\"$ref\":\"#/components/responses/200\",\"response\":{\"descri"
- "ption\":\"Array of endpoint info structures\",\"type\":\"array\",\"items"
- "\":{\"$ref\":\"#/components/schemas/endpoint_info\"}}},\"400\":{\"$ref\""
- ":\"#/components/responses/400\"}}}},\"/get_sinks\":{\"description\":\"Re"
- "trieve array of available audio sinks\",\"get\":{\"parameters\":[{\"in\""
- ":\"query\",\"name\":\"audio_role\",\"required\":true,\"schema\":{\"type\""
- ":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses"
- "/200\",\"response\":{\"description\":\"Array of endpoint info structures"
- "\",\"type\":\"array\",\"items\":{\"$ref\":\"#/components/schemas/endpoin"
- "t_info\"}}},\"400\":{\"$ref\":\"#/components/responses/400\"}}}},\"/stre"
- "am_open\":{\"description\":\"Request opening a stream\",\"get\":{\"x-per"
- "missions\":{\"$ref\":\"#/components/x-permissions/audiostream\"},\"param"
- "eters\":[{\"in\":\"query\",\"name\":\"audio_role\",\"required\":true,\"s"
- "chema\":{\"type\":\"string\"}},{\"in\":\"query\",\"name\":\"endpoint_typ"
- "e\",\"required\":true,\"schema\":{\"type\":\"enum\"}},{\"in\":\"query\","
- "\"name\":\"endpoint_id\",\"required\":false,\"schema\":{\"type\":\"int\""
- "}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/200\",\"re"
- "sponse\":{\"description\":\"Stream information structure\",\"$ref\":\"#/"
- "components/schemas/stream_info\"}},\"400\":{\"$ref\":\"#/components/resp"
- "onses/400\"}}}},\"/stream_close\":{\"description\":\"Request closing a s"
- "tream\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permission"
- "s/audiostream\"},\"parameters\":[{\"in\":\"query\",\"name\":\"stream_id\""
- ",\"required\":true,\"schema\":{\"type\":\"int\"}}],\"responses\":{\"200\""
- ":{\"$ref\":\"#/components/responses/200\"},\"400\":{\"$ref\":\"#/compone"
- "nts/responses/400\"}}}},\"/set_stream_state\":{\"description\":\"Change "
- "stream active state\",\"get\":{\"x-permissions\":{\"$ref\":\"#/component"
- "s/x-permissions/streamcontrol\"},\"parameters\":[{\"in\":\"query\",\"nam"
- "e\":\"stream_id\",\"required\":true,\"schema\":{\"type\":\"int\"}},{\"in"
- "\":\"query\",\"name\":\"state\",\"required\":true,\"schema\":{\"type\":\""
- "int\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/200\""
- "},\"400\":{\"$ref\":\"#/components/responses/400\"}}}},\"/set_stream_mut"
- "e\":{\"description\":\"Change stream mute state\",\"get\":{\"x-permissio"
- "ns\":{\"$ref\":\"#/components/x-permissions/streamcontrol\"},\"parameter"
- "s\":[{\"in\":\"query\",\"name\":\"stream_id\",\"required\":true,\"schema"
- "\":{\"type\":\"int\"}},{\"in\":\"query\",\"name\":\"mute\",\"required\":"
- "true,\"schema\":{\"type\":\"int\"}}],\"responses\":{\"200\":{\"$ref\":\""
- "#/components/responses/200\"},\"400\":{\"$ref\":\"#/components/responses"
- "/400\"}}}},\"/get_stream_info\":{\"description\":\"Retrieve stream infor"
- "mation\",\"get\":{\"parameters\":[{\"in\":\"query\",\"name\":\"stream_id"
- "\",\"required\":true,\"schema\":{\"type\":\"int\"}}],\"responses\":{\"20"
- "0\":{\"$ref\":\"#/components/responses/200\",\"response\":{\"description"
- "\":\"Stream information structure\",\"$ref\":\"#/components/schemas/stre"
- "am_info\"}},\"400\":{\"$ref\":\"#/components/responses/400\"}}}},\"/set_"
- "volume\":{\"description\":\"Set volume on endpoint\",\"get\":{\"x-permis"
- "sions\":{\"$ref\":\"#/components/x-permissions/endpointcontrol\"},\"para"
- "meters\":[{\"in\":\"query\",\"name\":\"endpoint_type\",\"required\":true"
- ",\"schema\":{\"type\":\"enum\"}},{\"in\":\"query\",\"name\":\"endpoint_i"
- "d\",\"required\":true,\"schema\":{\"type\":\"int\"}},{\"in\":\"query\",\""
- "name\":\"volume\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\""
- "responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"},\"400\":{"
- "\"$ref\":\"#/components/responses/400\"}}}},\"/get_volume\":{\"descripti"
- "on\":\"Get endpoint volume\",\"get\":{\"parameters\":[{\"in\":\"query\","
- "\"name\":\"endpoint_type\",\"required\":true,\"schema\":{\"type\":\"enum"
- "\"}},{\"in\":\"query\",\"name\":\"endpoint_id\",\"required\":true,\"sche"
- "ma\":{\"type\":\"int\"}}],\"responses\":{\"200\":{\"$ref\":\"#/component"
- "s/responses/200\",\"response\":{\"description\":\"Endpoint volume value\""
- ",\"type\":\"double\"}},\"400\":{\"$ref\":\"#/components/responses/400\"}"
- "}}},\"/get_endpoint_info\":{\"description\":\"Retrieve endpoint informat"
- "ion including its properties\",\"get\":{\"parameters\":[{\"in\":\"query\""
- ",\"name\":\"endpoint_type\",\"required\":true,\"schema\":{\"type\":\"enu"
- "m\"}},{\"in\":\"query\",\"name\":\"endpoint_id\",\"required\":false,\"sc"
- "hema\":{\"type\":\"int\"}}],\"responses\":{\"200\":{\"$ref\":\"#/compone"
- "nts/responses/200\"},\"400\":{\"$ref\":\"#/components/responses/400\"}}}"
- "},\"/set_property\":{\"description\":\"Set endpoint property value\",\"g"
- "et\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/endpointc"
- "ontrol\"},\"parameters\":[{\"in\":\"query\",\"name\":\"endpoint_type\",\""
- "required\":true,\"schema\":{\"type\":\"enum\"}},{\"in\":\"query\",\"name"
- "\":\"endpoint_id\",\"required\":false,\"schema\":{\"type\":\"int\"}},{\""
- "in\":\"query\",\"name\":\"property_name\",\"required\":true,\"schema\":{"
- "\"type\":\"string\"}},{\"in\":\"query\",\"name\":\"value\",\"required\":"
- "true,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\""
- ":\"#/components/responses/200\"},\"400\":{\"$ref\":\"#/components/respon"
- "ses/400\"}}}},\"/get_property\":{\"description\":\"Get endpoint property"
- " value\",\"get\":{\"parameters\":[{\"in\":\"query\",\"name\":\"endpoint_"
- "type\",\"required\":true,\"schema\":{\"type\":\"enum\"}},{\"in\":\"query"
- "\",\"name\":\"endpoint_id\",\"required\":false,\"schema\":{\"type\":\"in"
- "t\"}},{\"in\":\"query\",\"name\":\"property_name\",\"required\":true,\"s"
- "chema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/com"
- "ponents/responses/200\",\"response\":{\"description\":\"Property value\""
- ",\"type\":\"double\"}},\"400\":{\"$ref\":\"#/components/responses/400\"}"
- "}}},\"/get_list_actions\":{\"description\":\"Retrieve a list of supporte"
- "d actions for a particular audio role\",\"get\":{\"parameters\":[{\"in\""
- ":\"query\",\"name\":\"audio_role\",\"required\":true,\"schema\":{\"type\""
- ":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses"
- "/200\"},\"400\":{\"$ref\":\"#/components/responses/400\"}}}},\"/post_act"
- "ion\":{\"description\":\"Post sound or audio device related action event"
- " (extendable mechanism)\",\"get\":{\"x-permissions\":{\"$ref\":\"#/compo"
- "nents/x-permissions/soundevent\"},\"parameters\":[{\"in\":\"query\",\"na"
- "me\":\"action_name\",\"required\":true,\"schema\":{\"type\":\"string\"}}"
- ",{\"in\":\"query\",\"name\":\"audio_role\",\"required\":true,\"schema\":"
- "{\"type\":\"string\"}},{\"in\":\"query\",\"name\":\"media_name\",\"requi"
- "red\":false,\"schema\":{\"type\":\"string\"}},{\"in\":\"query\",\"name\""
- ":\"action_context\",\"required\":false,\"schema\":{\"type\":\"object\"}}"
- "],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"},\"400"
- "\":{\"$ref\":\"#/components/responses/400\"}}}},\"/subscribe\":{\"descri"
- "ption\":\"Subscribe to audio high level events\",\"get\":{\"parameters\""
- ":[{\"in\":\"query\",\"name\":\"events\",\"required\":true,\"schema\":{\""
- "type\":\"array\",\"items\":{\"type\":\"string\"}}}],\"responses\":{\"200"
- "\":{\"$ref\":\"#/components/responses/200\"},\"400\":{\"$ref\":\"#/compo"
- "nents/responses/400\"}}}},\"/unsubscribe\":{\"description\":\"Unubscribe"
- " to audio high level events\",\"get\":{\"parameters\":[{\"in\":\"query\""
- ",\"name\":\"events\",\"required\":true,\"schema\":{\"type\":\"array\",\""
- "items\":{\"type\":\"string\"}}}],\"responses\":{\"200\":{\"$ref\":\"#/co"
- "mponents/responses/200\"},\"400\":{\"$ref\":\"#/components/responses/400"
- "\"}}}}}}"
-;
-
-static const struct afb_auth _afb_auths_v2_audiohl[] = {
- { .type = afb_auth_Permission, .text = "urn:AGL:permission:audio:public:audiostream" },
- { .type = afb_auth_Permission, .text = "urn:AGL:permission:audio:public:streamcontrol" },
- { .type = afb_auth_Permission, .text = "urn:AGL:permission:audio:public:endpointcontrol" },
- { .type = afb_auth_Permission, .text = "urn:AGL:permission:audio:public:soundevent" }
-};
-
- void audiohlapi_get_sources(struct afb_req req);
- void audiohlapi_get_sinks(struct afb_req req);
- void audiohlapi_stream_open(struct afb_req req);
- void audiohlapi_stream_close(struct afb_req req);
- void audiohlapi_set_stream_state(struct afb_req req);
- void audiohlapi_set_stream_mute(struct afb_req req);
- void audiohlapi_get_stream_info(struct afb_req req);
- void audiohlapi_set_volume(struct afb_req req);
- void audiohlapi_get_volume(struct afb_req req);
- void audiohlapi_get_endpoint_info(struct afb_req req);
- void audiohlapi_set_property(struct afb_req req);
- void audiohlapi_get_property(struct afb_req req);
- void audiohlapi_get_list_actions(struct afb_req req);
- void audiohlapi_post_action(struct afb_req req);
- void audiohlapi_subscribe(struct afb_req req);
- void audiohlapi_unsubscribe(struct afb_req req);
-
-static const struct afb_verb_v2 _afb_verbs_v2_audiohl[] = {
- {
- .verb = "get_sources",
- .callback = audiohlapi_get_sources,
- .auth = NULL,
- .info = "Retrieve array of available audio sources",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "get_sinks",
- .callback = audiohlapi_get_sinks,
- .auth = NULL,
- .info = "Retrieve array of available audio sinks",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "stream_open",
- .callback = audiohlapi_stream_open,
- .auth = &_afb_auths_v2_audiohl[0],
- .info = "Request opening a stream",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "stream_close",
- .callback = audiohlapi_stream_close,
- .auth = &_afb_auths_v2_audiohl[0],
- .info = "Request closing a stream",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "set_stream_state",
- .callback = audiohlapi_set_stream_state,
- .auth = &_afb_auths_v2_audiohl[1],
- .info = "Change stream active state",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "set_stream_mute",
- .callback = audiohlapi_set_stream_mute,
- .auth = &_afb_auths_v2_audiohl[1],
- .info = "Change stream mute state",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "get_stream_info",
- .callback = audiohlapi_get_stream_info,
- .auth = NULL,
- .info = "Retrieve stream information",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "set_volume",
- .callback = audiohlapi_set_volume,
- .auth = &_afb_auths_v2_audiohl[2],
- .info = "Set volume on endpoint",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "get_volume",
- .callback = audiohlapi_get_volume,
- .auth = NULL,
- .info = "Get endpoint volume",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "get_endpoint_info",
- .callback = audiohlapi_get_endpoint_info,
- .auth = NULL,
- .info = "Retrieve endpoint information including its properties",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "set_property",
- .callback = audiohlapi_set_property,
- .auth = &_afb_auths_v2_audiohl[2],
- .info = "Set endpoint property value",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "get_property",
- .callback = audiohlapi_get_property,
- .auth = NULL,
- .info = "Get endpoint property value",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "get_list_actions",
- .callback = audiohlapi_get_list_actions,
- .auth = NULL,
- .info = "Retrieve a list of supported actions for a particular audio role",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "post_action",
- .callback = audiohlapi_post_action,
- .auth = &_afb_auths_v2_audiohl[3],
- .info = "Post sound or audio device related action event (extendable mechanism)",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "subscribe",
- .callback = audiohlapi_subscribe,
- .auth = NULL,
- .info = "Subscribe to audio high level events",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "unsubscribe",
- .callback = audiohlapi_unsubscribe,
- .auth = NULL,
- .info = "Unubscribe to audio high level events",
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = NULL,
- .callback = NULL,
- .auth = NULL,
- .info = NULL,
- .session = 0
- }
-};
-
-const struct afb_binding_v2 afbBindingV2 = {
- .api = "audiohl",
- .specification = _afb_description_v2_audiohl,
- .info = "Audio high level API for AGL applications",
- .verbs = _afb_verbs_v2_audiohl,
- .preinit = NULL,
- .init = AhlBindingInit,
- .onevent = AhlOnEvent,
- .noconcurrency = 0
-};
-
diff --git a/src/ahl-apidef.json b/src/ahl-apidef.json
deleted file mode 100644
index 3ab6f4a..0000000
--- a/src/ahl-apidef.json
+++ /dev/null
@@ -1,565 +0,0 @@
-{
- "openapi": "3.0.0",
- "info": {
- "description": "Audio high level API for AGL applications",
- "title": "audiohighlevel",
- "version": "1.0",
- "x-binding-c-generator": {
- "api": "audiohl",
- "version": 2,
- "prefix": "audiohlapi_",
- "postfix": "",
- "start": null,
- "onevent": "AhlOnEvent",
- "init": "AhlBindingInit",
- "scope": "",
- "private": false
- }
- },
- "servers": [
- {
- "url": "ws://{host}:{port}/api/audiohl",
- "description": "Audio high level API for AGL applications.",
- "variables": {
- "host": {
- "default": "localhost"
- },
- "port": {
- "default": "1234"
- }
- },
- "x-afb-events": [
- {
- "$ref": "#/components/schemas/afb-event"
- }
- ]
- }
- ],
- "components": {
- "schemas": {
- "afb-reply": {
- "$ref": "#/components/schemas/afb-reply-v2"
- },
- "afb-event": {
- "$ref": "#/components/schemas/afb-event-v2"
- },
- "afb-reply-v2": {
- "title": "Generic response.",
- "type": "object",
- "required": ["jtype", "request"],
- "properties": {
- "jtype": {
- "type": "string",
- "const": "afb-reply"
- },
- "request": {
- "type": "object",
- "required": ["status"],
- "properties": {
- "status": {
- "type": "string"
- },
- "info": {
- "type": "string"
- },
- "token": {
- "type": "string"
- },
- "uuid": {
- "type": "string"
- },
- "reqid": {
- "type": "string"
- }
- }
- },
- "response": {
- "type": "object"
- }
- }
- },
- "afb-event-v2": {
- "type": "object",
- "required": ["jtype", "event"],
- "properties": {
- "jtype": {
- "type": "string",
- "const": "afb-event"
- },
- "event": {
- "type": "string"
- },
- "data": {
- "type": "object"
- }
- }
- },
- "endpoint_info": {
- "type": "object",
- "required": [ "endpoint_id", "type", "device_name", "device_uri" ],
- "properties": {
- "endpoint_id": { "type": "int" },
- "type": { "type": "enum" },
- "device_name": { "type": "string" },
- "device_uri_type": { "type": "string" }
- }
- },
- "stream_info": {
- "type": "object",
- "required": [ "stream_id", "state", "mute", "endpoint_info" ],
- "properties": {
- "stream_id": { "type": "int" },
- "state": { "type": "int" },
- "mute": { "type": "int" },
- "device_uri": { "type": "string" },
- "$ref": "#/components/schemas/endpoint_info"
- }
- }
- },
- "x-permissions": {
- "streamcontrol": { "permission": "urn:AGL:permission:audio:public:streamcontrol"},
- "endpointcontrol": { "permission": "urn:AGL:permission:audio:public:endpointcontrol"},
- "audiostream": { "permission": "urn:AGL:permission:audio:public:audiostream"},
- "soundevent": {"permission": "urn:AGL:permission:audio:public:soundevent"}
- },
- "responses": {
- "200": {
- "description": "A complex object array response",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/afb-reply"
- }
- }
- }
- },
- "400": { "description": "Invalid arguments" }
- }
- },
- "paths": {
- "/get_sources": {
- "description": "Retrieve array of available audio sources",
- "get": {
- "parameters": [
- {
- "in": "query",
- "name": "audio_role",
- "required": true,
- "schema": { "type": "string" }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200",
- "response": {
- "description": "Array of endpoint info structures",
- "type": "array",
- "items": { "$ref": "#/components/schemas/endpoint_info"}
- }
- },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/get_sinks": {
- "description": "Retrieve array of available audio sinks",
- "get": {
- "parameters": [
- {
- "in": "query",
- "name": "audio_role",
- "required": true,
- "schema": { "type": "string" }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200",
- "response": {
- "description": "Array of endpoint info structures",
- "type": "array",
- "items": { "$ref": "#/components/schemas/endpoint_info"}
- }
- },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/stream_open": {
- "description": "Request opening a stream",
- "get": {
- "x-permissions": { "$ref": "#/components/x-permissions/audiostream" },
- "parameters": [
- {
- "in": "query",
- "name": "audio_role",
- "required": true,
- "schema": { "type": "string" }
- },
- {
- "in": "query",
- "name": "endpoint_type",
- "required": true,
- "schema": { "type": "enum" }
- },
- {
- "in": "query",
- "name": "endpoint_id",
- "required": false,
- "schema": { "type": "int" }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200",
- "response": {
- "description": "Stream information structure",
- "$ref": "#/components/schemas/stream_info"
- }
- },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/stream_close": {
- "description": "Request closing a stream",
- "get": {
- "x-permissions": { "$ref": "#/components/x-permissions/audiostream" },
- "parameters": [
- {
- "in": "query",
- "name": "stream_id",
- "required": true,
- "schema": { "type": "int" }
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/set_stream_state": {
- "description": "Change stream active state",
- "get": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/streamcontrol"
- },
- "parameters": [
- {
- "in": "query",
- "name": "stream_id",
- "required": true,
- "schema": {"type": "int"}
- },
- {
- "in": "query",
- "name": "state",
- "required": true,
- "schema": {"type": "int"}
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/set_stream_mute": {
- "description": "Change stream mute state",
- "get": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/streamcontrol"
- },
- "parameters": [
- {
- "in": "query",
- "name": "stream_id",
- "required": true,
- "schema": {"type": "int"}
- },
- {
- "in": "query",
- "name": "mute",
- "required": true,
- "schema": {"type": "int"}
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/get_stream_info": {
- "description": "Retrieve stream information",
- "get": {
- "parameters": [
- {
- "in": "query",
- "name": "stream_id",
- "required": true,
- "schema": {"type": "int"}
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200",
- "response": {
- "description": "Stream information structure",
- "$ref": "#/components/schemas/stream_info"
- }
- },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/set_volume": {
- "description": "Set volume on endpoint",
- "get": {
- "x-permissions": { "$ref": "#/components/x-permissions/endpointcontrol" },
- "parameters": [
- {
- "in": "query",
- "name": "endpoint_type",
- "required": true,
- "schema": { "type": "enum" }
- },
- {
- "in": "query",
- "name": "endpoint_id",
- "required": true,
- "schema": { "type": "int" }
- },
- {
- "in": "query",
- "name": "volume",
- "required": true,
- "schema": { "type": "string" }
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/get_volume": {
- "description": "Get endpoint volume",
- "get": {
- "parameters": [
- {
- "in": "query",
- "name": "endpoint_type",
- "required": true,
- "schema": { "type": "enum" }
- },
- {
- "in": "query",
- "name": "endpoint_id",
- "required": true,
- "schema": { "type": "int" }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200",
- "response": {
- "description": "Endpoint volume value",
- "type": "double"
- }
- },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/get_endpoint_info": {
- "description": "Retrieve endpoint information including its properties",
- "get": {
- "parameters": [
- {
- "in": "query",
- "name": "endpoint_type",
- "required": true,
- "schema": { "type": "enum" }
- },
- {
- "in": "query",
- "name": "endpoint_id",
- "required": false,
- "schema": { "type": "int" }
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/set_property": {
- "description": "Set endpoint property value",
- "get": {
- "x-permissions": { "$ref": "#/components/x-permissions/endpointcontrol" },
- "parameters": [
- {
- "in": "query",
- "name": "endpoint_type",
- "required": true,
- "schema": { "type": "enum" }
- },
- {
- "in": "query",
- "name": "endpoint_id",
- "required": false,
- "schema": { "type": "int" }
- },
- {
- "in": "query",
- "name": "property_name",
- "required": true,
- "schema": { "type": "string" }
- },
- {
- "in": "query",
- "name": "value",
- "required": true,
- "schema": { "type": "string" }
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/get_property": {
- "description": "Get endpoint property value",
- "get": {
- "parameters": [
- {
- "in": "query",
- "name": "endpoint_type",
- "required": true,
- "schema": { "type": "enum" }
- },
- {
- "in": "query",
- "name": "endpoint_id",
- "required": false,
- "schema": { "type": "int" }
- },
- {
- "in": "query",
- "name": "property_name",
- "required": true,
- "schema": { "type": "string" }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200",
- "response": {
- "description": "Property value",
- "type": "double"
- }
- },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/get_list_actions": {
- "description": "Retrieve a list of supported actions for a particular audio role",
- "get": {
- "parameters": [
- {
- "in": "query",
- "name": "audio_role",
- "required": true,
- "schema": { "type": "string" }
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/post_action": {
- "description": "Post sound or audio device related action event (extendable mechanism)",
- "get": {
- "x-permissions": { "$ref": "#/components/x-permissions/soundevent" },
- "parameters": [
- {
- "in": "query",
- "name": "action_name",
- "required": true,
- "schema": { "type": "string" }
- },
- {
- "in": "query",
- "name": "audio_role",
- "required": true,
- "schema": { "type": "string" }
- },
- {
- "in": "query",
- "name": "media_name",
- "required": false,
- "schema": { "type": "string"}
- },
- {
- "in": "query",
- "name": "action_context",
- "required": false,
- "schema": { "type": "object" }
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/subscribe": {
- "description": "Subscribe to audio high level events",
- "get": {
- "parameters": [
- {
- "in": "query",
- "name": "events",
- "required": true,
- "schema": { "type": "array",
- "items": { "type": "string" }
- }
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- },
- "/unsubscribe": {
- "description": "Unubscribe to audio high level events",
- "get": {
- "parameters": [
- {
- "in": "query",
- "name": "events",
- "required": true,
- "schema": {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- }
- ],
- "responses": {
- "200": { "$ref": "#/components/responses/200" },
- "400": { "$ref": "#/components/responses/400" }
- }
- }
- }
- }
-}
diff --git a/src/ahl-binding.c b/src/ahl-binding.c
deleted file mode 100644
index 264930f..0000000
--- a/src/ahl-binding.c
+++ /dev/null
@@ -1,1577 +0,0 @@
-/*
- * 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.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-
-#include "ahl-binding.h"
-#include "ahl-apidef.h" // Generated from JSON OpenAPI
-#include "wrap-json.h"
-#include "ahl-policy.h"
-#include "ahl-policy-utils.h"
-
-// Global high-level binding context
-AHLCtxT g_AHLCtx;
-
-// TODO: Helpers that could be common
-static EndpointTypeT EndpointTypeToEnum(char * in_pEndpointTypeStr)
-{
- if (in_pEndpointTypeStr == NULL) {
- return ENDPOINTTYPE_MAXVALUE;
- }
- else if (strcasecmp(in_pEndpointTypeStr,AHL_ENDPOINTTYPE_SOURCE)==0) {
- return ENDPOINTTYPE_SOURCE;
- }
- else if (strcasecmp(in_pEndpointTypeStr,AHL_ENDPOINTTYPE_SINK)==0) {
- return ENDPOINTTYPE_SINK;
- }
- else
- return ENDPOINTTYPE_MAXVALUE;
-}
-
-static StreamStateT StreamStateToEnum(char * in_pStreamStateStr)
-{
- if (in_pStreamStateStr == NULL) {
- return STREAM_STATE_MAXVALUE;
- }
- else if (strcasecmp(in_pStreamStateStr,AHL_STREAM_STATE_IDLE)==0) {
- return STREAM_STATE_IDLE;
- }
- else if (strcasecmp(in_pStreamStateStr,AHL_STREAM_STATE_RUNNING)==0) {
- return STREAM_STATE_RUNNING;
- }
- else if (strcasecmp(in_pStreamStateStr,AHL_STREAM_STATE_PAUSED)==0) {
- return STREAM_STATE_PAUSED;
- }
- else
- return STREAM_STATE_MAXVALUE;
-}
-
-static StreamMuteT StreamMuteToEnum(char * in_pStreamMuteStr)
-{
- if (in_pStreamMuteStr == NULL) {
- return STREAM_MUTE_MAXVALUE;
- }
- else if (strcasecmp(in_pStreamMuteStr,AHL_STREAM_UNMUTED)==0) {
- return STREAM_UNMUTED;
- }
- else if (strcasecmp(in_pStreamMuteStr,AHL_STREAM_MUTED)==0) {
- return STREAM_MUTED;
- }
- else
- return STREAM_MUTE_MAXVALUE;
-}
-
-static char * DeviceURITypeEnumToStr(DeviceURITypeT in_eDeviceURIType) {
- switch(in_eDeviceURIType) {
- case DEVICEURITYPE_ALSA_HW: // Alsa hardware device URI
- return AHL_DEVICEURITYPE_ALSA_HW;
- case DEVICEURITYPE_ALSA_DMIX: // Alsa Dmix device URI (only for playback devices)
- return AHL_DEVICEURITYPE_ALSA_DMIX;
- case DEVICEURITYPE_ALSA_DSNOOP: // Alsa DSnoop device URI (only for capture devices)
- return AHL_DEVICEURITYPE_ALSA_DSNOOP;
- case DEVICEURITYPE_ALSA_SOFTVOL: // Alsa softvol device URI
- return AHL_DEVICEURITYPE_ALSA_SOFTVOL;
- case DEVICEURITYPE_ALSA_PLUG: // Alsa plug device URI
- return AHL_DEVICEURITYPE_ALSA_PLUG;
- case DEVICEURITYPE_ALSA_OTHER: // Alsa domain URI device of unspecified type
- return AHL_DEVICEURITYPE_ALSA_OTHER;
- case DEVICEURITYPE_NOT_ALSA: // Unknown (not ALSA domain)
- return AHL_DEVICEURITYPE_NOT_ALSA;
- default:
- return "Unknown";
- }
-}
-
-static char * StreamStateEnumToStr(StreamStateT in_eStreamState) {
- switch(in_eStreamState) {
- case STREAM_STATE_IDLE:
- return AHL_STREAM_STATE_IDLE;
- case STREAM_STATE_RUNNING:
- return AHL_STREAM_STATE_RUNNING;
- case STREAM_STATE_PAUSED:
- return AHL_STREAM_STATE_PAUSED;
- default:
- return "Unknown";
- }
-}
-
-static char * StreamMuteEnumToStr(StreamMuteT in_eStreamMute) {
- switch(in_eStreamMute) {
- case STREAM_UNMUTED:
- return AHL_STREAM_UNMUTED;
- case STREAM_MUTED:
- return AHL_STREAM_MUTED;
- default:
- return "Unknown";
- }
-}
-
-static void AudioFormatStructToJSON(json_object **audioFormatJ, AudioFormatT * pAudioFormat)
-{
- wrap_json_pack(audioFormatJ, "{s:i,s:i,s:i}",
- "sample_rate", pAudioFormat->sampleRate,
- "num_channels", pAudioFormat->numChannels,
- "sample_type", pAudioFormat->sampleType);
-}
-
-// Package only information that can useful to application clients when selecting endpoint
-static void EndpointInfoStructToJSON(json_object **endpointInfoJ, EndpointInfoT * pEndpointInfo)
-{
- json_object *formatInfoJ = NULL;
- wrap_json_pack(endpointInfoJ, "{s:i,s:s,s:s,s:s,s:s,s:s,s:s}",
- "endpoint_id", pEndpointInfo->endpointID,
- "endpoint_type", (pEndpointInfo->type == ENDPOINTTYPE_SOURCE) ? AHL_ENDPOINTTYPE_SOURCE : AHL_ENDPOINTTYPE_SINK,
- "device_name", pEndpointInfo->gsDeviceName,
- "display_name", pEndpointInfo->gsDisplayName,
- "audio_role", pEndpointInfo->pRoleName,
- "device_domain",pEndpointInfo->gsDeviceDomain,
- "device_uri_type", DeviceURITypeEnumToStr(pEndpointInfo->deviceURIType));
- AudioFormatStructToJSON(&formatInfoJ,&pEndpointInfo->format);
- json_object_object_add(*endpointInfoJ,"format",formatInfoJ);
-
- // Properties
- if (pEndpointInfo->pPropTable) {
- json_object *pPropTableJ = json_object_new_array();
-
- GHashTableIter iter;
- gpointer key, value;
- g_hash_table_iter_init (&iter, pEndpointInfo->pPropTable);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- if((key!=NULL) && (value!=NULL))
- {
- json_object *pPropertyJ = NULL;
- json_object_get((json_object*)value); // Don't let the framework free our object when the request is done
- wrap_json_pack(&pPropertyJ, "{s:s,s:o}","property_name", (char*)key, "property_value", (json_object*)value);
- json_object_array_add(pPropTableJ, pPropertyJ);
- }
- }
- json_object_object_add(*endpointInfoJ,"properties",pPropTableJ);
- }
-}
-
-// Package only information that can useful to application clients when opening a stream
-static void StreamInfoStructToJSON(json_object **streamInfoJ, StreamInfoT * pStreamInfo)
-{
- json_object *endpointInfoJ = NULL;
- EndpointInfoStructToJSON(&endpointInfoJ,pStreamInfo->pEndpointInfo);
- wrap_json_pack(streamInfoJ, "{s:i,s:s,s:s,s:s}",
- "stream_id", pStreamInfo->streamID,
- "state", StreamStateEnumToStr(pStreamInfo->streamState),
- "mute", StreamMuteEnumToStr(pStreamInfo->streamMute),
- "device_uri",pStreamInfo->pEndpointInfo->gsDeviceURI); // Need to open a stream to have access to the device URI
- json_object_object_add(*streamInfoJ,"endpoint_info",endpointInfoJ);
-}
-
-static streamID_t CreateNewStreamID()
-{
- streamID_t newID = g_AHLCtx.nextStreamID;
- g_AHLCtx.nextStreamID++;
- return newID;
-}
-
-static EndpointInfoT * GetEndpointInfoWithRole(endpointID_t in_endpointID, EndpointTypeT in_endpointType, RoleInfoT * in_pRole)
-{
- EndpointInfoT * pEndpointInfo = NULL;
- GPtrArray * pDeviceArray = NULL;
- if (in_endpointType == ENDPOINTTYPE_SOURCE){
- pDeviceArray = in_pRole->pSourceEndpoints;
- }
- else {
- pDeviceArray = in_pRole->pSinkEndpoints;
- }
- g_assert_nonnull(pDeviceArray);
-
- for (int j = 0; j < pDeviceArray->len; j++) {
- EndpointInfoT * pCurEndpointInfo = g_ptr_array_index(pDeviceArray,j);
- g_assert_nonnull(pCurEndpointInfo);
- if (pCurEndpointInfo->endpointID == in_endpointID) {
- pEndpointInfo = pCurEndpointInfo;
- break;
- }
- }
-
- return pEndpointInfo;
-}
-
-static int ReplaceEndpointInfoWithRole(endpointID_t in_endpointID, EndpointTypeT in_endpointType, RoleInfoT * in_pRole, EndpointInfoT * in_pNewEndpoint)
-{
- GPtrArray * pDeviceArray = NULL;
- if (in_endpointType == ENDPOINTTYPE_SOURCE){
- pDeviceArray = in_pRole->pSourceEndpoints;
- }
- else {
- pDeviceArray = in_pRole->pSinkEndpoints;
- }
- g_assert_nonnull(pDeviceArray);
-
- for (int j = 0; j < pDeviceArray->len; j++) {
- EndpointInfoT * pCurEndpointInfo = g_ptr_array_index(pDeviceArray,j);
- g_assert_nonnull(pCurEndpointInfo);
- if (pCurEndpointInfo->endpointID == in_endpointID) {
- g_ptr_array_insert(pDeviceArray,j,in_pNewEndpoint);
- g_ptr_array_remove_index(pDeviceArray,j+1);
- TermEndpointInfo(pCurEndpointInfo);
- // GLib automatically frees item upon array removal
- return AHL_SUCCESS;
- }
- }
-
- return AHL_FAIL;
-}
-
-static EndpointInfoT * GetEndpointInfo(endpointID_t in_endpointID, EndpointTypeT in_endpointType)
-{
- EndpointInfoT * pEndpointInfo = NULL;
-
- GHashTableIter iter;
- gpointer key, value;
- g_hash_table_iter_init (&iter, g_AHLCtx.policyCtx.pRoleInfo);
- while (pEndpointInfo == NULL && g_hash_table_iter_next (&iter, &key, &value))
- {
- RoleInfoT * pRoleInfo = (RoleInfoT*)value;
- pEndpointInfo = GetEndpointInfoWithRole(in_endpointID,in_endpointType,pRoleInfo);
- }
-
- return pEndpointInfo;
-}
-
-static StreamInfoT * GetStream(streamID_t in_streamID)
-{
- if (g_AHLCtx.policyCtx.pStreams == NULL)
- return NULL;
-
- return g_hash_table_lookup(g_AHLCtx.policyCtx.pStreams,GINT_TO_POINTER(&in_streamID));
-}
-
-static RoleInfoT * GetRole(char * in_pAudioRoleName)
-{
- if (g_AHLCtx.policyCtx.pRoleInfo == NULL)
- return NULL;
-
- return g_hash_table_lookup(g_AHLCtx.policyCtx.pRoleInfo,in_pAudioRoleName);
-}
-
-static AHLClientCtxT * AllocateClientContext()
-{
- AHLClientCtxT * pClientCtx = malloc(sizeof(AHLClientCtxT));
- pClientCtx->pStreamAccessList = g_array_new(FALSE, TRUE, sizeof(streamID_t));
- return pClientCtx;
-}
-
-static void TerminateClientContext(void * ptr)
-{
- AHLClientCtxT * pClientCtx = (AHLClientCtxT *) ptr;
- if (pClientCtx != NULL) {
-
- // Avoid having policy in bad state if client loses WS connection (e.g. app termination without close stream)
- // Force close streams in those cases.
-
- if (pClientCtx->pStreamAccessList != NULL) {
-#ifndef AHL_DISCONNECT_POLICY
- for (int i = 0; i < pClientCtx->pStreamAccessList->len; i++)
- {
- streamID_t streamID = g_array_index(pClientCtx->pStreamAccessList,streamID_t,i);
- // Call policy to verify whether creating a new audio stream is allowed in current context and possibly take other actions
- StreamInfoT * pStreamInfo = GetStream(streamID);
- if (pStreamInfo == NULL) {
- AFB_ERROR("Specified stream not currently active stream_id -> %d",streamID);
- return;
- }
-
- json_object *pPolicyStreamJ = NULL;
- int err = PolicyStreamStructToJSON(pStreamInfo, &pPolicyStreamJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- AFB_ERROR("Audio policy violation, Unable to get JSON object for Policy_CloseStream");
- return;
- }
- Policy_CloseStream(pPolicyStreamJ);
- }
-#endif
- g_array_free( pClientCtx->pStreamAccessList, TRUE);
- pClientCtx->pStreamAccessList = NULL;
- }
- free(pClientCtx);
- }
-}
-
-static int CheckStreamAccessControl(AHLClientCtxT * pClientCtx, streamID_t streamID)
-{
- int iAccessControl = AHL_ACCESS_CONTROL_DENIED;
- if (pClientCtx && pClientCtx->pStreamAccessList) {
- for (int i = 0; i < pClientCtx->pStreamAccessList->len ; i++) {
- streamID_t iID = g_array_index(pClientCtx->pStreamAccessList,streamID_t,i);
- if (iID == streamID) {
- iAccessControl = AHL_ACCESS_CONTROL_GRANTED;
- }
- }
- }
- return iAccessControl;
-}
-
-static int CreateEvents()
-{
- int err = 0;
-
- g_AHLCtx.policyCtx.propertyEvent = afb_daemon_make_event(AHL_ENDPOINT_PROPERTY_EVENT);
- err = !afb_event_is_valid(g_AHLCtx.policyCtx.propertyEvent);
- if (err) {
- AFB_ERROR("Could not create endpoint property change event");
- return err;
- }
-
- g_AHLCtx.policyCtx.volumeEvent = afb_daemon_make_event(AHL_ENDPOINT_VOLUME_EVENT);
- err = !afb_event_is_valid(g_AHLCtx.policyCtx.volumeEvent);
- if (err) {
- AFB_ERROR("Could not create endpoint volume change event");
- return err;
- }
-
- g_AHLCtx.policyCtx.postActionEvent = afb_daemon_make_event(AHL_POST_ACTION_EVENT);
- err = !afb_event_is_valid(g_AHLCtx.policyCtx.postActionEvent);
- if (err) {
- AFB_ERROR("Could not create post action event call event");
- return err;
- }
-
- return err;
-}
-
-static void AhlBindingTerm()
-{
-#ifndef AHL_DISCONNECT_POLICY
- // Policy termination
- Policy_Term();
-#endif
-
- // Roles
- if (g_AHLCtx.policyCtx.pRoleInfo != NULL) {
- GHashTableIter iter;
- gpointer key, value;
- g_hash_table_iter_init(&iter, g_AHLCtx.policyCtx.pRoleInfo);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- RoleInfoT * pRole = (RoleInfoT *)value;
- if (pRole)
- {
- if(pRole->pRoleName) {
- g_free(pRole->pRoleName);
- pRole->pRoleName = NULL;
- }
- // Actions
- if (pRole->pActionList) {
- for (int i = 0; i < pRole->pActionList->len; i++)
- {
- g_ptr_array_remove_index( pRole->pActionList, i ); // Free char * is called by GLib
- }
- }
- // Source endpoints
- if (pRole->pSourceEndpoints) {
- for (int i = 0; i < pRole->pSourceEndpoints->len; i++)
- {
- EndpointInfoT * pEndpoint = g_ptr_array_remove_index( pRole->pSourceEndpoints, i ); // Free endpoint * is called by GLib
- if (pEndpoint) {
- TermEndpointInfo(pEndpoint);
- }
- }
- }
- // Sink endpoints
- if (pRole->pSinkEndpoints) {
- for (int i = 0; i < pRole->pSinkEndpoints->len; i++)
- {
- EndpointInfoT * pEndpoint = g_ptr_array_remove_index( pRole->pSinkEndpoints, i ); // Free endpoint * is called by GLib
- if (pEndpoint) {
- TermEndpointInfo(pEndpoint);
- }
- }
- }
- free(pRole);
- }
- }
- g_hash_table_remove_all(g_AHLCtx.policyCtx.pRoleInfo);
- g_hash_table_destroy(g_AHLCtx.policyCtx.pRoleInfo);
- g_AHLCtx.policyCtx.pRoleInfo = NULL;
- }
-
- if (g_AHLCtx.policyCtx.pStreams) {
- GHashTableIter iter;
- gpointer key, value;
- g_hash_table_iter_init (&iter, g_AHLCtx.policyCtx.pStreams);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- if (value)
- free(value);
- }
- g_hash_table_remove_all(g_AHLCtx.policyCtx.pStreams);
- g_hash_table_destroy(g_AHLCtx.policyCtx.pStreams);
- g_AHLCtx.policyCtx.pStreams = NULL;
- }
-
- if (g_AHLCtx.policyCtx.pHALList) {
- g_ptr_array_free(g_AHLCtx.policyCtx.pHALList,TRUE);
- g_AHLCtx.policyCtx.pHALList = NULL;
- }
-
- AFB_INFO("Audio high-level binding termination success");
-}
-
-// Binding initialization
-PUBLIC int AhlBindingInit()
-{
- int err = 0;
-
- memset(&g_AHLCtx,0,sizeof(g_AHLCtx));
-
- // Register exit function
- atexit(AhlBindingTerm);
-
- //Create AGL Events
- err=CreateEvents();
- if(err)
- {
- //Error messages already reported inside CreateEvents
- return err;
- }
-
- // Parse high-level binding JSON configuration file (will build device lists)
- err = ParseHLBConfig();
- if(err)
- {
- //Error messages already reported inside ParseHLBConfig
- return err;
- }
-
-#ifndef AHL_DISCONNECT_POLICY
- // Policy initialization
- err = Policy_Init();
- if(err == AHL_POLICY_REJECT)
- {
- //Error messages already reported inside PolicyInit
- return err;
- }
-
- // for all audio Roles
- GHashTableIter iter;
- gpointer key, value;
-
- g_hash_table_iter_init (&iter, g_AHLCtx.policyCtx.pRoleInfo);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- RoleInfoT * pRoleInfo = (RoleInfoT*)value;
- if (pRoleInfo->pSourceEndpoints){
- // for all source endpoints
- for (int j = 0; j < pRoleInfo->pSourceEndpoints->len; j++) {
- EndpointInfoT * pCurEndpointInfo = g_ptr_array_index(pRoleInfo->pSourceEndpoints,j);
- g_assert_nonnull(pCurEndpointInfo);
- json_object *pPolicyEndpointJ = NULL;
- err = PolicyEndpointStructToJSON(pCurEndpointInfo, &pPolicyEndpointJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- AFB_ERROR("Unable to Create Endpoint Json object error:%s ",wrap_json_get_error_string(err));
- return err;
- }
- else
- {
- err = Policy_Endpoint_Init(pPolicyEndpointJ);
- if (err == AHL_POLICY_REJECT) {
- AFB_ERROR("Policy endpoint properties initalization failed for endpoint_id :%d type:%d",pCurEndpointInfo->endpointID, pCurEndpointInfo->type);
- }
- //free pPolicyEndpointJ
- json_object_put(pPolicyEndpointJ);
- }
- }
- }
- if (pRoleInfo->pSinkEndpoints){
- // for all sink endpoints
- for (int j = 0; j < pRoleInfo->pSinkEndpoints->len; j++) {
- EndpointInfoT * pCurEndpointInfo = g_ptr_array_index(pRoleInfo->pSinkEndpoints,j);
- g_assert_nonnull(pCurEndpointInfo);
- json_object *pPolicyEndpointJ = NULL;
- err = PolicyEndpointStructToJSON(pCurEndpointInfo, &pPolicyEndpointJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- AFB_ERROR("Unable to Create Endpoint Json object error:%s ",wrap_json_get_error_string(err));
- return err;
- }
- else
- {
- err = Policy_Endpoint_Init(pPolicyEndpointJ);
- if (err== AHL_POLICY_REJECT) {
- AFB_ERROR("Policy endpoint properties initalization failed for endpoint_id :%d type:%d",pCurEndpointInfo->endpointID, pCurEndpointInfo->type);
- }
- //free pPolicyEndpointJ
- json_object_put(pPolicyEndpointJ);
- }
-
- }
- }
- }
-#endif
-
- // Initialize list of active streams
- g_AHLCtx.policyCtx.pStreams = g_hash_table_new(g_int_hash, g_int_equal);
- if(g_AHLCtx.policyCtx.pStreams == NULL)
- {
- AFB_ERROR("Unable to create Active Stream List");
- return err;
- }
-
- // TODO: Use AGL persistence framework to retrieve and set initial volumes/properties
-
- AFB_DEBUG("Audio high-level Binding success");
- return err;
-}
-
-PUBLIC void AhlOnEvent(const char *evtname, json_object *eventJ)
-{
- AFB_DEBUG("AHL received event %s", evtname);
-
- // TODO: Handle event from the policy to update internal information (currently not possible since within the same binding)
-
-#ifndef AHL_DISCONNECT_POLICY
- // Temp: currently forward to policy to handle events (they will be received directly when disconnected into separate binding)
- Policy_OnEvent(evtname, eventJ);
-#endif
-}
-
-PUBLIC void audiohlapi_get_sources(struct afb_req req)
-{
- json_object *devicesJ = NULL;
- json_object *deviceJ = NULL;
- json_object *queryJ = NULL;
- char * audioRole = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s}", "audio_role", &audioRole);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
-
- AFB_DEBUG("Filtering devices according to specified audio role=%s", audioRole);
-
- RoleInfoT * pRole = GetRole(audioRole);
- if ( pRole == NULL )
- {
- afb_req_fail_f(req, "Invalid arguments", "Requested audio role does not exist in current configuration -> %s", json_object_get_string(queryJ));
- return;
- }
- else
- {
- devicesJ = json_object_new_array();
- GPtrArray * pDeviceArray = pRole->pSourceEndpoints;
- if (pDeviceArray) {
- int iNumberDevices = pDeviceArray->len;
- for ( int j = 0 ; j < iNumberDevices; j++)
- {
- EndpointInfoT * pEndpointInfo = g_ptr_array_index(pDeviceArray,j);
- if (pEndpointInfo) {
- EndpointInfoStructToJSON(&deviceJ, pEndpointInfo);
- json_object_array_add(devicesJ, deviceJ);
- }
- }
- }
- }
-
- afb_req_success(req, devicesJ, "List of sources");
-}
-
-PUBLIC void audiohlapi_get_sinks(struct afb_req req)
-{
- json_object *devicesJ = NULL;
- json_object *deviceJ = NULL;
- json_object *queryJ = NULL;
- char * audioRole = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s}", "audio_role", &audioRole);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
-
- AFB_DEBUG("Filtering devices according to specified audio role=%s", audioRole);
-
- RoleInfoT * pRole = GetRole(audioRole);
- if ( pRole == NULL )
- {
- afb_req_fail_f(req, "Invalid arguments", "Requested audio role does not exist in current configuration -> %s", json_object_get_string(queryJ));
- return;
- }
- else
- {
- devicesJ = json_object_new_array();
- GPtrArray * pDeviceArray = pRole->pSinkEndpoints;
- if (pDeviceArray) {
- int iNumberDevices = pDeviceArray->len;
- for ( int j = 0 ; j < iNumberDevices; j++)
- {
- EndpointInfoT * pEndpointInfo = g_ptr_array_index(pDeviceArray,j);
- EndpointInfoStructToJSON(&deviceJ, pEndpointInfo);
- json_object_array_add(devicesJ, deviceJ);
- }
- }
- }
-
- afb_req_success(req, devicesJ, "List of sinks");
-}
-
-PUBLIC void audiohlapi_stream_open(struct afb_req req)
-{
- json_object *streamInfoJ = NULL;
- StreamInfoT * pStreamInfo = NULL;
- json_object *queryJ = NULL;
- char * audioRole = NULL;
- char * endpointTypeStr = NULL;
- EndpointTypeT endpointType = ENDPOINTTYPE_MAXVALUE;
- endpointID_t endpointID = AHL_UNDEFINED;
- EndpointInfoT * pEndpointInfo = NULL;
- EndpointSelectionModeT endpointSelMode = ENDPOINTSELMODEMAXVALUE;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s,s:s,s?i}", "audio_role", &audioRole, "endpoint_type", &endpointTypeStr, "endpoint_id", &endpointID);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = audio_role:%s endpoint_type:%s endpoint_id:%d", audioRole,endpointTypeStr,endpointID);
- endpointType = EndpointTypeToEnum(endpointTypeStr);
-
- // Check if there is already an existing context for this client
- AHLClientCtxT * pClientCtx = afb_req_context_get(req); // Retrieve client-specific data structure
- if (pClientCtx == NULL)
- {
- pClientCtx = AllocateClientContext();
- afb_req_context_set(req, pClientCtx, TerminateClientContext);
- }
-
- RoleInfoT * pRole = GetRole(audioRole);
- if ( pRole == NULL )
- {
- afb_req_fail_f(req, "Invalid audio role", "Audio role was not found in configuration -> %s",audioRole);
- return;
- }
-
- GPtrArray * pDeviceArray = NULL;
- if (endpointType == ENDPOINTTYPE_SOURCE){
- pDeviceArray = pRole->pSourceEndpoints;
- }
- else{
- pDeviceArray = pRole->pSinkEndpoints;
- }
- if (pDeviceArray == NULL || pDeviceArray->len == 0) {
- afb_req_fail_f(req, "No available devices", "No available devices for role:%s and device type:%s",audioRole,endpointTypeStr);
- return;
- }
-
- if (endpointID == AHL_UNDEFINED)
- {
- // Assign a device based on configuration priority (first in the list for requested role and endpoint type)
- pEndpointInfo = g_ptr_array_index(pDeviceArray,0);
- endpointSelMode = ENDPOINTSELMODE_AUTO;
-
- }
- else{
- endpointSelMode = ENDPOINTSELMODE_MANUAL;
- // Find specified endpoint ID in list of devices
- int iNumberDevices = pDeviceArray->len;
- for ( int j = 0 ; j < iNumberDevices; j++)
- {
- pEndpointInfo = g_ptr_array_index(pDeviceArray,j);
- if (pEndpointInfo && pEndpointInfo->endpointID == endpointID) {
- break;
- }
- pEndpointInfo = NULL;
- }
-
- }
-
- if (pEndpointInfo == NULL) {
- afb_req_fail_f(req, "Endpoint not available", "Specified endpoint not available for role:%s and device type:%d endpoint id %d",audioRole,endpointType,endpointID);
- return;
- }
-
- pStreamInfo = (StreamInfoT*) malloc(sizeof(StreamInfoT));
- memset(pStreamInfo,0,sizeof(StreamInfoT));
-
- // Create stream
- pStreamInfo->streamID = CreateNewStreamID(); // create new ID
- pStreamInfo->streamState = STREAM_STATE_IDLE;
- pStreamInfo->streamMute = STREAM_UNMUTED;
- pStreamInfo->pEndpointInfo = pEndpointInfo;
- pStreamInfo->endpointSelMode = endpointSelMode;
- // Directly from role config for now, but could be programmatically overriden in the future
- pStreamInfo->pRoleName = pRole->pRoleName;
- pStreamInfo->iPriority = pRole->iPriority;
- pStreamInfo->eInterruptBehavior = pRole->eInterruptBehavior;
-
-#ifndef AHL_DISCONNECT_POLICY
- // Call policy to verify whether creating a new audio stream is allowed in current context and possibly take other actions
- json_object *pPolicyStreamJ = NULL;
- err = PolicyStreamStructToJSON(pStreamInfo, &pPolicyStreamJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- afb_req_fail(req, "Audio policy violation", "Unable to get JSON object for Policy_OpenStream");
- return;
- }
-
- int policyAllowed = Policy_OpenStream(pPolicyStreamJ);
- if (policyAllowed == AHL_POLICY_REJECT)
- {
- afb_req_fail(req, "Audio policy violation", "Open stream not allowed in current context");
- return;
- }
-#endif
-
- char streamEventName[128];
- snprintf(streamEventName,128,"ahl_streamstate_%d",pStreamInfo->streamID);
-
- pStreamInfo->streamStateEvent = afb_daemon_make_event(streamEventName);
- err = !afb_event_is_valid(pStreamInfo->streamStateEvent);
- if (err) {
- afb_req_fail(req, "Stream event creation failure", "Could not create stream specific state change event");
- return;
- }
-
- err = afb_req_subscribe(req,pStreamInfo->streamStateEvent);
- if (err) {
- afb_req_fail(req, "Stream event subscription failure", "Could not subscribe to stream specific state change event");
- return;
- }
-
- // Add to client context stream ID access rights
- g_array_append_val(pClientCtx->pStreamAccessList, pStreamInfo->streamID);
-
- // Push stream on active stream list
- if (g_AHLCtx.policyCtx.pStreams)
- g_hash_table_insert( g_AHLCtx.policyCtx.pStreams, GINT_TO_POINTER(&pStreamInfo->streamID), pStreamInfo );
-
- StreamInfoStructToJSON(&streamInfoJ,pStreamInfo);
-
- afb_req_success(req, streamInfoJ, "Stream info structure");
-}
-
-PUBLIC void audiohlapi_stream_close(struct afb_req req)
-{
- json_object *queryJ = NULL;
- streamID_t streamID = AHL_UNDEFINED;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:i}", "stream_id", &streamID);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = stream_id:%d", streamID);
-
-
- StreamInfoT * pStreamInfo = GetStream(streamID);
- if (pStreamInfo == NULL) {
- afb_req_fail_f(req, "Stream not found", "Specified stream not currently active stream_id -> %d",streamID);
- return;
- }
-
- // Check if there is already an existing context for this client
- AHLClientCtxT * pClientCtx = afb_req_context_get(req); // Retrieve client-specific data structure
- if (pClientCtx == NULL)
- {
- afb_req_fail(req, "Bad state", "No client context associated with the request (is there an opened stream by this client?)");
- return;
- }
-
- // Verify that this client can control the stream
- int iStreamAccessControl = CheckStreamAccessControl( pClientCtx, streamID );
- if (iStreamAccessControl == AHL_ACCESS_CONTROL_DENIED)
- {
- afb_req_fail(req, "Access control denied", "Close stream not allowed in current client context");
- return;
- }
-
-#ifndef AHL_DISCONNECT_POLICY
- json_object *pPolicyStreamJ = NULL;
- err = PolicyStreamStructToJSON(pStreamInfo, &pPolicyStreamJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- afb_req_fail(req, "Audio policy violation", "Unable to get JSON object for Policy_CloseStream");
- return;
- }
- // Call policy to verify whether creating a new audio stream is allowed in current context and possibly take other actions
- int policyAllowed = Policy_CloseStream(pPolicyStreamJ);
- if (policyAllowed == AHL_POLICY_REJECT)
- {
- afb_req_fail(req, "Audio policy violation", "Close stream not allowed in current context");
- return;
- }
-#endif
-
- // Unsubscribe client from stream events
- char streamEventName[128];
- snprintf(streamEventName,128,"ahl_streamstate_%d",streamID);
- int iValid = afb_event_is_valid(pStreamInfo->streamStateEvent);
- if (iValid) {
- err = afb_req_unsubscribe(req,pStreamInfo->streamStateEvent);
- if (err) {
- afb_req_fail(req, "Stream event subscription failure", "Could not unsubscribe to stream specific state change event");
- return;
- }
- }
-
- // Remove from stream list (if present)
- if (g_AHLCtx.policyCtx.pStreams)
- g_hash_table_remove(g_AHLCtx.policyCtx.pStreams,GINT_TO_POINTER(&pStreamInfo->streamID));
- free(pStreamInfo);
- pStreamInfo = NULL;
-
- // Find index for cases where there are multiple streams per client
- // Remove from client context stream ID and endpoint ID access rights
- if (pClientCtx->pStreamAccessList) {
- for (int i = 0; i < pClientCtx->pStreamAccessList->len ; i++) {
- streamID_t iID = g_array_index(pClientCtx->pStreamAccessList,streamID_t,i);
- if (iID == streamID) {
- g_array_remove_index(pClientCtx->pStreamAccessList, i);
- }
- }
-
- if (pClientCtx->pStreamAccessList->len == 0) {
- // If no more streams/endpoints owner, clear session
- afb_req_context_clear(req);
- }
- }
-
- afb_req_success(req, NULL, "Stream close completed");
-}
-
- PUBLIC void audiohlapi_set_stream_state(struct afb_req req)
- {
- json_object *queryJ = NULL;
- streamID_t streamID = AHL_UNDEFINED;
- char * streamStateStr = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:i,s:s}", "stream_id", &streamID,"state",&streamStateStr);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = stream_id:%d, state:%s", streamID,streamStateStr);
-
- StreamInfoT * pStreamInfo = GetStream(streamID);
- if (pStreamInfo == NULL) {
- afb_req_fail_f(req, "Stream not found", "Specified stream not found stream_id -> %d",streamID);
- return;
- }
-
- // Check if there is already an existing context for this client
- AHLClientCtxT * pClientCtx = afb_req_context_get(req); // Retrieve client-specific data structure
- if (pClientCtx == NULL)
- {
- afb_req_fail(req, "Bad state", "No client context associated with the request (is there an opened stream by this client?)");
- return;
- }
-
- // Verify that this client can control the stream
- int iStreamAccessControl = CheckStreamAccessControl( pClientCtx, streamID );
- if (iStreamAccessControl == AHL_ACCESS_CONTROL_DENIED)
- {
- afb_req_fail(req, "Access control denied", "Set stream state not allowed in current client context");
- return;
- }
-
- StreamStateT streamState = StreamStateToEnum(streamStateStr);
-#ifndef AHL_DISCONNECT_POLICY
- json_object *pPolicyStreamJ = NULL;
- err = PolicyStreamStructToJSON(pStreamInfo, &pPolicyStreamJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- afb_req_fail(req, "Audio policy violation", "Unable to get JSON object for Policy_SetStreamState");
- return;
- }
-
- json_object *paramJ= json_object_new_int(streamState);
- json_object_object_add(pPolicyStreamJ, "arg_stream_state", paramJ);
-
- int policyAllowed = Policy_SetStreamState(pPolicyStreamJ);
- if (policyAllowed == AHL_POLICY_REJECT)
- {
- afb_req_fail(req, "Audio policy violation", "Change stream state not allowed in current context");
- return;
- }
-#else
- // Simulate that policy returns target state (accepted)
- pStreamInfo->streamState = streamState;
-#endif
-
- afb_req_success(req, NULL, "Set stream state");
- }
-
- PUBLIC void audiohlapi_set_stream_mute(struct afb_req req)
- {
- json_object *queryJ = NULL;
- streamID_t streamID = AHL_UNDEFINED;
- char * pMuteStr = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:i,s:s}", "stream_id", &streamID,"mute",&pMuteStr);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = stream_id:%d, mute:%s", streamID,pMuteStr);
-
- StreamInfoT * pStreamInfo = GetStream(streamID);
- if (pStreamInfo == NULL) {
- afb_req_fail_f(req, "Stream not found", "Specified stream not currently active stream_id -> %d",streamID);
- return;
- }
-
- // Check if there is already an existing context for this client
- AHLClientCtxT * pClientCtx = afb_req_context_get(req); // Retrieve client-specific data structure
- if (pClientCtx == NULL)
- {
- afb_req_fail(req, "Bad state", "No client context associated with the request (is there an opened stream by this client?)");
- return;
- }
-
- // Verify that this client can control the stream
- int iStreamAccessControl = CheckStreamAccessControl( pClientCtx, streamID );
- if (iStreamAccessControl == AHL_ACCESS_CONTROL_DENIED)
- {
- afb_req_fail(req, "Access control denied", "Set stream mute state not allowed in current client context");
- return;
- }
-
-
- StreamMuteT muteState = StreamMuteToEnum(pMuteStr);
-#ifndef AHL_DISCONNECT_POLICY
- json_object *pPolicyStreamJ = NULL;
- err = PolicyStreamStructToJSON(pStreamInfo, &pPolicyStreamJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- afb_req_fail(req, "Audio policy violation", "Unable to get JSON object for Policy_SetStreamMute");
- return;
- }
-
- json_object *paramJ= json_object_new_int(muteState);
- json_object_object_add(pPolicyStreamJ, "mute_state", paramJ);
-
- int policyAllowed = Policy_SetStreamMute(pPolicyStreamJ);
- if (policyAllowed == AHL_POLICY_REJECT)
- {
- afb_req_fail(req, "Audio policy violation", "Mute stream not allowed in current context");
- return;
- }
-#else
- // Simulate that policy returns target state (accepted)
- pStreamInfo->streamMute = muteState;
-#endif
-
- afb_req_success(req, NULL, "Set stream mute completed");
- }
-
- PUBLIC void audiohlapi_get_stream_info(struct afb_req req)
- {
- json_object *queryJ = NULL;
- streamID_t streamID = AHL_UNDEFINED;
- json_object * streamInfoJ = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:i}", "stream_id", &streamID);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = stream_id:%d", streamID);
-
- StreamInfoT * pStreamInfo = GetStream(streamID);
- if (pStreamInfo == NULL) {
- afb_req_fail_f(req, "Stream not found", "Specified stream not currently active stream_id -> %d",streamID);
- return;
- }
-
- StreamInfoStructToJSON(&streamInfoJ,pStreamInfo);
-
- afb_req_success(req, streamInfoJ, "Get stream info completed");
- }
-
-PUBLIC void audiohlapi_set_volume(struct afb_req req)
-{
- json_object *queryJ = NULL;
- endpointID_t endpointID = AHL_UNDEFINED;
- char * pEndpointTypeStr = NULL;
- EndpointTypeT endpointType = ENDPOINTTYPE_MAXVALUE;
- char * volumeStr = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s,s:i,s:s}", "endpoint_type", &pEndpointTypeStr,"endpoint_id",&endpointID,"volume",&volumeStr);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = endpoint_type:%s endpoint_id:%d volume:%s", pEndpointTypeStr,endpointID,volumeStr);
- endpointType = EndpointTypeToEnum(pEndpointTypeStr);
-
- EndpointInfoT * pEndpointInfo = GetEndpointInfo(endpointID,endpointType);
- if (pEndpointInfo == NULL)
- {
- afb_req_fail_f(req, "Endpoint not found", "Endpoint information not found for id:%d type%d",endpointID,endpointType);
- return;
- }
-
-#ifndef AHL_DISCONNECT_POLICY
- json_object *pPolicyEndpointJ = NULL;
- err = PolicyEndpointStructToJSON(pEndpointInfo, &pPolicyEndpointJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- afb_req_fail(req, "Audio policy violation", "Unable to get JSON object for Policy_SetVolume");
- return;
- }
-
- json_object *paramJ= json_object_new_string(volumeStr);
- json_object_object_add(pPolicyEndpointJ, "arg_volume", paramJ);
-
- int policyAllowed = Policy_SetVolume(pPolicyEndpointJ);
- if (!policyAllowed)
- {
- afb_req_fail(req, "Audio policy violation", "Set volume not allowed in current context");
- return;
- }
-#else
- // Simulate that policy returns target state (accepted)
- pEndpointInfo->iVolume = atoi(volumeStr);
-#endif
-
- afb_req_success(req, NULL, "Set volume completed");
-}
-
-PUBLIC void audiohlapi_get_volume(struct afb_req req)
-{
- json_object *queryJ = NULL;
- endpointID_t endpointID = AHL_UNDEFINED;
- char * pEndpointTypeStr = NULL;
- EndpointTypeT endpointType = ENDPOINTTYPE_MAXVALUE;
- json_object * volumeJ = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s,s:i}", "endpoint_type", &pEndpointTypeStr,"endpoint_id",&endpointID);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = endpoint_type:%s endpoint_id:%d", pEndpointTypeStr,endpointID);
- endpointType = EndpointTypeToEnum(pEndpointTypeStr);
-
- EndpointInfoT * pEndpointInfo = GetEndpointInfo(endpointID,endpointType);
- if (pEndpointInfo == NULL)
- {
- afb_req_fail_f(req, "Endpoint not found", "Endpoint information not found for id:%d type%d",endpointID,endpointType);
- return;
- }
-
- volumeJ = json_object_new_int(pEndpointInfo->iVolume);
-
- afb_req_success(req, volumeJ, "Retrieved volume value");
-}
-
-// Properties
-PUBLIC void audiohlapi_get_endpoint_info(struct afb_req req)
-{
- json_object *queryJ = NULL;
- endpointID_t endpointID = AHL_UNDEFINED;
- char * pEndpointTypeStr = NULL;
- EndpointTypeT endpointType = ENDPOINTTYPE_MAXVALUE;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s,s:i}", "endpoint_type", &pEndpointTypeStr,"endpoint_id",&endpointID);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = endpoint_type:%s endpoint_id:%d", pEndpointTypeStr,endpointID);
- endpointType = EndpointTypeToEnum(pEndpointTypeStr);
-
- EndpointInfoT * pEndpointInfo = GetEndpointInfo(endpointID,endpointType);
- if (pEndpointInfo == NULL)
- {
- afb_req_fail_f(req, "Endpoint not found", "Endpoint information not found for id:%d type%d",endpointID,endpointType);
- return;
- }
-
- json_object *endpointInfoJ = NULL;
- EndpointInfoStructToJSON(&endpointInfoJ,pEndpointInfo);
-
- afb_req_success(req, endpointInfoJ, "Retrieved endpoint information and properties");
-}
-
-PUBLIC void audiohlapi_set_property(struct afb_req req)
-{
- json_object *queryJ = NULL;
- endpointID_t endpointID = AHL_UNDEFINED;
- char * pEndpointTypeStr = NULL;
- EndpointTypeT endpointType = ENDPOINTTYPE_MAXVALUE;
- char * propertyName = NULL;
- json_object * propValueJ = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s,s:i,s:s,s:o}", "endpoint_type", &pEndpointTypeStr,"endpoint_id",&endpointID,"property_name",&propertyName,"value",&propValueJ);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = endpoint_type:%s endpoint_id:%d property_name:%s", pEndpointTypeStr,endpointID,propertyName);
- endpointType = EndpointTypeToEnum(pEndpointTypeStr);
-
- EndpointInfoT * pEndpointInfo = GetEndpointInfo(endpointID,endpointType);
- if (pEndpointInfo == NULL)
- {
- afb_req_fail_f(req, "Endpoint not found", "Endpoint information not found for id:%d type%d",endpointID,endpointType);
- return;
- }
-
-#ifndef AHL_DISCONNECT_POLICY
- json_object *pPolicyEndpointJ = NULL;
- err = PolicyEndpointStructToJSON(pEndpointInfo, &pPolicyEndpointJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- afb_req_fail(req, "Audio policy violation", "Unable to get JSON object for Policy_SetVolume");
- return;
- }
-
- json_object *paramJ= json_object_new_string(propertyName);
- json_object_object_add(pPolicyEndpointJ, "arg_property_name", paramJ);
- json_object_object_add(pPolicyEndpointJ, "arg_property_value", propValueJ);
-
- // Call policy to allow custom policy actions in current context
- int policyAllowed = Policy_SetProperty(pPolicyEndpointJ);
- if (!policyAllowed)
- {
- afb_req_fail(req, "Audio policy violation", "Set endpoint property not allowed in current context");
- return;
- }
-#else
- // Simulate that policy returns target state (accepted)
- if (pEndpointInfo->pPropTable)
- g_hash_table_insert(pEndpointInfo->pPropTable, propertyName, propValueJ);
-#endif
-
- //afb_event_push(g_AHLCtx.policyCtx.propertyEvent,queryJ);
-
- afb_req_success(req, NULL, "Set property completed");
-}
-
-PUBLIC void audiohlapi_get_property(struct afb_req req)
-{
- json_object *queryJ = NULL;
- endpointID_t endpointID = AHL_UNDEFINED;
- char * pEndpointTypeStr = NULL;
- EndpointTypeT endpointType = ENDPOINTTYPE_MAXVALUE;
- char * propertyName = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s,s:i,s:s}", "endpoint_type", &pEndpointTypeStr,"endpoint_id",&endpointID,"property_name",&propertyName);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = endpoint_type:%s endpoint_id:%d property_name:%s", pEndpointTypeStr,endpointID,propertyName);
- endpointType = EndpointTypeToEnum(pEndpointTypeStr);
-
- EndpointInfoT * pEndpointInfo = GetEndpointInfo(endpointID,endpointType);
- if (pEndpointInfo == NULL)
- {
- afb_req_fail_f(req, "Endpoint not found", "Endpoint information not found for id:%d type%d",endpointID,endpointType);
- return;
- }
-
- // Retrieve cached property value
- json_object * propertyValJ = (json_object *)g_hash_table_lookup(pEndpointInfo->pPropTable,propertyName);
- if (propertyValJ == NULL) {
- afb_req_fail_f(req, "Property not found", "Property information not found: %s",propertyName);
- return;
- }
-
- json_object_get(propertyValJ); // Increase ref count so that framework does not free our JSON object
- //AFB_WARNING("properties %s", json_object_get_string(propertyValJ));
- //json_object_get(propertyValJ); // Increase ref count so that framework does not free our JSON object
-
- afb_req_success(req, propertyValJ, "Retrieved property value");
-}
-
-// Audio related events
-
-PUBLIC void audiohlapi_get_list_actions(struct afb_req req)
-{
- json_object *queryJ = NULL;
- char * audioRole = NULL;
- json_object * roleActionsJ = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s}", "audio_role",&audioRole);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = audio_role:%s",audioRole);
-
- // Build and return list of actions for specific audio role
- RoleInfoT * pRole = GetRole(audioRole);
- if ( pRole == NULL )
- {
- afb_req_fail_f(req, "Invalid audio role", "Audio role was not found in configuration -> %s",audioRole);
- return;
- }
-
- roleActionsJ = json_object_new_array();
- if (pRole->pActionList) {
- int iNumberActions = pRole->pActionList->len;
- for ( int i = 0 ; i < iNumberActions; i++)
- {
- char * pActionName = g_ptr_array_index(pRole->pActionList,i);
- json_object * actionJ = json_object_new_string(pActionName);
- json_object_array_add(roleActionsJ, actionJ);
- }
- }
-
- afb_req_success(req, roleActionsJ, "Retrieved action list for audio role");
-}
-
-PUBLIC void audiohlapi_post_action(struct afb_req req)
-{
- json_object *queryJ = NULL;
- char * actionName = NULL;
- char * audioRole = NULL;
- char * mediaName = NULL;
- json_object *actionContext = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:s,s:s,s?s,s?o}", "action_name", &actionName,"audio_role",&audioRole,"media_name",&mediaName,"action_context",&actionContext);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
- AFB_DEBUG("Parsed input arguments = action_name:%s audio_role:%s", actionName,audioRole);
-
- // Verify if known action for audio role
- RoleInfoT * pRole = GetRole(audioRole);
- if ( pRole == NULL )
- {
- afb_req_fail_f(req, "Invalid audio role", "Audio role was not found in configuration -> %s",audioRole);
- return;
- }
-
- // Check to find specific action
- int iActionFound = 0;
- if (pRole->pActionList) {
- int iNumberActions = pRole->pActionList->len;
- char * pTargetActionName = NULL;
- for ( int i = 0 ; i < iNumberActions; i++)
- {
- pTargetActionName = g_ptr_array_index(pRole->pActionList,i);
- if ( strcasecmp(pTargetActionName,actionName)==0) {
- iActionFound = 1;
- break;
- }
- }
- }
-
- if (!iActionFound) {
- afb_req_fail_f(req, "Event not found for audio role", "Event -> %s not found for role:%s",actionName,audioRole);
- return;
- }
-
-#ifndef AHL_DISCONNECT_POLICY
- // Call policy to allow custom policy actions in current context (e.g. cancel playback)
- int policyAllowed = Policy_PostAction(queryJ);
- if (!policyAllowed)
- {
- afb_req_fail(req, "Audio policy violation", "Post sound action not allowed in current context");
- return;
- }
-#endif
-
- //afb_event_push(g_AHLCtx.policyCtx.postEvent,queryJ);
-
- afb_req_success(req, NULL, "Posted sound action");
- }
-
-
-// Monitoring
-PUBLIC void audiohlapi_subscribe(struct afb_req req)
-{
- json_object *queryJ = NULL;
- json_object * eventArrayJ = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:o}", "events", &eventArrayJ);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
-
- int iNumEvents = json_object_array_length(eventArrayJ);
- for (int i = 0; i < iNumEvents; i++)
- {
- char * pEventName = NULL;
- json_object * jEvent = json_object_array_get_idx(eventArrayJ,i);
- pEventName = (char *)json_object_get_string(jEvent);
- if(pEventName == NULL) {
- afb_req_fail(req, "failed", "Invalid event");
- return;
- }
- else if(!strcasecmp(pEventName, AHL_ENDPOINT_PROPERTY_EVENT)) {
- afb_req_subscribe(req, g_AHLCtx.policyCtx.propertyEvent);
- AFB_DEBUG("Client subscribed to endpoint property events");
- }
- else if(!strcasecmp(pEventName, AHL_ENDPOINT_VOLUME_EVENT)) {
- afb_req_subscribe(req, g_AHLCtx.policyCtx.volumeEvent);
- AFB_DEBUG("Client subscribed to endpoint volume events");
- }
- else if(!strcasecmp(pEventName, AHL_POST_ACTION_EVENT)) {
- afb_req_subscribe(req, g_AHLCtx.policyCtx.postActionEvent);
- AFB_DEBUG("Client subscribed to post event calls events");
- }
- else {
- afb_req_fail(req, "failed", "Invalid event");
- return;
- }
- }
-
- afb_req_success(req, NULL, "Subscribe to events finished");
-}
-
-PUBLIC void audiohlapi_unsubscribe(struct afb_req req)
-{
- json_object *queryJ = NULL;
- json_object * eventArrayJ = NULL;
-
- queryJ = afb_req_json(req);
- int err = wrap_json_unpack(queryJ, "{s:o}", "events", &eventArrayJ);
- if (err) {
- afb_req_fail_f(req, "Invalid arguments", "Args not a valid json object query=%s", json_object_get_string(queryJ));
- return;
- }
-
- int iNumEvents = json_object_array_length(eventArrayJ);
- for (int i = 0; i < iNumEvents; i++)
- {
- char * pEventName = NULL;
- json_object * jEvent = json_object_array_get_idx(eventArrayJ,i);
- pEventName = (char *)json_object_get_string(jEvent);
- if(pEventName == NULL) {
- afb_req_fail(req, "failed", "Invalid event");
- return;
- }
- else if(!strcasecmp(pEventName, AHL_ENDPOINT_PROPERTY_EVENT)) {
- afb_req_unsubscribe(req, g_AHLCtx.policyCtx.propertyEvent);
- AFB_DEBUG("Client unsubscribed to endpoint property events");
- }
- else if(!strcasecmp(pEventName, AHL_ENDPOINT_VOLUME_EVENT)) {
- afb_req_unsubscribe(req, g_AHLCtx.policyCtx.volumeEvent);
- AFB_DEBUG("Client unsubscribed to endpoint volume events");
- }
- else if(!strcasecmp(pEventName, AHL_POST_ACTION_EVENT)) {
- afb_req_unsubscribe(req, g_AHLCtx.policyCtx.postActionEvent);
- AFB_DEBUG("Client unsubscribed to post event calls events");
- }
- else {
- afb_req_fail(req, "failed", "Invalid event");
- return;
- }
- }
-
- afb_req_success(req, NULL, "Unsubscribe to events finished");
-}
-
-// Since the policy is currently in the same binding, it cannot raise events on its own
-// This is a first step toward isolation, when policy is migrated in its own binding it can simply raise AGL events
-// This binding will register for these policy events and will execute the code below upon event reception
-PUBLIC void audiohlapi_raise_event(json_object * pEventDataJ)
-{
- char * pEventName = NULL;
-
- int err = wrap_json_unpack(pEventDataJ,"{s:s}","event_name", &pEventName);
- if(err)
- {
- AFB_ERROR("Unable to retrieve event name");
- return;
- }
-
- if(strcasecmp(pEventName, AHL_ENDPOINT_INIT_EVENT)==0) {
- char * pAudioRole = NULL;
- endpointID_t endpointID = AHL_UNDEFINED;
- EndpointTypeT endpointType = ENDPOINTTYPE_MAXVALUE;
- int err = wrap_json_unpack(pEventDataJ,"{s:i,s:i,s:s}",
- "endpoint_id", &endpointID,
- "endpoint_type", &endpointType,
- "audio_role", &pAudioRole);
- if(err)
- {
- AFB_ERROR("Unable to unpack property init event");
- return;
- }
-
- RoleInfoT * pRole = GetRole(pAudioRole);
- if ( pRole == NULL ){
- AFB_ERROR("Requested audio role does not exist in current configuration -> %s", pAudioRole);
- return;
- }
-
- EndpointInfoT * pEndpointInfo = InitEndpointInfo();
- g_assert_nonnull(pEndpointInfo);
- PolicyCtxJSONToEndpoint(pEventDataJ,pEndpointInfo);
-
- err = ReplaceEndpointInfoWithRole(endpointID,endpointType,pRole,pEndpointInfo);
- if(err == AHL_FAIL)
- {
- AFB_ERROR("Can't update EndpointInfo aborting");
- return;
- }
-
- // Remove event name from object
- // json_object_object_del(pEventDataJ,"event_name");
- //afb_event_push(g_AHLCtx.policyCtx.propertyEvent,pEventDataJ); // Not broadcasted to application at this time
- }
- else if(strcasecmp(pEventName, AHL_ENDPOINT_PROPERTY_EVENT)==0) {
- char * pAudioRole = NULL;
- char * pPropertyName = NULL;
- endpointID_t endpointID = AHL_UNDEFINED;
- EndpointTypeT endpointType = ENDPOINTTYPE_MAXVALUE;
- json_object * propValueJ = NULL;
- int err = wrap_json_unpack(pEventDataJ,"{s:i,s:i,s:s,s:o,s:s}",
- "endpoint_id", &endpointID,
- "endpoint_type", &endpointType,
- "property_name", &pPropertyName,
- "value",&propValueJ,
- "audio_role", &pAudioRole);
- if(err)
- {
- AFB_ERROR("Unable to unpack property event");
- return;
- }
- RoleInfoT * pRole = GetRole(pAudioRole);
- if ( pRole == NULL ){
- AFB_ERROR("Requested audio role does not exist in current configuration -> %s", pAudioRole);
- return;
- }
- EndpointInfoT * pEndpointInfo = GetEndpointInfoWithRole(endpointID,endpointType,pRole);
- // update property value
- if (pEndpointInfo->pPropTable)
- {
- json_type jType = json_object_get_type(propValueJ);
- switch (jType) {
- case json_type_double:
- Add_Endpoint_Property_Double(pEndpointInfo,pPropertyName,json_object_get_double(propValueJ));
- break;
- case json_type_int:
- Add_Endpoint_Property_Int(pEndpointInfo,pPropertyName,json_object_get_int(propValueJ));
- break;
- case json_type_string:
- Add_Endpoint_Property_String(pEndpointInfo,pPropertyName,json_object_get_string(propValueJ));
- break;
- default:
- AFB_ERROR("Invalid property argument Property value not a valid json object query=%s", json_object_get_string(propValueJ));
- return ;
- }
- }
- // Remove event name from object
- json_object_object_del(pEventDataJ,"event_name");
- afb_event_push(g_AHLCtx.policyCtx.propertyEvent,pEventDataJ);
- }
- else if(strcasecmp(pEventName, AHL_ENDPOINT_VOLUME_EVENT)==0) {
- char * pAudioRole = NULL;
- endpointID_t endpointID = AHL_UNDEFINED;
- EndpointTypeT endpointType = ENDPOINTTYPE_MAXVALUE;
- int iVolume = 0;
- int err = wrap_json_unpack(pEventDataJ,"{s:i,s:i,s:i,s:s}",
- "endpoint_id", &endpointID,
- "endpoint_type", &endpointType,
- "value",&iVolume,
- "audio_role", &pAudioRole);
- if(err)
- {
- AFB_ERROR("Unable to unpack volume event data");
- return;
- }
- RoleInfoT * pRole = GetRole(pAudioRole);
- if ( pRole == NULL ){
- AFB_ERROR("Requested audio role does not exist in current configuration -> %s", pAudioRole);
- return;
- }
- EndpointInfoT * pEndpointInfo = GetEndpointInfoWithRole(endpointID,endpointType,pRole);
- // update volume value
- pEndpointInfo->iVolume = iVolume;
- // Remove event name from object
- json_object_object_del(pEventDataJ,"event_name");
- afb_event_push(g_AHLCtx.policyCtx.volumeEvent,pEventDataJ);
- }
- else if(strcasecmp(pEventName, AHL_POST_ACTION_EVENT)==0) {
- // Remove event name from object
- json_object_object_del(pEventDataJ,"event_name");
- afb_event_push(g_AHLCtx.policyCtx.postActionEvent,pEventDataJ);
- }
- else if(strcasecmp(pEventName, AHL_STREAM_STATE_EVENT)==0) {
- streamID_t streamID = AHL_UNDEFINED;
- StreamEventT streamEvent = STREAM_EVENT_MAXVALUE;
- int err = wrap_json_unpack(pEventDataJ,"{s:i,s:i}",
- "stream_id", &streamID,
- "state_event", &streamEvent);
- if(err)
- {
- AFB_ERROR("Unable to unpack stream event data");
- return;
- }
-
- StreamInfoT * pStreamInfo = GetStream(streamID);
- if (pStreamInfo == NULL) {
- AFB_ERROR("Specified stream not currently active stream_id -> %d",streamID);
- return;
- }
-
- // update streamstate value
- switch (streamEvent) {
- case STREAM_EVENT_START:
- pStreamInfo->streamState = STREAM_STATE_RUNNING;
- break;
- case STREAM_EVENT_STOP:
- pStreamInfo->streamState = STREAM_STATE_IDLE;
- break;
- case STREAM_EVENT_PAUSE:
- pStreamInfo->streamState = STREAM_STATE_PAUSED;
- break;
- case STREAM_EVENT_RESUME:
- pStreamInfo->streamState = STREAM_STATE_RUNNING;
- break;
- case STREAM_EVENT_MUTED:
- pStreamInfo->streamMute = STREAM_MUTED;
- break;
- case STREAM_EVENT_UNMUTED:
- pStreamInfo->streamMute = STREAM_UNMUTED;
- break;
- default:
- AFB_ERROR("Unknown stream event");
- }
-
- // Remove event name from object
- json_object_object_del(pEventDataJ,"event_name");
- AFB_ERROR("pEventDataJ=%s", json_object_get_string(pEventDataJ));
- afb_event_push(pStreamInfo->streamStateEvent,pEventDataJ);
- }
- else {
- AFB_ERROR("Unknown event name");
- }
-} \ No newline at end of file
diff --git a/src/ahl-binding.h b/src/ahl-binding.h
deleted file mode 100644
index 9b4c37e..0000000
--- a/src/ahl-binding.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef AHL_BINDING_INCLUDE
-#define AHL_BINDING_INCLUDE
-
-#define AFB_BINDING_VERSION 2
-
-//#define AHL_DISCONNECT_POLICY // define for debugging HLB in standalone only
-
-#include <json-c/json.h>
-#include <glib.h>
-
-#include <afb/afb-binding.h>
-#include "ahl-interface.h"
-#include "ahl-policy-utils.h"
-
-
-#ifndef PUBLIC
- #define PUBLIC
-#endif
-
-#define AHL_SUCCESS 0
-#define AHL_FAIL 1
-
-#define AHL_ACCESS_CONTROL_GRANTED 1
-#define AHL_ACCESS_CONTROL_DENIED 0
-
-#define AHL_UNDEFINED -1
-#define AHL_STR_MAX_LENGTH 256
-
-
-typedef struct RoleInfo {
- char * pRoleName; // Role string identifier
- int iPriority; // Role normalized priority (0-100)
- InterruptBehaviorT eInterruptBehavior; // Role behavior when interrupting lower priority streams
- GPtrArray * pActionList; // List of supported actions for the role (gchar*)
- GPtrArray * pSourceEndpoints; // Source endpoints info (EndpointInfoT*)
- GPtrArray * pSinkEndpoints; // Sink endpoints info (EndpointInfoT*)
-} RoleInfoT;
-
-// Parts of the context that are visible to the policy (for state based decisions)
-typedef struct AHLPolicyCtx {
- GHashTable * pRoleInfo; // Hash table of role information structure (RoleInfoT*) accessed by role name
- GHashTable * pStreams; // List of active streams (StreamInfoT*) accessed by streamID
- GPtrArray * pHALList; // List of HAL dependencies
- // TODO: Events need to be sent directly by HLB when separation with policy complete
- struct afb_event propertyEvent; // AGL event used when property changes
- struct afb_event volumeEvent; // AGL event used when volume changes
- struct afb_event postActionEvent; // AGL event used on post action call
-} AHLPolicyCtxT;
-
-// Global binding context
-typedef struct AHLCtx {
- AHLPolicyCtxT policyCtx;
- endpointID_t nextSourceEndpointID; // Counter to assign new ID
- endpointID_t nextSinkEndpointID; // Counter to assign new ID
- endpointID_t nextStreamID; // Counter to assign new ID
-} AHLCtxT;
-
-// Client specific binding context
-typedef struct AHLClientCtx {
- GArray * pStreamAccessList; // List of streams that client has control over
-} AHLClientCtxT;
-
-// ahl-binding.c
-PUBLIC int AhlBindingInit();
-PUBLIC void AhlOnEvent(const char *evtname, json_object *eventJ);
-
-// ahl-deviceenum.c
-int EnumerateDevices(json_object * in_jDeviceArray, char * in_pAudioRole, EndpointTypeT in_deviceType, GPtrArray * out_pEndpointArray);
-EndpointInfoT * InitEndpointInfo();
-void TermEndpointInfo( EndpointInfoT * out_pEndpointInfo );
-// ahl-config.c
-int ParseHLBConfig();
-// ahl-policy.c
-#ifndef AHL_DISCONNECT_POLICY
-PUBLIC void audiohlapi_raise_event(json_object *EventDataJ);
-#endif
-
-#endif // AHL_BINDING_INCLUDE
diff --git a/src/ahl-config.c b/src/ahl-config.c
deleted file mode 100644
index 5e3de08..0000000
--- a/src/ahl-config.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * 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.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <json-c/json.h>
-#include "wrap-json.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;
-}
-
-int ParseHLBConfig() {
- char * versionStr = NULL;
- json_object * jAudioRoles = NULL;
- json_object * jHALList = NULL;
- char * policyModule = NULL;
-
- // TODO: This should be retrieve from binding startup arguments
- char configfile_path[256];
- if(getenv("AHL_CONFIG_FILE") == NULL)
- {
- AFB_ERROR("Please Set Environnement Variable AHL_CONFIG_FILE");
- return 1;
- }
-
- sprintf(configfile_path, "%s", getenv("AHL_CONFIG_FILE"));
- 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 1;
- }
-
- 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 1;
- }
- 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 1;
- }
- }
- }
-
- 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 1;
- }
-
- 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 1;
- }
- }
- // 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 1;
- }
- }
-
- 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 0;
-}
diff --git a/src/ahl-deviceenum.c b/src/ahl-deviceenum.c
deleted file mode 100644
index 7e67d7a..0000000
--- a/src/ahl-deviceenum.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * 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.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <alsa/asoundlib.h>
-#include <alsa/pcm.h>
-#include <json-c/json.h>
-#include "wrap-json.h"
-
-#include "ahl-binding.h"
-#include "ahl-policy.h"
-
-extern AHLCtxT g_AHLCtx;
-
-// TODO: Hash from endpoint ID information instead
-static endpointID_t CreateNewSourceID()
-{
- endpointID_t newID = g_AHLCtx.nextSourceEndpointID;
- g_AHLCtx.nextSourceEndpointID++;
- return newID;
-}
-
-// TODO: Hash from endpoint ID information instead
-static endpointID_t CreateNewSinkID()
-{
- endpointID_t newID = g_AHLCtx.nextSinkEndpointID;
- g_AHLCtx.nextSinkEndpointID++;
- return newID;
-}
-
-// Watchout: This function uses strtok and is destructive on the input string (use a copy)
-static int SeparateDomainFromDeviceURI( char * in_pDeviceURI, char ** out_pDomain, char ** out_pDevice)
-{
- *out_pDomain = strtok(in_pDeviceURI, ".");
- if (*out_pDomain == NULL)
- {
- AFB_ERROR("Error tokenizing device URI -> %s",in_pDeviceURI);
- return 1;
- }
- // TODO: Validate domain is known string (e.g. ALSA,Pulse,GStreamer)
- *out_pDevice = strtok(NULL, ".");
- if (*out_pDevice == NULL)
- {
- AFB_ERROR("Error tokenizing device URI -> %s",in_pDeviceURI);
- return 1;
- }
- return 0;
-}
-
-static int IsAlsaDomain(const char * in_pDomainStr)
-{
- return (int) (strcasecmp(in_pDomainStr,AHL_DOMAIN_ALSA) == 0);
-}
-
-static int IsPulseDomain(const char * in_pDomainStr)
-{
- return (int) (strcasecmp(in_pDomainStr,AHL_DOMAIN_PULSE) == 0);
-}
-
-static int IsGStreamerDomain(const char * in_pDomainStr)
-{
- return (int) (strcasecmp(in_pDomainStr,AHL_DOMAIN_GSTREAMER) == 0);
-}
-
-static int IsExternalDomain(const char * in_pDomainStr)
-{
- return (int) (strcasecmp(in_pDomainStr,AHL_DOMAIN_EXTERNAL) == 0);
-}
-
-static int FillALSAPCMInfo( snd_pcm_t * in_pPcmHandle, EndpointInfoT * out_pEndpointInfo )
-{
- g_assert_nonnull(in_pPcmHandle);
- g_assert_nonnull(out_pEndpointInfo);
- snd_pcm_type_t pcmType = 0;
- snd_pcm_info_t * pPcmInfo = NULL;
- int iAlsaRet = 0;
- const char * pCardName = NULL;
- int retVal = 0;
- snd_ctl_t * ctlHandle = NULL;
- snd_ctl_card_info_t * ctlInfo = NULL;
-
- snd_pcm_info_alloca(&pPcmInfo);
- snd_ctl_card_info_alloca(&ctlInfo);
-
- // retrieve PCM type
- pcmType = snd_pcm_type(in_pPcmHandle);
- switch (pcmType) {
- case SND_PCM_TYPE_HW:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_HW;
- break;
- case SND_PCM_TYPE_DMIX:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_DMIX;
- break;
- case SND_PCM_TYPE_SOFTVOL:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_SOFTVOL;
- break;
- case SND_PCM_TYPE_PLUG:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_PLUG;
- break;
- default:
- out_pEndpointInfo->deviceURIType = DEVICEURITYPE_ALSA_OTHER;
- break;
- }
-
- iAlsaRet = snd_pcm_info(in_pPcmHandle,pPcmInfo);
- if (iAlsaRet < 0)
- {
- AFB_WARNING("Error retrieving PCM device info");
- return 1;
- }
-
- // get card number
- out_pEndpointInfo->alsaInfo.cardNum = snd_pcm_info_get_card(pPcmInfo);
- if ( out_pEndpointInfo->alsaInfo.cardNum < 0 )
- {
- AFB_WARNING("No Alsa card number available");
- return 1;
- }
-
- // get device number
- out_pEndpointInfo->alsaInfo.deviceNum = snd_pcm_info_get_device(pPcmInfo);
- if ( out_pEndpointInfo->alsaInfo.deviceNum < 0 )
- {
- AFB_WARNING("No Alsa device number available");
- return 1;
- }
-
- // get sub-device number
- out_pEndpointInfo->alsaInfo.subDeviceNum = snd_pcm_info_get_subdevice(pPcmInfo);
- if ( out_pEndpointInfo->alsaInfo.subDeviceNum < 0 )
- {
- AFB_WARNING("No Alsa subdevice number available");
- return 1;
- }
-
- char cardName[32];
- sprintf(cardName, "hw:%d", out_pEndpointInfo->alsaInfo.cardNum);
- iAlsaRet = snd_ctl_open(&ctlHandle, cardName, 0);
- if ( iAlsaRet < 0 )
- {
- AFB_WARNING("Could not open ALSA card control");
- return 1;
- }
-
- iAlsaRet = snd_ctl_card_info(ctlHandle, ctlInfo);
- if ( iAlsaRet < 0 )
- {
- AFB_WARNING("Could not retrieve ALSA card info");
- snd_ctl_close(ctlHandle);
- return 1;
- }
-
- // Populate unique target card name
- pCardName = snd_ctl_card_info_get_id(ctlInfo);
- if (pCardName == NULL)
- {
- AFB_WARNING("No Alsa card name available");
- snd_ctl_close(ctlHandle);
- return 1;
- }
- out_pEndpointInfo->gsDeviceName = g_strdup(pCardName);
-
- snd_ctl_close(ctlHandle);
-
- return retVal;
-}
-
-EndpointInfoT * InitEndpointInfo()
-{
- EndpointInfoT * pEndpointInfo = (EndpointInfoT*) malloc(sizeof(EndpointInfoT));
- memset(pEndpointInfo,0,sizeof(EndpointInfoT));
- pEndpointInfo->endpointID = AHL_UNDEFINED;
- pEndpointInfo->type = ENDPOINTTYPE_MAXVALUE;
- pEndpointInfo->deviceURIType = DEVICEURITYPE_MAXVALUE;
- pEndpointInfo->alsaInfo.cardNum = AHL_UNDEFINED;
- pEndpointInfo->alsaInfo.deviceNum = AHL_UNDEFINED;
- pEndpointInfo->alsaInfo.subDeviceNum = AHL_UNDEFINED;
- pEndpointInfo->format.sampleRate = AHL_UNDEFINED;
- pEndpointInfo->format.numChannels = AHL_UNDEFINED;
- pEndpointInfo->format.sampleType = AHL_FORMAT_UNKNOWN;
- pEndpointInfo->pPropTable = g_hash_table_new(g_str_hash, g_str_equal);
- return pEndpointInfo;
-}
-
-void TermEndpointInfo( EndpointInfoT * out_pEndpointInfo )
-{
- #define SAFE_FREE(__ptr__) if(__ptr__) g_free(__ptr__); __ptr__ = NULL;
- SAFE_FREE(out_pEndpointInfo->gsDeviceName);
- SAFE_FREE(out_pEndpointInfo->gsDisplayName);
- SAFE_FREE(out_pEndpointInfo->gsDeviceDomain);
- SAFE_FREE(out_pEndpointInfo->pRoleName);
- SAFE_FREE(out_pEndpointInfo->gsDeviceURI);
- SAFE_FREE(out_pEndpointInfo->gsHALAPIName);
-
- if (out_pEndpointInfo->pPropTable) {
- // Free json_object for all property values
- GHashTableIter iter;
- gpointer key, value;
- g_hash_table_iter_init (&iter, out_pEndpointInfo->pPropTable);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- if (value)
- json_object_put(value);
- }
- g_hash_table_remove_all(out_pEndpointInfo->pPropTable);
- g_hash_table_destroy(out_pEndpointInfo->pPropTable);
- out_pEndpointInfo->pPropTable = NULL;
- }
- // GLib automatically frees item when removed from the array
-}
-
-// For a given audio role
-int EnumerateDevices(json_object * in_jDeviceArray, char * in_pAudioRole, EndpointTypeT in_deviceType, GPtrArray * out_pEndpointArray) {
-
- g_assert_nonnull(in_jDeviceArray);
- int iNumberDevices = json_object_array_length(in_jDeviceArray);
-
- // Parse and validate list of available devices
- for (int i = 0; i < iNumberDevices; i++)
- {
- char * pDeviceURIDomain = NULL;
- char * pFullDeviceURI = NULL;
- char * pDeviceURIPCM = NULL;
- int err = 0;
-
- json_object * jDevice = json_object_array_get_idx(in_jDeviceArray,i);
- if (jDevice == NULL) {
- AFB_WARNING("Invalid device array -> %s",json_object_to_json_string(in_jDeviceArray));
- continue;
- }
- // strip domain name from URI
- pFullDeviceURI = (char *)json_object_get_string(jDevice);
- char * pFullDeviceURICopy = g_strdup(pFullDeviceURI); // strtok is destructive
- err = SeparateDomainFromDeviceURI(pFullDeviceURICopy,&pDeviceURIDomain,&pDeviceURIPCM);
- if (err)
- {
- AFB_WARNING("Invalid device URI string -> %s",pFullDeviceURICopy);
- continue;
- }
-
- EndpointInfoT * pEndpointInfo = InitEndpointInfo();
- g_assert_nonnull(pEndpointInfo);
-
- // non ALSA URI are simply passed to application (no validation) at this time
- // In Non ALSA case devices in config are assumed to be available, if not application can fallback on explicit device selection
- pEndpointInfo->gsDeviceName = g_strdup(pDeviceURIPCM);
- pEndpointInfo->gsDeviceDomain = g_strdup(pDeviceURIDomain);
- pEndpointInfo->gsDeviceURI = g_strdup(pDeviceURIPCM);
- pEndpointInfo->pRoleName = g_strdup(in_pAudioRole);
-
- g_free(pFullDeviceURICopy);
- pFullDeviceURICopy = NULL;
- pDeviceURIDomain = NULL; //Derived from above mem
- pDeviceURIPCM = NULL; //Derived from above mem
-
- if (IsAlsaDomain(pEndpointInfo->gsDeviceDomain))
- {
- // TODO: Missing support for loose name matching
- // This will require using ALSA hints to get PCM names
- // And would iterate over all available devices matching string (possibly all if no filtering is desired for a certain role)
-
- // Get PCM handle
- snd_pcm_t * pPcmHandle = NULL;
- snd_pcm_stream_t streamType = in_deviceType == ENDPOINTTYPE_SOURCE ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK;
- err = snd_pcm_open(&pPcmHandle, pEndpointInfo->gsDeviceURI, streamType, 0);
- if (err < 0)
- {
- AFB_NOTICE("Alsa PCM device was not found -> %s", pEndpointInfo->gsDeviceURI);
- continue;
- }
-
- err = FillALSAPCMInfo(pPcmHandle,pEndpointInfo);
- if (err) {
- AFB_WARNING("Unable to retrieve PCM information for PCM -> %s",pEndpointInfo->gsDeviceURI);
- snd_pcm_close(pPcmHandle);
- continue;
- }
-
- snd_pcm_close(pPcmHandle);
- }
- else if (IsPulseDomain(pEndpointInfo->gsDeviceDomain)) {
- // Pulse domain
- // For now display name is device URI directly, could extrapolated using more heuristics or even usins Pulse API later on
- pEndpointInfo->deviceURIType = DEVICEURITYPE_NOT_ALSA;
- }
- else if (IsGStreamerDomain(pEndpointInfo->gsDeviceDomain)){
- // GStreamer domain
- // For now display name is device URI directly, could extrapolated using more heuristics or even usins GStreamer API later on
- pEndpointInfo->deviceURIType = DEVICEURITYPE_NOT_ALSA;
- }
- else if (IsExternalDomain(pEndpointInfo->gsDeviceDomain)){
- // External domain
- pEndpointInfo->deviceURIType = DEVICEURITYPE_NOT_ALSA;
- }
- else {
- // Unknown domain
- AFB_WARNING("Unknown domain in device URI string -> %s",pFullDeviceURI);
- continue;
- }
-
- pEndpointInfo->endpointID = in_deviceType == ENDPOINTTYPE_SOURCE ? CreateNewSourceID() : CreateNewSinkID();
- pEndpointInfo->type = in_deviceType;
- // Assigned by policy initialization
- pEndpointInfo->gsDisplayName = malloc(AHL_STR_MAX_LENGTH*sizeof(char));
- memset(pEndpointInfo->gsDisplayName,0,AHL_STR_MAX_LENGTH*sizeof(char));
- pEndpointInfo->gsHALAPIName = malloc(AHL_STR_MAX_LENGTH*sizeof(char));
- memset(pEndpointInfo->gsDisplayName,0,AHL_STR_MAX_LENGTH*sizeof(char));
-
- // add to structure to list of available devices
- g_ptr_array_add(out_pEndpointArray, pEndpointInfo);
-
- } // for all devices
-
- AFB_DEBUG ("Audio high-level - Enumerate devices done");
- return 0;
-} \ No newline at end of file
diff --git a/src/ahl-interface.h b/src/ahl-interface.h
deleted file mode 100644
index 0488e96..0000000
--- a/src/ahl-interface.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef AHL_INTERFACE_INCLUDE
-#define AHL_INTERFACE_INCLUDE
-
-///// API /////
-
-// Endpoint types
-#define AHL_ENDPOINTTYPE_SOURCE "source" // source devices
-#define AHL_ENDPOINTTYPE_SINK "sink" // sink devices
-
-// Stream state
-#define AHL_STREAM_STATE_IDLE "idle" // Stream is inactive
-#define AHL_STREAM_STATE_RUNNING "running" // Stream is active and running
-#define AHL_STREAM_STATE_PAUSED "paused" // Stream is active but paused
-
-// Stream mute state
-#define AHL_STREAM_UNMUTED "off" // Stream is not muted
-#define AHL_STREAM_MUTED "on" // Stream is muted
-
-// Property/Volume/Action events
-#define AHL_ENDPOINT_PROPERTY_EVENT "ahl_endpoint_property_event"
-#define AHL_ENDPOINT_VOLUME_EVENT "ahl_endpoint_volume_event"
-#define AHL_ENDPOINT_INIT_EVENT "ahl_endpoint_init_event"
-#define AHL_POST_ACTION_EVENT "ahl_post_action"
-#define AHL_STREAM_STATE_EVENT "ahl_stream_state_event"
-#define AHL_ENDPOINT_INIT_EVENT "ahl_endpoint_init_event"
-
-
-// Stream state event types
-#define AHL_STREAM_EVENT_START "start" // Stream is inactive
-#define AHL_STREAM_EVENT_STOP "stop" // Stream is running
-#define AHL_STREAM_EVENT_PAUSE "pause" // Audio stream paused
-#define AHL_STREAM_EVENT_RESUME "resume" // Audio stream resumed
-#define AHL_STREAM_EVENT_MUTE "mute" // Audio stream muted
-#define AHL_STREAM_EVENT_UNMUTE "unmute" // Audio stream unmuted
-
-///// Interpret returned or configuration information /////
-
-// Known audio domain string definitions (for configuration file format and device URI interpretation)
-#define AHL_DOMAIN_ALSA "alsa"
-#define AHL_DOMAIN_PULSE "pulse"
-#define AHL_DOMAIN_GSTREAMER "gstreamer"
-#define AHL_DOMAIN_EXTERNAL "external"
-
-// ALSA Device URI type
-#define AHL_DEVICEURITYPE_ALSA_HW "hw" // Alsa hardware device URI
-#define AHL_DEVICEURITYPE_ALSA_DMIX "dmix" // Alsa Dmix device URI (only for playback devices)
-#define AHL_DEVICEURITYPE_ALSA_DSNOOP "dsnoop" // Alsa DSnoop device URI (only for capture devices)
-#define AHL_DEVICEURITYPE_ALSA_SOFTVOL "softvol" // Alsa softvol device URI
-#define AHL_DEVICEURITYPE_ALSA_PLUG "plug" // Alsa plug device URI
-#define AHL_DEVICEURITYPE_ALSA_OTHER "other" // Alsa domain URI device of unspecified type
-#define AHL_DEVICEURITYPE_NOT_ALSA "nonalsa"
-
-// Define default behavior of audio role when interrupting lower priority sources (in configuration)
-#define AHL_INTERRUPTBEHAVIOR_CONTINUE "continue" // Continue to play when interrupted (e.g. media may be ducked)
-#define AHL_INTERRUPTBEHAVIOR_CANCEL "cancel" // Abort playback when interrupted (e.g. non-important HMI feedback that does not make sense later)
-#define AHL_INTERRUPTBEHAVIOR_PAUSE "pause" // Pause source when interrupted, to be resumed afterwards (e.g. non-temporal guidance)
-
-///// Naming convention /////
-
-// Standardized name for common audio roles (not enforced in any way, just helps compatibility)
-#define AHL_ROLE_WARNING "warning" // Safety-relevant or critical alerts/alarms
-#define AHL_ROLE_GUIDANCE "guidance" // Important user information where user action is expected (e.g. navigation instruction)
-#define AHL_ROLE_NOTIFICATION "notification" // HMI or else notifications (e.g. touchscreen events, speech recognition on/off,...)
-#define AHL_ROLE_COMMUNICATION "communication" // Voice communications (e.g. handsfree, speech recognition)
-#define AHL_ROLE_ENTERTAINMENT "entertainment" // Multimedia content (e.g. tuner, media player, etc.)
-#define AHL_ROLE_SYSTEM "system" // System level content or development
-#define AHL_ROLE_STARTUP "startup" // Early (startup) sound
-#define AHL_ROLE_SHUTDOWN "shutdown" // Late (shutdown) sound
-#define AHL_ROLE_NONE "none" // Non-assigned / legacy applications
-
-// Standardized list of properties (not enforced in any way, just helps compatibility)
-#define AHL_PROPERTY_BALANCE "balance"
-#define AHL_PROPERTY_FADE "fade"
-#define AHL_PROPERTY_EQ_LOW "eq_bass"
-#define AHL_PROPERTY_EQ_MID "eq_mid"
-#define AHL_PROPERTY_EQ_HIGH "eq_treble"
-
-// Standardized list of events (not enforced in any way, just helps compatibility)
-#define AHL_EVENTS_PLAYSOUND "play_sound"
-#define AHL_EVENTS_ECHOCANCEL_ENABLE "echocancel_enable"
-#define AHL_EVENTS_ECHOCANCEL_DISABLE "echocancel_disable"
-
-#endif // AHL_INTERFACE_INCLUDE
diff --git a/src/ahl-policy-utils.c b/src/ahl-policy-utils.c
deleted file mode 100644
index 60ddd36..0000000
--- a/src/ahl-policy-utils.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * 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 "ahl-policy-utils.h"
-#include "wrap-json.h"
-#include <json-c/json.h>
-#include <glib.h>
-
-void Add_Endpoint_Property_Double( EndpointInfoT * io_pEndpointInfo, char * in_pPropertyName, double in_dPropertyValue)
-{
- json_object * propValueJ = json_object_new_double(in_dPropertyValue);
- g_hash_table_insert(io_pEndpointInfo->pPropTable, in_pPropertyName, propValueJ);
-}
-
-
-void Add_Endpoint_Property_Int( EndpointInfoT * io_pEndpointInfo, char * in_pPropertyName, int in_iPropertyValue)
-{
- json_object * propValueJ = json_object_new_int(in_iPropertyValue);
- g_hash_table_insert(io_pEndpointInfo->pPropTable, in_pPropertyName, propValueJ);
-}
-
-void Add_Endpoint_Property_String( EndpointInfoT * io_pEndpointInfo, char * in_pPropertyName, const char * in_pPropertyValue)
-{
- json_object * propValueJ = json_object_new_string(in_pPropertyValue);
- g_hash_table_insert(io_pEndpointInfo->pPropTable, in_pPropertyName, propValueJ);
-}
-
-int PolicyEndpointStructToJSON(EndpointInfoT * pEndpointInfo, json_object **ppPolicyEndpointJ)
-{
- if(pEndpointInfo == NULL || pEndpointInfo->pPropTable == NULL)
- {
- AFB_ERROR("Invalid PolicyEndpointStructToJSON arguments");
- return AHL_POLICY_UTIL_FAIL;
- }
-
- //Create json object for PropTable
- json_object *pPropTableJ = json_object_new_array();
- if(pEndpointInfo->pPropTable) {
- GHashTableIter iter;
- gpointer key, value;
- g_hash_table_iter_init (&iter, pEndpointInfo->pPropTable);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- json_object *pPropertyJ = NULL;
- int error=wrap_json_pack(&pPropertyJ, "{s:s,s:o}",
- "property_name", (char*)key,
- "property_value", value
- );
- if(error)
- {
- AFB_ERROR("Unable to pack JSON endpoint, =%s", wrap_json_get_error_string(error));
- return AHL_POLICY_UTIL_FAIL;
- }
- json_object_array_add(pPropTableJ, pPropertyJ);
- }
- AFB_DEBUG("json object query=%s", json_object_get_string(pPropTableJ));
- }
-
- //Create json object for Endpoint
- int err= wrap_json_pack(ppPolicyEndpointJ, "{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:i,s:s,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:o}",
- "endpoint_id", pEndpointInfo->endpointID,
- "endpoint_type", pEndpointInfo->type,
- "device_name", pEndpointInfo->gsDeviceName,
- "display_name", pEndpointInfo->gsDisplayName,
- "device_uri", pEndpointInfo->gsDeviceURI,
- "device_domain", pEndpointInfo->gsDeviceDomain,
- "audio_role",pEndpointInfo->pRoleName,
- "device_uri_type", pEndpointInfo->deviceURIType,
- "hal_api_name", pEndpointInfo->gsHALAPIName,
- "alsa_cardNum", pEndpointInfo->alsaInfo.cardNum,
- "alsa_deviceNum", pEndpointInfo->alsaInfo.deviceNum,
- "alsa_subDeviceNum", pEndpointInfo->alsaInfo.subDeviceNum,
- "format_samplerate", pEndpointInfo->format.sampleRate,
- "format_numchannels", pEndpointInfo->format.numChannels,
- "format_sampletype",pEndpointInfo->format.sampleType,
- "volume", pEndpointInfo->iVolume,
- "property_table", pPropTableJ
- );
- if (err) {
- AFB_ERROR("Unable to pack JSON endpoint, =%s", wrap_json_get_error_string(err));
- return AHL_POLICY_UTIL_FAIL;
- }
- AFB_DEBUG("JSON endpoint information=%s", json_object_get_string(*ppPolicyEndpointJ));
- return AHL_POLICY_UTIL_SUCCESS;
-}
-
-int PolicyStreamStructToJSON(StreamInfoT * pPolicyStream, json_object **ppPolicyStreamJ)
-{
- if(pPolicyStream == NULL)
- {
- AFB_ERROR("Invalid arguments to PolicyStreamStructToJSON");
- return AHL_POLICY_UTIL_FAIL;
- }
-
- json_object * pEndpointJ = NULL;
- int iRet = PolicyEndpointStructToJSON(pPolicyStream->pEndpointInfo, &pEndpointJ);
- if (iRet) {
- return iRet;
- }
-
- //Create json object for stream
- int err = wrap_json_pack(ppPolicyStreamJ, "{s:i,s:i,s:i,s:I,s:i,s:s,s:i,s:i,s:o}",
- "stream_id", pPolicyStream->streamID,
- "stream_state", pPolicyStream->streamState,
- "stream_mute", pPolicyStream->streamMute,
- "stream_state_event", &pPolicyStream->streamStateEvent,
- "endpoint_sel_mod", pPolicyStream->endpointSelMode,
- "role_name", pPolicyStream->pRoleName,
- "priority", pPolicyStream->iPriority,
- "interrupt_behavior", pPolicyStream->eInterruptBehavior,
- "endpoint_info", pEndpointJ
- );
- if (err) {
- AFB_ERROR("Unable to pack JSON endpoint, =%s", wrap_json_get_error_string(err));
- return AHL_POLICY_UTIL_FAIL;
- }
-
- AFB_DEBUG("JSON stream information=%s", json_object_get_string(*ppPolicyStreamJ));
-
- return AHL_POLICY_UTIL_SUCCESS;
-}
-
-int PolicyCtxJSONToEndpoint(json_object *pEndpointJ, EndpointInfoT * pEndpointInfo)
-{
- if(pEndpointJ == NULL || pEndpointInfo == NULL /*|| pEndpointInfo->pPropTable == NULL */ )
- {
- AFB_ERROR("Invalid arguments for PolicyCtxJSONToEndpoint");
- return AHL_POLICY_UTIL_FAIL;
- }
-
- //Unpack Endpoint
- json_object *pPropTableJ = NULL;
- int err = wrap_json_unpack(pEndpointJ, "{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:i,s:s,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:o}",
- "endpoint_id", &pEndpointInfo->endpointID,
- "endpoint_type", &pEndpointInfo->type,
- "device_name", &pEndpointInfo->gsDeviceName,
- "display_name", &pEndpointInfo->gsDisplayName,
- "device_uri", &pEndpointInfo->gsDeviceURI,
- "device_domain", &pEndpointInfo->gsDeviceDomain,
- "audio_role", &pEndpointInfo->pRoleName,
- "device_uri_type", &pEndpointInfo->deviceURIType,
- "hal_api_name", &pEndpointInfo->gsHALAPIName,
- "alsa_cardNum", &pEndpointInfo->alsaInfo.cardNum,
- "alsa_deviceNum", &pEndpointInfo->alsaInfo.deviceNum,
- "alsa_subDeviceNum", &pEndpointInfo->alsaInfo.subDeviceNum,
- "format_samplerate", &pEndpointInfo->format.sampleRate,
- "format_numchannels", &pEndpointInfo->format.numChannels,
- "format_sampletype",&pEndpointInfo->format.sampleType,
- "volume", &pEndpointInfo->iVolume,
- "property_table", &pPropTableJ
- );
- if (err) {
- AFB_ERROR("Unable to unpack JSON endpoint, =%s", wrap_json_get_error_string(err));
- return AHL_POLICY_UTIL_FAIL;
- }
-
- // Unpack prop table
- if(pPropTableJ)
- {
- pEndpointInfo->pPropTable = g_hash_table_new(g_str_hash, g_str_equal);
-
- int nbProperties = json_object_array_length(pPropTableJ);
- for(int i=0; i<nbProperties; i++)
- {
- json_object * propJ = json_object_array_get_idx(pPropTableJ,i);
- if (propJ) {
- char * pPropertyName = NULL;
- json_object * pPropertyValueJ = NULL;
-
- int err=wrap_json_unpack(propJ, "{s:s,s:o}",
- "property_name", &pPropertyName,
- "property_value", &pPropertyValueJ);
- if (err) {
- AFB_ERROR("Unable to unpack JSON endpoint, = %s", wrap_json_get_error_string(err));
- return AHL_POLICY_UTIL_FAIL;
- }
-
- // Object type detection for property value (string = state, numeric = property)
- json_type jType = json_object_get_type(pPropertyValueJ);
- switch (jType) {
- case json_type_double:
- Add_Endpoint_Property_Double(pEndpointInfo,pPropertyName,json_object_get_double(pPropertyValueJ));
- break;
- case json_type_int:
- Add_Endpoint_Property_Int(pEndpointInfo,pPropertyName,json_object_get_int(pPropertyValueJ));
- break;
- case json_type_string:
- Add_Endpoint_Property_String(pEndpointInfo,pPropertyName,json_object_get_string(pPropertyValueJ));
- break;
- default:
- AFB_ERROR("Invalid property argument Property value not a valid json object query=%s", json_object_get_string(pPropertyValueJ));
- return AHL_POLICY_UTIL_FAIL;
- }
- }
- }
- }
-
- return AHL_POLICY_UTIL_SUCCESS;
-}
-
-int PolicyCtxJSONToStream(json_object *pStreamJ, StreamInfoT * pPolicyStream)
-{
- if(pStreamJ == NULL || pPolicyStream == NULL)
- {
- AFB_ERROR("Invalid arguments for PolicyCtxJSONToStream");
- return AHL_POLICY_UTIL_FAIL;
- }
-
- //Unpack StreamInfo
- json_object *pEndpointJ = NULL;
- AFB_WARNING("json object query=%s", json_object_get_string(pStreamJ));
- int err=wrap_json_unpack(pStreamJ, "{s:i,s:i,s:i,s:I,s:i,s:s,s:i,s:i,s:o}",
- "stream_id", &pPolicyStream->streamID,
- "stream_state", &pPolicyStream->streamState,
- "stream_mute", &pPolicyStream->streamMute,
- "stream_state_event", &pPolicyStream->streamStateEvent,
- "endpoint_sel_mod", &pPolicyStream->endpointSelMode,
- "role_name", &pPolicyStream->pRoleName,
- "priority", &pPolicyStream->iPriority,
- "interrupt_behavior", &pPolicyStream->eInterruptBehavior,
- "endpoint_info", &pEndpointJ
- );
-
- if (err) {
- AFB_ERROR("Unable to parse JSON stream information=%s", json_object_get_string(pStreamJ));
- return AHL_POLICY_UTIL_FAIL;
- }
-
- int iRet = PolicyCtxJSONToEndpoint(pEndpointJ,pPolicyStream->pEndpointInfo);
- if (iRet) {
- return iRet;
- }
- return AHL_POLICY_UTIL_SUCCESS;
-}
- \ No newline at end of file
diff --git a/src/ahl-policy-utils.h b/src/ahl-policy-utils.h
deleted file mode 100644
index 6adfa4e..0000000
--- a/src/ahl-policy-utils.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef AHL_POLICY_UTILS_INCLUDE
-#define AHL_POLICY_UTILS_INCLUDE
-
-#define AFB_BINDING_VERSION 2
-#include <json-c/json.h>
-#include <afb/afb-binding.h>
-#include <glib.h>
-
-#define AHL_POLICY_ACCEPT 1
-#define AHL_POLICY_REJECT 0
-#define AHL_POLICY_UTIL_SUCCESS 0
-#define AHL_POLICY_UTIL_FAIL 1
-
-typedef int endpointID_t;
-typedef int streamID_t;
-
-typedef enum StreamEvent {
- STREAM_EVENT_START = 0, // Stream is inactive
- STREAM_EVENT_STOP, // Stream is running
- STREAM_EVENT_PAUSE, // Audio stream paused
- STREAM_EVENT_RESUME, // Audio stream resumed
- STREAM_EVENT_MUTED, // Audio stream muted
- STREAM_EVENT_UNMUTED, // Audio stream unmuted
- STREAM_EVENT_MAXVALUE // Enum count, keep at the end
-} StreamEventT;
-
-typedef enum StreamMute {
- STREAM_UNMUTED = 0, // Stream is not muted
- STREAM_MUTED, // Stream is muted
- STREAM_MUTE_MAXVALUE, // Enum count, keep at the end
-} StreamMuteT;
-
-typedef enum EndpointType {
- ENDPOINTTYPE_SOURCE = 0, // source devices
- ENDPOINTTYPE_SINK, // sink devices
- ENDPOINTTYPE_MAXVALUE // Enum count, keep at the end
-} EndpointTypeT;
-
-typedef enum StreamState {
- STREAM_STATE_IDLE = 0, // Stream is inactive
- STREAM_STATE_RUNNING, // Stream is active and running
- STREAM_STATE_PAUSED, // Stream is active but paused
- STREAM_STATE_MAXVALUE // Enum count, keep at the end
-} StreamStateT;
-
-// Define default behavior of audio role when interrupting lower priority sources
-typedef enum InterruptBehavior {
- INTERRUPTBEHAVIOR_CONTINUE = 0, // Continue to play lower priority source when interrupted (e.g. media may be ducked)
- INTERRUPTBEHAVIOR_CANCEL, // Abort playback of lower priority source when interrupted (e.g. non-important HMI feedback that does not make sense later)
- INTERRUPTBEHAVIOR_PAUSE, // Pause lower priority source when interrupted, to be resumed afterwards (e.g. non-temporal guidance)
- INTERRUPTBEHAVIOR_MAXVALUE, // Enum count, keep at the end
-} InterruptBehaviorT;
-
-typedef enum DeviceURIType {
- DEVICEURITYPE_ALSA_HW = 0, // Alsa hardware device URI
- DEVICEURITYPE_ALSA_DMIX, // Alsa Dmix device URI (only for playback devices)
- DEVICEURITYPE_ALSA_DSNOOP, // Alsa DSnoop device URI (only for capture devices)
- DEVICEURITYPE_ALSA_SOFTVOL, // Alsa softvol device URI
- DEVICEURITYPE_ALSA_PLUG, // Alsa plug device URI
- DEVICEURITYPE_ALSA_OTHER, // Alsa domain URI device of unspecified type
- DEVICEURITYPE_NOT_ALSA, // Unknown (not ALSA domain)
- DEVICEURITYPE_MAXVALUE // Enum count, keep at the end
-} DeviceURITypeT;
-
-// CPU endianness assumed in all formats
-typedef enum SampleType {
- AHL_FORMAT_UNKNOWN = -1, // Unknown
- AHL_FORMAT_U8 = 0, // Unsigned 8 bit
- AHL_FORMAT_S16, // Signed 16 bit Little Endian
- AHL_FORMAT_S24, // Signed 24 bit Little Endian using low three bytes in 32-bit word
- AHL_FORMAT_S32, // Signed 32 bit Little Endian
- AHL_FORMAT_FLOAT, // Float 32 bit Little Endian, Range -1.0 to 1.0
- AHL_FORMAT_FLOAT64, // Float 64 bit Little Endian, Range -1.0 to 1.0
- AHL_FORMAT_IEC958, // IEC-958 Little Endian (SPDIF)
- AHL_FORMAT_MU_LAW, // Mu-Law
- AHL_FORMAT_A_LAW, // A-Law
- AHL_FORMAT_IMA_ADPCM, // Ima-ADPCM
- AHL_FORMAT_MPEG, // MPEG
- AHL_FORMAT_GSM, // GSM
- AHL_FORMAT_G723, // G723
- AHL_FORMAT_DSD, // Direct stream digital
- AHL_FORMAT_MAXVALUE, // Enum count, keep at the end
-} SampleTypeT;
-
-typedef struct AudioFormat {
- int sampleRate; // Sample rate
- int numChannels; // Number of channels
- SampleTypeT sampleType; // Sample type
- // TODO: Interleaving?
- // TODO: Sample sub format?
-} AudioFormatT;
-
-typedef struct AlsaDeviceInfo {
- int cardNum; // HW card number
- int deviceNum; // HW device number
- int subDeviceNum; // HW sub device number
-} AlsaDeviceInfoT;
-
-typedef enum EndpointSelectionMode {
- ENDPOINTSELMODE_AUTO = 0, // Automatic endpoint selection based on config priority
- ENDPOINTSELMODE_MANUAL, // Explicit endpoint selection
- ENDPOINTSELMODEMAXVALUE, // Enum count, keep at the end
-} EndpointSelectionModeT;
-
-typedef struct EndpointInfo
-{
- endpointID_t endpointID; // Unique endpoint ID (per type)
- EndpointTypeT type; // Source or sink device
- char * gsDeviceName; // Unique device card name
- char * gsDisplayName; // Application display name
- char * gsDeviceURI; // Associated URI
- char * gsDeviceDomain; // Device URI domain (e.g. alsa or pulse)
- char * pRoleName; // Role assigned to this endpoint
- DeviceURITypeT deviceURIType; // Device URI type (includes audio domain information)
- char * gsHALAPIName; // HAL associated with the device (for volume control)
- AlsaDeviceInfoT alsaInfo; // ALSA specific device information
- AudioFormatT format; // Preferred audio format supported (later could be array of supported formats)
- int iVolume; // Storage for current endpoint volume (policy effected).
- GHashTable * pPropTable; // Storage for array of properties (policy effected)
-} EndpointInfoT;
-
-typedef struct StreamInfo {
- streamID_t streamID; // Stream unique ID
- EndpointInfoT * pEndpointInfo; // Associated endpoint information (reference)
- StreamStateT streamState; // Stream activity state
- StreamMuteT streamMute; // Stream mute state
- struct afb_event streamStateEvent; // Stream specific event for stream state changes
- EndpointSelectionModeT endpointSelMode; // Automatic (priority based) or manual endpoint selection
- char * pRoleName; // Role string identifier (from role config but could be programatically overriden later)
- int iPriority; // Role normalized priority (0-100) (from role config but could be programatically overriden later)
- InterruptBehaviorT eInterruptBehavior; // Role behavior when interrupting lower priority streams (from role config but could be programatically overriden later)
-} StreamInfoT;
-
-
-typedef struct StreamPolicyInfo {
- streamID_t streamID;
- int RolePriority;
- char * pAudioRole;
- InterruptBehaviorT interruptBehavior;
- int iDuckVolume; //duck Volume
-} StreamPolicyInfoT;
-
-typedef struct EndPointPolicyInfo {
- endpointID_t endpointID;
- EndpointTypeT type;
- DeviceURITypeT deviceType;
- char * pDeviceName;
- char * pHalApiName;
- int iVolume; //Current Volume
- GArray * streamInfo; //List of playing or duck stream at a given endpoint
-} EndPointPolicyInfoT;
-
-void Add_Endpoint_Property_Double( EndpointInfoT * io_pEndpointInfo, char * in_pPropertyName, double in_dPropertyValue);
-void Add_Endpoint_Property_Int( EndpointInfoT * io_pEndpointInfo, char * in_pPropertyName, int in_iPropertyValue);
-void Add_Endpoint_Property_String( EndpointInfoT * io_pEndpointInfo, char * in_pPropertyName, const char * in_pPropertyValue);
-int PolicyEndpointStructToJSON(EndpointInfoT * pPolicyEndpoint, json_object **ppPolicyEndpointJ);
-int PolicyCtxJSONToEndpoint(json_object *pEndpointJ, EndpointInfoT * pPolicyStream);
-int PolicyStreamStructToJSON(StreamInfoT * pPolicyStream, json_object **ppPolicyStreamJ);
-int PolicyCtxJSONToStream(json_object *pStreamJ, StreamInfoT * pPolicyStream);
-
-#endif // AHL_POLICY_UTILS_INCLUDE
diff --git a/src/ahl-policy.c b/src/ahl-policy.c
deleted file mode 100644
index 54634ff..0000000
--- a/src/ahl-policy.c
+++ /dev/null
@@ -1,1108 +0,0 @@
-/*
- * 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.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-#include "wrap-json.h"
-#include "ahl-policy-utils.h"
-#include "ahl-interface.h"
-#include "ahl-policy.h"
-
-#ifndef AHL_DISCONNECT_POLICY
-
-// Global Context
-PolicyLocalCtxT g_PolicyCtx;
-
-
-// Helper Functions
-static int getStreamConfig(char *pAudioRole, StreamConfigT *pStreamConfig)
-{
- if(pAudioRole == NULL || pStreamConfig==NULL)
- {
- return POLICY_FAIL;
- }
-
- if ( strcasecmp(pAudioRole,AHL_ROLE_WARNING) == 0 )
- {
- pStreamConfig->iNbMaxStream = 4;
- pStreamConfig->iVolumeInit = 80;
- pStreamConfig->iVolumeDuckValue = 0;
- }
- else if ( strcasecmp(pAudioRole,AHL_ROLE_GUIDANCE) == 0 )
- {
- pStreamConfig->iNbMaxStream = 10;
- pStreamConfig->iVolumeInit = 70;
- pStreamConfig->iVolumeDuckValue = 30;
- }
- else if ( strcasecmp(pAudioRole,AHL_ROLE_NOTIFICATION) == 0 )
- {
- pStreamConfig->iNbMaxStream = 4;
- pStreamConfig->iVolumeInit = 80;
- pStreamConfig->iVolumeDuckValue = 10;
- }
- else if ( strcasecmp(pAudioRole,AHL_ROLE_COMMUNICATION) == 0 )
- {
- pStreamConfig->iNbMaxStream = 10;
- pStreamConfig->iVolumeInit = 70;
- pStreamConfig->iVolumeDuckValue = 10;
- }
- else if ( strcasecmp(pAudioRole,AHL_ROLE_ENTERTAINMENT) == 0 )
- {
- pStreamConfig->iNbMaxStream = MAX_ACTIVE_STREAM_POLICY;
- pStreamConfig->iVolumeInit = 60;
- pStreamConfig->iVolumeDuckValue = 40;
- }
- else if ( strcasecmp(pAudioRole,AHL_ROLE_SYSTEM) == 0 )
- {
- pStreamConfig->iNbMaxStream = 2;
- pStreamConfig->iVolumeInit = 100;
- pStreamConfig->iVolumeDuckValue = 0;
- }
- else if ( strcasecmp(pAudioRole,AHL_ROLE_STARTUP) == 0 )
- {
- pStreamConfig->iNbMaxStream = 1;
- pStreamConfig->iVolumeInit = 90;
- pStreamConfig->iVolumeDuckValue = 0;
- }
- else if ( strcasecmp(pAudioRole,AHL_ROLE_SHUTDOWN) == 0 )
- {
- pStreamConfig->iNbMaxStream = 1;
- pStreamConfig->iVolumeInit = 90;
- pStreamConfig->iVolumeDuckValue = 0;
- }
- return POLICY_SUCCESS;
-}
-
-static int PolicySetVolume(int iEndpointID, int iEndpointType, char *pHalApiName, char *AudioRole, DeviceURITypeT deviceType, int iVolume, bool bMute)
-{
- if(pHalApiName == NULL)
- {
- AFB_WARNING("SetVolume cannot be accomplished without proper HAL association");
- return POLICY_FAIL;
- }
-
- if(AudioRole == NULL)
- {
- AFB_ERROR("Invalid AudioRole : %s",AudioRole);
- return POLICY_FAIL;
- }
-
- // Using audio role available from endpoint to target the right HAL control (build string based on convention)
- GString * gsHALControlName = NULL;
- switch(deviceType)
- {
- case DEVICEURITYPE_ALSA_HW:
- gsHALControlName = g_string_new("Master_Playback_Volume");
- break;
- case DEVICEURITYPE_ALSA_DMIX:
- case DEVICEURITYPE_ALSA_DSNOOP:
- case DEVICEURITYPE_ALSA_PLUG:
- case DEVICEURITYPE_ALSA_SOFTVOL:
- gsHALControlName = g_string_new(AudioRole);
- if(bMute == false)
- {
- AFB_DEBUG("Using ramp");
- g_string_append(gsHALControlName,"_Ramp");
- }
- else
- {
- AFB_DEBUG("Not using ramp");
- g_string_append(gsHALControlName,"_Vol"); // no ramping
- }
- break;
- default:
- //Set volume to zero for display purpose only.
- //Not support yet
- AFB_WARNING("Device Type %i is not support and can't set volume on HalName %s",deviceType, pHalApiName);
- return POLICY_FAIL;
- break;
- }
-
- // Set endpoint volume using HAL services (leveraging ramps etc.)
- json_object *j_response, *j_query = NULL;
-
- // Package query
- int err = wrap_json_pack(&j_query,"{s:s,s:i}","label",gsHALControlName->str, "val",iVolume);
- if (err)
- {
- AFB_ERROR("Invalid query for HAL ctlset: %s with errorcode: %i",json_object_to_json_string(j_query), err);
- return POLICY_FAIL;
- }
-
- //TODO implement Volume limitation based on policy
-
- // Set the volume using the HAL
- err = afb_service_call_sync(pHalApiName, "ctlset", j_query, &j_response);
- if (err)
- {
- AFB_ERROR("Could not ctlset on HAL: %s with errorcode: %i",pHalApiName, err);
- return POLICY_FAIL;
- }
- AFB_DEBUG("HAL ctlset response=%s", json_object_to_json_string(j_response));
-
- if (bMute == false) {
- // Package event data
- json_object * eventDataJ = NULL;
- err = wrap_json_pack(&eventDataJ,"{s:s,s:i,s:i,s:i,s:s}","event_name", AHL_ENDPOINT_VOLUME_EVENT,"endpoint_id", iEndpointID, "endpoint_type", iEndpointType,"value",iVolume, "audio_role", AudioRole);
- if (err)
- {
- AFB_ERROR("Invalid event data for volume event %s with errorcode: %i",json_object_to_json_string(eventDataJ), err);
- return POLICY_FAIL;
- }
-
- audiohlapi_raise_event(eventDataJ);
- }
-
- return POLICY_SUCCESS;
-}
-
-static int PolicyGetVolume(int iEndpointID, int iEndpointType, char *pHalApiName, char *AudioRole, DeviceURITypeT deviceType, int *pVolume)
-{
- GString * gsHALControlName = NULL;
-
- // Using audio role available from endpoint to target the right HAL control (build string based on convention)
- switch(deviceType)
- {
- case DEVICEURITYPE_ALSA_HW:
- gsHALControlName = g_string_new("Master_Playback_Volume");
- break;
- case DEVICEURITYPE_ALSA_DMIX:
- case DEVICEURITYPE_ALSA_DSNOOP:
- case DEVICEURITYPE_ALSA_PLUG:
- case DEVICEURITYPE_ALSA_SOFTVOL:
- gsHALControlName = g_string_new(AudioRole);
- g_string_append(gsHALControlName,"_Vol"); // Or _Vol for direct control (no ramping)
- break;
- default:
- // Set volume to zero for display purpose only.
- // Not supported yet
- *pVolume = 0;
- AFB_WARNING("Can't get volume on HAL: %s for device type: %d",pHalApiName,deviceType);
- return POLICY_FAIL;
- }
-
- // Set endpoint volume using HAL services (leveraging ramps etc.)
- json_object *j_response = NULL, *j_query = NULL;
-
- // Package query
- int err = wrap_json_pack(&j_query,"{s:s}","label",gsHALControlName->str);
- if (err)
- {
- AFB_WARNING("Invalid query for HAL ctlset: %s, errorcode: %i",json_object_to_json_string(j_query),err);
- return POLICY_FAIL;
- }
-
- //TODO implement Volume limitation based on policy
-
- // Get the volume using the HAL
- err = afb_service_call_sync(pHalApiName, "ctlget", j_query, &j_response);
- if (err)
- {
- AFB_WARNING("Could not ctlset on HAL: %s, errorcode: %i",pHalApiName, err);
- return POLICY_FAIL;
- }
- AFB_DEBUG("HAL ctlget response=%s", json_object_to_json_string(j_response));
-
- // Parse response
- json_object * jRespObj = NULL;
- json_object_object_get_ex(j_response, "response", &jRespObj);
- json_object * jVal = NULL;
- int val1 = 0, val2 = 0; // Why 2 values?
-
- json_object_object_get_ex(jRespObj, "val", &jVal);
- int nbElement = json_object_array_length(jVal);
- if(nbElement == 2)
- {
- err = wrap_json_unpack(jVal, "[ii]", &val1, &val2);
- if (err) {
- AFB_ERROR("Volume retrieve failed Could not retrieve volume value -> %s", json_object_get_string(jVal));
- return POLICY_FAIL;
- }
-
- }
- else
- {
- err = wrap_json_unpack(jVal, "[i]", &val1);
- if (err) {
- AFB_ERROR("Volume retrieve failed Could not retrieve volume value -> %s", json_object_get_string(jVal));
- return POLICY_FAIL;
- }
-
- }
-
- *pVolume = val1;
-
- // Package event data
- json_object * eventDataJ = NULL;
- err = wrap_json_pack(&eventDataJ,"{s:s,s:i,s:i,s:i,s:s}","event_name", AHL_ENDPOINT_VOLUME_EVENT,"endpoint_id", iEndpointID, "endpoint_type", iEndpointType,"value",*pVolume, "audio_role", AudioRole);
- if (err)
- {
- AFB_ERROR("Invalid event data for volume event %s with errorcode: %i",json_object_to_json_string(eventDataJ), err);
- return POLICY_FAIL;
- }
-
- audiohlapi_raise_event(eventDataJ);
-
- return POLICY_SUCCESS;
-}
-
-static void PolicyPostStateEvent(int iStreamID, StreamEventT eventState)
-{
-
- json_object * eventDataJ = NULL;
- int err = wrap_json_pack(&eventDataJ,"{s:s,s:i,s:i}","event_name", AHL_STREAM_STATE_EVENT,"stream_id",iStreamID, "state_event",eventState);
- if (err)
- {
- AFB_ERROR("Invalid event data for stream state event: %s",json_object_to_json_string(eventDataJ));
- }
- else
- {
- audiohlapi_raise_event(eventDataJ);
- }
-}
-
-static EndPointPolicyInfoT *PolicySearchEndPoint(EndpointTypeT type, char *pDeviceName)
-{
- GArray *pcurEndpointArray = NULL;
-
- if(type==ENDPOINTTYPE_SINK)
- {
- pcurEndpointArray = g_PolicyCtx.pSinkEndpoints;
- }
- else
- {
- pcurEndpointArray = g_PolicyCtx.pSourceEndpoints;
- }
-
- for(int i=0; i<pcurEndpointArray->len; i++)
- {
- EndPointPolicyInfoT * pCurEndpoint = &g_array_index(pcurEndpointArray,EndPointPolicyInfoT,i);
-
- if(strcasecmp(pCurEndpoint->pDeviceName,pDeviceName)==0)
- {
- return pCurEndpoint;
- }
- }
-
- return NULL;
-}
-
-
-static int PolicyAddEndPoint(StreamInfoT *pStreamInfo)
-{
- EndPointPolicyInfoT *pPolicyEndPoint = PolicySearchEndPoint(pStreamInfo->pEndpointInfo->type, pStreamInfo->pEndpointInfo->gsDeviceName);
- if(pPolicyEndPoint == NULL)
- {
- //create EndPoint and add playing stream
- EndPointPolicyInfoT newEndPointPolicyInfo;
- newEndPointPolicyInfo.endpointID = pStreamInfo->pEndpointInfo->endpointID;
- newEndPointPolicyInfo.type = pStreamInfo->pEndpointInfo->type;
- newEndPointPolicyInfo.deviceType = pStreamInfo->pEndpointInfo->deviceURIType;
- newEndPointPolicyInfo.pDeviceName = strdup(pStreamInfo->pEndpointInfo->gsDeviceName);
- newEndPointPolicyInfo.pHalApiName = strdup(pStreamInfo->pEndpointInfo->gsHALAPIName);
- newEndPointPolicyInfo.iVolume = pStreamInfo->pEndpointInfo->iVolume;
- newEndPointPolicyInfo.streamInfo = g_array_new(FALSE, TRUE, sizeof(StreamPolicyInfoT));;
-
- if(pStreamInfo->pEndpointInfo->type == ENDPOINTTYPE_SINK)
- {
- g_array_append_val(g_PolicyCtx.pSinkEndpoints, newEndPointPolicyInfo);
- }
- else
- {
- g_array_append_val(g_PolicyCtx.pSourceEndpoints, newEndPointPolicyInfo);
- }
-
- }
- return POLICY_SUCCESS;
-}
-
-
-static int PolicyAddStream(EndPointPolicyInfoT *pCurrEndPointPolicy, StreamInfoT *pStreamInfo)
-{
- StreamPolicyInfoT newStreamPolicyInfo;
-
- newStreamPolicyInfo.streamID = pStreamInfo->streamID;
- newStreamPolicyInfo.RolePriority = pStreamInfo->iPriority;
- newStreamPolicyInfo.pAudioRole = pStreamInfo->pRoleName;
- newStreamPolicyInfo.interruptBehavior = pStreamInfo->eInterruptBehavior;
- newStreamPolicyInfo.iDuckVolume = 0;
- g_array_append_val(pCurrEndPointPolicy->streamInfo, newStreamPolicyInfo);
- return POLICY_SUCCESS;
-}
-
-static int PolicyRunningIdleTransition(EndPointPolicyInfoT *pCurrEndPointPolicy,StreamInfoT * pStreamInfo)
-{
- int err=0;
- if(pCurrEndPointPolicy == NULL || pCurrEndPointPolicy->streamInfo->len == 0)
- {
- //Remove endpoint
- AFB_ERROR("StreamID not found in active Endpoint when Running to Idle transition is request");
- return POLICY_FAIL;
- }
- //Search for the matching stream
- for(int i=0; i<pCurrEndPointPolicy->streamInfo->len; i++)
- {
- StreamPolicyInfoT currentPolicyStreamInfo = g_array_index(pCurrEndPointPolicy->streamInfo,StreamPolicyInfoT,i);
- if(currentPolicyStreamInfo.streamID == pStreamInfo->streamID)
- {
- //remove the current stream
- g_array_remove_index(pCurrEndPointPolicy->streamInfo, i);
- if(pCurrEndPointPolicy->streamInfo->len > 0) //need to unduck
- {
- //check the last element(Akways highest priority)
- StreamPolicyInfoT HighPriorityStreamInfo = g_array_index(pCurrEndPointPolicy->streamInfo,StreamPolicyInfoT,pCurrEndPointPolicy->streamInfo->len-1);
- switch(currentPolicyStreamInfo.interruptBehavior)
- {
- case INTERRUPTBEHAVIOR_CONTINUE:
- //unduck and set Volume back to original value
- err= PolicySetVolume(pCurrEndPointPolicy->endpointID,
- pCurrEndPointPolicy->type,
- pCurrEndPointPolicy->pHalApiName,
- HighPriorityStreamInfo.pAudioRole,
- pCurrEndPointPolicy->deviceType,
- HighPriorityStreamInfo.iDuckVolume,
- false);
- if(err)
- {
- return POLICY_FAIL;
- }
-
- return POLICY_SUCCESS;
- break;
- case INTERRUPTBEHAVIOR_PAUSE:
- //pInterruptStreamInfo->streamState = STREAM_STATE_RUNNING;
- PolicyPostStateEvent(HighPriorityStreamInfo.streamID,STREAM_EVENT_RESUME);
- return POLICY_SUCCESS;
- break;
-
- case INTERRUPTBEHAVIOR_CANCEL:
- PolicyPostStateEvent(HighPriorityStreamInfo.streamID,STREAM_EVENT_START);
- return POLICY_SUCCESS;
- break;
- default:
- AFB_ERROR("Unsupported Intterupt Behavior");
- return POLICY_FAIL;
- break;
- }
- }
- }
- }
- return POLICY_SUCCESS;
-}
-
-static int PolicyIdleRunningTransition(EndPointPolicyInfoT *pCurrEndPointPolicy, StreamInfoT * pStreamInfo)
-{
- int err=0;
- if(pCurrEndPointPolicy->streamInfo == NULL)
- {
- AFB_ERROR("pCurrEndPointPolicy->streamInfo is null on an active endpoint");
- return POLICY_FAIL;
- }
-
- if(pCurrEndPointPolicy->streamInfo->len == 0) //No stream is playing on this endpoint
- {
- PolicyAddStream(pCurrEndPointPolicy, pStreamInfo);
- }
- else //Interrupt case
- {
- //check the last element
- StreamPolicyInfoT *pCurrentActiveStreamInfo = &g_array_index(pCurrEndPointPolicy->streamInfo,StreamPolicyInfoT,pCurrEndPointPolicy->streamInfo->len-1);
- g_assert_nonnull(pCurrentActiveStreamInfo);
- if(pStreamInfo->iPriority >= pCurrentActiveStreamInfo->RolePriority)
- {
- switch(pStreamInfo->eInterruptBehavior)
- {
- case INTERRUPTBEHAVIOR_CONTINUE:
- //Save the current Volume and set the docking volume
- pCurrentActiveStreamInfo->iDuckVolume = pStreamInfo->pEndpointInfo->iVolume;
- StreamConfigT StreamConfig;
- err = getStreamConfig(pStreamInfo->pRoleName, &StreamConfig);
- if(err == POLICY_FAIL)
- {
- AFB_ERROR("Error getting stream configuration for audiorole: %s", pStreamInfo->pRoleName);
- return POLICY_FAIL;
- }
- err= PolicySetVolume(pCurrEndPointPolicy->endpointID,
- pCurrEndPointPolicy->type,
- pCurrEndPointPolicy->pHalApiName,
- pCurrentActiveStreamInfo->pAudioRole,
- pCurrEndPointPolicy->deviceType,
- StreamConfig.iVolumeDuckValue,
- false);
- if(err)
- {
- AFB_ERROR("Set Volume return with errorcode%i for streamID: %i and Hal:%s", err, pCurrentActiveStreamInfo->streamID, pCurrEndPointPolicy->pHalApiName);
- return POLICY_FAIL;
- }
- break;
- case INTERRUPTBEHAVIOR_PAUSE:
- PolicyPostStateEvent(pCurrentActiveStreamInfo->streamID,STREAM_EVENT_PAUSE);
- break;
-
- case INTERRUPTBEHAVIOR_CANCEL:
- PolicyPostStateEvent(pCurrentActiveStreamInfo->streamID,STREAM_EVENT_STOP);
- g_array_remove_index(pCurrEndPointPolicy->streamInfo, pCurrEndPointPolicy->streamInfo->len-1);
- break;
- default:
- AFB_ERROR("Unsupported Intterupt Behavior");
- return AHL_POLICY_REJECT;
- break;
-
- }
-
- //Add the playing stream at last
- PolicyAddStream(pCurrEndPointPolicy, pStreamInfo);
- }
- else
- {
- //Higher Priority Stream is playing
- AFB_ERROR("Higher Priority Stream is playing");
- return POLICY_FAIL;
- }
-
-
- }
-
- return POLICY_SUCCESS;
-}
-
-static void PolicySpeedModify(int speed)
-{
-
- for(int i=0; i<g_PolicyCtx.pSinkEndpoints->len; i++)
- {
- EndPointPolicyInfoT * pCurEndpoint = &g_array_index(g_PolicyCtx.pSinkEndpoints,EndPointPolicyInfoT,i);
- if(pCurEndpoint == NULL)
- {
- AFB_WARNING("Sink Endpoint not found");
- return;
- }
-
- //check if active
- if(pCurEndpoint->streamInfo->len > 0 )
- {
- StreamPolicyInfoT * pCurStream = &g_array_index(pCurEndpoint->streamInfo,StreamPolicyInfoT,pCurEndpoint->streamInfo->len-1);
- if(strcasecmp(pCurStream->pAudioRole,AHL_ROLE_ENTERTAINMENT)==0)
- {
- if(speed > 30 && speed < 100)
- {
- int volume =speed;
- PolicySetVolume(pCurEndpoint->endpointID,
- pCurEndpoint->type,
- pCurEndpoint->pHalApiName,
- pCurStream->pAudioRole,
- pCurEndpoint->deviceType,
- volume,
- false);
- }
- }
- }
- }
-}
-
-static int RetrieveAssociatedHALAPIName(EndpointInfoT * io_pEndpointInfo)
-{
- if(g_PolicyCtx.pHALList)
- {
- for(int i=0; i<g_PolicyCtx.pHALList->len; i++)
- {
- HalInfoT *pHalInfo = g_ptr_array_index(g_PolicyCtx.pHALList, i);
- // Retrieve card number (e.g. hw:0)
- int iCardNum = atoi(pHalInfo->pDevID+3);
- if (iCardNum == io_pEndpointInfo->alsaInfo.cardNum) {
- io_pEndpointInfo->gsHALAPIName=strdup(pHalInfo->pAPIName);
- io_pEndpointInfo->gsDisplayName=strdup(pHalInfo->pDisplayName);
- return POLICY_SUCCESS;
- }
- }
- }
-
- io_pEndpointInfo->gsHALAPIName=strdup(AHL_POLICY_UNDEFINED_HALNAME);
- io_pEndpointInfo->gsDisplayName=strdup(AHL_POLICY_UNDEFINED_DISPLAYNAME);
-
- return POLICY_FAIL;
-}
-
-static int GetHALList(void)
-{
- json_object *j_response, *j_query = NULL;
- int err;
- err = afb_service_call_sync("alsacore", "hallist", j_query, &j_response);
- if (err) {
- AFB_ERROR("Could not retrieve list of HAL from ALSA core");
- return POLICY_FAIL;
- }
- AFB_DEBUG("ALSAcore hallist response=%s", json_object_to_json_string(j_response));
-
- // Look through returned list for matching card
- json_object * jRespObj = NULL;
- json_object_object_get_ex(j_response, "response", &jRespObj);
- int iNumHAL = json_object_array_length(jRespObj);
- for ( int i = 0 ; i < iNumHAL; i++)
- {
- json_object * jHAL = json_object_array_get_idx(jRespObj,i);
- char * pDevIDStr = NULL;
- char * pAPIName = NULL;
- char * pShortName = NULL;
-
- int err = wrap_json_unpack(jHAL, "{s:s,s:s,s:s}", "devid", &pDevIDStr,"api", &pAPIName,"shortname",&pShortName);
- if (err) {
- AFB_ERROR("Could not retrieve devid string=%s", json_object_get_string(jHAL));
- return POLICY_FAIL;
- }
-
- HalInfoT *pHalInfo = (HalInfoT*)malloc(sizeof(HalInfoT));
- if(pHalInfo == NULL)
- {
- AFB_ERROR("Unable to allocate memory for HalInfo");
- return POLICY_FAIL;
- }
-
- pHalInfo->pDevID = strdup(pDevIDStr);
- pHalInfo->pAPIName = strdup(pAPIName);
- pHalInfo->pDisplayName = strdup(pShortName);
-
- g_ptr_array_add( g_PolicyCtx.pHALList, pHalInfo);
- }
-
- return POLICY_SUCCESS;
-}
-
-//
-// Policy API Functions
-//
-int Policy_OpenStream(json_object *pPolicyStreamJ)
-{
- StreamInfoT PolicyStream;
- EndpointInfoT EndpointInfo;
- PolicyStream.pEndpointInfo =&EndpointInfo;
-
- int err = PolicyCtxJSONToStream(pPolicyStreamJ, &PolicyStream);
- if(err == AHL_POLICY_UTIL_FAIL)
- {
- return AHL_POLICY_ACCEPT;
- }
-
- // Example rule -> when system is in shutdown or low power mode, no audio stream can be opened (return AHL_POLICY_REJECT)
- // Should receive event from lower level layer
- if(g_PolicyCtx.systemState != SYSTEM_NORMAL)
- {
- return AHL_POLICY_REJECT;
- }
-
- StreamConfigT StreamConfig;
- err = getStreamConfig(PolicyStream.pRoleName, &StreamConfig);
- if(err == POLICY_FAIL)
- {
- return AHL_POLICY_ACCEPT;
- }
-
- if(PolicyStream.pEndpointInfo->deviceURIType != DEVICEURITYPE_NOT_ALSA) {
- err=PolicyGetVolume(PolicyStream.pEndpointInfo->endpointID,
- PolicyStream.pEndpointInfo->type,
- PolicyStream.pEndpointInfo->gsHALAPIName,
- PolicyStream.pEndpointInfo->pRoleName,
- PolicyStream.pEndpointInfo->deviceURIType,
- &PolicyStream.pEndpointInfo->iVolume);
- if(err == POLICY_FAIL)
- {
- return AHL_POLICY_REJECT;
- }
- }
-
- err = PolicyAddEndPoint(&PolicyStream);
- if(err == POLICY_FAIL)
- {
- return AHL_POLICY_REJECT;
- }
- return AHL_POLICY_ACCEPT;
-}
-
-int Policy_CloseStream(json_object *pPolicyStreamJ)
-{
- //TODO remove Endpoint when there is no stream
- StreamInfoT PolicyStream;
- EndpointInfoT EndpointInfo;
- PolicyStream.pEndpointInfo =&EndpointInfo;
- int err = PolicyCtxJSONToStream(pPolicyStreamJ, &PolicyStream);
- if(err == AHL_POLICY_UTIL_FAIL)
- {
- return AHL_POLICY_ACCEPT;
- }
-
- return AHL_POLICY_ACCEPT;
-}
-
-int Policy_SetStreamState(json_object *pPolicyStreamJ)
-{
- //TODO
- // Optional: Mute endpoint before activation, unmute afterwards (after a delay?) to avoid noises
- StreamInfoT PolicyStream;
- EndpointInfoT EndpointInfo;
- PolicyStream.pEndpointInfo =&EndpointInfo;
-
-
- StreamStateT streamState = 0;
- StreamInfoT * pPolicyStream = &PolicyStream;
- int err = PolicyCtxJSONToStream(pPolicyStreamJ, pPolicyStream);
- if(err == AHL_POLICY_UTIL_FAIL)
- {
- return AHL_POLICY_ACCEPT;
- }
-
- json_object *streamStateJ=NULL;
-
- if(!json_object_object_get_ex(pPolicyStreamJ, "arg_stream_state", &streamStateJ))
- {
- return AHL_POLICY_ACCEPT;
- }
- streamState = (StreamStateT)json_object_get_int(streamStateJ);
-
- //Change of state
- if(pPolicyStream->streamState != streamState)
- {
- //seach corresponding endpoint and gather information on it
- EndPointPolicyInfoT *pCurrEndPointPolicy = PolicySearchEndPoint(pPolicyStream->pEndpointInfo->type , pPolicyStream->pEndpointInfo->gsDeviceName);
-
- switch(pPolicyStream->streamState)
- {
- case STREAM_STATE_IDLE:
- switch(streamState)
- {
- case STREAM_STATE_RUNNING:
- err = PolicyIdleRunningTransition(pCurrEndPointPolicy, pPolicyStream);
- if(err)
- {
- return AHL_POLICY_REJECT;
- }
- PolicyPostStateEvent(pPolicyStream->streamID,STREAM_EVENT_START);
- break;
- case STREAM_STATE_PAUSED:
- err = PolicyIdleRunningTransition(pCurrEndPointPolicy, pPolicyStream);
- if(err)
- {
- return AHL_POLICY_REJECT;
- }
- PolicyPostStateEvent(pPolicyStream->streamID,STREAM_EVENT_PAUSE);
- break;
- default:
- return AHL_POLICY_REJECT;
- break;
- }
- break;
- case STREAM_STATE_RUNNING:
- switch(streamState)
- {
- case STREAM_STATE_IDLE:
- err = PolicyRunningIdleTransition(pCurrEndPointPolicy, pPolicyStream);
- if(err)
- {
- return AHL_POLICY_REJECT;
- }
- PolicyPostStateEvent(pPolicyStream->streamID,STREAM_EVENT_STOP);
- break;
- case STREAM_STATE_PAUSED:
- PolicyPostStateEvent(pPolicyStream->streamID,STREAM_EVENT_PAUSE);
- break;
- default:
- return AHL_POLICY_REJECT;
- break;
- }
- break;
- case STREAM_STATE_PAUSED:
- switch(streamState)
- {
- case STREAM_STATE_IDLE:
- err = PolicyRunningIdleTransition(pCurrEndPointPolicy, pPolicyStream);
- if(err)
- {
- return AHL_POLICY_REJECT;
- }
- PolicyPostStateEvent(pPolicyStream->streamID,STREAM_EVENT_STOP);
- break;
- case STREAM_STATE_RUNNING:
- PolicyPostStateEvent(pPolicyStream->streamID,STREAM_EVENT_RESUME);
- break;
- default:
- return AHL_POLICY_REJECT;
- break;
- }
- break;
- default:
- return AHL_POLICY_REJECT;
- break;
- }
- }
- return AHL_POLICY_ACCEPT;
-}
-
-int Policy_SetStreamMute(json_object *pPolicyStreamJ)
-{
- StreamMuteT streamMute = 0;
- StreamInfoT PolicyStream;
- EndpointInfoT EndpointInfo;
- PolicyStream.pEndpointInfo =&EndpointInfo;
- StreamInfoT * pPolicyStream = &PolicyStream;
-
- int err = PolicyCtxJSONToStream(pPolicyStreamJ, pPolicyStream);
- if(err == AHL_POLICY_UTIL_FAIL)
- {
- return AHL_POLICY_ACCEPT;
- }
-
- json_object *streamMuteJ=NULL;
-
- if(!json_object_object_get_ex(pPolicyStreamJ, "mute_state", &streamMuteJ))
- {
- return AHL_POLICY_ACCEPT;
- }
- streamMute = (StreamMuteT)json_object_get_int(streamMuteJ);
-
- if(streamMute != pPolicyStream->streamMute)
- {
- if(streamMute == STREAM_MUTED)
- {
-
- err= PolicySetVolume(pPolicyStream->pEndpointInfo->endpointID,
- pPolicyStream->pEndpointInfo->type,
- pPolicyStream->pEndpointInfo->gsHALAPIName,
- pPolicyStream->pRoleName,
- pPolicyStream->pEndpointInfo->deviceURIType,
- 0,
- true);
- if(err)
- {
- AFB_ERROR("StreamID:%i Set Volume return with errorcode%i",pPolicyStream->streamID, err);
- return AHL_POLICY_REJECT;
- }
- PolicyPostStateEvent(pPolicyStream->streamID,STREAM_EVENT_MUTED);
- }
- else
- {
- err= PolicySetVolume(pPolicyStream->pEndpointInfo->endpointID,
- pPolicyStream->pEndpointInfo->type,
- pPolicyStream->pEndpointInfo->gsHALAPIName,
- pPolicyStream->pRoleName,
- pPolicyStream->pEndpointInfo->deviceURIType,
- pPolicyStream->pEndpointInfo->iVolume,
- true);
- if(err)
- {
- AFB_ERROR("Endpoint:%i Set Volume return with errorcode%i",pPolicyStream->streamID, err);
- return AHL_POLICY_REJECT;
- }
- PolicyPostStateEvent(pPolicyStream->streamID,STREAM_EVENT_UNMUTED);
-
- }
-
- pPolicyStream->streamMute = streamMute;
- }
-
- return AHL_POLICY_ACCEPT;
-}
-
-int Policy_SetVolume(json_object *pPolicyEndpointJ)
-{
- char *volumeStr = NULL;
- EndpointInfoT EndpointInfo;
-
- int err = PolicyCtxJSONToEndpoint(pPolicyEndpointJ, &EndpointInfo);
- if(err == AHL_POLICY_UTIL_FAIL)
- {
- return AHL_POLICY_ACCEPT;
- }
-
- json_object *volumeJ=NULL;
-
- if(!json_object_object_get_ex(pPolicyEndpointJ, "arg_volume", &volumeJ))
- {
- return AHL_POLICY_ACCEPT;
- }
- volumeStr = (char*)json_object_get_string(volumeJ);
-
- // TODO: Parse volume string to support increment/absolute/percent notation (or delegate to action / policy layer to interpret)
- int vol = atoi(volumeStr);
-
- //Set the volume
- err= PolicySetVolume(EndpointInfo.endpointID,
- EndpointInfo.type,
- EndpointInfo.gsHALAPIName,
- EndpointInfo.pRoleName,
- EndpointInfo.deviceURIType,
- vol,
- false);
- if (err)
- {
- AFB_ERROR("Set Volume return with errorcode%i", err);
- return AHL_POLICY_REJECT;
- }
-
- return AHL_POLICY_ACCEPT;
-}
-
-int Policy_SetProperty(json_object *pPolicyEndpointJ)
-{
-
- char *propertyName = NULL;
- EndpointInfoT EndpointInfo;
-
- int err = PolicyCtxJSONToEndpoint(pPolicyEndpointJ, &EndpointInfo);
- if(err == AHL_POLICY_UTIL_FAIL)
- {
- return AHL_POLICY_ACCEPT;
- }
-
- json_object *propertyNameJ=NULL;
-
- if(!json_object_object_get_ex(pPolicyEndpointJ, "arg_property_name", &propertyNameJ))
- {
- return AHL_POLICY_ACCEPT;
- }
- propertyName = (char*)json_object_get_string(propertyNameJ);
-
- json_object *propValueJ;
- if(!json_object_object_get_ex(pPolicyEndpointJ, "arg_property_value", &propValueJ))
- {
- return AHL_POLICY_ACCEPT;
- }
-
- gpointer *key_value=NULL;
-
- key_value = g_hash_table_lookup(EndpointInfo.pPropTable,propertyName);
- if(key_value == NULL)
- {
- AFB_ERROR("Can't find property %s, request will be rejected", propertyName);
- return AHL_POLICY_REJECT;
- }
-
- //Get JsonObjectype
- json_type currentjType = json_object_get_type((json_object*)key_value);
- json_type newjType = json_object_get_type(propValueJ);
-
- //Apply policy on set property if needed here
- //Here we only validate that the type is the same
- if(currentjType != newjType)
- {
- AFB_ERROR("Property Value Type is wrong");
- return AHL_POLICY_REJECT;
- }
-
-
- //Create a new Json Object
- json_object *pEventDataJ = NULL;
- err = wrap_json_pack(&pEventDataJ,"{s:s,s:i,s:i,s:s,s:o,s:s}",
- "event_name", AHL_ENDPOINT_PROPERTY_EVENT,
- "endpoint_id", EndpointInfo.endpointID,
- "endpoint_type", EndpointInfo.type,
- "property_name", propertyName,
- "value",propValueJ,
- "audio_role", EndpointInfo.pRoleName);
- if(err)
- {
- AFB_ERROR("Unable to pack property event");
- return AHL_POLICY_REJECT;
- }
- //Raise Event to update HLB
- audiohlapi_raise_event(pEventDataJ);
-
- return AHL_POLICY_ACCEPT;
-}
-
-int Policy_PostAction(json_object *pPolicyActionJ)
-{
- char * actionName = NULL;
- char * audioRole = NULL;
- char * mediaName = NULL;
- json_object *actionContext = NULL;
-
- int err = wrap_json_unpack(pPolicyActionJ, "{s:s,s:s,s?s,s?o}", "action_name", &actionName,"audio_role",&audioRole,"media_name",&mediaName,"action_context",&actionContext);
- if (err) {
- AFB_ERROR("Unable to pack JSON endpoint, =%s", wrap_json_get_error_string(err));
- return AHL_POLICY_REJECT;
- }
-
- // TODO: Any event with media specified should trigger action on provided rendering services (e.g. Wwise binding, gstreamer file player wrapper, MPDC? simple ALSA player (aplay)?)
- // Example (when the policy is hooked to CAN events). Post audio playback events other than safety during reverse gear engaged declined
- // Example post HMI audio role playback events declined when higher priority streams are active
-
- //In this use case just return the action back to highlevel binding.
-
- json_object *pEventDataJ = NULL;
- err = wrap_json_pack(&pEventDataJ, "{s:s,s:s,s:s,s?s,s?o}", "event_name", AHL_POST_ACTION_EVENT, "action_name", &actionName,"audio_role",&audioRole,"media_name",&mediaName,"action_context",&actionContext);
- if (err) {
- AFB_ERROR("Unable to pack JSON endpoint, =%s", wrap_json_get_error_string(err));
- return AHL_POLICY_REJECT;
- }
- audiohlapi_raise_event(pEventDataJ);
-
- return AHL_POLICY_ACCEPT;
-}
-
-int Policy_Endpoint_Init(json_object *pPolicyEndpointJ)
-{
- EndpointInfoT EndpointInfo;
-
- int err = PolicyCtxJSONToEndpoint(pPolicyEndpointJ, &EndpointInfo);
- if(err == AHL_POLICY_UTIL_FAIL)
- {
- return AHL_POLICY_REJECT;
- }
-
- if (EndpointInfo.deviceURIType != DEVICEURITYPE_NOT_ALSA) {
- // Update Hal Name
- err = RetrieveAssociatedHALAPIName(&EndpointInfo);
- if (err) {
- AFB_ERROR("HAL not found for Device %s", EndpointInfo.gsDeviceName);
- return AHL_POLICY_REJECT;
- }
-
- //Set Init Volume
- StreamConfigT StreamConfig;
- getStreamConfig(EndpointInfo.pRoleName, &StreamConfig);
- err = PolicySetVolume(EndpointInfo.endpointID,
- EndpointInfo.type,
- EndpointInfo.gsHALAPIName,
- EndpointInfo.pRoleName,
- EndpointInfo.deviceURIType,
- StreamConfig.iVolumeInit,
- false);
- if(err) {
- return AHL_POLICY_REJECT;
- }
- }
-
- // Test example
- Add_Endpoint_Property_Int(&EndpointInfo,AHL_PROPERTY_EQ_LOW,3);
- Add_Endpoint_Property_Int(&EndpointInfo,AHL_PROPERTY_EQ_MID,0);
- Add_Endpoint_Property_Int(&EndpointInfo,AHL_PROPERTY_EQ_HIGH,6);
- Add_Endpoint_Property_Int(&EndpointInfo,AHL_PROPERTY_BALANCE,0);
- Add_Endpoint_Property_Int(&EndpointInfo,AHL_PROPERTY_FADE,30);
- Add_Endpoint_Property_String(&EndpointInfo,"preset_name","flat");
-
-
- gpointer *key_value = g_hash_table_lookup(EndpointInfo.pPropTable,AHL_PROPERTY_BALANCE);
- if(key_value == NULL)
- {
- AFB_ERROR("Can't find property %s, request will be rejected", AHL_PROPERTY_BALANCE);
- return AHL_POLICY_REJECT;
- }
-
- //Create a new Json Object
- json_object *pNewPolicyEndpointJ = NULL;
- err = PolicyEndpointStructToJSON(&EndpointInfo, &pNewPolicyEndpointJ);
- if (err == AHL_POLICY_UTIL_FAIL)
- {
- return AHL_POLICY_REJECT;
- }
- json_object *paramJ= json_object_new_string(AHL_ENDPOINT_INIT_EVENT);
- json_object_object_add(pNewPolicyEndpointJ, "event_name", paramJ);
-
- //Raise Event to update HLB
- audiohlapi_raise_event(pNewPolicyEndpointJ);
-
- return AHL_POLICY_ACCEPT; // No errors
-}
-
-int Policy_Init()
-{
- // Initialize Ressources
- g_PolicyCtx.pSourceEndpoints =g_array_new(FALSE,TRUE,sizeof(EndPointPolicyInfoT));
- g_PolicyCtx.pSinkEndpoints = g_array_new(FALSE,TRUE,sizeof(EndPointPolicyInfoT));
- g_PolicyCtx.pHALList = g_ptr_array_new_with_free_func(g_free);
-
- //Get HalList
- GetHALList();
-
- //Set System Normal for now, this should be set by an event
- //TODO: Receive event from low level
- g_PolicyCtx.systemState = SYSTEM_NORMAL;
-
- //register audio backend events
- //This is to simulate can bus, only used for demo
- json_object *queryurl, *responseJ, *eventsJ;
-
- eventsJ = json_object_new_array();
- json_object_array_add(eventsJ, json_object_new_string("audiod_system_event"));
- queryurl = json_object_new_object();
- json_object_object_add(queryurl, "events", eventsJ);
- int returnResult = afb_service_call_sync("audiod", "subscribe", queryurl, &responseJ);
- if (returnResult) {
- AFB_ERROR("Fail subscribing to Audio Backend System events");
- return AHL_POLICY_REJECT;
- }
- return AHL_POLICY_ACCEPT;
-}
-
-void Policy_Term()
-{
- //Free Ressources
- if (g_PolicyCtx.pHALList) {
- g_ptr_array_free(g_PolicyCtx.pHALList,TRUE);
- g_PolicyCtx.pHALList = NULL;
- }
-
- for(int i=0; i<g_PolicyCtx.pSourceEndpoints->len; i++)
- {
- EndPointPolicyInfoT * pCurEndpoint = &g_array_index(g_PolicyCtx.pSourceEndpoints,EndPointPolicyInfoT,i);
- g_array_free(pCurEndpoint->streamInfo,TRUE);
- pCurEndpoint->streamInfo= NULL;
- }
-
- for(int i=0; i<g_PolicyCtx.pSinkEndpoints->len; i++)
- {
- EndPointPolicyInfoT * pCurEndpoint = &g_array_index(g_PolicyCtx.pSinkEndpoints,EndPointPolicyInfoT,i);
- g_array_free(pCurEndpoint->streamInfo,TRUE);
- pCurEndpoint->streamInfo = NULL;
- }
-
- g_array_free(g_PolicyCtx.pSourceEndpoints,TRUE);
- g_PolicyCtx.pSourceEndpoints = NULL;
- g_array_free(g_PolicyCtx.pSinkEndpoints,TRUE);
- g_PolicyCtx.pSinkEndpoints = NULL;
-}
-
-void Policy_OnEvent(const char *evtname, json_object *eventJ)
-{
- AFB_DEBUG("Policy received event %s", evtname);
- char *eventName = NULL;
- json_object *event_parameter = NULL;
- int speed = 0;
-
- if(strcasecmp(evtname, "audiod/system_events")==0)
- {
- int err = wrap_json_unpack(eventJ, "{s:s,s:o}", "event_name", &eventName, "event_parameter", &event_parameter);
- if (err) {
- AFB_WARNING("Invalid arguments, Args not a valid json object query=%s", json_object_get_string(eventJ));
- return;
- }
-
- if(strcasecmp(eventName, "speed")==0)
- {
- AFB_NOTICE("Invalid arguments, Args not a valid json object query=%s", json_object_get_string(event_parameter));
- err = wrap_json_unpack(event_parameter, "{s:i}", "speed_value", &speed);
- if (err) {
- AFB_WARNING("Invalid arguments, Args not a valid json object query=%s", json_object_get_string(event_parameter));
- return;
- }
- //When speed change Modify volume on Endpoint where entertainment change
- PolicySpeedModify(speed);
- }
- }
-}
-
-#endif // AHL_DISCONNECT_POLICY \ No newline at end of file
diff --git a/src/ahl-policy.h b/src/ahl-policy.h
deleted file mode 100644
index d1cf87e..0000000
--- a/src/ahl-policy.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef AHL_POLICY_INCLUDE
-#define AHL_POLICY_INCLUDE
-#include "ahl-policy-utils.h"
-
-#ifndef AHL_DISCONNECT_POLICY
-
-#define MAX_ACTIVE_STREAM_POLICY 30
-#define POLICY_FAIL 1
-#define POLICY_SUCCESS 0
-
-#define AHL_POLICY_UNDEFINED_HALNAME "UNDEFINED"
-#define AHL_POLICY_UNDEFINED_DISPLAYNAME "DeviceNotFound"
-
-typedef enum SystemState {
- SYSTEM_STARTUP = 0, // Startup
- SYSTEM_SHUTDOWN, // ShutDown
- SYSTEM_NORMAL, // Normal
- SYSTEM_LOW_POWER, // Low Power, save mode
- SYSTEM_MAXVALUE // Enum count, keep at the end
-} SystemStateT;
-
-
-typedef struct HalInfo {
- char *pDevID;
- char *pAPIName;
- char *pDisplayName;
-} HalInfoT;
-
-typedef struct StreamConfig {
- int iNbMaxStream;
- int iVolumeInit;
- int iVolumeDuckValue;
-} StreamConfigT;
-
-// Global Policy Local context
-typedef struct PolicyLocalCtx {
- GArray * pSourceEndpoints; // List of Source Endpoint with playing stream or interrupted stream
- GArray * pSinkEndpoints; // List of Sink Endpoint with playing stream or interrupted stream
- GPtrArray * pHALList;
- SystemStateT systemState;
-} PolicyLocalCtxT;
-
-int Policy_Endpoint_Init(json_object *pPolicyEndpointJ);
-int Policy_OpenStream(json_object *pPolicyStreamJ);
-int Policy_CloseStream(json_object *pPolicyStreamJ);
-int Policy_SetStreamState(json_object *pPolicyStreamJ);
-int Policy_SetStreamMute(json_object *pPolicyStreamJ);
-int Policy_PostAction(json_object *pPolicyActionJ);
-int Policy_SetVolume(json_object *pPolicyEndpointJ);
-int Policy_SetProperty(json_object *pPolicyEndpointJ);
-int Policy_Init();
-void Policy_Term();
-void Policy_OnEvent(const char *evtname, json_object *eventJ);
-
-extern void audiohlapi_raise_event(json_object * pEventDataJ);
-#endif // AHL_DISCONNECT_POLICY
-#endif // AHL_POLICY_INCLUDE \ No newline at end of file