aboutsummaryrefslogtreecommitdiffstats
path: root/src/soundmanager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soundmanager.c')
-rw-r--r--src/soundmanager.c1570
1 files changed, 1570 insertions, 0 deletions
diff --git a/src/soundmanager.c b/src/soundmanager.c
new file mode 100644
index 0000000..030b1ab
--- /dev/null
+++ b/src/soundmanager.c
@@ -0,0 +1,1570 @@
+/*
+ * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
+ *
+ * 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
+#define AFB_BINDING_VERSION 2
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <json-c/json.h>
+#include <glib.h>
+#include <pthread.h>
+#include <afb/afb-binding.h>
+#include "sm-error.h"
+#include "sm-helper.h"
+#include "dbus/audio_manager_interface.h"
+
+#define AM_NAME "org.genivi.audiomanager"
+#define AM_CMD_PATH "/org/genivi/audiomanager/commandinterface"
+#define AM_ROUTE_PATH "/org/genivi/audiomanager/routinginterface"
+#define AM_ROUTE_NAME "org.genivi.audiomanager.routinginterface"
+#define SOUND_MANAGER_RETURN_INTERFACE "org.genivi.audiomanager.routing.soundmanager"
+#define SOUND_MANAGER_BUS_NAME "org.genivi.audiomanager.routing.soundmanager"
+#define SOUND_MANAGER_PATH "/org/genivi/audiomanager/routing/soundmanager"
+
+#define COMMAND_EVENT_NUM 10
+#define ROUTING_EVENT_NUM 10
+#define DEFAULT_SINK 1
+#define DEFAULT_SOURCE_CLASS_ID 100
+#define DYNAMIC_DOMAIN_ID 100
+#define DEFAULT_DOMAIN_ID 0
+#define DYNAMIC_SOURCE_ID 0
+#define DEFAULT_VOLUME 100
+#define DEFAULT_AVAILABLES 1
+#define DEFAULT_CONNECTION_FORMAT 2
+#define DEFAULT_INTERRUPT 0
+#define DEFAULT_SOURCE_STATE 2
+#define DS_CONTROLLED 1
+
+#define EVENT_SUBSCRIBE_ERROR_CODE 100
+
+const static struct afb_binding_interface *afbitf;
+static AudiomanagerCommandinterface *am_cmd_bus;
+static AudiomanagerRoutinginterface *am_route_bus;
+static AudiomanagerRoutingSoundmanager *sm_adapter;
+static AudiomanagerRoutingSoundmanagerIface* sm_itf;
+static GDBusConnection* system_conn = NULL;
+
+static GMainLoop *loop = NULL;
+static guint16 SOUNDMANAGER_DOMAIN_ID;
+/* To Do hash table is better */
+struct event{
+ char* name;
+ struct afb_event* event;
+ };
+static struct event command_event_list[COMMAND_EVENT_NUM];
+static struct event routing_event_list[ROUTING_EVENT_NUM];
+
+static struct afb_event ev_new_connection;
+static struct afb_event ev_removed_main_connection;
+static struct afb_event ev_volume_changed;
+static struct afb_event ev_sink_mute_state_changed;
+static struct afb_event ev_main_connection_state_changed;
+
+/* Routing interface event */
+static struct afb_event ev_set_routing_ready;
+static struct afb_event ev_set_routing_rundown;
+static struct afb_event ev_async_connect;
+static struct afb_event ev_async_disconnect;
+static struct afb_event ev_async_set_source_state;
+
+static const char _source_id[] = "sourceID";
+static const char _sink_id[] = "sinkID" ;
+static const char _sink_name[] = "sinkName" ;
+static const char _main_connection_id[] = "mainConnectionID";
+static const char _delay[] = "delay";
+static const char _connection_state[] = "connectionState";
+static const char _connection_id[] = "connectionID";
+static const char _volume[] = "volume";
+static const char _volume_step[] = "volumeStep";
+static const char _mute_state[] = "muteState";
+
+static const char _domain_id[] = "domainID";
+static const char _handle[] = "handle";
+static const char _appname[] = "appname";
+static const char _ramp[] = "ramp";
+static const char _time[] = "time";
+static const char _source_state[] = "sourceState";
+static const char _source_class_id[] = "sourceClassID";
+static const char _sink_class_id[] = "sinkClassID";
+static const char _error[] = "error";
+static const char _sink_data[] = "sinkData";
+static const char _source_data[] = "sourceData";
+static const char _interrupt_state[] = "interruptState";
+static const char _availability[] = "availability";
+static const char _list_volumes[] = "listVolumes";
+static const char _payload[] = "payload";
+static const char _connection_format[] = "connectionFormat";
+/*
+********** Method of Sound Manager (API) **********
+*/
+
+/**
+ * Call "connect" function of Audio Manager.
+ * Getting resource right to output audio stream.
+ * Please input following keys with value into json string object in argument.
+ * In case of using libsoundmanager,
+ * json_object *jobj = json_object_new_object();
+ * json_object_object_add(jobj, "sourceID", json_object_new_int(100));
+ * json_object_object_add(jobj, "sinkID", json_object_new_int(100));
+ * call("connect", jobj);
+ *
+ * The order of arguments is not important.
+ *
+ * #### Parameters
+ * Request key
+ * - sourceID : Source ID getting in return value in registerSource or appname.
+ * - sinkID : Sink ID. This should be more than 0. If no request, defalut value is set by sound manager
+ *
+ * This will be changed in near future because these arguments should be aliased like
+ * sinkID:100 -> sinkID:"speaker"
+ *
+ * This will be modified after integrating
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ * sourceID and sinkID should be more than 0
+ *
+ */
+static void connect (struct afb_req request)
+{
+ AFB_DEBUG("call %s", __FUNCTION__);
+ guint16 source_id = 0, sink_id = 0;
+ guint16 main_connectionID = 0;
+ gint16 ret = -1;
+ REQ_ERROR req_err1 = REQ_FAIL;
+ REQ_ERROR req_err2 = REQ_FAIL;
+ GError *err = NULL;
+
+ req_err1 = get_value_uint16(request, _source_id, &source_id);
+ /* ToDo: Hardware abstraction for application user is needed.
+ select appname(speaker) or sourceID(sinkID). If appname is desired, it changes to sourceID(sinkID) */
+
+ const char* default_sink = afb_req_value (request, _sink_id);
+ if(default_sink != NULL){
+ if((strlen("default") == strlen(default_sink)) &&
+ (0 == strncmp("default", default_sink, strlen("default")))){
+ sink_id = DEFAULT_SINK;
+ req_err2 = REQ_OK;
+ }
+ else{
+ req_err2 = get_value_uint16(request, _sink_id, &sink_id);
+ }
+ }
+
+ if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
+ {
+ AFB_INFO("get_value_uint16 source ret = %d,sink ret = %d", source_id, sink_id);
+ AFB_NOTICE("wrong request");
+ afb_req_fail(request,"wrong-request",NULL);
+ return;
+ }
+
+ audiomanager_commandinterface_call_connect_sync(
+ am_cmd_bus,
+ source_id,
+ sink_id,
+ &ret,
+ &main_connectionID,
+ NULL, &err);
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+
+ /* ToDo Remember appname(key) and tie to sourceID(value) */
+
+ /*create response json object*/
+ struct json_object *res = json_object_new_object();
+ sm_add_object_to_json_object_func(res, __FUNCTION__, 4,
+ "error", ret,
+ _main_connection_id, main_connectionID);
+ char *info = get_response_audiomanager_massage_error(ret);
+ afb_req_success(request, res, info);
+}
+
+/**
+ * Call "disconnect" function of Audio Manager.
+ * Release resource right to output audio stream.
+ *
+ * #### Parameters
+ * Request key
+ * - sourceID : Source ID getting in return value in registerSource or appname.
+ *
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ * sourceID should be more than 0
+ *
+ */
+static void disconnect (struct afb_req request)
+{
+ AFB_DEBUG("call %s", __FUNCTION__);
+
+ guint16 id;
+ gint16 ret;
+ REQ_ERROR req_err;
+ GError *err = NULL;
+
+ req_err = get_value_uint16(request, _main_connection_id, &id);
+ AFB_DEBUG( "requested %s = %d", _main_connection_id, id);
+
+ if(req_err != REQ_OK)
+ {
+ afb_req_fail(request,"wrong-request",afb_req_value (request, _main_connection_id));
+ return;
+ }
+ audiomanager_commandinterface_call_disconnect_sync(
+ am_cmd_bus,
+ id,
+ &ret,
+ NULL, &err);
+ AFB_DEBUG( "ret = %d", ret);
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object_func(res_obj, __FUNCTION__, 2,
+ _error, ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+
+ afb_req_success(request, res_obj, info); /* return error num as status */
+}
+
+/**
+ * Call "setVolume" function of Audio Manager.
+ * Set sink volume.
+ *
+ * #### Parameters
+ * Request key
+ * - volume : volume value. The range of value should be [0-100]
+ * - sinkID : sinkID you would like to change volume at
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ *
+ */
+static void setVolume (struct afb_req request)
+{
+ AFB_DEBUG("call %s", __FUNCTION__);
+
+ guint16 sink_id, vol;
+ gint16 ret;
+ REQ_ERROR req_err1, req_err2;
+ GError *err = NULL;
+
+ req_err1 = get_value_uint16(request, _sink_id, &sink_id);
+ req_err2 = get_value_int16(request, _volume, &vol);
+ AFB_DEBUG( "requested %s = %d, %s = %d",_sink_id, sink_id, _volume, vol);
+ if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
+ {
+ afb_req_fail(request,"wrong-request", NULL);
+ return;
+ }
+
+ audiomanager_commandinterface_call_set_volume_sync(
+ am_cmd_bus,
+ sink_id,
+ vol,
+ &ret,
+ NULL, &err);
+ AFB_DEBUG( "ret = %d", ret);
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object_func(res_obj, __FUNCTION__, 2,
+ "error", ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+
+ afb_req_success(request, res_obj, info); /* return error num as status */
+}
+
+/**
+ * Call "volumeStep" function of Audio Manager.
+ * Change volume step of sink
+ *
+ * #### Parameters
+ * Request key
+ * - sinkID : sinkID you would to change volume step
+ * - volumeStep : Step size of volume
+ *
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ *
+ */
+static void volumeStep (struct afb_req request)
+{
+ AFB_DEBUG("call %s", __FUNCTION__);
+
+ guint16 sink_id, vol;
+ gint16 ret;
+ REQ_ERROR req_err1, req_err2;
+ GError *err = NULL;
+
+ req_err1 = get_value_uint16(request, _sink_id, &sink_id);
+ req_err2 = get_value_int16(request, _volume_step, &vol);
+ AFB_DEBUG( "requested %s = %d, %s = %d",_sink_id, sink_id, _volume_step, vol);
+ if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
+ {
+ afb_req_fail(request,"wrong-request", NULL);
+ return;
+ }
+
+ audiomanager_commandinterface_call_volume_step_sync(
+ am_cmd_bus,
+ sink_id,
+ vol,
+ &ret,
+ NULL, &err);
+ AFB_DEBUG( "ret = %d", ret);
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object_func(res_obj, __FUNCTION__, 2,
+ "error", ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+
+ afb_req_success(request, res_obj, info); /* return error num as status */
+}
+
+/**
+ * Call "volumeStep" function of Audio Manager.
+ * Change volume step of sink
+ *
+ * #### Parameters
+ * Request key
+ * - sinkID : sinkID you would like to change mute state
+ * - muteState : muteState, 1 means mute, 2 means unmute. Or you can designate as "mute" or "unmute"
+ *
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ *
+ */
+static void setSinkMuteState(struct afb_req request)
+{
+ AFB_DEBUG("call %s", __FUNCTION__);
+
+ guint16 sink_id, mute;
+ gint16 ret;
+ REQ_ERROR req_err1, req_err2;
+ GError *err = NULL;
+
+ req_err1 = get_value_uint16(request, _sink_id, &sink_id);
+ req_err2 = get_value_int16(request, _mute_state, &mute);
+ AFB_DEBUG( "requested %s = %d, %s = %d",_sink_id, sink_id, _mute_state, mute);
+ if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
+ {
+ afb_req_fail(request,"wrong-request", NULL);
+ return;
+ }
+
+ audiomanager_commandinterface_call_set_sink_mute_state_sync(
+ am_cmd_bus,
+ sink_id,
+ mute,
+ &ret,
+ NULL, &err);
+ AFB_DEBUG( "ret = %d", ret);
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object_func(res_obj, __FUNCTION__, 2,
+ "error", ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+
+ afb_req_success(request, res_obj, info); /* return error num as status */
+}
+
+/**
+ * Call "getListMainConnections" function of Audio Manager.
+ * Get mainc connection list
+ *
+ * #### Parameters
+ * Request key
+ * None
+ *
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message. Even if there is no connection list,
+ * Sound Manager return success.
+ *
+ * #### Note
+ *
+ */
+static void getListMainConnections(struct afb_req request)
+{
+ AFB_DEBUG("call getListMainConnections");
+ guint16 ret;
+ GVariant* mainConnectionList;
+ GError *err = NULL;
+
+ audiomanager_commandinterface_call_get_list_main_connections_sync(
+ am_cmd_bus,
+ &ret,
+ &mainConnectionList,
+ NULL,
+ &err
+ );
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+
+ /* create response */
+ struct json_object *array_res = json_object_new_array();
+ gsize size = g_variant_n_children(mainConnectionList);
+ AFB_DEBUG("mainConnectionList size is %u",(uint16_t)size);
+ struct json_object *verb_obj = json_object_new_object();
+ sm_add_object_to_json_object_func(verb_obj, __FUNCTION__, 0);
+ json_object_array_add(array_res, verb_obj);
+ if(size <= 0)
+ {
+ AFB_NOTICE( "mainConnectionList size is 0");
+ }
+ else{
+ for(int i = 0; i < size; ++i)
+ {
+ guint16 mcid, srcid, sinkid;
+ gint16 delay, constate;
+ g_variant_get_child(
+ mainConnectionList,i,"(qqqnn)",
+ &mcid, &srcid, &sinkid, &delay, &constate
+ );
+
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object(res_obj,10,
+ _main_connection_id, mcid,
+ _source_id, srcid,
+ _sink_id, sinkid,
+ _delay, delay,
+ _connection_state, constate
+ );
+ json_object_array_add(array_res,res_obj);
+ }
+ }
+ AFB_DEBUG("json object :%s:",json_object_to_json_string(array_res));
+ afb_req_success(request, array_res, "Success to get main connection list");
+}
+
+/**
+ * Call "getListMainSinks" function of Audio Manager.
+ * Get main sink list
+ *
+ * #### Parameters
+ * Request key
+ * None
+ *
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message. Even if there is no connection list,
+ * Sound Manager return success.
+ *
+ * #### Note
+ *
+ */
+static void getListMainSinks(struct afb_req request)
+{
+ AFB_DEBUG("call %s", __FUNCTION__);
+ guint16 ret;
+ GVariant* mainSinkList;
+ GError *err = NULL;
+
+ audiomanager_commandinterface_call_get_list_main_sinks_sync(
+ am_cmd_bus,
+ &ret,
+ &mainSinkList,
+ NULL,
+ &err
+ );
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+
+ /* create response */
+ struct json_object *array_res = json_object_new_array();
+ gsize size = g_variant_n_children(mainSinkList);
+ AFB_DEBUG( "%s size is %u",__FUNCTION__, (uint16_t)size);
+ struct json_object *verb_obj = json_object_new_object();
+ sm_add_object_to_json_object_func(verb_obj, __FUNCTION__, 0);
+ json_object_array_add(array_res, verb_obj);
+ if(size <= 0)
+ {
+ AFB_NOTICE("%s size is 0", __FUNCTION__);
+ }
+ else{
+ /*for(int i = 0; i < size; ++i)
+ {
+ guint16 sinkid, sinkclassid;
+ gchar* sinkname;
+ GVariant* available = g_variant_new("(nn)", -1, -1);
+ gint16 volume, mutestate;
+ g_variant_get_child(
+ mainSinkList,i,"(qs(nn)nnq)",
+ &sinkid, sinkname, &volume, &mutestate, &sinkclassid);
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object(res_obj,2,_sink_id, sinkid);
+ json_object_object_add(res_obj, _sink_name, json_object_new_string(sinkname));
+ sm_add_object_to_json_object(res_obj,6,
+ _volume, volume,
+ _mute_state, mutestate,
+ _sink_class_id, sinkclassid);
+ json_object_array_add(array_res,res_obj);
+ }*/
+ }
+ AFB_DEBUG("json object :%s:",json_object_to_json_string(array_res));
+ //afb_req_success(request, array_res, "Success to get main sink list");
+ afb_req_success(request, array_res, "This is not implemented yet");
+}
+/*
+*
+****** Routing Interface method(API) ***********
+*
+*/
+
+/**
+ * Call "ackConnect" function of Audio Manager.
+ * Return acknowledge of connect against asyncConnect
+ *
+ * #### Parameters
+ * - handle : Handle id when you get on asyncConnect
+ * - connectionID : connection id when you got on connect return value
+ * - error : Error Number you would like to send. If error is 0, it means OK.
+ * If an application has some error, send error number in function then AM release
+ * resources the application got in connect.
+ *
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message. Even if there is no connection list,
+ * Sound Manager return success. So you should check the contents size of return json object
+ *
+ * #### Note
+ *
+ */
+static void ackConnect(struct afb_req request)
+{
+ /* This function will be deprecated */
+ AFB_DEBUG("call %s", __FUNCTION__);
+ guint16 handle, connection_id, error;
+ guint16 ret = 0;
+ REQ_ERROR req_err1, req_err2 , req_err3;
+ GError *err = NULL;
+
+ req_err1 = get_value_uint16(request, _handle, &handle);
+ req_err2 = get_value_uint16(request, _connection_id, &connection_id);
+ req_err3 = get_value_uint16(request, _error, &error);
+
+ if((req_err1 != REQ_OK) || (req_err2 != REQ_OK) || (req_err3 != REQ_OK))
+ {
+ afb_req_fail(request,"wrong-request", NULL);
+ return;
+ }
+ if(connection_id == 0)
+ {
+ afb_req_fail(request,"wrong-request", "connectionID is more than 0");
+ return;
+ }
+
+ audiomanager_routinginterface_call_ack_connect_sync(
+ am_route_bus,
+ handle,
+ connection_id,
+ error,
+ NULL, &err);
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+ /*create response json object*/
+ struct json_object *res = json_object_new_object();
+ sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
+ _error, ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+ afb_req_success(request, res, info);
+}
+
+/**
+ * Call "ackDisconnect" function of Audio Manager.
+ * Return acknowledge of disconnect against asyncDisconnect
+ *
+ * #### Parameters
+ * - handle : Handle id when you get on asyncDisconnect
+ * - connectionID : connection id when you got on connect return value
+ * - error : Error Number you would like to send. If error is 0, it means OK.
+ * If an application has some error, send error number in function then AM
+ *
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message. Even if there is no connection list,
+ * Sound Manager return success. So you should check the contents size of return json object
+ *
+ * #### Note
+ *
+ */
+static void ackDisconnect(struct afb_req request)
+{
+ /* This function will be deprecated */
+ AFB_DEBUG("call %s", __FUNCTION__);
+ guint16 handle, connection_id, error;
+ guint16 ret = 0;
+ REQ_ERROR req_err1, req_err2 , req_err3;
+ GError *err = NULL;
+
+ req_err1 = get_value_uint16(request, _handle, &handle);
+ req_err2 = get_value_uint16(request, _connection_id, &connection_id);
+ req_err3 = get_value_uint16(request, _error, &error);
+
+ if((req_err1 != REQ_OK) || (req_err2 != REQ_OK) || (req_err3 != REQ_OK))
+ {
+ afb_req_fail(request,"wrong-request", "connectionID is more than 0");
+ return;
+ }
+ if(connection_id == 0)
+ {
+ afb_req_fail(request,"wrong-request", "connectionID is more than 0");
+ return;
+ }
+
+ audiomanager_routinginterface_call_ack_disconnect_sync(
+ am_route_bus,
+ handle,
+ connection_id,
+ error,
+ NULL, &err);
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+ /*create response json object*/
+ struct json_object *res = json_object_new_object();
+ sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
+ _error, ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+ afb_req_success(request, res, info);
+}
+
+/**
+ * Call "ackSetSourceState" function of Audio Manager.
+ * Return acknowledge of setSourceState against asyncSetSourceState.
+ *
+ * #### Parameters
+ * - handle : Handle id when you get on asyncSetSourceState
+ * - error : Error Number you would like to send. If error is 0, it means OK.
+ * If an application has some errors, send error number in function
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ * This function is very important for applications to realise the sequence of Audio Management.
+ * An Application which matches with sourceID in the parameter of asyncSetSourceState has to return ack to use this function
+ *
+ */
+static void ackSetSourceState(struct afb_req request)
+{
+ AFB_DEBUG("call %s", __FUNCTION__);
+ guint16 handle, error;
+ guint16 ret = 0;
+ REQ_ERROR req_err1, req_err2;
+ GError *err = NULL;
+
+ req_err1 = get_value_uint16(request, _handle, &handle);
+ req_err2 = get_value_uint16(request, _error, &error);
+
+ if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
+ {
+ AFB_DEBUG("wrong request");
+ afb_req_fail(request,"wrong-request", NULL);
+ return;
+ }
+
+ audiomanager_routinginterface_call_ack_set_source_state_sync(
+ am_route_bus,
+ handle,
+ error,
+ NULL, &err);
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+ /*create response json object*/
+ struct json_object *res = json_object_new_object();
+ sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
+ _error, ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+ afb_req_success(request, res, info);
+}
+
+/**
+ * Call "registerSource" function of Audio Manager.
+ * Register source(application) to Audio Manager Policy Management
+ * Application must call this function on its initialization
+ *
+ * #### Parameters
+ * - appname : Application unieque name
+ * [Option]
+ * It is not necessary to designate following argument, because these are default value is selected y soundmanager
+ * If you would like to set value, please input the following key and value
+ * - sourceClassID :
+ * - sourceState :
+ *
+ * #### Return
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ *
+ */
+static void registerSource(struct afb_req request)
+{
+ AFB_DEBUG("call %s", __FUNCTION__);
+ GError *err = NULL;
+
+
+ guint16 source_id; /* q 0 is for dynamic id*/
+ guint16 domain_id; /* q */
+ guint16 source_class_id; /* q */
+ gint32 source_state; /* i */
+ gint16 volume; /* n */
+
+ if(REQ_OK != get_value_uint16(request, _source_id, &source_id)){
+ source_id = DYNAMIC_SOURCE_ID; /* if 0, dynamic source id will be applied */
+ }
+ REQ_ERROR req_err = get_value_uint16(request, _domain_id, &domain_id);
+ if( req_err != REQ_OK){
+ if(req_err == REQ_FAIL)
+ {
+ domain_id = SOUNDMANAGER_DOMAIN_ID; /* default in AGL */
+ }
+ else{
+ afb_req_fail(request,"wrong-request", "Please input domainID as uint16, otherwise no value is OK");
+ return;
+ }
+ }
+ if(domain_id == 0)
+ {
+ afb_req_fail(request,"wrong-request", "domainID should be more than 0");
+ return;
+ }
+ const gchar* name = afb_req_value(request, _appname); /* s */
+ if(!name)
+ {
+ char* info = "Must specify the name. Please input json arg such as {\"appname\":\"radio\"}";
+ afb_req_fail(request, NULL, info);
+ return;
+ }
+ if(REQ_OK != get_value_uint16(request, _source_class_id, &source_class_id)){
+ source_class_id = DEFAULT_SOURCE_CLASS_ID; /* BASE */
+ }
+ if(REQ_OK != get_value_int32(request, _source_state, &source_state)){
+ source_state = DEFAULT_SOURCE_STATE; /* SS_OFF */
+ }
+ if(REQ_OK != get_value_int16(request, _volume, &volume)){
+ volume = DEFAULT_VOLUME;
+ }
+ gboolean visible = TRUE; /* b */
+ struct availability_s available; /* (ii) */
+ available.availability = DEFAULT_AVAILABLES; /* A_UNKNOWN */
+ available.avalilable_reason = 0; /* AR_UNKNOWN */
+ guint16 interrupt = DEFAULT_INTERRUPT; /* q IS_OFF */
+
+ struct sound_property_s sound_property_list; /* a(in) */
+ sound_property_list.type = 0;
+ sound_property_list.value = 0; /* in reality, this is array of struct */
+
+ gint32 connection_format_list = DEFAULT_CONNECTION_FORMAT; /* ai */
+ struct main_sound_property_s main_property_list; /* a(in) */
+ main_property_list.type = 0;
+ main_property_list.value = 0;
+
+ struct notification_config_s nconf_routing;
+ struct notification_config_s nconf_command; /* a(iin)a(iin) */
+ nconf_routing.type = 0;
+ nconf_routing.status = 0;
+ nconf_routing.parameter = 0;
+
+ nconf_command.type = 0;
+ nconf_command.status = 0;
+ nconf_command.parameter = 0;
+
+ /* acquire data */
+ guint16 acquire_source_id;
+ guint16 ret;
+
+ GVariant* sourceData = create_source_data (source_id, domain_id, name, source_class_id,
+ source_state, volume, visible, available, interrupt,
+ sound_property_list, connection_format_list, main_property_list,
+ nconf_routing, nconf_command);
+
+ GVariant* input = g_variant_ref_sink(sourceData);
+ audiomanager_routinginterface_call_register_source_sync(
+ am_route_bus,
+ input,
+ &acquire_source_id,
+ &ret,
+ NULL, &err);
+ g_variant_unref(input);
+
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+
+ /*create response json object*/
+ struct json_object *res = json_object_new_object();
+ sm_add_object_to_json_object_func(res, __FUNCTION__, 4,
+ _error, ret,
+ _source_id, acquire_source_id);
+ char *info = get_response_audiomanager_massage_error(ret);
+ afb_req_success(request, res, info);
+}
+
+/**
+ * Call "deregisterSource" function of Audio Manager.
+ * Deregister source(application) to Audio Manager Policy Management
+ *
+ * #### Parameters
+ * - sourceID : sourceID returned in resisterSource
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ *
+ */
+static void deregisterSource(struct afb_req request)
+{
+ guint16 source_id;
+ guint16 ret;
+
+ GError *err = NULL;
+
+ if(REQ_OK != get_value_uint16(request, _source_id, &source_id)){
+ afb_req_fail(request, "wrong-request", NULL);
+ }
+ audiomanager_routinginterface_call_deregister_source_sync(
+ am_route_bus,
+ source_id,
+ &ret,
+ NULL, &err
+ );
+ if(err != NULL)
+ {
+ afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
+ return;
+ }
+ /*create response json object*/
+ struct json_object *res = json_object_new_object();
+ sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
+ _error, ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+ afb_req_success(request, res, info);
+
+}
+
+/**
+ * Subscribe event
+ *
+ * #### Parameters
+ * - event : Event name. Event list is written in libsoundmanager.hpp
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ *
+ */
+static void subscribe(struct afb_req request)
+{
+ const char *value = afb_req_value(request, "event");
+ AFB_DEBUG( "value is %s", value);
+ int ret = 0;
+ if(value) {
+ int index = sm_search_event_name_index(value);
+ if(index < 0)
+ {
+ index = sm_search_routing_event_name_index(value);
+ if(index < 0)
+ {
+ AFB_NOTICE( "dedicated event doesn't exist");
+ ret = EVENT_SUBSCRIBE_ERROR_CODE;
+ }
+ else
+ {
+ afb_req_subscribe(request, *routing_event_list[index].event);
+ }
+ }
+ else
+ {
+ afb_req_subscribe(request, *command_event_list[index].event);
+ }
+ }
+ else{
+ AFB_NOTICE( "Please input event name");
+ ret = EVENT_SUBSCRIBE_ERROR_CODE;
+ }
+ /*create response json object*/
+ struct json_object *res = json_object_new_object();
+ sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
+ _error, ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+ afb_req_success(request, res, info);
+}
+
+/**
+ * Unsubscribe event
+ *
+ * #### Parameters
+ * - event : Event name. Event list is written in libsoundmanager.hpp
+ *
+ * #### Rreturn
+ * - error : Error status number. If error is 0, it means the request is accepted, otherwise error message is attached with error code in reply message.
+ *
+ * #### Note
+ *
+ */
+static void unsubscribe(struct afb_req request)
+{
+ const char *value = afb_req_value(request, "event");
+ AFB_DEBUG( "value is %s", value);
+ int ret = 0;
+ if(value) {
+ int index = sm_search_event_name_index(value);
+ if(index < 0)
+ {
+ index = sm_search_routing_event_name_index(value);
+ if(index < 0)
+ {
+ AFB_NOTICE( "dedicated event doesn't exist");
+ ret = EVENT_SUBSCRIBE_ERROR_CODE;
+ }
+ else
+ {
+ afb_req_unsubscribe(request, *routing_event_list[index].event);
+ }
+ }
+ else
+ {
+ afb_req_unsubscribe(request, *command_event_list[index].event);
+ }
+ }
+ else{
+ AFB_NOTICE( "Please input event name");
+ ret = EVENT_SUBSCRIBE_ERROR_CODE;
+ }
+ /*create response json object*/
+ struct json_object *res = json_object_new_object();
+ sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
+ _error, ret);
+ char *info = get_response_audiomanager_massage_error(ret);
+ afb_req_success(request, res, info);
+}
+
+/*
+********** Callback Function invoked by Audio Manager **********
+*/
+
+static void on_new_main_connection(AudiomanagerCommandinterface* interface,
+ GVariant* mainConnection)
+{
+ AFB_DEBUG("%s is called",__FUNCTION__);
+
+ guint16 mcid, srcid, sinkid;
+ gint16 delay, constate;
+ g_variant_get(
+ mainConnection,"(qqqnn)", &mcid, &srcid, &sinkid, &delay, &constate);
+
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object(res_obj,10,
+ _main_connection_id, mcid,
+ _source_id, srcid,
+ _sink_id, sinkid,
+ _delay, delay,
+ _connection_state, constate
+ );
+ AFB_DEBUG("json object :%s:",json_object_to_json_string(res_obj));
+
+ afb_event_push(ev_new_connection, res_obj);
+}
+
+static void on_removed_main_connection(
+ AudiomanagerCommandinterface* interface, guint16 mainConnectionID)
+{
+ AFB_DEBUG("%s is called",__FUNCTION__);
+
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object(res_obj, 2,
+ _main_connection_id, mainConnectionID);
+ afb_event_push(ev_removed_main_connection, res_obj);
+}
+
+static void on_main_connection_state_changed(
+ AudiomanagerCommandinterface* interface, guint16 connectionID, gint16 connectionState)
+{
+ AFB_DEBUG("%s is called",__FUNCTION__);
+
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object(res_obj, 4,
+ _connection_id, connectionID,
+ _connection_state, connectionState);
+ afb_event_push(ev_main_connection_state_changed, res_obj);
+}
+
+static void on_volume_changed(
+ AudiomanagerCommandinterface* interface, guint16 sinkID, gint16 volume)
+{
+ AFB_DEBUG("%s is called",__FUNCTION__);
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object(res_obj, 4,
+ _sink_id, sinkID,
+ _volume, volume);
+ afb_event_push(ev_volume_changed, res_obj);
+}
+
+static void on_sink_mute_state_changed(
+ AudiomanagerCommandinterface* interface, guint16 sinkID, gint16 mute)
+{
+ AFB_DEBUG("%s is called",__FUNCTION__);
+ struct json_object* res_obj = json_object_new_object();
+ sm_add_object_to_json_object(res_obj, 4,
+ _sink_id, sinkID,
+ _mute_state, mute);
+ afb_event_push(ev_sink_mute_state_changed, res_obj);
+}
+
+/*
+********** Callback Function invoked by Audio Manager Routing Interface**********
+*/
+static void on_set_routing_ready(
+ AudiomanagerRoutinginterface* interface)
+{
+ AFB_DEBUG("%s is called",__FUNCTION__);
+ afb_event_push(ev_set_routing_ready, NULL);
+}
+
+static void on_set_routing_rundown(
+ AudiomanagerRoutinginterface* interface)
+{
+ AFB_DEBUG("%s is called",__FUNCTION__);
+ afb_event_push(ev_set_routing_ready, NULL);
+}
+
+
+
+/*
+********** Callback Function invoked by Sound Manager Adapter Interface**********
+*
+* For now, there may be no need to send events to applications from these invocation.
+* Sound Manager just sends ack to Audio Manager in charge of applications.
+*
+*/
+static gboolean on_async_abort(
+ AudiomanagerRoutingSoundmanager *object,
+ GDBusMethodInvocation *invocation,
+ guint16 arg_handle)
+{
+ AFB_DEBUG( "%s called", __FUNCTION__);
+ /* Nothing To Do. If it is better to implement something, I will implement */
+ return TRUE;
+}
+
+static gboolean on_async_connect(
+ AudiomanagerRoutingSoundmanager *object,
+ GDBusMethodInvocation *invocation,
+ guint16 arg_handle,
+ guint16 arg_connectionID,
+ guint16 arg_sourceID,
+ guint16 arg_sinkID,
+ gint arg_connectionFormat)
+{
+ AFB_DEBUG( "%s called", __FUNCTION__);
+
+ struct json_object* ev_obj = json_object_new_object();
+ sm_add_object_to_json_object(ev_obj, 10,
+ _handle, arg_handle,
+ _connection_id, arg_connectionID,
+ _source_id, arg_sourceID,
+ _sink_id, arg_sinkID,
+ _connection_format, arg_connectionFormat);
+ afb_event_push(ev_async_connect, ev_obj);
+
+ /* GError must be initialized here because it is same as grobal errno,
+ so if afb_event_push is failed due to something, number will be changed */
+ GError* err = NULL;
+ audiomanager_routinginterface_call_ack_connect_sync(
+ am_route_bus,
+ arg_handle,
+ arg_connectionID,
+ 0,
+ NULL, &err);
+ if(err != NULL)
+ {
+ AFB_ERROR( "Can't send ack to sound manager adapter %s", __FUNCTION__);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean on_async_disconnect(
+ AudiomanagerRoutingSoundmanager *object,
+ GDBusMethodInvocation *invocation,
+ guint16 arg_handle,
+ guint16 arg_connectionID)
+{
+ AFB_DEBUG( "%s called", __FUNCTION__);
+ struct json_object* ev_obj = json_object_new_object();
+ sm_add_object_to_json_object(ev_obj, 4,
+ _handle, arg_handle,
+ _connection_id, arg_connectionID);
+ afb_event_push(ev_async_disconnect, ev_obj);
+ GError* err = NULL;
+ audiomanager_routinginterface_call_ack_disconnect_sync(
+ am_route_bus,
+ arg_handle,
+ arg_connectionID,
+ 0,
+ NULL, &err);
+ if(err != NULL)
+ {
+ AFB_ERROR( "Can't send ack to sound manager adapter %s", __FUNCTION__);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean on_async_set_sink_volume(
+ AudiomanagerRoutingSoundmanager *object,
+ GDBusMethodInvocation *invocation,
+ guint16 arg_handle,
+ guint16 arg_sinkID,
+ gint16 arg_volume,
+ gint16 arg_ramp,
+ guint16 arg_time)
+{
+ AFB_DEBUG( "%s called", __FUNCTION__);
+ GError* err = NULL;
+ audiomanager_routinginterface_call_ack_set_sink_volume_sync(
+ am_route_bus,
+ arg_handle,
+ arg_volume,
+ 0, NULL, &err);
+ if(err != NULL);{
+ AFB_ERROR( "Can't send ack to sound manager adapter %s", __FUNCTION__);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Event "asyncSetSourceState"
+ * This event is one of the result of Audio Management for connect/disconnect.
+ *
+ * #### Parameters
+ * Request key
+ * - sourceID : sourceID to be commanded by Audio Manager. The contents of command is sourceState
+ * - handle : handle is the dynamic number managed by Audio Manager. Please return this parameter to input ackSetSourceState as is
+ * - sourceState : "on" is the instruction that application can output sound
+ * "off" is the instruction that application sound right will be removed_main_connection
+ * "pause" is the instruction that application must stop output sound because other applications temporaly got sound right and will output sound
+ *
+ * #### Note
+ * This function is very important for applications to realise the sequence of Audio Management.
+ * An Application which matches with sourceID in the parameter of asyncSetSourceState has to return ack to use this function
+ *
+ */
+static gboolean on_async_set_source_state(
+ AudiomanagerRoutingSoundmanager *object,
+ GDBusMethodInvocation *invocation,
+ guint16 arg_handle,
+ guint16 arg_sourceID,
+ gint arg_sourceState)
+{
+ AFB_DEBUG( "%s called", __FUNCTION__);
+ struct json_object* ev_obj = json_object_new_object();
+ char* ss_key = get_source_state_key(arg_sourceState);
+ sm_add_object_to_json_object(ev_obj, 4,
+ _handle, arg_handle,
+ _source_id, arg_sourceID);
+ json_object_object_add(ev_obj, _source_state, json_object_new_string(ss_key));
+ afb_event_push(ev_async_set_source_state, ev_obj);
+ /* Applications must return ackSetSourceState to look sourceID, then Sound Manager doen't return ackSetSourceState */
+ /*audiomanager_routinginterface_call_ack_set_source_state_sync(
+ am_route_bus,
+ arg_handle,
+ NULL,
+ NULL, &err);*/
+}
+
+
+/*
+ * array of the verbs exported to afb-daemon
+ */
+static const struct afb_verb_v2 binding_verbs[]= {
+{ .verb = "connect", .callback = connect, .auth = NULL,
+ .info = "Connect source id and sink id" , .session = AFB_SESSION_NONE},
+{ .verb = "disconnect", .callback = disconnect, .auth = NULL,
+ .info = "Disconnect source id and sink id" , .session = AFB_SESSION_NONE},
+{ .verb = "setVolume", .callback = setVolume, .auth = NULL,
+ .info = "Set volume value" , .session = AFB_SESSION_NONE}, /* it is better to show the range*/
+{ .verb = "volumeStep", .callback = volumeStep, .auth = NULL,
+ .info = "Set volume step range" , .session = AFB_SESSION_NONE},
+{ .verb = "setSinkMuteState", .callback = setSinkMuteState, .auth = NULL,
+ .info = "Set Mute state: 1 means mute, 2 means umute. Others are invalid" ,.session = AFB_SESSION_NONE},
+{ .verb = "getListMainConnections", .callback = getListMainConnections, .auth = NULL,
+ .info = "Get MainConnection List" , .session = AFB_SESSION_NONE},
+{ .verb = "getListMainSinks", .callback = getListMainSinks, .auth = NULL,
+ .info = "Get MainSink List" , .session = AFB_SESSION_NONE},
+{ .verb = "registerSource", .callback = registerSource, .auth = NULL,
+ .info = "Register Application" , .session = AFB_SESSION_NONE},
+{ .verb = "deregisterSource", .callback = deregisterSource, .auth = NULL,
+ .info = "Deregister Application" , .session = AFB_SESSION_NONE},
+{ .verb = "ackConnect", .callback = ackConnect, .auth = NULL,
+ .info = "Acknowledge of asyncConnect" , .session = AFB_SESSION_NONE},
+{ .verb = "ackDisconnect", .callback = ackDisconnect, .auth = NULL,
+ .info = "Acknowledge of asyncConnect" , .session = AFB_SESSION_NONE},
+{ .verb = "ackSetSourceState", .callback = ackSetSourceState, .auth = NULL,
+ .info = "Acknowledge of asyncSetSourceState" , .session = AFB_SESSION_NONE},
+{ .verb = "subscribe", .callback = subscribe, .auth = NULL,
+ .info = "Subscribe event" , .session = AFB_SESSION_NONE},
+{ .verb = "unsubscribe", .callback = unsubscribe, .auth = NULL,
+ .info = "Unsubscribe event" , .session = AFB_SESSION_NONE},
+{ .verb = NULL } /* marker for end of the array */};
+
+static void *dbus_event_loop_run(void *args)
+{
+ loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(loop);
+}
+
+/*
+*
+********** Internal Function used by Sound Manager **********
+*
+*/
+
+static int registerDomain()
+{
+ /* Default Setting of Sound Manager Domain */
+ struct domain_data ddata = {
+ .domainID = DYNAMIC_DOMAIN_ID,
+ .name = "SoundManager",
+ .busname = SOUND_MANAGER_BUS_NAME,
+ .nodename = "soundmanager",
+ .early = FALSE,
+ .complete = TRUE,
+ .state = DS_CONTROLLED
+ };
+ GVariant* domainData = create_domain_data(&ddata);
+ gchar* retBusName = SOUND_MANAGER_BUS_NAME;
+ gchar* retPath = SOUND_MANAGER_PATH;
+ gchar* retInterface = SOUND_MANAGER_RETURN_INTERFACE;
+ guint16 domain_id;
+ GError *err = NULL;
+ guint16 error;
+
+ audiomanager_routinginterface_call_register_domain_sync(
+ am_route_bus,
+ domainData,
+ retBusName,
+ retPath,
+ retInterface,
+ &domain_id, &error,
+ NULL, &err);
+ if(err != NULL){
+ AFB_ERROR( "Failed to call %s", __FUNCTION__);
+ return -1;
+ }
+ if(error != 0)
+ {
+ AFB_ERROR( "Failed to register domain");
+ return error;
+ }
+ SOUNDMANAGER_DOMAIN_ID = domain_id;
+ AFB_NOTICE( "Complete registered domain id:%d",SOUNDMANAGER_DOMAIN_ID);
+ return 0;
+}
+
+static int preinit()
+{
+ int ret;
+ AFB_INFO("Initialize Dbus object");
+ /* Initialize Dbus interface */
+ if(am_cmd_bus || am_route_bus)
+ {
+ AFB_ERROR( "Dbus object to Audio Manager is already created");
+ goto out;
+ }
+ am_cmd_bus = audiomanager_commandinterface_proxy_new_for_bus_sync(
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ AM_NAME,
+ AM_CMD_PATH,
+ NULL,
+ NULL
+ );
+ am_route_bus = audiomanager_routinginterface_proxy_new_for_bus_sync(
+ G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ AM_NAME,
+ AM_ROUTE_PATH,
+ NULL,
+ NULL
+ );
+
+ if(!am_cmd_bus || !am_route_bus)
+ {
+ goto out;
+ }
+
+ AFB_NOTICE( "Finish Initialize");
+ return 0;
+out:
+ AFB_ERROR("Failed to initialize");
+ return -1;
+}
+
+static int create_adapter()
+{
+ GError *error = NULL;
+ gboolean ret;
+ GVariant *value;
+ system_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (error)
+ {
+ g_error_free(error);
+ return -1;
+ }
+ sm_adapter = audiomanager_routing_soundmanager_skeleton_new();
+ sm_itf = AUDIOMANAGER_ROUTING_SOUNDMANAGER_GET_IFACE(sm_adapter);
+
+ /* initialize sound manager adapter */
+ sm_itf->handle_async_abort = on_async_abort;
+ sm_itf->handle_async_connect = on_async_connect;
+ sm_itf->handle_async_disconnect = on_async_disconnect;
+ sm_itf->handle_async_set_sink_volume = on_async_set_sink_volume;
+ sm_itf->handle_async_set_source_state = on_async_set_source_state;
+
+ int sigret = g_signal_connect(sm_adapter, "handle-async-abort", G_CALLBACK(on_async_abort),NULL);
+ sigret = g_signal_connect(sm_adapter, "handle-async-connect", G_CALLBACK(on_async_connect),NULL);
+ sigret = g_signal_connect(sm_adapter, "handle-async-disconnect", G_CALLBACK(on_async_disconnect),NULL);
+ sigret = g_signal_connect(sm_adapter, "handle-async-set-sink-volume", G_CALLBACK(on_async_set_sink_volume),NULL);
+ sigret = g_signal_connect(sm_adapter, "handle-async-set-source-state", G_CALLBACK(on_async_set_source_state),NULL);
+ ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(sm_adapter), system_conn, SOUND_MANAGER_PATH, &error);
+ if (FALSE == ret)
+ {
+ AFB_ERROR( "failed to export");
+ g_error_free(error);
+ g_object_unref(system_conn);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void on_name_lost(GDBusServer *server, GDBusConnection *conn, gpointer data)
+{
+ AFB_WARNING("%s called", __FUNCTION__);
+}
+
+
+static int sm_event_init()
+{
+ AFB_NOTICE("Initialize event receive setting");
+ printf("Initialize event receive setting");
+ int ret;
+ /* Initialize make event */
+ size_t size = sizeof cmd_evlist / sizeof *cmd_evlist;
+
+ /*create event*/
+ /*ToDo Hash table is better. And event should be created in the loop
+ I would like to change */
+ ev_volume_changed = afb_daemon_make_event(cmd_evlist[0]);
+ ev_new_connection = afb_daemon_make_event(cmd_evlist[1]);
+ ev_removed_main_connection = afb_daemon_make_event(cmd_evlist[2]);
+ ev_sink_mute_state_changed = afb_daemon_make_event(cmd_evlist[3]);
+ ev_main_connection_state_changed = afb_daemon_make_event(cmd_evlist[4]);
+ command_event_list[0].name = cmd_evlist[0];
+ command_event_list[0].event = &ev_volume_changed;
+ command_event_list[1].name = cmd_evlist[1];
+ command_event_list[1].event = &ev_new_connection;
+ command_event_list[2].name = cmd_evlist[2];
+ command_event_list[2].event = &ev_removed_main_connection;
+ command_event_list[3].name = cmd_evlist[3];
+ command_event_list[3].event = &ev_sink_mute_state_changed;
+ command_event_list[4].name = cmd_evlist[4];
+ command_event_list[4].event = &ev_main_connection_state_changed;
+
+ /* create routing event */
+ ev_set_routing_ready = afb_daemon_make_event(route_evlist[0]);
+ ev_set_routing_rundown = afb_daemon_make_event(route_evlist[1]);
+ ev_async_connect = afb_daemon_make_event(route_evlist[2]);
+ ev_async_set_source_state = afb_daemon_make_event(route_evlist[3]);
+ ev_async_disconnect = afb_daemon_make_event(route_evlist[4]);
+
+ routing_event_list[0].name = route_evlist[0];
+ routing_event_list[0].event = &ev_set_routing_ready;
+ routing_event_list[1].name = route_evlist[1];
+ routing_event_list[1].event = &ev_set_routing_rundown;
+ routing_event_list[2].name = route_evlist[2];
+ routing_event_list[2].event = &ev_async_connect;
+ routing_event_list[3].name = route_evlist[3];
+ routing_event_list[3].event = &ev_async_set_source_state;
+ routing_event_list[4].name = route_evlist[4];
+ routing_event_list[4].event = &ev_async_disconnect;
+ /*for(size_t i = 0; i < size; ++i)
+ {
+ struct afb_event afbev = afb_daemon_make_event(afbitf->daemon, cmd_evlist[i]));
+ size_t afbev_size = sizeof afbev;
+ size_t key_size = sizeof cmd_evlist[i];
+
+ struct event ev = {cmd_evlist[i],afbev};
+ command_event_list[i] = malloc(key_size + afbev_size);
+ command_event_list[i] = ev;
+ search_result = hsearch(entry, FIND);
+ if(search_result)
+ AFB_NOTICE( "event name is %s", search_result->key);
+ }*/
+
+ /* Initialize dbus event thread */
+ if(!am_cmd_bus || !am_route_bus)
+ {
+ goto ev_init_out;
+ }
+ pthread_t thread_id;
+ ret = pthread_create(&thread_id, NULL, dbus_event_loop_run, NULL);
+ if(ret != 0)
+ {
+ goto ev_init_out;
+ }
+ /* initialize signal from audio manager command interface */
+ g_signal_connect(am_cmd_bus,
+ "volume_changed",
+ G_CALLBACK(on_volume_changed),
+ NULL);
+ g_signal_connect(am_cmd_bus,
+ "new_main_connection",
+ G_CALLBACK(on_new_main_connection),
+ NULL);
+ g_signal_connect(am_cmd_bus,
+ "removed_main_connection",
+ G_CALLBACK(on_removed_main_connection),
+ NULL);
+ g_signal_connect(am_cmd_bus,
+ "sink_mute_state_changed",
+ G_CALLBACK(on_sink_mute_state_changed),
+ NULL);
+ g_signal_connect(am_cmd_bus,
+ "main_connection_state_changed",
+ G_CALLBACK(on_main_connection_state_changed),
+ NULL);
+ g_signal_connect(am_route_bus,
+ "set_routing_ready",
+ G_CALLBACK(on_set_routing_ready),
+ NULL);
+ g_signal_connect(am_route_bus,
+ "set_routing_rundown",
+ G_CALLBACK(on_set_routing_rundown),
+ NULL);
+
+ /* Get soundmanager adapter bus */
+ ret = g_bus_own_name(G_BUS_TYPE_SYSTEM, SOUND_MANAGER_BUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE,
+ NULL,NULL, NULL, NULL, NULL);
+ AFB_DEBUG( "g_bus_own_name ret: %d", ret);
+ ret = create_adapter();
+ if(ret != 0)
+ {
+ goto ev_init_out;
+ }
+ ret = registerDomain();
+
+ if(ret != 0)
+ {
+ AFB_ERROR("registerDomain error: %s",get_response_audiomanager_massage_error(ret));
+ goto ev_init_out;
+ }
+
+ AFB_INFO("Finish Initialize event receive setting");
+ return 0;
+
+ev_init_out:
+ if(loop != NULL)
+ {
+ g_main_loop_unref(loop);
+ }
+ AFB_WARNING( "DBus connection is not created");
+ return -1;
+}
+
+static void onevent(const char *event, struct json_object *object)
+{
+ AFB_NOTICE("on_event %s", event);
+}
+
+const struct afb_binding_v2 afbBindingV2 = {
+ .api = "soundmanager",
+ .specification = NULL,
+ .verbs = binding_verbs,
+ .preinit = preinit,
+ .init = sm_event_init,
+ .onevent = onevent
+};