2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/***
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  This  file  is  part  of  PulseAudio . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  Copyright  2008 - 2013  João  Paulo  Rechi  Vita 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  Copyright  2011 - 2013  BMW  Car  IT  GmbH . 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  Copyright  2018 - 2019  Pali  Rohár  < pali . rohar @ gmail . com > 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  PulseAudio  is  free  software ;  you  can  redistribute  it  and / or  modify 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  it  under  the  terms  of  the  GNU  Lesser  General  Public  License  as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  published  by  the  Free  Software  Foundation ;  either  version  2.1  of  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  License ,  or  ( at  your  option )  any  later  version . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  PulseAudio  is  distributed  in  the  hope  that  it  will  be  useful ,  but 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  WITHOUT  ANY  WARRANTY ;  without  even  the  implied  warranty  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE .  See  the  GNU 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  General  Public  License  for  more  details . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  You  should  have  received  a  copy  of  the  GNU  Lesser  General  Public 
							 
						 
					
						
							
								
									
										
										
										
											2014-11-26 14:14:51 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  License  along  with  PulseAudio ;  if  not ,  see  < http : //www.gnu.org/licenses/>.
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								* * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# ifdef HAVE_CONFIG_H 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <config.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <errno.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <arpa/inet.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulse/rtclock.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulse/timeval.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-11 17:27:06 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulse/utf8.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-21 09:45:26 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulse/util.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulse/message-params.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/core-error.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/core-rtclock.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/core-util.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/i18n.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/message-handler.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/module.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/modargs.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/poll.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/rtpoll.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:56 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/shared.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/socket-util.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/thread.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/thread-mq.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/time-smoother.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "a2dp-codecs.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  "a2dp-codec-util.h" 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  "bluez5-util.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								PA_MODULE_AUTHOR ( " João Paulo Rechi Vita " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								PA_MODULE_DESCRIPTION ( " BlueZ 5 Bluetooth audio sink and source " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								PA_MODULE_VERSION ( PACKAGE_VERSION ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								PA_MODULE_LOAD_ONCE ( false ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 09:10:02 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								PA_MODULE_USAGE ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " path=<device object path> " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " autodetect_mtu=<boolean> " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " output_rate_refresh_interval_ms=<interval between attempts to improve output rate in milliseconds> " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# define FIXED_LATENCY_PLAYBACK_A2DP (25 * PA_USEC_PER_MSEC) 
 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# define FIXED_LATENCY_PLAYBACK_SCO  (25 * PA_USEC_PER_MSEC) 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# define FIXED_LATENCY_RECORD_A2DP   (25 * PA_USEC_PER_MSEC) 
 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# define FIXED_LATENCY_RECORD_SCO    (25 * PA_USEC_PER_MSEC) 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  const  char *  const  valid_modargs [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " path " , 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-04 20:32:15 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    " autodetect_mtu " , 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 09:10:02 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    " output_rate_refresh_interval_ms " , 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    NULL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								enum  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    BLUETOOTH_MESSAGE_IO_THREAD_FAILED , 
							 
						 
					
						
							
								
									
										
										
										
											2014-02-04 19:04:05 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    BLUETOOTH_MESSAGE_STREAM_FD_HUP , 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-22 10:47:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    BLUETOOTH_MESSAGE_SET_TRANSPORT_PLAYING , 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    BLUETOOTH_MESSAGE_MAX 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								enum  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_SOURCE_MESSAGE_SETUP_STREAM  =  PA_SOURCE_MESSAGE_MAX , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								enum  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_SINK_MESSAGE_SETUP_STREAM  =  PA_SINK_MESSAGE_MAX , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								typedef  struct  bluetooth_msg  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_msgobject  parent ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_card  * card ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  bluetooth_msg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								PA_DEFINE_PRIVATE_CLASS ( bluetooth_msg ,  pa_msgobject ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define BLUETOOTH_MSG(o) (bluetooth_msg_cast(o)) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								struct  userdata  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_module  * module ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_core  * core ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:42 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * device_connection_changed_slot ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * transport_state_changed_slot ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * transport_speaker_volume_changed_slot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * transport_microphone_volume_changed_slot ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:42 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_bluetooth_discovery  * discovery ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_device  * device ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_bluetooth_transport  * transport ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  transport_acquired ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  stream_setup_done ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_card  * card ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_sink  * sink ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:48 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_source  * source ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_bluetooth_profile_t  profile ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    char  * output_port_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    char  * input_port_name ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_thread  * thread ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_thread_mq  thread_mq ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_rtpoll  * rtpoll ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_rtpoll_item  * rtpoll_item ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bluetooth_msg  * msg ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    int  stream_fd ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    int  stream_write_type ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    size_t  read_link_mtu ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  write_link_mtu ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  read_block_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  write_block_size ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    uint64_t  read_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint64_t  write_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_usec_t  started_at ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_smoother  * read_smoother ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memchunk  write_memchunk ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  pa_a2dp_codec  * a2dp_codec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * encoder_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sample_spec  encoder_sample_spec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * encoder_buffer ;                         /* Codec transfer buffer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  encoder_buffer_size ;                   /* Size of the buffer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * decoder_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sample_spec  decoder_sample_spec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * decoder_buffer ;                         /* Codec transfer buffer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  decoder_buffer_size ;                   /* Size of the buffer */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-21 18:41:25 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  message_handler_registered ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								typedef  enum  pa_bluetooth_form_factor  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_UNKNOWN , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_HEADSET , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_HANDSFREE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_MICROPHONE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_SPEAKER , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_HEADPHONE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_PORTABLE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_CAR , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_HIFI , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_BLUETOOTH_FORM_FACTOR_PHONE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}  pa_bluetooth_form_factor_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  pa_bluetooth_form_factor_t  form_factor_from_class ( uint32_t  class_of_device )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    unsigned  major ,  minor ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_form_factor_t  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    static  const  pa_bluetooth_form_factor_t  table [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ 1 ]  =  PA_BLUETOOTH_FORM_FACTOR_HEADSET , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ 2 ]  =  PA_BLUETOOTH_FORM_FACTOR_HANDSFREE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ 4 ]  =  PA_BLUETOOTH_FORM_FACTOR_MICROPHONE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ 5 ]  =  PA_BLUETOOTH_FORM_FACTOR_SPEAKER , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ 6 ]  =  PA_BLUETOOTH_FORM_FACTOR_HEADPHONE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ 7 ]  =  PA_BLUETOOTH_FORM_FACTOR_PORTABLE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ 8 ]  =  PA_BLUETOOTH_FORM_FACTOR_CAR , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ 10 ]  =  PA_BLUETOOTH_FORM_FACTOR_HIFI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  See  Bluetooth  Assigned  Numbers : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  https : //www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    major  =  ( class_of_device  > >  8 )  &  0x1F ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    minor  =  ( class_of_device  > >  2 )  &  0x3F ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( major )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  PA_BLUETOOTH_FORM_FACTOR_PHONE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  4 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " Unknown Bluetooth major device class %u " ,  major ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  PA_BLUETOOTH_FORM_FACTOR_UNKNOWN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    r  =  minor  <  PA_ELEMENTSOF ( table )  ?  table [ minor ]  :  PA_BLUETOOTH_FORM_FACTOR_UNKNOWN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_debug ( " Unknown Bluetooth minor device class %u " ,  minor ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  const  char  * form_factor_to_string ( pa_bluetooth_form_factor_t  ff )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( ff )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_UNKNOWN : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " unknown " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_HEADSET : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " headset " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_HANDSFREE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " hands-free " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_MICROPHONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " microphone " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_SPEAKER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " speaker " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_HEADPHONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " headphone " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_PORTABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " portable " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_CAR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " car " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_HIFI : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " hifi " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_PHONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  " phone " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_not_reached ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  connect_ports ( struct  userdata  * u ,  void  * new_data ,  pa_direction_t  direction )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port  * port ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( direction  = =  PA_DIRECTION_OUTPUT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_new_data  * sink_new_data  =  new_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert_se ( port  =  pa_hashmap_get ( u - > card - > ports ,  u - > output_port_name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert_se ( pa_hashmap_put ( sink_new_data - > ports ,  port - > name ,  port )  > =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_device_port_ref ( port ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_source_new_data  * source_new_data  =  new_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert_se ( port  =  pa_hashmap_get ( u - > card - > ports ,  u - > input_port_name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert_se ( pa_hashmap_put ( source_new_data - > ports ,  port - > name ,  port )  > =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_device_port_ref ( port ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  sco_process_render ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ssize_t  l ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memchunk  memchunk ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:29:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    int  saved_errno ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS  | | 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								              u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_render_full ( u - > sink ,  u - > write_block_size ,  & memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( memchunk . length  = =  u - > write_block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( ; ; )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        const  void  * p ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Now write that data to the socket. The socket is of type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  SEQPACKET ,  and  we  generated  the  data  of  the  MTU  size ,  so  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  should  just  work .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p  =  ( const  uint8_t  * )  pa_memblock_acquire_chunk ( & memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        l  =  pa_write ( u - > stream_fd ,  p ,  memchunk . length ,  & u - > stream_write_type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_release ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( l  ! =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( l  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:29:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        saved_errno  =  errno ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_unref ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( saved_errno  = =  EAGAIN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* Hmm, apparently the socket was not writable, give up for now.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  Because  the  data  was  already  rendered ,  let ' s  discard  the  block .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " Got EAGAIN on write() after POLLOUT, probably there is a temporary connection loss. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Failed to write data to SCO socket: %s " ,  pa_cstrerror ( saved_errno ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ( size_t )  l  < =  memchunk . length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ( size_t )  l  ! =  memchunk . length )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Wrote memory block to socket only partially! %llu written, wanted to write %llu. " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ( unsigned  long  long )  l , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    ( unsigned  long  long )  memchunk . length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:29:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_unref ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > write_index  + =  ( uint64_t )  memchunk . length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblock_unref ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  sco_process_push ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ssize_t  l ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memchunk  memchunk ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  cmsghdr  * cm ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  msghdr  m ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  found_tstamp  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_usec_t  tstamp  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS  | | 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								              u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > read_smoother ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memchunk . memblock  =  pa_memblock_new ( u - > core - > mempool ,  u - > read_block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memchunk . index  =  memchunk . length  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( ; ; )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        void  * p ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint8_t  aux [ 1024 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        struct  iovec  iov ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_zero ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_zero ( aux ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_zero ( iov ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m . msg_iov  =  & iov ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m . msg_iovlen  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m . msg_control  =  aux ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m . msg_controllen  =  sizeof ( aux ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p  =  pa_memblock_acquire ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        iov . iov_base  =  p ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        iov . iov_len  =  pa_memblock_get_length ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        l  =  recvmsg ( u - > stream_fd ,  & m ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_release ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( l  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( l  <  0  & &  errno  = =  EINTR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* Retry right away if we got interrupted */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_unref ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( l  <  0  & &  errno  = =  EAGAIN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* Hmm, apparently the socket was not readable, give up for now. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Failed to read data from SCO socket: %s " ,  l  <  0  ?  pa_cstrerror ( errno )  :  " EOF " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ( size_t )  l  < =  pa_memblock_get_length ( memchunk . memblock ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* In some rare occasions, we might receive packets of a very strange
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  size .  This  could  potentially  be  possible  if  the  SCO  packet  was 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  received  partially  over - the - air ,  or  more  probably  due  to  hardware 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  issues  in  our  Bluetooth  adapter .  In  these  cases ,  in  order  to  avoid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  an  assertion  failure  due  to  unaligned  data ,  just  discard  the  whole 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  packet  */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! pa_frame_aligned ( l ,  & u - > decoder_sample_spec ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_log_warn ( " SCO packet received of unaligned size: %zu " ,  l ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_unref ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memchunk . length  =  ( size_t )  l ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > read_index  + =  ( uint64_t )  l ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( cm  =  CMSG_FIRSTHDR ( & m ) ;  cm ;  cm  =  CMSG_NXTHDR ( & m ,  cm ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( cm - > cmsg_level  = =  SOL_SOCKET  & &  cm - > cmsg_type  = =  SO_TIMESTAMP )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            struct  timeval  * tv  =  ( struct  timeval * )  CMSG_DATA ( cm ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_rtclock_from_wallclock ( tv ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            tstamp  =  pa_timeval_load ( tv ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            found_tstamp  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! found_tstamp )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-21 20:36:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        PA_ONCE_BEGIN  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_warn ( " Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data! " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  PA_ONCE_END ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        tstamp  =  pa_rtclock_now ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_smoother_put ( u - > read_smoother ,  tstamp ,  pa_bytes_to_usec ( u - > read_index ,  & u - > decoder_sample_spec ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_smoother_resume ( u - > read_smoother ,  tstamp ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_source_post ( u - > source ,  & memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblock_unref ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  l ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  a2dp_prepare_encoder_buffer ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > encoder_buffer_size  <  u - > write_link_mtu )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_xfree ( u - > encoder_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_buffer  =  pa_xmalloc ( u - > write_link_mtu ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* Encoder buffer cannot be larger then link MTU, otherwise
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  encode  method  would  produce  larger  packets  then  link  MTU  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > encoder_buffer_size  =  u - > write_link_mtu ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  a2dp_prepare_decoder_buffer ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > decoder_buffer_size  <  u - > read_link_mtu )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_xfree ( u - > decoder_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > decoder_buffer  =  pa_xmalloc ( u - > read_link_mtu ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-17 14:43:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* Decoder buffer cannot be larger then link MTU, otherwise
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  decode  method  would  produce  larger  output  then  read_block_size  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > decoder_buffer_size  =  u - > read_link_mtu ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  a2dp_write_buffer ( struct  userdata  * u ,  size_t  nbytes )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  ret  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* Encoder function of A2DP codec may provide empty buffer, in this case do
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  not  post  any  empty  buffer  via  A2DP  socket .  It  may  be  because  of  codec 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  internal  state ,  e . g .  encoder  is  waiting  for  more  samples  so  it  can 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  provide  encoded  data .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( PA_UNLIKELY ( ! nbytes ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > write_index  + =  ( uint64_t )  u - > write_memchunk . length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_unref ( u - > write_memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memchunk_reset ( & u - > write_memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    for  ( ; ; )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ssize_t  l ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        l  =  pa_write ( u - > stream_fd ,  u - > encoder_buffer ,  nbytes ,  & u - > stream_write_type ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( l  ! =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( l  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-28 16:49:19 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( errno  = =  EAGAIN )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* Hmm, apparently the socket was not writable, give up for now */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:29:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                pa_log_debug ( " Got EAGAIN on write() after POLLOUT, probably there is a temporary connection loss. " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:29:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_error ( " Failed to write data to socket: %s " ,  pa_cstrerror ( errno ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ret  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( ( size_t )  l  < =  nbytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ( size_t )  l  ! =  nbytes )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_warn ( " Wrote memory block to socket only partially! %llu written, wanted to write %llu. " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        ( unsigned  long  long )  l , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        ( unsigned  long  long )  nbytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ret  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > write_index  + =  ( uint64_t )  u - > write_memchunk . length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_unref ( u - > write_memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memchunk_reset ( & u - > write_memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  a2dp_process_render ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  uint8_t  * ptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  processed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > a2dp_codec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* First, render some data */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > write_memchunk . memblock ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_render_full ( u - > sink ,  u - > write_block_size ,  & u - > write_memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > write_memchunk . length  = =  u - > write_block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    a2dp_prepare_encoder_buffer ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Try to create a packet of the full MTU */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ptr  =  ( const  uint8_t  * )  pa_memblock_acquire_chunk ( & u - > write_memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    length  =  u - > a2dp_codec - > encode_buffer ( u - > encoder_info ,  u - > write_index  /  pa_frame_size ( & u - > encoder_sample_spec ) ,  ptr ,  u - > write_memchunk . length ,  u - > encoder_buffer ,  u - > encoder_buffer_size ,  & processed ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblock_release ( u - > write_memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( processed  ! =  u - > write_memchunk . length )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Encoding error " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  a2dp_write_buffer ( u ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  a2dp_process_push ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  ret  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memchunk  memchunk ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > read_smoother ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > a2dp_codec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memchunk . memblock  =  pa_memblock_new ( u - > core - > mempool ,  u - > read_block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memchunk . index  =  memchunk . length  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    a2dp_prepare_decoder_buffer ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    for  ( ; ; )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-04 08:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        uint8_t  aux [ 1024 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        struct  iovec  iov ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        struct  cmsghdr  * cm ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        struct  msghdr  m ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        bool  found_tstamp  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_usec_t  tstamp ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        uint8_t  * ptr ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ssize_t  l ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        size_t  processed ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-05-04 08:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_zero ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_zero ( aux ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_zero ( iov ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m . msg_iov  =  & iov ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m . msg_iovlen  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m . msg_control  =  aux ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        m . msg_controllen  =  sizeof ( aux ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        iov . iov_base  =  u - > decoder_buffer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        iov . iov_len  =  u - > decoder_buffer_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        l  =  recvmsg ( u - > stream_fd ,  & m ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( l  < =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( l  <  0  & &  errno  = =  EINTR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                /* Retry right away if we got interrupted */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else  if  ( l  <  0  & &  errno  = =  EAGAIN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                /* Hmm, apparently the socket was not readable, give up for now. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_error ( " Failed to read data from socket: %s " ,  l  <  0  ?  pa_cstrerror ( errno )  :  " EOF " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ret  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_assert ( ( size_t )  l  < =  u - > decoder_buffer_size ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* TODO: get timestamp from rtp */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-04 08:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( cm  =  CMSG_FIRSTHDR ( & m ) ;  cm ;  cm  =  CMSG_NXTHDR ( & m ,  cm ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( cm - > cmsg_level  = =  SOL_SOCKET  & &  cm - > cmsg_type  = =  SO_TIMESTAMP )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                struct  timeval  * tv  =  ( struct  timeval * )  CMSG_DATA ( cm ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_rtclock_from_wallclock ( tv ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                tstamp  =  pa_timeval_load ( tv ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                found_tstamp  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! found_tstamp )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-04 08:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            PA_ONCE_BEGIN  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_log_warn ( " Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data! " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  PA_ONCE_END ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            tstamp  =  pa_rtclock_now ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ptr  =  pa_memblock_acquire ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        memchunk . length  =  pa_memblock_get_length ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        memchunk . length  =  u - > a2dp_codec - > decode_buffer ( u - > decoder_info ,  u - > decoder_buffer ,  l ,  ptr ,  memchunk . length ,  & processed ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_release ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( processed  ! =  ( size_t )  l )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_error ( " Decoding error " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ret  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        u - > read_index  + =  ( uint64_t )  memchunk . length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_smoother_put ( u - > read_smoother ,  tstamp ,  pa_bytes_to_usec ( u - > read_index ,  & u - > decoder_sample_spec ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-01-27 01:14:39 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_smoother_resume ( u - > read_smoother ,  tstamp ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /* Decoding of A2DP codec data may result in empty buffer, in this case
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  do  not  post  empty  audio  samples .  It  may  happen  due  to  algorithmic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  delay  of  audio  codec .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( PA_LIKELY ( memchunk . length ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_source_post ( u - > source ,  & memchunk ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  l ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblock_unref ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  update_sink_buffer_size ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    int  old_bufsize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    socklen_t  len  =  sizeof ( int ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ret  =  getsockopt ( u - > stream_fd ,  SOL_SOCKET ,  SO_SNDBUF ,  & old_bufsize ,  & len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ret  = =  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_warn ( " Changing bluetooth buffer size: Failed to getsockopt(SO_SNDBUF): %s " ,  pa_cstrerror ( errno ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        int  new_bufsize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Set send buffer size as small as possible. The minimum value is 1024 according to the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  socket  man  page .  The  data  is  written  to  the  socket  in  chunks  of  write_block_size ,  so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  there  should  at  least  be  room  for  two  chunks  in  the  buffer .  Generally ,  write_block_size 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  is  larger  than  512.  If  not ,  use  the  next  multiple  of  write_block_size  which  is  larger 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  than  1024.  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        new_bufsize  =  2  *  u - > write_block_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( new_bufsize  <  1024 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            new_bufsize  =  ( 1024  /  u - > write_block_size  +  1 )  *  u - > write_block_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* The kernel internally doubles the buffer size that was set by setsockopt and getsockopt
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  returns  the  doubled  value .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( new_bufsize  ! =  old_bufsize  /  2 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ret  =  setsockopt ( u - > stream_fd ,  SOL_SOCKET ,  SO_SNDBUF ,  & new_bufsize ,  len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ret  = =  - 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_log_warn ( " Changing bluetooth buffer size: Failed to change from %d to %d: %s " ,  old_bufsize  /  2 ,  new_bufsize ,  pa_cstrerror ( errno ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_log_info ( " Changing bluetooth buffer size: Changed from %d to %d " ,  old_bufsize  /  2 ,  new_bufsize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  teardown_stream ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > rtpoll_item )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_rtpoll_item_free ( u - > rtpoll_item ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > rtpoll_item  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > stream_fd  > =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_close ( u - > stream_fd ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > stream_fd  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > read_smoother )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_smoother_free ( u - > read_smoother ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > read_smoother  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > write_memchunk . memblock )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_unref ( u - > write_memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memchunk_reset ( & u - > write_memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_log_debug ( " Audio stream torn down " ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > stream_setup_done  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  transport_acquire ( struct  userdata  * u ,  bool  optional )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > transport_acquired ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_debug ( " Acquiring transport %s " ,  u - > transport - > path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > stream_fd  =  u - > transport - > acquire ( u - > transport ,  optional ,  & u - > read_link_mtu ,  & u - > write_link_mtu ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > stream_fd  <  0 ) 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  u - > stream_fd ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-22 10:47:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* transport_acquired must be set before calling
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  pa_bluetooth_transport_set_state ( )  */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > transport_acquired  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_info ( " Transport %s acquired: fd %d " ,  u - > transport - > path ,  u - > stream_fd ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-07-22 10:47:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > transport - > state  = =  PA_BLUETOOTH_TRANSPORT_STATE_IDLE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( pa_thread_mq_get ( )  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_asyncmsgq_post ( pa_thread_mq_get ( ) - > outq ,  PA_MSGOBJECT ( u - > msg ) ,  BLUETOOTH_MESSAGE_SET_TRANSPORT_PLAYING ,  NULL ,  0 ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_bluetooth_transport_set_state ( u - > transport ,  PA_BLUETOOTH_TRANSPORT_STATE_PLAYING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  transport_release ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Ignore if already released */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > transport_acquired ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_debug ( " Releasing transport %s " ,  u - > transport - > path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > transport - > release ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > transport_acquired  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    teardown_stream ( u ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Set transport state to idle if this was not already done by the remote end closing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  the  file  descriptor .  Only  do  this  when  called  from  the  I / O  thread  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_thread_mq_get ( )  ! =  NULL  & &  u - > transport - > state  = =  PA_BLUETOOTH_TRANSPORT_STATE_PLAYING ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_asyncmsgq_post ( pa_thread_mq_get ( ) - > outq ,  PA_MSGOBJECT ( u - > msg ) ,  BLUETOOTH_MESSAGE_STREAM_FD_HUP ,  NULL ,  0 ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from I/O thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  handle_sink_block_size_change ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_max_request_within_thread ( u - > sink ,  u - > write_block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_fixed_latency_within_thread ( u - > sink , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                            ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                             FIXED_LATENCY_PLAYBACK_A2DP  :  FIXED_LATENCY_PLAYBACK_SCO )  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                            pa_bytes_to_usec ( u - > write_block_size ,  & u - > encoder_sample_spec ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* If there is still data in the memchunk, we have to discard it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  because  the  write_block_size  may  have  changed .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > write_memchunk . memblock )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_unref ( u - > write_memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memchunk_reset ( & u - > write_memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    update_sink_buffer_size ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from I/O thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  transport_config_mtu ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        u - > read_block_size  =  u - > read_link_mtu ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > write_block_size  =  u - > write_link_mtu ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-13 12:49:28 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! pa_frame_aligned ( u - > read_block_size ,  & u - > source - > sample_spec ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " Got invalid read MTU: %lu, rounding down " ,  u - > read_block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > read_block_size  =  pa_frame_align ( u - > read_block_size ,  & u - > source - > sample_spec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! pa_frame_aligned ( u - > write_block_size ,  & u - > sink - > sample_spec ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " Got invalid write MTU: %lu, rounding down " ,  u - > write_block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > write_block_size  =  pa_frame_align ( u - > write_block_size ,  & u - > sink - > sample_spec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_assert ( u - > a2dp_codec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > write_block_size  =  u - > a2dp_codec - > get_write_block_size ( u - > encoder_info ,  u - > write_link_mtu ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > read_block_size  =  u - > a2dp_codec - > get_read_block_size ( u - > decoder_info ,  u - > read_link_mtu ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > sink ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        handle_sink_block_size_change ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > source ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_source_set_fixed_latency_within_thread ( u - > source , 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                                  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                                   FIXED_LATENCY_RECORD_A2DP  :  FIXED_LATENCY_RECORD_SCO )  + 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                                  pa_bytes_to_usec ( u - > read_block_size ,  & u - > decoder_sample_spec ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Run from I/O thread */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  setup_stream ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  pollfd  * pollfd ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  one ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-06-18 10:15:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > stream_fd  > =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* return if stream is already set up */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > stream_setup_done ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_log_info ( " Transport %s resuming " ,  u - > transport - > path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( u - > a2dp_codec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > a2dp_codec - > reset ( u - > encoder_info )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( u - > a2dp_codec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > a2dp_codec - > reset ( u - > decoder_info )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    transport_config_mtu ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_make_fd_nonblock ( u - > stream_fd ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_make_socket_low_delay ( u - > stream_fd ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    one  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( setsockopt ( u - > stream_fd ,  SOL_SOCKET ,  SO_TIMESTAMP ,  & one ,  sizeof ( one ) )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_warn ( " Failed to enable SO_TIMESTAMP: %s " ,  pa_cstrerror ( errno ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_debug ( " Stream properly set up, we're ready to roll! " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > rtpoll_item  =  pa_rtpoll_item_new ( u - > rtpoll ,  PA_RTPOLL_NEVER ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pollfd  =  pa_rtpoll_item_get_pollfd ( u - > rtpoll_item ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pollfd - > fd  =  u - > stream_fd ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pollfd - > events  =  pollfd - > revents  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > read_index  =  u - > write_index  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > started_at  =  0 ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > stream_setup_done  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > source ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > read_smoother  =  pa_smoother_new ( PA_USEC_PER_SEC ,  2 * PA_USEC_PER_SEC ,  true ,  true ,  10 ,  pa_rtclock_now ( ) ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Called from I/O thread, returns true if the transport was acquired or
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  a  connection  was  requested  successfully .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  bool  setup_transport_and_stream ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  transport_error ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    transport_error  =  transport_acquire ( u ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( transport_error  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( transport_error  ! =  - EAGAIN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( setup_stream ( u )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  source_process_msg ( pa_msgobject  * o ,  int  code ,  void  * data ,  int64_t  offset ,  pa_memchunk  * chunk )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u  =  PA_SOURCE ( o ) - > userdata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > source  = =  PA_SOURCE ( o ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( code )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SOURCE_MESSAGE_GET_LATENCY :  { 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												source/sink: Allow pa_{source, sink}_get_latency_within_thread() to return negative values
The reported latency of source or sink is based on measured initial conditions.
If the conditions contain an error, the estimated latency values may become negative.
This does not indicate that the latency is indeed negative but can be considered
merely an offset error. The current get_latency_in_thread() calls and the
implementations of the PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY messages truncate negative
latencies because they do not make sense from a physical point of view. In fact,
the values are truncated twice, once in the message handler and a second time in
the pa_{source,sink}_get_latency_within_thread() call itself.
This leads to two problems for the latency controller within module-loopback:
- Truncating leads to discontinuities in the latency reports which then trigger
  unwanted end to end latency corrections.
- If a large negative port latency offsets is set, the reported latency is always 0,
  making it impossible to control the end to end latency at all.
This patch is a pre-condition for solving these problems.
It adds a new flag to pa_{sink,source}_get_latency_within_thread() to allow
negative return values. Truncating is also removed in all implementations of the
PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY message handlers. The allow_negative flag
is set to false for all calls of pa_{sink,source}_get_latency_within_thread()
except when used within PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY. This means that the
original behavior is not altered in most cases. Only if a positive latency offset
is set and the message returns a negative value, the reported latency is smaller
because the values are not truncated twice.
Additionally let PA_SOURCE_MESSAGE_GET_LATENCY return -pa_sink_get_latency_within_thread()
for monitor sources because the source gets the data before it is played.
											 
										 
										
											2017-04-17 19:50:10 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            int64_t  wi ,  ri ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( u - > read_smoother )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                wi  =  pa_smoother_get ( u - > read_smoother ,  pa_rtclock_now ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                ri  =  pa_bytes_to_usec ( u - > read_index ,  & u - > decoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												source/sink: Allow pa_{source, sink}_get_latency_within_thread() to return negative values
The reported latency of source or sink is based on measured initial conditions.
If the conditions contain an error, the estimated latency values may become negative.
This does not indicate that the latency is indeed negative but can be considered
merely an offset error. The current get_latency_in_thread() calls and the
implementations of the PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY messages truncate negative
latencies because they do not make sense from a physical point of view. In fact,
the values are truncated twice, once in the message handler and a second time in
the pa_{source,sink}_get_latency_within_thread() call itself.
This leads to two problems for the latency controller within module-loopback:
- Truncating leads to discontinuities in the latency reports which then trigger
  unwanted end to end latency corrections.
- If a large negative port latency offsets is set, the reported latency is always 0,
  making it impossible to control the end to end latency at all.
This patch is a pre-condition for solving these problems.
It adds a new flag to pa_{sink,source}_get_latency_within_thread() to allow
negative return values. Truncating is also removed in all implementations of the
PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY message handlers. The allow_negative flag
is set to false for all calls of pa_{sink,source}_get_latency_within_thread()
except when used within PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY. This means that the
original behavior is not altered in most cases. Only if a positive latency offset
is set and the message returns a negative value, the reported latency is smaller
because the values are not truncated twice.
Additionally let PA_SOURCE_MESSAGE_GET_LATENCY return -pa_sink_get_latency_within_thread()
for monitor sources because the source gets the data before it is played.
											 
										 
										
											2017-04-17 19:50:10 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                * ( ( int64_t * )  data )  =  u - > source - > thread_info . fixed_latency  +  wi  -  ri ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            }  else 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												source/sink: Allow pa_{source, sink}_get_latency_within_thread() to return negative values
The reported latency of source or sink is based on measured initial conditions.
If the conditions contain an error, the estimated latency values may become negative.
This does not indicate that the latency is indeed negative but can be considered
merely an offset error. The current get_latency_in_thread() calls and the
implementations of the PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY messages truncate negative
latencies because they do not make sense from a physical point of view. In fact,
the values are truncated twice, once in the message handler and a second time in
the pa_{source,sink}_get_latency_within_thread() call itself.
This leads to two problems for the latency controller within module-loopback:
- Truncating leads to discontinuities in the latency reports which then trigger
  unwanted end to end latency corrections.
- If a large negative port latency offsets is set, the reported latency is always 0,
  making it impossible to control the end to end latency at all.
This patch is a pre-condition for solving these problems.
It adds a new flag to pa_{sink,source}_get_latency_within_thread() to allow
negative return values. Truncating is also removed in all implementations of the
PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY message handlers. The allow_negative flag
is set to false for all calls of pa_{sink,source}_get_latency_within_thread()
except when used within PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY. This means that the
original behavior is not altered in most cases. Only if a positive latency offset
is set and the message returns a negative value, the reported latency is smaller
because the values are not truncated twice.
Additionally let PA_SOURCE_MESSAGE_GET_LATENCY return -pa_sink_get_latency_within_thread()
for monitor sources because the source gets the data before it is played.
											 
										 
										
											2017-04-17 19:50:10 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                * ( ( int64_t * )  data )  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SOURCE_MESSAGE_SETUP_STREAM : 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-18 10:15:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* Skip stream setup if stream_fd has been invalidated.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               This  can  occur  if  the  stream  has  already  been  set  up  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               then  immediately  received  POLLHUP .  If  the  stream  has 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               already  been  set  up  earlier ,  then  this  setup_stream ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               call  is  redundant  anyway ,  but  currently  the  code 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               is  such  that  this  kind  of  unnecessary  setup_stream ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               calls  can  happen .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( u - > stream_fd  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_log_debug ( " Skip source stream setup while closing " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                setup_stream ( u ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-19 16:48:25 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  pa_source_process_msg ( o ,  code ,  data ,  offset ,  chunk ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Called from the IO thread. */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-19 23:11:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  source_set_state_in_io_thread_cb ( pa_source  * s ,  pa_source_state_t  new_state ,  pa_suspend_cause_t  new_suspend_cause )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  s - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( new_state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SOURCE_SUSPENDED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* Ignore if transition is PA_SOURCE_INIT->PA_SOURCE_SUSPENDED */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-20 16:26:20 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ! PA_SOURCE_IS_OPENED ( s - > thread_info . state ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* Stop the device if the sink is suspended as well */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! u - > sink  | |  u - > sink - > state  = =  PA_SINK_SUSPENDED ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                transport_release ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( u - > read_smoother ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_smoother_pause ( u - > read_smoother ,  pa_rtclock_now ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SOURCE_IDLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SOURCE_RUNNING : 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-20 16:26:20 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( s - > thread_info . state  ! =  PA_SOURCE_SUSPENDED ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* Resume the device if the sink was suspended as well */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! u - > sink  | |  ! PA_SINK_IS_OPENED ( u - > sink - > thread_info . state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( ! setup_transport_and_stream ( u ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* We don't resume the smoother here. Instead we
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  wait  until  the  first  packet  arrives  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SOURCE_UNLINKED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SOURCE_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SOURCE_INVALID_STATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  source_set_volume_cb ( pa_source  * s )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_volume_t  volume ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s - > core ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u  =  s - > userdata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > source  = =  s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > transport - > set_microphone_volume  = =  NULL ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* If we are in the AG role, we send a command to the head set to change
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  the  microphone  gain .  In  the  HS  role ,  source  and  sink  are  swapped ,  so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  in  this  case  we  notify  the  AG  that  the  speaker  gain  has  changed  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    volume  =  u - > transport - > set_microphone_volume ( u - > transport ,  pa_cvolume_max ( & s - > real_volume ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_cvolume_set ( & s - > real_volume ,  u - > decoder_sample_spec . channels ,  volume ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-07 13:44:54 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* Set soft volume when in headset role */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG  | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_cvolume_set ( & s - > soft_volume ,  u - > decoder_sample_spec . channels ,  volume ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:48 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  add_source ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_source_new_data  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_source_new_data_init ( & data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . module  =  u - > module ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . card  =  u - > card ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . driver  =  __FILE__ ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-15 17:52:40 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    data . name  =  pa_sprintf_malloc ( " bluez_source.%s.%s " ,  u - > device - > address ,  pa_bluetooth_profile_to_string ( u - > profile ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:48 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    data . namereg_fail  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( data . proplist ,  " bluetooth.protocol " ,  pa_bluetooth_profile_to_string ( u - > profile ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-31 13:59:40 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > a2dp_codec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_sets ( data . proplist ,  PA_PROP_BLUETOOTH_CODEC ,  u - > a2dp_codec - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_source_new_data_set_sample_spec ( & data ,  & u - > decoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_proplist_sets ( data . proplist ,  PA_PROP_DEVICE_INTENDED_ROLES ,  " phone " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:48 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    connect_ports ( u ,  & data ,  PA_DIRECTION_INPUT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > transport_acquired ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        switch  ( u - > profile )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_A2DP_SOURCE : 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_HFP_AG : 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_HSP_AG : 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:48 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                data . suspend_cause  =  PA_SUSPEND_USER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_HSP_HS : 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_HFP_HF : 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* u->stream_fd contains the error returned by the last transport_acquire()
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 *  EAGAIN  means  we  are  waiting  for  a  NewConnection  signal  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( u - > stream_fd  = =  - EAGAIN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    data . suspend_cause  =  PA_SUSPEND_USER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    pa_assert_not_reached ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_A2DP_SINK : 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:48 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_OFF : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_assert_not_reached ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > source  =  pa_source_new ( u - > core ,  & data ,  PA_SOURCE_HARDWARE | PA_SOURCE_LATENCY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_source_new_data_done ( & data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > source )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Failed to create source " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > source - > userdata  =  u ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > source - > parent . process_msg  =  source_process_msg ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > source - > set_state_in_io_thread  =  source_set_state_in_io_thread_cb ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:48 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_source_set_set_volume_callback ( u - > source ,  source_set_volume_cb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > source - > n_volume_steps  =  16 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:48 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  sink_process_msg ( pa_msgobject  * o ,  int  code ,  void  * data ,  int64_t  offset ,  pa_memchunk  * chunk )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u  =  PA_SINK ( o ) - > userdata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > sink  = =  PA_SINK ( o ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( code )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_MESSAGE_GET_LATENCY :  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            int64_t  wi  =  0 ,  ri  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( u - > read_smoother )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ri  =  pa_smoother_get ( u - > read_smoother ,  pa_rtclock_now ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                wi  =  pa_bytes_to_usec ( u - > write_index  +  u - > write_block_size ,  & u - > encoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            }  else  if  ( u - > started_at )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                ri  =  pa_rtclock_now ( )  -  u - > started_at ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                wi  =  pa_bytes_to_usec ( u - > write_index ,  & u - > encoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												source/sink: Allow pa_{source, sink}_get_latency_within_thread() to return negative values
The reported latency of source or sink is based on measured initial conditions.
If the conditions contain an error, the estimated latency values may become negative.
This does not indicate that the latency is indeed negative but can be considered
merely an offset error. The current get_latency_in_thread() calls and the
implementations of the PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY messages truncate negative
latencies because they do not make sense from a physical point of view. In fact,
the values are truncated twice, once in the message handler and a second time in
the pa_{source,sink}_get_latency_within_thread() call itself.
This leads to two problems for the latency controller within module-loopback:
- Truncating leads to discontinuities in the latency reports which then trigger
  unwanted end to end latency corrections.
- If a large negative port latency offsets is set, the reported latency is always 0,
  making it impossible to control the end to end latency at all.
This patch is a pre-condition for solving these problems.
It adds a new flag to pa_{sink,source}_get_latency_within_thread() to allow
negative return values. Truncating is also removed in all implementations of the
PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY message handlers. The allow_negative flag
is set to false for all calls of pa_{sink,source}_get_latency_within_thread()
except when used within PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY. This means that the
original behavior is not altered in most cases. Only if a positive latency offset
is set and the message returns a negative value, the reported latency is smaller
because the values are not truncated twice.
Additionally let PA_SOURCE_MESSAGE_GET_LATENCY return -pa_sink_get_latency_within_thread()
for monitor sources because the source gets the data before it is played.
											 
										 
										
											2017-04-17 19:50:10 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            * ( ( int64_t * )  data )  =  u - > sink - > thread_info . fixed_latency  +  wi  -  ri ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_MESSAGE_SETUP_STREAM : 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-18 10:15:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* Skip stream setup if stream_fd has been invalidated.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               This  can  occur  if  the  stream  has  already  been  set  up  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               then  immediately  received  POLLHUP .  If  the  stream  has 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               already  been  set  up  earlier ,  then  this  setup_stream ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               call  is  redundant  anyway ,  but  currently  the  code 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               is  such  that  this  kind  of  unnecessary  setup_stream ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								               calls  can  happen .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( u - > stream_fd  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_log_debug ( " Skip sink stream setup while closing " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                setup_stream ( u ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-02-19 16:48:25 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  pa_sink_process_msg ( o ,  code ,  data ,  offset ,  chunk ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Called from the IO thread. */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-19 23:11:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  sink_set_state_in_io_thread_cb ( pa_sink  * s ,  pa_sink_state_t  new_state ,  pa_suspend_cause_t  new_suspend_cause )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  s - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( new_state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_SUSPENDED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* Ignore if transition is PA_SINK_INIT->PA_SINK_SUSPENDED */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-20 16:26:20 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ! PA_SINK_IS_OPENED ( s - > thread_info . state ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* Stop the device if the source is suspended as well */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! u - > source  | |  u - > source - > state  = =  PA_SOURCE_SUSPENDED ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                /* We deliberately ignore whether stopping
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 *  actually  worked .  Since  the  stream_fd  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 *  closed  it  doesn ' t  really  matter  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                transport_release ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_IDLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_RUNNING : 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-20 16:26:20 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( s - > thread_info . state  ! =  PA_SINK_SUSPENDED ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* Resume the device if the source was suspended as well */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! u - > source  | |  ! PA_SOURCE_IS_OPENED ( u - > source - > thread_info . state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( ! setup_transport_and_stream ( u ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_UNLINKED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_INIT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_INVALID_STATE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_set_volume_cb ( pa_sink  * s )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_volume_t  volume ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s - > core ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u  =  s - > userdata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > sink  = =  s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > transport - > set_speaker_volume  = =  NULL ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* If we are in the AG role, we send a command to the head set to change
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  the  speaker  gain .  In  the  HS  role ,  source  and  sink  are  swapped ,  so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  in  this  case  we  notify  the  AG  that  the  microphone  gain  has  changed  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    volume  =  u - > transport - > set_speaker_volume ( u - > transport ,  pa_cvolume_max ( & s - > real_volume ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_cvolume_set ( & s - > real_volume ,  u - > encoder_sample_spec . channels ,  volume ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-07 13:44:54 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* Set soft volume when in headset role */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG  | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_cvolume_set ( & s - > soft_volume ,  u - > encoder_sample_spec . channels ,  volume ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  add_sink ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_new_data  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_new_data_init ( & data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . module  =  u - > module ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . card  =  u - > card ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . driver  =  __FILE__ ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-15 17:52:40 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    data . name  =  pa_sprintf_malloc ( " bluez_sink.%s.%s " ,  u - > device - > address ,  pa_bluetooth_profile_to_string ( u - > profile ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    data . namereg_fail  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( data . proplist ,  " bluetooth.protocol " ,  pa_bluetooth_profile_to_string ( u - > profile ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-31 13:59:40 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > a2dp_codec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_sets ( data . proplist ,  PA_PROP_BLUETOOTH_CODEC ,  u - > a2dp_codec - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_sink_new_data_set_sample_spec ( & data ,  & u - > encoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_proplist_sets ( data . proplist ,  PA_PROP_DEVICE_INTENDED_ROLES ,  " phone " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    connect_ports ( u ,  & data ,  PA_DIRECTION_OUTPUT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > transport_acquired ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        switch  ( u - > profile )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_HFP_AG : 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_HSP_AG : 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                data . suspend_cause  =  PA_SUSPEND_USER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_HSP_HS : 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_HFP_HF : 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* u->stream_fd contains the error returned by the last transport_acquire()
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 *  EAGAIN  means  we  are  waiting  for  a  NewConnection  signal  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( u - > stream_fd  = =  - EAGAIN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    data . suspend_cause  =  PA_SUSPEND_USER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    pa_assert_not_reached ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_A2DP_SINK : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                /* Profile switch should have failed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_A2DP_SOURCE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_PROFILE_OFF : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_assert_not_reached ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink  =  pa_sink_new ( u - > core ,  & data ,  PA_SINK_HARDWARE | PA_SINK_LATENCY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_new_data_done ( & data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > sink )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Failed to create sink " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink - > userdata  =  u ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > sink - > parent . process_msg  =  sink_process_msg ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > sink - > set_state_in_io_thread  =  sink_set_state_in_io_thread_cb ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sink_set_set_volume_callback ( u - > sink ,  sink_set_volume_cb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > sink - > n_volume_steps  =  16 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  transport_config ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        u - > encoder_sample_spec . format  =  PA_SAMPLE_S16LE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_sample_spec . channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_sample_spec . rate  =  8000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > decoder_sample_spec . format  =  PA_SAMPLE_S16LE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > decoder_sample_spec . channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > decoder_sample_spec . rate  =  8000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        bool  is_a2dp_sink  =  u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        void  * info ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_assert ( ! u - > a2dp_codec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( ! u - > encoder_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( ! u - > decoder_info ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        u - > a2dp_codec  =  u - > transport - > a2dp_codec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( u - > a2dp_codec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-04 19:40:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        info  =  u - > a2dp_codec - > init ( is_a2dp_sink ,  false ,  u - > transport - > config ,  u - > transport - > config_size ,  is_a2dp_sink  ?  & u - > encoder_sample_spec  :  & u - > decoder_sample_spec ,  u - > core ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( is_a2dp_sink ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > encoder_info  =  info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > decoder_info  =  info ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! info ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  setup_transport ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_transport  * t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ! u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > profile  ! =  PA_BLUETOOTH_PROFILE_OFF ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* check if profile has a transport */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    t  =  u - > device - > transports [ u - > profile ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! t  | |  t - > state  < =  PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED )  { 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-07 13:44:54 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_log_warn ( " Profile %s has no transport " ,  pa_bluetooth_profile_to_string ( u - > profile ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > transport  =  t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE  | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG  | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        transport_acquire ( u ,  true ) ;  /* In case of error, the sink/sources will be created suspended */ 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        int  transport_error ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transport_error  =  transport_acquire ( u ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( transport_error  <  0  & &  transport_error  ! =  - EAGAIN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - 1 ;  /* We need to fail here until the interactions with module-suspend-on-idle and alike get improved */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  transport_config ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:49 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  pa_direction_t  get_profile_direction ( pa_bluetooth_profile_t  p )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    static  const  pa_direction_t  profile_direction [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_A2DP_SINK ]  =  PA_DIRECTION_OUTPUT , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_A2DP_SOURCE ]  =  PA_DIRECTION_INPUT , 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_HSP_HS ]  =  PA_DIRECTION_INPUT  |  PA_DIRECTION_OUTPUT , 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_HSP_AG ]  =  PA_DIRECTION_INPUT  |  PA_DIRECTION_OUTPUT , 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_HFP_HF ]  =  PA_DIRECTION_INPUT  |  PA_DIRECTION_OUTPUT , 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_HFP_AG ]  =  PA_DIRECTION_INPUT  |  PA_DIRECTION_OUTPUT , 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:49 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_OFF ]  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  profile_direction [ p ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  init_profile ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  r  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > profile  ! =  PA_BLUETOOTH_PROFILE_OFF ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    r  =  setup_transport ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( r  = =  - EINPROGRESS ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else  if  ( r  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:49 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( get_profile_direction  ( u - > profile )  &  PA_DIRECTION_OUTPUT ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( add_sink ( u )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            r  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:49 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( get_profile_direction  ( u - > profile )  &  PA_DIRECTION_INPUT ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:48 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( add_source ( u )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            r  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  write_block ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  n_written ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > write_index  < =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > started_at  =  pa_rtclock_now ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ( n_written  =  a2dp_process_render ( u ) )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ( n_written  =  sco_process_render ( u ) )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  n_written ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* I/O thread function */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  thread_func ( void  * userdata )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  userdata  * u  =  userdata ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    unsigned  blocks_to_write  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    unsigned  bytes_to_write  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:51:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  timeval  tv_last_output_rate_change ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_debug ( " IO Thread starting up " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > core - > realtime_scheduling ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-21 09:45:26 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_thread_make_realtime ( u - > core - > realtime_priority ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_thread_mq_install ( & u - > thread_mq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Setup the stream only if the transport was already acquired */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > transport_acquired ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        setup_stream ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:51:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_gettimeofday ( & tv_last_output_rate_change ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    for  ( ; ; )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        struct  pollfd  * pollfd ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        int  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        bool  disable_timer  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        bool  writable  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        bool  have_source  =  u - > source  ?  PA_SOURCE_IS_LINKED ( u - > source - > thread_info . state )  :  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        bool  have_sink  =  u - > sink  ?  PA_SINK_IS_LINKED ( u - > sink - > thread_info . state )  :  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pollfd  =  u - > rtpoll_item  ?  pa_rtpoll_item_get_pollfd ( u - > rtpoll_item ,  NULL )  :  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /* Check for stream error or close */ 
							 
						 
					
						
							
								
									
										
										
										
											2014-06-01 14:55:02 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( pollfd  & &  ( pollfd - > revents  &  ~ ( POLLOUT | POLLIN ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " FD error: %s%s%s%s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        pollfd - > revents  &  POLLERR  ?  " POLLERR  "  : " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        pollfd - > revents  &  POLLHUP  ?  " POLLHUP  "  : " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        pollfd - > revents  &  POLLPRI  ?  " POLLPRI  "  : " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        pollfd - > revents  &  POLLNVAL  ?  " POLLNVAL  "  : " " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( pollfd - > revents  &  POLLHUP )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pollfd  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                teardown_stream ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                blocks_to_write  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                bytes_to_write  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-06-01 14:55:02 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                pa_asyncmsgq_post ( pa_thread_mq_get ( ) - > outq ,  PA_MSGOBJECT ( u - > msg ) ,  BLUETOOTH_MESSAGE_STREAM_FD_HUP ,  NULL ,  0 ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /* If there is a pollfd, the stream is set up and we need to do something */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( pollfd )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* Handle source if present */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( have_source )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* We should send two blocks to the device before we expect a response. */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-27 08:41:27 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  ( have_sink  & &  u - > write_index  = =  0  & &  u - > read_index  < =  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    blocks_to_write  =  2 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* If we got woken up by POLLIN let's do some reading */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( pollfd - > revents  &  POLLIN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    int  n_read ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        n_read  =  a2dp_process_push ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        n_read  =  sco_process_push ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    if  ( n_read  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        goto  fail ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-08-27 08:41:27 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    if  ( have_sink  & &  n_read  >  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        /* We just read something, so we are supposed to write something, too */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        bytes_to_write  + =  n_read ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        blocks_to_write  + =  bytes_to_write  /  u - > write_block_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        bytes_to_write  =  bytes_to_write  %  u - > write_block_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
									
										
										
										
											2014-01-27 01:14:38 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* Handle sink if present */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( have_sink )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* Process rewinds */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( PA_UNLIKELY ( u - > sink - > thread_info . rewind_requested ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    pa_sink_process_rewind ( u - > sink ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* Test if the stream is writable */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  ( pollfd - > revents  &  POLLOUT ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    writable  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* If we have a source, we let the source determine the timing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 *  for  the  sink  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( have_source )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    if  ( writable  & &  blocks_to_write  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        int  result ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        if  ( ( result  =  write_block ( u ) )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            goto  fail ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        blocks_to_write  - =  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        /* writable controls whether we set POLLOUT when polling - we set it to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  false  to  enable  POLLOUT .  If  there  are  more  blocks  to  write ,  we  want  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  be  woken  up  immediately  when  the  socket  becomes  writable .  If  there 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  aren ' t  currently  any  more  blocks  to  write ,  then  we ' ll  have  to  wait 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  until  we ' ve  received  more  data ,  so  in  that  case  we  only  want  to  set 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  POLLIN .  Note  that  when  we  are  woken  up  the  next  time ,  POLLOUT  won ' t  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  set  in  revents  even  if  the  socket  has  meanwhile  become  writable ,  which 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  may  seem  bad ,  but  in  that  case  we ' ll  set  POLLOUT  in  the  subsequent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  poll ,  and  the  poll  will  return  immediately ,  so  our  writes  won ' t  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  delayed .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        if  ( blocks_to_write  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            writable  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                /* There is no source, we have to use the system clock for timing */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    bool  have_written  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    pa_usec_t  time_passed  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    pa_usec_t  audio_sent  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    if  ( u - > started_at )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        time_passed  =  pa_rtclock_now ( )  -  u - > started_at ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        audio_sent  =  pa_bytes_to_usec ( u - > write_index ,  & u - > encoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    /* A new block needs to be sent. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    if  ( audio_sent  < =  time_passed )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        size_t  bytes_to_send  =  pa_usec_to_bytes ( time_passed  -  audio_sent ,  & u - > encoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        /* There are more than two blocks that need to be written. It seems that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  the  socket  has  not  been  accepting  data  fast  enough  ( could  be  due  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  hiccups  in  the  wireless  transmission ) .  We  need  to  discard  everything 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  older  than  two  block  sizes  to  keep  the  latency  from  growing .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        if  ( bytes_to_send  >  2  *  u - > write_block_size )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            uint64_t  skip_bytes ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            pa_memchunk  tmp ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-30 00:00:50 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            size_t  max_render_size  =  pa_frame_align ( pa_mempool_block_size_max ( u - > core - > mempool ) ,  & u - > encoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            pa_usec_t  skip_usec ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            skip_bytes  =  bytes_to_send  -  2  *  u - > write_block_size ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            skip_usec  =  pa_bytes_to_usec ( skip_bytes ,  & u - > encoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            pa_log_debug ( " Skipping %llu us (= %llu bytes) in audio stream " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                        ( unsigned  long  long )  skip_usec , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                        ( unsigned  long  long )  skip_bytes ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            while  ( skip_bytes  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                size_t  bytes_to_render ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-30 00:00:50 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                if  ( skip_bytes  >  max_render_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    bytes_to_render  =  max_render_size ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    bytes_to_render  =  skip_bytes ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                pa_sink_render_full ( u - > sink ,  bytes_to_render ,  & tmp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                pa_memblock_unref ( tmp . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                u - > write_index  + =  bytes_to_render ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                skip_bytes  - =  bytes_to_render ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            } 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            if  ( u - > write_index  >  0  & &  u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                size_t  new_write_block_size  =  u - > a2dp_codec - > reduce_encoder_bitrate ( u - > encoder_info ,  u - > write_link_mtu ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                if  ( new_write_block_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    u - > write_block_size  =  new_write_block_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    handle_sink_block_size_change ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                } 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:51:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                pa_gettimeofday ( & tv_last_output_rate_change ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        blocks_to_write  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    /* If the stream is writable, send some data if necessary */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    if  ( writable  & &  blocks_to_write  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        int  result ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        if  ( ( result  =  write_block ( u ) )  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            goto  fail ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        blocks_to_write  - =  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        writable  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        if  ( result ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            have_written  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    /* If nothing was written during this iteration, either the stream
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     *  is  not  writable  or  there  was  no  write  pending .  Set  up  a  timer  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     *  will  wake  up  the  thread  when  the  next  data  needs  to  be  written .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    if  ( ! have_written )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        pa_usec_t  sleep_for ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        pa_usec_t  next_write_at ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        if  ( writable )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            /* There was no write pending on this iteration of the loop.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             *  Let ' s  estimate  when  we  need  to  wake  up  next  */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            next_write_at  =  pa_bytes_to_usec ( u - > write_index ,  & u - > encoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            sleep_for  =  time_passed  <  next_write_at  ?  next_write_at  -  time_passed  :  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            /* pa_log("Sleeping for %lu; time passed %lu, next write at %lu", (unsigned long) sleep_for, (unsigned long) time_passed, (unsigned long)next_write_at); */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:51:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK  & &  u - > write_memchunk . memblock  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                /* write_block() is keeping up with input, try increasing bitrate */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                if  ( u - > a2dp_codec - > increase_encoder_bitrate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    & &  pa_timeval_age ( & tv_last_output_rate_change )  > =  u - > device - > output_rate_refresh_interval_ms  *  PA_USEC_PER_MSEC )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    size_t  new_write_block_size  =  u - > a2dp_codec - > increase_encoder_bitrate ( u - > encoder_info ,  u - > write_link_mtu ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    if  ( new_write_block_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                        u - > write_block_size  =  new_write_block_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                        handle_sink_block_size_change ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                    pa_gettimeofday ( & tv_last_output_rate_change ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            } 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        }  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            /* We could not write because the stream was not ready. Let's try
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             *  again  in  500  ms  and  drop  audio  if  we  still  can ' t  write .  The 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                             *  thread  will  also  be  woken  up  when  we  can  write  again .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            sleep_for  =  PA_USEC_PER_MSEC  *  500 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        pa_rtpoll_set_timer_relative ( u - > rtpoll ,  sleep_for ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        disable_timer  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* Set events to wake up the thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pollfd - > events  =  ( short )  ( ( ( have_sink  & &  ! writable )  ?  POLLOUT  :  0 )  |  ( have_source  ?  POLLIN  :  0 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( disable_timer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_rtpoll_set_timer_disabled ( u - > rtpoll ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-10-28 13:46:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ( ret  =  pa_rtpoll_run ( u - > rtpoll ) )  <  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " pa_rtpoll_run failed with: %d " ,  ret ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ret  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " IO thread shutdown requested, stopping cleanly " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            transport_release ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  finish ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								fail : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_debug ( " IO thread failed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_asyncmsgq_post ( pa_thread_mq_get ( ) - > outq ,  PA_MSGOBJECT ( u - > msg ) ,  BLUETOOTH_MESSAGE_IO_THREAD_FAILED ,  NULL ,  0 ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_asyncmsgq_wait_for ( u - > thread_mq . inq ,  PA_MESSAGE_SHUTDOWN ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								finish : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_debug ( " IO thread shutting down " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  start_thread ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ! u - > thread ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ! u - > rtpoll ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ! u - > rtpoll_item ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > rtpoll  =  pa_rtpoll_new ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-13 18:43:38 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_thread_mq_init ( & u - > thread_mq ,  u - > core - > mainloop ,  u - > rtpoll )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " pa_thread_mq_init() failed. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ( u - > thread  =  pa_thread_new ( " bluetooth " ,  thread_func ,  u ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Failed to create IO thread " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > sink )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_set_asyncmsgq ( u - > sink ,  u - > thread_mq . inq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_set_rtpoll ( u - > sink ,  u - > rtpoll ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-02 21:46:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* If we are in the headset role, the sink should not become default
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  unless  there  is  no  other  sound  device  available .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG  | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-02 21:46:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            u - > sink - > priority  =  1500 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sink_put ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > sink - > set_volume ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > sink - > set_volume ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > source )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_source_set_asyncmsgq ( u - > source ,  u - > thread_mq . inq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_source_set_rtpoll ( u - > source ,  u - > rtpoll ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-02 21:46:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* If we are in the headset role or the device is an a2dp source,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  the  source  should  not  become  default  unless  there  is  no  other 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  sound  device  available .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_AG  | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_AG  | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-02 21:46:04 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            u - > source - > priority  =  1500 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_source_put ( u - > source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > source - > set_volume ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > source - > set_volume ( u - > source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-31 13:59:40 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > sink  | |  u - > source ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > a2dp_codec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_proplist_sets ( u - > card - > proplist ,  PA_PROP_BLUETOOTH_CODEC ,  u - > a2dp_codec - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  stop_thread ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-31 13:59:40 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > sink  | |  u - > source ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_unset ( u - > card - > proplist ,  PA_PROP_BLUETOOTH_CODEC ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > sink ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_unlink ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > source ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_source_unlink ( u - > source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > thread )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_asyncmsgq_send ( u - > thread_mq . inq ,  NULL ,  PA_MESSAGE_SHUTDOWN ,  NULL ,  0 ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_thread_free ( u - > thread ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > thread  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > rtpoll_item )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_rtpoll_item_free ( u - > rtpoll_item ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > rtpoll_item  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > rtpoll )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_rtpoll_free ( u - > rtpoll ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > rtpoll  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-03-24 17:17:03 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_thread_mq_done ( & u - > thread_mq ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > transport )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        transport_release ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > transport  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > sink )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_unref ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > sink  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > source )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_source_unref ( u - > source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > source  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > read_smoother )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_smoother_free ( u - > read_smoother ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > read_smoother  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK  | |  u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > encoder_info )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > a2dp_codec - > deinit ( u - > encoder_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > encoder_info  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > decoder_info )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > a2dp_codec - > deinit ( u - > decoder_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > decoder_info  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > a2dp_codec  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  pa_available_t  get_port_availability ( struct  userdata  * u ,  pa_direction_t  direction )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_available_t  result  =  PA_AVAILABLE_NO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    unsigned  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > device ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( i  =  0 ;  i  <  PA_BLUETOOTH_PROFILE_COUNT ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_bluetooth_transport  * transport ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! ( get_profile_direction ( i )  &  direction ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! ( transport  =  u - > device - > transports [ i ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        switch ( transport - > state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_TRANSPORT_STATE_IDLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( result  = =  PA_AVAILABLE_NO ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    result  =  PA_AVAILABLE_UNKNOWN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PA_BLUETOOTH_TRANSPORT_STATE_PLAYING : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  PA_AVAILABLE_YES ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  pa_available_t  transport_state_to_availability ( pa_bluetooth_transport_state_t  state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  PA_AVAILABLE_NO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_TRANSPORT_STATE_PLAYING : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  PA_AVAILABLE_YES ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  PA_AVAILABLE_UNKNOWN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  create_card_ports ( struct  userdata  * u ,  pa_hashmap  * ports )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port  * port ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data  port_data ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_device_port_type_t  input_type ,  output_type ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    const  char  * name_prefix ,  * input_description ,  * output_description ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ports ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > device ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    name_prefix  =  " unknown " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    input_description  =  _ ( " Bluetooth Input " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    output_description  =  _ ( " Bluetooth Output " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    input_type  =  output_type  =  PA_DEVICE_PORT_TYPE_BLUETOOTH ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( form_factor_from_class ( u - > device - > class_of_device ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_HEADSET : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name_prefix  =  " headset " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            input_description  =  output_description  =  _ ( " Headset " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            input_type  =  output_type  =  PA_DEVICE_PORT_TYPE_HEADSET ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_HANDSFREE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name_prefix  =  " handsfree " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            input_description  =  output_description  =  _ ( " Handsfree " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            input_type  =  output_type  =  PA_DEVICE_PORT_TYPE_HANDSFREE ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_MICROPHONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name_prefix  =  " microphone " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            input_description  =  _ ( " Microphone " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            output_description  =  _ ( " Bluetooth Output " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            input_type  =  PA_DEVICE_PORT_TYPE_MIC ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_SPEAKER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name_prefix  =  " speaker " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            input_description  =  _ ( " Bluetooth Input " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            output_description  =  _ ( " Speaker " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            output_type  =  PA_DEVICE_PORT_TYPE_SPEAKER ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_HEADPHONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name_prefix  =  " headphone " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            input_description  =  _ ( " Bluetooth Input " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            output_description  =  _ ( " Headphone " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            output_type  =  PA_DEVICE_PORT_TYPE_HEADPHONES ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_PORTABLE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name_prefix  =  " portable " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            input_description  =  output_description  =  _ ( " Portable " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            input_type  =  output_type  =  PA_DEVICE_PORT_TYPE_PORTABLE ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_CAR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name_prefix  =  " car " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            input_description  =  output_description  =  _ ( " Car " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            input_type  =  output_type  =  PA_DEVICE_PORT_TYPE_CAR ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_HIFI : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name_prefix  =  " hifi " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            input_description  =  output_description  =  _ ( " HiFi " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            input_type  =  output_type  =  PA_DEVICE_PORT_TYPE_HIFI ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_PHONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name_prefix  =  " phone " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            input_description  =  output_description  =  _ ( " Phone " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            input_type  =  output_type  =  PA_DEVICE_PORT_TYPE_PHONE ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_BLUETOOTH_FORM_FACTOR_UNKNOWN : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > output_port_name  =  pa_sprintf_malloc ( " %s-output " ,  name_prefix ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_init ( & port_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_name ( & port_data ,  u - > output_port_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_description ( & port_data ,  output_description ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_direction ( & port_data ,  PA_DIRECTION_OUTPUT ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_type ( & port_data ,  output_type ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_available ( & port_data ,  get_port_availability ( u ,  PA_DIRECTION_OUTPUT ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( port  =  pa_device_port_new ( u - > core ,  & port_data ,  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( pa_hashmap_put ( ports ,  port - > name ,  port )  > =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_done ( & port_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > input_port_name  =  pa_sprintf_malloc ( " %s-input " ,  name_prefix ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_init ( & port_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_name ( & port_data ,  u - > input_port_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_description ( & port_data ,  input_description ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_direction ( & port_data ,  PA_DIRECTION_INPUT ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-14 20:04:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_type ( & port_data ,  input_type ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_set_available ( & port_data ,  get_port_availability ( u ,  PA_DIRECTION_INPUT ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( port  =  pa_device_port_new ( u - > core ,  & port_data ,  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( pa_hashmap_put ( ports ,  port - > name ,  port )  > =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_new_data_done ( & port_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  pa_card_profile  * create_card_profile ( struct  userdata  * u ,  pa_bluetooth_profile_t  profile ,  pa_hashmap  * ports )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_device_port  * input_port ,  * output_port ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    const  char  * name ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_card_profile  * cp  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_profile_t  * p ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > input_port_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > output_port_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( input_port  =  pa_hashmap_get ( ports ,  u - > input_port_name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( output_port  =  pa_hashmap_get ( ports ,  u - > output_port_name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    name  =  pa_bluetooth_profile_to_string ( profile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( profile )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  PA_BLUETOOTH_PROFILE_A2DP_SINK : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp  =  pa_card_profile_new ( name ,  _ ( " High Fidelity Playback (A2DP Sink) " ) ,  sizeof ( pa_bluetooth_profile_t ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 13:29:42 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp - > priority  =  40 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp - > n_sinks  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > n_sources  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_sink_channels  =  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_source_channels  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( output_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p  =  PA_CARD_PROFILE_DATA ( cp ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    case  PA_BLUETOOTH_PROFILE_A2DP_SOURCE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp  =  pa_card_profile_new ( name ,  _ ( " High Fidelity Capture (A2DP Source) " ) ,  sizeof ( pa_bluetooth_profile_t ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 13:29:42 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp - > priority  =  20 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp - > n_sinks  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > n_sources  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_sink_channels  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_source_channels  =  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( input_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p  =  PA_CARD_PROFILE_DATA ( cp ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    case  PA_BLUETOOTH_PROFILE_HSP_HS : 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp  =  pa_card_profile_new ( name ,  _ ( " Headset Head Unit (HSP) " ) ,  sizeof ( pa_bluetooth_profile_t ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp - > priority  =  30 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > n_sinks  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > n_sources  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_sink_channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_source_channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( input_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( output_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p  =  PA_CARD_PROFILE_DATA ( cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    case  PA_BLUETOOTH_PROFILE_HSP_AG : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp  =  pa_card_profile_new ( name ,  _ ( " Headset Audio Gateway (HSP) " ) ,  sizeof ( pa_bluetooth_profile_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > priority  =  10 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > n_sinks  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > n_sources  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_sink_channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_source_channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( input_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( output_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p  =  PA_CARD_PROFILE_DATA ( cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    case  PA_BLUETOOTH_PROFILE_HFP_HF : 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								         cp  =  pa_card_profile_new ( name ,  _ ( " Handsfree Head Unit (HFP) " ) ,  sizeof ( pa_bluetooth_profile_t ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 13:29:42 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp - > priority  =  30 ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp - > n_sinks  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > n_sources  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_sink_channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_source_channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( input_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( output_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p  =  PA_CARD_PROFILE_DATA ( cp ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    case  PA_BLUETOOTH_PROFILE_HFP_AG : 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp  =  pa_card_profile_new ( name ,  _ ( " Handsfree Audio Gateway (HFP) " ) ,  sizeof ( pa_bluetooth_profile_t ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 13:29:42 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp - > priority  =  10 ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp - > n_sinks  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > n_sources  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_sink_channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > max_source_channels  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( input_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( output_port - > profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        p  =  PA_CARD_PROFILE_DATA ( cp ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    case  PA_BLUETOOTH_PROFILE_OFF : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert_not_reached ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-11 12:47:46 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    * p  =  profile ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > device - > transports [ * p ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > available  =  transport_state_to_availability ( u - > device - > transports [ * p ] - > state ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cp - > available  =  PA_AVAILABLE_NO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  cp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:50 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  set_profile_cb ( pa_card  * c ,  pa_card_profile  * new_profile )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_profile_t  * p ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( c ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( new_profile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  c - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p  =  PA_CARD_PROFILE_DATA ( new_profile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( * p  ! =  PA_BLUETOOTH_PROFILE_OFF )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        const  pa_bluetooth_device  * d  =  u - > device ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! d - > transports [ * p ]  | |  d - > transports [ * p ] - > state  < =  PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_warn ( " Refused to switch profile to %s: Not connected " ,  new_profile - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_IO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    stop_thread ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > profile  =  * p ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  ! =  PA_BLUETOOTH_PROFILE_OFF ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( init_profile ( u )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > sink  | |  u - > source ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( start_thread ( u )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								off : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    stop_thread ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-11-20 15:42:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert_se ( pa_card_set_profile ( u - > card ,  pa_hashmap_get ( u - > card - > profiles ,  " off " ) ,  false )  > =  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:50 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  - PA_ERR_IO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  uuid_to_profile ( const  char  * uuid ,  pa_bluetooth_profile_t  * _r )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_streq ( uuid ,  PA_BLUETOOTH_UUID_A2DP_SINK ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * _r  =  PA_BLUETOOTH_PROFILE_A2DP_SINK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else  if  ( pa_streq ( uuid ,  PA_BLUETOOTH_UUID_A2DP_SOURCE ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * _r  =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else  if  ( pa_bluetooth_uuid_is_hsp_hs ( uuid ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        * _r  =  PA_BLUETOOTH_PROFILE_HSP_HS ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-18 08:48:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else  if  ( pa_streq ( uuid ,  PA_BLUETOOTH_UUID_HFP_HF ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * _r  =  PA_BLUETOOTH_PROFILE_HFP_HF ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else  if  ( pa_streq ( uuid ,  PA_BLUETOOTH_UUID_HSP_AG ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * _r  =  PA_BLUETOOTH_PROFILE_HSP_AG ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else  if  ( pa_streq ( uuid ,  PA_BLUETOOTH_UUID_HFP_AG ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-20 10:39:30 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        * _r  =  PA_BLUETOOTH_PROFILE_HFP_AG ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  add_card ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  pa_bluetooth_device  * d ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_card_new_data  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    char  * alias ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_form_factor_t  ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_card_profile  * cp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_profile_t  * p ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    const  char  * uuid ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * state ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > device ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    d  =  u - > device ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_card_new_data_init ( & data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . driver  =  __FILE__ ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . module  =  u - > module ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-10-11 17:27:06 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    alias  =  pa_utf8_filter ( d - > alias ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( data . proplist ,  PA_PROP_DEVICE_DESCRIPTION ,  alias ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_xfree ( alias ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( data . proplist ,  PA_PROP_DEVICE_STRING ,  d - > address ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( data . proplist ,  PA_PROP_DEVICE_API ,  " bluez " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( data . proplist ,  PA_PROP_DEVICE_CLASS ,  " sound " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( data . proplist ,  PA_PROP_DEVICE_BUS ,  " bluetooth " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ( ff  =  form_factor_from_class ( d - > class_of_device ) )  ! =  PA_BLUETOOTH_FORM_FACTOR_UNKNOWN ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_sets ( data . proplist ,  PA_PROP_DEVICE_FORM_FACTOR ,  form_factor_to_string ( ff ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( data . proplist ,  " bluez.path " ,  d - > path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_setf ( data . proplist ,  " bluez.class " ,  " 0x%06x " ,  d - > class_of_device ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( data . proplist ,  " bluez.alias " ,  d - > alias ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . name  =  pa_sprintf_malloc ( " bluez_card.%s " ,  d - > address ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    data . namereg_fail  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    create_card_ports ( u ,  data . ports ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    PA_HASHMAP_FOREACH ( uuid ,  d - > uuids ,  state )  { 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_bluetooth_profile_t  profile ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( uuid_to_profile ( uuid ,  & profile )  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( pa_hashmap_get ( data . profiles ,  pa_bluetooth_profile_to_string ( profile ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluetooth: don't create the HSP/HFP profile twice
create_card_profile() used to get called separately for HSP and HFP,
so if a headset supports both profiles, a profile named
"headset_head_unit" would get created twice. The second instance would
get immediately freed, so that wasn't a particularly serious problem.
However, I think it makes more sense to create the profile only once.
This patch makes things so that before a profile is created, we check
what name that profile would have, and if a profile with that name
already exists, we don't create the profile.
A couple of Yocto releases (jethro and krogoth) have non-upstream
patches that suffer from this double creation. The patches add
associations between profiles and ports, and those associations use
the profile name as the key. When the second profile gets freed, the
associations between the profile and its ports get removed, and since
the profile name is used as the key, this erroneously affects the
first profile too. Crashing ensues.
BugLink: https://bugzilla.yoctoproject.org/show_bug.cgi?id=10018
											 
										 
										
											2016-07-31 02:44:55 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        cp  =  create_card_profile ( u ,  profile ,  data . ports ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_hashmap_put ( data . profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ! pa_hashmap_isempty ( data . profiles ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    cp  =  pa_card_profile_new ( " off " ,  _ ( " Off " ) ,  sizeof ( pa_bluetooth_profile_t ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    cp - > available  =  PA_AVAILABLE_YES ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p  =  PA_CARD_PROFILE_DATA ( cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    * p  =  PA_BLUETOOTH_PROFILE_OFF ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_hashmap_put ( data . profiles ,  cp - > name ,  cp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > card  =  pa_card_new ( u - > core ,  & data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_card_new_data_done ( & data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > card )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Failed to allocate card. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > card - > userdata  =  u ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:50 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > card - > set_profile  =  set_profile_cb ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												card: move profile selection after pa_card_new()
I want module-alsa-card to set the availability of unavailable
profiles before the initial card profile gets selected, so that the
selection logic can use correct availability information.
module-alsa-card initializes the jack state after calling
pa_card_new(), however, and the profile selection happens in
pa_card_new(). This patch solves that by moving parts of pa_card_new()
to pa_card_choose_initial_profile() and pa_card_put().
pa_card_choose_initial_profile() applies the profile selection policy,
so module-alsa-card can first call pa_card_new(), then initialize the
jack state, and then call pa_card_choose_initial_profile(). After that
module-alsa-card can still override the profile selection policy, in
case module-alsa-card was loaded with the "profile" argument. Finally,
pa_card_put() finalizes the card creation.
An alternative solution would have been to move the jack
initialization to happen before pa_card_new() and use pa_card_new_data
instead of pa_card in the jack initialization code, but I disliked
that idea (I want to get rid of the "new data" pattern eventually).
The order in which the initial profile policy is applied is reversed
in this patch. Previously the first one to set it won, now the last
one to set it wins. I think this is better, because if you have N
parties that want to set the profile, we avoid checking N times
whether someone else has already set the profile.
											 
										 
										
											2015-10-23 12:59:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_card_choose_initial_profile ( u - > card ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_card_put ( u - > card ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    p  =  PA_CARD_PROFILE_DATA ( u - > card - > active_profile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > profile  =  * p ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  handle_transport_state_change ( struct  userdata  * u ,  struct  pa_bluetooth_transport  * t )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  acquire  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  release  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_card_profile  * cp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port  * port ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-19 10:24:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_available_t  oldavail ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( t ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:12 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert_se ( cp  =  pa_hashmap_get ( u - > card - > profiles ,  pa_bluetooth_profile_to_string ( t - > profile ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-12-19 10:24:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    oldavail  =  cp - > available ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  If  codec  switching  is  in  progress ,  transport  state  change  should  not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  make  profile  unavailable . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! t - > device - > codec_switching_in_progress ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_card_profile_set_available ( cp ,  transport_state_to_availability ( t - > state ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Update port availability */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( port  =  pa_hashmap_get ( u - > card - > ports ,  u - > output_port_name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_set_available ( port ,  get_port_availability ( u ,  PA_DIRECTION_OUTPUT ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( port  =  pa_hashmap_get ( u - > card - > ports ,  u - > input_port_name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_device_port_set_available ( port ,  get_port_availability ( u ,  PA_DIRECTION_INPUT ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Acquire or release transport as needed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    acquire  =  ( t - > state  = =  PA_BLUETOOTH_TRANSPORT_STATE_PLAYING  & &  u - > profile  = =  t - > profile ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-12-19 10:24:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    release  =  ( oldavail  ! =  PA_AVAILABLE_NO  & &  t - > state  ! =  PA_BLUETOOTH_TRANSPORT_STATE_PLAYING  & &  u - > profile  = =  t - > profile ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( acquire  & &  transport_acquire ( u ,  true )  > =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > source )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " Resuming source %s because its transport state changed to playing " ,  u - > source - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-29 19:47:16 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* When the ofono backend resumes source or sink when in the audio gateway role, the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  state  of  source  or  sink  may  already  be  RUNNING  before  the  transport  is  acquired  via 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  hf_audio_agent_new_connection ( ) ,  so  the  pa_source_suspend ( )  call  will  not  lead  to  a 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-17 09:57:20 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             *  state  change  message .  In  this  case  we  explicitly  need  to  signal  the  I / O  thread  to 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             *  set  up  the  stream .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( PA_SOURCE_IS_OPENED ( u - > source - > state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_asyncmsgq_send ( u - > source - > asyncmsgq ,  PA_MSGOBJECT ( u - > source ) ,  PA_SOURCE_MESSAGE_SETUP_STREAM ,  NULL ,  0 ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-29 19:47:16 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* We remove the IDLE suspend cause, because otherwise
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  module - loopback  doesn ' t  uncork  its  streams .  FIXME :  Messing  with 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  the  IDLE  suspend  cause  here  is  wrong ,  the  correct  way  to  handle 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  this  would  probably  be  to  uncork  the  loopback  streams  not  only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  when  the  other  end  is  unsuspended ,  but  also  when  the  other  end ' s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  suspend  cause  changes  to  IDLE  only  ( currently  there ' s  no 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  notification  mechanism  for  suspend  cause  changes ,  though ) .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            pa_source_suspend ( u - > source ,  false ,  PA_SUSPEND_IDLE | PA_SUSPEND_USER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > sink )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " Resuming sink %s because its transport state changed to playing " ,  u - > sink - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-29 19:47:16 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* Same comment as above */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( PA_SINK_IS_OPENED ( u - > sink - > state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_asyncmsgq_send ( u - > sink - > asyncmsgq ,  PA_MSGOBJECT ( u - > sink ) ,  PA_SINK_MESSAGE_SETUP_STREAM ,  NULL ,  0 ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-29 19:47:16 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* FIXME: See the previous comment. */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            pa_sink_suspend ( u - > sink ,  false ,  PA_SUSPEND_IDLE | PA_SUSPEND_USER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( release  & &  u - > transport_acquired )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* FIXME: this release is racy, since the audio stream might have
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  been  set  up  again  in  the  meantime  ( but  not  processed  yet  by  PA ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  BlueZ  should  probably  release  the  transport  automatically ,  and  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  that  case  we  would  just  mark  the  transport  as  released  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Remote side closed the stream so we consider it PA_SUSPEND_USER */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > source )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " Suspending source %s because the remote end closed the stream " ,  u - > source - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_source_suspend ( u - > source ,  true ,  PA_SUSPEND_USER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > sink )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " Suspending sink %s because the remote end closed the stream " ,  u - > sink - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_sink_suspend ( u - > sink ,  true ,  PA_SUSPEND_USER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:42 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  pa_hook_result_t  device_connection_changed_cb ( pa_bluetooth_discovery  * y ,  const  pa_bluetooth_device  * d ,  struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( d ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( d  ! =  u - > device  | |  pa_bluetooth_device_any_transport_connected ( d )  | |  d - > codec_switching_in_progress ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:42 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_debug ( " Unloading module for device %s " ,  d - > path ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-06-25 21:59:36 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_module_unload ( u - > module ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:42 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  pa_hook_result_t  transport_state_changed_cb ( pa_bluetooth_discovery  * y ,  pa_bluetooth_transport  * t ,  struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( t  = =  u - > transport  & &  t - > state  < =  PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-11-20 15:42:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_assert_se ( pa_card_set_profile ( u - > card ,  pa_hashmap_get ( u - > card - > profiles ,  " off " ) ,  false )  > =  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-06-13 19:02:37 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( t - > device  = =  u - > device ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        handle_transport_state_change ( u ,  t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  pa_hook_result_t  transport_speaker_volume_changed_cb ( pa_bluetooth_discovery  * y ,  pa_bluetooth_transport  * t ,  struct  userdata  * u )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_volume_t  volume ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_cvolume  v ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( t  ! =  u - > transport ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    volume  =  t - > speaker_volume ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_cvolume_set ( & v ,  u - > encoder_sample_spec . channels ,  volume ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( t - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS  | |  t - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-07 13:44:54 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sink_volume_changed ( u - > sink ,  & v ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_set_volume ( u - > sink ,  & v ,  true ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  pa_hook_result_t  transport_microphone_volume_changed_cb ( pa_bluetooth_discovery  * y ,  pa_bluetooth_transport  * t ,  struct  userdata  * u )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_volume_t  volume ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_cvolume  v ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( t ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( t  ! =  u - > transport ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    volume  =  t - > microphone_volume ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_cvolume_set ( & v ,  u - > decoder_sample_spec . channels ,  volume ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-07 13:44:54 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-29 21:32:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( t - > profile  = =  PA_BLUETOOTH_PROFILE_HSP_HS  | |  t - > profile  = =  PA_BLUETOOTH_PROFILE_HFP_HF ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-07 13:44:54 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_source_volume_changed ( u - > source ,  & v ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_source_set_volume ( u - > source ,  & v ,  true ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  char *  make_message_handler_path ( const  char  * name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  pa_sprintf_malloc ( " /card/%s/bluez " ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  switch_codec_cb_handler ( bool  success ,  pa_bluetooth_profile_t  profile ,  void  * userdata ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u  =  ( struct  userdata  * )  userdata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! success ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > profile  =  profile ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( init_profile ( u )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_info ( " Failed to initialise profile after codec switching " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > sink  | |  u - > source ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( start_thread ( u )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " Failed to start thread after codec switching " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_info ( " Codec successfully switched to %s with profile: %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > a2dp_codec - > name ,  pa_bluetooth_profile_to_string ( u - > profile ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								off : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( pa_card_set_profile ( u - > card ,  pa_hashmap_get ( u - > card - > profiles ,  " off " ) ,  false )  > =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  char  * list_codecs ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  pa_a2dp_codec_capabilities  * a2dp_capabilities ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  pa_a2dp_codec_id  * key ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_hashmap  * a2dp_endpoints ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_message_params  * param ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    unsigned  int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  is_a2dp_sink ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * state ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    is_a2dp_sink  =  u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    a2dp_endpoints  =  is_a2dp_sink  ?  u - > device - > a2dp_sink_endpoints  :  u - > device - > a2dp_source_endpoints ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    param  =  pa_message_params_new ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_message_params_begin_list ( param ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    PA_HASHMAP_FOREACH_KV ( key ,  a2dp_capabilities ,  a2dp_endpoints ,  state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( i  =  0 ;  i  <  pa_bluetooth_a2dp_codec_count ( ) ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            const  pa_a2dp_codec  * a2dp_codec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            a2dp_codec  =  pa_bluetooth_a2dp_codec_iter ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 19:38:48 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( memcmp ( key ,  & a2dp_codec - > id ,  sizeof ( pa_a2dp_codec_id ) )  = =  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 23:20:07 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  ( a2dp_codec - > can_be_supported ( is_a2dp_sink ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 19:38:48 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    pa_message_params_begin_list ( param ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 19:38:48 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    pa_message_params_write_string ( param ,  a2dp_codec - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    pa_message_params_write_string ( param ,  a2dp_codec - > description ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 19:38:48 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    pa_message_params_end_list ( param ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_message_params_end_list ( param ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  pa_message_params_to_string_free ( param ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  bluez5_device_message_handler ( const  char  * object_path ,  const  char  * message ,  char  * message_parameters ,  char  * * response ,  void  * userdata )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    char  * message_handler_path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_hashmap  * capabilities_hashmap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_profile_t  profile ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  pa_a2dp_codec  * codec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  char  * codec_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  is_a2dp_sink ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * state  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u  =  ( struct  userdata  * ) userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( response ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    message_handler_path  =  make_message_handler_path ( u - > card - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! object_path  | |  ! pa_streq ( object_path ,  message_handler_path ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_xfree ( message_handler_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - PA_ERR_NOENTITY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_xfree ( message_handler_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > device - > codec_switching_in_progress )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_info ( " Codec switching operation already in progress " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > device - > adapter - > application_registered )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_info ( " Old BlueZ version was detected, only SBC codec supported. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - PA_ERR_NOTIMPLEMENTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_OFF )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_info ( " Bluetooth profile is off. Message cannot be handled. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  if  ( u - > profile  ! =  PA_BLUETOOTH_PROFILE_A2DP_SINK  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > profile  ! =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_log_info ( " Listing or switching codecs only allowed for A2DP sink or source " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_streq ( message ,  " switch-codec " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        err  =  pa_message_params_read_string ( message_parameters ,  & codec_name ,  & state ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( err  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > a2dp_codec  & &  pa_streq ( codec_name ,  u - > a2dp_codec - > name ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " Requested codec is currently selected codec " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        codec  =  pa_bluetooth_get_a2dp_codec ( codec_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( codec  = =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " Invalid codec %s specified for switching " ,  codec_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 23:20:07 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        is_a2dp_sink  =  u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 22:47:20 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! codec - > can_be_supported ( is_a2dp_sink ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 19:38:48 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            pa_log_info ( " Codec not found on system " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_NOTSUPPORTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  We  need  to  check  if  we  have  valid  sink  or  source  endpoints  which 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  were  registered  during  the  negotiation  process .  If  we  do ,  then  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  check  if  the  specified  codec  is  present  among  the  codecs  supported 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  by  the  remote  endpoint . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( pa_hashmap_isempty ( is_a2dp_sink  ?  u - > device - > a2dp_sink_endpoints  :  u - > device - > a2dp_source_endpoints ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " No device endpoints found. Codec switching not allowed. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        capabilities_hashmap  =  pa_hashmap_get ( is_a2dp_sink  ?  u - > device - > a2dp_sink_endpoints  :  u - > device - > a2dp_source_endpoints ,  & codec - > id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! capabilities_hashmap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " No remote endpoint found for %s codec. Codec not supported by remote endpoint. " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    codec - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_info ( " Initiating codec switching process to %s " ,  codec - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  The  current  profile  needs  to  be  saved  before  we  stop  the  thread  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  initiate  the  switch .  u - > profile  will  be  changed  in  other  places 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  depending  on  the  state  of  transport  and  port  availability . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        profile  =  u - > profile ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stop_thread ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-24 14:10:16 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! pa_bluetooth_device_switch_codec ( u - > device ,  profile ,  capabilities_hashmap ,  codec ,  switch_codec_cb_handler ,  userdata ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                & &  ! u - > device - > codec_switching_in_progress ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  profile_off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  PA_OK ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  if  ( pa_streq ( message ,  " list-codecs " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * response  =  list_codecs ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 11:48:11 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  PA_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  if  ( pa_streq ( message ,  " get-codec " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_message_params  * param ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        param  =  pa_message_params_new ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > a2dp_codec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_message_params_write_string ( param ,  u - > a2dp_codec - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_message_params_write_string ( param ,  " none " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * response  =  pa_message_params_to_string_free ( param ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  PA_OK ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  - PA_ERR_NOTIMPLEMENTED ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								profile_off : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( pa_card_set_profile ( u - > card ,  pa_hashmap_get ( u - > card - > profiles ,  " off " ) ,  false )  > =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  - PA_ERR_IO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  device_process_msg ( pa_msgobject  * obj ,  int  code ,  void  * data ,  int64_t  offset ,  pa_memchunk  * chunk )  { 
							 
						 
					
						
							
								
									
										
										
										
											2014-02-04 19:04:04 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  bluetooth_msg  * m  =  BLUETOOTH_MSG ( obj ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-09-17 13:04:59 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  userdata  * u  =  m - > card - > userdata ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( code )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  BLUETOOTH_MESSAGE_IO_THREAD_FAILED : 
							 
						 
					
						
							
								
									
										
										
										
											2014-02-04 19:04:04 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( m - > card - > module - > unload_requested ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " Switching the profile to off due to IO thread failure. " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-02-04 19:04:04 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            pa_assert_se ( pa_card_set_profile ( m - > card ,  pa_hashmap_get ( m - > card - > profiles ,  " off " ) ,  false )  > =  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-02-04 19:04:05 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        case  BLUETOOTH_MESSAGE_STREAM_FD_HUP : 
							 
						 
					
						
							
								
									
										
										
										
											2016-04-15 17:37:22 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( u - > transport - > state  >  PA_BLUETOOTH_TRANSPORT_STATE_IDLE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_bluetooth_transport_set_state ( u - > transport ,  PA_BLUETOOTH_TRANSPORT_STATE_IDLE ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-02-04 19:04:05 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-07-22 10:47:07 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        case  BLUETOOTH_MESSAGE_SET_TRANSPORT_PLAYING : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* transport_acquired needs to be checked here, because a message could have been
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  pending  when  the  profile  was  switched .  If  the  new  transport  has  been  acquired 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  correctly ,  the  call  below  will  have  no  effect  because  the  transport  state  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  already  PLAYING .  If  transport_acquire ( )  failed  for  the  new  profile ,  the  transport 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  state  should  not  be  changed .  If  the  transport  has  been  released  for  other  reasons 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  ( I / O  thread  shutdown ) ,  transport_acquired  will  also  be  false .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( u - > transport_acquired ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_bluetooth_transport_set_state ( u - > transport ,  PA_BLUETOOTH_TRANSPORT_STATE_PLAYING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								int  pa__init ( pa_module *  m )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  char  * path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_modargs  * ma ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-04 20:32:15 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  autodetect_mtu ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    char  * message_handler_path ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 09:10:02 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    uint32_t  output_rate_refresh_interval_ms ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    m - > userdata  =  u  =  pa_xnew0 ( struct  userdata ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > module  =  m ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > core  =  m - > core ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-21 18:41:25 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > message_handler_registered  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ( ma  =  pa_modargs_new ( m - > argument ,  valid_modargs ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Failed to parse module arguments " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-16 07:16:31 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        goto  fail_free_modargs ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ( path  =  pa_modargs_get_value ( ma ,  " path " ,  NULL ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Failed to get device path from module arguments " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-16 07:16:31 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        goto  fail_free_modargs ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:56 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ( u - > discovery  =  pa_shared_get ( u - > core ,  " bluetooth-discovery " ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_bluetooth_discovery_ref ( u - > discovery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " module-bluez5-discover doesn't seem to be loaded, refusing to load module-bluez5-device " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-16 07:16:31 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        goto  fail_free_modargs ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:56 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ( u - > device  =  pa_bluetooth_discovery_get_device_by_path ( u - > discovery ,  path ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " %s is unknown " ,  path ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-16 07:16:31 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        goto  fail_free_modargs ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-09-13 09:22:27 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    autodetect_mtu  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-04 20:32:15 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( pa_modargs_get_value_boolean ( ma ,  " autodetect_mtu " ,  & autodetect_mtu )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Invalid boolean value for autodetect_mtu parameter " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail_free_modargs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > device - > autodetect_mtu  =  autodetect_mtu ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 09:10:02 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    output_rate_refresh_interval_ms  =  DEFAULT_OUTPUT_RATE_REFRESH_INTERVAL_MS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_modargs_get_value_u32 ( ma ,  " output_rate_refresh_interval_ms " ,  & output_rate_refresh_interval_ms )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Invalid value for output_rate_refresh_interval parameter. " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:51:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        goto  fail_free_modargs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > device - > output_rate_refresh_interval_ms  =  output_rate_refresh_interval_ms ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_modargs_free ( ma ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:42 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > device_connection_changed_slot  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_connect ( pa_bluetooth_discovery_hook ( u - > discovery ,  PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        PA_HOOK_NORMAL ,  ( pa_hook_cb_t )  device_connection_changed_cb ,  u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > transport_state_changed_slot  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_connect ( pa_bluetooth_discovery_hook ( u - > discovery ,  PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        PA_HOOK_NORMAL ,  ( pa_hook_cb_t )  transport_state_changed_cb ,  u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > transport_speaker_volume_changed_slot  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_connect ( pa_bluetooth_discovery_hook ( u - > discovery ,  PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_VOLUME_CHANGED ) ,  PA_HOOK_NORMAL ,  ( pa_hook_cb_t )  transport_speaker_volume_changed_cb ,  u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > transport_microphone_volume_changed_slot  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_connect ( pa_bluetooth_discovery_hook ( u - > discovery ,  PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_VOLUME_CHANGED ) ,  PA_HOOK_NORMAL ,  ( pa_hook_cb_t )  transport_microphone_volume_changed_cb ,  u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( add_card ( u )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! ( u - > msg  =  pa_msgobject_new ( bluetooth_msg ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > msg - > parent . process_msg  =  device_process_msg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > msg - > card  =  u - > card ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												bluez5-device: Correctly handle suspend/resume cyle for audio gateway role of ofono backend
When the ofono backend released a tranport during suspend of sink or source, the
transport state was not changed to IDLE. Therefore pa_bluetooth_transport_set_state()
would return immediately when trying to resume. Even though the transport was acquired
correctly, setup_stream() would never be called and the resume failed.
This patch sets the transport state to IDLE when the transport is released. On resume,
the first call to transport_acquire() will be done from the message handler of the
*_SET_STATE message when source or sink are set to RUNNING. This call will only request
the setup of the connection, so setup_stream() cannot be called.
When the transport changes the state to PLAYING in hf_audio_agent_new_connection(),
handle_transport_state_change() is called. Because the sink or source state is already
RUNNING, the pa_{source,sink}_suspend() call will not lead to a state change message
and the I/O thread must be signaled explicitely to setup the stream.
The first setup of the device would also fail, which was only visible when the profile
was restored after connecting the headset. When trying to restore the headset_head_unit
profile, the profile was shortly set to off, so the headset always returned to a2dp.
This patch allows a delayed setup for the headset_head_unit profile, so that the profile
can successfully be restored.
											 
										 
										
											2017-05-04 13:14:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > stream_setup_done  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > profile  ! =  PA_BLUETOOTH_PROFILE_OFF ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( init_profile ( u )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > sink  | |  u - > source ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( start_thread ( u )  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            goto  off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    message_handler_path  =  make_message_handler_path ( u - > card - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_message_handler_register ( m - > core ,  message_handler_path ,  " Bluez5 device message handler " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            bluez5_device_message_handler ,  ( void  * )  u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_log_info ( " Bluez5 device message handler registered at path: %s " ,  message_handler_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_xfree ( message_handler_path ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-21 18:41:25 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > message_handler_registered  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								off : 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    stop_thread ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-11-20 15:42:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert_se ( pa_card_set_profile ( u - > card ,  pa_hashmap_get ( u - > card - > profiles ,  " off " ) ,  false )  > =  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-16 07:16:31 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								fail_free_modargs : 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ma ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_modargs_free ( ma ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-08-16 07:16:31 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								fail : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa__done ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  pa__done ( pa_module  * m )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    char  * message_handler_path ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ( u  =  m - > userdata ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-21 18:41:25 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > message_handler_registered )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        message_handler_path  =  make_message_handler_path ( u - > card - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_message_handler_unregister ( m - > core ,  message_handler_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_xfree ( message_handler_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    stop_thread ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:42 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > device_connection_changed_slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_slot_free ( u - > device_connection_changed_slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > transport_state_changed_slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_slot_free ( u - > transport_state_changed_slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > transport_speaker_volume_changed_slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_slot_free ( u - > transport_speaker_volume_changed_slot ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 16:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > transport_microphone_volume_changed_slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_slot_free ( u - > transport_microphone_volume_changed_slot ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > encoder_buffer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_xfree ( u - > encoder_buffer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > decoder_buffer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_xfree ( u - > decoder_buffer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > msg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_xfree ( u - > msg ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > card ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_card_free ( u - > card ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > discovery ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_bluetooth_discovery_unref ( u - > discovery ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:44 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_xfree ( u - > output_port_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_xfree ( u - > input_port_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:41 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_xfree ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:40 -03:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:55 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  pa__get_n_used ( pa_module  * m )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  m - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ( u - > sink  ?  pa_sink_linked_by ( u - > sink )  :  0 )  +  ( u - > source  ?  pa_source_linked_by ( u - > source )  :  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}