policy/stream-manager: Add break statement for selecting sink/source logic for STREAM... 82/49682/8 accepted/tizen/mobile/20151021.012938 accepted/tizen/tv/20151021.012947 accepted/tizen/wearable/20151021.012954 submit/tizen/20151020.121851
authorSangchul Lee <sc11.lee@samsung.com>
Mon, 19 Oct 2015 01:35:56 +0000 (10:35 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 20 Oct 2015 11:13:54 +0000 (20:13 +0900)
[Version] 5.0.5
[Profile] Common
[Issue Type] Bug Fix

Change-Id: I1ad33d6e1af90db63e40953b913e12e3ebe64c54

packaging/pulseaudio-modules-tizen.spec
src/module-policy.c
src/stream-manager.c
src/stream-manager.h
src/tizen-audio.h

index c8e2a4ccef9a45ebb82db644b65c9187333912ad..16dee25b6763794682cea2c9364d7522e90d14d3 100644 (file)
@@ -3,7 +3,7 @@
 
 Name:             pulseaudio-modules-tizen
 Summary:          Improved Linux sound server
-Version:          5.0.4
+Version:          5.0.5
 Release:          0
 Group:            Multimedia/Audio
 License:          LGPL-2.1+
index f34d0cc76362dc053131bb06518c088d7cad6c33..125e44d9fa8c467f182b54bae6d861153f19a54d 100644 (file)
@@ -316,6 +316,7 @@ static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stre
     char *args = NULL;
     void *s = NULL;
     uint32_t s_idx = 0;
+    pa_bool_t is_found = FALSE;
 
     pa_assert(c);
     pa_assert(data);
@@ -343,7 +344,7 @@ static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stre
                 pa_log_debug("  -- conn_devices, type[%-16s], subtype[%-5s], direction[0x%x]", dm_device_type, dm_device_subtype, device_direction);
                 if (pa_streq(device_type, dm_device_type) && IS_AVAILABLE_DIRECTION(data->stream_type, device_direction)) {
                     pa_log_debug("  ** found a matched device: type[%-16s], direction[0x%x]", device_type, device_direction);
-
+                    is_found = TRUE;
                     if (data->stream_type == STREAM_SINK_INPUT) {
                         if (data->route_type == STREAM_ROUTE_TYPE_AUTO_ALL && u->module_combine_sink) {
                             *(data->proper_sink) = (pa_sink*)pa_namereg_get(u->core, SINK_COMBINED, PA_NAMEREG_SINK);
@@ -352,12 +353,14 @@ static pa_hook_result_t select_proper_sink_or_source_hook_cb(pa_core *c, pa_stre
                             *(data->proper_sink) = pa_device_manager_get_sink(device, DEVICE_ROLE_NORMAL);
                     } else
                         *(data->proper_source) = pa_device_manager_get_source(device, DEVICE_ROLE_NORMAL);
-
-                    /* update activated device if it has the AUTO route type */
-                    if (data->route_type == STREAM_ROUTE_TYPE_AUTO)
-                        pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
-                    }
+                    break;
                 }
+            }
+            /* update activated device if it has the AUTO route type */
+            if (data->route_type == STREAM_ROUTE_TYPE_AUTO && is_found) {
+                pa_proplist_sets(GET_STREAM_NEW_PROPLIST(data->stream, data->stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, dm_device_type);
+                break;
+            }
         }
 
     } else if (data->route_type == STREAM_ROUTE_TYPE_MANUAL && data->idx_manual_devices && data->idx_avail_devices) {
@@ -906,7 +909,7 @@ static void update_sink_or_source_as_device_connection_change(stream_route_type_
     pa_source *next_source = NULL;
     pa_source *null_source = NULL;
     pa_bool_t available = FALSE;
-    pa_bool_t cur_highest_priority = FALSE;
+    pa_bool_t use_internal_codec = FALSE;
     cached_device_list cached_prev_dev_list[MAX_CACHED_LEN] = {{NULL,0},};
     uint32_t cnt = 0;
     pa_sink *combine_sink = NULL;
@@ -949,6 +952,7 @@ static void update_sink_or_source_as_device_connection_change(stream_route_type_
                                 if ((_device = pa_device_manager_get_device(u->device_manager, device_type)))
                                     _set_device_state(_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
                                 cached_prev_dev_list[cnt++].device_type = cur_device_type;
+                                use_internal_codec = sink->use_internal_codec;
                             }
                         } else
                             pa_log_error("  -- could not find current device type for s->sink(%p)", ((pa_sink_input*)s)->sink);
@@ -964,11 +968,20 @@ static void update_sink_or_source_as_device_connection_change(stream_route_type_
                                 if ((_device = pa_device_manager_get_device(u->device_manager, device_type)))
                                     _set_device_state(_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
                                 cached_prev_dev_list[cnt++].device_type = cur_device_type;
+                                use_internal_codec = source->use_internal_codec;
                             }
                         } else
                             pa_log_error("  -- could not find current device type for s->source(%p)", ((pa_source_output*)s)->source);
                         }
-
+                    if (available) {
+                        /* trigger to update routing path */
+                        memset(&hook_call_update_route_data, 0, sizeof(pa_stream_manager_hook_data_for_update_route));
+                        hook_call_update_route_data.stream = s;
+                        hook_call_update_route_data.stream_type = stream_type;
+                        hook_call_update_route_data.is_device_connected = is_connected;
+                        hook_call_update_route_data.use_internal_codec = use_internal_codec;
+                        pa_hook_fire(pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_NEED_UPDATE_ROUTE), &hook_call_update_route_data);
+                    }
                 } else if (!is_connected) {
                     /* DISCONNECTED: find a connected device that has the next priority */
                     if (sink && (sink == ((pa_sink_input*)s)->sink)) {
@@ -979,21 +992,22 @@ static void update_sink_or_source_as_device_connection_change(stream_route_type_
                             if (next_device_type) {
                                 if ((next_device = pa_device_manager_get_device(u->device_manager, next_device_type))) {
                                     if ((next_sink = pa_device_manager_get_sink(next_device, DEVICE_ROLE_NORMAL))) {
-                                        pa_sink_input_move_to(s, next_sink, FALSE);
-                                        pa_log_debug("  -- *** sink-input(%p,%u) moves to sink(%p,%s), new device(%s)",
-                                            s, ((pa_sink_input*)s)->index, next_sink, next_sink->name, next_device_type);
                                         /* update activated device */
                                         pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, next_device_type);
                                         _set_device_state(next_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
                                         cached_prev_dev_list[cnt++].device_type = init_device_type;
-
-                                        pa_stream_manager_is_current_highest_priority(s, stream_type, &cur_highest_priority, u->stream_manager);
-                                        if (cur_highest_priority && next_sink->use_internal_codec) {
-                                             /* trigger to update route path for internal audio codec */
+                                        /* trigger to update routing path if the next device uses internal audio codec */
+                                        if (next_sink->use_internal_codec) {
                                              memset(&hook_call_update_route_data, 0, sizeof(pa_stream_manager_hook_data_for_update_route));
+                                             hook_call_update_route_data.stream = s;
                                              hook_call_update_route_data.stream_type = stream_type;
+                                             hook_call_update_route_data.is_device_connected = is_connected;
+                                             hook_call_update_route_data.use_internal_codec = next_sink->use_internal_codec;
                                              pa_hook_fire(pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_NEED_UPDATE_ROUTE), &hook_call_update_route_data);
                                         }
+                                        pa_sink_input_move_to(s, next_sink, FALSE);
+                                        pa_log_debug("  -- *** sink-input(%p,%u) moves to sink(%p,%s), new device(%s)",
+                                            s, ((pa_sink_input*)s)->index, next_sink, next_sink->name, next_device_type);
                                         break;
                                     }
                                 } else {
@@ -1017,21 +1031,22 @@ static void update_sink_or_source_as_device_connection_change(stream_route_type_
                             if (next_device_type) {
                                 if ((next_device = pa_device_manager_get_device(u->device_manager, next_device_type))) {
                                     if ((next_source = pa_device_manager_get_source(next_device, DEVICE_ROLE_NORMAL))) {
-                                        pa_source_output_move_to(s, next_source, FALSE);
-                                        pa_log_debug("  -- *** source-output(%p,%u) moves to source(%p,%s), new device(%s)",
-                                            s, ((pa_source_output*)s)->index, next_source, next_source->name, next_device_type);
                                         /* update activated device */
                                         pa_proplist_sets(GET_STREAM_PROPLIST(s, stream_type), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, next_device_type);
                                         _set_device_state(next_device, stream_type, DM_DEVICE_STATE_ACTIVATED);
                                         cached_prev_dev_list[cnt++].device_type = init_device_type;
-
-                                        pa_stream_manager_is_current_highest_priority(s, stream_type, &cur_highest_priority, u->stream_manager);
-                                        if (cur_highest_priority && next_source->use_internal_codec) {
-                                             /* trigger to update route path for internal audio codec */
+                                        /* trigger to update routing path if the next device uses internal audio codec */
+                                        if (next_source->use_internal_codec) {
                                              memset(&hook_call_update_route_data, 0, sizeof(pa_stream_manager_hook_data_for_update_route));
+                                             hook_call_update_route_data.stream = s;
                                              hook_call_update_route_data.stream_type = stream_type;
+                                             hook_call_update_route_data.is_device_connected = is_connected;
+                                             hook_call_update_route_data.use_internal_codec = next_sink->use_internal_codec;
                                              pa_hook_fire(pa_communicator_hook(u->communicator.comm, PA_COMMUNICATOR_HOOK_NEED_UPDATE_ROUTE), &hook_call_update_route_data);
                                         }
+                                        pa_source_output_move_to(s, next_source, FALSE);
+                                        pa_log_debug("  -- *** source-output(%p,%u) moves to source(%p,%s), new device(%s)",
+                                            s, ((pa_source_output*)s)->index, next_source, next_source->name, next_device_type);
                                         break;
                                     }
                                 } else {
@@ -1106,7 +1121,7 @@ static void update_sink_or_source_as_device_connection_change(stream_route_type_
     return;
 }
 
-/* Reorganize routing when a device using external audio codec has been connected or disconnected */
+/* Reorganize routing when a device has been connected or disconnected */
 static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_manager_hook_data_for_conn_changed *conn, struct userdata *u) {
     uint32_t idx = 0;
     pa_sink_input *s = NULL;
@@ -1138,6 +1153,7 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_
 
     pa_device_manager_use_internal_codec(conn->device, device_direction, DEVICE_ROLE_NORMAL, &use_internal_codec);
     if (!use_internal_codec) {
+        /* EXTERNAL AUDIO CODEC */
         if (!conn->is_connected && (device_direction & DM_DEVICE_DIRECTION_OUT)) {
             if (u->module_combine_sink) {
                 /* unload combine sink */
@@ -1200,6 +1216,13 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_
 
             update_sink_or_source_as_device_connection_change(STREAM_ROUTE_TYPE_AUTO, STREAM_SINK_INPUT, u->core->sink_inputs, conn->device, conn->is_connected, u);
         }
+
+    } else {
+       /* INTERNAL AUDIO CODEC */
+       if (conn->is_connected && (device_direction & DM_DEVICE_DIRECTION_IN))
+           update_sink_or_source_as_device_connection_change(STREAM_ROUTE_TYPE_AUTO, STREAM_SOURCE_OUTPUT, u->core->source_outputs, conn->device, conn->is_connected, u);
+       if (conn->is_connected && (device_direction & DM_DEVICE_DIRECTION_OUT))
+           update_sink_or_source_as_device_connection_change(STREAM_ROUTE_TYPE_AUTO, STREAM_SINK_INPUT, u->core->sink_inputs, conn->device, conn->is_connected, u);
     }
 
     return PA_HOOK_OK;
index 2faf9b659f55e7fc30b9a4038d2bb13dc4665caf..478bc563500b1b64d9a055436146cf6c2285c5a5 100644 (file)
@@ -1636,16 +1636,18 @@ static pa_bool_t update_the_highest_priority_stream(pa_stream_manager *m, proces
     const int32_t *priority = NULL;
     const char *route_type_str = NULL;
     stream_route_type_t route_type;
-    const char *focus_status = NULL;
+    const char *focus_status_str = NULL;
     void *cur_max_stream = NULL;
     void *cur_max_stream_tmp = NULL;
     const int32_t *cur_max_priority = NULL;
     const char *cur_max_role = NULL;
-    int32_t cur_max_focus_status_int = 0;
-    int32_t focus_status_int = 0;
+    int32_t cur_max_focus_status = 0;
+    int32_t focus_status = 0;
     void *i = NULL;
     const char *_role = NULL;
     pa_idxset *streams = NULL;
+    pa_sink *sink = NULL;
+    pa_source *source = NULL;
 
     pa_assert(m);
     pa_assert(mine);
@@ -1665,19 +1667,33 @@ static pa_bool_t update_the_highest_priority_stream(pa_stream_manager *m, proces
     pa_log_info("update_the_highest_priority_stream(), stream_type(%d), role(%s), command(%d)", type, role, command);
     if (command == PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED_WITH_NEW_DATA ||
         command == PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED) {
-        /* get focus status */
-        if (command == PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED_WITH_NEW_DATA)
-            focus_status = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(mine, type), PA_PROP_MEDIA_FOCUS_STATUS);
-        else
-            focus_status = pa_proplist_gets(GET_STREAM_PROPLIST(mine, type), PA_PROP_MEDIA_FOCUS_STATUS);
-        if (focus_status && !pa_atoi(focus_status, &focus_status_int)) {
-            pa_log_debug("focus status(0x%x)", focus_status_int);
+        /* get focus status, route type */
+        if (command == PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED_WITH_NEW_DATA) {
+            focus_status_str = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(mine, type), PA_PROP_MEDIA_FOCUS_STATUS);
+            route_type_str = pa_proplist_gets(GET_STREAM_NEW_PROPLIST(mine, type), PA_PROP_MEDIA_ROLE_ROUTE_TYPE);
+        } else {
+            focus_status_str = pa_proplist_gets(GET_STREAM_PROPLIST(mine, type), PA_PROP_MEDIA_FOCUS_STATUS);
+            route_type_str = pa_proplist_gets(GET_STREAM_PROPLIST(mine, type), PA_PROP_MEDIA_ROLE_ROUTE_TYPE);
+        }
+        if (focus_status_str && !pa_atoi(focus_status_str, &focus_status)) {
+            pa_log_debug("focus status(0x%x) of mine", focus_status);
+        }
+        /* check if this stream is for external device with ROUTE_TYPE_AUTO */
+        if (IS_ROUTE_TYPE_FOR_AUTO(route_type_str, route_type) && (command == PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED_WITH_NEW_DATA)) {
+            if (type == STREAM_SINK_INPUT)
+                sink = ((pa_sink_input_new_data*)mine)->sink;
+            else
+                source = ((pa_source_output_new_data*)mine)->source;
+            if ((sink && !(sink->use_internal_codec)) || (source && !(source->use_internal_codec))) {
+                pa_log_warn("stream(%p) uses external device, skip it", mine);
+                *need_to_update = FALSE;
+                return TRUE;
+            }
         }
         if (cur_max_stream == NULL) {
             *need_to_update = TRUE;
             pa_log_debug("set cur_highest to mine");
         } else {
-            /* TODO : need to check if this stream should be played to external devices */
             if (command == PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED_WITH_NEW_DATA) {
                 if (pa_proplist_get(GET_STREAM_NEW_PROPLIST(mine, type), PA_PROP_MEDIA_ROLE_PRIORITY, (const void**)&priority, &size))
                     pa_log_error("failed to pa_proplist_get() for priority");
@@ -1687,9 +1703,9 @@ static pa_bool_t update_the_highest_priority_stream(pa_stream_manager *m, proces
             }
             if (pa_proplist_get(GET_STREAM_PROPLIST(cur_max_stream, type), PA_PROP_MEDIA_ROLE_PRIORITY, (const void**)&cur_max_priority, &size))
                 pa_log_error("failed to pa_proplist_get() for priority");
-            focus_status = pa_proplist_gets(GET_STREAM_PROPLIST(cur_max_stream, type), PA_PROP_MEDIA_FOCUS_STATUS);
-            if (focus_status && !pa_atoi(focus_status, &cur_max_focus_status_int)) {
-                pa_log_debug("cur_max_focus status(0x%x)", cur_max_focus_status_int);
+            focus_status_str = pa_proplist_gets(GET_STREAM_PROPLIST(cur_max_stream, type), PA_PROP_MEDIA_FOCUS_STATUS);
+            if (focus_status_str && !pa_atoi(focus_status_str, &cur_max_focus_status)) {
+                pa_log_debug("cur_max_focus status(0x%x)", cur_max_focus_status);
             }
             cur_max_role = pa_proplist_gets(GET_STREAM_PROPLIST(cur_max_stream, type), PA_PROP_MEDIA_ROLE);
             if (!cur_max_priority || !cur_max_role) {
@@ -1697,8 +1713,8 @@ static pa_bool_t update_the_highest_priority_stream(pa_stream_manager *m, proces
                 return FALSE;
             } else {
                 if (priority && cur_max_priority) {
-                    if (IS_FOCUS_ACQUIRED(focus_status_int, type) ||
-                        (!IS_FOCUS_ACQUIRED(cur_max_focus_status_int, type) && *priority >= *cur_max_priority)) {
+                    if (IS_FOCUS_ACQUIRED(focus_status, type) ||
+                        (!IS_FOCUS_ACQUIRED(cur_max_focus_status, type) && *priority >= *cur_max_priority)) {
                         *need_to_update = TRUE;
                         pa_log_debug("update cur_highest to mine(%s)", role);
                     } else {
@@ -1718,6 +1734,8 @@ static pa_bool_t update_the_highest_priority_stream(pa_stream_manager *m, proces
             }
             /* find the next highest priority input */
             PA_IDXSET_FOREACH(i, streams, idx) {
+                if (i == mine)
+                    continue;
                 if (!(_role = pa_proplist_gets(GET_STREAM_PROPLIST(i, type), PA_PROP_MEDIA_ROLE))) {
                     pa_log_error("failed to pa_proplist_gets() for role");
                     continue;
@@ -1732,27 +1750,31 @@ static pa_bool_t update_the_highest_priority_stream(pa_stream_manager *m, proces
                 } else if (IS_ROUTE_TYPE_FOR_EXTERNAL_DEV(route_type_str, route_type)) {
                     pa_log_warn("stream(%p) has the route type for external device, skip it", i);
                     continue;
+                } else {
+                    if (type==STREAM_SINK_INPUT?!(((pa_sink_input*)i)->sink->use_internal_codec):!(((pa_source_output*)i)->source->use_internal_codec)) {
+                        pa_log_warn("stream(%p) uses external audio codec, skip it", i);
+                        continue;
+                    }
                 }
-                if (!(focus_status = pa_proplist_gets(GET_STREAM_PROPLIST(i, type), PA_PROP_MEDIA_FOCUS_STATUS))) {
+                if (!(focus_status_str = pa_proplist_gets(GET_STREAM_PROPLIST(i, type), PA_PROP_MEDIA_FOCUS_STATUS))) {
                     pa_log_warn("failed to pa_proplist_gets() for focus status");
                 } else {
-                    if (!pa_atoi(focus_status, &focus_status_int)) {
-                        pa_log_debug("focus status(0x%x)", focus_status_int);
-                        }
+                    if (!pa_atoi(focus_status_str, &focus_status))
+                        pa_log_debug("focus status(0x%x)", focus_status);
                 }
-                pa_log_debug("role(%s)/priority(%p)/route_type(%d)/focus_status(0x%x)/stream(%p)", _role, priority, route_type, focus_status_int, i);
+                pa_log_debug("role(%s)/priority(%p)/route_type(%d)/focus_status(0x%x)/stream(%p)", _role, priority, route_type, focus_status, i);
                 if (cur_max_priority == NULL) {
                     cur_max_priority = priority;
-                    cur_max_focus_status_int = focus_status_int;
+                    cur_max_focus_status = focus_status;
                     cur_max_stream_tmp = i;
                 }
                 if (cur_max_priority && priority) {
-                    if (IS_FOCUS_ACQUIRED(cur_max_focus_status_int, type) ||
-                        (!IS_FOCUS_ACQUIRED(focus_status_int, type) && (*cur_max_priority > *priority))) {
+                    if (IS_FOCUS_ACQUIRED(cur_max_focus_status, type) ||
+                        (!IS_FOCUS_ACQUIRED(focus_status, type) && (*cur_max_priority > *priority))) {
                         /* skip */
                     } else  {
                         cur_max_priority = priority;
-                        cur_max_focus_status_int = focus_status_int;
+                        cur_max_focus_status = focus_status;
                         cur_max_stream_tmp = i;
                     }
                 }
@@ -2513,6 +2535,11 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_
                             pa_proplist_sets(GET_STREAM_PROPLIST(m->cur_highest_priority.source_output, STREAM_SOURCE_OUTPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, "removed");
                     }
                     do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, STREAM_SOURCE_OUTPUT, FALSE, m->cur_highest_priority.source_output);
+                    if (!((pa_source_output*)(m->cur_highest_priority.source_output))->source->use_internal_codec) {
+                        /* As only process_stream(PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED) can update the cur_highest_priority,
+                         * call it here, this would be fixed later on with new internal API */
+                        process_stream(STREAM_SOURCE_OUTPUT, m->cur_highest_priority.source_output, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, m);
+                    }
                 }
             }
         }
@@ -2520,7 +2547,7 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_
     if (m->cur_highest_priority.sink_input && (device_direction & DM_DEVICE_DIRECTION_OUT)) {
         if (!pa_stream_manager_get_route_type(m->cur_highest_priority.sink_input, FALSE, STREAM_SINK_INPUT, &route_type)) {
             if (route_type < STREAM_ROUTE_TYPE_MANUAL) {
-                if (use_internal_codec || (!use_internal_codec && (route_type == STREAM_ROUTE_TYPE_AUTO_ALL))) {
+                if (use_internal_codec) {
                     if (route_type == STREAM_ROUTE_TYPE_AUTO && !data->is_connected) {
                         /* remove activated device info. if it has the AUTO route type */
                         active_dev = pa_proplist_gets(GET_STREAM_PROPLIST(m->cur_highest_priority.sink_input, STREAM_SINK_INPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV);
@@ -2528,7 +2555,13 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_device_
                             pa_proplist_sets(GET_STREAM_PROPLIST(m->cur_highest_priority.sink_input, STREAM_SINK_INPUT), PA_PROP_MEDIA_ROUTE_AUTO_ACTIVE_DEV, "removed");
                     }
                     do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, STREAM_SINK_INPUT, FALSE, m->cur_highest_priority.sink_input);
-                }
+                    if ((route_type == STREAM_ROUTE_TYPE_AUTO) && !((pa_sink_input*)(m->cur_highest_priority.sink_input))->sink->use_internal_codec) {
+                        /* As only process_stream(PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED) can update the cur_highest_priority,
+                         * call it here, this would be fixed later on with new internal API */
+                        process_stream(STREAM_SINK_INPUT, m->cur_highest_priority.sink_input, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, m);
+                    }
+                } else if (route_type == STREAM_ROUTE_TYPE_AUTO_ALL)
+                    do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, STREAM_SINK_INPUT, FALSE, m->cur_highest_priority.sink_input);
             }
         }
     }
@@ -2550,15 +2583,29 @@ static pa_hook_result_t device_information_changed_hook_cb(pa_core *c, pa_device
     return PA_HOOK_OK;
 }
 
-/* Re-trigger for routing */
+/* Re-trigger for updating audio routing regarding internal audio codec */
 static pa_hook_result_t need_update_route_hook_cb(pa_core *c, pa_stream_manager_hook_data_for_update_route *data, pa_stream_manager *m) {
     pa_assert(c);
     pa_assert(data);
     pa_assert(m);
 
-    pa_log_info("[SM] need_update_route_hook_cb is called. data(%p), stream_type(%d)", data, data->stream_type);
+    pa_log_info("[SM] need_update_route_hook_cb is called. data(%p), stream(%p), stream_type(%d), is_device_connected(%d), use_internal_codec(%d)",
+        data, data->stream, data->stream_type, data->is_device_connected, data->use_internal_codec);
 
-    do_notify(m, NOTIFY_COMMAND_CHANGE_ROUTE_START, data->stream_type, FALSE, (data->stream_type==STREAM_SINK_INPUT)?(void*)m->cur_highest_priority.sink_input:(void*)m->cur_highest_priority.source_output);
+    if (data->is_device_connected) {
+        /* it is caused by the connection of supported device for the stream */
+        if (data->use_internal_codec) {
+            if (((data->stream_type == STREAM_SINK_INPUT) && (!m->cur_highest_priority.sink_input || (m->cur_highest_priority.sink_input != data->stream))) ||
+                ((data->stream_type == STREAM_SOURCE_OUTPUT) && (!m->cur_highest_priority.source_output || (m->cur_highest_priority.source_output != data->stream))))
+                process_stream(data->stream_type, data->stream, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, m);
+        } else
+            process_stream(data->stream_type, data->stream, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, m);
+    } else {
+        /* it is caused by the disconnection of external device
+         * and the supported next device of this stream using internal audio codec */
+        if (data->use_internal_codec)
+            process_stream(data->stream_type, data->stream, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, m);
+    }
 
     return PA_HOOK_OK;
 }
index e36850d87217edbf1055a78d0aca7a7a29ec8c14..67bae302c40cf13e8b14728b4d7a1378a514efa5 100644 (file)
@@ -5,6 +5,9 @@
 #define IS_ROUTE_TYPE_FOR_EXTERNAL_DEV(route_type_str, route_type) \
       (route_type_str && !pa_atoi(route_type_str, (int32_t*)&route_type) && (route_type == STREAM_ROUTE_TYPE_MANUAL_EXT))
 
+#define IS_ROUTE_TYPE_FOR_AUTO(route_type_str, route_type) \
+      (route_type_str && !pa_atoi(route_type_str, (int32_t*)&route_type) && (route_type == STREAM_ROUTE_TYPE_AUTO))
+
 #define GET_STREAM_NEW_PROPLIST(stream, type) \
       (type == STREAM_SINK_INPUT? ((pa_sink_input_new_data*)stream)->proplist : ((pa_source_output_new_data*)stream)->proplist)
 
@@ -59,7 +62,10 @@ typedef struct _hook_call_data_for_option {
 } pa_stream_manager_hook_data_for_option;
 
 typedef struct _hook_call_data_for_update_route {
+    void *stream;
     stream_type_t stream_type;
+    pa_bool_t is_device_connected;
+    pa_bool_t use_internal_codec;
 } pa_stream_manager_hook_data_for_update_route;
 
 int32_t pa_stream_manager_get_route_type(void *stream, pa_bool_t origins_from_new_data, stream_type_t stream_type, stream_route_type_t *stream_route_type);
index 47ef0d8545e4bbbf8786f20c5251fd8b554532fb..9c503625f791da685bd21d590eb791db802ba268 100644 (file)
@@ -81,7 +81,8 @@ typedef struct audio_interface {
     audio_return_t (*do_route)(void *userdata, audio_route_info_t *info);
     audio_return_t (*update_route_option)(void *userdata, audio_route_option_t *option);
     audio_return_t (*update_stream_connection_info) (void *userdata, audio_stream_info_t *info, uint32_t is_connected);
-    audio_return_t (*get_buffer_attr)(void *userdata, uint32_t direction, const char *latency, uint32_t samplerate, int format, uint32_t channels, uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
+    audio_return_t (*get_buffer_attr)(void *userdata, uint32_t direction, const char *latency, uint32_t samplerate, int format, uint32_t channels,
+                                      uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
     /* Interface of PCM device */
     audio_return_t (*alsa_pcm_open)(void *userdata, void **pcm_handle, char *device_name, uint32_t direction, int mode);
     audio_return_t (*alsa_pcm_close)(void *userdata, void *pcm_handle);
@@ -94,25 +95,26 @@ typedef struct audio_interface {
     audio_return_t (*pcm_read)(void *userdata, void *pcm_handle, void *buffer, uint32_t frames);
 } audio_interface_t;
 
-audio_return_t audio_init (void **userdata, void *platform_data);
-audio_return_t audio_deinit (void **userdata);
-audio_return_t audio_get_volume_level_max (void *userdata, audio_volume_info_t *info, uint32_t *level);
-audio_return_t audio_get_volume_level (void *userdata, audio_volume_info_t *info, uint32_t *level);
-audio_return_t audio_set_volume_level (void *userdata, audio_volume_info_t *info, uint32_t level);
-audio_return_t audio_get_volume_value (void *userdata, audio_volume_info_t *info, uint32_t level, double *value);
-audio_return_t audio_get_volume_mute (void *userdata, audio_volume_info_t *info, uint32_t *mute);
-audio_return_t audio_set_volume_mute (void *userdata, audio_volume_info_t *info, uint32_t mute);
-audio_return_t audio_do_route (void *userdata, audio_route_info_t *info);
-audio_return_t audio_update_route_option (void *userdata, audio_route_option_t *option);
-audio_return_t audio_update_stream_connection_info (void *userdata, audio_stream_info_t *info, uint32_t is_connected);
-audio_return_t audio_get_buffer_attr (void *userdata, uint32_t direction, const char *latency, uint32_t samplerate, int format, uint32_t channels, uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
-audio_return_t audio_alsa_pcm_open (void *userdata, void **pcm_handle, char *device_name, uint32_t direction, int mode);
-audio_return_t audio_alsa_pcm_close (void *userdata, void *pcm_handle);
-audio_return_t audio_pcm_open (void *userdata, void **pcm_handle, void *sample_spec, uint32_t direction);
-audio_return_t audio_pcm_start (void *userdata, void *pcm_handle);
-audio_return_t audio_pcm_stop (void *userdata, void *pcm_handle);
-audio_return_t audio_pcm_close (void *userdata, void *pcm_handle);
-audio_return_t audio_pcm_avail (void *userdata, void *pcm_handle, uint32_t *avail);
-audio_return_t audio_pcm_write (void *userdata, void *pcm_handle, const void *buffer, uint32_t frames);
-audio_return_t audio_pcm_read (void *userdata, void *pcm_handle, void *buffer, uint32_t frames);
+audio_return_t audio_init(void **userdata, void *platform_data);
+audio_return_t audio_deinit(void **userdata);
+audio_return_t audio_get_volume_level_max(void *userdata, audio_volume_info_t *info, uint32_t *level);
+audio_return_t audio_get_volume_level(void *userdata, audio_volume_info_t *info, uint32_t *level);
+audio_return_t audio_set_volume_level(void *userdata, audio_volume_info_t *info, uint32_t level);
+audio_return_t audio_get_volume_value(void *userdata, audio_volume_info_t *info, uint32_t level, double *value);
+audio_return_t audio_get_volume_mute(void *userdata, audio_volume_info_t *info, uint32_t *mute);
+audio_return_t audio_set_volume_mute(void *userdata, audio_volume_info_t *info, uint32_t mute);
+audio_return_t audio_do_route(void *userdata, audio_route_info_t *info);
+audio_return_t audio_update_route_option(void *userdata, audio_route_option_t *option);
+audio_return_t audio_update_stream_connection_info(void *userdata, audio_stream_info_t *info, uint32_t is_connected);
+audio_return_t audio_get_buffer_attr(void *userdata, uint32_t direction, const char *latency, uint32_t samplerate, int format, uint32_t channels,
+                                     uint32_t *maxlength, uint32_t *tlength, uint32_t *prebuf, uint32_t* minreq, uint32_t *fragsize);
+audio_return_t audio_alsa_pcm_open(void *userdata, void **pcm_handle, char *device_name, uint32_t direction, int mode);
+audio_return_t audio_alsa_pcm_close(void *userdata, void *pcm_handle);
+audio_return_t audio_pcm_open(void *userdata, void **pcm_handle, void *sample_spec, uint32_t direction);
+audio_return_t audio_pcm_start(void *userdata, void *pcm_handle);
+audio_return_t audio_pcm_stop(void *userdata, void *pcm_handle);
+audio_return_t audio_pcm_close(void *userdata, void *pcm_handle);
+audio_return_t audio_pcm_avail(void *userdata, void *pcm_handle, uint32_t *avail);
+audio_return_t audio_pcm_write(void *userdata, void *pcm_handle, const void *buffer, uint32_t frames);
+audio_return_t audio_pcm_read(void *userdata, void *pcm_handle, void *buffer, uint32_t frames);
 #endif