From a0f30f1186d0a7c3fa7d0dfae18995de6bb09515 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Tue, 5 Jan 2021 00:52:21 +0900 Subject: [PATCH 01/16] tizenaudio-policy: unload modules safely when daemon is on shutdown [Version] 13.0.44 [Issue Type] Bug Change-Id: Ib92c5cbff8bb48b40eef5685dc5549894a58cdd8 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/module-tizenaudio-policy.c | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index c99a785..d76a281 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.43 +Version: 13.0.44 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/module-tizenaudio-policy.c b/src/module-tizenaudio-policy.c index 43f8bca..a6c1075 100644 --- a/src/module-tizenaudio-policy.c +++ b/src/module-tizenaudio-policy.c @@ -168,8 +168,8 @@ struct userdata { pa_module *module_combine_sink; pa_module *module_combine_sink_for_ex; - pa_module *module_null_sink; - pa_module *module_null_source; + uint32_t module_null_sink_index; + uint32_t module_null_source_index; pa_module *module_loopback; struct { int32_t latency_msec; @@ -1047,8 +1047,8 @@ static void reset_route(struct userdata *u, stream_type_t stream_type) { /* unload combine sink */ if (stream_type == STREAM_SINK_INPUT) { - null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK); - unload_combine_sink_module(u, SINK_NAME_COMBINED, null_sink); + if (null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK)) + unload_combine_sink_module(u, SINK_NAME_COMBINED, null_sink); } route_info.role = "reset"; @@ -1793,6 +1793,7 @@ int pa__init(pa_module *m) pa_modargs *ma = NULL; struct userdata *u; char *args = NULL; + pa_module *module_loaded; pa_assert(m); @@ -1804,6 +1805,8 @@ int pa__init(pa_module *m) m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; + u->module_null_sink_index = PA_INVALID_INDEX; + u->module_null_source_index = PA_INVALID_INDEX; if (!(u->hal_interface = pa_hal_interface_get(u->core))) { pa_log("Failed to get hal interface"); @@ -1826,17 +1829,21 @@ int pa__init(pa_module *m) PA_HOOK_EARLY, (pa_hook_cb_t)update_info_hook_cb, u); } u->device_manager = pa_device_manager_get(u->core); - u->stream_manager = pa_stream_manager_get(u->core); /* load null sink/source */ args = pa_sprintf_malloc("sink_name=%s norewinds=1", SINK_NAME_NULL); - if (pa_module_load(&u->module_null_sink, u->core, MODULE_NULL_SINK, args)) + if (pa_module_load(&module_loaded, u->core, MODULE_NULL_SINK, args)) pa_log_error("failed to load module-null-sink"); + else + u->module_null_sink_index = module_loaded->index; pa_xfree(args); + args = pa_sprintf_malloc("source_name=%s max_latency_msec=100", SOURCE_NAME_NULL); - if (pa_module_load(&u->module_null_source, u->core, MODULE_NULL_SOURCE, args)) + if (pa_module_load(&module_loaded, u->core, MODULE_NULL_SOURCE, args)) pa_log_error("failed to load module-null-source"); + else + u->module_null_source_index = module_loaded->index; pa_xfree(args); __load_dump_config(u); @@ -1865,11 +1872,11 @@ void pa__done(pa_module *m) bt_sco_close(u, false); - if (u->module_null_sink) - pa_module_unload(u->module_null_sink, true); + if (u->module_null_sink_index != PA_INVALID_INDEX) + pa_module_unload_by_index(m->core, u->module_null_sink_index, true); - if (u->module_null_source) - pa_module_unload(u->module_null_source, true); + if (u->module_null_source_index != PA_INVALID_INDEX) + pa_module_unload_by_index(m->core, u->module_null_source_index, true); if (u->device_manager) pa_device_manager_unref(u->device_manager); -- 2.7.4 From c310166cd5d92259499e46aea5f133549e21ca7b Mon Sep 17 00:00:00 2001 From: jungsup lee Date: Tue, 5 Jan 2021 15:01:46 +0900 Subject: [PATCH 02/16] device-manager: handle rtsp device handle rtsp device as network type device [Version] 13.0.45 [Issue Type] Update Change-Id: I90e4965c34db184f6177b19cf6e1874a13175723 Signed-off-by: jungsup lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/device-manager.c | 51 +++++++++++++++++++++++++++++++++ src/tizen-device-def.c | 2 ++ src/tizen-device-def.h | 1 + 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index d76a281..a88cd4f 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.44 +Version: 13.0.45 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/device-manager.c b/src/device-manager.c index 7fc3435..14b2b89 100644 --- a/src/device-manager.c +++ b/src/device-manager.c @@ -82,6 +82,7 @@ #define DEVICE_API_ACM "acm" #define DEVICE_API_RAOP "raop" #define DEVICE_API_TUNNEL "tunnel" +#define DEVICE_API_RTSP "rtsp" #define DEVICE_BUS_USB "usb" #define DEVICE_CLASS_SOUND "sound" #define DEVICE_CLASS_MONITOR "monitor" @@ -456,6 +457,15 @@ static bool pulse_device_is_null(pa_object *pdevice) { } } +static bool pulse_device_is_rtsp(pa_object *pdevice) { + pa_proplist *prop = pulse_device_get_proplist(pdevice); + + if (!prop) + return false; + + return pa_safe_streq(pa_proplist_gets(prop, PA_PROP_DEVICE_API), DEVICE_API_RTSP); +} + static const char* pulse_device_get_device_string_removed_argument(pa_object *pdevice) { static char removed_param[DEVICE_PARAM_STRING_MAX] = {0,}; char *device_string_p = NULL; @@ -1152,6 +1162,8 @@ static const char* pulse_device_get_system_id(pa_object *pdevice) { return pa_proplist_gets(prop, PA_PROP_DEVICE_STRING); else if (pulse_device_is_tunnel(pdevice)) return pa_proplist_gets(prop, PA_PROP_DEVICE_DESCRIPTION); + else if (pulse_device_is_rtsp(pdevice)) + return pa_proplist_gets(prop, PA_PROP_DEVICE_DESCRIPTION); else return NULL; } @@ -1542,6 +1554,38 @@ static void handle_acm_pulse_device(pa_object *pdevice, bool is_loaded, pa_devic } } +static void handle_rtsp_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) { + pa_tz_device *device; + const char *system_id; + + pa_assert(pdevice); + pa_assert(dm); + + pa_log_info("Handle RTSP pulse device"); + + system_id = pulse_device_get_system_id(pdevice); + + if (is_loaded) { + pa_tz_device_new_data data; + + pa_proplist *prop = pulse_device_get_proplist(pdevice); + const char *name = pa_proplist_gets(prop, PA_PROP_DEVICE_DESCRIPTION); + + pa_tz_device_new_data_init(&data, dm->device_list, dm->comm, dm->dbus_conn); + _fill_new_data_basic(&data, DEVICE_TYPE_NETWORK, DM_DEVICE_DIRECTION_IN, false, dm); + pa_tz_device_new_data_set_name(&data, name); + pa_tz_device_new_data_set_system_id(&data, system_id); + pa_tz_device_new_data_add_source(&data, DEVICE_ROLE_RTSP, PA_SOURCE(pdevice)); + pa_tz_device_new(&data); + pa_tz_device_new_data_done(&data); + } else { + if (!(device = device_list_get_device(dm, DEVICE_TYPE_NETWORK, NULL, system_id))) + pa_log_warn("Can't get RTSP device for %s", system_id); + else + pa_tz_device_free(device); + } +} + static void handle_internal_pulse_device(pa_object *pdevice, bool is_loaded, pa_device_manager *dm) { pa_tz_device *device; struct composite_type *ctype; @@ -1698,6 +1742,10 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, pulse_device_set_use_internal_codec(PA_OBJECT(source), true); handle_internal_pulse_device(PA_OBJECT(source), true, dm); return PA_HOOK_OK; + } else if (pulse_device_is_rtsp(PA_OBJECT(source))) { + pulse_device_set_use_internal_codec(PA_OBJECT(source), false); + handle_rtsp_pulse_device(PA_OBJECT(source), true, dm); + return PA_HOOK_OK; } else { pa_log_debug("Don't care this source"); } @@ -1736,6 +1784,9 @@ static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *sourc } else if (pulse_device_is_alsa(PA_OBJECT(source)) || pulse_device_is_tizenaudio(PA_OBJECT(source))) { handle_internal_pulse_device(PA_OBJECT(source), false, dm); return PA_HOOK_OK; + } else if (pulse_device_is_rtsp(PA_OBJECT(source))) { + handle_rtsp_pulse_device(PA_OBJECT(source), false, dm); + return PA_HOOK_OK; } else { pa_log_debug("Don't care this source"); } diff --git a/src/tizen-device-def.c b/src/tizen-device-def.c index 164146c..cca9ae2 100644 --- a/src/tizen-device-def.c +++ b/src/tizen-device-def.c @@ -181,6 +181,8 @@ bool device_role_is_valid(const char *device_role) { return true; else if (pa_safe_streq(device_role, DEVICE_ROLE_ACM)) return true; + else if (pa_safe_streq(device_role, DEVICE_ROLE_RTSP)) + return true; else return false; } diff --git a/src/tizen-device-def.h b/src/tizen-device-def.h index e4232da..d3c3a76 100644 --- a/src/tizen-device-def.h +++ b/src/tizen-device-def.h @@ -29,6 +29,7 @@ #define DEVICE_ROLE_RAOP "raop" #define DEVICE_ROLE_TUNNEL "tunnel" #define DEVICE_ROLE_ACM "acm" +#define DEVICE_ROLE_RTSP "rtsp" typedef enum dm_device_direction_type { DM_DEVICE_DIRECTION_NONE, -- 2.7.4 From ca712cd12259fd18a28b945d09917d2c4452ca08 Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Mon, 25 Jan 2021 14:25:32 +0900 Subject: [PATCH 03/16] hal-interface: Use hal audio api + remove minor build warning [Version] 13.0.46 [Issue Type] Enhancement Change-Id: Iac9337a9c6f654723eb956f7f7a6b2a85deef8d6 Signed-off-by: Jaechul Lee --- Makefile.am | 4 +- configure.ac | 4 + packaging/pulseaudio-modules-tizen.spec | 6 +- src/hal-interface.c | 455 ++++++++++++++------------------ src/hal-interface.h | 8 +- src/module-tizenaudio-policy.c | 2 +- src/stream-manager.c | 8 +- 7 files changed, 222 insertions(+), 265 deletions(-) diff --git a/Makefile.am b/Makefile.am index e529cae..e66660b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,8 +53,8 @@ endif libhal_interface_la_SOURCES = \ src/hal-interface.c src/hal-interface.h libhal_interface_la_LDFLAGS = $(AM_LDFLAGS) $(PA_LDFLAGS) -avoid-version -libhal_interface_la_LIBADD = $(AM_LIBADD) $(PACORE_LIBS) $(PA_LIBS) -libhal_interface_la_CFLAGS = $(AM_CFLAGS) $(PACORE_CFLAGS) $(PA_CFLAGS) +libhal_interface_la_LIBADD = $(AM_LIBADD) $(PACORE_LIBS) $(PA_LIBS) $(HALAPIAUDIO_LIBS) +libhal_interface_la_CFLAGS = $(AM_CFLAGS) $(PACORE_CFLAGS) $(PA_CFLAGS) $(HALAPIAUDIO_CFLAGS) libcommunicator_la_SOURCES = \ src/communicator.c src/communicator.h diff --git a/configure.ac b/configure.ac index 8557992..ac631fa 100644 --- a/configure.ac +++ b/configure.ac @@ -365,6 +365,10 @@ PKG_CHECK_MODULES(DNSSD, dns_sd) AC_SUBST(DNSSD_CFLAGS) AC_SUBST(DNSSD_LIBS) +PKG_CHECK_MODULES(HALAPIAUDIO, hal-api-audio) +AC_SUBST(HALAPIAUDIO_CFLAGS) +AC_SUBST(HALAPIAUDIO_LIBS) + dnl use hal tc ------------------------------------------------------------ AC_ARG_ENABLE(haltc, AC_HELP_STRING([--enable-haltc], [using haltc]), [ diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index a88cd4f..0b5626f 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.45 +Version: 13.0.46 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ @@ -16,11 +16,11 @@ BuildRequires: pkgconfig(vconf) %if "%{tizen_profile_name}" == "tv" BuildRequires: pkgconfig(glib-2.0) %endif -BuildRequires: mm-hal-interface-devel BuildRequires: pkgconfig(libpulse) BuildRequires: pkgconfig(pulsecore) BuildRequires: pkgconfig(libsystemd) BuildRequires: pkgconfig(dns_sd) +BuildRequires: pkgconfig(hal-api-audio) BuildRequires: pulseaudio BuildRequires: m4 Requires(post): /sbin/ldconfig @@ -40,7 +40,7 @@ PulseAudio module-acm-sink for sending PCM data to ACM core. %setup -q %build -export CFLAGS="%{optflags} -fno-strict-aliasing -D__TIZEN__ -DSYSCONFDIR=\\\"%{_sysconfdir}\\\" -DAUDIOHALDIR=\\\"%{_libdir}\\\"" +export CFLAGS="%{optflags} -fno-strict-aliasing -D__TIZEN__ -DSYSCONFDIR=\\\"%{_sysconfdir}\\\" " export LD_AS_NEEDED=0 %reconfigure --prefix=%{_prefix} \ diff --git a/src/hal-interface.c b/src/hal-interface.c index 26ee345..e108f38 100644 --- a/src/hal-interface.c +++ b/src/hal-interface.c @@ -24,25 +24,24 @@ #endif #include "hal-interface.h" -#include + +#include +#include + #include #define SHARED_HAL_INTF "tizen-hal-interface" -/* Audio HAL library */ -#define LIB_TIZEN_AUDIO AUDIOHALDIR"/libtizen-audio.so" - struct _pa_hal_interface { PA_REFCNT_DECLARE; pa_core *core; - void *dl_handle; - void *ah_handle; - audio_interface_t intf; + void *audio_handle; }; pa_hal_interface* pa_hal_interface_get(pa_core *core) { pa_hal_interface *h; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(core); @@ -53,49 +52,12 @@ pa_hal_interface* pa_hal_interface_get(pa_core *core) { PA_REFCNT_INIT(h); h->core = core; - /* Load library & init HAL interface */ - h->dl_handle = dlopen(LIB_TIZEN_AUDIO, RTLD_NOW); - if (h->dl_handle) { - h->intf.init = dlsym(h->dl_handle, "audio_init"); - h->intf.deinit = dlsym(h->dl_handle, "audio_deinit"); - h->intf.get_volume_level_max = dlsym(h->dl_handle, "audio_get_volume_level_max"); - h->intf.get_volume_level = dlsym(h->dl_handle, "audio_get_volume_level"); - h->intf.set_volume_level = dlsym(h->dl_handle, "audio_set_volume_level"); - h->intf.get_volume_value = dlsym(h->dl_handle, "audio_get_volume_value"); - h->intf.get_volume_mute = dlsym(h->dl_handle, "audio_get_volume_mute"); - h->intf.set_volume_mute = dlsym(h->dl_handle, "audio_set_volume_mute"); - h->intf.set_volume_ratio = dlsym(h->dl_handle, "audio_set_volume_ratio"); - h->intf.notify_ducking_activation_changed = dlsym(h->dl_handle, "audio_notify_ducking_activation_changed"); - h->intf.update_route = dlsym(h->dl_handle, "audio_update_route"); - h->intf.update_route_option = dlsym(h->dl_handle, "audio_update_route_option"); - h->intf.notify_stream_connection_changed = dlsym(h->dl_handle, "audio_notify_stream_connection_changed"); - h->intf.pcm_open = dlsym(h->dl_handle, "audio_pcm_open"); - h->intf.pcm_start = dlsym(h->dl_handle, "audio_pcm_start"); - h->intf.pcm_stop = dlsym(h->dl_handle, "audio_pcm_stop"); - h->intf.pcm_close = dlsym(h->dl_handle, "audio_pcm_close"); - h->intf.pcm_avail = dlsym(h->dl_handle, "audio_pcm_avail"); - h->intf.pcm_write = dlsym(h->dl_handle, "audio_pcm_write"); - h->intf.pcm_read = dlsym(h->dl_handle, "audio_pcm_read"); - h->intf.pcm_get_fd = dlsym(h->dl_handle, "audio_pcm_get_fd"); - h->intf.pcm_recover = dlsym(h->dl_handle, "audio_pcm_recover"); - h->intf.pcm_get_params = dlsym(h->dl_handle, "audio_pcm_get_params"); - h->intf.pcm_set_params = dlsym(h->dl_handle, "audio_pcm_set_params"); - h->intf.add_message_cb = dlsym(h->dl_handle, "audio_add_message_cb"); - h->intf.remove_message_cb = dlsym(h->dl_handle, "audio_remove_message_cb"); - if (h->intf.init) { - if (h->intf.init(&h->ah_handle) != AUDIO_RET_OK) { - pa_log_error("hal_interface init failed"); - dlclose(h->dl_handle); - pa_xfree(h); - return NULL; - } - } - - } else { - pa_log_error("open hal_interface failed :%s", dlerror()); - pa_xfree(h); - return NULL; - } + hal_ret = hal_audio_init(&h->audio_handle); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_init error:0x%x", hal_ret); + pa_xfree(h); + return NULL; + } pa_shared_set(core, SHARED_HAL_INTF, h); @@ -112,20 +74,17 @@ pa_hal_interface* pa_hal_interface_ref(pa_hal_interface *h) { } void pa_hal_interface_unref(pa_hal_interface *h) { + audio_return_e hal_ret = AUDIO_RET_OK; + pa_assert(h); pa_assert(PA_REFCNT_VALUE(h) > 0); if (PA_REFCNT_DEC(h) > 0) return; - /* Deinit HAL manager & unload library */ - if (h->intf.deinit) { - if (h->intf.deinit(h->ah_handle) != AUDIO_RET_OK) { - pa_log_error("hal_interface deinit failed"); - } - } - if (h->dl_handle) - dlclose(h->dl_handle); + hal_ret = hal_audio_deinit(h->audio_handle); + if (hal_ret != AUDIO_RET_OK) + pa_log_error("hal_audio_deinit error:0x%x", hal_ret); if (h->core) pa_shared_remove(h->core, SHARED_HAL_INTF); @@ -133,88 +92,82 @@ void pa_hal_interface_unref(pa_hal_interface *h) { pa_xfree(h); } -int32_t pa_hal_interface_get_volume_level_max(pa_hal_interface *h, const char *volume_type, io_direction_t direction, uint32_t *level) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; - audio_volume_info_t info = {NULL, NULL, 0}; +int32_t pa_hal_interface_get_volume_level_max(pa_hal_interface *h, const char *volume_type, + io_direction_t direction, uint32_t *level) { + audio_return_e hal_ret = AUDIO_RET_OK; + audio_volume_info_s info = { volume_type, NULL, direction }; pa_assert(h); pa_assert(volume_type); pa_assert(level); - info.type = volume_type; - info.direction = direction; - - if (AUDIO_RET_OK != (hal_ret = h->intf.get_volume_level_max(h->ah_handle, &info, level))) { - pa_log_error("get_volume_level_max returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_get_volume_level_max(h->audio_handle, &info, level); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_get_volume_level_max error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } -int32_t pa_hal_interface_get_volume_level(pa_hal_interface *h, const char *volume_type, io_direction_t direction, uint32_t *level) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; - audio_volume_info_t info = {NULL, NULL, 0}; +int32_t pa_hal_interface_get_volume_level(pa_hal_interface *h, const char *volume_type, + io_direction_t direction, uint32_t *level) { + audio_return_e hal_ret = AUDIO_RET_OK; + audio_volume_info_s info = { volume_type, NULL, direction }; pa_assert(h); pa_assert(volume_type); pa_assert(level); - info.type = volume_type; - info.direction = direction; - - if (AUDIO_RET_OK != (hal_ret = h->intf.get_volume_level(h->ah_handle, &info, level))) { - pa_log_error("get_volume_level returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_get_volume_level(h->audio_handle, &info, level); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_get_volume_level error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } -int32_t pa_hal_interface_set_volume_level(pa_hal_interface *h, const char *volume_type, io_direction_t direction, uint32_t level) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; - audio_volume_info_t info = {NULL, NULL, 0}; +int32_t pa_hal_interface_set_volume_level(pa_hal_interface *h, const char *volume_type, + io_direction_t direction, uint32_t level) { + audio_return_e hal_ret = AUDIO_RET_OK; + audio_volume_info_s info = { volume_type, NULL, direction }; pa_assert(h); pa_assert(volume_type); - info.type = volume_type; - info.direction = direction; - - if (AUDIO_RET_OK != (hal_ret = h->intf.set_volume_level(h->ah_handle, &info, level))) { - pa_log_error("set_volume_level returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_set_volume_level(h->audio_handle, &info, level); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_set_volume_level error:0x%x", hal_ret); + return -1; } - return ret; + return 0; } -int32_t pa_hal_interface_get_volume_value(pa_hal_interface *h, const char *volume_type, const char *gain_type, io_direction_t direction, uint32_t level, double *value) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; - audio_volume_info_t info = {NULL, NULL, 0}; +int32_t pa_hal_interface_get_volume_value(pa_hal_interface *h, const char *volume_type, + const char *gain_type, io_direction_t direction, + uint32_t level, double *value) { + audio_return_e hal_ret = AUDIO_RET_OK; + audio_volume_info_s info = { volume_type, gain_type, direction }; pa_assert(h); pa_assert(volume_type); pa_assert(value); - info.type = volume_type; - info.gain = gain_type; - info.direction = direction; - - if (AUDIO_RET_OK != (hal_ret = h->intf.get_volume_value(h->ah_handle, &info, level, value))) { - pa_log_error("get_volume_value returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_get_volume_value(h->audio_handle, &info, level, value); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_get_volume_value error:0x%x", hal_ret); + return -1; } - return ret; + return 0; } -int32_t pa_hal_interface_get_volume_mute(pa_hal_interface *h, const char *volume_type, io_direction_t direction, uint32_t *mute) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; - audio_volume_info_t info = {NULL, NULL, 0}; +int32_t pa_hal_interface_get_volume_mute(pa_hal_interface *h, const char *volume_type, + io_direction_t direction, uint32_t *mute) { + audio_return_e hal_ret = AUDIO_RET_OK; + audio_volume_info_s info = { volume_type, NULL, direction }; pa_assert(h); pa_assert(volume_type); @@ -223,73 +176,63 @@ int32_t pa_hal_interface_get_volume_mute(pa_hal_interface *h, const char *volume info.type = volume_type; info.direction = direction; - if (AUDIO_RET_OK != (hal_ret = h->intf.get_volume_mute(h->ah_handle, &info, mute))) { - pa_log_error("get_mute returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_get_volume_mute(h->audio_handle, &info, mute); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_get_volume_mute error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } -int32_t pa_hal_interface_set_volume_mute(pa_hal_interface *h, const char *volume_type, io_direction_t direction, uint32_t mute) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; - audio_volume_info_t info = {NULL, NULL, 0}; +int32_t pa_hal_interface_set_volume_mute(pa_hal_interface *h, const char *volume_type, + io_direction_t direction, uint32_t mute) { + audio_return_e hal_ret = AUDIO_RET_OK; + audio_volume_info_s info = { volume_type, NULL, direction }; pa_assert(h); pa_assert(volume_type); - info.type = volume_type; - info.direction = direction; - - if (AUDIO_RET_OK != (hal_ret = h->intf.set_volume_mute(h->ah_handle, &info, mute))) { - pa_log_error("set_mute returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_set_volume_mute(h->audio_handle, &info, mute); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_set_volume_mute error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } -int32_t pa_hal_interface_set_volume_ratio(pa_hal_interface *h, const char *stream_role, io_direction_t direction, uint32_t idx, double ratio) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; - audio_stream_info_t info = {NULL, 0, 0}; +int32_t pa_hal_interface_set_volume_ratio(pa_hal_interface *h, const char *stream_role, + io_direction_t direction, uint32_t idx, double ratio) { + audio_return_e hal_ret = AUDIO_RET_OK; + audio_stream_info_s info = { stream_role, direction, idx }; pa_assert(h); pa_assert(stream_role); - if (h->intf.set_volume_ratio == NULL) { - pa_log_warn("there is no set_volume_ratio symbol in this audio hal, skip it"); + hal_ret = hal_audio_set_volume_ratio(h->audio_handle, &info, ratio); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_set_volume_ratio error:0x%x", hal_ret); return -1; } - info.role = stream_role; - info.direction = direction; - info.idx = idx; - - if (AUDIO_RET_OK != (hal_ret = h->intf.set_volume_ratio(h->ah_handle, &info, ratio))) { - pa_log_error("set_volume_ratio returns error:0x%x", hal_ret); - ret = -1; - } - return ret; + return 0; } int32_t pa_hal_interface_notify_ducking_activation_changed(pa_hal_interface *h, hal_ducking_activation_info *info) { - audio_return_t hal_ret = AUDIO_RET_OK; - audio_ducking_info_t hal_info; + audio_return_e hal_ret = AUDIO_RET_OK; + audio_ducking_info_s hal_info = { 0, }; pa_assert(h); pa_assert(info); - if (!h->intf.notify_ducking_activation_changed) { - pa_log_warn("not implemented"); - return -2; - } - hal_info.target_role = info->target_role; hal_info.duration = info->duration; hal_info.ratio = info->ratio; - if (AUDIO_RET_OK != (hal_ret = h->intf.notify_ducking_activation_changed(h->ah_handle, &hal_info, (uint32_t)info->is_activated))) { - pa_log_error("notify_ducking_activation_changed returns error:0x%x", hal_ret); + hal_ret = hal_audio_notify_ducking_activation_changed(h->audio_handle, &hal_info, (uint32_t)info->is_activated); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_notify_ducking_activation_changed error:0x%x", hal_ret); return -1; } @@ -297,37 +240,38 @@ int32_t pa_hal_interface_notify_ducking_activation_changed(pa_hal_interface *h, } int32_t pa_hal_interface_update_route(pa_hal_interface *h, hal_route_info *info) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(info); - if (AUDIO_RET_OK != (hal_ret = h->intf.update_route(h->ah_handle, (audio_route_info_t*)info))) { - pa_log_error("update_route returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_update_route(h->audio_handle, (audio_route_info_s*)info); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_update_route error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_update_route_option(pa_hal_interface *h, hal_route_option *option) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(option); - if (AUDIO_RET_OK != (hal_ret = h->intf.update_route_option(h->ah_handle, (audio_route_option_t*)option))) { - pa_log_error("update_route_option returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_update_route_option(h->audio_handle, (audio_route_option_s*)option); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_update_route_option error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_notify_stream_connection_changed(pa_hal_interface *h, hal_stream_connection_info *info) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; - audio_stream_info_t hal_info; + audio_return_e hal_ret = AUDIO_RET_OK; + audio_stream_info_s hal_info = { 0, }; pa_assert(h); pa_assert(info); @@ -336,17 +280,18 @@ int32_t pa_hal_interface_notify_stream_connection_changed(pa_hal_interface *h, h hal_info.direction = info->direction; hal_info.idx = info->idx; - if (AUDIO_RET_OK != (hal_ret = h->intf.notify_stream_connection_changed(h->ah_handle, &hal_info, (uint32_t)info->is_connected))) { - pa_log_error("notify_tream_connection_changed returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_notify_stream_connection_changed(h->audio_handle, &hal_info, (uint32_t)info->is_connected); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_notify_stream_connection_changed error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_pcm_open(pa_hal_interface *h, const char *card, const char *device, io_direction_t direction, pa_sample_spec *sample_spec, uint32_t period_size, uint32_t periods, pcm_handle *pcm_h) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(pcm_h); @@ -354,191 +299,199 @@ int32_t pa_hal_interface_pcm_open(pa_hal_interface *h, const char *card, const c pa_assert(device); pa_assert(sample_spec); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_open(h->ah_handle, card, device, direction, sample_spec, period_size, periods, pcm_h))) { - pa_log_error("pcm_open returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_open(h->audio_handle, card, device, direction, sample_spec, period_size, periods, pcm_h); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_open error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_pcm_start(pa_hal_interface *h, pcm_handle pcm_h) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(pcm_h); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_start(h->ah_handle, pcm_h))) { - pa_log_error("pcm_start returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_start(h->audio_handle, pcm_h); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_start error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_pcm_stop(pa_hal_interface *h, pcm_handle pcm_h) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(pcm_h); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_stop(h->ah_handle, pcm_h))) { - pa_log_error("pcm_stop returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_stop(h->audio_handle, pcm_h); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_stop error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_pcm_close(pa_hal_interface *h, pcm_handle pcm_h) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(pcm_h); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_close(h->ah_handle, pcm_h))) { - pa_log_error("pcm_close returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_close(h->audio_handle, pcm_h); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_close error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_pcm_available(pa_hal_interface *h, pcm_handle pcm_h, uint32_t *available) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(pcm_h); pa_assert(available); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_avail(h->ah_handle, pcm_h, available))) { - pa_log_error("pcm_avail returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_avail(h->audio_handle, pcm_h, available); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_avail error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_pcm_write(pa_hal_interface *h, pcm_handle pcm_h, const void *buffer, uint32_t frames) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(pcm_h); pa_assert(buffer); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_write(h->ah_handle, pcm_h, buffer, frames))) { - pa_log_error("pcm_write returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_write(h->audio_handle, pcm_h, buffer, frames); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_write error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_pcm_read(pa_hal_interface *h, pcm_handle pcm_h, void *buffer, uint32_t frames) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(pcm_h); pa_assert(buffer); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_read(h->ah_handle, pcm_h, buffer, frames))) { - pa_log_error("pcm_read returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_read(h->audio_handle, pcm_h, buffer, frames); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_read error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_pcm_get_fd(pa_hal_interface *h, pcm_handle pcm_h, int *fd) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(pcm_h); pa_assert(fd); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_get_fd(h->ah_handle, pcm_h, fd))) { - pa_log_error("pcm_get_fd returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_get_fd(h->audio_handle, pcm_h, fd); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_get_fd error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_pcm_recover(pa_hal_interface *h, pcm_handle pcm_h, int err) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(pcm_h); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_recover(h->ah_handle, pcm_h, err))) { - pa_log_error("pcm_recover returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_recover(h->audio_handle, pcm_h, err); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_recover error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } -int32_t pa_hal_interface_pcm_get_params(pa_hal_interface *h, pcm_handle pcm_h, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; +int32_t pa_hal_interface_pcm_get_params(pa_hal_interface *h, pcm_handle pcm_h, uint32_t direction, + void **sample_spec, uint32_t *period_size, uint32_t *periods) { + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(*sample_spec); pa_assert(period_size); pa_assert(periods); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_get_params(h->ah_handle, pcm_h, direction, sample_spec, period_size, periods))) { - pa_log_error("pcm_get_params returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_get_params(h->audio_handle, pcm_h, direction, sample_spec, period_size, periods); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_get_params error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } -int32_t pa_hal_interface_pcm_set_params(pa_hal_interface *h, pcm_handle pcm_h, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; +int32_t pa_hal_interface_pcm_set_params(pa_hal_interface *h, pcm_handle pcm_h, uint32_t direction, + void *sample_spec, uint32_t period_size, uint32_t periods) { + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(sample_spec); - if (AUDIO_RET_OK != (hal_ret = h->intf.pcm_set_params(h->ah_handle, pcm_h, direction, sample_spec, period_size, periods))) { - pa_log_error("pcm_set_params returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_pcm_set_params(h->audio_handle, pcm_h, direction, sample_spec, period_size, periods); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_pcm_set_params error:0x%x", hal_ret); + return -1; } - return ret; + + return 0; } int32_t pa_hal_interface_add_message_callback(pa_hal_interface *h, hal_message_callback callback, void *user_data) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(callback); - if (h->intf.add_message_cb == NULL) { - pa_log_error("there is no add_message_cb symbol in this audio hal"); - ret = -1; - } else if (AUDIO_RET_OK != (hal_ret = h->intf.add_message_cb(h->ah_handle, (message_cb)callback, user_data))) { - pa_log_error("add_message_cb returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_add_message_cb(h->audio_handle, (message_cb)callback, user_data); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_add_message_cb error:0x%x", hal_ret); + return -1; } - return ret; + return 0; } int32_t pa_hal_interface_remove_message_callback(pa_hal_interface *h, hal_message_callback callback) { - int32_t ret = 0; - audio_return_t hal_ret = AUDIO_RET_OK; + audio_return_e hal_ret = AUDIO_RET_OK; pa_assert(h); pa_assert(callback); - if (h->intf.remove_message_cb == NULL) { - pa_log_error("there is no remove_message_cb symbol in this audio hal"); - ret = -1; - } else if (AUDIO_RET_OK != (hal_ret = h->intf.remove_message_cb(h->ah_handle, (message_cb)callback))) { - pa_log_error("remove_message_cb returns error:0x%x", hal_ret); - ret = -1; + hal_ret = hal_audio_remove_message_cb(h->audio_handle, (message_cb)callback); + if (hal_ret != AUDIO_RET_OK) { + pa_log_error("hal_audio_remove_message_cb error:0x%x", hal_ret); + return -1; } - return ret; + return 0; } diff --git a/src/hal-interface.h b/src/hal-interface.h index 2351701..ebfca2f 100644 --- a/src/hal-interface.h +++ b/src/hal-interface.h @@ -65,10 +65,10 @@ typedef struct _hal_stream_info { } hal_stream_info; typedef struct _hal_ducking_activation_info { - const char *target_role; - uint32_t duration; - double ratio; - bool is_activated; + const char *target_role; + uint32_t duration; + double ratio; + bool is_activated; } hal_ducking_activation_info; typedef void* pcm_handle; diff --git a/src/module-tizenaudio-policy.c b/src/module-tizenaudio-policy.c index a6c1075..09759e3 100644 --- a/src/module-tizenaudio-policy.c +++ b/src/module-tizenaudio-policy.c @@ -1047,7 +1047,7 @@ static void reset_route(struct userdata *u, stream_type_t stream_type) { /* unload combine sink */ if (stream_type == STREAM_SINK_INPUT) { - if (null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK)) + if ((null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK))) unload_combine_sink_module(u, SINK_NAME_COMBINED, null_sink); } diff --git a/src/stream-manager.c b/src/stream-manager.c index 0ce45e2..d611844 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -3632,7 +3632,7 @@ static void subscribe_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t } /* Message callback from HAL interface */ -static void message_cb(const char *name, int value, void *user_data) { +static void message_cb_func(const char *name, int value, void *user_data) { pa_stream_manager *m; pa_stream_manager_hook_data_for_update_info hook_call_data; @@ -3760,7 +3760,7 @@ pa_stream_manager* pa_stream_manager_get(pa_core *c) { if (!(m->hal = pa_hal_interface_get(c))) goto fail; - if (pa_hal_interface_add_message_callback(m->hal, message_cb, m)) + if (pa_hal_interface_add_message_callback(m->hal, message_cb_func, m)) pa_log_warn("skip adding message callback"); m->dm = pa_device_manager_get(c); m->subs_ob = pa_subscribe_observer_get(c); @@ -3823,7 +3823,7 @@ fail: deinit_filters(m); deinit_ipc(m); if (m->hal) { - pa_hal_interface_remove_message_callback(m->hal, message_cb); + pa_hal_interface_remove_message_callback(m->hal, message_cb_func); pa_hal_interface_unref(m->hal); } if (m->dm) @@ -3937,7 +3937,7 @@ void pa_stream_manager_unref(pa_stream_manager *m) { pa_device_manager_unref(m->dm); if (m->hal) { - pa_hal_interface_remove_message_callback(m->hal, message_cb); + pa_hal_interface_remove_message_callback(m->hal, message_cb_func); pa_hal_interface_unref(m->hal); } -- 2.7.4 From d2c9f1b0308e96ae3d37a8ed65f4ddce8e2e9740 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 9 Feb 2021 20:52:10 +0900 Subject: [PATCH 04/16] stream-manager-dbus: Skip virtual stream for ducking streams - The ducking state is never changed because of virtual stream. [Version] 13.0.47 [Issue Type] Bug fix Change-Id: I545f381f8868c40eaa8562bcdf4f6ae3afecfb63 Signed-off-by: Jeongmo Yang --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-dbus.c | 2 ++ src/stream-manager-priv.h | 2 ++ src/stream-manager.c | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 0b5626f..9270deb 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.46 +Version: 13.0.47 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-dbus.c b/src/stream-manager-dbus.c index 3545cd1..d9320f5 100644 --- a/src/stream-manager-dbus.c +++ b/src/stream-manager-dbus.c @@ -2101,6 +2101,8 @@ static void handle_activate_ducking(DBusConnection *conn, DBusMessage *msg, void /* set volume ramp factor to target stream */ PA_IDXSET_FOREACH(i, m->core->sink_inputs, idx) { + if (pa_safe_streq(VIRTUAL_STREAM_NAME, pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME))) + continue; if (!pa_safe_streq(target_stream, pa_proplist_gets(i->proplist, PA_PROP_MEDIA_ROLE))) continue; diff --git a/src/stream-manager-priv.h b/src/stream-manager-priv.h index aeb0ac9..390b156 100644 --- a/src/stream-manager-priv.h +++ b/src/stream-manager-priv.h @@ -123,6 +123,8 @@ typedef enum _stream_ducking_state { #define STREAM_FOCUS_STATE_RELEASED "0" #define STREAM_FOCUS_STATE_ACQUIRED "1" +#define VIRTUAL_STREAM_NAME "VIRTUAL_STREAM" /* The virtual stream created by sound-manager */ + #define VOLUME_KEY_LENGTH 24 #define STREAM_ROLE_STR_MAX 32 diff --git a/src/stream-manager.c b/src/stream-manager.c index d611844..034bf0a 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -67,7 +67,7 @@ #define STREAM_MANAGER_CLIENT_INFO "SOUND_MANAGER_STREAM_INFO" /* The stream info client via sound-manager */ #define STREAM_MANAGER_CLIENT_DUCKING "SOUND_MANAGER_STREAM_DUCKING" /* The ducking client via sound-manager */ -#define VIRTUAL_STREAM_NAME "VIRTUAL_STREAM" /* The virtual stream created by sound-manager */ + #define DEFAULT_ROLE "media" #define SKIP_ROLE "skip" #define ACTIVE_DEV_REMOVED "removed" -- 2.7.4 From 8acb8aa1bf86eacf69f0b81cf1e07a20380a97df Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Thu, 4 Mar 2021 13:02:13 +0900 Subject: [PATCH 05/16] stream-manager-dbus: update volume vconf only after internal set is successful [Version] 13.0.48 [Issue Type] Bug fix Change-Id: I9238bbe1602b43f1ac1c56ef0029d248ddb56a22 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-dbus.c | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 9270deb..005241f 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.47 +Version: 13.0.48 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-dbus.c b/src/stream-manager-dbus.c index d9320f5..40b2160 100644 --- a/src/stream-manager-dbus.c +++ b/src/stream-manager-dbus.c @@ -1199,8 +1199,9 @@ static void handle_set_volume_level(DBusConnection *conn, DBusMessage *msg, void const char *direction = NULL; const char *type = NULL; dbus_uint32_t level = 0; + uint32_t old_level = 0; stream_type_t stream_type = STREAM_SINK_INPUT; - int ret = 0; + int ret = RET_MSG_OK; pa_assert(conn); pa_assert(msg); @@ -1218,19 +1219,26 @@ static void handle_set_volume_level(DBusConnection *conn, DBusMessage *msg, void goto finish; } - /* check vconf update here, volume will not be set if update fails */ - if ((ret = update_volume_vconf(type, level))) { + if (get_volume_level_by_type(m, GET_VOLUME_CURRENT_LEVEL, stream_type, type, &old_level) != 0) { ret = RET_MSG_ERROR_INTERNAL; goto finish; } - if ((ret = set_volume_level_by_type(m, stream_type, type, level)) != 0) + if ((ret = set_volume_level_by_type(m, stream_type, type, level)) != 0) { ret = (ret == -2) ? RET_MSG_ERROR_INVALID_ARGUMENT : RET_MSG_ERROR_INTERNAL; + goto finish; + } + + if (update_volume_vconf(type, level) != 0) { + ret = RET_MSG_ERROR_INTERNAL; + pa_log_error("Failed to update volume vconf, rollback to old level[%u]", old_level); + set_volume_level_by_type(m, stream_type, type, old_level); + } finish: pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[ret]); - if (ret == 0) + if (ret == RET_MSG_OK) send_volume_changed_signal(conn, direction, type, level); } -- 2.7.4 From e4cb6edb9e040c796ec6f3ca000c7526f4d88eb5 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Mon, 8 Mar 2021 17:47:34 +0900 Subject: [PATCH 06/16] stream-manager-dbus: fix improper null handling on handle_get_current_volume_type() [Version] 13.0.49 [Issue Type] Bug fix Change-Id: I067eeadf9deabcc17676df254984437920765be4 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-dbus.c | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 005241f..06a0216 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.48 +Version: 13.0.49 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-dbus.c b/src/stream-manager-dbus.c index 40b2160..80ec2c1 100644 --- a/src/stream-manager-dbus.c +++ b/src/stream-manager-dbus.c @@ -1475,7 +1475,7 @@ finish: static void handle_get_current_volume_type(DBusConnection *conn, DBusMessage *msg, void *userdata) { pa_stream_manager *m = (pa_stream_manager *)userdata; const char *direction = NULL; - const char *type = dbus_str_none; + const char *result = dbus_str_none; void *s = NULL; stream_type_t stream_type = STREAM_SINK_INPUT; DBusMessage *reply = NULL; @@ -1507,6 +1507,7 @@ static void handle_get_current_volume_type(DBusConnection *conn, DBusMessage *ms int cur_max_priority = 0; const char *cur_max_type = NULL; const char *role = NULL; + const char *type = NULL; stream_info *s_info; PA_IDXSET_FOREACH(s, streams, idx) { @@ -1524,14 +1525,16 @@ static void handle_get_current_volume_type(DBusConnection *conn, DBusMessage *ms } } } - type = cur_max_type; + + if (cur_max_type) + result = cur_max_type; } - if (!strncmp(type, dbus_str_none, strlen(dbus_str_none))) + if (pa_safe_streq(result, dbus_str_none)) ret = RET_MSG_ERROR_NO_STREAM; finish: - pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &type, + pa_assert_se(dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[ret], DBUS_TYPE_INVALID)); pa_assert_se(dbus_connection_send(conn, reply, NULL)); -- 2.7.4 From d45adaee6ea5b878f97d93759d6715b4b93e1589 Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Tue, 16 Mar 2021 14:36:54 +0900 Subject: [PATCH 07/16] stream-manager-dbus: Update mute vconf only after internal set is successful [Version] 13.0.50 [Issue Type] Bug fix Change-Id: Id58f2d54e5a88c583f87ab2ecaa56823b36fd8b3 Signed-off-by: Sangchul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-dbus.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 06a0216..351047c 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.49 +Version: 13.0.50 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-dbus.c b/src/stream-manager-dbus.c index 80ec2c1..2f6e4c6 100644 --- a/src/stream-manager-dbus.c +++ b/src/stream-manager-dbus.c @@ -1321,6 +1321,7 @@ static void handle_set_volume_mute(DBusConnection *conn, DBusMessage *msg, void const char *direction = NULL; const char *type = NULL; dbus_uint32_t do_mute = 0; + bool old_mute = false; stream_type_t stream_type = STREAM_SINK_INPUT; ret_msg_t ret = RET_MSG_OK; @@ -1340,14 +1341,21 @@ static void handle_set_volume_mute(DBusConnection *conn, DBusMessage *msg, void goto finish; } - /* check vconf update here, mute will not be set if update fails */ - if (update_mute_vconf(type, do_mute) != 0) { + if (get_volume_mute_by_type(m, stream_type, type, &old_mute) != 0) { ret = RET_MSG_ERROR_INTERNAL; goto finish; } - if (set_volume_mute_by_type(m, stream_type, type, (bool)do_mute) != 0) + if (set_volume_mute_by_type(m, stream_type, type, (bool)do_mute) != 0) { ret = RET_MSG_ERROR_INTERNAL; + goto finish; + } + + if (update_mute_vconf(type, do_mute) != 0) { + ret = RET_MSG_ERROR_INTERNAL; + pa_log_error("Failed to update mute vconf, rollback to old mute[%u]", old_mute); + set_volume_mute_by_type(m, stream_type, type, old_mute); + } finish: pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_STRING, &stream_manager_dbus_ret_str[ret]); -- 2.7.4 From 2e0bbdaefe031e2c493ed48ed781aa4cd24393d4 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Wed, 17 Mar 2021 16:05:44 +0900 Subject: [PATCH 08/16] stream-manager-dbus: remove unnessary dbus_launch_mdnsd() mdnsd is changed to launch by socket activation [Version] 13.0.51 [Issue Type] Dependancy Change-Id: Id957b580d877c802d282fe746248564998552b20 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-dbus.c | 44 --------------------------------- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 351047c..8446dce 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.50 +Version: 13.0.51 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-dbus.c b/src/stream-manager-dbus.c index 2f6e4c6..e68cda6 100644 --- a/src/stream-manager-dbus.c +++ b/src/stream-manager-dbus.c @@ -2230,40 +2230,6 @@ finish: dbus_message_unref(reply); } -static int dbus_launch_mdnsd(pa_stream_manager *m, DBusConnection *conn) { - DBusMessage *msg, *reply; - DBusError err; - const char *name = NULL; - - pa_log_info("launching mdnsd"); - - if (!(msg = dbus_message_new_method_call("net.netconfig", - "/net/netconfig/network", - "net.netconfig.network", - "LaunchMdns"))) { - pa_log_error("dbus method call failed"); - return -1; - } - - name = dbus_bus_get_unique_name(conn); - pa_assert_se(dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)); - - dbus_error_init(&err); - - reply = dbus_connection_send_with_reply_and_block(conn, msg, DBUS_TIMEOUT_USE_DEFAULT, &err); - dbus_message_unref(msg); - if (!reply) { - pa_log_error("Failed to method call : %s", err.message); - dbus_error_free(&err); - return -1; - } - - dbus_message_unref(reply); - pa_log_info("success"); - - return 0; -} - static void handle_set_remote_permission(DBusConnection *conn, DBusMessage *msg, void *userdata) { pa_stream_manager *m = (pa_stream_manager *)userdata; const char *type = NULL; @@ -2355,11 +2321,6 @@ static void handle_discover_remote_device(DBusConnection *conn, DBusMessage *msg goto error; } - if (dbus_launch_mdnsd(m, conn) == -1) { - pa_log_error("failed to launch mdnsd!!!"); - goto error; - } - if (pa_module_load(&module, m->core, "module-tizenaudio-discover", NULL)) { pa_log_error("failed to load module"); goto error; @@ -2401,11 +2362,6 @@ static void handle_publish_local_device(DBusConnection *conn, DBusMessage *msg, goto error; } - if (dbus_launch_mdnsd(m, conn) == -1) { - pa_log_error("failed to launch mdnsd!!!"); - goto error; - } - if (pa_module_load(&module, m->core, "module-native-protocol-tcp", "auth-anonymous=1")) { pa_log_error("failed to load module"); goto error; -- 2.7.4 From 144ce706b93a7741bff1a0b9f69b65d544481606 Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Thu, 18 Mar 2021 20:23:31 +0900 Subject: [PATCH 09/16] stream-manager: Apply designated initializers to arrays [Version] 13.0.52 [Issue Type] Refactoring Change-Id: If23ef59b2702618943f2029bd4bcaf35015bba3d Signed-off-by: Sangchul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager.c | 34 ++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 8446dce..2d4862d 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.51 +Version: 13.0.52 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager.c b/src/stream-manager.c index 034bf0a..c2b4c80 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -82,26 +82,26 @@ static const char* stream_manager_media_names_for_skip[NAME_FOR_SKIP_MAX] = {"pu #define TIMED_UNMUTE_USEC 300000 static const char* process_command_type_str[] = { - "PREPARE", - "CHANGE_ROUTE_BY_STREAM_STARTED", - "CHANGE_ROUTE_BY_STREAM_ENDED", - "CHANGE_ROUTE_BY_STATE_CHANGED_RUNNING", - "CHANGE_ROUTE_BY_STATE_CHANGED_CORKED", - "CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED", - "UPDATE_VOLUME", - "ADD_PARENT_ID", - "REMOVE_PARENT_ID", - "UPDATE_BUFFER_ATTR", - "APPLY_FILTER", + [PROCESS_COMMAND_PREPARE] = "PREPARE", + [PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED] = "CHANGE_ROUTE_BY_STREAM_STARTED", + [PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED] = "CHANGE_ROUTE_BY_STREAM_ENDED", + [PROCESS_COMMAND_CHANGE_ROUTE_BY_STATE_CHANGED_RUNNING] = "CHANGE_ROUTE_BY_STATE_CHANGED_RUNNING", + [PROCESS_COMMAND_CHANGE_ROUTE_BY_STATE_CHANGED_CORKED] = "CHANGE_ROUTE_BY_STATE_CHANGED_CORKED", + [PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED] = "CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED", + [PROCESS_COMMAND_UPDATE_VOLUME] = "UPDATE_VOLUME", + [PROCESS_COMMAND_ADD_PARENT_ID] = "ADD_PARENT_ID", + [PROCESS_COMMAND_REMOVE_PARENT_ID] = "REMOVE_PARENT_ID", + [PROCESS_COMMAND_UPDATE_BUFFER_ATTR] = "UPDATE_BUFFER_ATTR", + [PROCESS_COMMAND_APPLY_FILTER] = "APPLY_FILTER", }; static const char* notify_command_type_str[] = { - "SELECT_PROPER_SINK_OR_SOURCE_FOR_INIT", - "CHANGE_ROUTE_START", - "CHANGE_ROUTE_END", - "UPDATE_ROUTE_OPTION", - "INFORM_STREAM_CONNECTED", - "INFORM_STREAM_DISCONNECTED", + [NOTIFY_COMMAND_SELECT_PROPER_SINK_OR_SOURCE_FOR_INIT] = "SELECT_PROPER_SINK_OR_SOURCE_FOR_INIT", + [NOTIFY_COMMAND_CHANGE_ROUTE_START] = "CHANGE_ROUTE_START", + [NOTIFY_COMMAND_CHANGE_ROUTE_END] = "CHANGE_ROUTE_END", + [NOTIFY_COMMAND_UPDATE_ROUTE_OPTION] = "UPDATE_ROUTE_OPTION", + [NOTIFY_COMMAND_INFORM_STREAM_CONNECTED] = "INFORM_STREAM_CONNECTED", + [NOTIFY_COMMAND_INFORM_STREAM_DISCONNECTED] = "INFORM_STREAM_DISCONNECTED", }; #define STREAM_MAP_FILE "/etc/pulse/stream-map.json" -- 2.7.4 From 60e8045a5a78f7cec6bedd4bb7f5cc6ad2f236ed Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Thu, 18 Mar 2021 20:32:50 +0900 Subject: [PATCH 10/16] stream-manager: Rename enum and function Incorrect names are revised generically to embrace the actual doing in the function. [Version] 13.0.53 [Issue Type] Rename Change-Id: I2860404667916d7487131fccc02de4fa141f7074 Signed-off-by: Sangchul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-priv.h | 4 ++-- src/stream-manager.c | 30 +++++++++++++++--------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 2d4862d..6c7bd8b 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.52 +Version: 13.0.53 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-priv.h b/src/stream-manager-priv.h index 390b156..677deff 100644 --- a/src/stream-manager-priv.h +++ b/src/stream-manager-priv.h @@ -72,8 +72,8 @@ typedef enum _process_command_type { PROCESS_COMMAND_CHANGE_ROUTE_BY_STATE_CHANGED_CORKED, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED, PROCESS_COMMAND_UPDATE_VOLUME, - PROCESS_COMMAND_ADD_PARENT_ID, - PROCESS_COMMAND_REMOVE_PARENT_ID, + PROCESS_COMMAND_ADD_STREAM, + PROCESS_COMMAND_REMOVE_STREAM, PROCESS_COMMAND_UPDATE_BUFFER_ATTR, PROCESS_COMMAND_APPLY_FILTER, } process_command_type_t; diff --git a/src/stream-manager.c b/src/stream-manager.c index c2b4c80..8ff7dde 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -89,8 +89,8 @@ static const char* process_command_type_str[] = { [PROCESS_COMMAND_CHANGE_ROUTE_BY_STATE_CHANGED_CORKED] = "CHANGE_ROUTE_BY_STATE_CHANGED_CORKED", [PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED] = "CHANGE_ROUTE_BY_STREAM_FOCUS_CHANGED", [PROCESS_COMMAND_UPDATE_VOLUME] = "UPDATE_VOLUME", - [PROCESS_COMMAND_ADD_PARENT_ID] = "ADD_PARENT_ID", - [PROCESS_COMMAND_REMOVE_PARENT_ID] = "REMOVE_PARENT_ID", + [PROCESS_COMMAND_ADD_STREAM] = "ADD_STREAM", + [PROCESS_COMMAND_REMOVE_STREAM] = "REMOVE_STREAM", [PROCESS_COMMAND_UPDATE_BUFFER_ATTR] = "UPDATE_BUFFER_ATTR", [PROCESS_COMMAND_APPLY_FILTER] = "APPLY_FILTER", }; @@ -1230,12 +1230,12 @@ static bool update_stream_parent_info(pa_stream_manager *m, process_command_type sp = pa_hashmap_get(m->stream_parents, (const void*)parent_idx); if (sp) { uint32_t idx = GET_STREAM_INDEX(stream, type); - if (command == PROCESS_COMMAND_ADD_PARENT_ID) { + if (command == PROCESS_COMMAND_ADD_STREAM) { /* append this stream to the parent stream info. */ pa_log_debug(" - append this stream(%p, %u) to the list. sp(%p), stream_type(%d)", stream, idx, sp, type); pa_idxset_put(type == STREAM_SINK_INPUT ? (sp->idx_sink_inputs) : (sp->idx_source_outputs), stream, NULL); return true; - } else if (command == PROCESS_COMMAND_REMOVE_PARENT_ID) { + } else if (command == PROCESS_COMMAND_REMOVE_STREAM) { /* remove this stream from the parent stream info. */ pa_log_debug(" - remove this stream(%p, %u) from the list. sp(%p), stream_type(%d)", stream, idx, sp, type); pa_idxset_remove_by_data(type == STREAM_SINK_INPUT ? (sp->idx_sink_inputs) : (sp->idx_source_outputs), stream, NULL); @@ -2280,7 +2280,7 @@ static process_stream_result_t handle_command_update_volume(pa_stream_manager *m return PROCESS_STREAM_RESULT_OK; } -static process_stream_result_t handle_command_add_remove_parent_id(pa_stream_manager *m, process_command_type_t command, +static process_stream_result_t handle_command_add_remove_stream(pa_stream_manager *m, process_command_type_t command, void *stream, stream_type_t type, bool is_new_data) { const char *role = NULL; const char *route_type_str = NULL; @@ -2289,8 +2289,8 @@ static process_stream_result_t handle_command_add_remove_parent_id(pa_stream_man pa_assert(m); pa_assert(stream); - if (command != PROCESS_COMMAND_ADD_PARENT_ID && - command != PROCESS_COMMAND_REMOVE_PARENT_ID) + if (command != PROCESS_COMMAND_ADD_STREAM && + command != PROCESS_COMMAND_REMOVE_STREAM) return PROCESS_STREAM_RESULT_SKIP; if (!(role = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_MEDIA_ROLE))) { @@ -2309,7 +2309,7 @@ static process_stream_result_t handle_command_add_remove_parent_id(pa_stream_man } if (!IS_ROUTE_TYPE_FOR_EXTERNAL_DEV(route_type_str, route_type)) { - if (command == PROCESS_COMMAND_ADD_PARENT_ID && CHECK_STREAM_RUNNING(stream, type)) { + if (command == PROCESS_COMMAND_ADD_STREAM && CHECK_STREAM_RUNNING(stream, type)) { if (type == STREAM_SINK_INPUT && m->cur_highest_priority.need_to_update_si) { m->cur_highest_priority.sink_input = stream; m->cur_highest_priority.role_si = role; @@ -2373,9 +2373,9 @@ process_stream_result_t process_stream(pa_stream_manager *m, void *stream, strea case PROCESS_COMMAND_UPDATE_VOLUME: result = handle_command_update_volume(m, stream, type, is_new_data); break; - case PROCESS_COMMAND_ADD_PARENT_ID: - case PROCESS_COMMAND_REMOVE_PARENT_ID: - result = handle_command_add_remove_parent_id(m, command, stream, type, is_new_data); + case PROCESS_COMMAND_ADD_STREAM: + case PROCESS_COMMAND_REMOVE_STREAM: + result = handle_command_add_remove_stream(m, command, stream, type, is_new_data); break; case PROCESS_COMMAND_UPDATE_BUFFER_ATTR: update_buffer_attribute(m, stream, type, is_new_data); @@ -2507,7 +2507,7 @@ static pa_hook_result_t sink_input_put_cb(pa_core *core, pa_sink_input *i, pa_st pa_log_info("sink-input(%p, index:%u)", i, i->index); - process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_ADD_PARENT_ID, false); + process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_ADD_STREAM, false); process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_APPLY_FILTER, false); process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_UPDATE_VOLUME, false); if (is_stream_related_call_active_routing(PA_OBJECT(i))) { @@ -2534,7 +2534,7 @@ static pa_hook_result_t sink_input_unlink_cb(pa_core *core, pa_sink_input *i, pa remove_sink_input_from_muted_streams(m, i); remove_sink_input_from_ducking_streams(m, i); - process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_REMOVE_PARENT_ID, false); + process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_REMOVE_STREAM, false); process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, false); return PA_HOOK_OK; @@ -2668,7 +2668,7 @@ static pa_hook_result_t source_output_put_cb(pa_core *core, pa_source_output *o, pa_log_info("source-output(%p, index:%u)", o, o->index); update_mirroring_streams(m, o, true); - process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_ADD_PARENT_ID, false); + process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_ADD_STREAM, false); process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_UPDATE_VOLUME, false); if (is_stream_related_call_active_routing(PA_OBJECT(o))) { change_active_route_for_call(m, PA_OBJECT(o), true); @@ -2690,7 +2690,7 @@ static pa_hook_result_t source_output_unlink_cb(pa_core *core, pa_source_output } update_mirroring_streams(m, o, false); process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, false); - process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_REMOVE_PARENT_ID, false); + process_stream(m, o, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_REMOVE_STREAM, false); return PA_HOOK_OK; } -- 2.7.4 From 6bce670f413163517cfbc107d8a9399924accf6c Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Thu, 18 Mar 2021 21:19:13 +0900 Subject: [PATCH 11/16] Add support for notifying stream connection information to the policy implementation [Version] 13.0.54 [Issue Type] New feature Change-Id: I63ebdd3e62a40d54b04e0ac83f1654015e6095cb Signed-off-by: Sangchul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/communicator.h | 1 + src/module-tizenaudio-policy.c | 16 ++++++++++++++ src/stream-manager.c | 38 ++++++++++++++++++++++++++------- src/stream-manager.h | 8 +++++++ 5 files changed, 56 insertions(+), 9 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 6c7bd8b..6478812 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.53 +Version: 13.0.54 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/communicator.h b/src/communicator.h index 6dd40fc..f41ef58 100644 --- a/src/communicator.h +++ b/src/communicator.h @@ -27,6 +27,7 @@ typedef enum pa_communicator_hook { PA_COMMUNICATOR_HOOK_SELECT_INIT_SINK_OR_SOURCE, /* It is fired when a stream is created and needs to be set to sink or source */ PA_COMMUNICATOR_HOOK_CHANGE_ROUTE, /* It is fired when routing using internal codec should be processed */ + PA_COMMUNICATOR_HOOK_STREAM_CONNECTION_CHANGED, /* It is fired when a stream is connected or disconnected */ PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED, /* It is fired when a device is connected or disconnected */ PA_COMMUNICATOR_HOOK_DEVICE_STATE_CHANGED, /* It is fired when a device's state is changed, it will be replaced by RUNNING_CHANGED */ PA_COMMUNICATOR_HOOK_DEVICE_RUNNING_CHANGED, /* It is fired when a device's running state is changed */ diff --git a/src/module-tizenaudio-policy.c b/src/module-tizenaudio-policy.c index 09759e3..6aa2778 100644 --- a/src/module-tizenaudio-policy.c +++ b/src/module-tizenaudio-policy.c @@ -158,6 +158,7 @@ struct userdata { pa_communicator *comm; pa_hook_slot *comm_hook_select_proper_sink_or_source_slot; pa_hook_slot *comm_hook_change_route_slot; + pa_hook_slot *comm_hook_stream_connection_changed_slot; pa_hook_slot *comm_hook_device_connection_changed_slot; pa_hook_slot *comm_hook_update_info_slot; } communicator; @@ -1675,6 +1676,18 @@ static pa_hook_result_t route_change_hook_cb(pa_core *c, pa_stream_manager_hook_ return PA_HOOK_OK; } +static pa_hook_result_t stream_connection_changed_hook_cb(pa_core *c, pa_stream_manager_hook_data_for_stream *data, struct userdata *u) { + pa_assert(c); + pa_assert(data); + pa_assert(u); + + pa_log_info("[STREAM][%s] stream(%p, type:%d, role:%s, parent_id:%s)", + data->is_connected ? "connected" : "disconnected", + data->stream, data->stream_type, data->stream_role, data->parent_id); + + return PA_HOOK_OK; +} + static pa_hook_result_t update_info_hook_cb(pa_core *c, pa_stream_manager_hook_data_for_update_info *data, struct userdata *u) { pa_assert(c); pa_assert(data); @@ -1821,6 +1834,9 @@ int pa__init(pa_module *m) u->communicator.comm_hook_change_route_slot = pa_hook_connect( pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_CHANGE_ROUTE), PA_HOOK_EARLY, (pa_hook_cb_t)route_change_hook_cb, u); + u->communicator.comm_hook_stream_connection_changed_slot = pa_hook_connect( + pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_STREAM_CONNECTION_CHANGED), + PA_HOOK_EARLY, (pa_hook_cb_t)stream_connection_changed_hook_cb, u); u->communicator.comm_hook_device_connection_changed_slot = pa_hook_connect( pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_DEVICE_CONNECTION_CHANGED), PA_HOOK_EARLY, (pa_hook_cb_t)device_connection_changed_hook_cb, u); diff --git a/src/stream-manager.c b/src/stream-manager.c index 8ff7dde..8232c1a 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -1793,6 +1793,25 @@ static ret_msg_t prepare_and_invoke_hook_to_change_route(pa_stream_manager *m, n return ret; } +static ret_msg_t prepare_and_invoke_hook_to_inform_stream_connection(pa_stream_manager *m, bool is_connected, + stream_type_t type, void *s) { + pa_stream_manager_hook_data_for_stream hook_call_stream_data; + + pa_assert(m); + pa_assert(s); + + hook_call_stream_data.stream = s; + hook_call_stream_data.stream_type = type; + hook_call_stream_data.stream_role = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_ROLE); + hook_call_stream_data.parent_id = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_PARENT_ID); + hook_call_stream_data.is_connected = is_connected; + + if (pa_hook_fire(pa_communicator_hook(m->comm.comm, PA_COMMUNICATOR_HOOK_STREAM_CONNECTION_CHANGED), &hook_call_stream_data)) + return RET_MSG_ERROR_INTERNAL; + + return RET_MSG_OK; +} + ret_msg_t do_notify(pa_stream_manager *m, notify_command_type_t command, stream_type_t type, bool is_new_data, void *user_data) { hal_stream_connection_info stream_conn_info; hal_route_option route_option; @@ -1838,14 +1857,17 @@ ret_msg_t do_notify(pa_stream_manager *m, notify_command_type_t command, stream_ pa_assert(user_data); memset(&stream_conn_info, 0, sizeof(hal_stream_connection_info)); s = user_data; - if (s) { - stream_conn_info.role = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_ROLE); - stream_conn_info.direction = (type == STREAM_SINK_INPUT) ? DIRECTION_OUT : DIRECTION_IN; - stream_conn_info.idx = GET_STREAM_INDEX(s, type); - stream_conn_info.is_connected = (command == NOTIFY_COMMAND_INFORM_STREAM_CONNECTED) ? true : false; - if (pa_hal_interface_notify_stream_connection_changed(m->hal, &stream_conn_info)) - ret = RET_MSG_ERROR_INTERNAL; - } + + ret = prepare_and_invoke_hook_to_inform_stream_connection(m, command == NOTIFY_COMMAND_INFORM_STREAM_CONNECTED, type, s); + if (ret != RET_MSG_OK) + pa_log_error("failed to prepare_and_invoke_hook_to_inform_stream_connection()"); + stream_conn_info.role = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_ROLE); + stream_conn_info.direction = (type == STREAM_SINK_INPUT) ? DIRECTION_OUT : DIRECTION_IN; + stream_conn_info.idx = GET_STREAM_INDEX(s, type); + stream_conn_info.is_connected = (command == NOTIFY_COMMAND_INFORM_STREAM_CONNECTED); + if (pa_hal_interface_notify_stream_connection_changed(m->hal, &stream_conn_info)) + ret = RET_MSG_ERROR_INTERNAL; + break; } } diff --git a/src/stream-manager.h b/src/stream-manager.h index 1aae92c..ffb9d34 100644 --- a/src/stream-manager.h +++ b/src/stream-manager.h @@ -146,6 +146,14 @@ typedef struct _hook_call_data_for_route { bool origins_from_new_data; } pa_stream_manager_hook_data_for_route; +typedef struct _hook_call_data_for_stream { + void *stream; + const char *stream_role; + const char *parent_id; + stream_type_t stream_type; + bool is_connected; +} pa_stream_manager_hook_data_for_stream; + typedef struct _hook_call_data_for_update_info { const char *stream_role; const char *name; -- 2.7.4 From 5e4cb76033a4a929c90b4dfb57e69c42ec3f58cc Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Fri, 19 Mar 2021 14:34:21 +0900 Subject: [PATCH 12/16] stream-manager: handle ramp finished task at core mainloop Sometimes sd handle is accessed simultaneously, which may leads to memory corruption. [Version] 13.0.55 [Issue Type] Bug fix Change-Id: I214c58c1ccde292c918033aaded695f6b59324ef --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-priv.h | 8 ++ src/stream-manager.c | 133 ++++++++++++++++++++++---------- 3 files changed, 101 insertions(+), 42 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 6478812..51228a8 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.54 +Version: 13.0.55 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-priv.h b/src/stream-manager-priv.h index 677deff..e3d9298 100644 --- a/src/stream-manager-priv.h +++ b/src/stream-manager-priv.h @@ -233,6 +233,10 @@ typedef struct _filter_info { uint32_t n_controls; } filter_info; +typedef struct _stream_manager_msg { + pa_msgobject parent; +} stream_manager_msg; + struct _stream_manager { PA_REFCNT_DECLARE; @@ -255,6 +259,10 @@ struct _stream_manager { pa_time_event *time_event_for_unmute; pa_hashmap *filter_infos; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + stream_manager_msg *msg; + pa_hook_slot *sink_input_new_slot, *sink_input_put_slot, diff --git a/src/stream-manager.c b/src/stream-manager.c index 8232c1a..9a69289 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -129,6 +129,17 @@ static const char* notify_command_type_str[] = { #define STREAM_MAP_STREAM_AVAIL_OUT_DEVICES "avail-out-devices" #define STREAM_MAP_STREAM_AVAIL_FRAMEWORKS "avail-frameworks" +PA_DEFINE_PRIVATE_CLASS(stream_manager_msg, pa_msgobject); + +enum { + MESSAGE_RAMP_FINISHED, +}; + +struct stream_manager_param { + pa_stream_manager *m; + pa_sink_input *i; +}; + static bool is_valid_notify_command(notify_command_type_t command) { return (command < sizeof(notify_command_type_str) / sizeof(char *)); } @@ -2566,7 +2577,7 @@ static pa_hook_result_t sink_input_state_changed_cb(pa_core *core, pa_sink_input pa_assert(i); pa_assert(m); - pa_log_debug("sink-input(%p, index:%u), state(%d)", i, i->index, i->state); + pa_log_debug("sink-input(%p, index:%u, state:%d)", i, i->index, i->state); switch (i->state) { case PA_SINK_INPUT_CORKED: @@ -2615,8 +2626,7 @@ static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input * } static pa_hook_result_t sink_input_ramp_finish_cb(pa_core *core, pa_sink_input *i, pa_stream_manager *m) { - stream_ducking *sd; - void *state; + struct stream_manager_param param = { m, i }; pa_core_assert_ref(core); pa_sink_input_assert_ref(i); @@ -2625,44 +2635,9 @@ static pa_hook_result_t sink_input_ramp_finish_cb(pa_core *core, pa_sink_input * if (core->state == PA_CORE_SHUTDOWN) return PA_HOOK_OK; - pa_log_debug("sink-input(%p, index:%u)", i, i->index); - - /* Find a context id from all the ducked stream list by this stream index. - * Check the number of managed streams of the context id, if it is the last one - * then broadcast a signal with context id.*/ - PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) { - if (!pa_idxset_get_by_data(sd->idx_ducking_streams, i, NULL)) { - pa_log_debug("not found matched stream(%p, index:%u) in sd(%p)", i, i->index, sd); - continue; - } - - pa_log_info("found matched stream(%p, index:%u) in sd(%p, ducking_stream_count:%d, state:%u)", - i, i->index, sd, sd->ducking_stream_count, sd->state); - - if (sd->ducking_stream_count <= 0) - continue; - - /* Remove trigger when unducked */ - if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) - pa_idxset_remove_by_data(sd->idx_ducking_streams, (void *)i, NULL); - - /* Send signal when all streams are ducked. - * Note that the condition of increasing count value below is located in - * handle_activate_ducking() of DBus handler. */ - if (--sd->ducking_stream_count == 0) { - if (sd->state == STREAM_DUCKING_STATE_DUCKING) { - sd->state = STREAM_DUCKING_STATE_DUCKED; - } else if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) { - sd->state = STREAM_DUCKING_STATE_UNDUCKED; - } else { - pa_log_warn("sd->state(%d), already ducked or unducked, skip sending signal", sd->state); - continue; - } - - pa_log_info("send signal for ramp finished - sd(%p, state:%u)", sd, sd->state); - send_ducking_state_changed_signal(pa_dbus_connection_get(m->dbus_conn), sd->trigger_index, is_stream_ducked(sd)); - } - } + pa_log_info("sink-input(%p, index:%u)", i, i->index); + pa_asyncmsgq_send(m->thread_mq.outq, PA_MSGOBJECT(m->msg), MESSAGE_RAMP_FINISHED, ¶m, 0, NULL); + pa_log_info("sink-input(%p, index:%u) : pa_asyncmsgq_send() done", i, i->index); return PA_HOOK_OK; } @@ -3765,6 +3740,70 @@ const char* pa_stream_manager_get_volume_type(pa_stream_manager *m, stream_type_ return s->volume_types[stream_type == STREAM_SINK_INPUT ? STREAM_DIRECTION_OUT : STREAM_DIRECTION_IN]; } +static int stream_manager_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct stream_manager_param* param = (struct stream_manager_param*)data; + pa_stream_manager *m; + pa_sink_input *i; + stream_ducking *sd; + void *state; + + pa_assert(param); + + m = param->m; + i = param->i; + + pa_log_info("code(%d), sink-input(%p, index:%u, state:%d)", code, i, i->index, i->state); + + if (param->m->core->state == PA_CORE_SHUTDOWN) + return 0; + + switch (code) { + case MESSAGE_RAMP_FINISHED: + /* Find a context id from all the ducked stream list by this stream index. + * Check the number of managed streams of the context id, if it is the last one + * then broadcast a signal with context id.*/ + PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) { + if (!pa_idxset_get_by_data(sd->idx_ducking_streams, i, NULL)) { + pa_log_debug("not found matched stream(%p, index:%u) in sd(%p)", i, i->index, sd); + continue; + } + + pa_log_info("found matched stream(%p, index:%u) in sd(%p, ducking_stream_count:%d, state:%u)", + i, i->index, sd, sd->ducking_stream_count, sd->state); + + if (sd->ducking_stream_count <= 0) + continue; + + /* Remove trigger when unducked */ + if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) + pa_idxset_remove_by_data(sd->idx_ducking_streams, (void *)i, NULL); + + /* Send signal when all streams are ducked. + * Note that the condition of increasing count value below is located in + * handle_activate_ducking() of DBus handler. */ + if (--sd->ducking_stream_count == 0) { + if (sd->state == STREAM_DUCKING_STATE_DUCKING) { + sd->state = STREAM_DUCKING_STATE_DUCKED; + } else if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) { + sd->state = STREAM_DUCKING_STATE_UNDUCKED; + } else { + pa_log_warn("sd->state(%d), already ducked or unducked, skip sending signal", sd->state); + continue; + } + + pa_log_info("send signal for ramp finished - sd(%p, state:%u)", sd, sd->state); + send_ducking_state_changed_signal(pa_dbus_connection_get(m->dbus_conn), sd->trigger_index, is_stream_ducked(sd)); + } + } + break; + + default: + pa_assert_not_reached(); + } + + return 0; +} + pa_stream_manager* pa_stream_manager_get(pa_core *c) { pa_stream_manager *m; @@ -3779,6 +3818,14 @@ pa_stream_manager* pa_stream_manager_get(pa_core *c) { PA_REFCNT_INIT(m); m->core = c; + m->rtpoll = pa_rtpoll_new(); + if (pa_thread_mq_init(&m->thread_mq, m->core->mainloop, m->rtpoll) < 0) { + pa_log("pa_thread_mq_init() failed."); + goto fail; + } + m->msg = pa_msgobject_new(stream_manager_msg); + m->msg->parent.process_msg = stream_manager_process_msg; + if (!(m->hal = pa_hal_interface_get(c))) goto fail; @@ -3921,6 +3968,10 @@ void pa_stream_manager_unref(pa_stream_manager *m) { if (PA_REFCNT_DEC(m) > 0) return; + pa_thread_mq_done(&m->thread_mq); + pa_rtpoll_free(m->rtpoll); + pa_xfree(m->msg); + free_hook_slots(m); if (m->comm.comm) -- 2.7.4 From 1a8818f89985dc752e2d95b021803d2edbdb70d6 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Tue, 23 Mar 2021 20:30:55 +0900 Subject: [PATCH 13/16] Revert "stream-manager: handle ramp finished task at core mainloop" [Version] 13.0.56 [Issue Type] Revert This reverts commit 5e4cb76033a4a929c90b4dfb57e69c42ec3f58cc. Change-Id: I04b5587085b31c29ed57dabac3c42ccc0b4f9869 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-priv.h | 8 -- src/stream-manager.c | 133 ++++++++++---------------------- 3 files changed, 42 insertions(+), 101 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 51228a8..2214288 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.55 +Version: 13.0.56 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-priv.h b/src/stream-manager-priv.h index e3d9298..677deff 100644 --- a/src/stream-manager-priv.h +++ b/src/stream-manager-priv.h @@ -233,10 +233,6 @@ typedef struct _filter_info { uint32_t n_controls; } filter_info; -typedef struct _stream_manager_msg { - pa_msgobject parent; -} stream_manager_msg; - struct _stream_manager { PA_REFCNT_DECLARE; @@ -259,10 +255,6 @@ struct _stream_manager { pa_time_event *time_event_for_unmute; pa_hashmap *filter_infos; - pa_thread_mq thread_mq; - pa_rtpoll *rtpoll; - stream_manager_msg *msg; - pa_hook_slot *sink_input_new_slot, *sink_input_put_slot, diff --git a/src/stream-manager.c b/src/stream-manager.c index 9a69289..8232c1a 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -129,17 +129,6 @@ static const char* notify_command_type_str[] = { #define STREAM_MAP_STREAM_AVAIL_OUT_DEVICES "avail-out-devices" #define STREAM_MAP_STREAM_AVAIL_FRAMEWORKS "avail-frameworks" -PA_DEFINE_PRIVATE_CLASS(stream_manager_msg, pa_msgobject); - -enum { - MESSAGE_RAMP_FINISHED, -}; - -struct stream_manager_param { - pa_stream_manager *m; - pa_sink_input *i; -}; - static bool is_valid_notify_command(notify_command_type_t command) { return (command < sizeof(notify_command_type_str) / sizeof(char *)); } @@ -2577,7 +2566,7 @@ static pa_hook_result_t sink_input_state_changed_cb(pa_core *core, pa_sink_input pa_assert(i); pa_assert(m); - pa_log_debug("sink-input(%p, index:%u, state:%d)", i, i->index, i->state); + pa_log_debug("sink-input(%p, index:%u), state(%d)", i, i->index, i->state); switch (i->state) { case PA_SINK_INPUT_CORKED: @@ -2626,7 +2615,8 @@ static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input * } static pa_hook_result_t sink_input_ramp_finish_cb(pa_core *core, pa_sink_input *i, pa_stream_manager *m) { - struct stream_manager_param param = { m, i }; + stream_ducking *sd; + void *state; pa_core_assert_ref(core); pa_sink_input_assert_ref(i); @@ -2635,9 +2625,44 @@ static pa_hook_result_t sink_input_ramp_finish_cb(pa_core *core, pa_sink_input * if (core->state == PA_CORE_SHUTDOWN) return PA_HOOK_OK; - pa_log_info("sink-input(%p, index:%u)", i, i->index); - pa_asyncmsgq_send(m->thread_mq.outq, PA_MSGOBJECT(m->msg), MESSAGE_RAMP_FINISHED, ¶m, 0, NULL); - pa_log_info("sink-input(%p, index:%u) : pa_asyncmsgq_send() done", i, i->index); + pa_log_debug("sink-input(%p, index:%u)", i, i->index); + + /* Find a context id from all the ducked stream list by this stream index. + * Check the number of managed streams of the context id, if it is the last one + * then broadcast a signal with context id.*/ + PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) { + if (!pa_idxset_get_by_data(sd->idx_ducking_streams, i, NULL)) { + pa_log_debug("not found matched stream(%p, index:%u) in sd(%p)", i, i->index, sd); + continue; + } + + pa_log_info("found matched stream(%p, index:%u) in sd(%p, ducking_stream_count:%d, state:%u)", + i, i->index, sd, sd->ducking_stream_count, sd->state); + + if (sd->ducking_stream_count <= 0) + continue; + + /* Remove trigger when unducked */ + if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) + pa_idxset_remove_by_data(sd->idx_ducking_streams, (void *)i, NULL); + + /* Send signal when all streams are ducked. + * Note that the condition of increasing count value below is located in + * handle_activate_ducking() of DBus handler. */ + if (--sd->ducking_stream_count == 0) { + if (sd->state == STREAM_DUCKING_STATE_DUCKING) { + sd->state = STREAM_DUCKING_STATE_DUCKED; + } else if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) { + sd->state = STREAM_DUCKING_STATE_UNDUCKED; + } else { + pa_log_warn("sd->state(%d), already ducked or unducked, skip sending signal", sd->state); + continue; + } + + pa_log_info("send signal for ramp finished - sd(%p, state:%u)", sd, sd->state); + send_ducking_state_changed_signal(pa_dbus_connection_get(m->dbus_conn), sd->trigger_index, is_stream_ducked(sd)); + } + } return PA_HOOK_OK; } @@ -3740,70 +3765,6 @@ const char* pa_stream_manager_get_volume_type(pa_stream_manager *m, stream_type_ return s->volume_types[stream_type == STREAM_SINK_INPUT ? STREAM_DIRECTION_OUT : STREAM_DIRECTION_IN]; } -static int stream_manager_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { - struct stream_manager_param* param = (struct stream_manager_param*)data; - pa_stream_manager *m; - pa_sink_input *i; - stream_ducking *sd; - void *state; - - pa_assert(param); - - m = param->m; - i = param->i; - - pa_log_info("code(%d), sink-input(%p, index:%u, state:%d)", code, i, i->index, i->state); - - if (param->m->core->state == PA_CORE_SHUTDOWN) - return 0; - - switch (code) { - case MESSAGE_RAMP_FINISHED: - /* Find a context id from all the ducked stream list by this stream index. - * Check the number of managed streams of the context id, if it is the last one - * then broadcast a signal with context id.*/ - PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) { - if (!pa_idxset_get_by_data(sd->idx_ducking_streams, i, NULL)) { - pa_log_debug("not found matched stream(%p, index:%u) in sd(%p)", i, i->index, sd); - continue; - } - - pa_log_info("found matched stream(%p, index:%u) in sd(%p, ducking_stream_count:%d, state:%u)", - i, i->index, sd, sd->ducking_stream_count, sd->state); - - if (sd->ducking_stream_count <= 0) - continue; - - /* Remove trigger when unducked */ - if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) - pa_idxset_remove_by_data(sd->idx_ducking_streams, (void *)i, NULL); - - /* Send signal when all streams are ducked. - * Note that the condition of increasing count value below is located in - * handle_activate_ducking() of DBus handler. */ - if (--sd->ducking_stream_count == 0) { - if (sd->state == STREAM_DUCKING_STATE_DUCKING) { - sd->state = STREAM_DUCKING_STATE_DUCKED; - } else if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) { - sd->state = STREAM_DUCKING_STATE_UNDUCKED; - } else { - pa_log_warn("sd->state(%d), already ducked or unducked, skip sending signal", sd->state); - continue; - } - - pa_log_info("send signal for ramp finished - sd(%p, state:%u)", sd, sd->state); - send_ducking_state_changed_signal(pa_dbus_connection_get(m->dbus_conn), sd->trigger_index, is_stream_ducked(sd)); - } - } - break; - - default: - pa_assert_not_reached(); - } - - return 0; -} - pa_stream_manager* pa_stream_manager_get(pa_core *c) { pa_stream_manager *m; @@ -3818,14 +3779,6 @@ pa_stream_manager* pa_stream_manager_get(pa_core *c) { PA_REFCNT_INIT(m); m->core = c; - m->rtpoll = pa_rtpoll_new(); - if (pa_thread_mq_init(&m->thread_mq, m->core->mainloop, m->rtpoll) < 0) { - pa_log("pa_thread_mq_init() failed."); - goto fail; - } - m->msg = pa_msgobject_new(stream_manager_msg); - m->msg->parent.process_msg = stream_manager_process_msg; - if (!(m->hal = pa_hal_interface_get(c))) goto fail; @@ -3968,10 +3921,6 @@ void pa_stream_manager_unref(pa_stream_manager *m) { if (PA_REFCNT_DEC(m) > 0) return; - pa_thread_mq_done(&m->thread_mq); - pa_rtpoll_free(m->rtpoll); - pa_xfree(m->msg); - free_hook_slots(m); if (m->comm.comm) -- 2.7.4 From 98cb10c7170457fe5960cdcd56aa6f179f1d1990 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Wed, 24 Mar 2021 16:08:00 +0900 Subject: [PATCH 14/16] stream-manager: handle ramp finished task only at the main thread Sometimes sd handle is accessed simultaneously in different thread, which may leads to memory corruption. This patch makes to handle ramp finish task directly only if inside of main thread. Otherwise, request a message to make it handle from the main thread. To avoid possible deadlock, request by posting(async) instead of send(sync). [Version] 13.0.57 [Issue Type] Bug fix Change-Id: I178dbc5b29adccc6f74e41b7e105681c3fd570d0 --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-priv.h | 8 ++ src/stream-manager.c | 158 ++++++++++++++++++++++++-------- 3 files changed, 128 insertions(+), 40 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 2214288..f01676e 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.56 +Version: 13.0.57 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-priv.h b/src/stream-manager-priv.h index 677deff..e3d9298 100644 --- a/src/stream-manager-priv.h +++ b/src/stream-manager-priv.h @@ -233,6 +233,10 @@ typedef struct _filter_info { uint32_t n_controls; } filter_info; +typedef struct _stream_manager_msg { + pa_msgobject parent; +} stream_manager_msg; + struct _stream_manager { PA_REFCNT_DECLARE; @@ -255,6 +259,10 @@ struct _stream_manager { pa_time_event *time_event_for_unmute; pa_hashmap *filter_infos; + pa_thread_mq thread_mq; + pa_rtpoll *rtpoll; + stream_manager_msg *msg; + pa_hook_slot *sink_input_new_slot, *sink_input_put_slot, diff --git a/src/stream-manager.c b/src/stream-manager.c index 8232c1a..8dec615 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -129,6 +129,62 @@ static const char* notify_command_type_str[] = { #define STREAM_MAP_STREAM_AVAIL_OUT_DEVICES "avail-out-devices" #define STREAM_MAP_STREAM_AVAIL_FRAMEWORKS "avail-frameworks" +PA_DEFINE_PRIVATE_CLASS(stream_manager_msg, pa_msgobject); + +enum { + MESSAGE_RAMP_FINISHED, +}; + +struct stream_manager_param { + pa_stream_manager *m; + pa_sink_input *sink_input; + uint32_t index; +}; + +/* Called from main context */ +static void process_ramp_finish(struct stream_manager_param *param) { + stream_ducking *sd; + void *state; + + /* Find a context id from all the ducked stream list by this stream index. + * Check the number of managed streams of the context id, if it is the last one + * then broadcast a signal with context id.*/ + PA_HASHMAP_FOREACH(sd, param->m->stream_duckings, state) { + if (!pa_idxset_get_by_data(sd->idx_ducking_streams, param->sink_input, NULL)) { + pa_log_debug("not found matched stream(%p, index:%u) in sd(%p)", + param->sink_input, param->index, sd); + continue; + } + + pa_log_info("found matched stream(%p, index:%u) in sd(%p, ducking_stream_count:%d, state:%u)", + param->sink_input, param->index, sd, sd->ducking_stream_count, sd->state); + + if (sd->ducking_stream_count <= 0) + continue; + + /* Remove trigger when unducked */ + if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) + pa_idxset_remove_by_data(sd->idx_ducking_streams, (void *)param->sink_input, NULL); + + /* Send signal when all streams are ducked. + * Note that the condition of increasing count value below is located in + * handle_activate_ducking() of DBus handler. */ + if (--sd->ducking_stream_count == 0) { + if (sd->state == STREAM_DUCKING_STATE_DUCKING) { + sd->state = STREAM_DUCKING_STATE_DUCKED; + } else if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) { + sd->state = STREAM_DUCKING_STATE_UNDUCKED; + } else { + pa_log_warn("sd->state(%d), already ducked or unducked, skip sending signal", sd->state); + continue; + } + + pa_log_info("send signal for ramp finished - sd(%p, state:%u)", sd, sd->state); + send_ducking_state_changed_signal(pa_dbus_connection_get(param->m->dbus_conn), sd->trigger_index, is_stream_ducked(sd)); + } + } +} + static bool is_valid_notify_command(notify_command_type_t command) { return (command < sizeof(notify_command_type_str) / sizeof(char *)); } @@ -1966,7 +2022,7 @@ static process_stream_result_t handle_command_prepare(pa_stream_manager *m, void pa_assert(stream); if (type == STREAM_SINK_INPUT) { - /* Parse request formats for samplerate, channel, format infomation */ + /* Parse request formats for samplerate, channel, format information */ if (((pa_sink_input_new_data*)stream)->req_formats) { req_format = pa_idxset_first(((pa_sink_input_new_data*)stream)->req_formats, NULL); if (req_format && req_format->plist) { @@ -2566,7 +2622,7 @@ static pa_hook_result_t sink_input_state_changed_cb(pa_core *core, pa_sink_input pa_assert(i); pa_assert(m); - pa_log_debug("sink-input(%p, index:%u), state(%d)", i, i->index, i->state); + pa_log_debug("sink-input(%p, index:%u, state:%d)", i, i->index, i->state); switch (i->state) { case PA_SINK_INPUT_CORKED: @@ -2614,9 +2670,15 @@ static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input * return PA_HOOK_OK; } +static bool is_in_main_thread() +{ + return (getpid() == gettid()); +} + +/* Called from either IO thread context or main context */ +/* FIXME : make this callback be invoked from the main context only */ static pa_hook_result_t sink_input_ramp_finish_cb(pa_core *core, pa_sink_input *i, pa_stream_manager *m) { - stream_ducking *sd; - void *state; + struct stream_manager_param param; pa_core_assert_ref(core); pa_sink_input_assert_ref(i); @@ -2625,43 +2687,20 @@ static pa_hook_result_t sink_input_ramp_finish_cb(pa_core *core, pa_sink_input * if (core->state == PA_CORE_SHUTDOWN) return PA_HOOK_OK; - pa_log_debug("sink-input(%p, index:%u)", i, i->index); - - /* Find a context id from all the ducked stream list by this stream index. - * Check the number of managed streams of the context id, if it is the last one - * then broadcast a signal with context id.*/ - PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) { - if (!pa_idxset_get_by_data(sd->idx_ducking_streams, i, NULL)) { - pa_log_debug("not found matched stream(%p, index:%u) in sd(%p)", i, i->index, sd); - continue; - } - - pa_log_info("found matched stream(%p, index:%u) in sd(%p, ducking_stream_count:%d, state:%u)", - i, i->index, sd, sd->ducking_stream_count, sd->state); - - if (sd->ducking_stream_count <= 0) - continue; - - /* Remove trigger when unducked */ - if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) - pa_idxset_remove_by_data(sd->idx_ducking_streams, (void *)i, NULL); + param.m = m; + param.sink_input = i; + param.index = i->index; - /* Send signal when all streams are ducked. - * Note that the condition of increasing count value below is located in - * handle_activate_ducking() of DBus handler. */ - if (--sd->ducking_stream_count == 0) { - if (sd->state == STREAM_DUCKING_STATE_DUCKING) { - sd->state = STREAM_DUCKING_STATE_DUCKED; - } else if (sd->state == STREAM_DUCKING_STATE_UNDUCKING) { - sd->state = STREAM_DUCKING_STATE_UNDUCKED; - } else { - pa_log_warn("sd->state(%d), already ducked or unducked, skip sending signal", sd->state); - continue; - } + pa_log_info("sink-input(%p, index:%u)", i, i->index); - pa_log_info("send signal for ramp finished - sd(%p, state:%u)", sd, sd->state); - send_ducking_state_changed_signal(pa_dbus_connection_get(m->dbus_conn), sd->trigger_index, is_stream_ducked(sd)); - } + if (is_in_main_thread()) { + process_ramp_finish(¶m); + pa_log_info("sink-input(%p, index:%u) : direct process_ramp_finish() done", i, i->index); + } else { + /* Post message to make process_ramp_finish() run from main thread */ + pa_asyncmsgq_post(m->thread_mq.outq, PA_MSGOBJECT(m->msg), MESSAGE_RAMP_FINISHED, + pa_xmemdup(¶m, sizeof(struct stream_manager_param)), 0, NULL, pa_xfree); + pa_log_info("sink-input(%p, index:%u) : posting MESSAGE_RAMP_FINISHED done", i, i->index); } return PA_HOOK_OK; @@ -3765,6 +3804,30 @@ const char* pa_stream_manager_get_volume_type(pa_stream_manager *m, stream_type_ return s->volume_types[stream_type == STREAM_SINK_INPUT ? STREAM_DIRECTION_OUT : STREAM_DIRECTION_IN]; } +static int stream_manager_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { + struct stream_manager_param *param = (struct stream_manager_param *)data; + + pa_assert(param); + pa_assert(param->m); + pa_assert(param->m->core); + + pa_log_info("code(%d), sink-input(%p, index:%u)", code, param->sink_input, param->index); + + if (param->m->core->state == PA_CORE_SHUTDOWN) + return 0; + + switch (code) { + case MESSAGE_RAMP_FINISHED: + process_ramp_finish(param); + break; + + default: + pa_assert_not_reached(); + } + + return 0; +} + pa_stream_manager* pa_stream_manager_get(pa_core *c) { pa_stream_manager *m; @@ -3779,6 +3842,14 @@ pa_stream_manager* pa_stream_manager_get(pa_core *c) { PA_REFCNT_INIT(m); m->core = c; + m->rtpoll = pa_rtpoll_new(); + if (pa_thread_mq_init(&m->thread_mq, m->core->mainloop, m->rtpoll) < 0) { + pa_log("pa_thread_mq_init() failed."); + goto fail; + } + m->msg = pa_msgobject_new(stream_manager_msg); + m->msg->parent.process_msg = stream_manager_process_msg; + if (!(m->hal = pa_hal_interface_get(c))) goto fail; @@ -3840,6 +3911,11 @@ pa_stream_manager* pa_stream_manager_get(pa_core *c) { fail: pa_log_error("failed to initialize stream-manager"); + + pa_thread_mq_done(&m->thread_mq); + pa_rtpoll_free(m->rtpoll); + pa_xfree(m->msg); + deinit_volumes(m); deinit_stream_map(m); deinit_filters(m); @@ -3921,6 +3997,10 @@ void pa_stream_manager_unref(pa_stream_manager *m) { if (PA_REFCNT_DEC(m) > 0) return; + pa_thread_mq_done(&m->thread_mq); + pa_rtpoll_free(m->rtpoll); + pa_xfree(m->msg); + free_hook_slots(m); if (m->comm.comm) -- 2.7.4 From cccecc52adeea52077908828d9125610234151ac Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Wed, 17 Mar 2021 13:22:30 +0900 Subject: [PATCH 15/16] stream-manager: Pass parent id when calling callback for selecting sink or source It is also fixed to pass parent_id as unsigned integer to STREAM CONNECTION CHANGED callback. [Version] 13.0.58 [Issue Type] Improvement Change-Id: I64d300df0c7cc3f68fa97d6bffb809e38421801f Signed-off-by: Sangchul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/module-tizenaudio-policy.c | 6 +++--- src/stream-manager.c | 25 ++++++++++++++++++++----- src/stream-manager.h | 3 ++- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index f01676e..0b48635 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.57 +Version: 13.0.58 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/module-tizenaudio-policy.c b/src/module-tizenaudio-policy.c index 6aa2778..c18391c 100644 --- a/src/module-tizenaudio-policy.c +++ b/src/module-tizenaudio-policy.c @@ -971,8 +971,8 @@ static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stre pa_assert(data); pa_assert(u); - pa_log_info("[SELECT] data(%p), stream_type(%d), stream_role(%s), device_role(%s), route_type(%d)", - data, data->stream_type, data->stream_role, data->device_role, data->route_type); + pa_log_info("[SELECT] data(%p), stream_type(%d), stream_role(%s), device_role(%s), route_type(%d), parent_id(%d)", + data, data->stream_type, data->stream_role, data->device_role, data->route_type, data->parent_id); null_sink = (pa_sink*)pa_namereg_get(u->core, SINK_NAME_NULL, PA_NAMEREG_SINK); null_source = (pa_source*)pa_namereg_get(u->core, SOURCE_NAME_NULL, PA_NAMEREG_SOURCE); @@ -1681,7 +1681,7 @@ static pa_hook_result_t stream_connection_changed_hook_cb(pa_core *c, pa_stream_ pa_assert(data); pa_assert(u); - pa_log_info("[STREAM][%s] stream(%p, type:%d, role:%s, parent_id:%s)", + pa_log_info("[STREAM][%s] stream(%p, type:%d, role:%s, parent_id:%d)", data->is_connected ? "connected" : "disconnected", data->stream, data->stream_type, data->stream_role, data->parent_id); diff --git a/src/stream-manager.c b/src/stream-manager.c index 8dec615..15c1191 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -1718,6 +1718,8 @@ static ret_msg_t prepare_and_invoke_hook_to_select_device(pa_stream_manager *m, pa_stream_manager_hook_data_for_select hook_call_select_data; pa_idxset *filtered_avail_devices = NULL; void *s = NULL; + const char *parent_id; + uint32_t parent_id_u; pa_assert(m); pa_assert(user_data); @@ -1760,6 +1762,13 @@ static ret_msg_t prepare_and_invoke_hook_to_select_device(pa_stream_manager *m, if (hook_call_select_data.route_type == STREAM_ROUTE_TYPE_MANUAL) CONVERT_TO_DEVICE_ROLE(hook_call_select_data.stream_role, hook_call_select_data.device_role); + parent_id = is_new_data ? pa_proplist_gets(GET_STREAM_NEW_PROPLIST(s, type), PA_PROP_MEDIA_PARENT_ID) : + pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_PARENT_ID); + if (parent_id && pa_atou(parent_id, &parent_id_u) == 0) + hook_call_select_data.parent_id = parent_id_u; + else + hook_call_select_data.parent_id = -1; + if (pa_hook_fire(pa_communicator_hook(m->comm.comm, PA_COMMUNICATOR_HOOK_SELECT_INIT_SINK_OR_SOURCE), &hook_call_select_data)) { ret = RET_MSG_ERROR_INTERNAL; } else { @@ -1820,8 +1829,6 @@ static ret_msg_t prepare_and_invoke_hook_to_change_route(pa_stream_manager *m, n hook_call_route_data.stream = NULL; } } - if (pa_hook_fire(pa_communicator_hook(m->comm.comm, PA_COMMUNICATOR_HOOK_CHANGE_ROUTE), &hook_call_route_data)) - ret = RET_MSG_ERROR_INTERNAL; } else { memset(&hook_call_route_data, 0, sizeof(pa_stream_manager_hook_data_for_route)); @@ -1842,24 +1849,32 @@ static ret_msg_t prepare_and_invoke_hook_to_change_route(pa_stream_manager *m, n hook_call_route_data.stream = NULL; hook_call_route_data.stream_type = type; } - if (pa_hook_fire(pa_communicator_hook(m->comm.comm, PA_COMMUNICATOR_HOOK_CHANGE_ROUTE), &hook_call_route_data)) - ret = RET_MSG_ERROR_INTERNAL; } + if (pa_hook_fire(pa_communicator_hook(m->comm.comm, PA_COMMUNICATOR_HOOK_CHANGE_ROUTE), &hook_call_route_data)) + ret = RET_MSG_ERROR_INTERNAL; + return ret; } static ret_msg_t prepare_and_invoke_hook_to_inform_stream_connection(pa_stream_manager *m, bool is_connected, stream_type_t type, void *s) { pa_stream_manager_hook_data_for_stream hook_call_stream_data; + const char *parent_id; + uint32_t parent_id_u; pa_assert(m); pa_assert(s); + memset(&hook_call_stream_data, 0, sizeof(pa_stream_manager_hook_data_for_stream)); hook_call_stream_data.stream = s; hook_call_stream_data.stream_type = type; hook_call_stream_data.stream_role = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_ROLE); - hook_call_stream_data.parent_id = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_PARENT_ID); + parent_id = pa_proplist_gets(GET_STREAM_PROPLIST(s, type), PA_PROP_MEDIA_PARENT_ID); + if (parent_id && pa_atou(parent_id, &parent_id_u) == 0) + hook_call_stream_data.parent_id = parent_id_u; + else + hook_call_stream_data.parent_id = -1; hook_call_stream_data.is_connected = is_connected; if (pa_hook_fire(pa_communicator_hook(m->comm.comm, PA_COMMUNICATOR_HOOK_STREAM_CONNECTION_CHANGED), &hook_call_stream_data)) diff --git a/src/stream-manager.h b/src/stream-manager.h index ffb9d34..96b8fb2 100644 --- a/src/stream-manager.h +++ b/src/stream-manager.h @@ -119,6 +119,7 @@ typedef struct _hook_call_data_for_select { const char *stream_role; const char *device_role; const char *occupying_role; + int32_t parent_id; stream_type_t stream_type; stream_route_type_t route_type; pa_sink **proper_sink; @@ -149,7 +150,7 @@ typedef struct _hook_call_data_for_route { typedef struct _hook_call_data_for_stream { void *stream; const char *stream_role; - const char *parent_id; + int32_t parent_id; stream_type_t stream_type; bool is_connected; } pa_stream_manager_hook_data_for_stream; -- 2.7.4 From 64bf38bd9afae04238769bdb724a163e578ee1a2 Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Fri, 19 Mar 2021 08:58:42 +0900 Subject: [PATCH 16/16] tizenaudio-policy: Preparation for new loopback module management [Version] 13.0.59 [Issue Type] Improvement Change-Id: I1fa78fdc41913f0db7e8d08b0ebe4d4c33b21c62 Signed-off-by: Sangchul Lee --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/module-tizenaudio-policy.c | 152 ++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 0b48635..e0f63c5 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 13.0.58 +Version: 13.0.59 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/module-tizenaudio-policy.c b/src/module-tizenaudio-policy.c index c18391c..bb3a727 100644 --- a/src/module-tizenaudio-policy.c +++ b/src/module-tizenaudio-policy.c @@ -150,6 +150,12 @@ static device_type_t convert_device_type_str(const char *device) return DEVICE_UNKNOWN; } +typedef struct _loopback_module { + pa_sink *sink; + pa_source *source; + pa_module *module; +} loopback_module; + struct userdata { pa_core *core; pa_module *module; @@ -172,6 +178,7 @@ struct userdata { uint32_t module_null_sink_index; uint32_t module_null_source_index; pa_module *module_loopback; + pa_hashmap *loopback_modules; struct { int32_t latency_msec; int32_t adjust_sec; @@ -446,6 +453,134 @@ static void update_bt_sco_option(struct userdata *u, const char* role) { } } +static void update_loopback_module_args(struct userdata* u, int32_t parent_id, pa_sink *sink, pa_source *source) +{ + loopback_module *loopback; + + pa_assert(u); + + if (parent_id < 0) { + pa_log_error("invalid parent_id(%d)", parent_id); + return; + } + + loopback = pa_hashmap_get(u->loopback_modules, (const void*)parent_id); + if (!loopback) { + loopback = pa_xnew0(loopback_module, 1); + pa_hashmap_put(u->loopback_modules, (void*)parent_id, loopback); + } + if (sink) + loopback->sink = sink; + if (source) + loopback->source = source; + + pa_log_info("loopback module for parent_id(%d) is updated, sink(%s), source(%s)", + parent_id, loopback->sink ? loopback->sink->name : "null", loopback->source ? loopback->source->name : "null"); +} + +static void load_loopback_module_by_parent_id(struct userdata* u, int32_t parent_id) +{ + loopback_module *loopback; + char *args; + const char *volume_type; + + pa_assert(u); + + if (parent_id < 0) { + pa_log_error("invalid parent_id(%d)", parent_id); + return; + } + + loopback = pa_hashmap_get(u->loopback_modules, (const void*)parent_id); + if (!loopback) { + pa_log_error("could not find loopback module for parent_id(%d)", parent_id); + return; + } + + if (!loopback->sink || !loopback->source) { + pa_log_debug("sink(%p) or source(%p) is not set", loopback->sink, loopback->source); + return; + } + + if (!u->loopback_args.latency_msec) + u->loopback_args.latency_msec = LOOPBACK_DEFAULT_LATENCY_MSEC; + if (!u->loopback_args.adjust_sec) + u->loopback_args.adjust_sec = LOOPBACK_DEFAULT_ADJUST_SEC; + + volume_type = pa_stream_manager_get_volume_type(u->stream_manager, STREAM_SINK_INPUT, STREAM_ROLE_LOOPBACK); + args = pa_sprintf_malloc("sink=%s source=%s latency_msec=%d adjust_time=%d sink_input_properties=%s=%s", + loopback->sink->name, loopback->source->name, + u->loopback_args.latency_msec, u->loopback_args.adjust_sec, + PA_PROP_MEDIA_TIZEN_VOLUME_TYPE, volume_type); + + if (pa_module_load(&loopback->module, u->core, MODULE_LOOPBACK, args)) + pa_log_error("failed to load module-loopback for parent_id(%d) with (%s)", parent_id, args); + else + pa_log_info("load module-loopback(%p) for parent_id(%d) with (%s)", loopback->module, parent_id, args); + + pa_xfree(args); +} + +static void unload_loopback_modules_by_device_disconnect(struct userdata* u, pa_sink *sink, pa_source *source) +{ + loopback_module *loopback; + int32_t parent_id; + void *state; + + pa_assert(u); + + pa_log_info("disconnected sink(%s), source(%s)", sink ? sink->name : "null", source ? source->name : "null"); + + PA_HASHMAP_FOREACH_KV(parent_id, loopback, u->loopback_modules, state) { + if (loopback->module && + ((sink && (loopback->sink == sink)) || + (source && (loopback->source == source)))) { + pa_log_info(" -- unload module-loopback(%p) for parent_id(%d)", loopback->module, parent_id); + pa_hashmap_remove_and_free(u->loopback_modules, (const void*)parent_id); + } + } +} + +static void unload_loopback_modules_by_stream_disconnect(struct userdata* u, int32_t parent_id, pa_sink_input *i, pa_source_output *o) +{ + loopback_module *loopback; + + pa_assert(u); + + if (parent_id < 0) + return; + + if (!i && !o) + return; + + loopback = pa_hashmap_get(u->loopback_modules, (const void*)parent_id); + if (!loopback) + return; + + if (!loopback->module) { + pa_log_info("module is not loaded yet"); + return; + } + + pa_log_info("disconnected sink-input(%p) or source-output(%p) of parent_id(%d)", i, o, parent_id); + + if (i && loopback->sink) + if (pa_idxset_get_by_data(loopback->sink->inputs, i, NULL) && pa_idxset_size(loopback->sink->inputs)) + goto unload; + + if (o && loopback->source) + if (pa_idxset_get_by_data(loopback->source->outputs, o, NULL) && pa_idxset_size(loopback->source->outputs)) + goto unload; + + pa_log_warn("no loopback module to be unloaded with parent_id(%d), sink-input(%p), source-output(%p)", parent_id, i, o); + + return; + +unload: + pa_log_info(" -- unload module-loopback(%p) for parent_id(%d)", loopback->module, parent_id); + pa_hashmap_remove_and_free(u->loopback_modules, (const void*)parent_id); +} + /* Load/Unload module-loopback */ static void update_loopback_module(struct userdata *u, bool load) { char *args = NULL; @@ -1801,6 +1936,16 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_tz_devi return PA_HOOK_OK; } +static void loopback_module_free(loopback_module *loopback) { + pa_assert(loopback); + + pa_log_info("unload module-loopback(%p)", loopback->module); + + pa_module_unload(loopback->module, true); + + pa_xfree(loopback); +} + int pa__init(pa_module *m) { pa_modargs *ma = NULL; @@ -1862,6 +2007,8 @@ int pa__init(pa_module *m) u->module_null_source_index = module_loaded->index; pa_xfree(args); + u->loopback_modules = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, (pa_free_cb_t)loopback_module_free); + __load_dump_config(u); pa_log_info("Tizen Audio Policy module is loaded\n"); @@ -1888,6 +2035,11 @@ void pa__done(pa_module *m) bt_sco_close(u, false); + if (u->loopback_modules) { + pa_hashmap_remove_all(u->loopback_modules); + pa_hashmap_free(u->loopback_modules); + } + if (u->module_null_sink_index != PA_INVALID_INDEX) pa_module_unload_by_index(m->core, u->module_null_sink_index, true); -- 2.7.4