2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/***
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    This  file  is  part  of  PulseAudio . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Copyright  2010  Intel  Corporation 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Contributor :  Pierre - Louis  Bossart  < pierre - louis . bossart @ intel . com > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    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  License 
							 
						 
					
						
							
								
									
										
										
										
											2014-11-26 14:14:51 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    along  with  PulseAudio ;  if  not ,  see  < http : //www.gnu.org/licenses/>.
 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								* * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# ifdef HAVE_CONFIG_H 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <config.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-06-13 15:04:33 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulse/gccmacro.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulse/xmalloc.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-08-10 10:30:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <pulsecore/i18n.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/namereg.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/sink.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/module.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/core-util.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/modargs.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/log.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/rtpoll.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/sample-util.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <pulsecore/ltdl-helper.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								PA_MODULE_AUTHOR ( " Pierre-Louis Bossart " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								PA_MODULE_DESCRIPTION ( _ ( " Virtual sink " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								PA_MODULE_VERSION ( PACKAGE_VERSION ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-27 19:28:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								PA_MODULE_LOAD_ONCE ( false ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								PA_MODULE_USAGE ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        _ ( " sink_name=<name for the sink>  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          " sink_properties=<properties for the sink>  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          " master=<name of sink to filter>  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          " rate=<sample rate>  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          " channels=<number of channels>  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          " channel_map=<channel map>  " 
							 
						 
					
						
							
								
									
										
										
										
											2011-02-24 16:16:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								          " use_volume_sharing=<yes or no>  " 
							 
						 
					
						
							
								
									
										
										
										
											2011-02-24 16:16:40 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								          " force_flat_volume=<yes or no>  " 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# define MEMBLOCKQ_MAXLENGTH (16*1024*1024) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								struct  userdata  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_module  * module ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-05-02 10:08:27 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* FIXME: Uncomment this and take "autoloaded" as a modarg if this is a filter */ 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-27 19:28:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* bool autoloaded; */ 
							 
						 
					
						
							
								
									
										
										
										
											2011-05-02 10:08:27 +05:30 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink  * sink ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input  * sink_input ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblockq  * memblockq ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-27 19:28:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  auto_desc ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    unsigned  channels ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  const  char *  const  valid_modargs [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " sink_name " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " sink_properties " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " master " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " rate " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " channels " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    " channel_map " , 
							 
						 
					
						
							
								
									
										
										
										
											2011-02-24 16:16:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    " use_volume_sharing " , 
							 
						 
					
						
							
								
									
										
										
										
											2011-02-24 16:16:40 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    " force_flat_volume " , 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    NULL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  sink_process_msg_cb ( pa_msgobject  * o ,  int  code ,  void  * data ,  int64_t  offset ,  pa_memchunk  * chunk )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u  =  PA_SINK ( o ) - > userdata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    switch  ( code )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_MESSAGE_GET_LATENCY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* The sink is _put() before the sink input is, so let's
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  make  sure  we  don ' t  access  it  in  that  time .  Also ,  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  sink  input  is  first  shut  down ,  the  sink  second .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! PA_SINK_IS_LINKED ( u - > sink - > thread_info . state )  | | 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:08 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                ! PA_SINK_INPUT_IS_LINKED ( u - > sink_input - > thread_info . state ) )  { 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								                return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												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 )  = 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                /* Get the latency of the master sink */ 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                pa_sink_get_latency_within_thread ( u - > sink_input - > sink ,  true )  + 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                /* Add the latency internal to our sink input on top */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_bytes_to_usec ( pa_memblockq_get_length ( u - > sink_input - > thread_info . render_memblockq ) ,  & u - > sink_input - > sink - > sample_spec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        case  PA_SINK_MESSAGE_SET_STATE :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_sink_state_t  new_state  =  ( pa_sink_state_t )  PA_PTR_TO_UINT ( data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            /* When set to running or idle for the first time, request a rewind
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             *  of  the  master  sink  to  make  sure  we  are  heard  immediately  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ( new_state  = =  PA_SINK_IDLE  | |  new_state  = =  PA_SINK_RUNNING )  & &  u - > sink - > thread_info . state  = =  PA_SINK_INIT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_log_debug ( " Requesting rewind due to state change. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                pa_sink_input_request_rewind ( u - > sink_input ,  0 ,  false ,  true ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  pa_sink_process_msg ( o ,  code ,  data ,  offset ,  chunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from main context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  sink_set_state_cb ( pa_sink  * s ,  pa_sink_state_t  state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_assert_ref ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  s - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! PA_SINK_IS_LINKED ( state )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ! PA_SINK_INPUT_IS_LINKED ( pa_sink_input_get_state ( u - > sink_input ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_cork ( u - > sink_input ,  state  = =  PA_SINK_SUSPENDED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_request_rewind_cb ( pa_sink  * s )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_assert_ref ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  s - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! PA_SINK_IS_LINKED ( u - > sink - > thread_info . state )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ! PA_SINK_INPUT_IS_LINKED ( u - > sink_input - > thread_info . state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Just hand this one over to the master sink */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 00:39:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_sink_input_request_rewind ( u - > sink_input , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                                 s - > thread_info . rewind_nbytes  + 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-27 19:28:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                 pa_memblockq_get_length ( u - > memblockq ) ,  true ,  false ,  false ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_update_requested_latency_cb ( pa_sink  * s )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_assert_ref ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  s - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! PA_SINK_IS_LINKED ( u - > sink - > thread_info . state )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ! PA_SINK_INPUT_IS_LINKED ( u - > sink_input - > thread_info . state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Just hand this one over to the master sink */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_set_requested_latency_within_thread ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u - > sink_input , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            pa_sink_get_requested_latency_within_thread ( s ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from main context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_set_volume_cb ( pa_sink  * s )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_assert_ref ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  s - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! PA_SINK_IS_LINKED ( pa_sink_get_state ( s ) )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ! PA_SINK_INPUT_IS_LINKED ( pa_sink_input_get_state ( u - > sink_input ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-27 19:28:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_sink_input_set_volume ( u - > sink_input ,  & s - > real_volume ,  s - > save_volume ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from main context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_set_mute_cb ( pa_sink  * s )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_assert_ref ( s ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  s - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! PA_SINK_IS_LINKED ( pa_sink_get_state ( s ) )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ! PA_SINK_INPUT_IS_LINKED ( pa_sink_input_get_state ( u - > sink_input ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_set_mute ( u - > sink_input ,  s - > muted ,  s - > save_muted ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  int  sink_input_pop_cb ( pa_sink_input  * i ,  size_t  nbytes ,  pa_memchunk  * chunk )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    float  * src ,  * dst ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  fs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    unsigned  n ,  c ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memchunk  tchunk ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-03-19 16:26:47 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_usec_t  current_latency  PA_GCC_UNUSED ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( chunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! PA_SINK_IS_LINKED ( u - > sink - > thread_info . state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    /* Hmm, process any rewind request that might be queued up */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_process_rewind ( u - > sink ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* (1) IF YOU NEED A FIXED BLOCK SIZE USE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  pa_memblockq_peek_fixed_size ( )  HERE  INSTEAD .  NOTE  THAT  FILTERS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  WHICH  CAN  DEAL  WITH  DYNAMIC  BLOCK  SIZES  ARE  HIGHLY 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  PREFERRED .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    while  ( pa_memblockq_peek ( u - > memblockq ,  & tchunk )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memchunk  nchunk ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_render ( u - > sink ,  nbytes ,  & nchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblockq_push ( u - > memblockq ,  & nchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblock_unref ( nchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* (2) IF YOU NEED A FIXED BLOCK SIZE, THIS NEXT LINE IS NOT
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  NECESSARY  */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    tchunk . length  =  PA_MIN ( nbytes ,  tchunk . length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( tchunk . length  >  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    fs  =  pa_frame_size ( & i - > sample_spec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    n  =  ( unsigned )  ( tchunk . length  /  fs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( n  >  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    chunk - > index  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    chunk - > length  =  n * fs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    chunk - > memblock  =  pa_memblock_new ( i - > sink - > core - > mempool ,  chunk - > length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblockq_drop ( u - > memblockq ,  chunk - > length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-08-17 18:09:34 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    src  =  pa_memblock_acquire_chunk ( & tchunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    dst  =  pa_memblock_acquire ( chunk - > memblock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* (3) PUT YOUR CODE HERE TO DO SOMETHING WITH THE DATA */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 00:39:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* As an example, copy input to output */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    for  ( c  =  0 ;  c  <  u - > channels ;  c + + )  { 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 00:39:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sample_clamp ( PA_SAMPLE_FLOAT32NE , 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:10:45 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        dst + c ,  u - > channels  *  sizeof ( float ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        src + c ,  u - > channels  *  sizeof ( float ) , 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 00:39:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        n ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 00:39:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblock_release ( tchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblock_release ( chunk - > memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblock_unref ( tchunk . memblock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* (4) IF YOU NEED THE LATENCY FOR SOMETHING ACQUIRE IT LIKE THIS: */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    current_latency  = 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        /* Get the latency of the master sink */ 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												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 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sink_get_latency_within_thread ( i - > sink ,  false )  + 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /* Add the latency internal to our sink input on top */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_bytes_to_usec ( pa_memblockq_get_length ( i - > thread_info . render_memblockq ) ,  & i - > sink - > sample_spec ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_process_rewind_cb ( pa_sink_input  * i ,  size_t  nbytes )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size_t  amount  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* If the sink is not yet linked, there is nothing to rewind */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! PA_SINK_IS_LINKED ( u - > sink - > thread_info . state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > sink - > thread_info . rewind_nbytes  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        size_t  max_rewrite ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        max_rewrite  =  nbytes  +  pa_memblockq_get_length ( u - > memblockq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        amount  =  PA_MIN ( u - > sink - > thread_info . rewind_nbytes ,  max_rewrite ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > sink - > thread_info . rewind_nbytes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( amount  >  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-27 19:28:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            pa_memblockq_seek ( u - > memblockq ,  -  ( int64_t )  amount ,  PA_SEEK_RELATIVE ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /* (5) PUT YOUR CODE HERE TO RESET YOUR FILTER  */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_process_rewind ( u - > sink ,  amount ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblockq_rewind ( u - > memblockq ,  nbytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_update_max_rewind_cb ( pa_sink_input  * i ,  size_t  nbytes )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-08-19 14:49:27 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* FIXME: Too small max_rewind:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  https : //bugs.freedesktop.org/show_bug.cgi?id=53709 */
 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_memblockq_set_maxrewind ( u - > memblockq ,  nbytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_max_rewind_within_thread ( u - > sink ,  nbytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_update_max_request_cb ( pa_sink_input  * i ,  size_t  nbytes )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* (6) IF YOU NEED A FIXED BLOCK SIZE ROUND nbytes UP TO MULTIPLES
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  OF  IT  HERE .  THE  PA_ROUND_UP  MACRO  IS  USEFUL  FOR  THAT .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_max_request_within_thread ( u - > sink ,  nbytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_update_sink_latency_range_cb ( pa_sink_input  * i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_latency_range_within_thread ( u - > sink ,  i - > sink - > thread_info . min_latency ,  i - > sink - > thread_info . max_latency ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_update_sink_fixed_latency_cb ( pa_sink_input  * i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* (7) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  BLOCK  MINUS  ONE  SAMPLE  HERE .  pa_usec_to_bytes_round_up ( )  IS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  USEFUL  FOR  THAT .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_fixed_latency_within_thread ( u - > sink ,  i - > sink - > thread_info . fixed_latency ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_detach_cb ( pa_sink_input  * i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( PA_SINK_IS_LINKED ( u - > sink - > thread_info . state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_detach_within_thread ( u - > sink ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_rtpoll ( u - > sink ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from I/O thread context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_attach_cb ( pa_sink_input  * i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_rtpoll ( u - > sink ,  i - > sink - > thread_info . rtpoll ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_latency_range_within_thread ( u - > sink ,  i - > sink - > thread_info . min_latency ,  i - > sink - > thread_info . max_latency ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* (8.1) IF YOU NEED A FIXED BLOCK SIZE ADD THE LATENCY FOR ONE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  BLOCK  MINUS  ONE  SAMPLE  HERE .  SEE  ( 7 )  */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_fixed_latency_within_thread ( u - > sink ,  i - > sink - > thread_info . fixed_latency ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* (8.2) IF YOU NEED A FIXED BLOCK SIZE ROUND
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  pa_sink_input_get_max_request ( i )  UP  TO  MULTIPLES  OF  IT 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  HERE .  SEE  ( 6 )  */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_max_request_within_thread ( u - > sink ,  pa_sink_input_get_max_request ( i ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2012-08-19 14:49:27 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* FIXME: Too small max_rewind:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  https : //bugs.freedesktop.org/show_bug.cgi?id=53709 */
 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_max_rewind_within_thread ( u - > sink ,  pa_sink_input_get_max_rewind ( i ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( PA_SINK_IS_LINKED ( u - > sink - > thread_info . state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_attach_within_thread ( u - > sink ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from main context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_kill_cb ( pa_sink_input  * i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* The order here matters! We first kill the sink so that streams
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  can  properly  be  moved  away  while  the  sink  input  is  still  connected 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  to  the  master .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_cork ( u - > sink_input ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_unlink ( u - > sink ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_sink_input_unlink ( u - > sink_input ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_unref ( u - > sink_input ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_unref ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-06-27 19:28:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_module_unload_request ( u - > module ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from main context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_moving_cb ( pa_sink_input  * i ,  pa_sink  * dest )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( dest )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_set_asyncmsgq ( u - > sink ,  dest - > asyncmsgq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_update_flags ( u - > sink ,  PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY ,  dest - > flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_set_asyncmsgq ( u - > sink ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > auto_desc  & &  dest )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        const  char  * z ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist  * pl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pl  =  pa_proplist_new ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        z  =  pa_proplist_gets ( dest - > proplist ,  PA_PROP_DEVICE_DESCRIPTION ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_setf ( pl ,  PA_PROP_DEVICE_DESCRIPTION ,  " Virtual Sink %s on %s " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         pa_proplist_gets ( u - > sink - > proplist ,  " device.vsink.name " ) ,  z  ?  z  :  dest - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_update_proplist ( u - > sink ,  PA_UPDATE_REPLACE ,  pl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_free ( pl ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from main context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_volume_changed_cb ( pa_sink_input  * i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_volume_changed ( u - > sink ,  & i - > volume ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								/* Called from main context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  sink_input_mute_changed_cb ( pa_sink_input  * i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_assert_ref ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  i - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_mute_changed ( u - > sink ,  i - > muted ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  pa__init ( pa_module * m )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sample_spec  ss ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_channel_map  map ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_modargs  * ma ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink  * master = NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_new_data  sink_input_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_new_data  sink_data ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-27 19:28:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    bool  use_volume_sharing  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  force_flat_volume  =  false ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												virtual-sink: Fix a crash when moving the sink to a new master right after setup.
If the virtual sink is moved to a new master right after it has been created,
then the virtual sink input's memblockq can be rewound to a negative read
index. The data written prior to the move starts from index zero, so after the
rewind there's a bit of silence. If the memblockq doesn't have a silence
memchunk set, then pa_memblockq_peek() will return zero in such case, and the
returned memchunk's memblock pointer will be NULL.
That scenario wasn't taken into account in the implementation of
sink_input_pop_cb. Setting a silence memchunk for the memblockq solves this
problem, because pa_memblock_peek() will now return a valid memblock if the
read index happens to point to a hole in the memblockq.
I believe this isn't the best possible solution, though. It doesn't really make
sense to rewind the sink input's memblockq beyond index 0 in the first place,
because now when the stream starts to play to the new master sink, there's some
unnecessary silence before the actual data starts. This is a small problem,
though, and I don't grok the rewinding system well enough to know how to fix
this issue properly.
I went through all files that call pa_memblockq_peek() to see if there are more
similar bugs. play-memblockq.c was the only one that looked to me like it might
be broken in the same way. I didn't try reproducing the bug with
play-memblockq.c, though, so I just added a FIXME comment there.
											 
										 
										
											2011-02-24 16:16:43 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_memchunk  silence ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ( ma  =  pa_modargs_new ( m - > argument ,  valid_modargs ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Failed to parse module arguments. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ( master  =  pa_namereg_get ( m - > core ,  pa_modargs_get_value ( ma ,  " master " ,  NULL ) ,  PA_NAMEREG_SINK ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Master sink not found " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( master ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ss  =  master - > sample_spec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ss . format  =  PA_SAMPLE_FLOAT32 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    map  =  master - > channel_map ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_modargs_get_sample_spec_and_channel_map ( ma ,  & ss ,  & map ,  PA_CHANNEL_MAP_DEFAULT )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Invalid sample format specification or channel map " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-02-24 16:16:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( pa_modargs_get_value_boolean ( ma ,  " use_volume_sharing " ,  & use_volume_sharing )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " use_volume_sharing= expects a boolean argument " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-02-24 16:16:40 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( pa_modargs_get_value_boolean ( ma ,  " force_flat_volume " ,  & force_flat_volume )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " force_flat_volume= expects a boolean argument " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( use_volume_sharing  & &  force_flat_volume )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Flat volume can't be forced when using volume sharing. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    u  =  pa_xnew0 ( struct  userdata ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > module  =  m ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    m - > userdata  =  u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > channels  =  ss . channels ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Create sink */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_new_data_init ( & sink_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    sink_data . driver  =  __FILE__ ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    sink_data . module  =  m ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ( sink_data . name  =  pa_xstrdup ( pa_modargs_get_value ( ma ,  " sink_name " ,  NULL ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        sink_data . name  =  pa_sprintf_malloc ( " %s.vsink " ,  master - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_new_data_set_sample_spec ( & sink_data ,  & ss ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_new_data_set_channel_map ( & sink_data ,  & map ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( sink_data . proplist ,  PA_PROP_DEVICE_MASTER_DEVICE ,  master - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( sink_data . proplist ,  PA_PROP_DEVICE_CLASS ,  " filter " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( sink_data . proplist ,  " device.vsink.name " ,  sink_data . name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( pa_modargs_get_proplist ( ma ,  " sink_properties " ,  sink_data . proplist ,  PA_UPDATE_REPLACE )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Invalid properties " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_new_data_done ( & sink_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ( u - > auto_desc  =  ! pa_proplist_contains ( sink_data . proplist ,  PA_PROP_DEVICE_DESCRIPTION ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        const  char  * z ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        z  =  pa_proplist_gets ( master - > proplist ,  PA_PROP_DEVICE_DESCRIPTION ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_proplist_setf ( sink_data . proplist ,  PA_PROP_DEVICE_DESCRIPTION ,  " Virtual Sink %s on %s " ,  sink_data . name ,  z  ?  z  :  master - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-02-24 16:16:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > sink  =  pa_sink_new ( m - > core ,  & sink_data ,  ( master - > flags  &  ( PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2011-07-02 16:23:01 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                                               |  ( use_volume_sharing  ?  PA_SINK_SHARE_VOLUME_WITH_MASTER  :  0 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_new_data_done ( & sink_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > sink )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_log ( " Failed to create sink. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink - > parent . process_msg  =  sink_process_msg_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink - > set_state  =  sink_set_state_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink - > update_requested_latency  =  sink_update_requested_latency_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink - > request_rewind  =  sink_request_rewind_cb ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-07-17 15:29:29 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_sink_set_set_mute_callback ( u - > sink ,  sink_set_mute_cb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-07-21 06:50:56 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! use_volume_sharing )  { 
							 
						 
					
						
							
								
									
										
										
										
											2011-07-02 16:23:01 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sink_set_set_volume_callback ( u - > sink ,  sink_set_volume_cb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2013-06-27 19:28:09 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sink_enable_decibel_volume ( u - > sink ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-07-02 16:23:01 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Normally this flag would be enabled automatically be we can force it. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( force_flat_volume ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        u - > sink - > flags  | =  PA_SINK_FLAT_VOLUME ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink - > userdata  =  u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_set_asyncmsgq ( u - > sink ,  master - > asyncmsgq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* Create sink input */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_new_data_init ( & sink_input_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    sink_input_data . driver  =  __FILE__ ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    sink_input_data . module  =  m ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-28 19:50:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_sink_input_new_data_set_sink ( & sink_input_data ,  master ,  false ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-02-07 18:35:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    sink_input_data . origin_sink  =  u - > sink ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-02-24 16:16:41 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_proplist_setf ( sink_input_data . proplist ,  PA_PROP_MEDIA_NAME ,  " Virtual Sink Stream from %s " ,  pa_proplist_gets ( u - > sink - > proplist ,  PA_PROP_DEVICE_DESCRIPTION ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_proplist_sets ( sink_input_data . proplist ,  PA_PROP_MEDIA_ROLE ,  " filter " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_new_data_set_sample_spec ( & sink_input_data ,  & ss ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_new_data_set_channel_map ( & sink_input_data ,  & map ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    sink_input_data . flags  | =  PA_SINK_INPUT_START_CORKED ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_new ( & u - > sink_input ,  m - > core ,  & sink_input_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_new_data_done ( & sink_input_data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! u - > sink_input ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        goto  fail ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > pop  =  sink_input_pop_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > process_rewind  =  sink_input_process_rewind_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > update_max_rewind  =  sink_input_update_max_rewind_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > update_max_request  =  sink_input_update_max_request_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > update_sink_latency_range  =  sink_input_update_sink_latency_range_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > update_sink_fixed_latency  =  sink_input_update_sink_fixed_latency_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > kill  =  sink_input_kill_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > attach  =  sink_input_attach_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > detach  =  sink_input_detach_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > moving  =  sink_input_moving_cb ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-02-24 16:16:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > sink_input - > volume_changed  =  use_volume_sharing  ?  NULL  :  sink_input_volume_changed_cb ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > mute_changed  =  sink_input_mute_changed_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u - > sink_input - > userdata  =  u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-02-07 18:35:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > sink - > input_to_master  =  u - > sink_input ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												virtual-sink: Fix a crash when moving the sink to a new master right after setup.
If the virtual sink is moved to a new master right after it has been created,
then the virtual sink input's memblockq can be rewound to a negative read
index. The data written prior to the move starts from index zero, so after the
rewind there's a bit of silence. If the memblockq doesn't have a silence
memchunk set, then pa_memblockq_peek() will return zero in such case, and the
returned memchunk's memblock pointer will be NULL.
That scenario wasn't taken into account in the implementation of
sink_input_pop_cb. Setting a silence memchunk for the memblockq solves this
problem, because pa_memblock_peek() will now return a valid memblock if the
read index happens to point to a hole in the memblockq.
I believe this isn't the best possible solution, though. It doesn't really make
sense to rewind the sink input's memblockq beyond index 0 in the first place,
because now when the stream starts to play to the new master sink, there's some
unnecessary silence before the actual data starts. This is a small problem,
though, and I don't grok the rewinding system well enough to know how to fix
this issue properly.
I went through all files that call pa_memblockq_peek() to see if there are more
similar bugs. play-memblockq.c was the only one that looked to me like it might
be broken in the same way. I didn't try reproducing the bug with
play-memblockq.c, though, so I just added a FIXME comment there.
											 
										 
										
											2011-02-24 16:16:43 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_sink_input_get_silence ( u - > sink_input ,  & silence ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-09-29 18:54:03 +03:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u - > memblockq  =  pa_memblockq_new ( " module-virtual-sink memblockq " ,  0 ,  MEMBLOCKQ_MAXLENGTH ,  0 ,  & ss ,  1 ,  1 ,  0 ,  & silence ) ; 
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												virtual-sink: Fix a crash when moving the sink to a new master right after setup.
If the virtual sink is moved to a new master right after it has been created,
then the virtual sink input's memblockq can be rewound to a negative read
index. The data written prior to the move starts from index zero, so after the
rewind there's a bit of silence. If the memblockq doesn't have a silence
memchunk set, then pa_memblockq_peek() will return zero in such case, and the
returned memchunk's memblock pointer will be NULL.
That scenario wasn't taken into account in the implementation of
sink_input_pop_cb. Setting a silence memchunk for the memblockq solves this
problem, because pa_memblock_peek() will now return a valid memblock if the
read index happens to point to a hole in the memblockq.
I believe this isn't the best possible solution, though. It doesn't really make
sense to rewind the sink input's memblockq beyond index 0 in the first place,
because now when the stream starts to play to the new master sink, there's some
unnecessary silence before the actual data starts. This is a small problem,
though, and I don't grok the rewinding system well enough to know how to fix
this issue properly.
I went through all files that call pa_memblockq_peek() to see if there are more
similar bugs. play-memblockq.c was the only one that looked to me like it might
be broken in the same way. I didn't try reproducing the bug with
play-memblockq.c, though, so I just added a FIXME comment there.
											 
										 
										
											2011-02-24 16:16:43 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_memblock_unref ( silence . memblock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:41:09 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										 
										
											
												virtual-sink: Fix a crash when moving the sink to a new master right after setup.
If the virtual sink is moved to a new master right after it has been created,
then the virtual sink input's memblockq can be rewound to a negative read
index. The data written prior to the move starts from index zero, so after the
rewind there's a bit of silence. If the memblockq doesn't have a silence
memchunk set, then pa_memblockq_peek() will return zero in such case, and the
returned memchunk's memblock pointer will be NULL.
That scenario wasn't taken into account in the implementation of
sink_input_pop_cb. Setting a silence memchunk for the memblockq solves this
problem, because pa_memblock_peek() will now return a valid memblock if the
read index happens to point to a hole in the memblockq.
I believe this isn't the best possible solution, though. It doesn't really make
sense to rewind the sink input's memblockq beyond index 0 in the first place,
because now when the stream starts to play to the new master sink, there's some
unnecessary silence before the actual data starts. This is a small problem,
though, and I don't grok the rewinding system well enough to know how to fix
this issue properly.
I went through all files that call pa_memblockq_peek() to see if there are more
similar bugs. play-memblockq.c was the only one that looked to me like it might
be broken in the same way. I didn't try reproducing the bug with
play-memblockq.c, though, so I just added a FIXME comment there.
											 
										 
										
											2011-02-24 16:16:43 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* (9) INITIALIZE ANYTHING ELSE YOU NEED HERE */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-25 02:26:03 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /* The order here is important. The input must be put first,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  otherwise  streams  might  attach  to  the  sink  before  the  sink 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  input  is  attached  to  the  master .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_put ( u - > sink_input ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    pa_sink_put ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_sink_input_cork ( u - > sink_input ,  false ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_modargs_free ( ma ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2011-03-02 12:41:26 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								fail : 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ma ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_modargs_free ( ma ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa__done ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								int  pa__get_n_used ( pa_module  * m )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert_se ( u  =  m - > userdata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  pa_sink_linked_by ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  pa__done ( pa_module * m )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    struct  userdata  * u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_assert ( m ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! ( u  =  m - > userdata ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /* See comments in sink_input_kill_cb() above regarding
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  destruction  order !  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > sink_input ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        pa_sink_input_cork ( u - > sink_input ,  true ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > sink ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_unlink ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( u - > sink_input )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_input_unlink ( u - > sink_input ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_input_unref ( u - > sink_input ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-05-18 07:46:46 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2010-02-11 15:44:11 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > sink ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_sink_unref ( u - > sink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( u - > memblockq ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pa_memblockq_free ( u - > memblockq ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pa_xfree ( u ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}