diff options
author | Kazumasa Mitsunari <knimitz@witz-inc.co.jp> | 2018-03-28 21:03:23 +0900 |
---|---|---|
committer | Kazumasa Mitsunari <knimitz@witz-inc.co.jp> | 2018-05-16 18:38:27 +0900 |
commit | cbf280b545bbb3a879c55913564796f944b217c4 (patch) | |
tree | 0fa8345f5d396bca5d4049783fb914d1bb527880 /src/audiomanager_proxy.c | |
parent | 975d5e70b89481c90df30365c660b3f5043c3150 (diff) |
Clean: divide soundmanager.c into interface part and proxy part
* interface part ... soundmanager
This receives request and send event to clients
* proxy part ... am_proxy_audiomanager
This is the proxy to call and receive audiomanager API
Change-Id: If29643ba3356ec1d7ec87468b023cf8809aa4eb3
Signed-off-by: Kazumasa Mitsunari <knimitz@witz-inc.co.jp>
Diffstat (limited to 'src/audiomanager_proxy.c')
-rw-r--r-- | src/audiomanager_proxy.c | 697 |
1 files changed, 697 insertions, 0 deletions
diff --git a/src/audiomanager_proxy.c b/src/audiomanager_proxy.c new file mode 100644 index 0000000..d1ace2c --- /dev/null +++ b/src/audiomanager_proxy.c @@ -0,0 +1,697 @@ +/* + * 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. + */ + +#include <glib.h> +#include <assert.h> +#include <pthread.h> +#include "audiomanager_proxy.h" +#include "sm-helper.h" +#include "dbus/audio_manager_interface.h" + +static AudiomanagerCommandinterface *am_cmd_bus; +static AudiomanagerRoutinginterface *am_route_bus; +static AudiomanagerRoutingSoundmanager *sm_adapter; +static AudiomanagerRoutingSoundmanagerIface* sm_itf; +static GDBusConnection* system_conn = NULL; + +static am_event _am_event = {0}; +static am_instruction _am_instruction = {0}; +static void *dbus_event_loop_run(void *args); + +/* +********** Callback Function invoked by Audio Manager Command Interface********** +*/ +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); + + _am_event.on_new_main_connection(mcid, srcid, sinkid, delay, constate); +} + +static void _on_removed_main_connection( + AudiomanagerCommandinterface* interface, guint16 mainConnectionID) +{ + AFB_DEBUG("%s is called",__FUNCTION__); + + _am_event.on_removed_main_connection(mainConnectionID); +} + +static void _on_main_connection_state_changed( + AudiomanagerCommandinterface* interface, guint16 connectionID, gint16 connectionState) +{ + AFB_DEBUG("%s is called",__FUNCTION__); + _am_event.on_main_connection_state_changed(connectionID, connectionState); +} + +static void _on_volume_changed( + AudiomanagerCommandinterface* interface, guint16 sinkID, gint16 volume) +{ + AFB_DEBUG("%s is called",__FUNCTION__); + _am_event.on_volume_changed(sinkID, volume); +} + +static void _on_sink_mute_state_changed( + AudiomanagerCommandinterface* interface, guint16 sinkID, gint16 mute) +{ + AFB_DEBUG("%s is called",__FUNCTION__); + _am_event.on_sink_mute_state_changed(sinkID, mute); +} + +/* +********** Callback Function invoked by Audio Manager Routing Interface********** +*/ +static void _on_set_routing_ready( + AudiomanagerRoutinginterface* interface) +{ + AFB_DEBUG("%s is called",__FUNCTION__); + _am_event.on_set_routing_ready(); +} + +static void _on_set_routing_rundown( + AudiomanagerRoutinginterface* interface) +{ + AFB_DEBUG("%s is called",__FUNCTION__); + _am_event.on_set_routing_rundown(); +} + +static ErrorCode check_send_error(GError *err, guint16 result){ + if(err != NULL){ + return UNABLE_SEND; + } + return result; +} + +static gboolean _on_async_abort( + AudiomanagerRoutingSoundmanager *object, + GDBusMethodInvocation *invocation, + guint16 arg_handle) +{ + AFB_DEBUG( "%s called", __FUNCTION__); + _am_instruction.on_async_abort((int)arg_handle); + 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__); + int handle = (int)arg_handle; + int connection = (int)arg_connectionID; + int source = (int)arg_sourceID; + int sink = (int)arg_sinkID; + int connection_format = (int)arg_connectionFormat; + _am_instruction.on_async_connect(handle, connection, + source, sink, connection_format); + int ack_ok = 0; + ErrorCode ec = am_proxy_ack_connect(handle, connection, ack_ok); + if(ec == UNABLE_SEND) + { + AFB_ERROR( "Can't send ackConnect", __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__); + int handle = (int)arg_handle; + int connection = (int)arg_connectionID; + _am_instruction.on_async_disconnect(handle, connection); + GError* err = NULL; + int ack_ok = 0; + + ErrorCode ec = am_proxy_ack_disconnect(handle, connection, ack_ok); + if(ec == UNABLE_SEND) + { + 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__); + int handle = (int)arg_handle; + int sink = (int)arg_sinkID; + int volume = (int)arg_volume; + int ramp = (int)arg_ramp; + int time = (int)arg_time; + GError* err = NULL; + int ack_ok = 0; + ErrorCode ec = audiomanager_routinginterface_call_ack_set_sink_volume_sync( + am_route_bus, + arg_handle, + arg_volume, + ack_ok, NULL, &err); + if(ec == UNABLE_SEND);{ + AFB_ERROR( "Can't send ack to sound manager adapter %s", __FUNCTION__); + return FALSE; + } + return TRUE; +} + +static gboolean _on_async_set_source_state( + AudiomanagerRoutingSoundmanager *object, + GDBusMethodInvocation *invocation, + guint16 arg_handle, + guint16 arg_sourceID, + gint arg_sourceState) +{ + int handle = (int)arg_handle; + int source = (int)arg_sourceID; + int source_state = (int)arg_sourceState; + AFB_DEBUG( "%s called", __FUNCTION__); + _am_instruction.on_async_set_source_state(handle, source, source_state); + return TRUE; +} + +/* +********** API which calls audio manager API ********** +*/ +ErrorCode am_proxy_connect(int source, int sink, int *main_connection_id){ + if(is_range_over_guint16(source) == OUT_RANGE || is_range_over_guint16(sink) == OUT_RANGE){ + return OUT_RANGE; + } + AFB_DEBUG("Call %s: source:%d sink:%d", __FUNCTION__, source, sink); + + guint16 connection_id = 0, ret = 0; + ErrorCode ec; + GError *err = NULL; + + assert(am_cmd_bus != NULL); + + audiomanager_commandinterface_call_connect_sync( + am_cmd_bus, + (guint16)source, (guint16)sink, + &ret, &connection_id, + NULL, &err); + *main_connection_id = (int)connection_id; + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_disconnect(int main_connection_id){ + AFB_DEBUG("Call %s: mainConnectionID:%d", __FUNCTION__, main_connection_id); + if(is_range_over_guint16(main_connection_id) == OUT_RANGE){ + return OUT_RANGE; + } + guint16 ret = 0; + ErrorCode ec; + GError *err = NULL; + + assert(am_cmd_bus != NULL); + audiomanager_commandinterface_call_disconnect_sync( + am_cmd_bus, + (guint16)main_connection_id, + &ret, + NULL, &err); + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_set_volume(int sink, int volume){ + AFB_DEBUG("Call %s: sink:%d volume:%d", __FUNCTION__, sink, volume); + if(is_range_over_guint16(sink) == OUT_RANGE && is_range_over_gint16(volume) == OUT_RANGE){ + return OUT_RANGE; + } + guint16 ret = 0; + ErrorCode ec; + GError *err = NULL; + + assert(am_cmd_bus != NULL); + audiomanager_commandinterface_call_set_volume_sync( + am_cmd_bus, + (guint16)sink, + (gint16)volume, + &ret, NULL, &err); + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_volume_step(int sink, int volume){ + AFB_DEBUG("Call %s: sink:%d volume:%d", __FUNCTION__, sink, volume); + if(is_range_over_guint16(sink) == OUT_RANGE && is_range_over_gint16(volume) == OUT_RANGE){ + return OUT_RANGE; + } + guint16 ret = 0; + ErrorCode ec; + GError *err = NULL; + + assert(am_cmd_bus != NULL); + audiomanager_commandinterface_call_volume_step_sync( + am_cmd_bus, + (guint16)sink, + (gint16)volume, + &ret, NULL, &err); + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_set_sink_mute_state(int sink, int mute_state){ + AFB_DEBUG("Call %s: sink:%d mute_state:%d", __FUNCTION__, sink, mute_state); + if(is_range_over_guint16(sink) == OUT_RANGE || is_range_over_gint16(mute_state) == OUT_RANGE){ + return OUT_RANGE; + } + guint16 ret = 0; + ErrorCode ec; + GError *err = NULL; + + assert(am_cmd_bus != NULL); + audiomanager_commandinterface_call_set_sink_mute_state_sync( + am_cmd_bus, + (guint16)sink, (gint16)mute_state, + &ret, NULL, &err); + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_get_list_main_connections(GVariant** connection_list){ + guint16 ret = 0; + ErrorCode ec; + GError *err = NULL; + + AFB_DEBUG("Call %s", __FUNCTION__); + assert(am_cmd_bus != NULL); + audiomanager_commandinterface_call_get_list_main_connections_sync( + am_cmd_bus, + &ret, + connection_list, + NULL, + &err + ); + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_get_list_main_sources(GVariant** source_list){ + guint16 ret = 0; + ErrorCode ec; + GError *err = NULL; + + AFB_DEBUG("Call %s", __FUNCTION__); + assert(am_cmd_bus != NULL); + audiomanager_commandinterface_call_get_list_main_sources_sync( + am_cmd_bus, + &ret, + source_list, + NULL, + &err + ); + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_get_list_main_sinks(GVariant** sink_list){ + guint16 ret = 0; + ErrorCode ec; + GError *err = NULL; + + AFB_DEBUG("Call %s", __FUNCTION__); + assert(am_cmd_bus != NULL); + audiomanager_commandinterface_call_get_list_main_sinks_sync( + am_cmd_bus, + &ret, + sink_list, + NULL, + &err + ); + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_ack_connect(int handle, int connection_id, int usr_err){ + AFB_DEBUG("Call %s handle:%d connectionID:%d error:%d", __FUNCTION__, handle, connection_id, usr_err); + if(is_range_over_guint16(handle) == OUT_RANGE || + is_range_over_guint16(connection_id) == OUT_RANGE || + is_range_over_guint16(usr_err) == OUT_RANGE){ + return OUT_RANGE; + } + + assert(am_route_bus != NULL); + GError *err = NULL; + + audiomanager_routinginterface_call_ack_connect_sync( + am_route_bus, + (guint16)handle, + (guint16)connection_id, + (guint16)usr_err, NULL, &err); + return OK; +} + +ErrorCode am_proxy_ack_disconnect(int handle, int connection_id, int usr_err){ + AFB_DEBUG("Call %s handle:%d connectionID:%d error:%d", __FUNCTION__, handle, connection_id, usr_err); + if(is_range_over_guint16(handle) == OUT_RANGE || + is_range_over_guint16(connection_id) == OUT_RANGE || + is_range_over_guint16(usr_err) == OUT_RANGE){ + return OUT_RANGE; + } + assert(am_route_bus != NULL); + GError *err = NULL; + audiomanager_routinginterface_call_ack_disconnect_sync( + am_route_bus, + (guint16)handle, + (guint16)connection_id, + (guint16)usr_err,NULL, &err); + return OK; +} + +ErrorCode am_proxy_ack_set_source_state(int handle, int usr_err){ + AFB_DEBUG("Call %s handle:%d error:%d", __FUNCTION__, handle, usr_err); + if(is_range_over_guint16(handle) == OUT_RANGE || + is_range_over_guint16(usr_err) == OUT_RANGE){ + return OUT_RANGE; + } + + assert(am_route_bus != NULL); + GError *err = NULL; + audiomanager_routinginterface_call_ack_set_source_state_sync( + am_route_bus, + (guint16)handle, + (guint16)usr_err, + NULL, &err); + return OK; +} + +ErrorCode am_proxy_register_source(GVariant *source_data, int *source){ + AFB_DEBUG("Call %s", __FUNCTION__); + assert(am_route_bus != NULL); + guint16 ret = 0, g_source = 0; + ErrorCode ec; + GError *err = NULL; + + audiomanager_routinginterface_call_register_source_sync( + am_route_bus, + source_data, + &g_source, + &ret, + NULL, &err); + + *source = (int)g_source; + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_deregister_source(int source){ + AFB_DEBUG("Call %s source:%d", __FUNCTION__, source); + if(is_range_over_guint16(source) == OUT_RANGE){ + return OUT_RANGE; + } + guint16 ret = 0; + ErrorCode ec; + GError *err = NULL; + + assert(am_route_bus != NULL); + audiomanager_routinginterface_call_deregister_source_sync( + am_route_bus, + (guint16)source, + &ret, + NULL, &err + ); + ec = check_send_error(err, ret); + return ec; +} + +ErrorCode am_proxy_register_domain(GVariant* domain_data, int *domain){ + guint16 ret = 0, g_domain = 0; + ErrorCode ec; + GError *err = NULL; + + assert(am_route_bus != NULL); + assert(domain_data); + AFB_DEBUG("Call %s", __FUNCTION__); + audiomanager_routinginterface_call_register_domain_sync( + am_route_bus, + domain_data, + SOUND_MANAGER_BUS_NAME, + SOUND_MANAGER_PATH, + SOUND_MANAGER_RETURN_INTERFACE, + &g_domain, &ret, + NULL, &err); + + *domain = (int)g_domain; + ec = check_send_error(err, ret); + return ec; +} + +GVariant* create_domain_data(struct domain_data* domain){ + /* + * This function doesn't check the range of guint32 or gint16 + * Soundmanager must keep the input data is between the size of type. + * This function is considered to be only used by soundmanager. + */ + GVariantBuilder builder; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("(qsssbbn)")); + g_variant_builder_add (&builder, "q", (guint16)domain->domainID); + g_variant_builder_add (&builder, "s", domain->name); + g_variant_builder_add (&builder, "s", domain->busname); + g_variant_builder_add (&builder, "s", domain->nodename); + g_variant_builder_add (&builder, "b", (gboolean)domain->early); + g_variant_builder_add (&builder, "b", (gboolean)domain->complete); + g_variant_builder_add (&builder, "n", (gint16)domain->state); + AFB_DEBUG("create domainData"); + return g_variant_builder_end (&builder); +} + +GVariant* create_source_data(int sourceID, int domainID, const char* appname, int sourceClassID, + int sourceState, int volume, bool visible, struct availability_s availables, + int interrupt, struct sound_property_s soundPropertyList, int connectionFormatList, + struct main_sound_property_s mainPropertyList, struct notification_config_s NConfRouting, + struct notification_config_s NConfCommand) +{ + GVariantBuilder builder; + if(is_range_over_guint16(sourceID) == OUT_RANGE || + is_range_over_guint16(domainID) == OUT_RANGE || + is_range_over_gint16(volume) == OUT_RANGE || + is_range_over_guint16(interrupt) == OUT_RANGE || + is_range_over_gint16(soundPropertyList.value) == OUT_RANGE || + is_range_over_gint16(mainPropertyList.value) == OUT_RANGE || + is_range_over_gint16(NConfRouting.parameter) == OUT_RANGE || + is_range_over_gint16(NConfCommand.parameter) == OUT_RANGE) + { + return NULL; + } + g_variant_builder_init (&builder, G_VARIANT_TYPE ("(qqsqinb(ii)qa(in)aia(in)a(iin)a(iin))")); + g_variant_builder_add (&builder, "q", (guint16)sourceID); + g_variant_builder_add (&builder, "q", (guint16)domainID); + g_variant_builder_add (&builder, "s", appname); + g_variant_builder_add (&builder, "q", (guint16)sourceClassID); + g_variant_builder_add (&builder, "i", (gint32)sourceState); + g_variant_builder_add (&builder, "n", (gint16)volume); + g_variant_builder_add (&builder, "b", (gboolean)visible); + g_variant_builder_add (&builder, "(ii)", (gint32)availables.availability, (gint32)availables.avalilable_reason); + g_variant_builder_add (&builder, "q", (guint16)interrupt); + + g_variant_builder_open(&builder, G_VARIANT_TYPE("a(in)")); + g_variant_builder_open(&builder, G_VARIANT_TYPE("(in)")); + g_variant_builder_add (&builder, "i", (gint32)soundPropertyList.type); + g_variant_builder_add (&builder, "n", (gint16)soundPropertyList.value); + g_variant_builder_close(&builder); + g_variant_builder_close (&builder); + + g_variant_builder_open(&builder, G_VARIANT_TYPE("ai")); + g_variant_builder_add (&builder, "i", (gint32)connectionFormatList); + g_variant_builder_close (&builder); + + g_variant_builder_open(&builder, G_VARIANT_TYPE("a(in)")); + g_variant_builder_open(&builder, G_VARIANT_TYPE("(in)")); + g_variant_builder_add (&builder, "i", (gint32)mainPropertyList.type); + g_variant_builder_add (&builder, "n", (gint16)mainPropertyList.value); + g_variant_builder_close (&builder); + g_variant_builder_close(&builder); + + g_variant_builder_open(&builder, G_VARIANT_TYPE("a(iin)")); + g_variant_builder_open(&builder, G_VARIANT_TYPE("(iin)")); + g_variant_builder_add (&builder, "i", (gint32)NConfRouting.type); + g_variant_builder_add (&builder, "i", (gint32)NConfRouting.status); + g_variant_builder_add (&builder, "n", (gint16)NConfRouting.parameter); + g_variant_builder_close(&builder); + g_variant_builder_close (&builder); + + + g_variant_builder_open(&builder, G_VARIANT_TYPE("a(iin)")); + g_variant_builder_open(&builder, G_VARIANT_TYPE("(iin)")); + g_variant_builder_add (&builder, "i", (gint32)NConfCommand.type); + g_variant_builder_add (&builder, "i", (gint32)NConfCommand.status); + g_variant_builder_add (&builder, "n", (gint16)NConfCommand.parameter); + g_variant_builder_close(&builder); + g_variant_builder_close (&builder); + + AFB_DEBUG("create sourceData"); + return g_variant_builder_end (&builder); +} + +static void *dbus_event_loop_run(void *args) +{ + GMainLoop* loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(loop); +} + +ErrorCode initialize_proxy(){ + if(am_cmd_bus || am_route_bus) + { + return NOT_INITIALIZED; + } + 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 + ); + if(!am_cmd_bus){ + AFB_ERROR("Failed to create command interface"); + } + 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_route_bus){ + AFB_ERROR("Failed to create routing interface"); + } + return (am_cmd_bus && am_route_bus) ? OK : UNABLE_SEND; +} + +void close_proxy(){ + if(am_cmd_bus) free(am_cmd_bus); + if(am_route_bus) free(am_route_bus); +} + +void set_event_callback(const am_event* callback){ + assert(am_cmd_bus != NULL); + assert(am_route_bus != NULL); + /* initialize signal from audio manager command interface */ + _am_event.on_main_connection_state_changed = callback->on_main_connection_state_changed; + _am_event.on_new_main_connection = callback->on_new_main_connection; + _am_event.on_removed_main_connection = callback->on_removed_main_connection; + _am_event.on_set_routing_ready = callback->on_set_routing_ready; + _am_event.on_set_routing_rundown = callback->on_set_routing_rundown; + _am_event.on_sink_mute_state_changed = callback->on_sink_mute_state_changed; + _am_event.on_volume_changed = callback->on_volume_changed; + + 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); +} + +static void on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data){ + GError* error = NULL; + AFB_DEBUG("%s is called", __FUNCTION__); + + 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); + + AFB_DEBUG("register %s", AUDIOMANAGER_ROUTING_SOUNDMANAGER_SKELETON(sm_adapter)); + + gboolean rc = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(sm_adapter), connection, SOUND_MANAGER_PATH, &error); + AFB_DEBUG("export soundmanager path result: %d", rc); + if (FALSE == rc) + { + AFB_ERROR( "failed to export"); + g_error_free(error); + g_object_unref(connection); + } +} + +static void on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data){ + AFB_DEBUG("%s is called", __FUNCTION__); +} + +static void on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data){ + AFB_DEBUG("bus name is lost"); + // TODO: soundmanager should register current status? +} + +ErrorCode open_soundmanager_interface(const am_instruction *callback){ + _am_instruction.on_async_abort = callback->on_async_abort; + _am_instruction.on_async_connect = callback->on_async_connect; + _am_instruction.on_async_disconnect = callback->on_async_disconnect; + _am_instruction.on_async_set_sink_volume = callback->on_async_set_sink_volume; + _am_instruction.on_async_set_source_state = callback->on_async_set_source_state; + + guint owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, SOUND_MANAGER_BUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, + on_bus_acquired, on_name_acquired, on_name_lost, NULL/* (gpointer)callback */, NULL); + // see https://developer.gnome.org/gio/stable/gio-Owning-Bus-Names.html#g-bus-own-name + + pthread_t thread_id; + int ret = pthread_create(&thread_id, NULL, dbus_event_loop_run, NULL); + if(ret != 0) + { + AFB_ERROR("Failed to create thread"); + g_bus_unown_name(owner_id); + close_soundmanager_inerface(); + close_proxy(); + return NOT_INITIALIZED; + } + return OK; +} + +void close_soundmanager_inerface(){ + g_dbus_interface_skeleton_unexport(G_DBUS_INTERFACE_SKELETON(sm_adapter)); +} |