mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	- deprecate autoload stuff
- allow setting of the requested latency of a sink input/source output before _put() is called - allow sinks/sources to have a "minimal" latency which applies to all requested latencies by sink inputs/source outputs - add new client library flags PA_STREAM_ADJUST_LATENCY, PA_STREAM_START_MUTED - allow client library to fill in 0 to buffer_attr fields - update module-alsa-source following module-alsa-sink - other cleanups and fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2215 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
		
							parent
							
								
									ecf6439661
								
							
						
					
					
						commit
						cdfcf6654c
					
				
					 26 changed files with 708 additions and 260 deletions
				
			
		
							
								
								
									
										9
									
								
								PROTOCOL
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								PROTOCOL
									
										
									
									
									
								
							| 
						 | 
					@ -79,7 +79,7 @@ New opcodes for notifications:
 | 
				
			||||||
 PA_COMMAND_PLAYBACK_STREAM_MOVED
 | 
					 PA_COMMAND_PLAYBACK_STREAM_MOVED
 | 
				
			||||||
 PA_COMMAND_CAPTURE_STREAM_MOVED
 | 
					 PA_COMMAND_CAPTURE_STREAM_MOVED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### v13, implemented  by >= 0.9.10
 | 
					### v13, implemented  by >= 0.9.11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
New fields for PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM request at the end:
 | 
					New fields for PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM request at the end:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,3 +117,10 @@ New field for PA_COMMAND_PLAY_SAMPLE:
 | 
				
			||||||
New field for PA_COMMAND_PLAY_SAMPLE response:
 | 
					New field for PA_COMMAND_PLAY_SAMPLE response:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  idx
 | 
					  idx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					New field for PA_COMMAND_CREATE_PLAYBACK_STREAM at the end:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  start_muted
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Buffer attributes for PA_COMMAND_CREATE_PLAYBACK_STREAM and
 | 
				
			||||||
 | 
					PA_COMMAND_CREATE_RECORD_STREAM may now be 0 for default values.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,8 +73,8 @@ PA_MODULE_USAGE(
 | 
				
			||||||
        "tsched_buffer_watermark=<lower fill watermark>");
 | 
					        "tsched_buffer_watermark=<lower fill watermark>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFAULT_DEVICE "default"
 | 
					#define DEFAULT_DEVICE "default"
 | 
				
			||||||
#define DEFAULT_TSCHED_BUFFER_USEC (3*PA_USEC_PER_SEC)
 | 
					#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)
 | 
				
			||||||
#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)
 | 
					#define DEFAULT_TSCHED_WATERMARK_USEC (10*PA_USEC_PER_MSEC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct userdata {
 | 
					struct userdata {
 | 
				
			||||||
    pa_core *core;
 | 
					    pa_core *core;
 | 
				
			||||||
| 
						 | 
					@ -325,7 +325,7 @@ static int unix_write(struct userdata *u) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int update_smoother(struct userdata *u) {
 | 
					static int update_smoother(struct userdata *u) {
 | 
				
			||||||
    snd_pcm_sframes_t delay;
 | 
					    snd_pcm_sframes_t delay  = 0;
 | 
				
			||||||
    int64_t frames;
 | 
					    int64_t frames;
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
    pa_usec_t now1, now2;
 | 
					    pa_usec_t now1, now2;
 | 
				
			||||||
| 
						 | 
					@ -334,6 +334,7 @@ static int update_smoother(struct userdata *u) {
 | 
				
			||||||
    pa_assert(u->pcm_handle);
 | 
					    pa_assert(u->pcm_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Let's update the time smoother */
 | 
					    /* Let's update the time smoother */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snd_pcm_avail_update(u->pcm_handle);
 | 
					    snd_pcm_avail_update(u->pcm_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
 | 
					    if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
 | 
				
			||||||
| 
						 | 
					@ -441,6 +442,31 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
 | 
				
			||||||
    return usec;
 | 
					    return usec;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void update_hwbuf_unused_frames(struct userdata *u) {
 | 
				
			||||||
 | 
					    pa_usec_t usec;
 | 
				
			||||||
 | 
					    size_t b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((usec = pa_sink_get_requested_latency(u->sink)) <= 0) {
 | 
				
			||||||
 | 
					        /* Use the full buffer if noone asked us for anything
 | 
				
			||||||
 | 
					         * specific */
 | 
				
			||||||
 | 
					        u->hwbuf_unused_frames = 0;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    b = pa_usec_to_bytes(usec, &u->sink->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* We need at least one sample in our buffer */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (PA_UNLIKELY(b < u->frame_size))
 | 
				
			||||||
 | 
					        b = u->frame_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u->hwbuf_unused_frames =
 | 
				
			||||||
 | 
					        PA_LIKELY(b < u->hwbuf_size) ?
 | 
				
			||||||
 | 
					        ((u->hwbuf_size - b) / u->frame_size) : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int update_sw_params(struct userdata *u) {
 | 
					static int update_sw_params(struct userdata *u) {
 | 
				
			||||||
    size_t avail_min;
 | 
					    size_t avail_min;
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
| 
						 | 
					@ -465,6 +491,8 @@ static int update_sw_params(struct userdata *u) {
 | 
				
			||||||
        return err;
 | 
					        return err;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    update_hwbuf_unused_frames(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -535,29 +563,6 @@ fail:
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void update_hwbuf_unused_frames(struct userdata *u) {
 | 
					 | 
				
			||||||
    pa_usec_t usec;
 | 
					 | 
				
			||||||
    size_t b;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pa_assert(u);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((usec = pa_sink_get_requested_latency(u->sink)) <= 0) {
 | 
					 | 
				
			||||||
        /* Use the full buffer if noone asked us for anything
 | 
					 | 
				
			||||||
         * specific */
 | 
					 | 
				
			||||||
        u->hwbuf_unused_frames = 0;
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    b = pa_usec_to_bytes(usec, &u->sink->sample_spec);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* We need at least one sample in our buffer */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (PA_UNLIKELY(b < u->frame_size))
 | 
					 | 
				
			||||||
        b = u->frame_size;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    u->hwbuf_unused_frames = PA_LIKELY(b < u->hwbuf_size) ? ((u->hwbuf_size - b) / u->frame_size) : 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
 | 
					static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
 | 
				
			||||||
    struct userdata *u = PA_SINK(o)->userdata;
 | 
					    struct userdata *u = PA_SINK(o)->userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -608,13 +613,13 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case PA_SINK_MESSAGE_ADD_INPUT:
 | 
					/*         case PA_SINK_MESSAGE_ADD_INPUT: */
 | 
				
			||||||
        case PA_SINK_MESSAGE_REMOVE_INPUT:
 | 
					/*         case PA_SINK_MESSAGE_REMOVE_INPUT: */
 | 
				
			||||||
        case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: {
 | 
					/*         case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: { */
 | 
				
			||||||
            int r = pa_sink_process_msg(o, code, data, offset, chunk);
 | 
					/*             int r = pa_sink_process_msg(o, code, data, offset, chunk); */
 | 
				
			||||||
            update_hwbuf_unused_frames(u);
 | 
					/*             update_hwbuf_unused_frames(u); */
 | 
				
			||||||
            return r;
 | 
					/*             return r; */
 | 
				
			||||||
        }
 | 
					/*         } */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return pa_sink_process_msg(o, code, data, offset, chunk);
 | 
					    return pa_sink_process_msg(o, code, data, offset, chunk);
 | 
				
			||||||
| 
						 | 
					@ -703,6 +708,7 @@ static int sink_set_volume_cb(pa_sink *s) {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            u->hw_dB_supported = FALSE;
 | 
					            u->hw_dB_supported = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
 | 
					        alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
 | 
				
			||||||
| 
						 | 
					@ -776,7 +782,7 @@ static void thread_func(void *userdata) {
 | 
				
			||||||
    pa_thread_mq_install(&u->thread_mq);
 | 
					    pa_thread_mq_install(&u->thread_mq);
 | 
				
			||||||
    pa_rtpoll_install(u->rtpoll);
 | 
					    pa_rtpoll_install(u->rtpoll);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    update_hwbuf_unused_frames(u);
 | 
					/*     update_hwbuf_unused_frames(u); */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (;;) {
 | 
					    for (;;) {
 | 
				
			||||||
        int ret;
 | 
					        int ret;
 | 
				
			||||||
| 
						 | 
					@ -1174,6 +1180,9 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
 | 
					    u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!use_tsched)
 | 
				
			||||||
 | 
					        u->sink->min_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
 | 
					    pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
 | 
				
			||||||
                nfrags, (long unsigned) u->fragment_size,
 | 
					                nfrags, (long unsigned) u->fragment_size,
 | 
				
			||||||
                (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
 | 
					                (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,6 +92,8 @@ struct userdata {
 | 
				
			||||||
    snd_mixer_t *mixer_handle;
 | 
					    snd_mixer_t *mixer_handle;
 | 
				
			||||||
    snd_mixer_elem_t *mixer_elem;
 | 
					    snd_mixer_elem_t *mixer_elem;
 | 
				
			||||||
    long hw_volume_max, hw_volume_min;
 | 
					    long hw_volume_max, hw_volume_min;
 | 
				
			||||||
 | 
					    long hw_dB_max, hw_dB_min;
 | 
				
			||||||
 | 
					    pa_bool_t hw_dB_supported;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t frame_size, fragment_size, hwbuf_size, tsched_watermark;
 | 
					    size_t frame_size, fragment_size, hwbuf_size, tsched_watermark;
 | 
				
			||||||
    unsigned nfragments;
 | 
					    unsigned nfragments;
 | 
				
			||||||
| 
						 | 
					@ -288,25 +290,28 @@ static int unix_read(struct userdata *u) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int update_smoother(struct userdata *u) {
 | 
					static int update_smoother(struct userdata *u) {
 | 
				
			||||||
    snd_pcm_status_t *status;
 | 
					    snd_pcm_sframes_t delay = 0;
 | 
				
			||||||
    int64_t frames;
 | 
					    int64_t frames;
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
 | 
					    pa_usec_t now1, now2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(u);
 | 
					    pa_assert(u);
 | 
				
			||||||
    pa_assert(u->pcm_handle);
 | 
					    pa_assert(u->pcm_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snd_pcm_status_alloca(&status);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Let's update the time smoother */
 | 
					    /* Let's update the time smoother */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
 | 
					    snd_pcm_avail_update(u->pcm_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
 | 
				
			||||||
        pa_log("Failed to get delay: %s", snd_strerror(err));
 | 
					        pa_log("Failed to get delay: %s", snd_strerror(err));
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    frames = u->frame_index + snd_pcm_status_get_delay(status);
 | 
					    frames = u->frame_index + delay;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_smoother_put(u->smoother, pa_rtclock_usec(), pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec));
 | 
					    now1 = pa_rtclock_usec();
 | 
				
			||||||
 | 
					    now2 = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec);
 | 
				
			||||||
 | 
					    pa_smoother_put(u->smoother, now1, now2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -373,7 +378,7 @@ static int suspend(struct userdata *u) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static pa_usec_t hw_sleep_time(struct userdata *u) {
 | 
					static pa_usec_t hw_sleep_time(struct userdata *u) {
 | 
				
			||||||
    pa_usec_t usec;
 | 
					    pa_usec_t wm, usec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(u);
 | 
					    pa_assert(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -382,11 +387,17 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
 | 
				
			||||||
    if (usec <= 0)
 | 
					    if (usec <= 0)
 | 
				
			||||||
        usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
 | 
					        usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (usec >= u->tsched_watermark)
 | 
					    pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
 | 
				
			||||||
        usec -= u->tsched_watermark;
 | 
					
 | 
				
			||||||
 | 
					    wm = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (usec >= wm)
 | 
				
			||||||
 | 
					        usec -= wm;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        usec /= 2;
 | 
					        usec /= 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return usec;
 | 
					    return usec;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -470,7 +481,6 @@ static int unsuspend(struct userdata *u) {
 | 
				
			||||||
    /* FIXME: We need to reload the volume somehow */
 | 
					    /* FIXME: We need to reload the volume somehow */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snd_pcm_start(u->pcm_handle);
 | 
					    snd_pcm_start(u->pcm_handle);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pa_smoother_resume(u->smoother, pa_rtclock_usec());
 | 
					    pa_smoother_resume(u->smoother, pa_rtclock_usec());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_log_info("Resumed successfully...");
 | 
					    pa_log_info("Resumed successfully...");
 | 
				
			||||||
| 
						 | 
					@ -568,18 +578,24 @@ static int source_get_volume_cb(pa_source *s) {
 | 
				
			||||||
    pa_assert(u->mixer_elem);
 | 
					    pa_assert(u->mixer_elem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < s->sample_spec.channels; i++) {
 | 
					    for (i = 0; i < s->sample_spec.channels; i++) {
 | 
				
			||||||
        long set_vol, vol;
 | 
					        long alsa_vol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i]));
 | 
					        pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &vol)) < 0)
 | 
					        if (u->hw_dB_supported) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) >= 0) {
 | 
				
			||||||
 | 
					                s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            u->hw_dB_supported = FALSE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
 | 
					        s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* Try to avoid superfluous volume changes */
 | 
					 | 
				
			||||||
        if (set_vol != vol)
 | 
					 | 
				
			||||||
            s->volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
| 
						 | 
					@ -587,8 +603,6 @@ static int source_get_volume_cb(pa_source *s) {
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
    pa_log_error("Unable to read volume: %s", snd_strerror(err));
 | 
					    pa_log_error("Unable to read volume: %s", snd_strerror(err));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->get_volume = NULL;
 | 
					 | 
				
			||||||
    s->set_volume = NULL;
 | 
					 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -604,17 +618,36 @@ static int source_set_volume_cb(pa_source *s) {
 | 
				
			||||||
        long alsa_vol;
 | 
					        long alsa_vol;
 | 
				
			||||||
        pa_volume_t vol;
 | 
					        pa_volume_t vol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i]));
 | 
					        pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        vol = s->volume.values[i];
 | 
					        vol = PA_MIN(s->volume.values[i], PA_VOLUME_NORM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (u->hw_dB_supported) {
 | 
				
			||||||
 | 
					            alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
 | 
				
			||||||
 | 
					            alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ((err = snd_mixer_selem_set_capture_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, -1)) >= 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
 | 
				
			||||||
 | 
					                    s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            u->hw_dB_supported = FALSE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (vol > PA_VOLUME_NORM)
 | 
					 | 
				
			||||||
            vol = PA_VOLUME_NORM;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
 | 
					        alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
 | 
				
			||||||
 | 
					        alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
 | 
					        if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
 | 
				
			||||||
 | 
					            s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
| 
						 | 
					@ -622,8 +655,6 @@ static int source_set_volume_cb(pa_source *s) {
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
    pa_log_error("Unable to set volume: %s", snd_strerror(err));
 | 
					    pa_log_error("Unable to set volume: %s", snd_strerror(err));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->get_volume = NULL;
 | 
					 | 
				
			||||||
    s->set_volume = NULL;
 | 
					 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -636,9 +667,6 @@ static int source_get_mute_cb(pa_source *s) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = snd_mixer_selem_get_capture_switch(u->mixer_elem, 0, &sw)) < 0) {
 | 
					    if ((err = snd_mixer_selem_get_capture_switch(u->mixer_elem, 0, &sw)) < 0) {
 | 
				
			||||||
        pa_log_error("Unable to get switch: %s", snd_strerror(err));
 | 
					        pa_log_error("Unable to get switch: %s", snd_strerror(err));
 | 
				
			||||||
 | 
					 | 
				
			||||||
        s->get_mute = NULL;
 | 
					 | 
				
			||||||
        s->set_mute = NULL;
 | 
					 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -656,15 +684,20 @@ static int source_set_mute_cb(pa_source *s) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->muted)) < 0) {
 | 
					    if ((err = snd_mixer_selem_set_capture_switch_all(u->mixer_elem, !s->muted)) < 0) {
 | 
				
			||||||
        pa_log_error("Unable to set switch: %s", snd_strerror(err));
 | 
					        pa_log_error("Unable to set switch: %s", snd_strerror(err));
 | 
				
			||||||
 | 
					 | 
				
			||||||
        s->get_mute = NULL;
 | 
					 | 
				
			||||||
        s->set_mute = NULL;
 | 
					 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void source_update_requested_latency_cb(pa_source *s) {
 | 
				
			||||||
 | 
					    struct userdata *u = s->userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    update_sw_params(u);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void thread_func(void *userdata) {
 | 
					static void thread_func(void *userdata) {
 | 
				
			||||||
    struct userdata *u = userdata;
 | 
					    struct userdata *u = userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -694,10 +727,11 @@ static void thread_func(void *userdata) {
 | 
				
			||||||
                    goto fail;
 | 
					                    goto fail;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (work_done)
 | 
				
			||||||
                if (update_smoother(u) < 0)
 | 
					                if (update_smoother(u) < 0)
 | 
				
			||||||
                    goto fail;
 | 
					                    goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (u->use_tsched && work_done) {
 | 
					            if (u->use_tsched) {
 | 
				
			||||||
                pa_usec_t usec, cusec;
 | 
					                pa_usec_t usec, cusec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* OK, the capture buffer is now empty, let's
 | 
					                /* OK, the capture buffer is now empty, let's
 | 
				
			||||||
| 
						 | 
					@ -716,6 +750,10 @@ static void thread_func(void *userdata) {
 | 
				
			||||||
                /* We don't trust the conversion, so we wake up whatever comes first */
 | 
					                /* We don't trust the conversion, so we wake up whatever comes first */
 | 
				
			||||||
                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
 | 
					                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (u->use_tsched) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* OK, we're in an invalid state, let's disable our timers */
 | 
				
			||||||
 | 
					            pa_rtpoll_set_timer_disabled(u->rtpoll);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Hmm, nothing to do. Let's sleep */
 | 
					        /* Hmm, nothing to do. Let's sleep */
 | 
				
			||||||
| 
						 | 
					@ -797,7 +835,7 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
    const char *dev_id;
 | 
					    const char *dev_id;
 | 
				
			||||||
    pa_sample_spec ss;
 | 
					    pa_sample_spec ss;
 | 
				
			||||||
    pa_channel_map map;
 | 
					    pa_channel_map map;
 | 
				
			||||||
    uint32_t nfrags, frag_size, tsched_size, tsched_watermark;
 | 
					    uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
 | 
				
			||||||
    snd_pcm_uframes_t period_frames, tsched_frames;
 | 
					    snd_pcm_uframes_t period_frames, tsched_frames;
 | 
				
			||||||
    size_t frame_size;
 | 
					    size_t frame_size;
 | 
				
			||||||
    snd_pcm_info_t *pcm_info = NULL;
 | 
					    snd_pcm_info_t *pcm_info = NULL;
 | 
				
			||||||
| 
						 | 
					@ -846,6 +884,7 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hwbuf_size = frag_size * nfrags;
 | 
				
			||||||
    period_frames = frag_size/frame_size;
 | 
					    period_frames = frag_size/frame_size;
 | 
				
			||||||
    tsched_frames = tsched_size/frame_size;
 | 
					    tsched_frames = tsched_size/frame_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -874,6 +913,7 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
    u->rtpoll = pa_rtpoll_new();
 | 
					    u->rtpoll = pa_rtpoll_new();
 | 
				
			||||||
    u->alsa_rtpoll_item = NULL;
 | 
					    u->alsa_rtpoll_item = NULL;
 | 
				
			||||||
    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
 | 
					    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u->smoother = pa_smoother_new(DEFAULT_TSCHED_WATERMARK_USEC, DEFAULT_TSCHED_WATERMARK_USEC, TRUE);
 | 
					    u->smoother = pa_smoother_new(DEFAULT_TSCHED_WATERMARK_USEC, DEFAULT_TSCHED_WATERMARK_USEC, TRUE);
 | 
				
			||||||
    pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
 | 
					    pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -929,9 +969,6 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (update_sw_params(u) < 0)
 | 
					 | 
				
			||||||
        goto fail;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* ALSA might tweak the sample spec, so recalculate the frame size */
 | 
					    /* ALSA might tweak the sample spec, so recalculate the frame size */
 | 
				
			||||||
    frame_size = pa_frame_size(&ss);
 | 
					    frame_size = pa_frame_size(&ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -996,6 +1033,7 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u->source->parent.process_msg = source_process_msg;
 | 
					    u->source->parent.process_msg = source_process_msg;
 | 
				
			||||||
 | 
					    u->source->update_requested_latency = source_update_requested_latency_cb;
 | 
				
			||||||
    u->source->userdata = u;
 | 
					    u->source->userdata = u;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
 | 
					    pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
 | 
				
			||||||
| 
						 | 
					@ -1007,24 +1045,85 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
    u->hwbuf_size = u->fragment_size * nfrags;
 | 
					    u->hwbuf_size = u->fragment_size * nfrags;
 | 
				
			||||||
    u->tsched_watermark = tsched_watermark;
 | 
					    u->tsched_watermark = tsched_watermark;
 | 
				
			||||||
    u->frame_index = 0;
 | 
					    u->frame_index = 0;
 | 
				
			||||||
 | 
					    u->hw_dB_supported = FALSE;
 | 
				
			||||||
 | 
					    u->hw_dB_min = u->hw_dB_max = 0;
 | 
				
			||||||
 | 
					    u->hw_volume_min = u->hw_volume_max = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_log_info("Using %u fragments of size %lu bytes.", nfrags, (long unsigned) u->fragment_size);
 | 
					    if (!use_tsched)
 | 
				
			||||||
 | 
					        u->source->min_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
 | 
				
			||||||
 | 
					                nfrags, (long unsigned) u->fragment_size,
 | 
				
			||||||
 | 
					                (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (use_tsched)
 | 
				
			||||||
 | 
					        pa_log_info("Time scheduling watermark is %0.2fms",
 | 
				
			||||||
 | 
					                    (double) pa_bytes_to_usec(u->tsched_watermark, &ss) / PA_USEC_PER_MSEC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (update_sw_params(u) < 0)
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (u->mixer_handle) {
 | 
					    if (u->mixer_handle) {
 | 
				
			||||||
        pa_assert(u->mixer_elem);
 | 
					        pa_assert(u->mixer_elem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (snd_mixer_selem_has_capture_volume(u->mixer_elem))
 | 
					        if (snd_mixer_selem_has_capture_volume(u->mixer_elem))
 | 
				
			||||||
            if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0) {
 | 
					            if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0 &&
 | 
				
			||||||
 | 
					                snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) >= 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                pa_bool_t suitable = TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (u->hw_volume_min > u->hw_volume_max) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    pa_log_info("Minimal volume %li larger than maximum volume %li. Strange stuff Falling back to software volume control.", u->hw_volume_min, u->hw_volume_max);
 | 
				
			||||||
 | 
					                    suitable = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                } else if (u->hw_volume_max - u->hw_volume_min < 3) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
 | 
				
			||||||
 | 
					                    suitable = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                } else if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    /* Let's see if this thing actually is useful for muting */
 | 
				
			||||||
 | 
					                    if (u->hw_dB_min > -6000) {
 | 
				
			||||||
 | 
					                        pa_log_info("Device cannot attenuate for more than -60 dB (only %0.2f dB supported), falling back to software volume control.", ((double) u->hw_dB_min) / 100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        suitable = FALSE;
 | 
				
			||||||
 | 
					                    } else if (u->hw_dB_max < 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        pa_log_info("Device is still attenuated at maximum volume setting (%0.2f dB is maximum). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_max) / 100);
 | 
				
			||||||
 | 
					                        suitable = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    } else if (u->hw_dB_min >= u->hw_dB_max) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        pa_log_info("Minimal dB (%0.2f) larger or equal to maximum dB (%0.2f). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_min) / 100, ((double) u->hw_dB_max) / 100);
 | 
				
			||||||
 | 
					                        suitable = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    } else
 | 
				
			||||||
 | 
					                        u->hw_dB_supported = TRUE;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (suitable) {
 | 
				
			||||||
                    u->source->get_volume = source_get_volume_cb;
 | 
					                    u->source->get_volume = source_get_volume_cb;
 | 
				
			||||||
                    u->source->set_volume = source_set_volume_cb;
 | 
					                    u->source->set_volume = source_set_volume_cb;
 | 
				
			||||||
                snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
 | 
					                    u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SOURCE_DECIBEL_VOLUME : 0);
 | 
				
			||||||
                u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL;
 | 
					                    pa_log_info("Using hardware volume control. %s dB scale.", u->hw_dB_supported ? "Using" : "Not using");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
 | 
				
			||||||
 | 
					                    pa_alsa_0dB_capture(u->mixer_elem);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) {
 | 
					        if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) {
 | 
				
			||||||
            u->source->get_mute = source_get_mute_cb;
 | 
					            u->source->get_mute = source_get_mute_cb;
 | 
				
			||||||
            u->source->set_mute = source_set_mute_cb;
 | 
					            u->source->set_mute = source_set_mute_cb;
 | 
				
			||||||
            u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL;
 | 
					            u->source->flags |= PA_SOURCE_HW_MUTE_CTRL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        u->mixer_fdl = pa_alsa_fdlist_new();
 | 
					        u->mixer_fdl = pa_alsa_fdlist_new();
 | 
				
			||||||
| 
						 | 
					@ -1044,10 +1143,21 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /* Get initial mixer settings */
 | 
					    /* Get initial mixer settings */
 | 
				
			||||||
 | 
					    if (data.volume_is_set) {
 | 
				
			||||||
 | 
					        if (u->source->set_volume)
 | 
				
			||||||
 | 
					            u->source->set_volume(u->source);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
        if (u->source->get_volume)
 | 
					        if (u->source->get_volume)
 | 
				
			||||||
            u->source->get_volume(u->source);
 | 
					            u->source->get_volume(u->source);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (data.muted_is_set) {
 | 
				
			||||||
 | 
					        if (u->source->set_mute)
 | 
				
			||||||
 | 
					            u->source->set_mute(u->source);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
        if (u->source->get_mute)
 | 
					        if (u->source->get_mute)
 | 
				
			||||||
            u->source->get_mute(u->source);
 | 
					            u->source->get_mute(u->source);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_source_put(u->source);
 | 
					    pa_source_put(u->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -251,7 +251,7 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) {
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume) {
 | 
					int pa_oss_get_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, pa_cvolume *volume) {
 | 
				
			||||||
    char cv[PA_CVOLUME_SNPRINT_MAX];
 | 
					    char cv[PA_CVOLUME_SNPRINT_MAX];
 | 
				
			||||||
    unsigned vol;
 | 
					    unsigned vol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -273,7 +273,7 @@ int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *v
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa_oss_set_volume(int fd, long mixer, const pa_sample_spec *ss, const pa_cvolume *volume) {
 | 
					int pa_oss_set_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, const pa_cvolume *volume) {
 | 
				
			||||||
    char cv[PA_CVOLUME_SNPRINT_MAX];
 | 
					    char cv[PA_CVOLUME_SNPRINT_MAX];
 | 
				
			||||||
    unsigned vol;
 | 
					    unsigned vol;
 | 
				
			||||||
    pa_volume_t l, r;
 | 
					    pa_volume_t l, r;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,8 +33,8 @@ int pa_oss_auto_format(int fd, pa_sample_spec *ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa_oss_set_fragments(int fd, int frags, int frag_size);
 | 
					int pa_oss_set_fragments(int fd, int frags, int frag_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa_oss_set_volume(int fd, long mixer, const pa_sample_spec *ss, const pa_cvolume *volume);
 | 
					int pa_oss_set_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, const pa_cvolume *volume);
 | 
				
			||||||
int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume);
 | 
					int pa_oss_get_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, pa_cvolume *volume);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa_oss_get_hw_description(const char *dev, char *name, size_t l);
 | 
					int pa_oss_get_hw_description(const char *dev, char *name, size_t l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,16 +210,68 @@ typedef enum pa_stream_flags {
 | 
				
			||||||
                                     * on older servers. \since
 | 
					                                     * on older servers. \since
 | 
				
			||||||
                                     * 0.9.8 */
 | 
					                                     * 0.9.8 */
 | 
				
			||||||
    PA_STREAM_PEAK_DETECT = 2048, /**< Find peaks instead of
 | 
					    PA_STREAM_PEAK_DETECT = 2048, /**< Find peaks instead of
 | 
				
			||||||
                                   * resampling. \since 0.9.9 */
 | 
					                                   * resampling. \since 0.9.11 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PA_STREAM_START_MUTED = 4096,  /**< Create in muted state. \since 0.9.11 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PA_STREAM_ADJUST_LATENCY = 8192, /**< Try to adjust the latency of
 | 
				
			||||||
 | 
					                                      * the sink/source based on the
 | 
				
			||||||
 | 
					                                      * requested buffer metrics and
 | 
				
			||||||
 | 
					                                      * adjust buffer metrics
 | 
				
			||||||
 | 
					                                      * accordingly. \since 0.9.11 */
 | 
				
			||||||
} pa_stream_flags_t;
 | 
					} pa_stream_flags_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Playback and record buffer metrics */
 | 
					/** Playback and record buffer metrics */
 | 
				
			||||||
typedef struct pa_buffer_attr {
 | 
					typedef struct pa_buffer_attr {
 | 
				
			||||||
    uint32_t maxlength;      /**< Maximum length of the buffer */
 | 
					    uint32_t maxlength;      /**< Maximum length of the
 | 
				
			||||||
    uint32_t tlength;        /**< Playback only: target length of the buffer. The server tries to assure that at least tlength bytes are always available in the buffer */
 | 
					                              * buffer. Setting this to 0 will
 | 
				
			||||||
    uint32_t prebuf;         /**< Playback only: pre-buffering. The server does not start with playback before at least prebug bytes are available in the buffer */
 | 
					                              * initialize this to the maximum value
 | 
				
			||||||
    uint32_t minreq;         /**< Playback only: minimum request. The server does not request less than minreq bytes from the client, instead waints until the buffer is free enough to request more bytes at once */
 | 
					                              * supported by server, which is
 | 
				
			||||||
    uint32_t fragsize;       /**< Recording only: fragment size. The server sends data in blocks of fragsize bytes size. Large values deminish interactivity with other operations on the connection context but decrease control overhead. */
 | 
					                              * recommended. */
 | 
				
			||||||
 | 
					    uint32_t tlength;        /**< Playback only: target length of the
 | 
				
			||||||
 | 
					                              * buffer. The server tries to assure
 | 
				
			||||||
 | 
					                              * that at least tlength bytes are always
 | 
				
			||||||
 | 
					                              * available in the buffer. It is
 | 
				
			||||||
 | 
					                              * recommended to set this to 0, which
 | 
				
			||||||
 | 
					                              * will initialize this to a value that
 | 
				
			||||||
 | 
					                              * is deemed sensible by the
 | 
				
			||||||
 | 
					                              * server. However, this value will
 | 
				
			||||||
 | 
					                              * default to something like 2s, i.e. for
 | 
				
			||||||
 | 
					                              * applications that have specific
 | 
				
			||||||
 | 
					                              * latency requirements this value should
 | 
				
			||||||
 | 
					                              * be set to the maximum latency that the
 | 
				
			||||||
 | 
					                              * application can deal with.  */
 | 
				
			||||||
 | 
					    uint32_t prebuf;         /**< Playback only: pre-buffering. The
 | 
				
			||||||
 | 
					                              * server does not start with playback
 | 
				
			||||||
 | 
					                              * before at least prebug bytes are
 | 
				
			||||||
 | 
					                              * available in the buffer. It is
 | 
				
			||||||
 | 
					                              * recommended to set this to 0, which
 | 
				
			||||||
 | 
					                              * will initialize this to the same value
 | 
				
			||||||
 | 
					                              * as tlength, whatever that may be. */
 | 
				
			||||||
 | 
					    uint32_t minreq;         /**< Playback only: minimum request. The
 | 
				
			||||||
 | 
					                              * server does not request less than
 | 
				
			||||||
 | 
					                              * minreq bytes from the client, instead
 | 
				
			||||||
 | 
					                              * waits until the buffer is free enough
 | 
				
			||||||
 | 
					                              * to request more bytes at once. It is
 | 
				
			||||||
 | 
					                              * recommended to set this to 0, which
 | 
				
			||||||
 | 
					                              * will initialize this to a value that
 | 
				
			||||||
 | 
					                              * is deemed sensible by the server. */
 | 
				
			||||||
 | 
					    uint32_t fragsize;       /**< Recording only: fragment size. The
 | 
				
			||||||
 | 
					                              * server sends data in blocks of
 | 
				
			||||||
 | 
					                              * fragsize bytes size. Large values
 | 
				
			||||||
 | 
					                              * deminish interactivity with other
 | 
				
			||||||
 | 
					                              * operations on the connection context
 | 
				
			||||||
 | 
					                              * but decrease control overhead. It is
 | 
				
			||||||
 | 
					                              * recommended to set this to 0, which
 | 
				
			||||||
 | 
					                              * will initialize this to a value that
 | 
				
			||||||
 | 
					                              * is deemed sensible by the
 | 
				
			||||||
 | 
					                              * server. However, this value will
 | 
				
			||||||
 | 
					                              * default to something like 2s, i.e. for
 | 
				
			||||||
 | 
					                              * applications that have specific
 | 
				
			||||||
 | 
					                              * latency requirements this value should
 | 
				
			||||||
 | 
					                              * be set to the maximum latency that the
 | 
				
			||||||
 | 
					                              * application can deal with. */
 | 
				
			||||||
} pa_buffer_attr;
 | 
					} pa_buffer_attr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Error values as used by pa_context_errno(). Use pa_strerror() to convert these values to human readable strings */
 | 
					/** Error values as used by pa_context_errno(). Use pa_strerror() to convert these values to human readable strings */
 | 
				
			||||||
| 
						 | 
					@ -299,7 +351,9 @@ typedef enum pa_subscription_event_type {
 | 
				
			||||||
 * source_usec+buffer_usec+transport_usec-sink_usec. (Take care of
 | 
					 * source_usec+buffer_usec+transport_usec-sink_usec. (Take care of
 | 
				
			||||||
 * sign issues!) When connected to a monitor source sink_usec contains
 | 
					 * sign issues!) When connected to a monitor source sink_usec contains
 | 
				
			||||||
 * the latency of the owning sink. The two latency estimations
 | 
					 * the latency of the owning sink. The two latency estimations
 | 
				
			||||||
 * described here are implemented in pa_stream_get_latency().*/
 | 
					 * described here are implemented in pa_stream_get_latency(). Please
 | 
				
			||||||
 | 
					 * note that this structure can be extended as part of evolutionary
 | 
				
			||||||
 | 
					 * API updates at any time in any new release.*/
 | 
				
			||||||
typedef struct pa_timing_info {
 | 
					typedef struct pa_timing_info {
 | 
				
			||||||
    struct timeval timestamp; /**< The time when this timing info structure was current */
 | 
					    struct timeval timestamp; /**< The time when this timing info structure was current */
 | 
				
			||||||
    int synchronized_clocks;  /**< Non-zero if the local and the
 | 
					    int synchronized_clocks;  /**< Non-zero if the local and the
 | 
				
			||||||
| 
						 | 
					@ -346,6 +400,11 @@ typedef struct pa_timing_info {
 | 
				
			||||||
                               * want to use it. Consider using
 | 
					                               * want to use it. Consider using
 | 
				
			||||||
                               * PA_SEEK_RELATIVE_ON_READ
 | 
					                               * PA_SEEK_RELATIVE_ON_READ
 | 
				
			||||||
                               * instead. \since 0.8 */
 | 
					                               * instead. \since 0.8 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_usec_t max_sink_usec;   /**< The static configure latency for
 | 
				
			||||||
 | 
					                                * the sink. \since 0.9.10 */
 | 
				
			||||||
 | 
					    pa_usec_t max_source_usec; /**< The static configure latency for
 | 
				
			||||||
 | 
					                                * the source. \since 0.9.10 */
 | 
				
			||||||
} pa_timing_info;
 | 
					} pa_timing_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** A structure for the spawn api. This may be used to integrate auto
 | 
					/** A structure for the spawn api. This may be used to integrate auto
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,6 +149,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while (!pa_tagstruct_eof(t)) {
 | 
					        while (!pa_tagstruct_eof(t)) {
 | 
				
			||||||
            pa_sink_info i;
 | 
					            pa_sink_info i;
 | 
				
			||||||
 | 
					            pa_bool_t mute = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            memset(&i, 0, sizeof(i));
 | 
					            memset(&i, 0, sizeof(i));
 | 
				
			||||||
            i.proplist = pa_proplist_new();
 | 
					            i.proplist = pa_proplist_new();
 | 
				
			||||||
| 
						 | 
					@ -160,7 +161,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
 | 
				
			||||||
                pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
 | 
					                pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
 | 
				
			||||||
                pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
 | 
					                pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
 | 
				
			||||||
                pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
 | 
					                pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
 | 
				
			||||||
                pa_tagstruct_get_boolean(t, &i.mute) < 0 ||
 | 
					                pa_tagstruct_get_boolean(t, &mute) < 0 ||
 | 
				
			||||||
                pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
 | 
					                pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
 | 
				
			||||||
                pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
 | 
					                pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
 | 
				
			||||||
                pa_tagstruct_get_usec(t, &i.latency) < 0 ||
 | 
					                pa_tagstruct_get_usec(t, &i.latency) < 0 ||
 | 
				
			||||||
| 
						 | 
					@ -173,6 +174,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
 | 
				
			||||||
                goto finish;
 | 
					                goto finish;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            i.mute = (int) mute;
 | 
				
			||||||
            i.flags = (pa_sink_flags_t) flags;
 | 
					            i.flags = (pa_sink_flags_t) flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (o->callback) {
 | 
					            if (o->callback) {
 | 
				
			||||||
| 
						 | 
					@ -266,6 +268,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
        while (!pa_tagstruct_eof(t)) {
 | 
					        while (!pa_tagstruct_eof(t)) {
 | 
				
			||||||
            pa_source_info i;
 | 
					            pa_source_info i;
 | 
				
			||||||
            uint32_t flags;
 | 
					            uint32_t flags;
 | 
				
			||||||
 | 
					            pa_bool_t mute = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            memset(&i, 0, sizeof(i));
 | 
					            memset(&i, 0, sizeof(i));
 | 
				
			||||||
            i.proplist = pa_proplist_new();
 | 
					            i.proplist = pa_proplist_new();
 | 
				
			||||||
| 
						 | 
					@ -277,7 +280,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
                pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
 | 
					                pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
 | 
				
			||||||
                pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
 | 
					                pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
 | 
				
			||||||
                pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
 | 
					                pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
 | 
				
			||||||
                pa_tagstruct_get_boolean(t, &i.mute) < 0 ||
 | 
					                pa_tagstruct_get_boolean(t, &mute) < 0 ||
 | 
				
			||||||
                pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
 | 
					                pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
 | 
				
			||||||
                pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
 | 
					                pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
 | 
				
			||||||
                pa_tagstruct_get_usec(t, &i.latency) < 0 ||
 | 
					                pa_tagstruct_get_usec(t, &i.latency) < 0 ||
 | 
				
			||||||
| 
						 | 
					@ -290,6 +293,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
                goto finish;
 | 
					                goto finish;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            i.mute = (int) mute;
 | 
				
			||||||
            i.flags = (pa_source_flags_t) flags;
 | 
					            i.flags = (pa_source_flags_t) flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (o->callback) {
 | 
					            if (o->callback) {
 | 
				
			||||||
| 
						 | 
					@ -464,17 +468,20 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while (!pa_tagstruct_eof(t)) {
 | 
					        while (!pa_tagstruct_eof(t)) {
 | 
				
			||||||
            pa_module_info i;
 | 
					            pa_module_info i;
 | 
				
			||||||
 | 
					            pa_bool_t auto_unload = FALSE;
 | 
				
			||||||
            memset(&i, 0, sizeof(i));
 | 
					            memset(&i, 0, sizeof(i));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (pa_tagstruct_getu32(t, &i.index) < 0 ||
 | 
					            if (pa_tagstruct_getu32(t, &i.index) < 0 ||
 | 
				
			||||||
                pa_tagstruct_gets(t, &i.name) < 0 ||
 | 
					                pa_tagstruct_gets(t, &i.name) < 0 ||
 | 
				
			||||||
                pa_tagstruct_gets(t, &i.argument) < 0 ||
 | 
					                pa_tagstruct_gets(t, &i.argument) < 0 ||
 | 
				
			||||||
                pa_tagstruct_getu32(t, &i.n_used) < 0 ||
 | 
					                pa_tagstruct_getu32(t, &i.n_used) < 0 ||
 | 
				
			||||||
                pa_tagstruct_get_boolean(t, &i.auto_unload) < 0) {
 | 
					                pa_tagstruct_get_boolean(t, &auto_unload) < 0) {
 | 
				
			||||||
                pa_context_fail(o->context, PA_ERR_PROTOCOL);
 | 
					                pa_context_fail(o->context, PA_ERR_PROTOCOL);
 | 
				
			||||||
                goto finish;
 | 
					                goto finish;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            i.auto_unload = (int) auto_unload;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (o->callback) {
 | 
					            if (o->callback) {
 | 
				
			||||||
                pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
 | 
					                pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
 | 
				
			||||||
                cb(o->context, &i, 0, o->userdata);
 | 
					                cb(o->context, &i, 0, o->userdata);
 | 
				
			||||||
| 
						 | 
					@ -540,6 +547,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while (!pa_tagstruct_eof(t)) {
 | 
					        while (!pa_tagstruct_eof(t)) {
 | 
				
			||||||
            pa_sink_input_info i;
 | 
					            pa_sink_input_info i;
 | 
				
			||||||
 | 
					            pa_bool_t mute = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            memset(&i, 0, sizeof(i));
 | 
					            memset(&i, 0, sizeof(i));
 | 
				
			||||||
            i.proplist = pa_proplist_new();
 | 
					            i.proplist = pa_proplist_new();
 | 
				
			||||||
| 
						 | 
					@ -556,7 +564,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
 | 
				
			||||||
                pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
 | 
					                pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
 | 
				
			||||||
                pa_tagstruct_gets(t, &i.resample_method) < 0 ||
 | 
					                pa_tagstruct_gets(t, &i.resample_method) < 0 ||
 | 
				
			||||||
                pa_tagstruct_gets(t, &i.driver) < 0 ||
 | 
					                pa_tagstruct_gets(t, &i.driver) < 0 ||
 | 
				
			||||||
                (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &i.mute) < 0) ||
 | 
					                (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &mute) < 0) ||
 | 
				
			||||||
                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 | 
					                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                pa_context_fail(o->context, PA_ERR_PROTOCOL);
 | 
					                pa_context_fail(o->context, PA_ERR_PROTOCOL);
 | 
				
			||||||
| 
						 | 
					@ -564,6 +572,8 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
 | 
				
			||||||
                goto finish;
 | 
					                goto finish;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            i.mute = (int) mute;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (o->callback) {
 | 
					            if (o->callback) {
 | 
				
			||||||
                pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
 | 
					                pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
 | 
				
			||||||
                cb(o->context, &i, 0, o->userdata);
 | 
					                cb(o->context, &i, 0, o->userdata);
 | 
				
			||||||
| 
						 | 
					@ -961,6 +971,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while (!pa_tagstruct_eof(t)) {
 | 
					        while (!pa_tagstruct_eof(t)) {
 | 
				
			||||||
            pa_sample_info i;
 | 
					            pa_sample_info i;
 | 
				
			||||||
 | 
					            pa_bool_t lazy = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            memset(&i, 0, sizeof(i));
 | 
					            memset(&i, 0, sizeof(i));
 | 
				
			||||||
            i.proplist = pa_proplist_new();
 | 
					            i.proplist = pa_proplist_new();
 | 
				
			||||||
| 
						 | 
					@ -972,7 +983,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
                pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
 | 
					                pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
 | 
				
			||||||
                pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
 | 
					                pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
 | 
				
			||||||
                pa_tagstruct_getu32(t, &i.bytes) < 0 ||
 | 
					                pa_tagstruct_getu32(t, &i.bytes) < 0 ||
 | 
				
			||||||
                pa_tagstruct_get_boolean(t, &i.lazy) < 0 ||
 | 
					                pa_tagstruct_get_boolean(t, &lazy) < 0 ||
 | 
				
			||||||
                pa_tagstruct_gets(t, &i.filename) < 0 ||
 | 
					                pa_tagstruct_gets(t, &i.filename) < 0 ||
 | 
				
			||||||
                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 | 
					                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -980,6 +991,8 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
                goto finish;
 | 
					                goto finish;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            i.lazy = (int) lazy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (o->callback) {
 | 
					            if (o->callback) {
 | 
				
			||||||
                pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
 | 
					                pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
 | 
				
			||||||
                cb(o->context, &i, 0, o->userdata);
 | 
					                cb(o->context, &i, 0, o->userdata);
 | 
				
			||||||
| 
						 | 
					@ -1192,6 +1205,8 @@ finish:
 | 
				
			||||||
    pa_operation_unref(o);
 | 
					    pa_operation_unref(o);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PA_WARN_REFERENCE(pa_context_get_autoload_info_by_name, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata) {
 | 
					pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata) {
 | 
				
			||||||
    pa_tagstruct *t;
 | 
					    pa_tagstruct *t;
 | 
				
			||||||
    pa_operation *o;
 | 
					    pa_operation *o;
 | 
				
			||||||
| 
						 | 
					@ -1216,6 +1231,8 @@ pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *na
 | 
				
			||||||
    return o;
 | 
					    return o;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PA_WARN_REFERENCE(pa_context_get_autoload_info_by_index, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata) {
 | 
					pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata) {
 | 
				
			||||||
    pa_tagstruct *t;
 | 
					    pa_tagstruct *t;
 | 
				
			||||||
    pa_operation *o;
 | 
					    pa_operation *o;
 | 
				
			||||||
| 
						 | 
					@ -1238,10 +1255,15 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx,
 | 
				
			||||||
    return o;
 | 
					    return o;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PA_WARN_REFERENCE(pa_context_get_autoload_info_list, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata) {
 | 
					pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata) {
 | 
				
			||||||
    return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, (pa_operation_cb_t) cb, userdata);
 | 
					    return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, (pa_operation_cb_t) cb, userdata);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PA_WARN_REFERENCE(pa_context_add_autoload, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t cb, void* userdata) {
 | 
					pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t cb, void* userdata) {
 | 
				
			||||||
    pa_operation *o;
 | 
					    pa_operation *o;
 | 
				
			||||||
    pa_tagstruct *t;
 | 
					    pa_tagstruct *t;
 | 
				
			||||||
| 
						 | 
					@ -1268,6 +1290,8 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo
 | 
				
			||||||
    return o;
 | 
					    return o;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PA_WARN_REFERENCE(pa_context_remove_autoload_by_name, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata) {
 | 
					pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata) {
 | 
				
			||||||
    pa_operation *o;
 | 
					    pa_operation *o;
 | 
				
			||||||
    pa_tagstruct *t;
 | 
					    pa_tagstruct *t;
 | 
				
			||||||
| 
						 | 
					@ -1291,6 +1315,8 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name
 | 
				
			||||||
    return o;
 | 
					    return o;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PA_WARN_REFERENCE(pa_context_remove_autoload_by_index, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata) {
 | 
					pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata) {
 | 
				
			||||||
    pa_operation *o;
 | 
					    pa_operation *o;
 | 
				
			||||||
    pa_tagstruct *t;
 | 
					    pa_tagstruct *t;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,7 +212,11 @@ PA_C_DECL_BEGIN
 | 
				
			||||||
#define PA_PORT_ANALOG_5_1 "analog-5-1"
 | 
					#define PA_PORT_ANALOG_5_1 "analog-5-1"
 | 
				
			||||||
#define PA_PORT_ANALOG_4_0 "analog-4-0"
 | 
					#define PA_PORT_ANALOG_4_0 "analog-4-0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Stores information about sinks */
 | 
					/** @{ \name Sinks */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Stores information about sinks. Please note that this structure
 | 
				
			||||||
 | 
					 * can be extended as part of evolutionary API updates at any time in
 | 
				
			||||||
 | 
					 * any new release. */
 | 
				
			||||||
typedef struct pa_sink_info {
 | 
					typedef struct pa_sink_info {
 | 
				
			||||||
    const char *name;                  /**< Name of the sink */
 | 
					    const char *name;                  /**< Name of the sink */
 | 
				
			||||||
    uint32_t index;                    /**< Index of the sink */
 | 
					    uint32_t index;                    /**< Index of the sink */
 | 
				
			||||||
| 
						 | 
					@ -224,10 +228,11 @@ typedef struct pa_sink_info {
 | 
				
			||||||
    int mute;                          /**< Mute switch of the sink \since 0.8 */
 | 
					    int mute;                          /**< Mute switch of the sink \since 0.8 */
 | 
				
			||||||
    uint32_t monitor_source;           /**< Index of the monitor source connected to this sink */
 | 
					    uint32_t monitor_source;           /**< Index of the monitor source connected to this sink */
 | 
				
			||||||
    const char *monitor_source_name;   /**< The name of the monitor source */
 | 
					    const char *monitor_source_name;   /**< The name of the monitor source */
 | 
				
			||||||
    pa_usec_t latency;                 /**< Length of filled playback buffer of this sink */
 | 
					    pa_usec_t latency;                 /**< Length of queued audio in the output buffer. */
 | 
				
			||||||
    const char *driver;                /**< Driver name. \since 0.8 */
 | 
					    const char *driver;                /**< Driver name. \since 0.8 */
 | 
				
			||||||
    pa_sink_flags_t flags;             /**< Flags \since 0.8 */
 | 
					    pa_sink_flags_t flags;             /**< Flags \since 0.8 */
 | 
				
			||||||
    pa_proplist *proplist;             /**< Property list \since 0.9.10 */
 | 
					    pa_proplist *proplist;             /**< Property list \since 0.9.11 */
 | 
				
			||||||
 | 
					    pa_usec_t max_latency;             /**< The static latency this device has been configured to. \since 0.9.11 */
 | 
				
			||||||
} pa_sink_info;
 | 
					} pa_sink_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Callback prototype for pa_context_get_sink_info_by_name() and friends */
 | 
					/** Callback prototype for pa_context_get_sink_info_by_name() and friends */
 | 
				
			||||||
| 
						 | 
					@ -242,7 +247,31 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t id, pa_s
 | 
				
			||||||
/** Get the complete sink list */
 | 
					/** Get the complete sink list */
 | 
				
			||||||
pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Stores information about sources */
 | 
					/** Set the volume of a sink device specified by its index */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Set the volume of a sink device specified by its name */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Set the mute switch of a sink device specified by its index \since 0.8 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Set the mute switch of a sink device specified by its name \since 0.8 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Suspend/Resume a sink. \since 0.9.7 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_suspend_sink_by_name(pa_context *c, char *sink_name, int suspend, pa_context_success_cb_t cb, void* userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Suspend/Resume a sink. If idx is PA_INVALID_INDEX all sinks will be suspended. \since 0.9.7 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend,  pa_context_success_cb_t cb, void* userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @{ \name Sources */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Stores information about sources. Please note that this structure
 | 
				
			||||||
 | 
					 * can be extended as part of evolutionary API updates at any time in
 | 
				
			||||||
 | 
					 * any new release. */
 | 
				
			||||||
typedef struct pa_source_info {
 | 
					typedef struct pa_source_info {
 | 
				
			||||||
    const char *name;                   /**< Name of the source */
 | 
					    const char *name;                   /**< Name of the source */
 | 
				
			||||||
    uint32_t index;                     /**< Index of the source */
 | 
					    uint32_t index;                     /**< Index of the source */
 | 
				
			||||||
| 
						 | 
					@ -258,6 +287,7 @@ typedef struct pa_source_info {
 | 
				
			||||||
    const char *driver;                 /**< Driver name \since 0.8 */
 | 
					    const char *driver;                 /**< Driver name \since 0.8 */
 | 
				
			||||||
    pa_source_flags_t flags;            /**< Flags \since 0.8 */
 | 
					    pa_source_flags_t flags;            /**< Flags \since 0.8 */
 | 
				
			||||||
    pa_proplist *proplist;              /**< Property list \since 0.9.10 */
 | 
					    pa_proplist *proplist;              /**< Property list \since 0.9.10 */
 | 
				
			||||||
 | 
					    pa_usec_t max_latency;              /**< The static latency this device has been configured to. \since 0.9.11 */
 | 
				
			||||||
} pa_source_info;
 | 
					} pa_source_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Callback prototype for pa_context_get_source_info_by_name() and friends */
 | 
					/** Callback prototype for pa_context_get_source_info_by_name() and friends */
 | 
				
			||||||
| 
						 | 
					@ -272,7 +302,25 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t id, pa
 | 
				
			||||||
/** Get the complete source list */
 | 
					/** Get the complete source list */
 | 
				
			||||||
pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Server information */
 | 
					/** Set the volume of a source device specified by its index \since 0.8 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Set the volume of a source device specified by its name \since 0.8 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Set the mute switch of a source device specified by its index \since 0.8 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Set the mute switch of a source device specified by its name \since 0.8 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @{ \name Server */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Server information. Please note that this structure can be
 | 
				
			||||||
 | 
					 * extended as part of evolutionary API updates at any time in any new
 | 
				
			||||||
 | 
					 * release. */
 | 
				
			||||||
typedef struct pa_server_info {
 | 
					typedef struct pa_server_info {
 | 
				
			||||||
    const char *user_name;              /**< User name of the daemon process */
 | 
					    const char *user_name;              /**< User name of the daemon process */
 | 
				
			||||||
    const char *host_name;              /**< Host name the daemon is running on */
 | 
					    const char *host_name;              /**< Host name the daemon is running on */
 | 
				
			||||||
| 
						 | 
					@ -290,7 +338,13 @@ typedef void (*pa_server_info_cb_t) (pa_context *c, const pa_server_info*i, void
 | 
				
			||||||
/** Get some information about the server */
 | 
					/** Get some information about the server */
 | 
				
			||||||
pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Stores information about modules */
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @{ \name Modules */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Stores information about modules. Please note that this structure
 | 
				
			||||||
 | 
					 * can be extended as part of evolutionary API updates at any time in
 | 
				
			||||||
 | 
					 * any new release. */
 | 
				
			||||||
typedef struct pa_module_info {
 | 
					typedef struct pa_module_info {
 | 
				
			||||||
    uint32_t index;                     /**< Index of the module */
 | 
					    uint32_t index;                     /**< Index of the module */
 | 
				
			||||||
    const char*name,                    /**< Name of the module */
 | 
					    const char*name,                    /**< Name of the module */
 | 
				
			||||||
| 
						 | 
					@ -308,7 +362,22 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_
 | 
				
			||||||
/** Get the complete list of currently loaded modules */
 | 
					/** Get the complete list of currently loaded modules */
 | 
				
			||||||
pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Stores information about clients */
 | 
					/** Callback prototype for pa_context_load_module() */
 | 
				
			||||||
 | 
					typedef void (*pa_context_index_cb_t)(pa_context *c, uint32_t idx, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Load a module. \since 0.5 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Unload a module. \since 0.5 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @{ \name Clients */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Stores information about clients. Please note that this structure
 | 
				
			||||||
 | 
					 * can be extended as part of evolutionary API updates at any time in
 | 
				
			||||||
 | 
					 * any new release. */
 | 
				
			||||||
typedef struct pa_client_info {
 | 
					typedef struct pa_client_info {
 | 
				
			||||||
    uint32_t index;                      /**< Index of this client */
 | 
					    uint32_t index;                      /**< Index of this client */
 | 
				
			||||||
    const char *name;                    /**< Name of this client */
 | 
					    const char *name;                    /**< Name of this client */
 | 
				
			||||||
| 
						 | 
					@ -326,7 +395,16 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_
 | 
				
			||||||
/** Get the complete client list */
 | 
					/** Get the complete client list */
 | 
				
			||||||
pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Stores information about sink inputs */
 | 
					/** Kill a client. \since 0.5 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @{ \name Sink Inputs */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Stores information about sink inputs. Please note that this structure
 | 
				
			||||||
 | 
					 * can be extended as part of evolutionary API updates at any time in
 | 
				
			||||||
 | 
					 * any new release. */
 | 
				
			||||||
typedef struct pa_sink_input_info {
 | 
					typedef struct pa_sink_input_info {
 | 
				
			||||||
    uint32_t index;                      /**< Index of the sink input */
 | 
					    uint32_t index;                      /**< Index of the sink input */
 | 
				
			||||||
    const char *name;                    /**< Name of the sink input */
 | 
					    const char *name;                    /**< Name of the sink input */
 | 
				
			||||||
| 
						 | 
					@ -353,7 +431,28 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin
 | 
				
			||||||
/** Get the complete sink input list */
 | 
					/** Get the complete sink input list */
 | 
				
			||||||
pa_operation* pa_context_get_sink_input_info_list(pa_context *c, pa_sink_input_info_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_get_sink_input_info_list(pa_context *c, pa_sink_input_info_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Stores information about source outputs */
 | 
					/** Move the specified sink input to a different sink. \since 0.9.5 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, char *sink_name, pa_context_success_cb_t cb, void* userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Move the specified sink input to a different sink. \since 0.9.5 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Set the volume of a sink input stream */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Set the mute switch of a sink input stream \since 0.9.7 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Kill a sink input. \since 0.5 */
 | 
				
			||||||
 | 
					pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @{ \name Source Outputs */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Stores information about source outputs. Please note that this structure
 | 
				
			||||||
 | 
					 * can be extended as part of evolutionary API updates at any time in
 | 
				
			||||||
 | 
					 * any new release. */
 | 
				
			||||||
typedef struct pa_source_output_info {
 | 
					typedef struct pa_source_output_info {
 | 
				
			||||||
    uint32_t index;                      /**< Index of the sink input */
 | 
					    uint32_t index;                      /**< Index of the sink input */
 | 
				
			||||||
    const char *name;                    /**< Name of the sink input */
 | 
					    const char *name;                    /**< Name of the sink input */
 | 
				
			||||||
| 
						 | 
					@ -378,37 +477,28 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_
 | 
				
			||||||
/** Get the complete list of source outputs */
 | 
					/** Get the complete list of source outputs */
 | 
				
			||||||
pa_operation* pa_context_get_source_output_info_list(pa_context *c, pa_source_output_info_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_get_source_output_info_list(pa_context *c, pa_source_output_info_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Set the volume of a sink device specified by its index */
 | 
					/** Move the specified source output to a different source. \since 0.9.5 */
 | 
				
			||||||
pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, char *source_name, pa_context_success_cb_t cb, void* userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Set the volume of a sink device specified by its name */
 | 
					/** Move the specified source output to a different source. \since 0.9.5 */
 | 
				
			||||||
pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Set the mute switch of a sink device specified by its index \since 0.8 */
 | 
					/** Suspend/Resume a source. \since 0.9.7 */
 | 
				
			||||||
pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_suspend_source_by_name(pa_context *c, char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Set the mute switch of a sink device specified by its name \since 0.8 */
 | 
					/** Suspend/Resume a source. If idx is PA_INVALID_INDEX all sources will be suspended. \since 0.9.7 */
 | 
				
			||||||
pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Set the volume of a sink input stream */
 | 
					/** Kill a source output. \since 0.5 */
 | 
				
			||||||
pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Set the mute switch of a sink input stream \since 0.9.7 */
 | 
					/** @} */
 | 
				
			||||||
pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Set the volume of a source device specified by its index \since 0.8 */
 | 
					/** @{ \name Statistics */
 | 
				
			||||||
pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Set the volume of a source device specified by its name \since 0.8 */
 | 
					/** Memory block statistics. Please note that this structure
 | 
				
			||||||
pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 | 
					 * can be extended as part of evolutionary API updates at any time in
 | 
				
			||||||
 | 
					 * any new release. */
 | 
				
			||||||
/** Set the mute switch of a source device specified by its index \since 0.8 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Set the mute switch of a source device specified by its name \since 0.8 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Memory block statistics */
 | 
					 | 
				
			||||||
typedef struct pa_stat_info {
 | 
					typedef struct pa_stat_info {
 | 
				
			||||||
    uint32_t memblock_total;           /**< Currently allocated memory blocks */
 | 
					    uint32_t memblock_total;           /**< Currently allocated memory blocks */
 | 
				
			||||||
    uint32_t memblock_total_size;      /**< Currentl total size of allocated memory blocks */
 | 
					    uint32_t memblock_total_size;      /**< Currentl total size of allocated memory blocks */
 | 
				
			||||||
| 
						 | 
					@ -423,7 +513,13 @@ typedef void (*pa_stat_info_cb_t) (pa_context *c, const pa_stat_info *i, void *u
 | 
				
			||||||
/** Get daemon memory block statistics */
 | 
					/** Get daemon memory block statistics */
 | 
				
			||||||
pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Stores information about sample cache entries */
 | 
					/** @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @{ \name Cached Samples */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Stores information about sample cache entries. Please note that this structure
 | 
				
			||||||
 | 
					 * can be extended as part of evolutionary API updates at any time in
 | 
				
			||||||
 | 
					 * any new release. */
 | 
				
			||||||
typedef struct pa_sample_info {
 | 
					typedef struct pa_sample_info {
 | 
				
			||||||
    uint32_t index;                       /**< Index of this entry */
 | 
					    uint32_t index;                       /**< Index of this entry */
 | 
				
			||||||
    const char *name;                     /**< Name of this entry */
 | 
					    const char *name;                     /**< Name of this entry */
 | 
				
			||||||
| 
						 | 
					@ -449,23 +545,11 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, p
 | 
				
			||||||
/** Get the complete list of samples stored in the daemon. */
 | 
					/** Get the complete list of samples stored in the daemon. */
 | 
				
			||||||
pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t cb, void *userdata);
 | 
					pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t cb, void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Kill a client. \since 0.5 */
 | 
					/** @} */
 | 
				
			||||||
pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Kill a sink input. \since 0.5 */
 | 
					/** \cond fulldocs */
 | 
				
			||||||
pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Kill a source output. \since 0.5 */
 | 
					/** @{ \name Autoload Entries */
 | 
				
			||||||
pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Callback prototype for pa_context_load_module() and pa_context_add_autoload() */
 | 
					 | 
				
			||||||
typedef void (*pa_context_index_cb_t)(pa_context *c, uint32_t idx, void *userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Load a module. \since 0.5 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Unload a module. \since 0.5 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Type of an autoload entry. \since 0.5 */
 | 
					/** Type of an autoload entry. \since 0.5 */
 | 
				
			||||||
typedef enum pa_autoload_type {
 | 
					typedef enum pa_autoload_type {
 | 
				
			||||||
| 
						 | 
					@ -473,7 +557,9 @@ typedef enum pa_autoload_type {
 | 
				
			||||||
    PA_AUTOLOAD_SOURCE = 1
 | 
					    PA_AUTOLOAD_SOURCE = 1
 | 
				
			||||||
} pa_autoload_type_t;
 | 
					} pa_autoload_type_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Stores information about autoload entries. \since 0.5 */
 | 
					/** Stores information about autoload entries. Please note that this structure
 | 
				
			||||||
 | 
					 * can be extended as part of evolutionary API updates at any time in
 | 
				
			||||||
 | 
					 * any new release. \since 0.5 */
 | 
				
			||||||
typedef struct pa_autoload_info {
 | 
					typedef struct pa_autoload_info {
 | 
				
			||||||
    uint32_t index;               /**< Index of this autoload entry */
 | 
					    uint32_t index;               /**< Index of this autoload entry */
 | 
				
			||||||
    const char *name;             /**< Name of the sink or source */
 | 
					    const char *name;             /**< Name of the sink or source */
 | 
				
			||||||
| 
						 | 
					@ -503,29 +589,9 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name
 | 
				
			||||||
/** Remove an autoload entry. \since 0.6 */
 | 
					/** Remove an autoload entry. \since 0.6 */
 | 
				
			||||||
pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata);
 | 
					pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Move the specified sink input to a different sink. \since 0.9.5 */
 | 
					/** @} */
 | 
				
			||||||
pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, char *sink_name, pa_context_success_cb_t cb, void* userdata);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Move the specified sink input to a different sink. \since 0.9.5 */
 | 
					/** \endcond */
 | 
				
			||||||
pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Move the specified source output to a different source. \since 0.9.5 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, char *source_name, pa_context_success_cb_t cb, void* userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Move the specified source output to a different source. \since 0.9.5 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Suspend/Resume a sink. \since 0.9.7 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_suspend_sink_by_name(pa_context *c, char *sink_name, int suspend, pa_context_success_cb_t cb, void* userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Suspend/Resume a sink. If idx is PA_INVALID_INDEX all sinks will be suspended. \since 0.9.7 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend,  pa_context_success_cb_t cb, void* userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Suspend/Resume a source. \since 0.9.7 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_suspend_source_by_name(pa_context *c, char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Suspend/Resume a source. If idx is PA_INVALID_INDEX all sources will be suspended. \since 0.9.7 */
 | 
					 | 
				
			||||||
pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
PA_C_DECL_END
 | 
					PA_C_DECL_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,7 +292,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
 | 
				
			||||||
    pa_stream *s;
 | 
					    pa_stream *s;
 | 
				
			||||||
    uint32_t channel;
 | 
					    uint32_t channel;
 | 
				
			||||||
    const char *dn;
 | 
					    const char *dn;
 | 
				
			||||||
    int suspended;
 | 
					    pa_bool_t suspended;
 | 
				
			||||||
    uint32_t di;
 | 
					    uint32_t di;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(pd);
 | 
					    pa_assert(pd);
 | 
				
			||||||
| 
						 | 
					@ -342,7 +342,7 @@ void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUS
 | 
				
			||||||
    pa_context *c = userdata;
 | 
					    pa_context *c = userdata;
 | 
				
			||||||
    pa_stream *s;
 | 
					    pa_stream *s;
 | 
				
			||||||
    uint32_t channel;
 | 
					    uint32_t channel;
 | 
				
			||||||
    int suspended;
 | 
					    pa_bool_t suspended;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(pd);
 | 
					    pa_assert(pd);
 | 
				
			||||||
    pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED || command == PA_COMMAND_RECORD_STREAM_SUSPENDED);
 | 
					    pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED || command == PA_COMMAND_RECORD_STREAM_SUSPENDED);
 | 
				
			||||||
| 
						 | 
					@ -543,15 +543,31 @@ static void create_stream_complete(pa_stream *s) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void automatic_buffer_attr(pa_buffer_attr *attr, pa_sample_spec *ss) {
 | 
					static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_sample_spec *ss) {
 | 
				
			||||||
 | 
					    pa_assert(s);
 | 
				
			||||||
    pa_assert(attr);
 | 
					    pa_assert(attr);
 | 
				
			||||||
    pa_assert(ss);
 | 
					    pa_assert(ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    attr->tlength = pa_bytes_per_second(ss)/2;
 | 
					    if (s->context->version >= 13)
 | 
				
			||||||
    attr->maxlength = (attr->tlength*3)/2;
 | 
					        return;
 | 
				
			||||||
    attr->minreq = attr->tlength/50;
 | 
					
 | 
				
			||||||
    attr->prebuf = attr->tlength - attr->minreq;
 | 
					    /* Version older than 0.9.10 didn't do server side buffer_attr
 | 
				
			||||||
    attr->fragsize = attr->tlength/50;
 | 
					     * selection, hence we have to fake it on the client side */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!attr->maxlength <= 0)
 | 
				
			||||||
 | 
					        attr->maxlength = 4*1024*1024; /* 4MB is the maximum queue length PulseAudio <= 0.9.9 supported. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!attr->tlength <= 0)
 | 
				
			||||||
 | 
					        attr->tlength = pa_bytes_per_second(ss)*2; /* 2s of buffering */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!attr->minreq <= 0)
 | 
				
			||||||
 | 
					        attr->minreq = (9*attr->tlength)/10; /* Ask for more data when there are only 200ms left in the playback buffer */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!attr->prebuf)
 | 
				
			||||||
 | 
					        attr->prebuf = attr->tlength; /* Start to play only when the playback is fully filled up once */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!attr->fragsize)
 | 
				
			||||||
 | 
					        attr->fragsize  = attr->tlength; /* Pass data to the app only when the buffer is filled up once */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
 | 
					void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
 | 
				
			||||||
| 
						 | 
					@ -601,7 +617,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
 | 
				
			||||||
        pa_sample_spec ss;
 | 
					        pa_sample_spec ss;
 | 
				
			||||||
        pa_channel_map cm;
 | 
					        pa_channel_map cm;
 | 
				
			||||||
        const char *dn = NULL;
 | 
					        const char *dn = NULL;
 | 
				
			||||||
        int suspended;
 | 
					        pa_bool_t suspended;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
 | 
					        if (pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
 | 
				
			||||||
            pa_tagstruct_get_channel_map(t, &cm) < 0 ||
 | 
					            pa_tagstruct_get_channel_map(t, &cm) < 0 ||
 | 
				
			||||||
| 
						 | 
					@ -631,7 +647,8 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
 | 
				
			||||||
            pa_buffer_attr attr;
 | 
					            pa_buffer_attr attr;
 | 
				
			||||||
            pa_operation *o;
 | 
					            pa_operation *o;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            automatic_buffer_attr(&attr, &ss);
 | 
					            memset(&attr, 0, sizeof(attr));
 | 
				
			||||||
 | 
					            automatic_buffer_attr(s, &attr, &ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* If we need to update the buffer metrics, we wait for
 | 
					            /* If we need to update the buffer metrics, we wait for
 | 
				
			||||||
             * the the OK for that call before we go to
 | 
					             * the the OK for that call before we go to
 | 
				
			||||||
| 
						 | 
					@ -718,7 +735,9 @@ static int create_stream(
 | 
				
			||||||
                                              PA_STREAM_FIX_CHANNELS|
 | 
					                                              PA_STREAM_FIX_CHANNELS|
 | 
				
			||||||
                                              PA_STREAM_DONT_MOVE|
 | 
					                                              PA_STREAM_DONT_MOVE|
 | 
				
			||||||
                                              PA_STREAM_VARIABLE_RATE|
 | 
					                                              PA_STREAM_VARIABLE_RATE|
 | 
				
			||||||
                                              PA_STREAM_PEAK_DETECT)), PA_ERR_INVALID);
 | 
					                                              PA_STREAM_PEAK_DETECT|
 | 
				
			||||||
 | 
					                                              PA_STREAM_START_MUTED|
 | 
				
			||||||
 | 
					                                              PA_STREAM_ADJUST_LATENCY)), PA_ERR_INVALID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
 | 
					    PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
 | 
				
			||||||
    PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
 | 
					    PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
 | 
				
			||||||
| 
						 | 
					@ -727,6 +746,8 @@ static int create_stream(
 | 
				
			||||||
     * when they are passed but actually not supported. This makes
 | 
					     * when they are passed but actually not supported. This makes
 | 
				
			||||||
     * client development easier */
 | 
					     * client development easier */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PA_CHECK_VALIDITY(s->context, direction != PA_STREAM_PLAYBACK || !(flags & (PA_STREAM_START_MUTED)), PA_ERR_INVALID);
 | 
				
			||||||
 | 
					    PA_CHECK_VALIDITY(s->context, direction != PA_STREAM_RECORD || !(flags & (PA_STREAM_PEAK_DETECT)), PA_ERR_INVALID);
 | 
				
			||||||
    PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID);
 | 
					    PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID);
 | 
				
			||||||
    PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID);
 | 
					    PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -742,15 +763,12 @@ static int create_stream(
 | 
				
			||||||
        s->buffer_attr = *attr;
 | 
					        s->buffer_attr = *attr;
 | 
				
			||||||
        s->manual_buffer_attr = TRUE;
 | 
					        s->manual_buffer_attr = TRUE;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        /* half a second, with minimum request of 10 ms */
 | 
					        memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
 | 
				
			||||||
        s->buffer_attr.tlength = pa_bytes_per_second(&s->sample_spec)/2;
 | 
					 | 
				
			||||||
        s->buffer_attr.maxlength = (s->buffer_attr.tlength*3)/2;
 | 
					 | 
				
			||||||
        s->buffer_attr.minreq = s->buffer_attr.tlength/50;
 | 
					 | 
				
			||||||
        s->buffer_attr.prebuf = s->buffer_attr.tlength - s->buffer_attr.minreq;
 | 
					 | 
				
			||||||
        s->buffer_attr.fragsize = s->buffer_attr.tlength/50;
 | 
					 | 
				
			||||||
        s->manual_buffer_attr = FALSE;
 | 
					        s->manual_buffer_attr = FALSE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    automatic_buffer_attr(s, &s->buffer_attr, &s->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!dev)
 | 
					    if (!dev)
 | 
				
			||||||
        dev = s->direction == PA_STREAM_PLAYBACK ? s->context->conf->default_sink : s->context->conf->default_source;
 | 
					        dev = s->direction == PA_STREAM_PLAYBACK ? s->context->conf->default_sink : s->context->conf->default_source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -805,11 +823,16 @@ static int create_stream(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->context->version >= 13) {
 | 
					    if (s->context->version >= 13) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (s->direction == PA_STREAM_PLAYBACK)
 | 
				
			||||||
 | 
					            pa_tagstruct_put_boolean(t, flags & PA_STREAM_START_MUTED);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            pa_tagstruct_put_boolean(t, flags & PA_STREAM_PEAK_DETECT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pa_init_proplist(s->proplist);
 | 
					        pa_init_proplist(s->proplist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pa_tagstruct_put(
 | 
					        pa_tagstruct_put(
 | 
				
			||||||
                t,
 | 
					                t,
 | 
				
			||||||
                PA_TAG_BOOLEAN, flags & PA_STREAM_PEAK_DETECT,
 | 
					                PA_TAG_BOOLEAN, flags & PA_STREAM_ADJUST_LATENCY,
 | 
				
			||||||
                PA_TAG_PROPLIST, s->proplist,
 | 
					                PA_TAG_PROPLIST, s->proplist,
 | 
				
			||||||
                PA_TAG_INVALID);
 | 
					                PA_TAG_INVALID);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -1023,6 +1046,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
    pa_operation *o = userdata;
 | 
					    pa_operation *o = userdata;
 | 
				
			||||||
    struct timeval local, remote, now;
 | 
					    struct timeval local, remote, now;
 | 
				
			||||||
    pa_timing_info *i;
 | 
					    pa_timing_info *i;
 | 
				
			||||||
 | 
					    pa_bool_t playing = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(pd);
 | 
					    pa_assert(pd);
 | 
				
			||||||
    pa_assert(o);
 | 
					    pa_assert(o);
 | 
				
			||||||
| 
						 | 
					@ -1047,7 +1071,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } else if (pa_tagstruct_get_usec(t, &i->sink_usec) < 0 ||
 | 
					    } else if (pa_tagstruct_get_usec(t, &i->sink_usec) < 0 ||
 | 
				
			||||||
               pa_tagstruct_get_usec(t, &i->source_usec) < 0 ||
 | 
					               pa_tagstruct_get_usec(t, &i->source_usec) < 0 ||
 | 
				
			||||||
               pa_tagstruct_get_boolean(t, &i->playing) < 0 ||
 | 
					               pa_tagstruct_get_boolean(t, &playing) < 0 ||
 | 
				
			||||||
               pa_tagstruct_get_timeval(t, &local) < 0 ||
 | 
					               pa_tagstruct_get_timeval(t, &local) < 0 ||
 | 
				
			||||||
               pa_tagstruct_get_timeval(t, &remote) < 0 ||
 | 
					               pa_tagstruct_get_timeval(t, &remote) < 0 ||
 | 
				
			||||||
               pa_tagstruct_gets64(t, &i->write_index) < 0 ||
 | 
					               pa_tagstruct_gets64(t, &i->write_index) < 0 ||
 | 
				
			||||||
| 
						 | 
					@ -1058,6 +1082,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        o->stream->timing_info_valid = 1;
 | 
					        o->stream->timing_info_valid = 1;
 | 
				
			||||||
 | 
					        i->playing = (int) playing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pa_gettimeofday(&now);
 | 
					        pa_gettimeofday(&now);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,10 +155,10 @@ static const struct command commands[] = {
 | 
				
			||||||
    { "load-sample-dir-lazy",    pa_cli_command_scache_load_dir,    "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
 | 
					    { "load-sample-dir-lazy",    pa_cli_command_scache_load_dir,    "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
 | 
				
			||||||
    { "play-file",               pa_cli_command_play_file,          "Play a sound file (args: filename, sink|index)", 3},
 | 
					    { "play-file",               pa_cli_command_play_file,          "Play a sound file (args: filename, sink|index)", 3},
 | 
				
			||||||
    { "list-autoload",           pa_cli_command_autoload_list,      "List autoload entries", 1},
 | 
					    { "list-autoload",           pa_cli_command_autoload_list,      "List autoload entries", 1},
 | 
				
			||||||
    { "add-autoload-sink",       pa_cli_command_autoload_add,       "Add autoload entry for a sink (args: sink, module name, arguments)", 4},
 | 
					    { "add-autoload-sink",       pa_cli_command_autoload_add,       NULL /*"Add autoload entry for a sink (args: sink, module name, arguments)"*/, 4},
 | 
				
			||||||
    { "add-autoload-source",     pa_cli_command_autoload_add,       "Add autoload entry for a source (args: source, module name, arguments)", 4},
 | 
					    { "add-autoload-source",     pa_cli_command_autoload_add,       NULL /*"Add autoload entry for a source (args: source, module name, arguments)"*/, 4},
 | 
				
			||||||
    { "remove-autoload-sink",    pa_cli_command_autoload_remove,    "Remove autoload entry for a sink (args: name)", 2},
 | 
					    { "remove-autoload-sink",    pa_cli_command_autoload_remove,    NULL /*"Remove autoload entry for a sink (args: name)"*/, 2},
 | 
				
			||||||
    { "remove-autoload-source",  pa_cli_command_autoload_remove,    "Remove autoload entry for a source (args: name)", 2},
 | 
					    { "remove-autoload-source",  pa_cli_command_autoload_remove,    NULL /*"Remove autoload entry for a source (args: name)"*/, 2},
 | 
				
			||||||
    { "dump",                    pa_cli_command_dump,               "Dump daemon configuration", 1},
 | 
					    { "dump",                    pa_cli_command_dump,               "Dump daemon configuration", 1},
 | 
				
			||||||
    { "list-props",              pa_cli_command_list_props,         NULL, 1},
 | 
					    { "list-props",              pa_cli_command_list_props,         NULL, 1},
 | 
				
			||||||
    { "move-sink-input",         pa_cli_command_move_sink_input,    "Move sink input to another sink (args: index, sink)", 3},
 | 
					    { "move-sink-input",         pa_cli_command_move_sink_input,    "Move sink input to another sink (args: index, sink)", 3},
 | 
				
			||||||
| 
						 | 
					@ -367,7 +367,7 @@ static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
 | 
				
			||||||
    pa_cli_command_sink_inputs(c, t, buf, fail);
 | 
					    pa_cli_command_sink_inputs(c, t, buf, fail);
 | 
				
			||||||
    pa_cli_command_source_outputs(c, t, buf, fail);
 | 
					    pa_cli_command_source_outputs(c, t, buf, fail);
 | 
				
			||||||
    pa_cli_command_scache_list(c, t, buf, fail);
 | 
					    pa_cli_command_scache_list(c, t, buf, fail);
 | 
				
			||||||
    pa_cli_command_autoload_list(c, t, buf, fail);
 | 
					/*     pa_cli_command_autoload_list(c, t, buf, fail); */
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -905,6 +905,8 @@ static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *b
 | 
				
			||||||
    pa_assert(buf);
 | 
					    pa_assert(buf);
 | 
				
			||||||
    pa_assert(fail);
 | 
					    pa_assert(fail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_log_warn("Autoload will no longer be implemented by future versions of the PulseAudio server.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!(a = pa_tokenizer_get(t, 1)) || !(b = pa_tokenizer_get(t, 2))) {
 | 
					    if (!(a = pa_tokenizer_get(t, 1)) || !(b = pa_tokenizer_get(t, 2))) {
 | 
				
			||||||
        pa_strbuf_puts(buf, "You need to specify a device name, a filename or a module name and optionally module arguments\n");
 | 
					        pa_strbuf_puts(buf, "You need to specify a device name, a filename or a module name and optionally module arguments\n");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
| 
						 | 
					@ -923,6 +925,8 @@ static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf
 | 
				
			||||||
    pa_assert(buf);
 | 
					    pa_assert(buf);
 | 
				
			||||||
    pa_assert(fail);
 | 
					    pa_assert(fail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_log_warn("Autoload will no longer be implemented by future versions of the PulseAudio server.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!(name = pa_tokenizer_get(t, 1))) {
 | 
					    if (!(name = pa_tokenizer_get(t, 1))) {
 | 
				
			||||||
        pa_strbuf_puts(buf, "You need to specify a device name\n");
 | 
					        pa_strbuf_puts(buf, "You need to specify a device name\n");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
| 
						 | 
					@ -944,6 +948,8 @@ static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *
 | 
				
			||||||
    pa_assert(buf);
 | 
					    pa_assert(buf);
 | 
				
			||||||
    pa_assert(fail);
 | 
					    pa_assert(fail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_log_warn("Autoload will no longer be implemented by future versions of the PulseAudio server.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert_se(s = pa_autoload_list_to_string(c));
 | 
					    pa_assert_se(s = pa_autoload_list_to_string(c));
 | 
				
			||||||
    pa_strbuf_puts(buf, s);
 | 
					    pa_strbuf_puts(buf, s);
 | 
				
			||||||
    pa_xfree(s);
 | 
					    pa_xfree(s);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -204,4 +204,17 @@ static inline const char *pa_strnull(const char *x) {
 | 
				
			||||||
    return x ? x : "(null)";
 | 
					    return x ? x : "(null)";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __GNUC__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PA_WARN_REFERENCE(sym,msg)              \
 | 
				
			||||||
 | 
					    __asm__(".section .gnu.warning.sym");       \
 | 
				
			||||||
 | 
					    __asm__(".asciz \"msg\"");                  \
 | 
				
			||||||
 | 
					    __asm__(".previous")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PA_WARN_REFERENCE(sym,msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -138,7 +138,7 @@ static void fix_current_read(pa_memblockq *bq) {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Scan right */
 | 
					    /* Scan right */
 | 
				
			||||||
    while (PA_LIKELY(bq->current_read != NULL) && PA_UNLIKELY(bq->current_read->index + bq->current_read->chunk.length <= bq->read_index))
 | 
					    while (PA_LIKELY(bq->current_read != NULL) && PA_UNLIKELY(bq->current_read->index + (int64_t) bq->current_read->chunk.length <= bq->read_index))
 | 
				
			||||||
        bq->current_read = bq->current_read->next;
 | 
					        bq->current_read = bq->current_read->next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* At this point current_read will either point at or left of the
 | 
					    /* At this point current_read will either point at or left of the
 | 
				
			||||||
| 
						 | 
					@ -158,7 +158,7 @@ static void fix_current_write(pa_memblockq *bq) {
 | 
				
			||||||
        bq->current_write = bq->blocks_tail;
 | 
					        bq->current_write = bq->blocks_tail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Scan right */
 | 
					    /* Scan right */
 | 
				
			||||||
    while (PA_UNLIKELY(bq->current_write->index + bq->current_write->chunk.length <= bq->write_index))
 | 
					    while (PA_UNLIKELY(bq->current_write->index + (int64_t) bq->current_write->chunk.length <= bq->write_index))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (bq->current_write->next)
 | 
					        if (bq->current_write->next)
 | 
				
			||||||
            bq->current_write = bq->current_write->next;
 | 
					            bq->current_write = bq->current_write->next;
 | 
				
			||||||
| 
						 | 
					@ -214,7 +214,7 @@ static void drop_backlog(pa_memblockq *bq) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    boundary = bq->read_index - bq->maxrewind;
 | 
					    boundary = bq->read_index - bq->maxrewind;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (bq->blocks && (bq->blocks->index + bq->blocks->chunk.length <= boundary))
 | 
					    while (bq->blocks && (bq->blocks->index + (int64_t) bq->blocks->chunk.length <= boundary))
 | 
				
			||||||
        drop_block(bq, bq->blocks);
 | 
					        drop_block(bq, bq->blocks);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,10 +232,10 @@ static pa_bool_t can_push(pa_memblockq *bq, size_t l) {
 | 
				
			||||||
            return TRUE;
 | 
					            return TRUE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    end = bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : bq->write_index;
 | 
					    end = bq->blocks_tail ? bq->blocks_tail->index + (int64_t) bq->blocks_tail->chunk.length : bq->write_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Make sure that the list doesn't get too long */
 | 
					    /* Make sure that the list doesn't get too long */
 | 
				
			||||||
    if (bq->write_index + l > end)
 | 
					    if (bq->write_index + (int64_t) l > end)
 | 
				
			||||||
        if (bq->write_index + l - bq->read_index > bq->maxlength)
 | 
					        if (bq->write_index + l - bq->read_index > bq->maxlength)
 | 
				
			||||||
            return FALSE;
 | 
					            return FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -269,7 +269,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 | 
				
			||||||
     * write to */
 | 
					     * write to */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (q) {
 | 
					    if (q) {
 | 
				
			||||||
        while (bq->write_index + chunk.length > q->index)
 | 
					        while (bq->write_index + (int64_t) chunk.length > q->index)
 | 
				
			||||||
            if (q->next)
 | 
					            if (q->next)
 | 
				
			||||||
                q = q->next;
 | 
					                q = q->next;
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
| 
						 | 
					@ -284,10 +284,10 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (q) {
 | 
					    while (q) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (bq->write_index >= q->index + q->chunk.length)
 | 
					        if (bq->write_index >= q->index + (int64_t) q->chunk.length)
 | 
				
			||||||
            /* We found the entry where we need to place the new entry immediately after */
 | 
					            /* We found the entry where we need to place the new entry immediately after */
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        else if (bq->write_index + chunk.length <= q->index) {
 | 
					        else if (bq->write_index + (int64_t) chunk.length <= q->index) {
 | 
				
			||||||
            /* This entry isn't touched at all, let's skip it */
 | 
					            /* This entry isn't touched at all, let's skip it */
 | 
				
			||||||
            q = q->prev;
 | 
					            q = q->prev;
 | 
				
			||||||
        } else if (bq->write_index <= q->index &&
 | 
					        } else if (bq->write_index <= q->index &&
 | 
				
			||||||
| 
						 | 
					@ -407,7 +407,7 @@ finish:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    delta = bq->write_index - old;
 | 
					    delta = bq->write_index - old;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (delta >= bq->requested) {
 | 
					    if (delta >= (int64_t) bq->requested) {
 | 
				
			||||||
        delta -= bq->requested;
 | 
					        delta -= bq->requested;
 | 
				
			||||||
        bq->requested = 0;
 | 
					        bq->requested = 0;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
| 
						 | 
					@ -526,7 +526,7 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
 | 
				
			||||||
            pa_assert(p >= bq->read_index);
 | 
					            pa_assert(p >= bq->read_index);
 | 
				
			||||||
            d = p - bq->read_index;
 | 
					            d = p - bq->read_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (d > length)
 | 
					            if (d > (int64_t) length)
 | 
				
			||||||
                d = length;
 | 
					                d = length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            bq->read_index += d;
 | 
					            bq->read_index += d;
 | 
				
			||||||
| 
						 | 
					@ -606,7 +606,7 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    delta = bq->write_index - old;
 | 
					    delta = bq->write_index - old;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (delta >= bq->requested) {
 | 
					    if (delta >= (int64_t) bq->requested) {
 | 
				
			||||||
        delta -= bq->requested;
 | 
					        delta -= bq->requested;
 | 
				
			||||||
        bq->requested = 0;
 | 
					        bq->requested = 0;
 | 
				
			||||||
    } else if (delta >= 0) {
 | 
					    } else if (delta >= 0) {
 | 
				
			||||||
| 
						 | 
					@ -633,7 +633,7 @@ void pa_memblockq_flush(pa_memblockq *bq) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    delta = bq->write_index - old;
 | 
					    delta = bq->write_index - old;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (delta >= bq->requested) {
 | 
					    if (delta >= (int64_t) bq->requested) {
 | 
				
			||||||
        delta -= bq->requested;
 | 
					        delta -= bq->requested;
 | 
				
			||||||
        bq->requested = 0;
 | 
					        bq->requested = 0;
 | 
				
			||||||
    } else if (delta >= 0) {
 | 
					    } else if (delta >= 0) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,8 +109,8 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
 | 
				
			||||||
    m->userdata = NULL;
 | 
					    m->userdata = NULL;
 | 
				
			||||||
    m->core = c;
 | 
					    m->core = c;
 | 
				
			||||||
    m->n_used = -1;
 | 
					    m->n_used = -1;
 | 
				
			||||||
    m->auto_unload = 0;
 | 
					    m->auto_unload = FALSE;
 | 
				
			||||||
    m->unload_requested = 0;
 | 
					    m->unload_requested = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (m->init(m) < 0) {
 | 
					    if (m->init(m) < 0) {
 | 
				
			||||||
        pa_log_error("Failed to load  module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : "");
 | 
					        pa_log_error("Failed to load  module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : "");
 | 
				
			||||||
| 
						 | 
					@ -281,7 +281,7 @@ static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) {
 | 
				
			||||||
void pa_module_unload_request(pa_module *m) {
 | 
					void pa_module_unload_request(pa_module *m) {
 | 
				
			||||||
    pa_assert(m);
 | 
					    pa_assert(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m->unload_requested = 1;
 | 
					    m->unload_requested = TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!m->core->module_defer_unload_event)
 | 
					    if (!m->core->module_defer_unload_event)
 | 
				
			||||||
        m->core->module_defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core);
 | 
					        m->core->module_defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,10 +45,10 @@ struct pa_module {
 | 
				
			||||||
    void *userdata;
 | 
					    void *userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int n_used;
 | 
					    int n_used;
 | 
				
			||||||
    int auto_unload;
 | 
					    pa_bool_t auto_unload;
 | 
				
			||||||
    time_t last_used_time;
 | 
					    time_t last_used_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int unload_requested;
 | 
					    pa_bool_t unload_requested;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pa_module* pa_module_load(pa_core *c, const char *name, const char*argument);
 | 
					pa_module* pa_module_load(pa_core *c, const char *name, const char*argument);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,6 +71,8 @@
 | 
				
			||||||
#define MAX_CONNECTIONS 64
 | 
					#define MAX_CONNECTIONS 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
 | 
					#define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
 | 
				
			||||||
 | 
					#define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
 | 
				
			||||||
 | 
					#define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct connection connection;
 | 
					typedef struct connection connection;
 | 
				
			||||||
struct pa_protocol_native;
 | 
					struct pa_protocol_native;
 | 
				
			||||||
| 
						 | 
					@ -469,9 +471,10 @@ static record_stream* record_stream_new(
 | 
				
			||||||
        pa_channel_map *map,
 | 
					        pa_channel_map *map,
 | 
				
			||||||
        const char *name,
 | 
					        const char *name,
 | 
				
			||||||
        uint32_t *maxlength,
 | 
					        uint32_t *maxlength,
 | 
				
			||||||
        uint32_t fragment_size,
 | 
					        uint32_t *fragsize,
 | 
				
			||||||
        pa_source_output_flags_t flags,
 | 
					        pa_source_output_flags_t flags,
 | 
				
			||||||
        pa_proplist *p) {
 | 
					        pa_proplist *p,
 | 
				
			||||||
 | 
					        pa_bool_t adjust_latency) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    record_stream *s;
 | 
					    record_stream *s;
 | 
				
			||||||
    pa_source_output *source_output;
 | 
					    pa_source_output *source_output;
 | 
				
			||||||
| 
						 | 
					@ -482,7 +485,6 @@ static record_stream* record_stream_new(
 | 
				
			||||||
    pa_assert(ss);
 | 
					    pa_assert(ss);
 | 
				
			||||||
    pa_assert(name);
 | 
					    pa_assert(name);
 | 
				
			||||||
    pa_assert(maxlength);
 | 
					    pa_assert(maxlength);
 | 
				
			||||||
    pa_assert(*maxlength > 0);
 | 
					 | 
				
			||||||
    pa_assert(p);
 | 
					    pa_assert(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_source_output_new_data_init(&data);
 | 
					    pa_source_output_new_data_init(&data);
 | 
				
			||||||
| 
						 | 
					@ -508,6 +510,7 @@ static record_stream* record_stream_new(
 | 
				
			||||||
    s->parent.process_msg = record_stream_process_msg;
 | 
					    s->parent.process_msg = record_stream_process_msg;
 | 
				
			||||||
    s->connection = c;
 | 
					    s->connection = c;
 | 
				
			||||||
    s->source_output = source_output;
 | 
					    s->source_output = source_output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->source_output->push = source_output_push_cb;
 | 
					    s->source_output->push = source_output_push_cb;
 | 
				
			||||||
    s->source_output->kill = source_output_kill_cb;
 | 
					    s->source_output->kill = source_output_kill_cb;
 | 
				
			||||||
    s->source_output->get_latency = source_output_get_latency_cb;
 | 
					    s->source_output->get_latency = source_output_get_latency_cb;
 | 
				
			||||||
| 
						 | 
					@ -515,11 +518,36 @@ static record_stream* record_stream_new(
 | 
				
			||||||
    s->source_output->suspend = source_output_suspend_cb;
 | 
					    s->source_output->suspend = source_output_suspend_cb;
 | 
				
			||||||
    s->source_output->userdata = s;
 | 
					    s->source_output->userdata = s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
				
			||||||
 | 
					        *maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
				
			||||||
 | 
					    if (*fragsize <= 0)
 | 
				
			||||||
 | 
					        *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &source_output->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (adjust_latency) {
 | 
				
			||||||
 | 
					        pa_usec_t fragsize_usec, source_latency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* So, the user asked us to adjust the latency according to
 | 
				
			||||||
 | 
					         * the what the source can provide. Half the latency will be
 | 
				
			||||||
 | 
					         * spent on the hw buffer, half of it in the async buffer
 | 
				
			||||||
 | 
					         * queue we maintain for each client. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fragsize_usec = pa_bytes_to_usec(*fragsize, &source_output->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        source_latency = pa_source_output_set_requested_latency(source_output, fragsize_usec/2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (fragsize_usec >= source_latency*2)
 | 
				
			||||||
 | 
					            fragsize_usec -= source_latency;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            fragsize_usec = source_latency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *fragsize = pa_usec_to_bytes(fragsize_usec, &source_output->sample_spec);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->memblockq = pa_memblockq_new(
 | 
					    s->memblockq = pa_memblockq_new(
 | 
				
			||||||
            0,
 | 
					            0,
 | 
				
			||||||
            *maxlength,
 | 
					            *maxlength,
 | 
				
			||||||
            0,
 | 
					            0,
 | 
				
			||||||
            base = pa_frame_size(&s->source_output->sample_spec),
 | 
					            base = pa_frame_size(&source_output->sample_spec),
 | 
				
			||||||
            1,
 | 
					            1,
 | 
				
			||||||
            0,
 | 
					            0,
 | 
				
			||||||
            0,
 | 
					            0,
 | 
				
			||||||
| 
						 | 
					@ -527,13 +555,15 @@ static record_stream* record_stream_new(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *maxlength = pa_memblockq_get_maxlength(s->memblockq);
 | 
					    *maxlength = pa_memblockq_get_maxlength(s->memblockq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->fragment_size = (fragment_size/base)*base;
 | 
					    s->fragment_size = (*fragsize/base)*base;
 | 
				
			||||||
    if (s->fragment_size <= 0)
 | 
					    if (s->fragment_size <= 0)
 | 
				
			||||||
        s->fragment_size = base;
 | 
					        s->fragment_size = base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->fragment_size > *maxlength)
 | 
					    if (s->fragment_size > *maxlength)
 | 
				
			||||||
        s->fragment_size = *maxlength;
 | 
					        s->fragment_size = *maxlength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *fragsize = s->fragment_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *ss = s->source_output->sample_spec;
 | 
					    *ss = s->source_output->sample_spec;
 | 
				
			||||||
    *map = s->source_output->channel_map;
 | 
					    *map = s->source_output->channel_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -658,10 +688,12 @@ static playback_stream* playback_stream_new(
 | 
				
			||||||
        uint32_t *prebuf,
 | 
					        uint32_t *prebuf,
 | 
				
			||||||
        uint32_t *minreq,
 | 
					        uint32_t *minreq,
 | 
				
			||||||
        pa_cvolume *volume,
 | 
					        pa_cvolume *volume,
 | 
				
			||||||
 | 
					        pa_bool_t muted,
 | 
				
			||||||
        uint32_t syncid,
 | 
					        uint32_t syncid,
 | 
				
			||||||
        uint32_t *missing,
 | 
					        uint32_t *missing,
 | 
				
			||||||
        pa_sink_input_flags_t flags,
 | 
					        pa_sink_input_flags_t flags,
 | 
				
			||||||
        pa_proplist *p) {
 | 
					        pa_proplist *p,
 | 
				
			||||||
 | 
					        pa_bool_t adjust_latency) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    playback_stream *s, *ssync;
 | 
					    playback_stream *s, *ssync;
 | 
				
			||||||
    pa_sink_input *sink_input;
 | 
					    pa_sink_input *sink_input;
 | 
				
			||||||
| 
						 | 
					@ -674,6 +706,11 @@ static playback_stream* playback_stream_new(
 | 
				
			||||||
    pa_assert(ss);
 | 
					    pa_assert(ss);
 | 
				
			||||||
    pa_assert(name);
 | 
					    pa_assert(name);
 | 
				
			||||||
    pa_assert(maxlength);
 | 
					    pa_assert(maxlength);
 | 
				
			||||||
 | 
					    pa_assert(tlength);
 | 
				
			||||||
 | 
					    pa_assert(prebuf);
 | 
				
			||||||
 | 
					    pa_assert(minreq);
 | 
				
			||||||
 | 
					    pa_assert(volume);
 | 
				
			||||||
 | 
					    pa_assert(missing);
 | 
				
			||||||
    pa_assert(p);
 | 
					    pa_assert(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Find syncid group */
 | 
					    /* Find syncid group */
 | 
				
			||||||
| 
						 | 
					@ -706,6 +743,7 @@ static playback_stream* playback_stream_new(
 | 
				
			||||||
    pa_sink_input_new_data_set_sample_spec(&data, ss);
 | 
					    pa_sink_input_new_data_set_sample_spec(&data, ss);
 | 
				
			||||||
    pa_sink_input_new_data_set_channel_map(&data, map);
 | 
					    pa_sink_input_new_data_set_channel_map(&data, map);
 | 
				
			||||||
    pa_sink_input_new_data_set_volume(&data, volume);
 | 
					    pa_sink_input_new_data_set_volume(&data, volume);
 | 
				
			||||||
 | 
					    pa_sink_input_new_data_set_muted(&data, muted);
 | 
				
			||||||
    data.sync_base = ssync ? ssync->sink_input : NULL;
 | 
					    data.sync_base = ssync ? ssync->sink_input : NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sink_input = pa_sink_input_new(c->protocol->core, &data, flags);
 | 
					    sink_input = pa_sink_input_new(c->protocol->core, &data, flags);
 | 
				
			||||||
| 
						 | 
					@ -732,13 +770,49 @@ static playback_stream* playback_stream_new(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
 | 
					    start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    silence = pa_silence_memblock_new(c->protocol->core->mempool, &s->sink_input->sample_spec, 0);
 | 
					    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
				
			||||||
 | 
					        *maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
				
			||||||
 | 
					    if (*tlength <= 0)
 | 
				
			||||||
 | 
					        *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*1000, &sink_input->sample_spec);
 | 
				
			||||||
 | 
					    if (*minreq <= 0)
 | 
				
			||||||
 | 
					        *minreq = (*tlength*9)/10;
 | 
				
			||||||
 | 
					    if (*prebuf <= 0)
 | 
				
			||||||
 | 
					        *prebuf = *tlength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (adjust_latency) {
 | 
				
			||||||
 | 
					        pa_usec_t tlength_usec, minreq_usec, sink_latency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* So, the user asked us to adjust the latency according to
 | 
				
			||||||
 | 
					         * the what the sink can provide. Half the latency will be
 | 
				
			||||||
 | 
					         * spent on the hw buffer, half of it in the async buffer
 | 
				
			||||||
 | 
					         * queue we maintain for each client. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tlength_usec = pa_bytes_to_usec(*tlength, &sink_input->sample_spec);
 | 
				
			||||||
 | 
					        minreq_usec = pa_bytes_to_usec(*minreq, &sink_input->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sink_latency = pa_sink_input_set_requested_latency(sink_input, tlength_usec/2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (tlength_usec >= sink_latency*2)
 | 
				
			||||||
 | 
					            tlength_usec -= sink_latency;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            tlength_usec = sink_latency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (minreq_usec >= sink_latency*2)
 | 
				
			||||||
 | 
					            minreq_usec -= sink_latency;
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            minreq_usec = sink_latency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *tlength = pa_usec_to_bytes(tlength_usec, &sink_input->sample_spec);
 | 
				
			||||||
 | 
					        *minreq = pa_usec_to_bytes(minreq_usec, &sink_input->sample_spec);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    silence = pa_silence_memblock_new(c->protocol->core->mempool, &sink_input->sample_spec, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->memblockq = pa_memblockq_new(
 | 
					    s->memblockq = pa_memblockq_new(
 | 
				
			||||||
            start_index,
 | 
					            start_index,
 | 
				
			||||||
            *maxlength,
 | 
					            *maxlength,
 | 
				
			||||||
            *tlength,
 | 
					            *tlength,
 | 
				
			||||||
            pa_frame_size(&s->sink_input->sample_spec),
 | 
					            pa_frame_size(&sink_input->sample_spec),
 | 
				
			||||||
            *prebuf,
 | 
					            *prebuf,
 | 
				
			||||||
            *minreq,
 | 
					            *minreq,
 | 
				
			||||||
            0,
 | 
					            0,
 | 
				
			||||||
| 
						 | 
					@ -762,7 +836,6 @@ static playback_stream* playback_stream_new(
 | 
				
			||||||
    pa_idxset_put(c->output_streams, s, &s->index);
 | 
					    pa_idxset_put(c->output_streams, s, &s->index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_sink_input_put(s->sink_input);
 | 
					    pa_sink_input_put(s->sink_input);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return s;
 | 
					    return s;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1230,8 +1303,18 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
 | 
				
			||||||
    pa_tagstruct *reply;
 | 
					    pa_tagstruct *reply;
 | 
				
			||||||
    pa_sink *sink = NULL;
 | 
					    pa_sink *sink = NULL;
 | 
				
			||||||
    pa_cvolume volume;
 | 
					    pa_cvolume volume;
 | 
				
			||||||
    int corked;
 | 
					    pa_bool_t
 | 
				
			||||||
    int no_remap = 0, no_remix = 0, fix_format = 0, fix_rate = 0, fix_channels = 0, no_move = 0, variable_rate = 0;
 | 
					        corked = FALSE,
 | 
				
			||||||
 | 
					        no_remap = FALSE,
 | 
				
			||||||
 | 
					        no_remix = FALSE,
 | 
				
			||||||
 | 
					        fix_format = FALSE,
 | 
				
			||||||
 | 
					        fix_rate = FALSE,
 | 
				
			||||||
 | 
					        fix_channels = FALSE,
 | 
				
			||||||
 | 
					        no_move = FALSE,
 | 
				
			||||||
 | 
					        variable_rate = FALSE,
 | 
				
			||||||
 | 
					        muted = FALSE,
 | 
				
			||||||
 | 
					        adjust_latency = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_sink_input_flags_t flags = 0;
 | 
					    pa_sink_input_flags_t flags = 0;
 | 
				
			||||||
    pa_proplist *p;
 | 
					    pa_proplist *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1264,8 +1347,6 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
 | 
					    CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
 | 
					    CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
 | 
					    CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
 | 
					 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    p = pa_proplist_new();
 | 
					    p = pa_proplist_new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1291,7 +1372,9 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (c->version >= 13) {
 | 
					    if (c->version >= 13) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (pa_tagstruct_get_proplist(t, p) < 0) {
 | 
					        if (pa_tagstruct_get_boolean(t, &muted) < 0 ||
 | 
				
			||||||
 | 
					            pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
 | 
				
			||||||
 | 
					            pa_tagstruct_get_proplist(t, p) < 0) {
 | 
				
			||||||
            protocol_error(c);
 | 
					            protocol_error(c);
 | 
				
			||||||
            pa_proplist_free(p);
 | 
					            pa_proplist_free(p);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
| 
						 | 
					@ -1331,7 +1414,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
 | 
				
			||||||
        (no_move ?  PA_SINK_INPUT_DONT_MOVE : 0) |
 | 
					        (no_move ?  PA_SINK_INPUT_DONT_MOVE : 0) |
 | 
				
			||||||
        (variable_rate ?  PA_SINK_INPUT_VARIABLE_RATE : 0);
 | 
					        (variable_rate ?  PA_SINK_INPUT_VARIABLE_RATE : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, syncid, &missing, flags, p);
 | 
					    s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, muted, syncid, &missing, flags, p, adjust_latency);
 | 
				
			||||||
    pa_proplist_free(p);
 | 
					    pa_proplist_free(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 | 
					    CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 | 
				
			||||||
| 
						 | 
					@ -1438,8 +1521,16 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 | 
				
			||||||
    pa_channel_map map;
 | 
					    pa_channel_map map;
 | 
				
			||||||
    pa_tagstruct *reply;
 | 
					    pa_tagstruct *reply;
 | 
				
			||||||
    pa_source *source = NULL;
 | 
					    pa_source *source = NULL;
 | 
				
			||||||
    int corked;
 | 
					    pa_bool_t
 | 
				
			||||||
    int no_remap = 0, no_remix = 0, fix_format = 0, fix_rate = 0, fix_channels = 0, no_move = 0, variable_rate = 0;
 | 
					        corked = FALSE,
 | 
				
			||||||
 | 
					        no_remap = FALSE,
 | 
				
			||||||
 | 
					        no_remix = FALSE,
 | 
				
			||||||
 | 
					        fix_format = FALSE,
 | 
				
			||||||
 | 
					        fix_rate = FALSE,
 | 
				
			||||||
 | 
					        fix_channels = FALSE,
 | 
				
			||||||
 | 
					        no_move = FALSE,
 | 
				
			||||||
 | 
					        variable_rate = FALSE,
 | 
				
			||||||
 | 
					        adjust_latency = FALSE;
 | 
				
			||||||
    pa_source_output_flags_t flags = 0;
 | 
					    pa_source_output_flags_t flags = 0;
 | 
				
			||||||
    pa_proplist *p;
 | 
					    pa_proplist *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1463,8 +1554,6 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
 | 
					    CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID);
 | 
					    CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID);
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
 | 
					    CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
 | 
					 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    p = pa_proplist_new();
 | 
					    p = pa_proplist_new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1490,7 +1579,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (c->version >= 13) {
 | 
					    if (c->version >= 13) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (pa_tagstruct_get_proplist(t, p) < 0) {
 | 
					        if (pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
 | 
				
			||||||
 | 
					            pa_tagstruct_get_proplist(t, p) < 0) {
 | 
				
			||||||
            protocol_error(c);
 | 
					            protocol_error(c);
 | 
				
			||||||
            pa_proplist_free(p);
 | 
					            pa_proplist_free(p);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
| 
						 | 
					@ -1530,7 +1620,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 | 
				
			||||||
        (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
 | 
					        (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
 | 
				
			||||||
        (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0);
 | 
					        (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = record_stream_new(c, source, &ss, &map, name, &maxlength, fragment_size, flags, p);
 | 
					    s = record_stream_new(c, source, &ss, &map, name, &maxlength, &fragment_size, flags, p, adjust_latency);
 | 
				
			||||||
    pa_proplist_free(p);
 | 
					    pa_proplist_free(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 | 
					    CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 | 
				
			||||||
| 
						 | 
					@ -1544,7 +1634,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 | 
				
			||||||
        /* Since 0.9 we support sending the buffer metrics back to the client */
 | 
					        /* Since 0.9 we support sending the buffer metrics back to the client */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pa_tagstruct_putu32(reply, (uint32_t) maxlength);
 | 
					        pa_tagstruct_putu32(reply, (uint32_t) maxlength);
 | 
				
			||||||
        pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size);
 | 
					        pa_tagstruct_putu32(reply, (uint32_t) fragment_size);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (c->version >= 12) {
 | 
					    if (c->version >= 12) {
 | 
				
			||||||
| 
						 | 
					@ -1873,7 +1963,7 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN
 | 
				
			||||||
    reply = reply_new(tag);
 | 
					    reply = reply_new(tag);
 | 
				
			||||||
    pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0);
 | 
					    pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0);
 | 
				
			||||||
    pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source));
 | 
					    pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source));
 | 
				
			||||||
    pa_tagstruct_put_boolean(reply, 0);
 | 
					    pa_tagstruct_put_boolean(reply, FALSE);
 | 
				
			||||||
    pa_tagstruct_put_timeval(reply, &tv);
 | 
					    pa_tagstruct_put_timeval(reply, &tv);
 | 
				
			||||||
    pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
 | 
					    pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
 | 
				
			||||||
    pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
 | 
					    pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
 | 
				
			||||||
| 
						 | 
					@ -2511,7 +2601,7 @@ static void command_set_mute(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connection *c = CONNECTION(userdata);
 | 
					    connection *c = CONNECTION(userdata);
 | 
				
			||||||
    uint32_t idx;
 | 
					    uint32_t idx;
 | 
				
			||||||
    int mute;
 | 
					    pa_bool_t mute;
 | 
				
			||||||
    pa_sink *sink = NULL;
 | 
					    pa_sink *sink = NULL;
 | 
				
			||||||
    pa_source *source = NULL;
 | 
					    pa_source *source = NULL;
 | 
				
			||||||
    pa_sink_input *si = NULL;
 | 
					    pa_sink_input *si = NULL;
 | 
				
			||||||
| 
						 | 
					@ -2574,7 +2664,7 @@ static void command_set_mute(
 | 
				
			||||||
static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
 | 
					static void command_cork_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
 | 
				
			||||||
    connection *c = CONNECTION(userdata);
 | 
					    connection *c = CONNECTION(userdata);
 | 
				
			||||||
    uint32_t idx;
 | 
					    uint32_t idx;
 | 
				
			||||||
    int b;
 | 
					    pa_bool_t b;
 | 
				
			||||||
    playback_stream *s;
 | 
					    playback_stream *s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connection_assert_ref(c);
 | 
					    connection_assert_ref(c);
 | 
				
			||||||
| 
						 | 
					@ -2641,7 +2731,7 @@ static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN
 | 
				
			||||||
    connection *c = CONNECTION(userdata);
 | 
					    connection *c = CONNECTION(userdata);
 | 
				
			||||||
    uint32_t idx;
 | 
					    uint32_t idx;
 | 
				
			||||||
    record_stream *s;
 | 
					    record_stream *s;
 | 
				
			||||||
    int b;
 | 
					    pa_bool_t b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connection_assert_ref(c);
 | 
					    connection_assert_ref(c);
 | 
				
			||||||
    pa_assert(t);
 | 
					    pa_assert(t);
 | 
				
			||||||
| 
						 | 
					@ -2719,8 +2809,14 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
 | 
					        if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
				
			||||||
        CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
 | 
					            maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
				
			||||||
 | 
					        if (tlength <= 0)
 | 
				
			||||||
 | 
					            tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*1000, &s->sink_input->sample_spec);
 | 
				
			||||||
 | 
					        if (minreq <= 0)
 | 
				
			||||||
 | 
					            minreq = (tlength*9)/10;
 | 
				
			||||||
 | 
					        if (prebuf <= 0)
 | 
				
			||||||
 | 
					            prebuf = tlength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pa_memblockq_set_maxlength(s->memblockq, maxlength);
 | 
					        pa_memblockq_set_maxlength(s->memblockq, maxlength);
 | 
				
			||||||
        pa_memblockq_set_tlength(s->memblockq, tlength);
 | 
					        pa_memblockq_set_tlength(s->memblockq, tlength);
 | 
				
			||||||
| 
						 | 
					@ -2751,8 +2847,10 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
 | 
					        if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
 | 
				
			||||||
        CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
 | 
					            maxlength = MAX_MEMBLOCKQ_LENGTH;
 | 
				
			||||||
 | 
					        if (fragsize <= 0)
 | 
				
			||||||
 | 
					            fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &s->source_output->sample_spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pa_memblockq_set_maxlength(s->memblockq, maxlength);
 | 
					        pa_memblockq_set_maxlength(s->memblockq, maxlength);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3336,7 +3434,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
 | 
				
			||||||
    connection *c = CONNECTION(userdata);
 | 
					    connection *c = CONNECTION(userdata);
 | 
				
			||||||
    uint32_t idx = PA_INVALID_INDEX;
 | 
					    uint32_t idx = PA_INVALID_INDEX;
 | 
				
			||||||
    const char *name = NULL;
 | 
					    const char *name = NULL;
 | 
				
			||||||
    int b;
 | 
					    pa_bool_t b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connection_assert_ref(c);
 | 
					    connection_assert_ref(c);
 | 
				
			||||||
    pa_assert(t);
 | 
					    pa_assert(t);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -282,7 +282,9 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (st.st_size <= 0 || st.st_size > MAX_SHM_SIZE+PA_ALIGN(sizeof(struct shm_marker)) || PA_ALIGN(st.st_size) != st.st_size) {
 | 
					    if (st.st_size <= 0 ||
 | 
				
			||||||
 | 
					        st.st_size > (off_t) (MAX_SHM_SIZE+PA_ALIGN(sizeof(struct shm_marker))) ||
 | 
				
			||||||
 | 
					        PA_ALIGN((size_t) st.st_size) != (size_t) st.st_size) {
 | 
				
			||||||
        pa_log("Invalid shared memory segment size");
 | 
					        pa_log("Invalid shared memory segment size");
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -665,11 +665,18 @@ void pa_sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sin
 | 
				
			||||||
        i->set_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
 | 
					        i->set_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
 | 
					pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
 | 
				
			||||||
    pa_sink_input_assert_ref(i);
 | 
					    pa_sink_input_assert_ref(i);
 | 
				
			||||||
    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (usec < i->sink->min_latency)
 | 
				
			||||||
 | 
					        usec = i->sink->min_latency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (PA_SINK_INPUT_LINKED(i->state))
 | 
				
			||||||
        pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
 | 
					        pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        i->thread_info.requested_sink_latency = usec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return usec;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
 | 
					void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,7 +226,7 @@ void pa_sink_input_unlink(pa_sink_input* i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_sink_input_set_name(pa_sink_input *i, const char *name);
 | 
					void pa_sink_input_set_name(pa_sink_input *i, const char *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec);
 | 
					pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Request that the specified number of bytes already written out to
 | 
					/* Request that the specified number of bytes already written out to
 | 
				
			||||||
the hw device is rewritten, if possible. If this function is used you
 | 
					the hw device is rewritten, if possible. If this function is used you
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@
 | 
				
			||||||
#include <pulse/introspect.h>
 | 
					#include <pulse/introspect.h>
 | 
				
			||||||
#include <pulse/utf8.h>
 | 
					#include <pulse/utf8.h>
 | 
				
			||||||
#include <pulse/xmalloc.h>
 | 
					#include <pulse/xmalloc.h>
 | 
				
			||||||
 | 
					#include <pulse/timeval.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <pulsecore/sink-input.h>
 | 
					#include <pulsecore/sink-input.h>
 | 
				
			||||||
#include <pulsecore/namereg.h>
 | 
					#include <pulsecore/namereg.h>
 | 
				
			||||||
| 
						 | 
					@ -47,6 +48,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_MIX_CHANNELS 32
 | 
					#define MAX_MIX_CHANNELS 32
 | 
				
			||||||
#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
 | 
					#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
 | 
				
			||||||
 | 
					#define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
 | 
					static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -185,6 +187,8 @@ pa_sink* pa_sink_new(
 | 
				
			||||||
    s->rtpoll = NULL;
 | 
					    s->rtpoll = NULL;
 | 
				
			||||||
    s->silence = pa_silence_memblock_new(core->mempool, &s->sample_spec, 0);
 | 
					    s->silence = pa_silence_memblock_new(core->mempool, &s->sample_spec, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->min_latency = DEFAULT_MIN_LATENCY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 | 
					    s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 | 
				
			||||||
    s->thread_info.soft_volume = s->volume;
 | 
					    s->thread_info.soft_volume = s->volume;
 | 
				
			||||||
    s->thread_info.soft_muted = s->muted;
 | 
					    s->thread_info.soft_muted = s->muted;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,6 +91,8 @@ struct pa_sink {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_memblock *silence;
 | 
					    pa_memblock *silence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_usec_t min_latency; /* we won't go below this latency setting */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int (*set_state)(pa_sink *s, pa_sink_state_t state); /* may be NULL */
 | 
					    int (*set_state)(pa_sink *s, pa_sink_state_t state); /* may be NULL */
 | 
				
			||||||
    int (*set_volume)(pa_sink *s);             /* dito */
 | 
					    int (*set_volume)(pa_sink *s);             /* dito */
 | 
				
			||||||
    int (*get_volume)(pa_sink *s);             /* dito */
 | 
					    int (*get_volume)(pa_sink *s);             /* dito */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -360,13 +360,20 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
 | 
				
			||||||
    pa_memblock_unref(rchunk.memblock);
 | 
					    pa_memblock_unref(rchunk.memblock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
 | 
					pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
 | 
				
			||||||
    pa_source_output_assert_ref(o);
 | 
					    pa_source_output_assert_ref(o);
 | 
				
			||||||
    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 | 
					    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
 | 
					    if (usec < o->source->min_latency)
 | 
				
			||||||
}
 | 
					        usec = o->source->min_latency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (PA_SOURCE_OUTPUT_LINKED(o->state))
 | 
				
			||||||
 | 
					        pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        o->thread_info.requested_source_latency = usec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return usec;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_source_output_cork(pa_source_output *o, pa_bool_t b) {
 | 
					void pa_source_output_cork(pa_source_output *o, pa_bool_t b) {
 | 
				
			||||||
    pa_source_output_assert_ref(o);
 | 
					    pa_source_output_assert_ref(o);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -174,7 +174,7 @@ void pa_source_output_unlink(pa_source_output*o);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_source_output_set_name(pa_source_output *i, const char *name);
 | 
					void pa_source_output_set_name(pa_source_output *i, const char *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_source_output_set_requested_latency(pa_source_output *i, pa_usec_t usec);
 | 
					pa_usec_t pa_source_output_set_requested_latency(pa_source_output *i, pa_usec_t usec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Callable by everyone */
 | 
					/* Callable by everyone */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <pulse/utf8.h>
 | 
					#include <pulse/utf8.h>
 | 
				
			||||||
#include <pulse/xmalloc.h>
 | 
					#include <pulse/xmalloc.h>
 | 
				
			||||||
 | 
					#include <pulse/timeval.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <pulsecore/source-output.h>
 | 
					#include <pulsecore/source-output.h>
 | 
				
			||||||
#include <pulsecore/namereg.h>
 | 
					#include <pulsecore/namereg.h>
 | 
				
			||||||
| 
						 | 
					@ -41,6 +42,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "source.h"
 | 
					#include "source.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
 | 
					static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void source_free(pa_object *o);
 | 
					static void source_free(pa_object *o);
 | 
				
			||||||
| 
						 | 
					@ -162,6 +165,8 @@ pa_source* pa_source_new(
 | 
				
			||||||
    s->muted = data->muted;
 | 
					    s->muted = data->muted;
 | 
				
			||||||
    s->refresh_volume = s->refresh_muted = FALSE;
 | 
					    s->refresh_volume = s->refresh_muted = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->min_latency = DEFAULT_MIN_LATENCY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->get_latency = NULL;
 | 
					    s->get_latency = NULL;
 | 
				
			||||||
    s->set_volume = NULL;
 | 
					    s->set_volume = NULL;
 | 
				
			||||||
    s->get_volume = NULL;
 | 
					    s->get_volume = NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,6 +91,8 @@ struct pa_source {
 | 
				
			||||||
    pa_asyncmsgq *asyncmsgq;
 | 
					    pa_asyncmsgq *asyncmsgq;
 | 
				
			||||||
    pa_rtpoll *rtpoll;
 | 
					    pa_rtpoll *rtpoll;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_usec_t min_latency; /* we won't go below this latency setting */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int (*set_state)(pa_source*source, pa_source_state_t state); /* may be NULL */
 | 
					    int (*set_state)(pa_source*source, pa_source_state_t state); /* may be NULL */
 | 
				
			||||||
    int (*set_volume)(pa_source *s);         /* dito */
 | 
					    int (*set_volume)(pa_source *s);         /* dito */
 | 
				
			||||||
    int (*get_volume)(pa_source *s);         /* dito */
 | 
					    int (*get_volume)(pa_source *s);         /* dito */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,7 +163,7 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) {
 | 
				
			||||||
    t->length += 5+length;
 | 
					    t->length += 5+length;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_tagstruct_put_boolean(pa_tagstruct*t, int b) {
 | 
					void pa_tagstruct_put_boolean(pa_tagstruct*t, pa_bool_t b) {
 | 
				
			||||||
    pa_assert(t);
 | 
					    pa_assert(t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    extend(t, 1);
 | 
					    extend(t, 1);
 | 
				
			||||||
| 
						 | 
					@ -407,7 +407,7 @@ const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l) {
 | 
				
			||||||
    return t->data;
 | 
					    return t->data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) {
 | 
					int pa_tagstruct_get_boolean(pa_tagstruct*t, pa_bool_t *b) {
 | 
				
			||||||
    pa_assert(t);
 | 
					    pa_assert(t);
 | 
				
			||||||
    pa_assert(b);
 | 
					    pa_assert(b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -415,9 +415,9 @@ int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (t->data[t->rindex] == PA_TAG_BOOLEAN_TRUE)
 | 
					    if (t->data[t->rindex] == PA_TAG_BOOLEAN_TRUE)
 | 
				
			||||||
        *b = 1;
 | 
					        *b = TRUE;
 | 
				
			||||||
    else if (t->data[t->rindex] == PA_TAG_BOOLEAN_FALSE)
 | 
					    else if (t->data[t->rindex] == PA_TAG_BOOLEAN_FALSE)
 | 
				
			||||||
        *b = 0;
 | 
					        *b = FALSE;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -725,7 +725,7 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            case PA_TAG_BOOLEAN_TRUE:
 | 
					            case PA_TAG_BOOLEAN_TRUE:
 | 
				
			||||||
            case PA_TAG_BOOLEAN_FALSE:
 | 
					            case PA_TAG_BOOLEAN_FALSE:
 | 
				
			||||||
                ret = pa_tagstruct_get_boolean(t, va_arg(va, int*));
 | 
					                ret = pa_tagstruct_get_boolean(t, va_arg(va, pa_bool_t*));
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            case PA_TAG_TIMEVAL:
 | 
					            case PA_TAG_TIMEVAL:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,7 @@ void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t i);
 | 
				
			||||||
void pa_tagstruct_puts64(pa_tagstruct*t, int64_t i);
 | 
					void pa_tagstruct_puts64(pa_tagstruct*t, int64_t i);
 | 
				
			||||||
void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss);
 | 
					void pa_tagstruct_put_sample_spec(pa_tagstruct *t, const pa_sample_spec *ss);
 | 
				
			||||||
void pa_tagstruct_put_arbitrary(pa_tagstruct*t, const void *p, size_t length);
 | 
					void pa_tagstruct_put_arbitrary(pa_tagstruct*t, const void *p, size_t length);
 | 
				
			||||||
void pa_tagstruct_put_boolean(pa_tagstruct*t, int b);
 | 
					void pa_tagstruct_put_boolean(pa_tagstruct*t, pa_bool_t b);
 | 
				
			||||||
void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv);
 | 
					void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv);
 | 
				
			||||||
void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u);
 | 
					void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u);
 | 
				
			||||||
void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map);
 | 
					void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map);
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,7 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *i);
 | 
				
			||||||
int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *i);
 | 
					int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *i);
 | 
				
			||||||
int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss);
 | 
					int pa_tagstruct_get_sample_spec(pa_tagstruct *t, pa_sample_spec *ss);
 | 
				
			||||||
int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length);
 | 
					int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length);
 | 
				
			||||||
int pa_tagstruct_get_boolean(pa_tagstruct *t, int *b);
 | 
					int pa_tagstruct_get_boolean(pa_tagstruct *t, pa_bool_t *b);
 | 
				
			||||||
int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv);
 | 
					int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv);
 | 
				
			||||||
int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u);
 | 
					int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u);
 | 
				
			||||||
int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map);
 | 
					int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue