2 * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <json-c/json.h>
27 #include <afb/afb-binding.h>
29 #include "sm-helper.h"
30 #include "dbus/audio_manager_interface.h"
32 #define AM_NAME "org.genivi.audiomanager"
33 #define AM_CMD_PATH "/org/genivi/audiomanager/commandinterface"
34 #define AM_ROUTE_PATH "/org/genivi/audiomanager/routinginterface"
35 #define AM_ROUTE_NAME "org.genivi.audiomanager.routinginterface"
36 #define SOUND_MANAGER_RETURN_INTERFACE "org.genivi.audiomanager.routing.soundmanager"
37 #define SOUND_MANAGER_BUS_NAME "org.genivi.audiomanager.routing.soundmanager"
38 #define SOUND_MANAGER_PATH "/org/genivi/audiomanager/routing/soundmanager"
40 #define COMMAND_EVENT_NUM 10
41 #define ROUTING_EVENT_NUM 10
42 #define MAX_LEN_STR 100
43 #define DEFAULT_SOURCE_CLASS_ID 100
44 #define DYNAMIC_DOMAIN_ID 100
45 #define DEFAULT_DOMAIN_ID 0
46 #define DYNAMIC_SOURCE_ID 0
47 #define DEFAULT_VOLUME 100
48 #define EVENT_SUBSCRIBE_ERROR_CODE 100
49 #define DEFAULT_AVAILABLES 1
50 #define DEFAULT_CONNECTION_FORMAT 2
51 #define DEFAULT_INTERRUPT 0
52 #define DEFAULT_SOURCE_STATE 2
53 #define DS_CONTROLLED 1
56 const static struct afb_binding_interface *afbitf;
57 static AudiomanagerCommandinterface *am_cmd_bus;
58 static AudiomanagerRoutinginterface *am_route_bus;
59 static AudiomanagerRoutingSoundmanager *sm_adapter;
60 static AudiomanagerRoutingSoundmanagerIface* sm_itf;
61 static GDBusConnection* system_conn = NULL;
63 static GMainLoop *loop = NULL;
64 static guint16 SOUNDMANAGER_DOMAIN_ID;
65 /* To Do hash table is better */
68 struct afb_event* event;
70 static struct event command_event_list[COMMAND_EVENT_NUM];
71 static struct event routing_event_list[ROUTING_EVENT_NUM];
73 static struct afb_event ev_new_connection;
74 static struct afb_event ev_removed_main_connection;
75 static struct afb_event ev_volume_changed;
76 static struct afb_event ev_sink_mute_state_changed;
77 static struct afb_event ev_main_connection_state_changed;
79 /* Routing interface event */
80 static struct afb_event ev_set_routing_ready;
81 static struct afb_event ev_set_routing_rundown;
82 static struct afb_event ev_async_connect;
83 static struct afb_event ev_async_disconnect;
84 static struct afb_event ev_async_set_source_state;
86 static const char _source_id[] = "sourceID";
87 static const char _sink_id[] = "sinkID" ;
88 static const char _main_connection_id[] = "mainConnectionID";
89 static const char _delay[] = "delay";
90 static const char _connection_state[] = "connectionState";
91 static const char _connection_id[] = "connectionID";
92 static const char _volume[] = "volume";
93 static const char _volume_step[] = "volumeStep";
94 static const char _mute_state[] = "muteState";
96 static const char _domain_id[] = "domainID";
97 static const char _handle[] = "handle";
98 static const char _appname[] = "appname";
99 static const char _ramp[] = "ramp";
100 static const char _time[] = "time";
101 static const char _source_state[] = "sourceState";
102 static const char _source_class_id[] = "sourceClassID";
103 static const char _error[] = "error";
104 static const char _sink_data[] = "sinkData";
105 static const char _source_data[] = "sourceData";
106 static const char _interrupt_state[] = "interruptState";
107 static const char _availability[] = "availability";
108 static const char _list_volumes[] = "listVolumes";
109 static const char _payload[] = "payload";
110 static const char _connection_format[] = "connectionFormat";
112 ********** Method of Sound Manager (API) **********
116 * Call "connect" function of Audio Manager.
117 * Getting resource right to output audio stream.
118 * Please input following keys with value into json string object in argument.
119 * In case of using libsoundmanager,
120 * json_object *jobj = json_object_new_object();
121 * json_object_object_add(jobj, "sourceID", json_object_new_int(100));
122 * json_object_object_add(jobj, "sinkID", json_object_new_int(100));
123 * call("connect", jobj);
125 * The order of arguments is not important.
129 * - sourceID : Source ID getting in return value in registerSource or appname.
130 * - sinkID : Sink ID. This should be more than 0. If no request, defalut value is set by sound manager
132 * This will be changed in near future because these arguments should be aliased like
133 * sinkID:100 -> sinkID:"speaker"
135 * This will be modified after integrating
138 * - 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.
141 * sourceID and sinkID should be more than 0
144 static void connect (struct afb_req request)
146 NOTICE(afbitf,"call connect");
147 guint16 source_id, sink_id;
148 guint16 main_connectionID = 0;
150 REQ_ERROR req_err1, req_err2;
152 /* ToDo select appname(speaker) or sourceID(sinkID). If appname is desired, it changes to sourceID(sinkID) */
154 req_err1 = get_value_uint16(request, _source_id, &source_id);
155 req_err2 = get_value_uint16(request, _sink_id, &sink_id);
157 if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
159 NOTICE(afbitf, "get_value_uint16 source ret = %d,sink ret = %d", source_id, sink_id);
160 NOTICE(afbitf,"wrong request");
161 afb_req_fail(request,"wrong-request",NULL);
165 audiomanager_commandinterface_call_connect_sync(
175 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
179 /* ToDo Remember appname(key) and tie to sourceID(value) */
181 /*create response json object*/
182 struct json_object *res = json_object_new_object();
183 sm_add_object_to_json_object_func(res, __FUNCTION__, 4,
185 _main_connection_id, main_connectionID);
186 char *info = get_response_audiomanager_massage_error(ret);
187 afb_req_success(request, res, info);
191 * Call "disconnect" function of Audio Manager.
192 * Release resource right to output audio stream.
196 * - sourceID : Source ID getting in return value in registerSource or appname.
200 * - 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.
203 * sourceID should be more than 0
206 static void disconnect (struct afb_req request)
208 NOTICE(afbitf,"call disconnect");
215 req_err = get_value_uint16(request, _main_connection_id, &id);
216 NOTICE(afbitf, "requested %s = %d", _main_connection_id, id);
218 if(req_err != REQ_OK)
220 afb_req_fail(request,"wrong-request",afb_req_value (request, _main_connection_id));
223 audiomanager_commandinterface_call_disconnect_sync(
228 NOTICE(afbitf, "ret = %d", ret);
232 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
236 struct json_object* res_obj = json_object_new_object();
237 sm_add_object_to_json_object_func(res_obj, __FUNCTION__, 2,
239 char *info = get_response_audiomanager_massage_error(ret);
241 afb_req_success(request, res_obj, info); /* return error num as status */
245 * Call "setVolume" function of Audio Manager.
250 * - volume : volume value. The range of value should be [0-100]
251 * - sinkID : sinkID you would like to change volume at
254 * - 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.
259 static void setVolume (struct afb_req request)
261 NOTICE(afbitf,"call setVolume");
263 guint16 sink_id, vol;
265 REQ_ERROR req_err1, req_err2;
268 req_err1 = get_value_uint16(request, _sink_id, &sink_id);
269 req_err2 = get_value_int16(request, _volume, &vol);
270 NOTICE(afbitf, "requested %s = %d, %s = %d",_sink_id, sink_id, _volume, vol);
271 if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
273 afb_req_fail(request,"wrong-request", NULL);
277 audiomanager_commandinterface_call_set_volume_sync(
283 NOTICE(afbitf, "ret = %d", ret);
287 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
291 struct json_object* res_obj = json_object_new_object();
292 sm_add_object_to_json_object_func(res_obj, __FUNCTION__, 2,
294 char *info = get_response_audiomanager_massage_error(ret);
296 afb_req_success(request, res_obj, info); /* return error num as status */
300 * Call "volumeStep" function of Audio Manager.
301 * Change volume step of sink
305 * - sinkID : sinkID you would to change volume step
306 * - volumeStep : Step size of volume
310 * - 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.
315 static void volumeStep (struct afb_req request)
317 NOTICE(afbitf,"call volumeStep");
319 guint16 sink_id, vol;
321 REQ_ERROR req_err1, req_err2;
324 req_err1 = get_value_uint16(request, _sink_id, &sink_id);
325 req_err2 = get_value_int16(request, _volume_step, &vol);
326 NOTICE(afbitf, "requested %s = %d, %s = %d",_sink_id, sink_id, _volume_step, vol);
327 if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
329 afb_req_fail(request,"wrong-request", NULL);
333 audiomanager_commandinterface_call_volume_step_sync(
339 NOTICE(afbitf, "ret = %d", ret);
343 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
347 struct json_object* res_obj = json_object_new_object();
348 sm_add_object_to_json_object_func(res_obj, __FUNCTION__, 2,
350 char *info = get_response_audiomanager_massage_error(ret);
352 afb_req_success(request, res_obj, info); /* return error num as status */
356 * Call "volumeStep" function of Audio Manager.
357 * Change volume step of sink
361 * - sinkID : sinkID you would like to change mute state
362 * - muteState : muteState, 1 means mute, 2 means unmute. Or you can designate as "mute" or "unmute"
366 * - 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.
371 static void setSinkMuteState(struct afb_req request)
373 NOTICE(afbitf,"call setSinkMuteStete");
375 guint16 sink_id, mute;
377 REQ_ERROR req_err1, req_err2;
380 req_err1 = get_value_uint16(request, _sink_id, &sink_id);
381 req_err2 = get_value_int16(request, _mute_state, &mute);
382 NOTICE(afbitf, "requested %s = %d, %s = %d",_sink_id, sink_id, _mute_state, mute);
383 if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
385 afb_req_fail(request,"wrong-request", NULL);
389 audiomanager_commandinterface_call_set_sink_mute_state_sync(
395 NOTICE(afbitf, "ret = %d", ret);
399 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
403 struct json_object* res_obj = json_object_new_object();
404 sm_add_object_to_json_object_func(res_obj, __FUNCTION__, 2,
406 char *info = get_response_audiomanager_massage_error(ret);
408 afb_req_success(request, res_obj, info); /* return error num as status */
412 * Call "getListMainConnections" function of Audio Manager.
413 * Change volume step of sink
421 * - 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,
422 * Sound Manager return success. So you should check the contents size of return json object
427 static void getListMainConnections(struct afb_req request)
429 NOTICE(afbitf,"call getListMainConnections");
431 GVariant* mainConnectionList;
434 audiomanager_commandinterface_call_get_list_main_connections_sync(
441 NOTICE(afbitf,"ret = %d, mainConnectionList pointer = %p", ret, &mainConnectionList);
445 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
449 /* create response */
450 struct json_object *array_res = json_object_new_array();
451 gsize size = g_variant_n_children(mainConnectionList);
452 NOTICE(afbitf, "mainConnectionList size is %u",(uint16_t)size);
453 struct json_object *verb_obj = json_object_new_object();
454 sm_add_object_to_json_object_func(verb_obj, __FUNCTION__, 0);
455 json_object_array_add(array_res, verb_obj);
458 NOTICE(afbitf, "mainConnectionList size is 0");
461 for(int i = 0; i < size; ++i)
463 guint16 mcid, srcid, sinkid;
464 gint16 delay, constate;
466 mainConnectionList,i,"(qqqnn)",
467 &mcid, &srcid, &sinkid, &delay, &constate
470 struct json_object* res_obj = json_object_new_object();
471 sm_add_object_to_json_object(res_obj,10,
472 _main_connection_id, mcid,
476 _connection_state, constate
478 json_object_array_add(array_res,res_obj);
481 NOTICE(afbitf,"json object :%s:",json_object_to_json_string(array_res));
482 afb_req_success(request, array_res, "Success to get main connection list");
487 ****** Routing Interface method(API) ***********
492 * Call "ackConnect" function of Audio Manager.
493 * Return acknowledge of connect against asyncConnect
496 * - handle : Handle id when you get on asyncConnect
497 * - connectionID : connection id when you got on connect return value
498 * - error : Error Number you would like to send. If error is 0, it means OK.
499 * If an application has some error, send error number in function then AM release
500 * resources the application got in connect.
504 * - 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,
505 * Sound Manager return success. So you should check the contents size of return json object
510 static void ackConnect(struct afb_req request)
512 /* This function will be deprecated */
513 NOTICE(afbitf,"call %s", __FUNCTION__);
514 guint16 handle, connection_id, error;
516 REQ_ERROR req_err1, req_err2 , req_err3;
519 req_err1 = get_value_uint16(request, _handle, &handle);
520 req_err2 = get_value_uint16(request, _connection_id, &connection_id);
521 req_err3 = get_value_uint16(request, _error, &error);
523 if((req_err1 != REQ_OK) || (req_err2 != REQ_OK) || (req_err3 != REQ_OK))
525 afb_req_fail(request,"wrong-request", NULL);
528 if(connection_id == 0)
530 afb_req_fail(request,"wrong-request", "connectionID is more than 0");
534 audiomanager_routinginterface_call_ack_connect_sync(
543 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
546 /*create response json object*/
547 struct json_object *res = json_object_new_object();
548 sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
550 char *info = get_response_audiomanager_massage_error(ret);
551 afb_req_success(request, res, info);
555 * Call "ackDisconnect" function of Audio Manager.
556 * Return acknowledge of disconnect against asyncDisconnect
559 * - handle : Handle id when you get on asyncDisconnect
560 * - connectionID : connection id when you got on connect return value
561 * - error : Error Number you would like to send. If error is 0, it means OK.
562 * If an application has some error, send error number in function then AM
566 * - 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,
567 * Sound Manager return success. So you should check the contents size of return json object
572 static void ackDisconnect(struct afb_req request)
574 /* This function will be deprecated */
575 NOTICE(afbitf,"call %s", __FUNCTION__);
576 guint16 handle, connection_id, error;
578 REQ_ERROR req_err1, req_err2 , req_err3;
581 req_err1 = get_value_uint16(request, _handle, &handle);
582 req_err2 = get_value_uint16(request, _connection_id, &connection_id);
583 req_err3 = get_value_uint16(request, _error, &error);
585 if((req_err1 != REQ_OK) || (req_err2 != REQ_OK) || (req_err3 != REQ_OK))
587 afb_req_fail(request,"wrong-request", "connectionID is more than 0");
590 if(connection_id == 0)
592 afb_req_fail(request,"wrong-request", "connectionID is more than 0");
596 audiomanager_routinginterface_call_ack_disconnect_sync(
605 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
608 /*create response json object*/
609 struct json_object *res = json_object_new_object();
610 sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
612 char *info = get_response_audiomanager_massage_error(ret);
613 afb_req_success(request, res, info);
617 * Call "ackSetSourceState" function of Audio Manager.
618 * Return acknowledge of setSourceState against asyncSetSourceState.
621 * - handle : Handle id when you get on asyncSetSourceState
622 * - error : Error Number you would like to send. If error is 0, it means OK.
623 * If an application has some errors, send error number in function
626 * - 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.
629 * This function is very important for applications to realise the sequence of Audio Management.
630 * An Application which matches with sourceID in the parameter of asyncSetSourceState has to return ack to use this function
633 static void ackSetSourceState(struct afb_req request)
635 NOTICE(afbitf,"call %s", __FUNCTION__);
636 guint16 handle, error;
638 REQ_ERROR req_err1, req_err2;
641 req_err1 = get_value_uint16(request, _handle, &handle);
642 req_err2 = get_value_uint16(request, _error, &error);
644 if((req_err1 != REQ_OK) || (req_err2 != REQ_OK))
646 NOTICE(afbitf,"wrong request");
647 afb_req_fail(request,"wrong-request", NULL);
651 audiomanager_routinginterface_call_ack_set_source_state_sync(
659 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
662 /*create response json object*/
663 struct json_object *res = json_object_new_object();
664 sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
666 char *info = get_response_audiomanager_massage_error(ret);
667 afb_req_success(request, res, info);
671 * Call "registerSource" function of Audio Manager.
672 * Register source(application) to Audio Manager Policy Management
673 * Application must call this function on its initialization
676 * - appname : Application unieque name
678 * It is not necessary to designate following argument, because these are default value is selected y soundmanager
679 * If you would like to set value, please input the following key and value
684 * - 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.
689 static void registerSource(struct afb_req request)
691 NOTICE(afbitf,"call %s", __FUNCTION__);
695 guint16 source_id; /* q 0 is for dynamic id*/
696 guint16 domain_id; /* q */
697 guint16 source_class_id; /* q */
698 gint32 source_state; /* i */
699 gint16 volume; /* n */
701 if(REQ_OK != get_value_uint16(request, _source_id, &source_id)){
702 source_id = DYNAMIC_SOURCE_ID; /* if 0, dynamic source id will be applied */
704 REQ_ERROR req_err = get_value_uint16(request, _domain_id, &domain_id);
705 if( req_err != REQ_OK){
706 if(req_err == REQ_FAIL)
708 domain_id = SOUNDMANAGER_DOMAIN_ID; /* default in AGL */
711 afb_req_fail(request,"wrong-request", "Please input domainID as uint16, otherwise no value is OK");
717 afb_req_fail(request,"wrong-request", "domainID should be more than 0");
720 const gchar* name = afb_req_value(request, _appname); /* s */
723 char* info = "Must specify the name. Please input json arg such as {\"appname\":\"radio\"}";
724 afb_req_fail(request, NULL, info);
727 if(REQ_OK != get_value_uint16(request, _source_class_id, &source_class_id)){
728 source_class_id = DEFAULT_SOURCE_CLASS_ID; /* BASE */
730 if(REQ_OK != get_value_int32(request, _source_state, &source_state)){
731 source_state = DEFAULT_SOURCE_STATE; /* SS_OFF */
733 if(REQ_OK != get_value_int16(request, _volume, &volume)){
734 volume = DEFAULT_VOLUME;
736 gboolean visible = TRUE; /* b */
737 struct availability_s available; /* (ii) */
738 available.availability = DEFAULT_AVAILABLES; /* A_UNKNOWN */
739 available.avalilable_reason = 0; /* AR_UNKNOWN */
740 guint16 interrupt = DEFAULT_INTERRUPT; /* q IS_OFF */
742 struct sound_property_s sound_property_list; /* a(in) */
743 sound_property_list.type = 0;
744 sound_property_list.value = 0; /* in reality, this is array of struct */
746 gint32 connection_format_list = DEFAULT_CONNECTION_FORMAT; /* ai */
747 struct main_sound_property_s main_property_list; /* a(in) */
748 main_property_list.type = 0;
749 main_property_list.value = 0;
751 struct notification_config_s nconf_routing;
752 struct notification_config_s nconf_command; /* a(iin)a(iin) */
753 nconf_routing.type = 0;
754 nconf_routing.status = 0;
755 nconf_routing.parameter = 0;
757 nconf_command.type = 0;
758 nconf_command.status = 0;
759 nconf_command.parameter = 0;
762 guint16 acquire_source_id;
765 GVariant* sourceData = create_source_data (source_id, domain_id, name, source_class_id,
766 source_state, volume, visible, available, interrupt,
767 sound_property_list, connection_format_list, main_property_list,
768 nconf_routing, nconf_command, afbitf);
770 GVariant* input = g_variant_ref_sink(sourceData);
771 audiomanager_routinginterface_call_register_source_sync(
777 g_variant_unref(input);
781 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
785 /*create response json object*/
786 struct json_object *res = json_object_new_object();
787 sm_add_object_to_json_object_func(res, __FUNCTION__, 4,
789 _source_id, acquire_source_id);
790 char *info = get_response_audiomanager_massage_error(ret);
791 afb_req_success(request, res, info);
795 * Call "deregisterSource" function of Audio Manager.
796 * Deregister source(application) to Audio Manager Policy Management
799 * - sourceID : sourceID returned in resisterSource
802 * - 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.
807 static void deregisterSource(struct afb_req request)
814 if(REQ_OK != get_value_uint16(request, _source_id, &source_id)){
815 afb_req_fail(request, "wrong-request", NULL);
817 audiomanager_routinginterface_call_deregister_source_sync(
825 afb_req_fail_f(request, "failed", "Unable to call %s", __FUNCTION__);
828 /*create response json object*/
829 struct json_object *res = json_object_new_object();
830 sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
832 char *info = get_response_audiomanager_massage_error(ret);
833 afb_req_success(request, res, info);
841 * - event : Event name. Event list is written in libsoundmanager.hpp
844 * - 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.
849 static void subscribe(struct afb_req request)
851 const char *value = afb_req_value(request, "event");
852 NOTICE(afbitf, "value is %s", value);
855 int index = sm_search_event_name_index(value);
858 index = sm_search_routing_event_name_index(value);
861 NOTICE(afbitf, "dedicated event doesn't exist");
862 ret = EVENT_SUBSCRIBE_ERROR_CODE;
866 afb_req_subscribe(request, *routing_event_list[index].event);
871 afb_req_subscribe(request, *command_event_list[index].event);
875 NOTICE(afbitf, "Please input event name");
876 ret = EVENT_SUBSCRIBE_ERROR_CODE;
878 /*create response json object*/
879 struct json_object *res = json_object_new_object();
880 sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
882 char *info = get_response_audiomanager_massage_error(ret);
883 afb_req_success(request, res, info);
890 * - event : Event name. Event list is written in libsoundmanager.hpp
893 * - 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.
898 static void unsubscribe(struct afb_req request)
900 const char *value = afb_req_value(request, "event");
901 NOTICE(afbitf, "value is %s", value);
904 int index = sm_search_event_name_index(value);
907 index = sm_search_routing_event_name_index(value);
910 NOTICE(afbitf, "dedicated event doesn't exist");
911 ret = EVENT_SUBSCRIBE_ERROR_CODE;
915 afb_req_unsubscribe(request, *routing_event_list[index].event);
920 afb_req_unsubscribe(request, *command_event_list[index].event);
924 NOTICE(afbitf, "Please input event name");
925 ret = EVENT_SUBSCRIBE_ERROR_CODE;
927 /*create response json object*/
928 struct json_object *res = json_object_new_object();
929 sm_add_object_to_json_object_func(res, __FUNCTION__, 2,
931 char *info = get_response_audiomanager_massage_error(ret);
932 afb_req_success(request, res, info);
936 ********** Callback Function invoked by Audio Manager **********
939 static void on_new_main_connection(AudiomanagerCommandinterface* interface,
940 GVariant* mainConnection)
942 NOTICE(afbitf,"%s is called",__FUNCTION__);
944 guint16 mcid, srcid, sinkid;
945 gint16 delay, constate;
947 mainConnection,"(qqqnn)", &mcid, &srcid, &sinkid, &delay, &constate);
949 struct json_object* res_obj = json_object_new_object();
950 sm_add_object_to_json_object(res_obj,10,
951 _main_connection_id, mcid,
955 _connection_state, constate
957 NOTICE(afbitf,"json object :%s:",json_object_to_json_string(res_obj));
959 afb_event_push(ev_new_connection, res_obj);
962 static void on_removed_main_connection(
963 AudiomanagerCommandinterface* interface, guint16 mainConnectionID)
965 NOTICE(afbitf,"%s is called",__FUNCTION__);
967 struct json_object* res_obj = json_object_new_object();
968 sm_add_object_to_json_object(res_obj, 2,
969 _main_connection_id, mainConnectionID);
970 afb_event_push(ev_removed_main_connection, res_obj);
973 static void on_main_connection_state_changed(
974 AudiomanagerCommandinterface* interface, guint16 connectionID, gint16 connectionState)
976 NOTICE(afbitf,"%s is called",__FUNCTION__);
978 struct json_object* res_obj = json_object_new_object();
979 sm_add_object_to_json_object(res_obj, 4,
980 _connection_id, connectionID,
981 _connection_state, connectionState);
982 afb_event_push(ev_main_connection_state_changed, res_obj);
985 static void on_volume_changed(
986 AudiomanagerCommandinterface* interface, guint16 sinkID, gint16 volume)
988 NOTICE(afbitf,"%s is called",__FUNCTION__);
989 struct json_object* res_obj = json_object_new_object();
990 sm_add_object_to_json_object(res_obj, 4,
993 afb_event_push(ev_volume_changed, res_obj);
996 static void on_sink_mute_state_changed(
997 AudiomanagerCommandinterface* interface, guint16 sinkID, gint16 mute)
999 NOTICE(afbitf,"%s is called",__FUNCTION__);
1000 struct json_object* res_obj = json_object_new_object();
1001 sm_add_object_to_json_object(res_obj, 4,
1004 afb_event_push(ev_sink_mute_state_changed, res_obj);
1008 ********** Callback Function invoked by Audio Manager Routing Interface**********
1010 static void on_set_routing_ready(
1011 AudiomanagerRoutinginterface* interface)
1013 NOTICE(afbitf,"%s is called",__FUNCTION__);
1014 afb_event_push(ev_set_routing_ready, NULL);
1017 static void on_set_routing_rundown(
1018 AudiomanagerRoutinginterface* interface)
1020 NOTICE(afbitf,"%s is called",__FUNCTION__);
1021 afb_event_push(ev_set_routing_ready, NULL);
1027 ********** Callback Function invoked by Sound Manager Adapter Interface**********
1029 * For now, there may be no need to send events to applications from these invocation.
1030 * Sound Manager just sends ack to Audio Manager in charge of applications.
1033 static gboolean on_async_abort(
1034 AudiomanagerRoutingSoundmanager *object,
1035 GDBusMethodInvocation *invocation,
1038 NOTICE(afbitf, "%s called", __FUNCTION__);
1039 /* Nothing To Do. If it is better to implement something, I will implement */
1043 static gboolean on_async_connect(
1044 AudiomanagerRoutingSoundmanager *object,
1045 GDBusMethodInvocation *invocation,
1047 guint16 arg_connectionID,
1048 guint16 arg_sourceID,
1050 gint arg_connectionFormat)
1052 NOTICE(afbitf, "%s called", __FUNCTION__);
1054 struct json_object* ev_obj = json_object_new_object();
1055 sm_add_object_to_json_object(ev_obj, 10,
1056 _handle, arg_handle,
1057 _connection_id, arg_connectionID,
1058 _source_id, arg_sourceID,
1059 _sink_id, arg_sinkID,
1060 _connection_format, arg_connectionFormat);
1061 afb_event_push(ev_async_connect, ev_obj);
1063 /* GError must be initialized here because it is same as grobal errno,
1064 so if afb_event_push is failed due to something, number will be changed */
1066 audiomanager_routinginterface_call_ack_connect_sync(
1074 NOTICE(afbitf, "Can't send ack to sound manager adapter %s", __FUNCTION__);
1080 static gboolean on_async_disconnect(
1081 AudiomanagerRoutingSoundmanager *object,
1082 GDBusMethodInvocation *invocation,
1084 guint16 arg_connectionID)
1086 NOTICE(afbitf, "%s called", __FUNCTION__);
1087 struct json_object* ev_obj = json_object_new_object();
1088 sm_add_object_to_json_object(ev_obj, 4,
1089 _handle, arg_handle,
1090 _connection_id, arg_connectionID);
1091 afb_event_push(ev_async_disconnect, ev_obj);
1093 audiomanager_routinginterface_call_ack_disconnect_sync(
1101 NOTICE(afbitf, "Can't send ack to sound manager adapter %s", __FUNCTION__);
1107 static gboolean on_async_set_sink_volume(
1108 AudiomanagerRoutingSoundmanager *object,
1109 GDBusMethodInvocation *invocation,
1116 NOTICE(afbitf, "%s called", __FUNCTION__);
1118 audiomanager_routinginterface_call_ack_set_sink_volume_sync(
1124 NOTICE(afbitf, "Can't send ack to sound manager adapter %s", __FUNCTION__);
1131 * Event "asyncSetSourceState"
1132 * This event is the result of Audio Management.
1136 * - sourceID : sourceID to be commanded by Audio Manager. The contents of command is sourceState
1137 * - handle : handle is the dynamic number managed by Audio Manager. Please return this parameter to input ackSetSourceState as is
1138 * - sourceState : "on" is the instruction that application can output sound
1139 * "off" is the instruction that application sound right will be removed_main_connection
1140 * "pause" is the instruction that application must stop output sound because other applications got sound right and will output sound
1143 * This function is very important for applications to realise the sequence of Audio Management.
1144 * An Application which matches with sourceID in the parameter of asyncSetSourceState has to return ack to use this function
1147 static gboolean on_async_set_source_state(
1148 AudiomanagerRoutingSoundmanager *object,
1149 GDBusMethodInvocation *invocation,
1151 guint16 arg_sourceID,
1152 gint arg_sourceState)
1154 NOTICE(afbitf, "%s called", __FUNCTION__);
1155 struct json_object* ev_obj = json_object_new_object();
1156 char* ss_key = get_source_state_key(arg_sourceState);
1157 sm_add_object_to_json_object(ev_obj, 4,
1158 _handle, arg_handle,
1159 _source_id, arg_sourceID);
1160 json_object_object_add(ev_obj, _source_state, json_object_new_string(ss_key));
1161 afb_event_push(ev_async_set_source_state, ev_obj);
1162 /* Applications must return ackSetSourceState to look sourceID, then Sound Manager doen't return ackSetSourceState */
1163 /*audiomanager_routinginterface_call_ack_set_source_state_sync(
1172 * array of the verbs exported to afb-daemon
1174 static const struct afb_verb_desc_v1 binding_verbs[]= {
1175 /* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */
1176 { .name = "connect", .session = AFB_SESSION_NONE, .callback = connect, .info = "Connect source id and sink id" },
1177 { .name = "disconnect", .session = AFB_SESSION_NONE, .callback = disconnect, .info = "Disconnect source id and sink id" },
1178 { .name = "setVolume", .session = AFB_SESSION_NONE, .callback = setVolume, .info = "Set volume value" }, /* it is better to show the range*/
1179 { .name = "volumeStep", .session = AFB_SESSION_NONE, .callback = volumeStep, .info = "Set volume step range" },
1180 { .name = "setSinkMuteState", .session = AFB_SESSION_NONE, .callback = setSinkMuteState, .info = "Set Mute state: 1 means mute, 2 means umute. Others are invalid" },
1181 { .name = "getListMainConnections", .session = AFB_SESSION_NONE, .callback = getListMainConnections, .info = "Get MainConnection List" },
1182 /* Routing Interface */
1183 { .name = "registerSource", .session = AFB_SESSION_NONE, .callback = registerSource, .info = "Register Application" },
1184 { .name = "deregisterSource", .session = AFB_SESSION_NONE, .callback = deregisterSource, .info = "Deregister Application" },
1185 { .name = "ackConnect", .session = AFB_SESSION_NONE, .callback = ackConnect, .info = "Acknowledge of asyncConnect" },
1186 { .name = "ackDisconnect", .session = AFB_SESSION_NONE, .callback = ackDisconnect, .info = "Acknowledge of asyncConnect" },
1187 { .name = "ackSetSourceState", .session = AFB_SESSION_NONE, .callback = ackSetSourceState, .info = "Acknowledge of asyncSetSourceState" },
1188 { .name = "subscribe", .session = AFB_SESSION_NONE, .callback = subscribe, .info = "Subscribe event" },
1189 { .name = "unsubscribe", .session = AFB_SESSION_NONE, .callback = unsubscribe, .info = "Unsubscribe event" },
1190 { .name = NULL } /* marker for end of the array */
1193 static const struct afb_binding binding_description =
1195 .type = AFB_BINDING_VERSION_1,
1197 .info = "Sound Manager" ,
1198 .prefix = "soundmanager" ,
1199 .verbs = binding_verbs
1203 static void *dbus_event_loop_run(void *args)
1205 loop = g_main_loop_new(NULL, FALSE);
1206 g_main_loop_run(loop);
1212 ********** Internal Function used by Sound Manager **********
1216 static int registerDomain()
1218 /* Default Setting of Sound Manager Domain */
1219 struct domain_data ddata = {
1220 .domainID = DYNAMIC_DOMAIN_ID,
1221 .name = "SoundManager",
1222 .busname = SOUND_MANAGER_BUS_NAME,
1223 .nodename = "soundmanager",
1226 .state = DS_CONTROLLED
1228 GVariant* domainData = create_domain_data(&ddata, afbitf);
1229 gchar* retBusName = SOUND_MANAGER_BUS_NAME;
1230 gchar* retPath = SOUND_MANAGER_PATH;
1231 gchar* retInterface = SOUND_MANAGER_RETURN_INTERFACE;
1236 audiomanager_routinginterface_call_register_domain_sync(
1245 NOTICE(afbitf, "Failed to call %s", __FUNCTION__);
1250 NOTICE(afbitf, "Failed to register domain");
1253 SOUNDMANAGER_DOMAIN_ID = domain_id;
1254 NOTICE(afbitf, "Complete registered domain id:%d",SOUNDMANAGER_DOMAIN_ID);
1261 INFO(afbitf,"Initialize Dbus object");
1262 /* Initialize Dbus interface */
1263 if(am_cmd_bus || am_route_bus)
1265 NOTICE(afbitf, "Dbus object to Audio Manager is already created");
1268 am_cmd_bus = audiomanager_commandinterface_proxy_new_for_bus_sync(
1270 G_DBUS_PROXY_FLAGS_NONE,
1276 am_route_bus = audiomanager_routinginterface_proxy_new_for_bus_sync(
1278 G_DBUS_PROXY_FLAGS_NONE,
1285 if(!am_cmd_bus || !am_route_bus)
1290 INFO(afbitf, "Finish Initialize");
1293 NOTICE(afbitf,"Failed to initialize");
1297 static int create_adapter()
1299 GError *error = NULL;
1302 system_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1305 g_error_free(error);
1308 sm_adapter = audiomanager_routing_soundmanager_skeleton_new();
1309 sm_itf = AUDIOMANAGER_ROUTING_SOUNDMANAGER_GET_IFACE(sm_adapter);
1311 /* initialize sound manager adapter */
1312 sm_itf->handle_async_abort = on_async_abort;
1313 sm_itf->handle_async_connect = on_async_connect;
1314 sm_itf->handle_async_disconnect = on_async_disconnect;
1315 sm_itf->handle_async_set_sink_volume = on_async_set_sink_volume;
1316 sm_itf->handle_async_set_source_state = on_async_set_source_state;
1318 int sigret = g_signal_connect(sm_adapter, "handle-async-abort", G_CALLBACK(on_async_abort),NULL);
1319 sigret = g_signal_connect(sm_adapter, "handle-async-connect", G_CALLBACK(on_async_connect),NULL);
1320 sigret = g_signal_connect(sm_adapter, "handle-async-disconnect", G_CALLBACK(on_async_disconnect),NULL);
1321 sigret = g_signal_connect(sm_adapter, "handle-async-set-sink-volume", G_CALLBACK(on_async_set_sink_volume),NULL);
1322 sigret = g_signal_connect(sm_adapter, "handle-async-set-source-state", G_CALLBACK(on_async_set_source_state),NULL);
1323 ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(sm_adapter), system_conn, SOUND_MANAGER_PATH, &error);
1326 NOTICE(afbitf, "failed to export");
1327 g_error_free(error);
1328 g_object_unref(system_conn);
1337 static void on_name_lost(GDBusServer *server, GDBusConnection *conn, gpointer data)
1339 NOTICE(afbitf, "%s called", __FUNCTION__);
1343 static int sm_event_init()
1345 NOTICE(afbitf,"Initialize event receive setting");
1346 printf("Initialize event receive setting");
1348 /* Initialize make event */
1349 size_t size = sizeof cmd_evlist / sizeof *cmd_evlist;
1352 /*ToDo Hash table is better. And event should be created in the loop
1353 I would like to change */
1354 ev_volume_changed = afb_daemon_make_event(afbitf->daemon, cmd_evlist[0]);
1355 ev_new_connection = afb_daemon_make_event(afbitf->daemon, cmd_evlist[1]);
1356 ev_removed_main_connection = afb_daemon_make_event(afbitf->daemon, cmd_evlist[2]);
1357 ev_sink_mute_state_changed = afb_daemon_make_event(afbitf->daemon, cmd_evlist[3]);
1358 ev_main_connection_state_changed = afb_daemon_make_event(afbitf->daemon, cmd_evlist[4]);
1359 command_event_list[0].name = cmd_evlist[0];
1360 command_event_list[0].event = &ev_volume_changed;
1361 command_event_list[1].name = cmd_evlist[1];
1362 command_event_list[1].event = &ev_new_connection;
1363 command_event_list[2].name = cmd_evlist[2];
1364 command_event_list[2].event = &ev_removed_main_connection;
1365 command_event_list[3].name = cmd_evlist[3];
1366 command_event_list[3].event = &ev_sink_mute_state_changed;
1367 command_event_list[4].name = cmd_evlist[4];
1368 command_event_list[4].event = &ev_main_connection_state_changed;
1370 /* create routing event */
1371 ev_set_routing_ready = afb_daemon_make_event(afbitf->daemon, route_evlist[0]);
1372 ev_set_routing_rundown = afb_daemon_make_event(afbitf->daemon, route_evlist[1]);
1373 ev_async_connect = afb_daemon_make_event(afbitf->daemon, route_evlist[2]);
1374 ev_async_set_source_state = afb_daemon_make_event(afbitf->daemon, route_evlist[3]);
1375 ev_async_disconnect = afb_daemon_make_event(afbitf->daemon, route_evlist[4]);
1377 routing_event_list[0].name = route_evlist[0];
1378 routing_event_list[0].event = &ev_set_routing_ready;
1379 routing_event_list[1].name = route_evlist[1];
1380 routing_event_list[1].event = &ev_set_routing_rundown;
1381 routing_event_list[2].name = route_evlist[2];
1382 routing_event_list[2].event = &ev_async_connect;
1383 routing_event_list[3].name = route_evlist[3];
1384 routing_event_list[3].event = &ev_async_set_source_state;
1385 routing_event_list[4].name = route_evlist[4];
1386 routing_event_list[4].event = &ev_async_disconnect;
1387 /*for(size_t i = 0; i < size; ++i)
1389 struct afb_event afbev = afb_daemon_make_event(afbitf->daemon, cmd_evlist[i]));
1390 size_t afbev_size = sizeof afbev;
1391 size_t key_size = sizeof cmd_evlist[i];
1393 struct event ev = {cmd_evlist[i],afbev};
1394 command_event_list[i] = malloc(key_size + afbev_size);
1395 command_event_list[i] = ev;
1396 search_result = hsearch(entry, FIND);
1398 NOTICE(afbitf, "event name is %s", search_result->key);
1401 /* Initialize dbus event thread */
1402 if(!am_cmd_bus || !am_route_bus)
1406 pthread_t thread_id;
1407 ret = pthread_create(&thread_id, NULL, dbus_event_loop_run, NULL);
1412 /* initialize signal from audio manager command interface */
1413 g_signal_connect(am_cmd_bus,
1415 G_CALLBACK(on_volume_changed),
1417 g_signal_connect(am_cmd_bus,
1418 "new_main_connection",
1419 G_CALLBACK(on_new_main_connection),
1421 g_signal_connect(am_cmd_bus,
1422 "removed_main_connection",
1423 G_CALLBACK(on_removed_main_connection),
1425 g_signal_connect(am_cmd_bus,
1426 "sink_mute_state_changed",
1427 G_CALLBACK(on_sink_mute_state_changed),
1429 g_signal_connect(am_cmd_bus,
1430 "main_connection_state_changed",
1431 G_CALLBACK(on_main_connection_state_changed),
1433 g_signal_connect(am_route_bus,
1434 "set_routing_ready",
1435 G_CALLBACK(on_set_routing_ready),
1437 g_signal_connect(am_route_bus,
1438 "set_routing_rundown",
1439 G_CALLBACK(on_set_routing_rundown),
1442 /* Get soundmanager adapter bus */
1443 g_bus_own_name(G_BUS_TYPE_SYSTEM, SOUND_MANAGER_BUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE,
1444 NULL,NULL, on_name_lost, NULL, NULL);
1445 ret = create_adapter();
1450 ret = registerDomain();
1457 INFO(afbitf,"Finish Initialize event receive setting");
1463 g_main_loop_unref(loop);
1465 NOTICE(afbitf, "DBus connection is not created");
1470 * activation function for registering the binding called by afb-daemon
1472 const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf)
1474 afbitf = itf; // records the interface for accessing afb-daemon
1476 int ret = init(); // Set Dbus communication with audio mangaer
1477 return (ret == 0) ? &binding_description : NULL;
1480 int afbBindingV1ServiceInit(struct afb_service service)
1482 NOTICE(afbitf, "Initializing Audio Manager Notification \n");
1483 int ret = sm_event_init();