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> 
 
							 
						 
					
						
							
								
									
										
										
										
											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> 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-01 22:35:26 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/json.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> 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# ifdef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/time-smoother_2.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/time-smoother.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											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> " 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 21:59:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    " avrcp_absolute_volume=<synchronize volume with peer, true by default> " 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 09:10:02 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								) ; 
							 
						 
					
						
							
								
									
										
										
										
											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 " , 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 21:59:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    " avrcp_absolute_volume " , 
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 14:26:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * device_battery_level_changed_slot ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:54 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * transport_state_changed_slot ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * transport_sink_volume_changed_slot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * transport_source_volume_changed_slot ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:42 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * sink_volume_changed_slot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_hook_slot  * source_volume_changed_slot ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# ifdef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_smoother_2  * read_smoother ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_smoother  * read_smoother ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_memchunk  write_memchunk ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    const  pa_bt_codec  * bt_codec ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * encoder_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sample_spec  encoder_sample_spec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * encoder_buffer ;                         /* Codec transfer buffer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  encoder_buffer_size ;                   /* Size of the buffer */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    size_t  encoder_buffer_used ;                   /* Used space in the buffer */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /*
 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 00:25:13 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  See  Bluetooth  Assigned  Numbers  for  Baseband 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  https : //www.bluetooth.com/specifications/assigned-numbers/baseband/
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:43 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  bool  bt_prepare_encoder_buffer ( struct  userdata  * u ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-25 23:41:36 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    size_t  encoded_size ,  reserved_size ,  encoded_frames ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > bt_codec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* If socket write MTU is less than encoded frame size, there could be
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  up  to  one  write  MTU  of  data  left  in  encoder  buffer  from  previous  round . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-25 23:41:36 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  Reserve  space  for  at  least  2  encoded  frames  to  cover  that . 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Note  for  A2DP  codecs  it  is  expected  that  size  of  encoded  frame  is  less 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  than  write  link  MTU .  Therefore  each  encoded  frame  is  sent  out  completely 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  and  there  is  no  used  space  in  encoder  buffer  before  next  encoder  call . 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-25 23:41:36 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  For  SCO  socket  all  writes  will  be  of  MTU  size  to  match  payload  length 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  of  HCI  packet .  Depending  on  selected  USB  Alternate  Setting  the  payload 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  length  of  HCI  packet  may  exceed  encoded  frame  size .  For  mSBC  frame  size 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  is  60  bytes ,  payload  length  of  HCI  packet  in  USB  Alts  3  is  72  byte , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  in  USB  Alts  5  it  is  144  bytes . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Reserve  space  for  up  to  1  +  MTU  /  ( encoded  frame  size )  encoded  frames 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  to  cover  that . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Note  for  current  linux  kernel  ( up  to  5.13 . x  at  least )  there  is  no  way  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  reliably  detect  socket  MTU  size .  For  now  we  just  set  SCO  socket  MTU  to  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  large  enough  to  cover  all  known  sizes  ( largest  is  USB  ALts  5  with  144  bytes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  and  adjust  SCO  write  size  to  be  equal  to  last  SCO  read  size .  This  makes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  write  size  less  or  equal  to  MTU  size .  Reserving  the  same  number  of  encoded 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  frames  to  cover  full  MTU  is  still  enough . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  See  also  https : //gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/254#note_779802
 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-25 23:41:36 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > bt_codec - > get_encoded_block_size ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        encoded_size  =  u - > bt_codec - > get_encoded_block_size ( u - > encoder_info ,  u - > write_block_size ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        encoded_size  =  u - > write_block_size ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-07-25 23:41:36 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    encoded_frames  =  u - > write_link_mtu  /  u - > write_block_size  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( encoded_frames  <  2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        encoded_frames  =  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    reserved_size  =  encoded_frames  *  encoded_size ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > encoder_buffer_size  <  reserved_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_buffer  =  pa_xrealloc ( u - > encoder_buffer ,  reserved_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_buffer_size  =  reserved_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > encoder_buffer_used  >  reserved_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > encoder_buffer_used  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Report if there is still not enough space for new block */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > encoder_buffer_size  <  u - > encoder_buffer_used  +  encoded_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  bt_write_buffer ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ssize_t  written  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > bt_codec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    written  =  u - > transport - > write ( u - > transport ,  u - > stream_fd ,  u - > encoder_buffer ,  u - > encoder_buffer_used ,  u - > write_link_mtu ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( written  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* calculate remainder */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_buffer_used  - =  written ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /* move any remainder back to start of u->encoder_buffer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > encoder_buffer_used ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            memmove ( u - > encoder_buffer ,  u - > encoder_buffer  +  written ,  u - > encoder_buffer_used ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  if  ( written  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Not enough data in encoder buffer */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Reset encoder sequence number and buffer positions */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > bt_codec - > reset ( u - > encoder_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_buffer_used  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  bt_process_render ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    const  uint8_t  * ptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  processed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  length ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > bt_codec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:29:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! bt_prepare_encoder_buffer ( u ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* First, render some data */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > write_memchunk . memblock ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_render_full ( u - > sink ,  u - > write_block_size ,  & u - > write_memchunk ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:29:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > write_memchunk . length  = =  u - > write_block_size ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:29:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ptr  =  ( const  uint8_t  * )  pa_memblock_acquire_chunk ( & u - > write_memchunk ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    length  =  u - > bt_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_used ,  u - > encoder_buffer_size  -  u - > encoder_buffer_used , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            & processed ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:29:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_memblock_release ( u - > write_memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( processed  ! =  u - > write_memchunk . length )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Encoding error " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* Encoder function of BT codec may provide empty buffer, in this case do
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  not  post  any  empty  buffer  via  BT  socket .  It  may  be  because  of  codec 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  internal  state ,  e . g .  encoder  is  waiting  for  more  samples  so  it  can 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  provide  encoded  data .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( PA_LIKELY ( length ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_buffer_used  + =  length ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ret  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > write_index  + =  ( uint64_t )  u - > write_memchunk . length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblock_unref ( u - > write_memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memchunk_reset ( & u - > write_memchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  bt_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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  ssize_t  bt_transport_read ( pa_bluetooth_transport  * t ,  int  fd ,  void  * buffer ,  size_t  size ,  pa_usec_t  * p_timestamp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ssize_t  received  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( t ) ; 
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        iov . iov_base  =  buffer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        iov . iov_len  =  size ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-04 08:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        received  =  recvmsg ( fd ,  & m ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( received  < =  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( received  <  0  & &  errno  = =  EINTR ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* Retry right away if we got interrupted */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            else  if  ( received  <  0  & &  errno  = =  EAGAIN ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* Hmm, apparently the socket was not readable, give up for now. */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            pa_log_error ( " Failed to read data from socket: %s " ,  received  <  0  ?  pa_cstrerror ( errno )  :  " EOF " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_assert ( ( size_t )  received  < =  size ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-17 16:31:13 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /* allow write side to find out size of last read packet */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        t - > last_read_size  =  received ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( p_timestamp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* TODO: get timestamp from rtp */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-04 08:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03: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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    * p_timestamp  =  pa_timeval_load ( tv ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    found_tstamp  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2019-05-04 08:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ! found_tstamp )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                PA_ONCE_BEGIN  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    pa_log_warn ( " Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data! " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                }  PA_ONCE_END ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                * p_timestamp  =  pa_rtclock_now ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  received ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from IO thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Read incoming data, decode it and post result (if any) to source output.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Returns  number  of  bytes  posted  to  source  output .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  bt_process_push ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_usec_t  tstamp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  * ptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ssize_t  received ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  processed  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > read_smoother ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > bt_codec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bt_prepare_decoder_buffer ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-01-27 01:14:39 +11:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    received  =  bt_transport_read ( u - > transport ,  u - > stream_fd ,  u - > decoder_buffer ,  u - > decoder_buffer_size ,  & tstamp ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( received  < =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  received ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_memchunk  memchunk ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memchunk . memblock  =  pa_memblock_new ( u - > core - > mempool ,  u - > read_block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memchunk . index  =  memchunk . length  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ptr  =  pa_memblock_acquire ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memchunk . length  =  pa_memblock_get_length ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    memchunk . length  =  u - > bt_codec - > decode_buffer ( u - > decoder_info ,  u - > decoder_buffer ,  received ,  ptr ,  memchunk . length ,  & processed ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblock_release ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( processed  ! =  ( size_t )  received )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_error ( " Decoding error " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > read_index  + =  ( uint64_t )  memchunk . length ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# ifdef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_smoother_2_resume ( u - > read_smoother ,  tstamp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_smoother_2_put ( u - > read_smoother ,  tstamp ,  u - > read_index ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_smoother_put ( u - > read_smoother ,  tstamp ,  pa_bytes_to_usec ( u - > read_index ,  & u - > decoder_sample_spec ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_smoother_resume ( u - > read_smoother ,  tstamp ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Decoding of 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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* report decoded size */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    received  =  memchunk . length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_memblock_unref ( memchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  received ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# ifdef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_smoother_2_free ( u - > read_smoother ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_smoother_free ( u - > read_smoother ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        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 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > bt_codec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-13 12:49:28 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > encoder_info )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > write_block_size  =  u - > bt_codec - > get_write_block_size ( u - > encoder_info ,  u - > write_link_mtu ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-09-13 12:49:28 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > decoder_info )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > read_block_size  =  u - > bt_codec - > get_read_block_size ( u - > decoder_info ,  u - > read_link_mtu ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        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 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > bt_codec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > encoder_info )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > bt_codec - > reset ( u - > encoder_info )  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > decoder_info )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > bt_codec - > reset ( u - > decoder_info )  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-07-21 17:07:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            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 ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# ifdef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > read_smoother  =  pa_smoother_2_new ( 5 * PA_USEC_PER_SEC ,  pa_rtclock_now ( ) ,  pa_frame_size ( & u - > decoder_sample_spec ) ,  u - > decoder_sample_spec . rate ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        u - > read_smoother  =  pa_smoother_new ( PA_USEC_PER_SEC ,  2 * PA_USEC_PER_SEC ,  true ,  true ,  10 ,  pa_rtclock_now ( ) ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  pa_hook_result_t  sink_source_volume_changed_cb ( void  * hook_data ,  void  * call_data ,  void  * slot_data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u  =  slot_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    const  pa_cvolume  * new_volume  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_volume_t  volume ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_transport_set_volume_cb  notify_volume_change ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* In the HS/HF role, notify the AG of a change in speaker/microphone gain.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  In  the  AG  role  the  command  to  change  HW  volume  on  the  remote  is  already 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  sent  by  the  hardware  callback  ( if  the  peer  supports  it  and  the  sink 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  or  source  set_volume  callback  is  attached .  Otherwise  nothing  is  sent ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( pa_bluetooth_profile_should_attenuate_volume ( u - > profile ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > sink  = =  call_data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        new_volume  =  pa_sink_get_volume ( u - > sink ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        notify_volume_change  =  u - > transport - > set_sink_volume ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  if  ( u - > source  = =  call_data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        new_volume  =  pa_source_get_volume ( u - > source ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        notify_volume_change  =  u - > transport - > set_source_volume ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Volume control/notifications are optional */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! notify_volume_change ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    volume  =  pa_cvolume_max ( new_volume ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    notify_volume_change ( u - > transport ,  volume ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 :  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# ifndef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( u - > read_smoother )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# ifdef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                * ( ( int64_t * )  data )  =  u - > source - > thread_info . fixed_latency  -  pa_smoother_2_get_delay ( u - > read_smoother ,  pa_rtclock_now ( ) ,  u - > read_index ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:53 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											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 ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# ifdef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_smoother_2_pause ( u - > read_smoother ,  pa_rtclock_now ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                pa_smoother_pause ( u - > read_smoother ,  pa_rtclock_now ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-13 19:40:38 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            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 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( ! pa_bluetooth_profile_should_attenuate_volume ( u - > profile ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport - > set_source_volume ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* In the AG role, send a command to change microphone gain on the HS/HF */ 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    volume  =  u - > transport - > set_source_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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  source_setup_volume_callback ( pa_source  * s )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s - > core ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u  =  s - > userdata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > source  = =  s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 21:59:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( pa_bluetooth_profile_is_a2dp ( u - > profile )  & &  ! u - > transport - > device - > avrcp_absolute_volume ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* Remote volume control has to be supported for the callback to make sense,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  otherwise  this  source  should  continue  performing  attenuation  in  software 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  without  HW_VOLUME_CTL . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  If  the  peer  is  an  AG  however  backend - native  unconditionally  provides  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  function ,  PA  in  the  role  of  HS / HF  is  responsible  for  signalling  support 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  by  emitting  an  initial  volume  command . 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-16 15:39:41 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  For  A2DP  bluez - util  also  unconditionally  provides  this  function  to  keep 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  the  peer  informed  about  volume  changes . 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > transport - > set_source_volume ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_bluetooth_profile_should_attenuate_volume ( u - > profile ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > source_volume_changed_slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_debug ( " %s: Attaching volume hook to notify peer of changes " ,  s - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > source_volume_changed_slot  =  pa_hook_connect ( & s - > core - > hooks [ PA_CORE_HOOK_SOURCE_VOLUME_CHANGED ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                                        PA_HOOK_NORMAL ,  sink_source_volume_changed_cb ,  u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Send initial volume to peer, signalling support for volume control */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > transport - > set_source_volume ( u - > transport ,  pa_cvolume_max ( & s - > real_volume ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-16 15:39:41 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /* It is yet unknown how (if at all) volume is synchronized for bidirectional
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  A2DP  codecs .   Disallow  attaching  callbacks  ( and  using  HFP  n_volume_steps ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  below  to  a  pa_source  if  the  peer  is  in  A2DP_SINK  role .   This  assert  should 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  be  replaced  with  the  proper  logic  when  bidirectional  codecs  are  implemented . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( u - > profile  ! =  PA_BLUETOOTH_PROFILE_A2DP_SINK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( s - > set_volume  = =  source_set_volume_cb ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_log_debug ( " %s: Resetting software volume for hardware attenuation by peer " ,  s - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Reset local attenuation */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_source_set_soft_volume ( s ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_source_set_set_volume_callback ( s ,  source_set_volume_cb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-27 11:42:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        s - > n_volume_steps  =  HSP_MAX_GAIN  +  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01: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 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > bt_codec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_sets ( data . proplist ,  PA_PROP_BLUETOOTH_CODEC ,  u - > bt_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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    source_setup_volume_callback ( u - > source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 :  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            int64_t  wi ,  ri ,  delay  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( u - > read_smoother )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# ifdef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                /* This is only used for SCO where encoder and decoder sample specs are
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 *  equal  and  output  timing  is  based  on  the  source .  Therefore  we  can  pass 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 *  the  write  index  without  conversion .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                delay  =  pa_smoother_2_get_delay ( u - > read_smoother ,  pa_rtclock_now ( ) ,  u - > write_index  +  u - > write_block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                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 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                delay  =  wi  -  ri ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											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 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                delay  =  wi  -  ri ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:52 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            * ( ( int64_t * )  data )  =  u - > sink - > thread_info . fixed_latency  +  delay ; 
							 
						 
					
						
							
								
									
										
										
										
											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 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( ! pa_bluetooth_profile_should_attenuate_volume ( u - > profile ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport - > set_sink_volume ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* In the AG role, send a command to change speaker gain on the HS/HF */ 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    volume  =  u - > transport - > set_sink_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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  sink_setup_volume_callback ( pa_sink  * s )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( s - > core ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u  =  s - > userdata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > sink  = =  s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 21:59:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( pa_bluetooth_profile_is_a2dp ( u - > profile )  & &  ! u - > transport - > device - > avrcp_absolute_volume ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* Remote volume control has to be supported for the callback to make sense,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  otherwise  this  sink  should  continue  performing  attenuation  in  software 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  without  HW_VOLUME_CTL . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  If  the  peer  is  an  AG  however  backend - native  unconditionally  provides  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  function ,  PA  in  the  role  of  HS / HF  is  responsible  for  signalling  support 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  by  emitting  an  initial  volume  command . 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > transport - > set_sink_volume ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_bluetooth_profile_should_attenuate_volume ( u - > profile ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-16 02:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /* It is yet unknown how (if at all) volume is synchronized for bidirectional
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  A2DP  codecs .   Disallow  attaching  hooks  to  a  pa_sink  if  the  peer  is  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  A2DP_SOURCE  role .   This  assert  should  be  replaced  with  the  proper  logic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  when  bidirectional  codecs  are  implemented . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_assert ( u - > profile  ! =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > sink_volume_changed_slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_debug ( " %s: Attaching volume hook to notify peer of changes " ,  s - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > sink_volume_changed_slot  =  pa_hook_connect ( & s - > core - > hooks [ PA_CORE_HOOK_SINK_VOLUME_CHANGED ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                                      PA_HOOK_NORMAL ,  sink_source_volume_changed_cb ,  u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Send initial volume to peer, signalling support for volume control */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > transport - > set_sink_volume ( u - > transport ,  pa_cvolume_max ( & s - > real_volume ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( s - > set_volume  = =  sink_set_volume_cb ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_log_debug ( " %s: Resetting software volume for hardware attenuation by peer " ,  s - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Reset local attenuation */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_set_soft_volume ( s ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sink_set_set_volume_callback ( s ,  sink_set_volume_cb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-16 02:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > profile  = =  PA_BLUETOOTH_PROFILE_A2DP_SINK ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            s - > n_volume_steps  =  A2DP_MAX_GAIN  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            s - > n_volume_steps  =  HSP_MAX_GAIN  +  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01: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 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > bt_codec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_sets ( data . proplist ,  PA_PROP_BLUETOOTH_CODEC ,  u - > bt_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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    sink_setup_volume_callback ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:47 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								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 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_HSP_HS ]  =  PA_DIRECTION_INPUT  |  PA_DIRECTION_OUTPUT , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_HSP_AG ]  =  PA_DIRECTION_INPUT  |  PA_DIRECTION_OUTPUT , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_HFP_HF ]  =  PA_DIRECTION_INPUT  |  PA_DIRECTION_OUTPUT , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_HFP_AG ]  =  PA_DIRECTION_INPUT  |  PA_DIRECTION_OUTPUT , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        [ PA_BLUETOOTH_PROFILE_OFF ]  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  profile_direction [ p ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/* Run from main thread */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  transport_config ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ! u - > bt_codec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ! u - > encoder_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( ! u - > decoder_info ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > bt_codec  =  u - > transport - > bt_codec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u - > bt_codec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* reset encoder buffer contents */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > encoder_buffer_used  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( get_profile_direction ( u - > profile )  &  PA_DIRECTION_OUTPUT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_info  =  u - > bt_codec - > init ( true ,  false ,  u - > transport - > config ,  u - > transport - > config_size ,  & u - > encoder_sample_spec ,  u - > core ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! u - > encoder_info ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:46 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( get_profile_direction ( u - > profile )  &  PA_DIRECTION_INPUT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > decoder_info  =  u - > bt_codec - > init ( false ,  false ,  u - > transport - > config ,  u - > transport - > config_size ,  & u - > decoder_sample_spec ,  u - > core ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! u - > decoder_info )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( u - > encoder_info )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                u - > bt_codec - > deinit ( u - > encoder_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                u - > encoder_info  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* 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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  bt_render_block ( struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  n_rendered ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > write_index  < =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > started_at  =  pa_rtclock_now ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    n_rendered  =  bt_process_render ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( n_rendered  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        n_rendered  =  - 1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  n_rendered ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    n_read  =  bt_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 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:45:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        /* We just read something, so we are supposed to write something, too
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  If  source  and  sink  sample  specifications  are  not  equal , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         *  expected  write  size  needs  to  be  adjusted  accordingly . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 00:09:09 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        if  ( pa_sample_spec_equal ( & u - > encoder_sample_spec ,  & u - > decoder_sample_spec ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            bytes_to_write  + =  n_read ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            bytes_to_write  + =  pa_usec_to_bytes ( pa_bytes_to_usec ( n_read ,  & u - > decoder_sample_spec ) ,  & u - > encoder_sample_spec ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    /* If the stream is writable, send some data if necessary */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    if  ( writable )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        int  result ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        if  ( blocks_to_write  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            result  =  bt_render_block ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            if  ( result  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            blocks_to_write  - =  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        result  =  bt_write_buffer ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        if  ( result  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            goto  fail ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        if  ( result ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            writable  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    /* 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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                /* 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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            if  ( u - > write_index  >  0  & &  ( get_profile_direction ( u - > profile )  &  PA_DIRECTION_OUTPUT ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                size_t  new_write_block_size  =  u - > bt_codec - > reduce_encoder_bitrate ( u - > encoder_info ,  u - > write_link_mtu ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                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 */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    if  ( writable )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        int  result ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        if  ( blocks_to_write  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            int  result  =  bt_render_block ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            if  ( result  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            blocks_to_write  - =  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        result  =  bt_write_buffer ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        if  ( result  <  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2014-08-22 11:07:11 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            goto  fail ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        if  ( result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                            writable  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-09 07:27:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            have_written  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    /* 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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 18:14:53 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                            if  ( ( get_profile_direction ( u - > profile )  &  PA_DIRECTION_OUTPUT )  & &  u - > write_memchunk . memblock  = =  NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-21 11:41:52 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                /* bt_write_buffer() is keeping up with input, try increasing bitrate */ 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                if  ( u - > bt_codec - > increase_encoder_bitrate 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:51:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                    & &  pa_timeval_age ( & tv_last_output_rate_change )  > =  u - > device - > output_rate_refresh_interval_ms  *  PA_USEC_PER_MSEC )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                    size_t  new_write_block_size  =  u - > bt_codec - > increase_encoder_bitrate ( u - > encoder_info ,  u - > write_link_mtu ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-20 12:51:14 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                    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 ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > bt_codec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_proplist_sets ( u - > card - > proplist ,  PA_PROP_BLUETOOTH_CODEC ,  u - > bt_codec - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-31 13:59:40 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-27 14:05:00 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* Now that everything is set up we are ready to check for the Volume property.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Sometimes  its  initial  " change "  notification  arrives  too  early  when  the  sink 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  is  not  available  or  still  in  UNLINKED  state ;  check  it  again  here  to  know  if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  our  sink  peer  supports  Absolute  Volume ;  in  that  case  we  should  not  perform 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  any  attenuation  but  delegate  all  set_volume  calls  to  the  peer  through  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Volume  property . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Note  that  this  works  the  other  way  around  if  the  peer  is  in  source  profile : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  we  are  rendering  audio  and  hence  responsible  for  applying  attenuation .   The 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  set_volume  callback  is  always  registered ,  and  Volume  is  always  passed  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  BlueZ  unconditionally .   BlueZ  only  sends  a  notification  to  the  peer  if  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  registered  a  notification  request  for  absolute  volume  previously . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > transport  & &  u - > sink ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_bluetooth_transport_load_a2dp_sink_volume ( u - > transport ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 12:12:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > sink_volume_changed_slot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_slot_free ( u - > sink_volume_changed_slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > sink_volume_changed_slot  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > source_volume_changed_slot )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_slot_free ( u - > source_volume_changed_slot ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > source_volume_changed_slot  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:49 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    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 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# ifdef USE_SMOOTHER_2 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_smoother_2_free ( u - > read_smoother ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# else 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_smoother_free ( u - > read_smoother ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 20:36:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:51 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        u - > read_smoother  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > bt_codec )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > encoder_info )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            u - > bt_codec - > deinit ( u - > encoder_info ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            u - > encoder_info  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( u - > decoder_info )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            u - > bt_codec - > deinit ( u - > decoder_info ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            u - > decoder_info  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        u - > bt_codec  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > encoder_buffer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_xfree ( u - > encoder_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > encoder_buffer  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > encoder_buffer_size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > encoder_buffer_used  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > decoder_buffer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_xfree ( u - > decoder_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > decoder_buffer  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > decoder_buffer_size  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 14:26:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( d - > has_battery_level )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // See device_battery_level_changed_cb
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        uint8_t  level  =  d - > battery_level ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_setf ( data . proplist ,  " bluetooth.battery " ,  " %d%% " ,  level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-11 15:46:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_log_debug ( " Trying to create profile %s (%s) for device %s (%s) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     pa_bluetooth_profile_to_string ( profile ) ,  uuid ,  d - > alias ,  d - > address ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( pa_hashmap_get ( data . profiles ,  pa_bluetooth_profile_to_string ( profile ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " %s already exists " ,  pa_bluetooth_profile_to_string ( profile ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-11 15:46:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2013-09-24 19:45:45 -03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-11 15:46:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! pa_bluetooth_device_supports_profile ( d ,  profile ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_debug ( " %s is not supported by the device or adapter " ,  pa_bluetooth_profile_to_string ( profile ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-11 12:57:07 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-11 15:46:36 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-11 12:57:07 -07: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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 14:26:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  pa_hook_result_t  device_battery_level_changed_cb ( pa_bluetooth_discovery  * y ,  const  pa_bluetooth_device  * d ,  struct  userdata  * u )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    uint8_t  level ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( d ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 11:45:46 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( d  ! =  u - > device ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 14:26:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-19 11:45:46 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( d - > has_battery_level )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        level  =  d - > battery_level ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_setf ( u - > card - > proplist ,  " bluetooth.battery " ,  " %d%% " ,  level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_unset ( u - > card - > proplist ,  " bluetooth.battery " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 14:26:47 +01: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 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  pa_hook_result_t  transport_sink_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 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    volume  =  t - > sink_volume ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! u - > sink )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_warn ( " Received peer transport volume change without connected sink " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    sink_setup_volume_callback ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-06 11:15:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_cvolume_set ( & v ,  u - > encoder_sample_spec . channels ,  volume ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 11:30:42 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( pa_bluetooth_profile_should_attenuate_volume ( t - > profile ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-07 13:44:54 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sink_set_volume ( u - > sink ,  & v ,  true ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 11:30:42 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_volume_changed ( u - > sink ,  & v ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  pa_hook_result_t  transport_source_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 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    volume  =  t - > source_volume ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-21 00:41:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! u - > source )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log_warn ( " Received peer transport volume change without connected source " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  PA_HOOK_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    source_setup_volume_callback ( u - > source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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-03-04 11:30:42 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( pa_bluetooth_profile_should_attenuate_volume ( t - > profile ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-07 13:44:54 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_source_set_volume ( u - > source ,  & v ,  true ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 11:30:42 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_source_volume_changed ( u - > source ,  & v ) ; 
							 
						 
					
						
							
								
									
										
										
										
											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 " , 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            u - > bt_codec - > name ,  pa_bluetooth_profile_to_string ( u - > profile ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 09:49:05 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_json_encoder  * encoder ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    unsigned  int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  is_a2dp_sink ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    void  * state ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 09:49:05 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    encoder  =  pa_json_encoder_new ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 09:49:05 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_json_encoder_begin_element_array ( encoder ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 21:59:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( pa_bluetooth_profile_is_a2dp ( u - > profile ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-22 23:14:37 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        PA_HASHMAP_FOREACH_KV ( key ,  a2dp_capabilities ,  a2dp_endpoints ,  state )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            for  ( i  =  0 ;  i  <  pa_bluetooth_a2dp_endpoint_conf_count ( ) ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                const  pa_a2dp_endpoint_conf  * endpoint_conf ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                endpoint_conf  =  pa_bluetooth_a2dp_endpoint_conf_iter ( i ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  ( memcmp ( key ,  & endpoint_conf - > id ,  sizeof ( pa_a2dp_codec_id ) )  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    if  ( endpoint_conf - > can_be_supported ( is_a2dp_sink ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-22 23:14:37 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        pa_json_encoder_begin_element_object ( encoder ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        pa_json_encoder_add_member_string ( encoder ,  " name " ,  endpoint_conf - > bt_codec . name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        pa_json_encoder_add_member_string ( encoder ,  " description " ,  endpoint_conf - > bt_codec . description ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-02-22 23:14:37 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        pa_json_encoder_end_object ( encoder ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    } 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 19:38:48 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-22 23:14:37 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* find out active codec selection from device profile */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( i  =  0 ;  i  <  pa_bluetooth_hf_codec_count ( ) ;  i + + )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            const  pa_bt_codec  * hf_codec ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-22 23:14:37 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hf_codec  =  pa_bluetooth_hf_codec_iter ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( true )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_json_encoder_begin_element_object ( encoder ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_json_encoder_add_member_string ( encoder ,  " name " ,  hf_codec - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_json_encoder_add_member_string ( encoder ,  " description " ,  hf_codec - > description ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_json_encoder_end_object ( encoder ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 09:49:05 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_json_encoder_end_array ( encoder ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 09:49:05 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  pa_json_encoder_to_string_free ( encoder ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 21:03:48 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 09:49:05 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  int  bluez5_device_message_handler ( const  char  * object_path ,  const  char  * message ,  const  pa_json_object  * parameters ,  char  * * response ,  void  * userdata )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    char  * message_handler_path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_hashmap  * capabilities_hashmap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_bluetooth_profile_t  profile ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    const  pa_a2dp_endpoint_conf  * endpoint_conf ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    const  char  * codec_name ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 08:40:35 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    struct  userdata  * u  =  userdata ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  is_a2dp_sink ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-30 08:40:35 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_assert ( u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_streq ( message ,  " switch-codec " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-22 23:14:37 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > profile  ! =  PA_BLUETOOTH_PROFILE_A2DP_SINK  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > profile  ! =  PA_BLUETOOTH_PROFILE_A2DP_SOURCE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " Switching codecs only allowed for A2DP sink or source " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 09:49:05 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! parameters )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " Codec switching operation requires codec name string parameter " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( pa_json_object_get_type ( parameters )  ! =  PA_JSON_TYPE_STRING )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " Codec name object parameter must be a string " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        codec_name  =  pa_json_object_get_string ( parameters ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > bt_codec  & &  pa_streq ( codec_name ,  u - > bt_codec - > name ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            pa_log_info ( " Requested codec is currently selected codec " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        endpoint_conf  =  pa_bluetooth_get_a2dp_endpoint_conf ( codec_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( endpoint_conf  = =  NULL )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            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 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! endpoint_conf - > 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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        capabilities_hashmap  =  pa_hashmap_get ( is_a2dp_sink  ?  u - > device - > a2dp_sink_endpoints  :  u - > device - > a2dp_source_endpoints ,  & endpoint_conf - > id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! capabilities_hashmap )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_log_info ( " No remote endpoint found for %s codec. Codec not supported by remote endpoint. " , 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    endpoint_conf - > bt_codec . name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  - PA_ERR_INVALID ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_log_info ( " Initiating codec switching process to %s " ,  endpoint_conf - > bt_codec . name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-18 17:05:44 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         *  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-03-02 21:33:24 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! pa_bluetooth_device_switch_codec ( u - > device ,  profile ,  capabilities_hashmap ,  endpoint_conf ,  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 " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 09:49:05 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_json_encoder  * encoder ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        encoder  =  pa_json_encoder_new ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 11:48:11 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-03 08:12:08 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( u - > bt_codec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_json_encoder_add_element_string ( encoder ,  u - > bt_codec - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_json_encoder_add_element_null ( encoder ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 11:48:11 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-14 09:49:05 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        * response  =  pa_json_encoder_to_string_free ( encoder ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-01 11:48:11 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 21:59:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  autodetect_mtu ,  avrcp_absolute_volume ; 
							 
						 
					
						
							
								
									
										
										
										
											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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 21:59:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    avrcp_absolute_volume  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_modargs_get_value_boolean ( ma ,  " avrcp_absolute_volume " ,  & avrcp_absolute_volume )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Invalid boolean value for avrcp_absolute_volume parameter " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail_free_modargs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > device - > avrcp_absolute_volume  =  avrcp_absolute_volume ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 14:26:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > device_battery_level_changed_slot  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_connect ( pa_bluetooth_discovery_hook ( u - > discovery ,  PA_BLUETOOTH_HOOK_DEVICE_BATTERY_LEVEL_CHANGED ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        PA_HOOK_NORMAL ,  ( pa_hook_cb_t )  device_battery_level_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 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > transport_sink_volume_changed_slot  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_connect ( pa_bluetooth_discovery_hook ( u - > discovery ,  PA_BLUETOOTH_HOOK_TRANSPORT_SINK_VOLUME_CHANGED ) ,  PA_HOOK_NORMAL ,  ( pa_hook_cb_t )  transport_sink_volume_changed_cb ,  u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > transport_source_volume_changed_slot  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_connect ( pa_bluetooth_discovery_hook ( u - > discovery ,  PA_BLUETOOTH_HOOK_TRANSPORT_SOURCE_VOLUME_CHANGED ) ,  PA_HOOK_NORMAL ,  ( pa_hook_cb_t )  transport_source_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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-18 14:26:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > device_battery_level_changed_slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_slot_free ( u - > device_battery_level_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 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > transport_sink_volume_changed_slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_slot_free ( u - > transport_sink_volume_changed_slot ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2014-10-24 09:56:52 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-06-07 17:07:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > transport_source_volume_changed_slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_hook_slot_free ( u - > transport_source_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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}