stream-manager: Further modification to enhance codes regarding add/remove volume... 06/110206/4 accepted/tizen/3.0/common/20170118.130833 accepted/tizen/3.0/ivi/20170118.042802 accepted/tizen/3.0/mobile/20170118.042716 accepted/tizen/3.0/tv/20170118.042725 accepted/tizen/3.0/wearable/20170118.042742 submit/tizen_3.0/20170116.094232
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 13 Jan 2017 07:50:11 +0000 (16:50 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Mon, 16 Jan 2017 06:55:46 +0000 (15:55 +0900)
Excluded streams of auto-all and manual-ext type from the policy due to no need to be handled.
Timed mannaer adopted to remove volume factor forcedly.

[Version] 5.0.125
[Profile] Common
[Issue Type] Feature enhancement

Change-Id: Id87c58f91f25d3cb8c14de8a0342b4801f51ce2e
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
packaging/pulseaudio-modules-tizen.spec
src/stream-manager-priv.h
src/stream-manager.c

index c4a20f94cea1671e2f3ccc9d448370d51d3a5468..95dd7d1349aad5294a84b8e8a23eefe4e77b259f 100644 (file)
@@ -1,6 +1,6 @@
 Name:             pulseaudio-modules-tizen
 Summary:          Pulseaudio modules for Tizen
-Version:          5.0.124
+Version:          5.0.125
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index 00af023be6989838633cf7e1778f27e02ec8f64f..646417193d13e22bab94f915fc56cad39b194fbb 100644 (file)
@@ -115,6 +115,7 @@ struct _stream_manager {
     cur_max_priority_stream cur_highest_priority;
     stream_restrictions restrictions;
     bool on_call;
+    pa_time_event *time_event_for_unmute;
 
     pa_hook_slot
         *sink_input_new_slot,
index 24bb0413a2adcc9d6b3a9d232e4b7ef3af0a5c4b..d89b3fd056984b3a3dbbf8ad941153caf08e48a7 100644 (file)
@@ -31,6 +31,9 @@
 #include <sys/stat.h>
 #include <errno.h>
 
+#include <pulse/timeval.h>
+#include <pulse/rtclock.h>
+
 #include <pulse/xmalloc.h>
 #include <pulse/proplist.h>
 
@@ -365,6 +368,7 @@ const char* stream_manager_media_names_for_skip[NAME_FOR_SKIP_MAX] = {"pulsesink
 #define STREAM_FOCUS_STATE_ACQUIRED    "1"
 
 #define MUTE_KEY    "mute_by_device_disconnection"
+#define TIMED_UNMUTE_USEC    300000
 
 typedef enum _process_stream_result {
     PROCESS_STREAM_RESULT_OK,
@@ -2961,13 +2965,6 @@ static process_stream_result_t process_stream(pa_stream_manager *m, void *stream
         } else {
             role = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_MEDIA_ROLE);
             route_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(stream, type), PA_PROP_MEDIA_ROLE_ROUTE_TYPE);
-            /* FIXME: if PA_COMMUNICATOR_HOOK_EVENT_FULLY_HANDLED is not called for some reason,
-             * volume factor should be removed forcedly. */
-            if (type == STREAM_SINK_INPUT) {
-                pa_sink_input *i = (pa_sink_input *)stream;
-                if ((pa_hashmap_get(i->volume_factor_items, MUTE_KEY)))
-                    pa_sink_input_remove_volume_factor(i, MUTE_KEY);
-            }
         }
 
         /* skip roles */
@@ -3710,42 +3707,96 @@ static void update_sink_or_source_as_device_change(stream_route_type_t stream_ro
         pa_log_error("[SM][UPDATE_SINK_SOURCE] could not handle it here, stream_route_type(%d)", stream_route_type);
 }
 
-static void mute_sink_inputs_as_device_disconnection(pa_stream_manager *m, uint32_t event_id, bool need_to_mute, void *user_data) {
-    pa_idxset *muted_streams;
-    uint32_t s_idx = 0;
+static void apply_volume_factor_to_streams(pa_idxset *all_streams, pa_idxset **applied_streams) {
     pa_cvolume vol;
     pa_sink_input *i;
+    uint32_t idx = 0;
+
+    pa_assert(all_streams);
+    pa_assert(applied_streams);
+
+    pa_log_debug("apply_volume_factor_to_streams is called");
+
+    vol.channels = 1;
+    pa_parse_volume("0%", &vol.values[0]);
+    *applied_streams = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+    PA_IDXSET_FOREACH(i, all_streams, idx) {
+        stream_route_type_t route_type = STREAM_ROUTE_TYPE_AUTO;
+        /* skip in case of auto-all type or manual-ext type */
+        if (!get_route_type(i, STREAM_SINK_INPUT, false, &route_type) &&
+            (route_type == STREAM_ROUTE_TYPE_AUTO_ALL || route_type == STREAM_ROUTE_TYPE_MANUAL_EXT))
+            continue;
+
+        pa_log_info("found a stream(%p, %u) that should be muted.", i, i->index);
+        /* remove MUTE_KEY before adding to avoid abort-case in pa_sink_input_add_volume_factor */
+        pa_hashmap_remove(i->volume_factor_items, MUTE_KEY);
+        pa_sink_input_add_volume_factor(i, MUTE_KEY, &vol);
+        pa_idxset_put(*applied_streams, i, NULL);
+    }
+}
+
+static void clear_volume_factor_from_streams(pa_idxset *applied_streams) {
+    pa_sink_input *i;
+    uint32_t idx = 0;
+
+    pa_assert(applied_streams);
+
+    pa_log_debug("clear_volume_factor_from_streams is called");
+
+    PA_IDXSET_FOREACH(i, applied_streams, idx) {
+        pa_idxset_remove_by_data(applied_streams, i, NULL);
+        pa_sink_input_remove_volume_factor(i, MUTE_KEY);
+        pa_log_info("found a stream(%p, %u) that should be un-muted.", i, i->index);
+    }
+    pa_idxset_free(applied_streams, NULL);
+}
+
+static void timed_unmute_cb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *t, void *userdata) {
+    pa_stream_manager *m = userdata;
+    pa_idxset *applied_streams;
+    void *state;
+
+    pa_assert(m);
+    pa_assert(m->time_event_for_unmute == e);
+
+    pa_log_info("timed_unmute_cb is called");
+
+    PA_HASHMAP_FOREACH(applied_streams, m->muted_streams, state) {
+        clear_volume_factor_from_streams(applied_streams);
+        pa_log_warn("remove volume factors forcedly...");
+    }
+    pa_hashmap_remove_all(m->muted_streams);
+
+    m->core->mainloop->time_free(m->time_event_for_unmute);
+    m->time_event_for_unmute = NULL;
+}
+
+static void mute_sink_inputs_as_device_disconnection(pa_stream_manager *m, uint32_t event_id, bool need_to_mute, void *user_data) {
+    pa_idxset *applied_streams;
 
     pa_assert(m);
 
+    pa_log_info("mute_sink_inputs_as_device_disconnection(), event_id(%u), mute(%d) is called", event_id, need_to_mute);
+
     if (need_to_mute) {
         if (!user_data) {
             pa_log_error("invalid argument, inputs is needed");
             return;
         }
-        vol.channels = 1;
-        pa_parse_volume("0%", &vol.values[0]);
-        muted_streams = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
-        PA_IDXSET_FOREACH(i, (pa_idxset *)user_data, s_idx) {
-            pa_log_debug("found a stream(%p, %u) that should be muted.", i, i->index);
-            /* remove MUTE_KEY before adding to avoid abort-case in pa_sink_input_add_volume_factor */
-            pa_hashmap_remove(i->volume_factor_items, MUTE_KEY);
-            pa_sink_input_add_volume_factor(i, MUTE_KEY, &vol);
-            pa_idxset_put(muted_streams, i, NULL);
-        }
-        pa_hashmap_put(m->muted_streams, (void*)event_id, muted_streams);
+        apply_volume_factor_to_streams(m->core->sink_inputs, &applied_streams);
+        pa_hashmap_put(m->muted_streams, (void*)event_id, applied_streams);
+
+        /* If PA_COMMUNICATOR_HOOK_EVENT_FULLY_HANDLED is not called for some reason,
+        * volume factor should be removed forcedly. */
+        if (!m->time_event_for_unmute)
+            m->time_event_for_unmute = pa_core_rttime_new(m->core, pa_rtclock_now() + TIMED_UNMUTE_USEC, timed_unmute_cb, m);
     } else {
-        if (!(muted_streams = pa_hashmap_get(m->muted_streams, (void*)event_id))) {
-            pa_log_debug("could not find muted_streams for event_id(%u)", event_id);
+        if (!(applied_streams = pa_hashmap_get(m->muted_streams, (void*)event_id))) {
+            pa_log_debug("could not find applied_streams for event_id(%u)", event_id);
             return;
         }
-        PA_IDXSET_FOREACH(i, muted_streams, s_idx) {
-            pa_idxset_remove_by_data(muted_streams, i, NULL);
-            pa_sink_input_remove_volume_factor(i, MUTE_KEY);
-            pa_log_debug("found a stream(%p, %u) that should be un-muted.", i, i->index);
-        }
+        clear_volume_factor_from_streams(applied_streams);
         pa_hashmap_remove(m->muted_streams, (void*)event_id);
-        pa_idxset_free(muted_streams, NULL);
     }
 
     return;