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    #[repr(transparent)]
337    pub struct FlagSet: u32 {
338        /// Flag to pass when no specific options are needed.
339        const NOFLAGS = capi::PA_STREAM_NOFLAGS;
340
341        /// Create the stream corked, requiring an explicit [`Stream::uncork()`] call to uncork it.
342        const START_CORKED = capi::PA_STREAM_START_CORKED;
343
344        /// Interpolate the latency for this stream. When enabled, [`Stream::get_latency()`] and
345        /// [`Stream::get_time()`] will try to estimate the current record/playback time based on
346        /// the local time that passed since the last timing info update. Using this option has the
347        /// advantage of not requiring a whole round trip when the current playback/recording time
348        /// is needed. Consider using this option when requesting latency information frequently.
349        /// This is especially useful on long latency network connections. It makes a lot of sense
350        /// to combine this option with [`AUTO_TIMING_UPDATE`].
351        ///
352        /// [`AUTO_TIMING_UPDATE`]: Self::AUTO_TIMING_UPDATE
353        const INTERPOLATE_TIMING = capi::PA_STREAM_INTERPOLATE_TIMING;
354
355        /// Don’t force the time to increase monotonically. If this option is enabled,
356        /// [`Stream::get_time()`] will not necessarily return always monotonically increasing time
357        /// values on each call. This may confuse applications which cannot deal with time going
358        /// ‘backwards’, but has the advantage that bad transport latency estimations that caused
359        /// the time to jump ahead can be corrected quickly, without the need to wait.
360        const NOT_MONOTONIC = capi::PA_STREAM_NOT_MONOTONIC;
361
362        /// If set timing update requests are issued periodically automatically. Combined with
363        /// [`INTERPOLATE_TIMING`] you will be able to query the current time and latency with
364        /// [`Stream::get_time()`] and [`Stream::get_latency()`] at all times without a packet round
365        /// trip.
366        ///
367        /// [`INTERPOLATE_TIMING`]: Self::INTERPOLATE_TIMING
368        const AUTO_TIMING_UPDATE = capi::PA_STREAM_AUTO_TIMING_UPDATE;
369
370        /// Don’t remap channels by their name, instead map them simply by their index. Implies
371        /// [`NO_REMIX_CHANNELS`](Self::NO_REMIX_CHANNELS).
372        const NO_REMAP_CHANNELS = capi::PA_STREAM_NO_REMAP_CHANNELS;
373
374        /// When remapping channels by name, don’t upmix or downmix them to related channels. Copy
375        /// them into matching channels of the device 1:1.
376        const NO_REMIX_CHANNELS = capi::PA_STREAM_NO_REMIX_CHANNELS;
377
378        /// Use the sample format of the sink/device this stream is being connected to, and possibly
379        /// ignore the format the sample spec contains -- but you still have to pass a valid value
380        /// in it as a hint to PulseAudio what would suit your stream best. If this is used you
381        /// should query the used sample format after creating the stream by using
382        /// [`Stream::get_sample_spec()`]. Also, if you specified manual buffer metrics it is
383        /// recommended to update them with [`Stream::set_buffer_attr()`] to compensate for the
384        /// changed frame sizes.
385        ///
386        /// When creating streams with [`Stream::new_extended()`], this flag has no effect. If you
387        /// specify a format with PCM encoding, and you want the server to choose the sample format,
388        /// then you should leave the sample format unspecified in the [`Info`] object. This also
389        /// means that you can’t use [`Info::new_from_sample_spec()`], because that function always
390        /// sets the sample format.
391        ///
392        /// [`Info`]: crate::format::Info
393        /// [`Info::new_from_sample_spec()`]: crate::format::Info::new_from_sample_spec
394        const FIX_FORMAT = capi::PA_STREAM_FIX_FORMAT;
395
396        /// Use the sample rate of the sink, and possibly ignore the rate the sample spec contains.
397        /// Usage similar to [`FIX_FORMAT`].
398        ///
399        /// When creating streams with [`Stream::new_extended()`], this flag has no effect. If you
400        /// specify a format with PCM encoding, and you want the server to choose the sample rate,
401        /// then you should leave the rate unspecified in the [`Info`] object. This also means that
402        /// you can’t use [`Info::new_from_sample_spec()`], because that function always sets the
403        /// sample rate.
404        ///
405        /// [`FIX_FORMAT`]: Self::FIX_FORMAT
406        /// [`Info`]: crate::format::Info
407        /// [`Info::new_from_sample_spec()`]: crate::format::Info::new_from_sample_spec
408        const FIX_RATE = capi::PA_STREAM_FIX_RATE;
409
410        /// Use the number of channels and the channel map of the sink, and possibly ignore the number
411        /// of channels and the map the sample spec and the passed channel map contains. Usage similar
412        /// to [`FIX_FORMAT`].
413        ///
414        /// When creating streams with [`Stream::new_extended()`], this flag has no effect. If you
415        /// specify a format with PCM encoding, and you want the server to choose the channel count
416        /// and/or channel map, then you should leave the channels and/or the channel map
417        /// unspecified in the [`Info`] object. This also means that you can’t use
418        /// [`Info::new_from_sample_spec()`], because that function always sets the channel count
419        /// (but if you only want to leave the channel map unspecified, then
420        /// [`Info::new_from_sample_spec()`] works, because the channel map parameter is optional).
421        ///
422        /// [`FIX_FORMAT`]: Self::FIX_FORMAT
423        /// [`Info`]: crate::format::Info
424        /// [`Info::new_from_sample_spec()`]: crate::format::Info::new_from_sample_spec
425        const FIX_CHANNELS = capi::PA_STREAM_FIX_CHANNELS;
426
427        /// Don’t allow moving of this stream to another sink/device. Useful if you use any of the
428        /// `Fix*` flags and want to make sure that resampling never takes place -- which might
429        /// happen if the stream is moved to another sink/source with a different sample
430        /// spec/channel map.
431        const DONT_MOVE = capi::PA_STREAM_DONT_MOVE;
432
433        /// Allow dynamic changing of the sampling rate during playback with
434        /// [`Stream::update_sample_rate()`].
435        const VARIABLE_RATE = capi::PA_STREAM_VARIABLE_RATE;
436
437        /// Find peaks instead of resampling.
438        const PEAK_DETECT = capi::PA_STREAM_PEAK_DETECT;
439
440        /// Create in muted state. If neither [`START_UNMUTED`] nor this is specified, it is left to
441        /// the server to decide whether to create the stream in muted or in un-muted state.
442        ///
443        /// [`START_UNMUTED`]: Self::START_UNMUTED
444        const START_MUTED = capi::PA_STREAM_START_MUTED;
445
446        /// Try to adjust the latency of the sink/source based on the requested buffer metrics and
447        /// adjust buffer metrics accordingly. Also see [`BufferAttr`]. This option may not be
448        /// specified at the same time as [`EARLY_REQUESTS`].
449        ///
450        /// [`EARLY_REQUESTS`]: Self::EARLY_REQUESTS
451        /// [`BufferAttr`]: crate::def::BufferAttr
452        const ADJUST_LATENCY = capi::PA_STREAM_ADJUST_LATENCY;
453
454        /// Enable compatibility mode for legacy clients that rely on a “classic” hardware device
455        /// fragment-style playback model. If this option is set, the `minreq` value of the buffer
456        /// metrics gets a new meaning: instead of just specifying that no requests asking for less
457        /// new data than this value will be made to the client it will also guarantee that requests
458        /// are generated as early as this limit is reached. This flag should only be set in very
459        /// few situations where compatibility with a fragment-based playback model needs to be kept
460        /// and the client applications cannot deal with data requests that are delayed to the
461        /// latest moment possible. (Usually these are programs that use usleep() or a similar call
462        /// in their playback loops instead of sleeping on the device itself.) Also see
463        /// [`BufferAttr`]. This option may not be specified at the same time as [`ADJUST_LATENCY`].
464        ///
465        /// [`ADJUST_LATENCY`]: Self::ADJUST_LATENCY
466        /// [`BufferAttr`]: crate::def::BufferAttr
467        const EARLY_REQUESTS = capi::PA_STREAM_EARLY_REQUESTS;
468
469        /// If set this stream won’t be taken into account when it is checked whether the device
470        /// this stream is connected to should auto-suspend.
471        const DONT_INHIBIT_AUTO_SUSPEND = capi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND;
472
473        /// Create in unmuted state. If neither [`START_MUTED`] nor this is specified, it is left to
474        /// the server to decide whether to create the stream in muted or in unmuted state.
475        ///
476        /// [`START_MUTED`]: Self::START_MUTED
477        const START_UNMUTED = capi::PA_STREAM_START_UNMUTED;
478
479        /// If the sink/source this stream is connected to is suspended during the creation of this
480        /// stream, cause it to fail. If the sink/source is being suspended during creation of this
481        /// stream, make sure this stream is terminated.
482        const FAIL_ON_SUSPEND = capi::PA_STREAM_FAIL_ON_SUSPEND;
483
484        /// If a volume is passed when this stream is created, consider it relative to the sink’s
485        /// current volume, never as absolute device volume. If this is not specified the volume
486        /// will be consider absolute when the sink is in flat volume mode, relative otherwise.
487        const RELATIVE_VOLUME = capi::PA_STREAM_RELATIVE_VOLUME;
488
489        /// Used to tag content that will be rendered by passthrough sinks. The data will be left as
490        /// is and not reformatted, resampled.
491        const PASSTHROUGH = capi::PA_STREAM_PASSTHROUGH;
492    }
493}
494
495impl Default for FlagSet {
496    fn default() -> Self {
497        Self::NOFLAGS
498    }
499}
500
501/// Common event names supplied to the [`Stream::set_event_callback()`] callback.
502pub mod event_names {
503    use capi;
504
505    /// A stream policy/meta event requesting that an application should cork a specific stream.
506    pub const EVENT_REQUEST_CORK: &str = capi::PA_STREAM_EVENT_REQUEST_CORK;
507
508    /// A stream policy/meta event requesting that an application should cork a specific stream.
509    pub const EVENT_REQUEST_UNCORK: &str = capi::PA_STREAM_EVENT_REQUEST_UNCORK;
510
511    /// A stream event notifying that the stream is going to be disconnected because the underlying
512    /// sink changed and no longer supports the format that was originally negotiated. Clients need
513    /// to connect a new stream to renegotiate a format and continue playback.
514    pub const EVENT_FORMAT_LOST: &str = capi::PA_STREAM_EVENT_FORMAT_LOST;
515}
516
517/// Result type for the [`Stream::peek()`] method. See documentation of the method itself for more
518/// information.
519#[derive(Debug)]
520pub enum PeekResult<'a> {
521    /// No data (Null data pointer and size of 0 returned by PA).
522    Empty,
523    /// Data hole with given size (Null pointer with non-zero size returned by PA).
524    Hole(usize),
525    /// Data available, with slice into memory returned by PA.
526    Data(&'a [u8]),
527}
528
529/// Result type for [`Stream::get_latency()`].
530#[derive(Debug, Copy, Clone, PartialEq, Eq)]
531pub enum Latency {
532    /// No latency.
533    None,
534    /// A positive (greater than zero) amount of latency.
535    Positive(MicroSeconds),
536    /// A negative (less than zero) amount of latency.
537    Negative(MicroSeconds),
538}
539
540impl Stream {
541    /// Creates a new, unconnected stream with the specified name and sample type.
542    ///
543    /// It is recommended to use [`new_with_proplist()`] instead and specify some initial
544    /// properties.
545    ///
546    /// # Params
547    ///
548    /// * `ctx`: The context to create this stream in
549    /// * `name`: A name for this stream
550    /// * `ss`: The desired sample format
551    /// * `map`: The desired channel map, or `None` for default
552    ///
553    /// [`new_with_proplist()`]: Self::new_with_proplist
554    pub fn new(ctx: &mut Context, name: &str, ss: &sample::Spec, map: Option<&channelmap::Map>)
555        -> Option<Self>
556    {
557        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
558        // as_ptr() giving dangling pointers!
559        let c_name = CString::new(name).unwrap();
560
561        let p_map = map.map_or(null::<capi::pa_channel_map>(), |m| m.as_ref());
562
563        let ptr = unsafe { capi::pa_stream_new(ctx.ptr, c_name.as_ptr(), ss.as_ref(), p_map) };
564        match ptr.is_null() {
565            false => Some(Self::from_raw(ptr)),
566            true => None,
567        }
568    }
569
570    /// Creates a new, unconnected stream with the specified name and sample type, and specify the
571    /// initial stream property list.
572    ///
573    /// # Params
574    ///
575    /// * `ctx`: The context to create this stream in
576    /// * `name`: A name for this stream
577    /// * `ss`: The desired sample format
578    /// * `map`: The desired channel map, or `None` for default
579    /// * `proplist`: The initial property list
580    pub fn new_with_proplist(ctx: &mut Context, name: &str, ss: &sample::Spec,
581        map: Option<&channelmap::Map>, proplist: &mut Proplist) -> Option<Self>
582    {
583        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
584        // as_ptr() giving dangling pointers!
585        let c_name = CString::new(name).unwrap();
586
587        let p_map = map.map_or(null::<capi::pa_channel_map>(), |m| m.as_ref());
588
589        let ptr = unsafe {
590            capi::pa_stream_new_with_proplist(ctx.ptr, c_name.as_ptr(), ss.as_ref(),
591                p_map, proplist.0.ptr)
592        };
593        match ptr.is_null() {
594            false => Some(Self::from_raw(ptr)),
595            true => None,
596        }
597    }
598
599    /// Creates a new, unconnected stream with the specified name, the set of formats this client
600    /// can provide, and an initial list of properties.
601    ///
602    /// While connecting, the server will select the most appropriate format which the client must
603    /// then provide.
604    ///
605    /// # Params
606    ///
607    /// * `ctx`: The context to create this stream in
608    /// * `name`: A name for this stream
609    /// * `formats`: The list of formats that can be provided
610    /// * `proplist`: The initial property list
611    pub fn new_extended(ctx: &mut Context, name: &str, formats: &[&format::Info],
612        proplist: &mut Proplist) -> Option<Self>
613    {
614        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
615        // as_ptr() giving dangling pointers!
616        let c_name = CString::new(name).unwrap();
617
618        // Create array of format::InfoInternal pointers from provided array of `Info` pointers.
619        let mut info_ptrs: Vec<*const capi::pa_format_info> = Vec::with_capacity(formats.len());
620        for format in formats {
621            info_ptrs.push(format.ptr as *const capi::pa_format_info);
622        }
623
624        let ptr = unsafe {
625            capi::pa_stream_new_extended(ctx.ptr, c_name.as_ptr(), info_ptrs.as_ptr(),
626                info_ptrs.len() as u32, proplist.0.ptr)
627        };
628        match ptr.is_null() {
629            false => Some(Self::from_raw(ptr)),
630            true => None,
631        }
632    }
633
634    /// Creates a new `Stream` from an existing [`StreamInternal`] pointer.
635    #[inline]
636    fn from_raw(ptr: *mut StreamInternal) -> Self {
637        assert_eq!(false, ptr.is_null());
638        Self { ptr: ptr, cb_ptrs: Default::default() }
639    }
640
641    /// Gets the current state of the stream.
642    #[inline]
643    pub fn get_state(&self) -> State {
644        unsafe { capi::pa_stream_get_state(self.ptr).into() }
645    }
646
647    /// Gets the sink input resp. source output index this stream is identified in the server with.
648    ///
649    /// This is useful with the introspection functions such as
650    /// [`Introspector::get_sink_input_info()`] or [`Introspector::get_source_output_info()`].
651    ///
652    /// [`Introspector::get_sink_input_info()`]: crate::context::introspect::Introspector::get_sink_input_info
653    /// [`Introspector::get_source_output_info()`]: crate::context::introspect::Introspector::get_source_output_info
654    pub fn get_index(&self) -> Option<u32> {
655        match unsafe { capi::pa_stream_get_index(self.ptr) } {
656            def::INVALID_INDEX => None,
657            r => Some(r),
658        }
659    }
660
661    /// Gets the index of the sink or source this stream is connected to in the server.
662    ///
663    /// This is useful with the introspection functions such as
664    /// [`Introspector::get_sink_info_by_index()`] or [`Introspector::get_source_info_by_index()`].
665    ///
666    /// Please note that streams may be moved between sinks/sources and thus it is recommended to
667    /// use [`set_moved_callback()`] to be notified about this.
668    ///
669    /// [`set_moved_callback()`]: Self::set_moved_callback
670    /// [`Introspector::get_sink_info_by_index()`]: crate::context::introspect::Introspector::get_sink_info_by_index
671    /// [`Introspector::get_source_info_by_index()`]: crate::context::introspect::Introspector::get_source_info_by_index
672    pub fn get_device_index(&self) -> Option<u32> {
673        match unsafe { capi::pa_stream_get_device_index(self.ptr) } {
674            def::INVALID_INDEX => None,
675            r => Some(r),
676        }
677    }
678
679    /// Gets the name of the sink or source this stream is connected to in the server.
680    ///
681    /// This is useful with the introspection functions such as
682    /// [`Introspector::get_sink_info_by_name()`] or [`Introspector::get_source_info_by_name()`].
683    ///
684    /// Please note that streams may be moved between sinks/sources and thus it is recommended to
685    /// use [`set_moved_callback()`] to be notified about this.
686    ///
687    /// [`set_moved_callback()`]: Self::set_moved_callback
688    /// [`Introspector::get_sink_info_by_name()`]: crate::context::introspect::Introspector::get_sink_info_by_name
689    /// [`Introspector::get_source_info_by_name()`]: crate::context::introspect::Introspector::get_source_info_by_name
690    pub fn get_device_name(&self) -> Option<Cow<'static, str>> {
691        let ptr: *const c_char = unsafe { capi::pa_stream_get_device_name(self.ptr) };
692        match ptr.is_null() {
693            false => Some(unsafe { CStr::from_ptr(ptr).to_string_lossy() }),
694            true => None,
695        }
696    }
697
698    /// Checks whether or not the sink or source this stream is connected to has been suspended.
699    pub fn is_suspended(&self) -> Result<bool, PAErr> {
700        match unsafe { capi::pa_stream_is_suspended(self.ptr) } {
701            0 => Ok(false),
702            1 => Ok(true),
703            e => Err(PAErr(e)),
704        }
705    }
706
707    /// Checks whether or not this stream has been corked.
708    pub fn is_corked(&self) -> Result<bool, PAErr> {
709        match unsafe { capi::pa_stream_is_corked(self.ptr) } {
710            0 => Ok(false),
711            1 => Ok(true),
712            e => Err(PAErr(e)),
713        }
714    }
715
716    /// Connects the stream to a sink.
717    ///
718    /// It is strongly recommended to pass `None` in both `dev` and `volume` and to set neither
719    /// [`FlagSet::START_MUTED`] nor [`FlagSet::START_UNMUTED`] -- unless these options are directly
720    /// dependent on user input or configuration.
721    ///
722    /// If you follow this rule then the sound server will have the full flexibility to choose the
723    /// device, volume and mute status automatically, based on server-side policies, heuristics and
724    /// stored information from previous uses. Also the server may choose to reconfigure audio
725    /// devices to make other sinks/sources or capabilities available to be able to accept the
726    /// stream.
727    ///
728    /// Before PA 0.9.20 it was not defined whether the ‘volume’ parameter was interpreted relative
729    /// to the sink’s current volume or treated as an absolute device volume. Since PA 0.9.20 it is
730    /// an absolute volume when the sink is in flat volume mode, and relative otherwise, thus making
731    /// sure the volume passed here has always the same semantics as the volume passed to
732    /// [`Introspector::set_sink_input_volume()`]. It is possible to figure out whether flat volume
733    /// mode is in effect for a given sink by calling [`Introspector::get_sink_info_by_name()`].
734    ///
735    /// Since PA 5.0, it’s possible to specify a single-channel volume even if the stream has
736    /// multiple channels. In that case the same volume is applied to all channels.
737    ///
738    /// # Params
739    ///
740    /// * `dev`: Name of the sink to connect to, or `None` to let the server decide
741    /// * `attr`: Buffering attributes, or `None` for default
742    /// * `flags`: Additional flags, or `0` for default
743    /// * `volume`: Initial volume, or `None` for default
744    /// * `sync_stream`: Synchronize this stream with the specified one, or `None` for a standalone
745    ///   stream.
746    ///
747    /// [`Introspector::set_sink_input_volume()`]: crate::context::introspect::Introspector::set_sink_input_volume
748    /// [`Introspector::get_sink_info_by_name()`]: crate::context::introspect::Introspector::get_sink_info_by_name
749    pub fn connect_playback(&mut self, dev: Option<&str>, attr: Option<&def::BufferAttr>,
750        flags: FlagSet, volume: Option<&ChannelVolumes>, sync_stream: Option<&mut Self>)
751        -> Result<(), PAErr>
752    {
753        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
754        // as_ptr() giving dangling pointers!
755        let c_dev = match dev {
756            Some(dev) => CString::new(dev).unwrap(),
757            None => CString::new("").unwrap(),
758        };
759
760        let p_attr = attr.map_or(null::<capi::pa_buffer_attr>(), |a| a.as_ref());
761        let p_vol = volume.map_or(null::<capi::pa_cvolume>(), |v| v.as_ref());
762        let p_sync = sync_stream.map_or(null_mut::<StreamInternal>(), |s| s.ptr);
763        let p_dev = dev.map_or(null::<c_char>(), |_| c_dev.as_ptr() as *const c_char);
764
765        let r = unsafe {
766            capi::pa_stream_connect_playback(self.ptr, p_dev, p_attr, flags.bits(), p_vol, p_sync)
767        };
768        match r {
769            0 => Ok(()),
770            e => Err(PAErr(e)),
771        }
772    }
773
774    /// Connects the stream to a source.
775    ///
776    /// # Params
777    ///
778    /// * `dev`: Name of the source to connect to, or `None` to let the server decide
779    /// * `attr`: Buffering attributes, or `None` for default
780    /// * `flags`: Additional flags, or `0` for default
781    pub fn connect_record(&mut self, dev: Option<&str>, attr: Option<&def::BufferAttr>,
782        flags: FlagSet) -> Result<(), PAErr>
783    {
784        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
785        // as_ptr() giving dangling pointers!
786        let c_dev = match dev {
787            Some(dev) => CString::new(dev).unwrap(),
788            None => CString::new("").unwrap(),
789        };
790
791        let p_attr = attr.map_or(null::<capi::pa_buffer_attr>(), |a| a.as_ref());
792        let p_dev = dev.map_or(null::<c_char>(), |_| c_dev.as_ptr() as *const c_char);
793
794        match unsafe { capi::pa_stream_connect_record(self.ptr, p_dev, p_attr, flags.bits()) } {
795            0 => Ok(()),
796            e => Err(PAErr(e)),
797        }
798    }
799
800    /// Makes this stream a sample upload stream.
801    ///
802    /// (See [`scache`](mod@crate::context::scache)).
803    pub fn connect_upload(&mut self, length: usize) -> Result<(), PAErr> {
804        match unsafe { capi::pa_stream_connect_upload(self.ptr, length) } {
805            0 => Ok(()),
806            e => Err(PAErr(e)),
807        }
808    }
809
810    /// Finishes the sample upload, the stream name will become the sample name.
811    ///
812    /// You cancel a sample upload by issuing [`disconnect()`](Self::disconnect).
813    pub fn finish_upload(&mut self) -> Result<(), PAErr> {
814        match unsafe { capi::pa_stream_finish_upload(self.ptr) } {
815            0 => Ok(()),
816            e => Err(PAErr(e)),
817        }
818    }
819
820    /// Disconnects a stream from a source/sink.
821    pub fn disconnect(&mut self) -> Result<(), PAErr> {
822        match unsafe { capi::pa_stream_disconnect(self.ptr) } {
823            0 => Ok(()),
824            e => Err(PAErr(e)),
825        }
826    }
827
828    /// Prepares writing data to the server (for playback streams).
829    ///
830    /// This function may be used to optimize the number of memory copies when doing playback
831    /// (“zero-copy”). It is recommended to call this function before each call to [`write()`]. It
832    /// is used to obtain a chunk of PA internally allocated memory, into which you can directly
833    /// write your data before calling [`write()`] to actually execute the write.
834    ///
835    /// This function should be called with `nbytes` set to the number of bytes you want to write,
836    /// or `None`, in which case the size will be chosen automatically (which is recommended).
837    ///
838    /// The return value is a `Result` type, with the `Ok` variant wrapping an `Option`. `Err` will
839    /// be returned if PA encountered an error; `Ok(None)` will be  returned if it appeared to be
840    /// successful, but the pointer returned was `NULL`, otherwise the buffer will be returned as
841    /// `Ok(Some(_))`.
842    ///
843    /// After placing your data in the memory area returned, call [`write()`] with a sub-slice of
844    /// it, to actually execute the write. **Note**, the buffer may only be used once, i.e. if you
845    /// were thinking of getting a large buffer, placing a large chunk of data into it, then perform
846    /// multiple small writes from it, you **cannot** do this. Any attempt at accessing the memory
847    /// returned after the following [`write()`] or [`cancel_write()`] is invalid.
848    ///
849    /// If you want to cancel a previously called `begin_write()` without calling [`write()`] use
850    /// [`cancel_write()`].
851    ///
852    /// The memory should **not** be explicitly freed by the caller.
853    ///
854    /// An invocation of [`write()`] should “quickly” follow a `begin_write()`. It is not
855    /// recommended letting an unbounded amount of time pass after calling `begin_write()` and
856    /// before calling [`write()`]. Calling `begin_write()` twice without calling [`write()`] or
857    /// [`cancel_write()`] in between will return exactly the same `data` pointer and `nbytes`
858    /// values.
859    ///
860    /// [`write()`]: Self::write
861    /// [`cancel_write()`]: Self::cancel_write
862    pub fn begin_write<'a>(&mut self, nbytes: Option<usize>)
863        -> Result<Option<&'a mut [u8]>, PAErr>
864    {
865        let mut data_ptr = null_mut::<c_void>();
866        // If user asks for size to be automatically chosen by PA, we pass in std::usize::MAX
867        // (-1 as size_t) to signal this.
868        let mut nbytes_tmp = nbytes.unwrap_or(std::usize::MAX);
869        match unsafe { capi::pa_stream_begin_write(self.ptr, &mut data_ptr, &mut nbytes_tmp) } {
870            0 => match data_ptr.is_null() {
871                true => Ok(None),
872                false => {
873                    let slice =
874                        unsafe { std::slice::from_raw_parts_mut(data_ptr as *mut u8, nbytes_tmp) };
875                    Ok(Some(slice))
876                },
877            },
878            e => Err(PAErr(e)),
879        }
880    }
881
882    /// Reverses the effect of [`begin_write()`] dropping any data that has already been placed in
883    /// the memory area returned by [`begin_write()`].
884    ///
885    /// Only valid to call after a call to [`begin_write()`] has been made, and neither
886    /// `cancel_write()` nor [`write()`] have been called yet. Accessing the memory previously
887    /// returned by [`begin_write()`] after calling this function is invalid.
888    ///
889    /// [`write()`]: Self::write
890    /// [`begin_write()`]: Self::begin_write
891    pub fn cancel_write(&mut self) -> Result<(), PAErr> {
892        match unsafe { capi::pa_stream_cancel_write(self.ptr) } {
893            0 => Ok(()),
894            e => Err(PAErr(e)),
895        }
896    }
897
898    /// Writes some data to the server (for playback streams).
899    ///
900    /// If `free_cb` is provided, this routine is called when all data has been written out. An
901    /// internal reference to the specified data is kept, the data is not copied. If `None`, the
902    /// data is copied into an internal buffer.
903    ///
904    /// The client may freely seek around in the output buffer. For most applications it is typical
905    /// to pass `0` and [`SeekMode::Relative`] as values for the arguments `offset` and `seek`
906    /// respectively. After a successful write call the write index will be at the position after
907    /// where this chunk of data has been written to.
908    ///
909    /// As an optimization for avoiding needless memory copies you may call [`begin_write()`] before
910    /// this call and then place your audio data directly in the memory area returned by that call.
911    /// Then, pass a pointer to that memory area to `write()`. After the invocation of `write()` the
912    /// memory area may no longer be accessed. Any further explicit freeing of the memory area is
913    /// not necessary. It is OK to write to the memory area returned by [`begin_write()`] only
914    /// partially with this call, skipping bytes both at the end and at the beginning of the
915    /// reserved memory area.
916    ///
917    /// # Params
918    ///
919    /// * `data`: The data to write. The length must be in multiples of the stream’s sample spec
920    ///   frame size.
921    /// * `free_cb`: A cleanup routine for the data or `None` to request an internal copy of the
922    ///   data.
923    /// * `offset`: Offset for seeking. Must be `0` for upload streams. Must be in multiples of the
924    ///   stream’s sample spec frame size.
925    /// * `seek`: Seek mode. Must be [`SeekMode::Relative`] for upload streams.
926    ///
927    /// [`begin_write()`]: Self::begin_write
928    pub fn write(&mut self, data: &[u8], free_cb: Option<def::FreeCb>, offset: i64,
929        seek: SeekMode) -> Result<(), PAErr>
930    {
931        debug_assert_eq!(0, data.len().checked_rem(self.get_sample_spec().unwrap().frame_size())
932            .unwrap());
933        let r = unsafe {
934            capi::pa_stream_write(self.ptr, data.as_ptr() as *const c_void, data.len(), free_cb,
935                offset, seek)
936        };
937        match r {
938            0 => Ok(()),
939            e => Err(PAErr(e)),
940        }
941    }
942
943    /// Writes some data to the server (for playback streams).
944    ///
945    /// This function does exactly the same as [`write()`] as though `None` had been specified for
946    /// the `free_cb` param. I.e. an internal copy will be made of the provided data.
947    ///
948    /// # Params
949    ///
950    /// * `data`: The data to write. The length must be in multiples of the stream’s sample spec
951    ///   frame size.
952    /// * `offset`: Offset for seeking. Must be `0` for upload streams. Must be in multiples of the
953    ///   stream’s sample spec frame size.
954    /// * `seek`: Seek mode. Must be [`SeekMode::Relative`] for upload streams.
955    ///
956    /// [`write()`]: Self::write
957    #[inline(always)]
958    pub fn write_copy(&mut self, data: &[u8], offset: i64, seek: SeekMode) -> Result<(), PAErr> {
959        self.write(data, None, offset, seek)
960    }
961
962    /// Writes some data to the server (for playback streams).
963    ///
964    /// This function does exactly the same as [`write()`] with the only difference being that a
965    /// void pointer is provided along with the `free_cb` callback pointer, and this void pointer
966    /// will be passed to the callback instead of the `data` pointer.
967    ///
968    /// # Params
969    ///
970    /// * `data`: The data to write. The length must be in multiples of the stream’s sample spec
971    ///   frame size.
972    /// * `free_cb`: A cleanup routine for the data or `None` to request an internal copy of the
973    ///   data. If provided, the accompanying data pointer will be supplied to the callback.
974    /// * `offset`: Offset for seeking. Must be `0` for upload streams.
975    /// * `seek`: Seek mode, must be [`SeekMode::Relative`] for upload streams.
976    ///
977    /// [`write()`]: Self::write
978    #[cfg(any(doc, feature = "pa_v6"))]
979    #[cfg_attr(docsrs, doc(cfg(feature = "pa_v6")))]
980    pub fn write_ext_free(&mut self, data: &[u8], free_cb: Option<(def::FreeCb, *mut c_void)>,
981        offset: i64, seek: SeekMode) -> Result<(), PAErr>
982    {
983        let (cb_f, cb_d) = match free_cb {
984            Some((f, d)) => (Some(f), d),
985            None => (None, null_mut::<c_void>()),
986        };
987        debug_assert_eq!(0, data.len().checked_rem(self.get_sample_spec().unwrap().frame_size())
988            .unwrap());
989        let r = unsafe {
990            capi::pa_stream_write_ext_free(self.ptr, data.as_ptr() as *const c_void, data.len(),
991                cb_f, cb_d, offset, seek.into())
992        };
993        match r {
994            0 => Ok(()),
995            e => Err(PAErr(e)),
996        }
997    }
998
999    /// Reads the next fragment from the buffer (for recording streams).
1000    ///
1001    /// This function returns one of the [`PeekResult`] variants - either [`Empty`], [`Hole`] or
1002    /// [`Data`]:
1003    ///
1004    ///  * If there is data at the current read index, the [`Data`] variant will be returned, which
1005    ///    contains a slice giving a view of the data. (The length of this slice can be less or more
1006    ///    than a complete fragment). This is pointing into an internal buffer, so obviously you
1007    ///    must make a copy of it if you want to keep it.
1008    ///  * If there is no data at the current read index, it means that either the buffer is empty
1009    ///    or it contains a hole (that is, the write index is ahead of the read index but there’s no
1010    ///    data where the read index points at). If the buffer is empty, the [`Empty`] result
1011    ///    variant will be returned. If there is a hole, the [`Hole`] variant will be returned,
1012    ///    containing the length of the hole in bytes.
1013    ///
1014    /// Use [`discard()`] to actually remove the data from the buffer and move the read index
1015    /// forward. [`discard()`] should not be called if the buffer is empty, but it should be called
1016    /// if there is a hole.
1017    ///
1018    /// [`Empty`]: PeekResult::Empty
1019    /// [`Hole`]: PeekResult::Hole
1020    /// [`Data`]: PeekResult::Data
1021    /// [`discard()`]: Self::discard
1022    pub fn peek<'a>(&mut self) -> Result<PeekResult<'a>, PAErr> {
1023        let mut data_ptr = null::<c_void>();
1024        let mut nbytes: usize = 0;
1025        // Note, C function returns an i32, but documentation does not mention any use of it, so we
1026        // discard it.
1027        match unsafe { capi::pa_stream_peek(self.ptr, &mut data_ptr, &mut nbytes) } {
1028            0 => {
1029                if data_ptr.is_null() {
1030                    match nbytes {
1031                        0 => Ok(PeekResult::Empty),
1032                        _ => Ok(PeekResult::Hole(nbytes)),
1033                    }
1034                }
1035                else {
1036                    let slice =
1037                        unsafe { std::slice::from_raw_parts(data_ptr as *const u8, nbytes) };
1038                    Ok(PeekResult::Data(slice))
1039                }
1040            },
1041            e => Err(PAErr(e)),
1042        }
1043    }
1044
1045    /// Removes the current fragment on record streams.
1046    ///
1047    /// It is invalid to do this without first calling [`peek()`](Self::peek).
1048    ///
1049    /// Note: The original C function name used the term `drop`; We instead use `discard` here to
1050    /// avoid conflict with the Rust `Drop` trait!
1051    pub fn discard(&mut self) -> Result<(), PAErr> {
1052        match unsafe { capi::pa_stream_drop(self.ptr) } {
1053            0 => Ok(()),
1054            e => Err(PAErr(e)),
1055        }
1056    }
1057
1058    /// Gets the number of bytes requested by the server that have not yet been written.
1059    ///
1060    /// It is possible to write more than this amount, up to the stream’s [`buffer_attr.maxlength`]
1061    /// bytes. This is usually not desirable, though, as it would increase stream latency to be
1062    /// higher than requested ([`buffer_attr.tlength`]).
1063    ///
1064    /// [`buffer_attr.maxlength`]: crate::def::BufferAttr.maxlength
1065    /// [`buffer_attr.tlength`]: crate::def::BufferAttr.tlength
1066    pub fn writable_size(&self) -> Option<usize> {
1067        match unsafe { capi::pa_stream_writable_size(self.ptr) } {
1068            std::usize::MAX => None,
1069            r => Some(r),
1070        }
1071    }
1072
1073    /// Gets the number of bytes that may be read using [`peek()`](Self::peek).
1074    ///
1075    /// Returns `None` on error.
1076    pub fn readable_size(&self) -> Option<usize> {
1077        match unsafe { capi::pa_stream_readable_size(self.ptr) } {
1078            std::usize::MAX => None,
1079            r => Some(r),
1080        }
1081    }
1082
1083    /// Drains a playback stream.
1084    ///
1085    /// Use this for notification when the playback buffer is empty after playing all the audio in
1086    /// the buffer. Please note that only one drain operation per stream may be issued at a time.
1087    ///
1088    /// The optional callback must accept a `bool`, which indicates success.
1089    ///
1090    /// Panics if the underlying C function returns a null pointer.
1091    pub fn drain(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1092        -> Operation<dyn FnMut(bool)>
1093    {
1094        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1095            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1096        let ptr = unsafe { capi::pa_stream_drain(self.ptr, cb_fn, cb_data) };
1097        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1098    }
1099
1100    /// Requests a timing info structure update for a stream.
1101    ///
1102    /// Use [`get_timing_info()`] to get access to the raw timing data, or [`get_time()`] or
1103    /// [`get_latency()`] to get cleaned up values.
1104    ///
1105    /// The optional callback must accept a `bool`, which indicates success.
1106    ///
1107    /// Panics if the underlying C function returns a null pointer.
1108    ///
1109    /// [`get_timing_info()`]: Self::get_timing_info
1110    /// [`get_time()`]: Self::get_time
1111    /// [`get_latency()`]: Self::get_latency
1112    pub fn update_timing_info(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1113        -> Operation<dyn FnMut(bool)>
1114    {
1115        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1116            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1117        let ptr = unsafe { capi::pa_stream_update_timing_info(self.ptr, cb_fn, cb_data) };
1118        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1119    }
1120
1121    /// Sets the callback function that is called whenever the state of the stream changes.
1122    pub fn set_state_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1123        let saved = &mut self.cb_ptrs.set_state;
1124        *saved = NotifyCb::new(callback);
1125        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1126        unsafe { capi::pa_stream_set_state_callback(self.ptr, cb_fn, cb_data); }
1127    }
1128
1129    /// Sets the callback function that is called when new data may be written to the stream.
1130    ///
1131    /// The callback accepts an argument giving the number of bytes.
1132    pub fn set_write_callback(&mut self, callback: Option<Box<dyn FnMut(usize) + 'static>>) {
1133        let saved = &mut self.cb_ptrs.write;
1134        *saved = RequestCb::new(callback);
1135        let (cb_fn, cb_data) = saved.get_capi_params(request_cb_proxy);
1136        unsafe { capi::pa_stream_set_write_callback(self.ptr, cb_fn, cb_data); }
1137    }
1138
1139    /// Sets the callback function that is called when new data is available from the stream.
1140    ///
1141    /// The callback accepts an argument giving the number of bytes.
1142    pub fn set_read_callback(&mut self, callback: Option<Box<dyn FnMut(usize) + 'static>>) {
1143        let saved = &mut self.cb_ptrs.read;
1144        *saved = RequestCb::new(callback);
1145        let (cb_fn, cb_data) = saved.get_capi_params(request_cb_proxy);
1146        unsafe { capi::pa_stream_set_read_callback(self.ptr, cb_fn, cb_data); }
1147    }
1148
1149    /// Sets the callback function that is called when a buffer overflow happens. (Only for playback
1150    /// streams).
1151    pub fn set_overflow_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1152        let saved = &mut self.cb_ptrs.overflow;
1153        *saved = NotifyCb::new(callback);
1154        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1155        unsafe { capi::pa_stream_set_overflow_callback(self.ptr, cb_fn, cb_data); }
1156    }
1157
1158    /// Gets at what position the latest underflow occurred.
1159    ///
1160    /// `None` is returned if this information is not known (e.g. if no underflow has occurred).
1161    ///
1162    /// This can be used inside the underflow callback to get information about the current
1163    /// underflow. (Only for playback streams).
1164    pub fn get_underflow_index(&self) -> Option<u64> {
1165        match unsafe { capi::pa_stream_get_underflow_index(self.ptr) } {
1166            r if r < 0 => None,
1167            r => Some(r as u64),
1168        }
1169    }
1170
1171    /// Sets the callback function that is called when a buffer underflow happens.
1172    ///
1173    /// (Only for playback streams).
1174    pub fn set_underflow_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1175        let saved = &mut self.cb_ptrs.underflow;
1176        *saved = NotifyCb::new(callback);
1177        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1178        unsafe { capi::pa_stream_set_underflow_callback(self.ptr, cb_fn, cb_data); }
1179    }
1180
1181    /// Sets the callback function that is called when the server starts playback after an underrun
1182    /// or on initial startup.
1183    ///
1184    /// This only informs that audio is flowing again, it is no indication that audio started to
1185    /// reach the speakers already. (Only for playback streams).
1186    pub fn set_started_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1187        let saved = &mut self.cb_ptrs.started;
1188        *saved = NotifyCb::new(callback);
1189        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1190        unsafe { capi::pa_stream_set_started_callback(self.ptr, cb_fn, cb_data); }
1191    }
1192
1193    /// Sets the callback function that is called whenever a latency information update happens.
1194    ///
1195    /// Useful on [`FlagSet::AUTO_TIMING_UPDATE`] streams only.
1196    pub fn set_latency_update_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1197        let saved = &mut self.cb_ptrs.latency_update;
1198        *saved = NotifyCb::new(callback);
1199        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1200        unsafe { capi::pa_stream_set_latency_update_callback(self.ptr, cb_fn, cb_data); }
1201    }
1202
1203    /// Sets the callback function that is called whenever the stream is moved to a different
1204    /// sink/source.
1205    ///
1206    /// Use [`get_device_name()`] or [`get_device_index()`] to query the new sink/source.
1207    ///
1208    /// [`get_device_name()`]: Self::get_device_name
1209    /// [`get_device_index()`]: Self::get_device_index
1210    pub fn set_moved_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1211        let saved = &mut self.cb_ptrs.moved;
1212        *saved = NotifyCb::new(callback);
1213        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1214        unsafe { capi::pa_stream_set_moved_callback(self.ptr, cb_fn, cb_data); }
1215    }
1216
1217    /// Sets the callback function that is called whenever the sink/source this stream is connected
1218    /// to is suspended or resumed.
1219    ///
1220    /// Use [`is_suspended()`] to query the new suspend status. Please note that the suspend status
1221    /// might also change when the stream is moved between devices. Thus if you call this function
1222    /// you very likely want to call [`set_moved_callback()`] too.
1223    ///
1224    /// [`is_suspended()`]: Self::is_suspended
1225    /// [`set_moved_callback()`]: Self::set_moved_callback
1226    pub fn set_suspended_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1227        let saved = &mut self.cb_ptrs.suspended;
1228        *saved = NotifyCb::new(callback);
1229        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1230        unsafe { capi::pa_stream_set_suspended_callback(self.ptr, cb_fn, cb_data); }
1231    }
1232
1233    /// Sets the callback function that is called whenever a meta/policy control event is received.
1234    ///
1235    /// The callback is given a name which represents what event occurred. The set of defined events
1236    /// can be extended at any time. Also, server modules may introduce additional message types so
1237    /// make sure that your callback function ignores messages it doesn’t know. Some well known
1238    /// event names can be found in the [`event_names`](mod@self::event_names) submodule. It is also
1239    /// given an (owned) property list.
1240    pub fn set_event_callback(&mut self,
1241        callback: Option<Box<dyn FnMut(String, Proplist) + 'static>>)
1242    {
1243        let saved = &mut self.cb_ptrs.event;
1244        *saved = EventCb::new(callback);
1245        let (cb_fn, cb_data) = saved.get_capi_params(event_cb_proxy);
1246        unsafe { capi::pa_stream_set_event_callback(self.ptr, cb_fn, cb_data); }
1247    }
1248
1249    /// Sets the callback function that is called whenever the buffer attributes on the server side
1250    /// change.
1251    ///
1252    /// Please note that the buffer attributes can change when moving a stream to a different
1253    /// sink/source too, hence if you use this callback you should use [`set_moved_callback()`] as
1254    /// well.
1255    ///
1256    /// [`set_moved_callback()`]: Self::set_moved_callback
1257    pub fn set_buffer_attr_callback(&mut self, callback: Option<Box<dyn FnMut() + 'static>>) {
1258        let saved = &mut self.cb_ptrs.buffer_attr;
1259        *saved = NotifyCb::new(callback);
1260        let (cb_fn, cb_data) = saved.get_capi_params(notify_cb_proxy);
1261        unsafe { capi::pa_stream_set_buffer_attr_callback(self.ptr, cb_fn, cb_data); }
1262    }
1263
1264    /// Pauses playback of this stream temporarily.
1265    ///
1266    /// Available on both playback and recording streams.
1267    ///
1268    /// The pause operation is executed as quickly as possible. If a cork is very quickly followed
1269    /// by an uncork, this might not actually have any effect on the stream that is output. You can
1270    /// use [`is_corked()`] to find out whether the stream is currently paused or not. Normally a
1271    /// stream will be created in uncorked state. If you pass [`FlagSet::START_CORKED`] as a flag
1272    /// when connecting the stream, it will be created in corked state.
1273    ///
1274    /// The optional callback must accept a `bool`, which indicates success.
1275    ///
1276    /// Panics if the underlying C function returns a null pointer.
1277    ///
1278    /// [`is_corked()`]: Self::is_corked
1279    pub fn cork(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1280        -> Operation<dyn FnMut(bool)>
1281    {
1282        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1283            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1284        let ptr = unsafe { capi::pa_stream_cork(self.ptr, true as i32, cb_fn, cb_data) };
1285        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1286    }
1287
1288    /// Resumes playback of this stream.
1289    ///
1290    /// Available on both playback and recording streams.
1291    ///
1292    /// The un-pause operation is executed as quickly as possible. If an uncork is very quickly
1293    /// followed by a cork, this might not actually have any effect on the stream that is output.
1294    /// You can use [`is_corked()`] to find out whether the stream is currently paused or not.
1295    /// Normally a stream will be created in uncorked state. If you pass [`FlagSet::START_CORKED`]
1296    /// as a flag when connecting the stream, it will be created in corked state.
1297    ///
1298    /// The optional callback must accept a `bool`, which indicates success.
1299    ///
1300    /// Panics if the underlying C function returns a null pointer.
1301    ///
1302    /// [`is_corked()`]: Self::is_corked
1303    pub fn uncork(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1304        -> Operation<dyn FnMut(bool)>
1305    {
1306        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1307            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1308        let ptr = unsafe { capi::pa_stream_cork(self.ptr, false as i32, cb_fn, cb_data) };
1309        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1310    }
1311
1312    /// Flushes the playback or record buffer of this stream.
1313    ///
1314    /// This discards any audio data in the buffer. Most of the time you’re better off using the
1315    /// parameter `seek` of [`write()`](Self::write) instead of this function.
1316    ///
1317    /// The optional callback must accept a `bool`, which indicates success.
1318    ///
1319    /// Panics if the underlying C function returns a null pointer.
1320    pub fn flush(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1321        -> Operation<dyn FnMut(bool)>
1322    {
1323        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1324            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1325        let ptr = unsafe { capi::pa_stream_flush(self.ptr, cb_fn, cb_data) };
1326        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1327    }
1328
1329    /// Re-enables prebuffering if specified in the [`BufferAttr`] structure.
1330    ///
1331    /// Available for playback streams only.
1332    ///
1333    /// The optional callback must accept a `bool`, which indicates success.
1334    ///
1335    /// Panics if the underlying C function returns a null pointer.
1336    ///
1337    /// [`BufferAttr`]: crate::def::BufferAttr
1338    pub fn prebuf(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1339        -> Operation<dyn FnMut(bool)>
1340    {
1341        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1342            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1343        let ptr = unsafe { capi::pa_stream_prebuf(self.ptr, cb_fn, cb_data) };
1344        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1345    }
1346
1347    /// Requests immediate start of playback on this stream.
1348    ///
1349    /// This disables prebuffering temporarily if specified in the [`BufferAttr`] structure.
1350    /// Available for playback streams only.
1351    ///
1352    /// The optional callback must accept a `bool`, which indicates success.
1353    ///
1354    /// Panics if the underlying C function returns a null pointer.
1355    ///
1356    /// [`BufferAttr`]: crate::def::BufferAttr
1357    pub fn trigger(&mut self, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1358        -> Operation<dyn FnMut(bool)>
1359    {
1360        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1361            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1362        let ptr = unsafe { capi::pa_stream_trigger(self.ptr, cb_fn, cb_data) };
1363        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1364    }
1365
1366    /// Renames the stream.
1367    ///
1368    /// The optional callback must accept a `bool`, which indicates success.
1369    ///
1370    /// Panics if the underlying C function returns a null pointer.
1371    pub fn set_name(&mut self, name: &str, callback: Option<Box<dyn FnMut(bool) + 'static>>)
1372        -> Operation<dyn FnMut(bool)>
1373    {
1374        // Warning: New CStrings will be immediately freed if not bound to a
1375        // variable, leading to as_ptr() giving dangling pointers!
1376        let c_name = CString::new(name).unwrap();
1377
1378        let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1379            get_su_capi_params::<_, _>(callback, success_cb_proxy);
1380        let ptr = unsafe { capi::pa_stream_set_name(self.ptr, c_name.as_ptr(), cb_fn, cb_data) };
1381        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1382    }
1383
1384    /// Gets the current playback/recording time.
1385    ///
1386    /// This is based on the data in the timing info structure returned by [`get_timing_info()`].
1387    /// The returned time is in the sound card clock domain, which usually runs at a slightly
1388    /// different rate than the system clock.
1389    ///
1390    /// This function will usually only return new data if a timing info update has been received.
1391    /// Only if timing interpolation has been requested ([`FlagSet::INTERPOLATE_TIMING`]) the data
1392    /// from the last timing update is used for an estimation of the current playback/recording time
1393    /// based on the local time that passed since the timing info structure has been acquired.
1394    ///
1395    /// The time value returned by this function is guaranteed to increase monotonically (the
1396    /// returned value is always greater or equal to the value returned by the last call). This
1397    /// behaviour can be disabled by using [`FlagSet::NOT_MONOTONIC`]. This may be desirable to
1398    /// better deal with bad estimations of transport latencies, but may have strange effects if the
1399    /// application is not able to deal with time going ‘backwards’.
1400    ///
1401    /// The time interpolator activated by [`FlagSet::INTERPOLATE_TIMING`] favours ‘smooth’ time
1402    /// graphs over accurate ones to improve the smoothness of UI operations that are tied to the
1403    /// audio clock. If accuracy is more important to you, you might need to estimate your timing
1404    /// based on the data from [`get_timing_info()`] yourself or not work with interpolated timing
1405    /// at all and instead always query the server side for the most up to date timing with
1406    /// [`update_timing_info()`].
1407    ///
1408    /// If no timing information has been received yet this call will return `Ok(None)`. For more
1409    /// details see [`get_timing_info()`].
1410    ///
1411    /// [`get_timing_info()`]: Self::get_timing_info
1412    /// [`update_timing_info()`]: Self::update_timing_info
1413    pub fn get_time(&self) -> Result<Option<MicroSeconds>, PAErr> {
1414        let mut r_usecs = MicroSeconds(0);
1415        match unsafe { capi::pa_stream_get_time(self.ptr, &mut r_usecs.0) } {
1416            0 => Ok(Some(r_usecs)),
1417            e if e == PAErr::from(error::Code::NoData).0 => Ok(None),
1418            e => Err(PAErr(e)),
1419        }
1420    }
1421
1422    /// Determines the total stream latency.
1423    ///
1424    /// This function is based on [`get_time()`]. The returned time is in the sound card clock
1425    /// domain, which usually runs at a slightly different rate than the system clock.
1426    ///
1427    /// In case the stream is a monitoring stream the result can be negative, i.e. the captured
1428    /// samples are not yet played, in which case `Ok(Latency::Negative(usecs))` will be returned
1429    /// instead of `Ok(Latency::Positive(usecs))`
1430    ///
1431    /// If no timing information has been received yet, this call will return `Ok(Latency::None)`.
1432    ///
1433    /// For more details see [`get_timing_info()`] and [`get_time()`].
1434    ///
1435    /// [`get_time()`]: Self::get_time
1436    /// [`get_timing_info()`]: Self::get_timing_info
1437    pub fn get_latency(&self) -> Result<Latency, PAErr> {
1438        let mut r_usecs = MicroSeconds(0);
1439        let mut negative: i32 = 0;
1440        match unsafe { capi::pa_stream_get_latency(self.ptr, &mut r_usecs.0, &mut negative) } {
1441            0 => match negative {
1442                1 => Ok(Latency::Negative(r_usecs)),
1443                _ => Ok(Latency::Positive(r_usecs)),
1444            },
1445            e if e == PAErr::from(error::Code::NoData).0 => Ok(Latency::None),
1446            e => Err(PAErr(e)),
1447        }
1448    }
1449
1450    /// Gets the latest raw timing data structure.
1451    ///
1452    /// The returned pointer refers to an internal read-only instance of the timing structure. The
1453    /// user should make a copy of this structure if wanting to modify it. An in-place update to
1454    /// this data structure may be requested using [`update_timing_info()`].
1455    ///
1456    /// If no timing information has been received before (i.e. by requesting
1457    /// [`update_timing_info()`] or by using [`FlagSet::AUTO_TIMING_UPDATE`]), this function will
1458    /// return `None` (as it will also if an error occurs).
1459    ///
1460    /// Please note that the `write_index` member field (and only this field) is updated on each
1461    /// [`write()`] call, not just when a timing update has been received.
1462    ///
1463    /// [`update_timing_info()`]: Self::update_timing_info
1464    /// [`write()`]: Self::write
1465    pub fn get_timing_info<'a>(&mut self) -> Option<&'a def::TimingInfo> {
1466        unsafe {
1467            let ptr = capi::pa_stream_get_timing_info(self.ptr);
1468            ptr.as_ref().map(|r| r.as_ref())
1469        }
1470    }
1471
1472    /// Gets a pointer to the stream’s sample specification.
1473    pub fn get_sample_spec<'a>(&mut self) -> Option<&'a sample::Spec> {
1474        unsafe {
1475            let ptr = capi::pa_stream_get_sample_spec(self.ptr);
1476            ptr.as_ref().map(|r| r.as_ref())
1477        }
1478    }
1479
1480    /// Gets a pointer to the stream’s channel map.
1481    pub fn get_channel_map<'a>(&mut self) -> Option<&'a channelmap::Map> {
1482        unsafe {
1483            let ptr = capi::pa_stream_get_channel_map(self.ptr);
1484            ptr.as_ref().map(|r| r.as_ref())
1485        }
1486    }
1487
1488    /// Gets a pointer to the stream’s format.
1489    pub fn get_format_info(&self) -> Option<format::Info> {
1490        let ptr = unsafe { capi::pa_stream_get_format_info(self.ptr) };
1491        match ptr.is_null() {
1492            false => Some(format::Info::from_raw_weak(ptr as *mut InfoInternal)),
1493            true => None,
1494        }
1495    }
1496
1497    /// Gets the per-stream server-side buffer metrics of the stream.
1498    ///
1499    /// Only valid after the stream has been connected successfully. This will return the actual
1500    /// configured buffering metrics, which may differ from what was requested during
1501    /// [`connect_record()`] or [`connect_playback()`]. This call will always return the actual
1502    /// per-stream server-side buffer metrics, regardless whether [`FlagSet::ADJUST_LATENCY`] is set
1503    /// or not.
1504    ///
1505    /// [`connect_record()`]: Self::connect_record
1506    /// [`connect_playback()`]: Self::connect_playback
1507    pub fn get_buffer_attr<'a>(&mut self) -> Option<&'a def::BufferAttr> {
1508        unsafe {
1509            let ptr = capi::pa_stream_get_buffer_attr(self.ptr);
1510            ptr.as_ref().map(|r| r.as_ref())
1511        }
1512    }
1513
1514    /// Changes the buffer metrics of the stream during playback.
1515    ///
1516    /// The server might have chosen different buffer metrics then requested. The selected metrics
1517    /// may be queried with [`get_buffer_attr()`] as soon as the callback is called. Only valid
1518    /// after the stream has been connected successfully. Please be aware of the slightly different
1519    /// semantics of the call depending whether [`FlagSet::ADJUST_LATENCY`] is set or not.
1520    ///
1521    /// The callback must accept a `bool`, which indicates success.
1522    ///
1523    /// Panics if the underlying C function returns a null pointer.
1524    ///
1525    /// [`get_buffer_attr()`]: Self::get_buffer_attr
1526    pub fn set_buffer_attr<F>(&mut self, attr: &def::BufferAttr, callback: F)
1527        -> Operation<dyn FnMut(bool)>
1528        where F: FnMut(bool) + 'static
1529    {
1530        let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1531        let ptr = unsafe { capi::pa_stream_set_buffer_attr(self.ptr, attr.as_ref(),
1532            Some(success_cb_proxy), cb_data) };
1533        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1534    }
1535
1536    /// Changes the stream sampling rate during playback.
1537    ///
1538    /// You need to pass [`FlagSet::VARIABLE_RATE`] in the flags parameter of [`connect_playback()`]
1539    /// if you plan to use this function. Only valid after the stream has been connected
1540    /// successfully.
1541    ///
1542    /// The callback must accept a `bool`, which indicates success.
1543    ///
1544    /// Panics if the underlying C function returns a null pointer.
1545    ///
1546    /// [`connect_playback()`]: Self::connect_playback
1547    pub fn update_sample_rate<F>(&mut self, rate: u32, callback: F) -> Operation<dyn FnMut(bool)>
1548        where F: FnMut(bool) + 'static
1549    {
1550        let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1551        let ptr = unsafe { capi::pa_stream_update_sample_rate(self.ptr, rate,
1552            Some(success_cb_proxy), cb_data) };
1553        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1554    }
1555
1556    /// Updates the property list of the sink input/source output of this stream, adding new
1557    /// entries.
1558    ///
1559    /// Please note that it is highly recommended to set as many properties initially via
1560    /// [`new_with_proplist()`] as possible instead a posteriori with this function, since that
1561    /// information may be used to route this stream to the right device.
1562    ///
1563    /// The callback must accept a `bool`, which indicates success.
1564    ///
1565    /// Panics if the underlying C function returns a null pointer.
1566    ///
1567    /// [`new_with_proplist()`]: Self::new_with_proplist
1568    pub fn update_proplist<F>(&mut self, mode: proplist::UpdateMode, proplist: &mut Proplist,
1569        callback: F) -> Operation<dyn FnMut(bool)>
1570        where F: FnMut(bool) + 'static
1571    {
1572        let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1573        let ptr = unsafe { capi::pa_stream_proplist_update(self.ptr, mode, proplist.0.ptr,
1574            Some(success_cb_proxy), cb_data) };
1575        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1576    }
1577
1578    /// Updates the property list of the sink input/source output of this stream, removing entries.
1579    ///
1580    /// The callback must accept a `bool`, which indicates success.
1581    ///
1582    /// Panics if the underlying C function returns a null pointer.
1583    pub fn remove_proplist<F>(&mut self, keys: &[&str], callback: F) -> Operation<dyn FnMut(bool)>
1584        where F: FnMut(bool) + 'static
1585    {
1586        // Warning: New CStrings will be immediately freed if not bound to a variable, leading to
1587        // as_ptr() giving dangling pointers!
1588        let mut c_keys: Vec<CString> = Vec::with_capacity(keys.len());
1589        for key in keys {
1590            c_keys.push(CString::new(*key).unwrap());
1591        }
1592
1593        // Capture array of pointers to the above CString values
1594        // We also add a null pointer entry on the end, as expected by the C function called here.
1595        let mut c_key_ptrs: Vec<*const c_char> = Vec::with_capacity(c_keys.len() + 1);
1596        for c_key in &c_keys {
1597            c_key_ptrs.push(c_key.as_ptr());
1598        }
1599        c_key_ptrs.push(null());
1600
1601        let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1602        let ptr = unsafe {
1603            capi::pa_stream_proplist_remove(self.ptr, c_key_ptrs.as_ptr(),
1604                Some(success_cb_proxy), cb_data)
1605        };
1606        Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1607    }
1608
1609    /// For record streams connected to a monitor source: monitors only a very specific sink input
1610    /// of the sink.
1611    ///
1612    /// This function needs to be called before [`connect_record()`](Self::connect_record) is
1613    /// called.
1614    pub fn set_monitor_stream(&mut self, sink_input_index: u32) -> Result<(), PAErr> {
1615        match unsafe { capi::pa_stream_set_monitor_stream(self.ptr, sink_input_index) } {
1616            0 => Ok(()),
1617            e => Err(PAErr(e)),
1618        }
1619    }
1620
1621    /// Gets the sink input index previously set with [`set_monitor_stream()`].
1622    ///
1623    /// [`set_monitor_stream()`]: Self::set_monitor_stream
1624    pub fn get_monitor_stream(&self) -> Option<u32> {
1625        match unsafe { capi::pa_stream_get_monitor_stream(self.ptr) } {
1626            def::INVALID_INDEX => None,
1627            r => Some(r),
1628        }
1629    }
1630}
1631
1632impl Drop for Stream {
1633    fn drop(&mut self) {
1634        // Throw away the `Result` from disconnecting, it may legitimately be bad if stream failed.
1635        // See https://github.com/jnqnfe/pulse-binding-rust/issues/11
1636        let _ = self.disconnect();
1637        unsafe { capi::pa_stream_unref(self.ptr) };
1638        self.ptr = null_mut::<StreamInternal>();
1639    }
1640}
1641
1642/// Proxy for completion success callbacks.
1643///
1644/// Warning: This is for single-use cases only! It destroys the actual closure callback.
1645extern "C"
1646fn success_cb_proxy(_: *mut StreamInternal, success: i32, userdata: *mut c_void) {
1647    let success_actual = match success { 0 => false, _ => true };
1648    let _ = std::panic::catch_unwind(|| {
1649        // Note, destroys closure callback after use - restoring outer box means it gets dropped
1650        let mut callback = get_su_callback::<dyn FnMut(bool)>(userdata);
1651        (callback)(success_actual);
1652    });
1653}
1654
1655/// Proxy for request callbacks.
1656///
1657/// Warning: This is for multi-use cases! It does **not** destroy the actual closure callback, which
1658/// must be accomplished separately to avoid a memory leak.
1659extern "C"
1660fn request_cb_proxy(_: *mut StreamInternal, nbytes: usize, userdata: *mut c_void) {
1661    let _ = std::panic::catch_unwind(|| {
1662        let callback = RequestCb::get_callback(userdata);
1663        (callback)(nbytes);
1664    });
1665}
1666
1667/// Proxy for notify callbacks.
1668///
1669/// Warning: This is for multi-use cases! It does **not** destroy the actual closure callback, which
1670/// must be accomplished separately to avoid a memory leak.
1671extern "C"
1672fn notify_cb_proxy(_: *mut StreamInternal, userdata: *mut c_void) {
1673    let _ = std::panic::catch_unwind(|| {
1674        let callback = NotifyCb::get_callback(userdata);
1675        (callback)();
1676    });
1677}
1678
1679/// Proxy for event callbacks.
1680///
1681/// Warning: This is for multi-use cases! It does **not** destroy the actual closure callback, which
1682/// must be accomplished separately to avoid a memory leak.
1683extern "C"
1684fn event_cb_proxy(_: *mut StreamInternal, name: *const c_char, proplist: *mut ProplistInternal,
1685    userdata: *mut c_void)
1686{
1687    let _ = std::panic::catch_unwind(|| {
1688        assert!(!name.is_null());
1689        let n = {
1690            let tmp = unsafe { CStr::from_ptr(name) };
1691            tmp.to_string_lossy().into_owned()
1692        };
1693        let pl = Proplist::from_raw_weak(proplist);
1694
1695        let callback = EventCb::get_callback(userdata);
1696        (callback)(n, pl);
1697    });
1698}