libpulse_binding/
stream.rs

1// Copyright 2017 Lyndon Brown
2//
3// This file is part of the PulseAudio Rust language binding.
4//
5// Licensed under the MIT license or the Apache license (version 2.0), at your option. You may not
6// copy, modify, or distribute this file except in compliance with said license. You can find copies
7// of these licenses either in the LICENSE-MIT and LICENSE-APACHE files, or alternatively at
8// <http://opensource.org/licenses/MIT> and <http://www.apache.org/licenses/LICENSE-2.0>
9// respectively.
10//
11// Portions of documentation are copied from the LGPL 2.1+ licensed PulseAudio C headers on a
12// fair-use basis, as discussed in the overall project readme (available in the git repository).
13
14//! Audio streams for input, output and sample upload.
15//!
16//! # Overview
17//!
18//! Audio streams form the central functionality of the sound server. Data is routed, converted and
19//! mixed from several sources before it is passed along to a final output. Currently, there are
20//! three forms of audio streams:
21//!
22//! * Playback streams: Data flows from the client to the server.
23//! * Record streams: Data flows from the server to the client.
24//! * Upload streams: Similar to playback streams, but the data is stored in the sample cache. See
25//!   [`context::scache`] for more information about controlling the sample cache.
26//!
27//! # Creating
28//!
29//! To access a stream, a [`Stream`] object must be created using [`Stream::new()`] or
30//! [`Stream::new_extended()`]. `new` is for PCM streams only, while `new_extended` can be used for
31//! both PCM and compressed audio streams. At this point the application must specify what stream
32//! format(s) it supports. See [`sample`] and [`channelmap`] for more information on the stream
33//! format parameters.
34//!
35//! **FIXME**: Those references only talk about PCM parameters, we should also have an overview
36//! page for how the [`Info`] based stream format configuration works.
37//! [Bug filed](https://bugs.freedesktop.org/show_bug.cgi?id=72265).
38//!
39//! This first step will only create a client-side object, representing the stream. To use the
40//! stream, a server-side object must be created and associated with the local object. Depending on
41//! which type of stream is desired, a different function is needed:
42//!
43//! * Playback stream: [`Stream::connect_playback()`]
44//! * Record stream: [`Stream::connect_record()`]
45//! * Upload stream: [`Stream::connect_upload()`] \(see [`context::scache`])
46//!
47//! Similar to how connections are done in contexts, connecting a stream will not generate an
48//! [`Operation`] object. Also like contexts, the application should register a state change
49//! callback, using [`Stream::set_state_callback()`], and wait for the stream to enter an active
50//! state.
51//!
52//! Note: there is a user-controllable slider in mixer applications such as pavucontrol
53//! corresponding to each of the created streams. Multiple (especially identically named) volume
54//! sliders for the same application might confuse the user. Also, the server supports only a
55//! limited number of simultaneous streams. Because of this, it is not always appropriate to create
56//! multiple streams in one application that needs to output multiple sounds. The rough guideline
57//! is: if there is no use case that would require separate user-initiated volume changes for each
58//! stream, perform the mixing inside the application.
59//!
60//! # Buffer Attributes
61//!
62//! Playback and record streams always have a server-side buffer as part of the data flow. The size
63//! of this buffer needs to be chosen in a compromise between low latency and sensitivity for buffer
64//! overflows/underruns.
65//!
66//! The buffer metrics may be controlled by the application. They are described with a
67//! [`BufferAttr`] structure.
68//!
69//! If [`FlagSet::ADJUST_LATENCY`] is set, then the `tlength`/`fragsize` parameters of this
70//! structure will be interpreted slightly differently than otherwise when passed to
71//! [`Stream::connect_record()`] and [`Stream::connect_playback()`]: the overall latency that is
72//! comprised of both the server side playback buffer length, the hardware playback buffer length
73//! and additional latencies will be adjusted in a way that it matches `tlength` resp. `fragsize`.
74//! Set [`FlagSet::ADJUST_LATENCY`] if you want to control the overall playback latency for your
75//! stream. Unset it if you want to control only the latency induced by the server-side, rewritable
76//! playback buffer. The server will try to fulfill the client’s latency requests as good as
77//! possible. However if the underlying hardware cannot change the hardware buffer length or only in
78//! a limited range, the actually resulting latency might be different from what the client
79//! requested. Thus, for synchronization clients always need to check the actual measured latency
80//! via [`Stream::get_latency()`] or a similar call, and not make any assumptions about the latency
81//! available. The function [`Stream::get_buffer_attr()`] will always return the actual size of the
82//! server-side per-stream buffer in `tlength`/`fragsize`, regardless whether
83//! [`FlagSet::ADJUST_LATENCY`] is set or not.
84//!
85//! The server-side per-stream playback buffers are indexed by a write and a read index. The
86//! application writes to the write index and the sound device reads from the read index. The read
87//! index is increased monotonically, while the write index may be freely controlled by the
88//! application. Subtracting the read index from the write index will give you the current fill
89//! level of the buffer. The read/write indexes are 64bit values and measured in bytes, they will
90//! never wrap. The current read/write index may be queried using [`Stream::get_timing_info()`]
91//! \(see below for more information). In case of a buffer underrun the read index is equal or
92//! larger than the write index. Unless the `prebuf` value is `0`, PulseAudio will temporarily pause
93//! playback in such a case, and wait until the buffer is filled up to `prebuf` bytes again. If
94//! `prebuf` is `0`, the read index may be larger than the write index, in which case silence is
95//! played. If the application writes data to indexes lower than the read index, the data is
96//! immediately lost.
97//!
98//! # Transferring Data
99//!
100//! Once the stream is up, data can start flowing between the client and the server. Two different
101//! access models can be used to transfer the data:
102//!
103//! * Asynchronous: The application registers a callback using [`Stream::set_write_callback()`] and
104//!   [`Stream::set_read_callback()`] to receive notifications that data can either be written or
105//!   read.
106//! * Polled: Query the library for available data/space using [`Stream::writable_size()`] and
107//!   [`Stream::readable_size()`] and transfer data as needed. The sizes are stored locally, in the
108//!   client end, so there is no delay when reading them.
109//!
110//! It is also possible to mix the two models freely.
111//!
112//! Once there is data/space available, it can be transferred using either [`Stream::write()`] for
113//! playback, or [`Stream::peek()`] / [`Stream::discard()`] for record. Make sure you do not
114//! overflow the playback buffers as data will be dropped.
115//!
116//! # Buffer Control
117//!
118//! The transfer buffers can be controlled through a number of operations:
119//!
120//! * [`Stream::cork()`]: Stop the playback or recording.
121//! * [`Stream::uncork()`]: Start the playback or recording.
122//! * [`Stream::trigger()`]: Start playback immediately and do not wait for the buffer to fill up to
123//!   the set trigger level.
124//! * [`Stream::prebuf()`]: Re-enable the playback trigger level.
125//! * [`Stream::drain()`]: Wait for the playback buffer to go empty. Will return an [`Operation`]
126//!   object that will indicate when the buffer is completely drained.
127//! * [`Stream::flush()`]: Drop all data from the playback or record buffer. Do not wait for it to
128//!   finish playing.
129//!
130//! # Seeking in the Playback Buffer
131//!
132//! A client application may freely seek in the playback buffer. To accomplish that the
133//! [`Stream::write()`] function takes a seek mode and an offset argument. The seek mode is one of:
134//!
135//! * [`SeekMode::Relative`]: seek relative to the current write index.
136//! * [`SeekMode::Absolute`]: seek relative to the beginning of the playback buffer, (i.e. the first
137//!   that was ever played in the stream).
138//! * [`SeekMode::RelativeOnRead`]: seek relative to the current read index. Use this to write data
139//!   to the output buffer that should be played as soon as possible.
140//! * [`SeekMode::RelativeEnd`]: seek relative to the last byte ever written.
141//!
142//! If an application just wants to append some data to the output buffer, [`SeekMode::Relative`]
143//! and an offset of `0` should be used.
144//!
145//! After a call to [`Stream::write()`] the write index will be left at the position right after the
146//! last byte of the written data.
147//!
148//! # Latency
149//!
150//! A major problem with networked audio is the increased latency caused by the network. To remedy
151//! this, PulseAudio supports an advanced system of monitoring the current latency.
152//!
153//! To get the raw data needed to calculate latencies, call [`Stream::get_timing_info()`]. This will
154//! give you a [`TimingInfo`] structure that contains everything that is known about the server side
155//! buffer transport delays and the backend active in the server. (Besides other things it contains
156//! the write and read index values mentioned above.)
157//!
158//! This structure is updated every time a [`Stream::update_timing_info()`] operation is executed.
159//! (i.e. before the first call to this function the timing information structure is not available!)
160//! Since it is a lot of work to keep this structure up-to-date manually, PulseAudio can do that
161//! automatically for you: if [`FlagSet::AUTO_TIMING_UPDATE`] is passed when connecting the stream
162//! PulseAudio will automatically update the structure every 100ms and every time a function is
163//! called that might invalidate the previously known timing data (such as [`Stream::write()`] or
164//! [`Stream::flush()`]). Please note however, that there always is a short time window when the
165//! data in the timing information structure is out-of-date. PulseAudio tries to mark these
166//! situations by setting the `write_index_corrupt` and `read_index_corrupt` fields accordingly.
167//!
168//! The raw timing data in the [`TimingInfo`] structure is usually hard to deal with. Therefore a
169//! simpler interface is available: you can call [`Stream::get_time()`] or
170//! [`Stream::get_latency()`]. The former will return the current playback time of the hardware
171//! since the stream has been started. The latter returns the overall time a sample that you write
172//! now takes to be played by the hardware. These two functions base their calculations on the same
173//! data that is returned by [`Stream::get_timing_info()`]. Hence the same rules for keeping the
174//! timing data up-to-date apply here. In case the write or read index is corrupted, these two
175//! functions will fail.
176//!
177//! Since updating the timing info structure usually requires a full network round trip and some
178//! applications monitor the timing very often PulseAudio offers a timing interpolation system. If
179//! [`FlagSet::INTERPOLATE_TIMING`] is passed when connecting the stream, [`Stream::get_time()`] and
180//! [`Stream::get_latency()`] will try to interpolate the current playback time/latency by
181//! estimating the number of samples that have been played back by the hardware since the last
182//! regular timing update. It is especially useful to combine this option with
183//! [`FlagSet::AUTO_TIMING_UPDATE`], which will enable you to monitor the current playback
184//! time/latency very precisely and very frequently without requiring a network round trip every
185//! time.
186//!
187//! # Overflow and underflow
188//!
189//! Even with the best precautions, buffers will sometime over - or underflow. To handle this
190//! gracefully, the application can be notified when this happens. Callbacks are registered using
191//! [`Stream::set_overflow_callback()`] and [`Stream::set_underflow_callback()`].
192//!
193//! # Synchronizing Multiple Playback Streams
194//!
195//! PulseAudio allows applications to fully synchronize multiple playback streams that are connected
196//! to the same output device. That means the streams will always be played back sample-by-sample
197//! synchronously. If stream operations like [`Stream::cork()`] are issued on one of the
198//! synchronized streams, they are simultaneously issued on the others.
199//!
200//! To synchronize a stream to another, just pass the “master” stream as the last argument to
201//! [`Stream::connect_playback()`]. To make sure that the freshly created stream doesn’t start
202//! playback right-away, make sure to pass [`FlagSet::START_CORKED`] and, after all streams have
203//! been created, uncork them all with a single call to [`Stream::uncork()`] for the master stream.
204//!
205//! To make sure that a particular stream doesn’t stop to play when a server side buffer underrun
206//! happens on it while the other synchronized streams continue playing and hence deviate, you need
207//! to pass a [`BufferAttr`] with `prebuf` set to `0` when connecting.
208//!
209//! # Disconnecting
210//!
211//! When a stream has served is purpose it must be disconnected with [`Stream::disconnect()`]. If
212//! you only unreference it, then it will live on and eat resources both locally and on the server
213//! until you disconnect the context. This is done automatically upon drop of the stream object.
214//!
215//! [`context::scache`]: mod@crate::context::scache
216//! [`sample`]: mod@crate::sample
217//! [`channelmap`]: mod@crate::channelmap
218//! [`Info`]: crate::format::Info
219//! [`BufferAttr`]: crate::def::BufferAttr
220//! [`TimingInfo`]: crate::def::TimingInfo
221
222use std::os::raw::{c_char, c_void};
223use std::ffi::{CStr, CString};
224use std::ptr::{null, null_mut};
225use std::borrow::Cow;
226use bitflags::bitflags;
227use num_derive::{FromPrimitive, ToPrimitive};
228use capi::pa_stream as StreamInternal;
229use crate::{channelmap, format, def, proplist, sample};
230use crate::callbacks::{self, box_closure_get_capi_ptr, get_su_capi_params, get_su_callback};
231use crate::error::{self, PAErr};
232use crate::format::InfoInternal;
233use crate::proplist::{Proplist, ProplistInternal};
234use crate::{context::Context, volume::ChannelVolumes, operation::Operation, time::MicroSeconds};
235
236pub use capi::pa_seek_mode_t as SeekMode;
237pub use capi::pa_stream_direction_t as Direction;
238
239/// An opaque stream for playback or recording.
240///
241/// Note: Saves a copy of active multi-use closure callbacks, which it frees on drop.
242pub struct Stream {
243    /// The actual C object.
244    ptr: *mut StreamInternal,
245    /// Multi-use callback closure pointers.
246    cb_ptrs: CallbackPointers,
247}
248
249unsafe impl Send for Stream {}
250unsafe impl Sync for Stream {}
251
252/// Holds copies of callback closure pointers, for those that are “multi-use” (may be fired multiple
253/// times), for freeing at the appropriate time.
254#[derive(Default)]
255struct CallbackPointers {
256    read: RequestCb,
257    write: RequestCb,
258    set_state: NotifyCb,
259    overflow: NotifyCb,
260    underflow: NotifyCb,
261    started: NotifyCb,
262    latency_update: NotifyCb,
263    moved: NotifyCb,
264    suspended: NotifyCb,
265    buffer_attr: NotifyCb,
266    event: EventCb,
267}
268
269type RequestCb = callbacks::MultiUseCallback<dyn FnMut(usize),
270    extern "C" fn(*mut StreamInternal, usize, *mut c_void)>;
271
272type NotifyCb = callbacks::MultiUseCallback<dyn FnMut(),
273    extern "C" fn(*mut StreamInternal, *mut c_void)>;
274
275type EventCb = callbacks::MultiUseCallback<dyn FnMut(String, Proplist),
276    extern "C" fn(*mut StreamInternal, name: *const c_char, pl: *mut ProplistInternal, *mut c_void)>;
277
278/// Stream state.
279#[repr(C)]
280#[derive(Debug, Copy, Clone, PartialEq, Eq)]
281#[derive(FromPrimitive, ToPrimitive)]
282pub enum State {
283    /* NOTE: This enum’s variants and variant values **must** remain identical to the `sys` crate
284       (C API) equivalent */
285
286    /// The stream is not yet connected to any sink or source.
287    Unconnected,
288    /// The stream is being created.
289    Creating,
290    /// The stream is established, you may pass audio data to it now.
291    Ready,
292    /// An error occurred that made the stream invalid.
293    Failed,
294    /// The stream has been terminated cleanly.
295    Terminated,
296}
297
298/// Check is equal to `sys` equivalent
299#[test]
300fn state_compare_capi() {
301    assert_eq!(std::mem::size_of::<State>(), std::mem::size_of::<capi::pa_stream_state_t>());
302    assert_eq!(std::mem::align_of::<State>(), std::mem::align_of::<capi::pa_stream_state_t>());
303
304    // Check order and value of variants match
305    // No point checking conversions in both directions since both are a transmute
306    assert_eq!(State::Unconnected, State::from(capi::pa_stream_state_t::Unconnected));
307    assert_eq!(State::Creating,    State::from(capi::pa_stream_state_t::Creating));
308    assert_eq!(State::Ready,       State::from(capi::pa_stream_state_t::Ready));
309    assert_eq!(State::Failed,      State::from(capi::pa_stream_state_t::Failed));
310    assert_eq!(State::Terminated,  State::from(capi::pa_stream_state_t::Terminated));
311}
312
313impl From<State> for capi::pa_stream_state_t {
314    #[inline]
315    fn from(s: State) -> Self {
316        unsafe { std::mem::transmute(s) }
317    }
318}
319impl From<capi::pa_stream_state_t> for State {
320    #[inline]
321    fn from(s: capi::pa_stream_state_t) -> Self {
322        unsafe { std::mem::transmute(s) }
323    }
324}
325
326impl State {
327    /// Checks if the passed state is one of the connected states.
328    #[inline]
329    pub fn is_good(self) -> bool {
330        self == State::Creating || self == State::Ready
331    }
332}
333
334bitflags! {
335    /// Flag set.
336    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
337    #[repr(transparent)]
338    pub struct FlagSet: u32 {
339        /// Flag to pass when no specific options are needed.
340        const NOFLAGS = capi::PA_STREAM_NOFLAGS;
341
342        /// Create the stream corked, requiring an explicit [`Stream::uncork()`] call to uncork it.
343        const START_CORKED = capi::PA_STREAM_START_CORKED;
344
345        /// Interpolate the latency for this stream. When enabled, [`Stream::get_latency()`] and
346        /// [`Stream::get_time()`] will try to estimate the current record/playback time based on
347        /// the local time that passed since the last timing info update. Using this option has the
348        /// advantage of not requiring a whole round trip when the current playback/recording time
349        /// is needed. Consider using this option when requesting latency information frequently.
350        /// This is especially useful on long latency network connections. It makes a lot of sense
351        /// to combine this option with [`AUTO_TIMING_UPDATE`].
352        ///
353        /// [`AUTO_TIMING_UPDATE`]: Self::AUTO_TIMING_UPDATE
354        const INTERPOLATE_TIMING = capi::PA_STREAM_INTERPOLATE_TIMING;
355
356        /// Don’t force the time to increase monotonically. If this option is enabled,
357        /// [`Stream::get_time()`] will not necessarily return always monotonically increasing time
358        /// values on each call. This may confuse applications which cannot deal with time going
359        /// ‘backwards’, but has the advantage that bad transport latency estimations that caused
360        /// the time to jump ahead can be corrected quickly, without the need to wait.
361        const NOT_MONOTONIC = capi::PA_STREAM_NOT_MONOTONIC;
362
363        /// If set timing update requests are issued periodically automatically. Combined with
364        /// [`INTERPOLATE_TIMING`] you will be able to query the current time and latency with
365        /// [`Stream::get_time()`] and [`Stream::get_latency()`] at all times without a packet round
366        /// trip.
367        ///
368        /// [`INTERPOLATE_TIMING`]: Self::INTERPOLATE_TIMING
369        const AUTO_TIMING_UPDATE = capi::PA_STREAM_AUTO_TIMING_UPDATE;
370
371        /// Don’t remap channels by their name, instead map them simply by their index. Implies
372        /// [`NO_REMIX_CHANNELS`](Self::NO_REMIX_CHANNELS).
373        const NO_REMAP_CHANNELS = capi::PA_STREAM_NO_REMAP_CHANNELS;
374
375        /// When remapping channels by name, don’t upmix or downmix them to related channels. Copy
376        /// them into matching channels of the device 1:1.
377        const NO_REMIX_CHANNELS = capi::PA_STREAM_NO_REMIX_CHANNELS;
378
379        /// Use the sample format of the sink/device this stream is being connected to, and possibly
380        /// ignore the format the sample spec contains -- but you still have to pass a valid value
381        /// in it as a hint to PulseAudio what would suit your stream best. If this is used you
382        /// should query the used sample format after creating the stream by using
383        /// [`Stream::get_sample_spec()`]. Also, if you specified manual buffer metrics it is
384        /// recommended to update them with [`Stream::set_buffer_attr()`] to compensate for the
385        /// changed frame sizes.
386        ///
387        /// When creating streams with [`Stream::new_extended()`], this flag has no effect. If you
388        /// specify a format with PCM encoding, and you want the server to choose the sample format,
389        /// then you should leave the sample format unspecified in the [`Info`] object. This also
390        /// means that you can’t use [`Info::new_from_sample_spec()`], because that function always
391        /// sets the sample format.
392        ///
393        /// [`Info`]: crate::format::Info
394        /// [`Info::new_from_sample_spec()`]: crate::format::Info::new_from_sample_spec
395        const FIX_FORMAT = capi::PA_STREAM_FIX_FORMAT;
396
397        /// Use the sample rate of the sink, and possibly ignore the rate the sample spec contains.
398        /// Usage similar to [`FIX_FORMAT`].
399        ///
400        /// When creating streams with [`Stream::new_extended()`], this flag has no effect. If you
401        /// specify a format with PCM encoding, and you want the server to choose the sample rate,
402        /// then you should leave the rate unspecified in the [`Info`] object. This also means that
403        /// you can’t use [`Info::new_from_sample_spec()`], because that function always sets the
404        /// sample rate.
405        ///
406        /// [`FIX_FORMAT`]: Self::FIX_FORMAT
407        /// [`Info`]: crate::format::Info
408        /// [`Info::new_from_sample_spec()`]: crate::format::Info::new_from_sample_spec
409        const FIX_RATE = capi::PA_STREAM_FIX_RATE;
410
411        /// Use the number of channels and the channel map of the sink, and possibly ignore the number
412        /// of channels and the map the sample spec and the passed channel map contains. Usage similar
413        /// to [`FIX_FORMAT`].
414        ///
415        /// When creating streams with [`Stream::new_extended()`], this flag has no effect. If you
416        /// specify a format with PCM encoding, and you want the server to choose the channel count
417        /// and/or channel map, then you should leave the channels and/or the channel map
418        /// unspecified in the [`Info`] object. This also means that you can’t use
419        /// [`Info::new_from_sample_spec()`], because that function always sets the channel count
420        /// (but if you only want to leave the channel map unspecified, then
421        /// [`Info::new_from_sample_spec()`] works, because the channel map parameter is optional).
422        ///
423        /// [`FIX_FORMAT`]: Self::FIX_FORMAT
424        /// [`Info`]: crate::format::Info
425        /// [`Info::new_from_sample_spec()`]: crate::format::Info::new_from_sample_spec
426        const FIX_CHANNELS = capi::PA_STREAM_FIX_CHANNELS;
427
428        /// Don’t allow moving of this stream to another sink/device. Useful if you use any of the
429        /// `Fix*` flags and want to make sure that resampling never takes place -- which might
430        /// happen if the stream is moved to another sink/source with a different sample
431        /// spec/channel map.
432        const DONT_MOVE = capi::PA_STREAM_DONT_MOVE;
433
434        /// Allow dynamic changing of the sampling rate during playback with
435        /// [`Stream::update_sample_rate()`].
436        const VARIABLE_RATE = capi::PA_STREAM_VARIABLE_RATE;
437
438        /// Find peaks instead of resampling.
439        const PEAK_DETECT = capi::PA_STREAM_PEAK_DETECT;
440
441        /// Create in muted state. If neither [`START_UNMUTED`] nor this is specified, it is left to
442        /// the server to decide whether to create the stream in muted or in un-muted state.
443        ///
444        /// [`START_UNMUTED`]: Self::START_UNMUTED
445        const START_MUTED = capi::PA_STREAM_START_MUTED;
446
447        /// Try to adjust the latency of the sink/source based on the requested buffer metrics and
448        /// adjust buffer metrics accordingly. Also see [`BufferAttr`]. This option may not be
449        /// specified at the same time as [`EARLY_REQUESTS`].
450        ///
451        /// [`EARLY_REQUESTS`]: Self::EARLY_REQUESTS
452        /// [`BufferAttr`]: crate::def::BufferAttr
453        const ADJUST_LATENCY = capi::PA_STREAM_ADJUST_LATENCY;
454
455        /// Enable compatibility mode for legacy clients that rely on a “classic” hardware device
456        /// fragment-style playback model. If this option is set, the `minreq` value of the buffer
457        /// metrics gets a new meaning: instead of just specifying that no requests asking for less
458        /// new data than this value will be made to the client it will also guarantee that requests
459        /// are generated as early as this limit is reached. This flag should only be set in very
460        /// few situations where compatibility with a fragment-based playback model needs to be kept
461        /// and the client applications cannot deal with data requests that are delayed to the
462        /// latest moment possible. (Usually these are programs that use usleep() or a similar call
463        /// in their playback loops instead of sleeping on the device itself.) Also see
464        /// [`BufferAttr`]. This option may not be specified at the same time as [`ADJUST_LATENCY`].
465        ///
466        /// [`ADJUST_LATENCY`]: Self::ADJUST_LATENCY
467        /// [`BufferAttr`]: crate::def::BufferAttr
468        const EARLY_REQUESTS = capi::PA_STREAM_EARLY_REQUESTS;
469
470        /// If set this stream won’t be taken into account when it is checked whether the device
471        /// this stream is connected to should auto-suspend.
472        const DONT_INHIBIT_AUTO_SUSPEND = capi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND;
473
474        /// Create in unmuted state. If neither [`START_MUTED`] nor this is specified, it is left to
475        /// the server to decide whether to create the stream in muted or in unmuted state.
476        ///
477        /// [`START_MUTED`]: Self::START_MUTED
478        const START_UNMUTED = capi::PA_STREAM_START_UNMUTED;
479
480        /// If the sink/source this stream is connected to is suspended during the creation of this
481        /// stream, cause it to fail. If the sink/source is being suspended during creation of this
482        /// stream, make sure this stream is terminated.
483        const FAIL_ON_SUSPEND = capi::PA_STREAM_FAIL_ON_SUSPEND;
484
485        /// If a volume is passed when this stream is created, consider it relative to the sink’s
486        /// current volume, never as absolute device volume. If this is not specified the volume
487        /// will be consider absolute when the sink is in flat volume mode, relative otherwise.
488        const RELATIVE_VOLUME = capi::PA_STREAM_RELATIVE_VOLUME;
489
490        /// Used to tag content that will be rendered by passthrough sinks. The data will be left as
491        /// is and not reformatted, resampled.
492        const PASSTHROUGH = capi::PA_STREAM_PASSTHROUGH;
493    }
494}
495
496impl Default for FlagSet {
497    fn default() -> Self {
498        Self::NOFLAGS
499    }
500}
501
502/// Common event names supplied to the [`Stream::set_event_callback()`] callback.
503pub mod event_names {
504    use capi;
505
506    /// A stream policy/meta event requesting that an application should cork a specific stream.
507    pub const EVENT_REQUEST_CORK: &str = capi::PA_STREAM_EVENT_REQUEST_CORK;
508
509    /// A stream policy/meta event requesting that an application should cork a specific stream.
510    pub const EVENT_REQUEST_UNCORK: &str = capi::PA_STREAM_EVENT_REQUEST_UNCORK;
511
512    /// A stream event notifying that the stream is going to be disconnected because the underlying
513    /// sink changed and no longer supports the format that was originally negotiated. Clients need
514    /// to connect a new stream to renegotiate a format and continue playback.
515    pub const EVENT_FORMAT_LOST: &str = capi::PA_STREAM_EVENT_FORMAT_LOST;
516}
517
518/// Result type for the [`Stream::peek()`] method. See documentation of the method itself for more
519/// information.
520#[derive(Debug)]
521pub enum PeekResult<'a> {
522    /// No data (Null data pointer and size of 0 returned by PA).
523    Empty,
524    /// Data hole with given size (Null pointer with non-zero size returned by PA).
525    Hole(usize),
526    /// Data available, with slice into memory returned by PA.
527    Data(&'a [u8]),
528}
529
530/// Result type for [`Stream::get_latency()`].
531#[derive(Debug, Copy, Clone, PartialEq, Eq)]
532pub enum Latency {
533    /// No latency.
534    None,
535    /// A positive (greater than zero) amount of latency.
536    Positive(MicroSeconds),
537    /// A negative (less than zero) amount of latency.
538    Negative(MicroSeconds),
539}
540
541impl Stream {
542    /// Creates a new, unconnected stream with the specified name and sample type.
543    ///
544    /// It is recommended to use [`new_with_proplist()`] instead and specify some initial
545    /// properties.
546    ///
547    /// # Params
548    ///
549    /// * `ctx`: The context to create this stream in
550    /// * `name`: A name for this stream
551    /// * `ss`: The desired sample format
552    /// * `map`: The desired channel map, or `None` for default
553    ///
554    /// [`new_with_proplist()`]: Self::new_with_proplist
555    pub fn new(ctx: &mut Context, name: &str, ss: &sample::Spec, map: Option<&channelmap::Map>)
556        -> Option<Self>
557    {
558        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
559        // as_ptr() giving dangling pointers!
560        let c_name = CString::new(name).unwrap();
561
562        let p_map = map.map_or(null::<capi::pa_channel_map>(), |m| m.as_ref());
563
564        let ptr = unsafe { capi::pa_stream_new(ctx.ptr, c_name.as_ptr(), ss.as_ref(), p_map) };
565        match ptr.is_null() {
566            false => Some(Self::from_raw(ptr)),
567            true => None,
568        }
569    }
570
571    /// Creates a new, unconnected stream with the specified name and sample type, and specify the
572    /// initial stream property list.
573    ///
574    /// # Params
575    ///
576    /// * `ctx`: The context to create this stream in
577    /// * `name`: A name for this stream
578    /// * `ss`: The desired sample format
579    /// * `map`: The desired channel map, or `None` for default
580    /// * `proplist`: The initial property list
581    pub fn new_with_proplist(ctx: &mut Context, name: &str, ss: &sample::Spec,
582        map: Option<&channelmap::Map>, proplist: &mut Proplist) -> Option<Self>
583    {
584        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
585        // as_ptr() giving dangling pointers!
586        let c_name = CString::new(name).unwrap();
587
588        let p_map = map.map_or(null::<capi::pa_channel_map>(), |m| m.as_ref());
589
590        let ptr = unsafe {
591            capi::pa_stream_new_with_proplist(ctx.ptr, c_name.as_ptr(), ss.as_ref(),
592                p_map, proplist.0.ptr)
593        };
594        match ptr.is_null() {
595            false => Some(Self::from_raw(ptr)),
596            true => None,
597        }
598    }
599
600    /// Creates a new, unconnected stream with the specified name, the set of formats this client
601    /// can provide, and an initial list of properties.
602    ///
603    /// While connecting, the server will select the most appropriate format which the client must
604    /// then provide.
605    ///
606    /// Will panic if the `formats` array is longer than can be communicated to the C function.
607    ///
608    /// # Params
609    ///
610    /// * `ctx`: The context to create this stream in
611    /// * `name`: A name for this stream
612    /// * `formats`: The list of formats that can be provided
613    /// * `proplist`: The initial property list
614    pub fn new_extended(ctx: &mut Context, name: &str, formats: &[&format::Info],
615        proplist: &mut Proplist) -> Option<Self>
616    {
617        assert!(formats.len() <= u32::MAX as usize);
618        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
619        // as_ptr() giving dangling pointers!
620        let c_name = CString::new(name).unwrap();
621
622        // Create array of format::InfoInternal pointers from provided array of `Info` pointers.
623        let mut info_ptrs: Vec<*const capi::pa_format_info> = Vec::with_capacity(formats.len());
624        for format in formats {
625            info_ptrs.push(format.ptr as *const capi::pa_format_info);
626        }
627
628        let ptr = unsafe {
629            capi::pa_stream_new_extended(ctx.ptr, c_name.as_ptr(), info_ptrs.as_ptr(),
630                info_ptrs.len() as u32, proplist.0.ptr)
631        };
632        match ptr.is_null() {
633            false => Some(Self::from_raw(ptr)),
634            true => None,
635        }
636    }
637
638    /// Creates a new `Stream` from an existing [`StreamInternal`] pointer.
639    #[inline]
640    fn from_raw(ptr: *mut StreamInternal) -> Self {
641        assert_eq!(false, ptr.is_null());
642        Self { ptr: ptr, cb_ptrs: Default::default() }
643    }
644
645    /// Gets the current state of the stream.
646    #[inline]
647    pub fn get_state(&self) -> State {
648        unsafe { capi::pa_stream_get_state(self.ptr).into() }
649    }
650
651    /// Gets the sink input resp. source output index this stream is identified in the server with.
652    ///
653    /// This is useful with the introspection functions such as
654    /// [`Introspector::get_sink_input_info()`] or [`Introspector::get_source_output_info()`].
655    ///
656    /// [`Introspector::get_sink_input_info()`]: crate::context::introspect::Introspector::get_sink_input_info
657    /// [`Introspector::get_source_output_info()`]: crate::context::introspect::Introspector::get_source_output_info
658    pub fn get_index(&self) -> Option<u32> {
659        match unsafe { capi::pa_stream_get_index(self.ptr) } {
660            def::INVALID_INDEX => None,
661            r => Some(r),
662        }
663    }
664
665    /// Gets the index of the sink or source this stream is connected to in the server.
666    ///
667    /// This is useful with the introspection functions such as
668    /// [`Introspector::get_sink_info_by_index()`] or [`Introspector::get_source_info_by_index()`].
669    ///
670    /// Please note that streams may be moved between sinks/sources and thus it is recommended to
671    /// use [`set_moved_callback()`] to be notified about this.
672    ///
673    /// [`set_moved_callback()`]: Self::set_moved_callback
674    /// [`Introspector::get_sink_info_by_index()`]: crate::context::introspect::Introspector::get_sink_info_by_index
675    /// [`Introspector::get_source_info_by_index()`]: crate::context::introspect::Introspector::get_source_info_by_index
676    pub fn get_device_index(&self) -> Option<u32> {
677        match unsafe { capi::pa_stream_get_device_index(self.ptr) } {
678            def::INVALID_INDEX => None,
679            r => Some(r),
680        }
681    }
682
683    /// Gets the name of the sink or source this stream is connected to in the server.
684    ///
685    /// This is useful with the introspection functions such as
686    /// [`Introspector::get_sink_info_by_name()`] or [`Introspector::get_source_info_by_name()`].
687    ///
688    /// Please note that streams may be moved between sinks/sources and thus it is recommended to
689    /// use [`set_moved_callback()`] to be notified about this.
690    ///
691    /// [`set_moved_callback()`]: Self::set_moved_callback
692    /// [`Introspector::get_sink_info_by_name()`]: crate::context::introspect::Introspector::get_sink_info_by_name
693    /// [`Introspector::get_source_info_by_name()`]: crate::context::introspect::Introspector::get_source_info_by_name
694    pub fn get_device_name(&self) -> Option<Cow<'static, str>> {
695        let ptr: *const c_char = unsafe { capi::pa_stream_get_device_name(self.ptr) };
696        match ptr.is_null() {
697            false => Some(unsafe { CStr::from_ptr(ptr).to_string_lossy() }),
698            true => None,
699        }
700    }
701
702    /// Checks whether or not the sink or source this stream is connected to has been suspended.
703    pub fn is_suspended(&self) -> Result<bool, PAErr> {
704        match unsafe { capi::pa_stream_is_suspended(self.ptr) } {
705            0 => Ok(false),
706            1 => Ok(true),
707            e => Err(PAErr(e)),
708        }
709    }
710
711    /// Checks whether or not this stream has been corked.
712    pub fn is_corked(&self) -> Result<bool, PAErr> {
713        match unsafe { capi::pa_stream_is_corked(self.ptr) } {
714            0 => Ok(false),
715            1 => Ok(true),
716            e => Err(PAErr(e)),
717        }
718    }
719
720    /// Connects the stream to a sink.
721    ///
722    /// It is strongly recommended to pass `None` in both `dev` and `volume` and to set neither
723    /// [`FlagSet::START_MUTED`] nor [`FlagSet::START_UNMUTED`] -- unless these options are directly
724    /// dependent on user input or configuration.
725    ///
726    /// If you follow this rule then the sound server will have the full flexibility to choose the
727    /// device, volume and mute status automatically, based on server-side policies, heuristics and
728    /// stored information from previous uses. Also the server may choose to reconfigure audio
729    /// devices to make other sinks/sources or capabilities available to be able to accept the
730    /// stream.
731    ///
732    /// Before PA 0.9.20 it was not defined whether the ‘volume’ parameter was interpreted relative
733    /// to the sink’s current volume or treated as an absolute device volume. Since PA 0.9.20 it is
734    /// an absolute volume when the sink is in flat volume mode, and relative otherwise, thus making
735    /// sure the volume passed here has always the same semantics as the volume passed to
736    /// [`Introspector::set_sink_input_volume()`]. It is possible to figure out whether flat volume
737    /// mode is in effect for a given sink by calling [`Introspector::get_sink_info_by_name()`].
738    ///
739    /// Since PA 5.0, it’s possible to specify a single-channel volume even if the stream has
740    /// multiple channels. In that case the same volume is applied to all channels.
741    ///
742    /// # Params
743    ///
744    /// * `dev`: Name of the sink to connect to, or `None` to let the server decide
745    /// * `attr`: Buffering attributes, or `None` for default
746    /// * `flags`: Additional flags, or `0` for default
747    /// * `volume`: Initial volume, or `None` for default
748    /// * `sync_stream`: Synchronize this stream with the specified one, or `None` for a standalone
749    ///   stream.
750    ///
751    /// [`Introspector::set_sink_input_volume()`]: crate::context::introspect::Introspector::set_sink_input_volume
752    /// [`Introspector::get_sink_info_by_name()`]: crate::context::introspect::Introspector::get_sink_info_by_name
753    pub fn connect_playback(&mut self, dev: Option<&str>, attr: Option<&def::BufferAttr>,
754        flags: FlagSet, volume: Option<&ChannelVolumes>, sync_stream: Option<&mut Self>)
755        -> Result<(), PAErr>
756    {
757        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
758        // as_ptr() giving dangling pointers!
759        let c_dev = match dev {
760            Some(dev) => CString::new(dev).unwrap(),
761            None => CString::new("").unwrap(),
762        };
763
764        let p_attr = attr.map_or(null::<capi::pa_buffer_attr>(), |a| a.as_ref());
765        let p_vol = volume.map_or(null::<capi::pa_cvolume>(), |v| v.as_ref());
766        let p_sync = sync_stream.map_or(null_mut::<StreamInternal>(), |s| s.ptr);
767        let p_dev = dev.map_or(null::<c_char>(), |_| c_dev.as_ptr() as *const c_char);
768
769        let r = unsafe {
770            capi::pa_stream_connect_playback(self.ptr, p_dev, p_attr, flags.bits(), p_vol, p_sync)
771        };
772        match r {
773            0 => Ok(()),
774            e => Err(PAErr(e)),
775        }
776    }
777
778    /// Connects the stream to a source.
779    ///
780    /// # Params
781    ///
782    /// * `dev`: Name of the source to connect to, or `None` to let the server decide
783    /// * `attr`: Buffering attributes, or `None` for default
784    /// * `flags`: Additional flags, or `0` for default
785    pub fn connect_record(&mut self, dev: Option<&str>, attr: Option<&def::BufferAttr>,
786        flags: FlagSet) -> Result<(), PAErr>
787    {
788        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
789        // as_ptr() giving dangling pointers!
790        let c_dev = match dev {
791            Some(dev) => CString::new(dev).unwrap(),
792            None => CString::new("").unwrap(),
793        };
794
795        let p_attr = attr.map_or(null::<capi::pa_buffer_attr>(), |a| a.as_ref());
796        let p_dev = dev.map_or(null::<c_char>(), |_| c_dev.as_ptr() as *const c_char);
797
798        match unsafe { capi::pa_stream_connect_record(self.ptr, p_dev, p_attr, flags.bits()) } {
799            0 => Ok(()),
800            e => Err(PAErr(e)),
801        }
802    }
803
804    /// Makes this stream a sample upload stream.
805    ///
806    /// (See [`scache`](mod@crate::context::scache)).
807    pub fn connect_upload(&mut self, length: usize) -> Result<(), PAErr> {
808        match unsafe { capi::pa_stream_connect_upload(self.ptr, length) } {
809            0 => Ok(()),
810            e => Err(PAErr(e)),
811        }
812    }
813
814    /// Finishes the sample upload, the stream name will become the sample name.
815    ///
816    /// You cancel a sample upload by issuing [`disconnect()`](Self::disconnect).
817    pub fn finish_upload(&mut self) -> Result<(), PAErr> {
818        match unsafe { capi::pa_stream_finish_upload(self.ptr) } {
819            0 => Ok(()),
820            e => Err(PAErr(e)),
821        }
822    }
823
824    /// Disconnects a stream from a source/sink.
825    pub fn disconnect(&mut self) -> Result<(), PAErr> {
826        match unsafe { capi::pa_stream_disconnect(self.ptr) } {
827            0 => Ok(()),
828            e => Err(PAErr(e)),
829        }
830    }
831
832    /// Prepares writing data to the server (for playback streams).
833    ///
834    /// This function may be used to optimize the number of memory copies when doing playback
835    /// (“zero-copy”). It is recommended to call this function before each call to [`write()`]. It
836    /// is used to obtain a chunk of PA internally allocated memory, into which you can directly
837    /// write your data before calling [`write()`] to actually execute the write.
838    ///
839    /// This function should be called with `nbytes` set to the number of bytes you want to write,
840    /// or `None`, in which case the size will be chosen automatically (which is recommended).
841    ///
842    /// The return value is a `Result` type, with the `Ok` variant wrapping an `Option`. `Err` will
843    /// be returned if PA encountered an error; `Ok(None)` will be  returned if it appeared to be
844    /// successful, but the pointer returned was `NULL`, otherwise the buffer will be returned as
845    /// `Ok(Some(_))`.
846    ///
847    /// After placing your data in the memory area returned, call [`write()`] with a sub-slice of
848    /// it, to actually execute the write. **Note**, the buffer may only be used once, i.e. if you
849    /// were thinking of getting a large buffer, placing a large chunk of data into it, then perform
850    /// multiple small writes from it, you **cannot** do this. Any attempt at accessing the memory
851    /// returned after the following [`write()`] or [`cancel_write()`] is invalid.
852    ///
853    /// If you want to cancel a previously called `begin_write()` without calling [`write()`] use
854    /// [`cancel_write()`].
855    ///
856    /// The memory should **not** be explicitly freed by the caller.
857    ///
858    /// An invocation of [`write()`] should “quickly” follow a `begin_write()`. It is not
859    /// recommended letting an unbounded amount of time pass after calling `begin_write()` and
860    /// before calling [`write()`]. Calling `begin_write()` twice without calling [`write()`] or
861    /// [`cancel_write()`] in between will return exactly the same `data` pointer and `nbytes`
862    /// values.
863    ///
864    /// [`write()`]: Self::write
865    /// [`cancel_write()`]: Self::cancel_write
866    pub fn begin_write<'a>(&mut self, nbytes: Option<usize>)
867        -> Result<Option<&'a mut [u8]>, PAErr>
868    {
869        let mut data_ptr = null_mut::<c_void>();
870        // If user asks for size to be automatically chosen by PA, we pass in std::usize::MAX
871        // (-1 as size_t) to signal this.
872        let mut nbytes_tmp = nbytes.unwrap_or(std::usize::MAX);
873        match unsafe { capi::pa_stream_begin_write(self.ptr, &mut data_ptr, &mut nbytes_tmp) } {
874            0 => match data_ptr.is_null() {
875                true => Ok(None),
876                false => {
877                    let slice =
878                        unsafe { std::slice::from_raw_parts_mut(data_ptr as *mut u8, nbytes_tmp) };
879                    Ok(Some(slice))
880                },
881            },
882            e => Err(PAErr(e)),
883        }
884    }
885
886    /// Reverses the effect of [`begin_write()`] dropping any data that has already been placed in
887    /// the memory area returned by [`begin_write()`].
888    ///
889    /// Only valid to call after a call to [`begin_write()`] has been made, and neither
890    /// `cancel_write()` nor [`write()`] have been called yet. Accessing the memory previously
891    /// returned by [`begin_write()`] after calling this function is invalid.
892    ///
893    /// [`write()`]: Self::write
894    /// [`begin_write()`]: Self::begin_write
895    pub fn cancel_write(&mut self) -> Result<(), PAErr> {
896        match unsafe { capi::pa_stream_cancel_write(self.ptr) } {
897            0 => Ok(()),
898            e => Err(PAErr(e)),
899        }
900    }
901
902    /// Writes some data to the server (for playback streams).
903    ///
904    /// If `free_cb` is provided, this routine is called when all data has been written out. An
905    /// internal reference to the specified data is kept, the data is not copied. If `None`, the
906    /// data is copied into an internal buffer.
907    ///
908    /// The client may freely seek around in the output buffer. For most applications it is typical
909    /// to pass `0` and [`SeekMode::Relative`] as values for the arguments `offset` and `seek`
910    /// respectively. After a successful write call the write index will be at the position after
911    /// where this chunk of data has been written to.
912    ///
913    /// As an optimization for avoiding needless memory copies you may call [`begin_write()`] before
914    /// this call and then place your audio data directly in the memory area returned by that call.
915    /// Then, pass a pointer to that memory area to `write()`. After the invocation of `write()` the
916    /// memory area may no longer be accessed. Any further explicit freeing of the memory area is
917    /// not necessary. It is OK to write to the memory area returned by [`begin_write()`] only
918    /// partially with this call, skipping bytes both at the end and at the beginning of the
919    /// reserved memory area.
920    ///
921    /// # Params
922    ///
923    /// * `data`: The data to write. The length must be in multiples of the stream’s sample spec
924    ///   frame size.
925    /// * `free_cb`: A cleanup routine for the data or `None` to request an internal copy of the
926    ///   data.
927    /// * `offset`: Offset for seeking. Must be `0` for upload streams. Must be in multiples of the
928    ///   stream’s sample spec frame size.
929    /// * `seek`: Seek mode. Must be [`SeekMode::Relative`] for upload streams.
930    ///
931    /// [`begin_write()`]: Self::begin_write
932    pub fn write(&mut self, data: &[u8], free_cb: Option<def::FreeCb>, offset: i64,
933        seek: SeekMode) -> Result<(), PAErr>
934    {
935        debug_assert_eq!(0, data.len().checked_rem(self.get_sample_spec().unwrap().frame_size())
936            .unwrap());
937        let r = unsafe {
938            capi::pa_stream_write(self.ptr, data.as_ptr() as *const c_void, data.len(), free_cb,
939                offset, seek)
940        };
941        match r {
942            0 => Ok(()),
943            e => Err(PAErr(e)),
944        }
945    }
946
947    /// Writes some data to the server (for playback streams).
948    ///
949    /// This function does exactly the same as [`write()`] as though `None` had been specified for
950    /// the `free_cb` param. I.e. an internal copy will be made of the provided data.
951    ///
952    /// # Params
953    ///
954    /// * `data`: The data to write. The length must be in multiples of the stream’s sample spec
955    ///   frame size.
956    /// * `offset`: Offset for seeking. Must be `0` for upload streams. Must be in multiples of the
957    ///   stream’s sample spec frame size.
958    /// * `seek`: Seek mode. Must be [`SeekMode::Relative`] for upload streams.
959    ///
960    /// [`write()`]: Self::write
961    #[inline(always)]
962    pub fn write_copy(&mut self, data: &[u8], offset: i64, seek: SeekMode) -> Result<(), PAErr> {
963        self.write(data, None, offset, seek)
964    }
965
966    /// Writes some data to the server (for playback streams).
967    ///
968    /// This function does exactly the same as [`write()`] with the only difference being that a
969    /// void pointer is provided along with the `free_cb` callback pointer, and this void pointer
970    /// will be passed to the callback instead of the `data` pointer.
971    ///
972    /// # Params
973    ///
974    /// * `data`: The data to write. The length must be in multiples of the stream’s sample spec
975    ///   frame size.
976    /// * `free_cb`: A cleanup routine for the data or `None` to request an internal copy of the
977    ///   data. If provided, the accompanying data pointer will be supplied to the callback.
978    /// * `offset`: Offset for seeking. Must be `0` for upload streams.
979    /// * `seek`: Seek mode, must be [`SeekMode::Relative`] for upload streams.
980    ///
981    /// [`write()`]: Self::write
982    #[cfg(any(doc, feature = "pa_v6"))]
983    #[cfg_attr(docsrs, doc(cfg(feature = "pa_v6")))]
984    pub fn write_ext_free(&mut self, data: &[u8], free_cb: Option<(def::FreeCb, *mut c_void)>,
985        offset: i64, seek: SeekMode) -> Result<(), PAErr>
986    {
987        let (cb_f, cb_d) = match free_cb {
988            Some((f, d)) => (Some(f), d),
989            None => (None, null_mut::<c_void>()),
990        };
991        debug_assert_eq!(0, data.len().checked_rem(self.get_sample_spec().unwrap().frame_size())
992            .unwrap());
993        let r = unsafe {
994            capi::pa_stream_write_ext_free(self.ptr, data.as_ptr() as *const c_void, data.len(),
995                cb_f, cb_d, offset, seek.into())
996        };
997        match r {
998            0 => Ok(()),
999            e => Err(PAErr(e)),
1000        }
1001    }
1002
1003    /// Reads the next fragment from the buffer (for recording streams).
1004    ///
1005    /// This function returns one of the [`PeekResult`] variants - either [`Empty`], [`Hole`] or
1006    /// [`Data`]:
1007    ///
1008    ///  * If there is data at the current read index, the [`Data`] variant will be returned, which
1009    ///    contains a slice giving a view of the data. (The length of this slice can be less or more
1010    ///    than a complete fragment). This is pointing into an internal buffer, so obviously you
1011    ///    must make a copy of it if you want to keep it.
1012    ///  * If there is no data at the current read index, it means that either the buffer is empty
1013    ///    or it contains a hole (that is, the write index is ahead of the read index but there’s no
1014    ///    data where the read index points at). If the buffer is empty, the [`Empty`] result
1015    ///    variant will be returned. If there is a hole, the [`Hole`] variant will be returned,
1016    ///    containing the length of the hole in bytes.
1017    ///
1018    /// Use [`discard()`] to actually remove the data from the buffer and move the read index
1019    /// forward. [`discard()`] should not be called if the buffer is empty, but it should be called
1020    /// if there is a hole.
1021    ///
1022    /// [`Empty`]: PeekResult::Empty
1023    /// [`Hole`]: PeekResult::Hole
1024    /// [`Data`]: PeekResult::Data
1025    /// [`discard()`]: Self::discard
1026    pub fn peek<'a>(&mut self) -> Result<PeekResult<'a>, PAErr> {
1027        let mut data_ptr = null::<c_void>();
1028        let mut nbytes: usize = 0;
1029        // Note, C function returns an i32, but documentation does not mention any use of it, so we
1030        // discard it.
1031        match unsafe { capi::pa_stream_peek(self.ptr, &mut data_ptr, &mut nbytes) } {
1032            0 => {
1033                if data_ptr.is_null() {
1034                    match nbytes {
1035                        0 => Ok(PeekResult::Empty),
1036                        _ => Ok(PeekResult::Hole(nbytes)),
1037                    }
1038                }
1039                else {
1040                    let slice =
1041                        unsafe { std::slice::from_raw_parts(data_ptr as *const u8, nbytes) };
1042                    Ok(PeekResult::Data(slice))
1043                }
1044            },
1045            e => Err(PAErr(e)),
1046        }
1047    }
1048
1049    /// Removes the current fragment on record streams.
1050    ///
1051    /// It is invalid to do this without first calling [`peek()`](Self::peek).
1052    ///
1053    /// Note: The original C function name used the term `drop`; We instead use `discard` here to
1054    /// avoid conflict with the Rust `Drop` trait!
1055    pub fn discard(&mut self) -> Result<(), PAErr> {
1056        match unsafe { capi::pa_stream_drop(self.ptr) } {
1057            0 => Ok(()),
1058            e => Err(PAErr(e)),
1059        }
1060    }
1061
1062    /// Gets the number of bytes requested by the server that have not yet been written.
1063    ///
1064    /// It is possible to write more than this amount, up to the stream’s [`buffer_attr.maxlength`]
1065    /// bytes. This is usually not desirable, though, as it would increase stream latency to be
1066    /// higher than requested ([`buffer_attr.tlength`]).
1067    ///
1068    /// [`buffer_attr.maxlength`]: crate::def::BufferAttr.maxlength
1069    /// [`buffer_attr.tlength`]: crate::def::BufferAttr.tlength
1070    pub fn writable_size(&self) -> Option<usize> {
1071        match unsafe { capi::pa_stream_writable_size(self.ptr) } {
1072            std::usize::MAX => None,
1073            r => Some(r),
1074        }
1075    }
1076
1077    /// Gets the number of bytes that may be read using [`peek()`](Self::peek).
1078    ///
1079    /// Returns `None` on error.
1080    pub fn readable_size(&self) -> Option<usize> {
1081        match unsafe { capi::pa_stream_readable_size(self.ptr) } {
1082            std::usize::MAX => None,
1083            r => Some(r),
1084        }
1085    }
1086
1087    /// Drains a playback stream.
1088    ///
1089    /// Use this for notification when the playback buffer is empty after playing all the audio in
1090    /// the buffer. Please note that only one drain operation per stream may be issued at a time.
1091    ///
1092    /// The optional callback must accept a `bool`, which indicates success.
1093    ///
1094    /// Panics if the underlying C function returns a null pointer.
1095    pub fn drain(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1096        -> Operation<dyn FnMut(bool)>
1097    {
1098        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1099            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1100        let ptr = unsafe { capi::pa_stream_drain(self.ptr, cb_fn, cb_data) };
1101        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1102    }
1103
1104    /// Requests a timing info structure update for a stream.
1105    ///
1106    /// Use [`get_timing_info()`] to get access to the raw timing data, or [`get_time()`] or
1107    /// [`get_latency()`] to get cleaned up values.
1108    ///
1109    /// The optional callback must accept a `bool`, which indicates success.
1110    ///
1111    /// Panics if the underlying C function returns a null pointer.
1112    ///
1113    /// [`get_timing_info()`]: Self::get_timing_info
1114    /// [`get_time()`]: Self::get_time
1115    /// [`get_latency()`]: Self::get_latency
1116    pub fn update_timing_info(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1117        -> Operation<dyn FnMut(bool)>
1118    {
1119        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1120            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1121        let ptr = unsafe { capi::pa_stream_update_timing_info(self.ptr, cb_fn, cb_data) };
1122        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1123    }
1124
1125    /// Sets the callback function that is called whenever the state of the stream changes.
1126    pub fn set_state_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1127        let saved = &mut self.cb_ptrs.set_state;
1128        *saved = NotifyCb::new(callback);
1129        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1130        unsafe { capi::pa_stream_set_state_callback(self.ptr, cb_fn, cb_data); }
1131    }
1132
1133    /// Sets the callback function that is called when new data may be written to the stream.
1134    ///
1135    /// The callback accepts an argument giving the number of bytes.
1136    pub fn set_write_callback(&mut self, callback: Option<Box<dyn FnMut(usize) + 'static>>) {
1137        let saved = &mut self.cb_ptrs.write;
1138        *saved = RequestCb::new(callback);
1139        let (cb_fn, cb_data) = saved.get_capi_params(request_cb_proxy);
1140        unsafe { capi::pa_stream_set_write_callback(self.ptr, cb_fn, cb_data); }
1141    }
1142
1143    /// Sets the callback function that is called when new data is available from the stream.
1144    ///
1145    /// The callback accepts an argument giving the number of bytes.
1146    pub fn set_read_callback(&mut self, callback: Option<Box<dyn FnMut(usize) + 'static>>) {
1147        let saved = &mut self.cb_ptrs.read;
1148        *saved = RequestCb::new(callback);
1149        let (cb_fn, cb_data) = saved.get_capi_params(request_cb_proxy);
1150        unsafe { capi::pa_stream_set_read_callback(self.ptr, cb_fn, cb_data); }
1151    }
1152
1153    /// Sets the callback function that is called when a buffer overflow happens. (Only for playback
1154    /// streams).
1155    pub fn set_overflow_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1156        let saved = &mut self.cb_ptrs.overflow;
1157        *saved = NotifyCb::new(callback);
1158        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1159        unsafe { capi::pa_stream_set_overflow_callback(self.ptr, cb_fn, cb_data); }
1160    }
1161
1162    /// Gets at what position the latest underflow occurred.
1163    ///
1164    /// `None` is returned if this information is not known (e.g. if no underflow has occurred).
1165    ///
1166    /// This can be used inside the underflow callback to get information about the current
1167    /// underflow. (Only for playback streams).
1168    pub fn get_underflow_index(&self) -> Option<u64> {
1169        match unsafe { capi::pa_stream_get_underflow_index(self.ptr) } {
1170            r if r < 0 => None,
1171            r => Some(r as u64),
1172        }
1173    }
1174
1175    /// Sets the callback function that is called when a buffer underflow happens.
1176    ///
1177    /// (Only for playback streams).
1178    pub fn set_underflow_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1179        let saved = &mut self.cb_ptrs.underflow;
1180        *saved = NotifyCb::new(callback);
1181        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1182        unsafe { capi::pa_stream_set_underflow_callback(self.ptr, cb_fn, cb_data); }
1183    }
1184
1185    /// Sets the callback function that is called when the server starts playback after an underrun
1186    /// or on initial startup.
1187    ///
1188    /// This only informs that audio is flowing again, it is no indication that audio started to
1189    /// reach the speakers already. (Only for playback streams).
1190    pub fn set_started_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1191        let saved = &mut self.cb_ptrs.started;
1192        *saved = NotifyCb::new(callback);
1193        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1194        unsafe { capi::pa_stream_set_started_callback(self.ptr, cb_fn, cb_data); }
1195    }
1196
1197    /// Sets the callback function that is called whenever a latency information update happens.
1198    ///
1199    /// Useful on [`FlagSet::AUTO_TIMING_UPDATE`] streams only.
1200    pub fn set_latency_update_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1201        let saved = &mut self.cb_ptrs.latency_update;
1202        *saved = NotifyCb::new(callback);
1203        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1204        unsafe { capi::pa_stream_set_latency_update_callback(self.ptr, cb_fn, cb_data); }
1205    }
1206
1207    /// Sets the callback function that is called whenever the stream is moved to a different
1208    /// sink/source.
1209    ///
1210    /// Use [`get_device_name()`] or [`get_device_index()`] to query the new sink/source.
1211    ///
1212    /// [`get_device_name()`]: Self::get_device_name
1213    /// [`get_device_index()`]: Self::get_device_index
1214    pub fn set_moved_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1215        let saved = &mut self.cb_ptrs.moved;
1216        *saved = NotifyCb::new(callback);
1217        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1218        unsafe { capi::pa_stream_set_moved_callback(self.ptr, cb_fn, cb_data); }
1219    }
1220
1221    /// Sets the callback function that is called whenever the sink/source this stream is connected
1222    /// to is suspended or resumed.
1223    ///
1224    /// Use [`is_suspended()`] to query the new suspend status. Please note that the suspend status
1225    /// might also change when the stream is moved between devices. Thus if you call this function
1226    /// you very likely want to call [`set_moved_callback()`] too.
1227    ///
1228    /// [`is_suspended()`]: Self::is_suspended
1229    /// [`set_moved_callback()`]: Self::set_moved_callback
1230    pub fn set_suspended_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1231        let saved = &mut self.cb_ptrs.suspended;
1232        *saved = NotifyCb::new(callback);
1233        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1234        unsafe { capi::pa_stream_set_suspended_callback(self.ptr, cb_fn, cb_data); }
1235    }
1236
1237    /// Sets the callback function that is called whenever a meta/policy control event is received.
1238    ///
1239    /// The callback is given a name which represents what event occurred. The set of defined events
1240    /// can be extended at any time. Also, server modules may introduce additional message types so
1241    /// make sure that your callback function ignores messages it doesn’t know. Some well known
1242    /// event names can be found in the [`event_names`](mod@self::event_names) submodule. It is also
1243    /// given an (owned) property list.
1244    pub fn set_event_callback(&mut self,
1245        callback: Option<Box<dyn FnMut(String, Proplist) + 'static>>)
1246    {
1247        let saved = &mut self.cb_ptrs.event;
1248        *saved = EventCb::new(callback);
1249        let (cb_fn, cb_data) = saved.get_capi_params(event_cb_proxy);
1250        unsafe { capi::pa_stream_set_event_callback(self.ptr, cb_fn, cb_data); }
1251    }
1252
1253    /// Sets the callback function that is called whenever the buffer attributes on the server side
1254    /// change.
1255    ///
1256    /// Please note that the buffer attributes can change when moving a stream to a different
1257    /// sink/source too, hence if you use this callback you should use [`set_moved_callback()`] as
1258    /// well.
1259    ///
1260    /// [`set_moved_callback()`]: Self::set_moved_callback
1261    pub fn set_buffer_attr_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1262        let saved = &mut self.cb_ptrs.buffer_attr;
1263        *saved = NotifyCb::new(callback);
1264        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1265        unsafe { capi::pa_stream_set_buffer_attr_callback(self.ptr, cb_fn, cb_data); }
1266    }
1267
1268    /// Pauses playback of this stream temporarily.
1269    ///
1270    /// This simply calls [`set_corked_state()`] with a value of `true`.
1271    ///
1272    /// [`set_corked_state()`]: Self::set_corked_state
1273    #[inline(always)]
1274    pub fn cork(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1275        -> Operation<dyn FnMut(bool)>
1276    {
1277        self.set_corked_state(true, callback)
1278    }
1279
1280    /// Resumes playback of this stream.
1281    ///
1282    /// This simply calls [`set_corked_state()`] with a value of `false`.
1283    ///
1284    /// [`set_corked_state()`]: Self::set_corked_state
1285    #[inline(always)]
1286    pub fn uncork(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1287        -> Operation<dyn FnMut(bool)>
1288    {
1289        self.set_corked_state(false, callback)
1290    }
1291
1292    /// Pauses or resumes playback of this stream.
1293    ///
1294    /// Available on both playback and recording streams.
1295    ///
1296    /// Set state to `true` to cork (pause) the stream. Set state to `false` to uncork (resume) the
1297    /// stream. Alternatively [`cork()`] and [`uncork()`] helper functions can be used.
1298    ///
1299    /// The operation is executed as quickly as possible. If a cork is very quickly followed by an
1300    /// uncork, or vice versa, this might not actually have any effect on the stream that is output.
1301    /// You can use [`is_corked()`] to find out whether the stream is currently paused or not.
1302    /// Normally a stream will be created in uncorked state. If you pass [`FlagSet::START_CORKED`]
1303    /// as a flag when connecting the stream, it will be created in corked state.
1304    ///
1305    /// The optional callback must accept a `bool`, which indicates success.
1306    ///
1307    /// Panics if the underlying C function returns a null pointer.
1308    ///
1309    /// [`is_corked()`]: Self::is_corked
1310    /// [`cork()`]: Self::cork
1311    /// [`uncork()`]: Self::uncork
1312    pub fn set_corked_state(&mut self, state: bool, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1313        -> Operation<dyn FnMut(bool)>
1314    {
1315        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1316            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1317        let ptr = unsafe { capi::pa_stream_cork(self.ptr, state as i32, cb_fn, cb_data) };
1318        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1319    }
1320
1321    /// Flushes the playback or record buffer of this stream.
1322    ///
1323    /// This discards any audio data in the buffer. Most of the time you’re better off using the
1324    /// parameter `seek` of [`write()`](Self::write) instead of this function.
1325    ///
1326    /// The optional callback must accept a `bool`, which indicates success.
1327    ///
1328    /// Panics if the underlying C function returns a null pointer.
1329    pub fn flush(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1330        -> Operation<dyn FnMut(bool)>
1331    {
1332        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1333            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1334        let ptr = unsafe { capi::pa_stream_flush(self.ptr, cb_fn, cb_data) };
1335        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1336    }
1337
1338    /// Re-enables prebuffering if specified in the [`BufferAttr`] structure.
1339    ///
1340    /// Available for playback streams only.
1341    ///
1342    /// The optional callback must accept a `bool`, which indicates success.
1343    ///
1344    /// Panics if the underlying C function returns a null pointer.
1345    ///
1346    /// [`BufferAttr`]: crate::def::BufferAttr
1347    pub fn prebuf(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1348        -> Operation<dyn FnMut(bool)>
1349    {
1350        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1351            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1352        let ptr = unsafe { capi::pa_stream_prebuf(self.ptr, cb_fn, cb_data) };
1353        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1354    }
1355
1356    /// Requests immediate start of playback on this stream.
1357    ///
1358    /// This disables prebuffering temporarily if specified in the [`BufferAttr`] structure.
1359    /// Available for playback streams only.
1360    ///
1361    /// The optional callback must accept a `bool`, which indicates success.
1362    ///
1363    /// Panics if the underlying C function returns a null pointer.
1364    ///
1365    /// [`BufferAttr`]: crate::def::BufferAttr
1366    pub fn trigger(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1367        -> Operation<dyn FnMut(bool)>
1368    {
1369        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1370            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1371        let ptr = unsafe { capi::pa_stream_trigger(self.ptr, cb_fn, cb_data) };
1372        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1373    }
1374
1375    /// Renames the stream.
1376    ///
1377    /// The optional callback must accept a `bool`, which indicates success.
1378    ///
1379    /// Panics if the underlying C function returns a null pointer.
1380    pub fn set_name(&mut self, name: &str, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1381        -> Operation<dyn FnMut(bool)>
1382    {
1383        // Warning: New CStrings will be immediately freed if not bound to a
1384        // variable, leading to as_ptr() giving dangling pointers!
1385        let c_name = CString::new(name).unwrap();
1386
1387        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1388            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1389        let ptr = unsafe { capi::pa_stream_set_name(self.ptr, c_name.as_ptr(), cb_fn, cb_data) };
1390        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1391    }
1392
1393    /// Gets the current playback/recording time.
1394    ///
1395    /// This is based on the data in the timing info structure returned by [`get_timing_info()`].
1396    /// The returned time is in the sound card clock domain, which usually runs at a slightly
1397    /// different rate than the system clock.
1398    ///
1399    /// This function will usually only return new data if a timing info update has been received.
1400    /// Only if timing interpolation has been requested ([`FlagSet::INTERPOLATE_TIMING`]) the data
1401    /// from the last timing update is used for an estimation of the current playback/recording time
1402    /// based on the local time that passed since the timing info structure has been acquired.
1403    ///
1404    /// The time value returned by this function is guaranteed to increase monotonically (the
1405    /// returned value is always greater or equal to the value returned by the last call). This
1406    /// behaviour can be disabled by using [`FlagSet::NOT_MONOTONIC`]. This may be desirable to
1407    /// better deal with bad estimations of transport latencies, but may have strange effects if the
1408    /// application is not able to deal with time going ‘backwards’.
1409    ///
1410    /// The time interpolator activated by [`FlagSet::INTERPOLATE_TIMING`] favours ‘smooth’ time
1411    /// graphs over accurate ones to improve the smoothness of UI operations that are tied to the
1412    /// audio clock. If accuracy is more important to you, you might need to estimate your timing
1413    /// based on the data from [`get_timing_info()`] yourself or not work with interpolated timing
1414    /// at all and instead always query the server side for the most up to date timing with
1415    /// [`update_timing_info()`].
1416    ///
1417    /// If no timing information has been received yet this call will return `Ok(None)`. For more
1418    /// details see [`get_timing_info()`].
1419    ///
1420    /// [`get_timing_info()`]: Self::get_timing_info
1421    /// [`update_timing_info()`]: Self::update_timing_info
1422    pub fn get_time(&self) -> Result<Option<MicroSeconds>, PAErr> {
1423        let mut r_usecs = MicroSeconds(0);
1424        match unsafe { capi::pa_stream_get_time(self.ptr, &mut r_usecs.0) } {
1425            0 => Ok(Some(r_usecs)),
1426            e if e == PAErr::from(error::Code::NoData).0 => Ok(None),
1427            e => Err(PAErr(e)),
1428        }
1429    }
1430
1431    /// Determines the total stream latency.
1432    ///
1433    /// This function is based on [`get_time()`]. The returned time is in the sound card clock
1434    /// domain, which usually runs at a slightly different rate than the system clock.
1435    ///
1436    /// In case the stream is a monitoring stream the result can be negative, i.e. the captured
1437    /// samples are not yet played, in which case `Ok(Latency::Negative(usecs))` will be returned
1438    /// instead of `Ok(Latency::Positive(usecs))`
1439    ///
1440    /// If no timing information has been received yet, this call will return `Ok(Latency::None)`.
1441    ///
1442    /// For more details see [`get_timing_info()`] and [`get_time()`].
1443    ///
1444    /// [`get_time()`]: Self::get_time
1445    /// [`get_timing_info()`]: Self::get_timing_info
1446    pub fn get_latency(&self) -> Result<Latency, PAErr> {
1447        let mut r_usecs = MicroSeconds(0);
1448        let mut negative: i32 = 0;
1449        match unsafe { capi::pa_stream_get_latency(self.ptr, &mut r_usecs.0, &mut negative) } {
1450            0 => match negative {
1451                1 => Ok(Latency::Negative(r_usecs)),
1452                _ => Ok(Latency::Positive(r_usecs)),
1453            },
1454            e if e == PAErr::from(error::Code::NoData).0 => Ok(Latency::None),
1455            e => Err(PAErr(e)),
1456        }
1457    }
1458
1459    /// Gets the latest raw timing data structure.
1460    ///
1461    /// The returned pointer refers to an internal read-only instance of the timing structure. The
1462    /// user should make a copy of this structure if wanting to modify it. An in-place update to
1463    /// this data structure may be requested using [`update_timing_info()`].
1464    ///
1465    /// If no timing information has been received before (i.e. by requesting
1466    /// [`update_timing_info()`] or by using [`FlagSet::AUTO_TIMING_UPDATE`]), this function will
1467    /// return `None` (as it will also if an error occurs).
1468    ///
1469    /// Please note that the `write_index` member field (and only this field) is updated on each
1470    /// [`write()`] call, not just when a timing update has been received.
1471    ///
1472    /// [`update_timing_info()`]: Self::update_timing_info
1473    /// [`write()`]: Self::write
1474    pub fn get_timing_info<'a>(&mut self) -> Option<&'a def::TimingInfo> {
1475        unsafe {
1476            let ptr = capi::pa_stream_get_timing_info(self.ptr);
1477            ptr.as_ref().map(|r| r.as_ref())
1478        }
1479    }
1480
1481    /// Gets a pointer to the stream’s sample specification.
1482    pub fn get_sample_spec<'a>(&mut self) -> Option<&'a sample::Spec> {
1483        unsafe {
1484            let ptr = capi::pa_stream_get_sample_spec(self.ptr);
1485            ptr.as_ref().map(|r| r.as_ref())
1486        }
1487    }
1488
1489    /// Gets a pointer to the stream’s channel map.
1490    pub fn get_channel_map<'a>(&mut self) -> Option<&'a channelmap::Map> {
1491        unsafe {
1492            let ptr = capi::pa_stream_get_channel_map(self.ptr);
1493            ptr.as_ref().map(|r| r.as_ref())
1494        }
1495    }
1496
1497    /// Gets a pointer to the stream’s format.
1498    pub fn get_format_info(&self) -> Option<format::Info> {
1499        let ptr = unsafe { capi::pa_stream_get_format_info(self.ptr) };
1500        match ptr.is_null() {
1501            false => Some(format::Info::from_raw_weak(ptr as *mut InfoInternal)),
1502            true => None,
1503        }
1504    }
1505
1506    /// Gets the per-stream server-side buffer metrics of the stream.
1507    ///
1508    /// Only valid after the stream has been connected successfully. This will return the actual
1509    /// configured buffering metrics, which may differ from what was requested during
1510    /// [`connect_record()`] or [`connect_playback()`]. This call will always return the actual
1511    /// per-stream server-side buffer metrics, regardless whether [`FlagSet::ADJUST_LATENCY`] is set
1512    /// or not.
1513    ///
1514    /// [`connect_record()`]: Self::connect_record
1515    /// [`connect_playback()`]: Self::connect_playback
1516    pub fn get_buffer_attr<'a>(&mut self) -> Option<&'a def::BufferAttr> {
1517        unsafe {
1518            let ptr = capi::pa_stream_get_buffer_attr(self.ptr);
1519            ptr.as_ref().map(|r| r.as_ref())
1520        }
1521    }
1522
1523    /// Changes the buffer metrics of the stream during playback.
1524    ///
1525    /// The server might have chosen different buffer metrics then requested. The selected metrics
1526    /// may be queried with [`get_buffer_attr()`] as soon as the callback is called. Only valid
1527    /// after the stream has been connected successfully. Please be aware of the slightly different
1528    /// semantics of the call depending whether [`FlagSet::ADJUST_LATENCY`] is set or not.
1529    ///
1530    /// The callback must accept a `bool`, which indicates success.
1531    ///
1532    /// Panics if the underlying C function returns a null pointer.
1533    ///
1534    /// [`get_buffer_attr()`]: Self::get_buffer_attr
1535    pub fn set_buffer_attr<F>(&mut self, attr: &def::BufferAttr, callback: F)
1536        -> Operation<dyn FnMut(bool)>
1537        where F: FnMut(bool) + 'static
1538    {
1539        let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1540        let ptr = unsafe { capi::pa_stream_set_buffer_attr(self.ptr, attr.as_ref(),
1541            Some(success_cb_proxy), cb_data) };
1542        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1543    }
1544
1545    /// Changes the stream sampling rate during playback.
1546    ///
1547    /// You need to pass [`FlagSet::VARIABLE_RATE`] in the flags parameter of [`connect_playback()`]
1548    /// if you plan to use this function. Only valid after the stream has been connected
1549    /// successfully.
1550    ///
1551    /// The callback must accept a `bool`, which indicates success.
1552    ///
1553    /// Panics if the underlying C function returns a null pointer.
1554    ///
1555    /// [`connect_playback()`]: Self::connect_playback
1556    pub fn update_sample_rate<F>(&mut self, rate: u32, callback: F) -> Operation<dyn FnMut(bool)>
1557        where F: FnMut(bool) + 'static
1558    {
1559        let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1560        let ptr = unsafe { capi::pa_stream_update_sample_rate(self.ptr, rate,
1561            Some(success_cb_proxy), cb_data) };
1562        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1563    }
1564
1565    /// Updates the property list of the sink input/source output of this stream, adding new
1566    /// entries.
1567    ///
1568    /// Please note that it is highly recommended to set as many properties initially via
1569    /// [`new_with_proplist()`] as possible instead a posteriori with this function, since that
1570    /// information may be used to route this stream to the right device.
1571    ///
1572    /// The callback must accept a `bool`, which indicates success.
1573    ///
1574    /// Panics if the underlying C function returns a null pointer.
1575    ///
1576    /// [`new_with_proplist()`]: Self::new_with_proplist
1577    pub fn update_proplist<F>(&mut self, mode: proplist::UpdateMode, proplist: &mut Proplist,
1578        callback: F) -> Operation<dyn FnMut(bool)>
1579        where F: FnMut(bool) + 'static
1580    {
1581        let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1582        let ptr = unsafe { capi::pa_stream_proplist_update(self.ptr, mode, proplist.0.ptr,
1583            Some(success_cb_proxy), cb_data) };
1584        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1585    }
1586
1587    /// Updates the property list of the sink input/source output of this stream, removing entries.
1588    ///
1589    /// The callback must accept a `bool`, which indicates success.
1590    ///
1591    /// Panics if the underlying C function returns a null pointer.
1592    pub fn remove_proplist<F>(&mut self, keys: &[&str], callback: F) -> Operation<dyn FnMut(bool)>
1593        where F: FnMut(bool) + 'static
1594    {
1595        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
1596        // as_ptr() giving dangling pointers!
1597        let mut c_keys: Vec<CString> = Vec::with_capacity(keys.len());
1598        for key in keys {
1599            c_keys.push(CString::new(*key).unwrap());
1600        }
1601
1602        // Capture array of pointers to the above CString values
1603        // We also add a null pointer entry on the end, as expected by the C function called here.
1604        let mut c_key_ptrs: Vec<*const c_char> = Vec::with_capacity(c_keys.len() + 1);
1605        for c_key in &c_keys {
1606            c_key_ptrs.push(c_key.as_ptr());
1607        }
1608        c_key_ptrs.push(null());
1609
1610        let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1611        let ptr = unsafe {
1612            capi::pa_stream_proplist_remove(self.ptr, c_key_ptrs.as_ptr(),
1613                Some(success_cb_proxy), cb_data)
1614        };
1615        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1616    }
1617
1618    /// For record streams connected to a monitor source: monitors only a very specific sink input
1619    /// of the sink.
1620    ///
1621    /// This function needs to be called before [`connect_record()`](Self::connect_record) is
1622    /// called.
1623    pub fn set_monitor_stream(&mut self, sink_input_index: u32) -> Result<(), PAErr> {
1624        match unsafe { capi::pa_stream_set_monitor_stream(self.ptr, sink_input_index) } {
1625            0 => Ok(()),
1626            e => Err(PAErr(e)),
1627        }
1628    }
1629
1630    /// Gets the sink input index previously set with [`set_monitor_stream()`].
1631    ///
1632    /// [`set_monitor_stream()`]: Self::set_monitor_stream
1633    pub fn get_monitor_stream(&self) -> Option<u32> {
1634        match unsafe { capi::pa_stream_get_monitor_stream(self.ptr) } {
1635            def::INVALID_INDEX => None,
1636            r => Some(r),
1637        }
1638    }
1639}
1640
1641impl Drop for Stream {
1642    fn drop(&mut self) {
1643        // Throw away the `Result` from disconnecting, it may legitimately be bad if stream failed.
1644        // See https://github.com/jnqnfe/pulse-binding-rust/issues/11
1645        let _ = self.disconnect();
1646        unsafe { capi::pa_stream_unref(self.ptr) };
1647        self.ptr = null_mut::<StreamInternal>();
1648    }
1649}
1650
1651/// Proxy for completion success callbacks.
1652///
1653/// Warning: This is for single-use cases only! It destroys the actual closure callback.
1654extern "C"
1655fn success_cb_proxy(_: *mut StreamInternal, success: i32, userdata: *mut c_void) {
1656    let success_actual = match success { 0 => false, _ => true };
1657    let _ = std::panic::catch_unwind(|| {
1658        // Note, destroys closure callback after use - restoring outer box means it gets dropped
1659        let mut callback = get_su_callback::<dyn FnMut(bool)>(userdata);
1660        (callback)(success_actual);
1661    });
1662}
1663
1664/// Proxy for request callbacks.
1665///
1666/// Warning: This is for multi-use cases! It does **not** destroy the actual closure callback, which
1667/// must be accomplished separately to avoid a memory leak.
1668extern "C"
1669fn request_cb_proxy(_: *mut StreamInternal, nbytes: usize, userdata: *mut c_void) {
1670    let _ = std::panic::catch_unwind(|| {
1671        let callback = RequestCb::get_callback(userdata);
1672        (callback)(nbytes);
1673    });
1674}
1675
1676/// Proxy for notify callbacks.
1677///
1678/// Warning: This is for multi-use cases! It does **not** destroy the actual closure callback, which
1679/// must be accomplished separately to avoid a memory leak.
1680extern "C"
1681fn notify_cb_proxy(_: *mut StreamInternal, userdata: *mut c_void) {
1682    let _ = std::panic::catch_unwind(|| {
1683        let callback = NotifyCb::get_callback(userdata);
1684        (callback)();
1685    });
1686}
1687
1688/// Proxy for event callbacks.
1689///
1690/// Warning: This is for multi-use cases! It does **not** destroy the actual closure callback, which
1691/// must be accomplished separately to avoid a memory leak.
1692extern "C"
1693fn event_cb_proxy(_: *mut StreamInternal, name: *const c_char, proplist: *mut ProplistInternal,
1694    userdata: *mut c_void)
1695{
1696    let _ = std::panic::catch_unwind(|| {
1697        assert!(!name.is_null());
1698        let n = {
1699            let tmp = unsafe { CStr::from_ptr(name) };
1700            tmp.to_string_lossy().into_owned()
1701        };
1702        let pl = Proplist::from_raw_weak(proplist);
1703
1704        let callback = EventCb::get_callback(userdata);
1705        (callback)(n, pl);
1706    });
1707}