mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-10-29 05:40:23 -04:00 
			
		
		
		
	stream-interaction: Fix regression when a trigger role is also a cork role
If the same role is named in trigger_roles and cork_roles, a stream with that role will crash PA. This patch fixes the crash and re-introduces the old behavior, so that for example specifying trigger_roles=alarm, phone and cork_roles=alarm, multimedia means that a phone stream will cork alarm and multimedia streams while an alarm stream will only cork multimedia streams. Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/767>
This commit is contained in:
		
							parent
							
								
									94dd7b4b7b
								
							
						
					
					
						commit
						6473e9ed0e
					
				
					 1 changed files with 28 additions and 7 deletions
				
			
		|  | @ -100,7 +100,7 @@ static const char *get_trigger_role(struct userdata *u, pa_object *stream, struc | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const char *find_trigger_stream(struct userdata *u, pa_object *device, pa_object *ignore_stream, struct group *g) { | static const char *find_trigger_stream(struct userdata *u, pa_object *current_stream, pa_object *device, pa_object *ignore_stream, struct group *g) { | ||||||
|     pa_object *j; |     pa_object *j; | ||||||
|     uint32_t idx; |     uint32_t idx; | ||||||
|     const char *trigger_role; |     const char *trigger_role; | ||||||
|  | @ -108,6 +108,23 @@ static const char *find_trigger_stream(struct userdata *u, pa_object *device, pa | ||||||
|     pa_assert(u); |     pa_assert(u); | ||||||
|     pa_object_assert_ref(device); |     pa_object_assert_ref(device); | ||||||
| 
 | 
 | ||||||
|  |     /* If the current stream is a trigger stream, return the role of this stream, otherwise
 | ||||||
|  |      * return the role of the first trigger stream that is found on the device. */ | ||||||
|  | 
 | ||||||
|  |     trigger_role = get_trigger_role(u, current_stream, g); | ||||||
|  |     if (GET_DEVICE_FROM_STREAM(current_stream) == device && current_stream != ignore_stream && trigger_role) { | ||||||
|  | 
 | ||||||
|  |         if (pa_sink_isinstance(device)) { | ||||||
|  |             if (!PA_SINK_INPUT(current_stream)->muted && | ||||||
|  |                 PA_SINK_INPUT(current_stream)->state != PA_SINK_INPUT_CORKED) | ||||||
|  |                 return trigger_role; | ||||||
|  |         } else { | ||||||
|  |             if (!PA_SOURCE_OUTPUT(current_stream)->muted && | ||||||
|  |                 PA_SOURCE_OUTPUT(current_stream)->state != PA_SOURCE_OUTPUT_CORKED) | ||||||
|  |                 return trigger_role; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     PA_IDXSET_FOREACH(j, pa_sink_isinstance(device) ? PA_SINK(device)->inputs : PA_SOURCE(device)->outputs, idx) { |     PA_IDXSET_FOREACH(j, pa_sink_isinstance(device) ? PA_SINK(device)->inputs : PA_SOURCE(device)->outputs, idx) { | ||||||
|         if (j == ignore_stream) |         if (j == ignore_stream) | ||||||
|             continue; |             continue; | ||||||
|  | @ -129,7 +146,7 @@ static const char *find_trigger_stream(struct userdata *u, pa_object *device, pa | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const char *find_global_trigger_stream(struct userdata *u, pa_object *ignore_stream, struct group *g) { | static const char *find_global_trigger_stream(struct userdata *u, pa_object *current_stream, pa_object *ignore_stream, struct group *g) { | ||||||
|     const char *trigger_role = NULL; |     const char *trigger_role = NULL; | ||||||
|     pa_sink *sink; |     pa_sink *sink; | ||||||
|     pa_source *source; |     pa_source *source; | ||||||
|  | @ -137,16 +154,20 @@ static const char *find_global_trigger_stream(struct userdata *u, pa_object *ign | ||||||
| 
 | 
 | ||||||
|     pa_assert(u); |     pa_assert(u); | ||||||
| 
 | 
 | ||||||
|  |     /* Check device of current stream first in case the current stream is a trigger stream. */ | ||||||
|  |     if ((trigger_role = find_trigger_stream(u, current_stream, GET_DEVICE_FROM_STREAM(current_stream), ignore_stream, g))) | ||||||
|  |         return trigger_role; | ||||||
|  | 
 | ||||||
|     /* Find any trigger role among the sink-inputs and source-outputs. */ |     /* Find any trigger role among the sink-inputs and source-outputs. */ | ||||||
|     PA_IDXSET_FOREACH(sink, u->core->sinks, idx) |     PA_IDXSET_FOREACH(sink, u->core->sinks, idx) | ||||||
|         if ((trigger_role = find_trigger_stream(u, PA_OBJECT(sink), ignore_stream, g))) |         if ((trigger_role = find_trigger_stream(u, current_stream, PA_OBJECT(sink), ignore_stream, g))) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|     if (!u->source_trigger || trigger_role) |     if (!u->source_trigger || trigger_role) | ||||||
|         return trigger_role; |         return trigger_role; | ||||||
| 
 | 
 | ||||||
|     PA_IDXSET_FOREACH(source, u->core->sources, idx) |     PA_IDXSET_FOREACH(source, u->core->sources, idx) | ||||||
|         if ((trigger_role = find_trigger_stream(u, PA_OBJECT(source), ignore_stream, g))) |         if ((trigger_role = find_trigger_stream(u, current_stream, PA_OBJECT(source), ignore_stream, g))) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|     return trigger_role; |     return trigger_role; | ||||||
|  | @ -204,7 +225,7 @@ static inline void apply_interaction_to_sink(struct userdata *u, pa_sink *s, con | ||||||
|             role = "no_role"; |             role = "no_role"; | ||||||
| 
 | 
 | ||||||
|         PA_IDXSET_FOREACH(interaction_role, g->interaction_roles, role_idx) { |         PA_IDXSET_FOREACH(interaction_role, g->interaction_roles, role_idx) { | ||||||
|             if ((trigger = pa_streq(role, interaction_role))) |             if ((trigger = (pa_streq(interaction_role, role) && (!get_trigger_role(u, PA_OBJECT(j), g) || !pa_safe_streq(new_trigger, role))))) | ||||||
|                 break; |                 break; | ||||||
|             if ((trigger = (pa_streq(interaction_role, "any_role") && !get_trigger_role(u, PA_OBJECT(j), g)))) |             if ((trigger = (pa_streq(interaction_role, "any_role") && !get_trigger_role(u, PA_OBJECT(j), g)))) | ||||||
|                 break; |                 break; | ||||||
|  | @ -289,10 +310,10 @@ static pa_hook_result_t process(struct userdata *u, pa_object *stream, bool crea | ||||||
| 
 | 
 | ||||||
|     for (j = 0; j < u->n_groups; j++) { |     for (j = 0; j < u->n_groups; j++) { | ||||||
|         if (u->global) { |         if (u->global) { | ||||||
|             trigger_role = find_global_trigger_stream(u, create ? NULL : stream, u->groups[j]); |             trigger_role = find_global_trigger_stream(u, stream, create ? NULL : stream, u->groups[j]); | ||||||
|             apply_interaction_global(u, trigger_role, create ? NULL : (pa_sink_input_isinstance(stream) ? PA_SINK_INPUT(stream) : NULL), new_stream, u->groups[j]); |             apply_interaction_global(u, trigger_role, create ? NULL : (pa_sink_input_isinstance(stream) ? PA_SINK_INPUT(stream) : NULL), new_stream, u->groups[j]); | ||||||
|         } else { |         } else { | ||||||
|             trigger_role = find_trigger_stream(u, GET_DEVICE_FROM_STREAM(stream), create ? NULL : stream, u->groups[j]); |             trigger_role = find_trigger_stream(u, stream, GET_DEVICE_FROM_STREAM(stream), create ? NULL : stream, u->groups[j]); | ||||||
|             if (pa_sink_input_isinstance(stream)) |             if (pa_sink_input_isinstance(stream)) | ||||||
|                 apply_interaction_to_sink(u, PA_SINK_INPUT(stream)->sink, trigger_role, create ? NULL : PA_SINK_INPUT(stream), new_stream, u->groups[j]); |                 apply_interaction_to_sink(u, PA_SINK_INPUT(stream)->sink, trigger_role, create ? NULL : PA_SINK_INPUT(stream), new_stream, u->groups[j]); | ||||||
|         } |         } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Georg Chini
						Georg Chini