libpulse_binding/def.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//! Global definitions.
15
16use std::os::raw::c_void;
17use bitflags::bitflags;
18use num_derive::{FromPrimitive, ToPrimitive};
19use crate::time::{MicroSeconds, UnixTs};
20
21pub use capi::PA_INVALID_INDEX as INVALID_INDEX;
22pub use capi::pa_device_type_t as Device;
23pub use capi::pa_port_available_t as PortAvailable;
24pub use capi::pa_device_port_type_t as DevicePortType;
25
26/// A callback type for releasing allocations.
27pub type FreeCb = extern "C" fn(p: *mut c_void);
28
29/// PulseAudio 'quit return value' type.
30pub type RetvalActual = i32;
31
32/// A wrapper around integer ‘quit return values’ returned by PulseAudio.
33#[repr(transparent)]
34#[derive(Debug, Copy, Clone, PartialEq, Eq)]
35pub struct Retval(pub RetvalActual);
36
37/// Playback and record buffer metrics.
38#[repr(C)]
39#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
40pub struct BufferAttr {
41 /* NOTE: This struct must be directly usable by the C API, thus same attributes/layout/etc */
42
43 /// Maximum length of the buffer in bytes.
44 ///
45 /// Setting this to [`std::u32::MAX`] will initialize this to the maximum value supported by the
46 /// server, which is recommended. In strict low-latency playback scenarios you might want to set
47 /// this to a lower value, likely together with the [`stream::FlagSet::ADJUST_LATENCY`] flag. If
48 /// you do so, you ensure that the latency doesn’t grow beyond what is acceptable for the use
49 /// case, at the cost of getting more underruns if the latency is lower than what the server can
50 /// reliably handle.
51 ///
52 /// [`stream::FlagSet::ADJUST_LATENCY`]: crate::stream::FlagSet::ADJUST_LATENCY
53 pub maxlength: u32,
54
55 /// Target length of the buffer (playback only). The server tries to assure that at least
56 /// `tlength` bytes are always available in the per-stream server-side playback buffer. The
57 /// server will only send requests for more data as long as the buffer has less than this number
58 /// of bytes of data.
59 ///
60 /// It is recommended to set this to [`std::u32::MAX`], which will initialize this to a value
61 /// that is deemed sensible by the server. However, this value will default to something like
62 /// 2s; for applications that have specific latency requirements this value should be set to
63 /// the maximum latency that the application can deal with.
64 ///
65 /// When [`stream::FlagSet::ADJUST_LATENCY`] is not set this value will influence only the
66 /// per-stream playback buffer size. When [`stream::FlagSet::ADJUST_LATENCY`] is set, the
67 /// overall latency of the sink plus the playback buffer size is configured to this value. Set
68 /// [`stream::FlagSet::ADJUST_LATENCY`] if you are interested in adjusting the overall latency.
69 /// Don’t set it if you are interested in configuring the server-side per-stream playback buffer
70 /// size.
71 ///
72 /// [`stream::FlagSet::ADJUST_LATENCY`]: crate::stream::FlagSet::ADJUST_LATENCY
73 pub tlength: u32,
74
75 /// Pre-buffering (playback only). The server does not start with playback before at least
76 /// `prebuf` bytes are available in the buffer. It is recommended to set this to
77 /// [`std::u32::MAX`], which will initialize this to the same value as `tlength`, whatever that
78 /// may be.
79 ///
80 /// Initialize to `0` to enable manual start/stop control of the stream. This means that
81 /// playback will not stop on underrun and playback will not start automatically, instead
82 /// [`Stream::cork()`] needs to be called explicitly. If you set this value to `0` you should
83 /// also set [`stream::FlagSet::START_CORKED`]. Should underrun occur, the read index of the
84 /// output buffer overtakes the write index, and hence the fill level of the buffer is negative.
85 ///
86 /// Start of playback can be forced using [`Stream::trigger()`] even though the prebuffer size
87 /// hasn’t been reached. If a buffer underrun occurs, this prebuffering will be again enabled.
88 ///
89 /// [`Stream::cork()`]: crate::stream::Stream::cork
90 /// [`Stream::trigger()`]: crate::stream::Stream::trigger
91 /// [`stream::FlagSet::START_CORKED`]: crate::stream::FlagSet::START_CORKED
92 pub prebuf: u32,
93
94 /// Minimum request (playback only). The server does not request less than `minreq` bytes from
95 /// the client, instead it waits until the buffer is free enough to request more bytes at once.
96 ///
97 /// It is recommended to set this to [`std::u32::MAX`], which will initialize this to a value
98 /// that is deemed sensible by the server. This should be set to a value that gives PulseAudio
99 /// enough time to move the data from the per-stream playback buffer into the hardware playback
100 /// buffer.
101 pub minreq: u32,
102
103 /// Fragment size (recording only). The server sends data in blocks of `fragsize` bytes size.
104 ///
105 /// Large values diminish interactivity with other operations on the connection context but
106 /// decrease control overhead. It is recommended to set this to `std::u32::MAX`, which will
107 /// initialize this to a value that is deemed sensible by the server. However, this value will
108 /// default to something like 2s; For applications that have specific latency requirements this
109 /// value should be set to the maximum latency that the application can deal with.
110 ///
111 /// If [`stream::FlagSet::ADJUST_LATENCY`] is set the overall source latency will be adjusted
112 /// according to this value. If it is not set the source latency is left unmodified.
113 ///
114 /// [`stream::FlagSet::ADJUST_LATENCY`]: crate::stream::FlagSet::ADJUST_LATENCY
115 pub fragsize: u32,
116}
117
118/// Test size is equal to `sys` equivalent (duplicated here for different documentation)
119#[test]
120fn bufferattr_compare_capi() {
121 assert_eq!(std::mem::size_of::<BufferAttr>(), std::mem::size_of::<capi::pa_buffer_attr>());
122 assert_eq!(std::mem::align_of::<BufferAttr>(), std::mem::align_of::<capi::pa_buffer_attr>());
123}
124
125impl AsRef<capi::pa_buffer_attr> for BufferAttr {
126 #[inline]
127 fn as_ref(&self) -> &capi::pa_buffer_attr {
128 unsafe { &*(self as *const Self as *const capi::pa_buffer_attr) }
129 }
130}
131impl AsRef<BufferAttr> for capi::pa_buffer_attr {
132 #[inline]
133 fn as_ref(&self) -> &BufferAttr {
134 unsafe { &*(self as *const Self as *const BufferAttr) }
135 }
136}
137
138/// A structure for all kinds of timing information of a stream.
139///
140/// See [`Stream::update_timing_info()`] and [`Stream::get_timing_info()`].
141///
142/// The total output latency a sample that is written with [`Stream::write()`] takes to be played
143/// may be estimated by:
144///
145/// ``
146/// sink_usec + buffer_usec + transport_usec
147/// ``
148///
149/// (Where `buffer_usec` is defined as the result of passing ``write_index - read_index`` to
150/// [`Spec::bytes_to_usec()`]). The output buffer which `buffer_usec` relates to may be manipulated
151/// freely (with [`Stream::write()`]’s `seek` argument, [`Stream::flush()`] and friends), the
152/// buffers `sink_usec` and `source_usec` relate to are first-in first-out (FIFO) buffers which
153/// cannot be flushed or manipulated in any way. The total input latency a sample that is recorded
154/// takes to be delivered to the application is:
155///
156/// ``
157/// source_usec + buffer_usec + transport_usec - sink_usec
158/// ``
159///
160/// (Take care of sign issues!). When connected to a monitor source `sink_usec` contains the latency
161/// of the owning sink. The two latency estimations described here are implemented in
162/// [`Stream::get_latency()`].
163///
164/// All time values are in the sound card clock domain, unless noted otherwise. The sound card clock
165/// usually runs at a slightly different rate than the system clock.
166///
167/// Please note that this structure can be extended as part of evolutionary API updates at any time
168/// in any new release.
169///
170/// [`Spec::bytes_to_usec()`]: crate::sample::Spec::bytes_to_usec
171/// [`Stream::update_timing_info()`]: crate::stream::Stream::update_timing_info
172/// [`Stream::get_timing_info()`]: crate::stream::Stream::get_timing_info
173/// [`Stream::write()`]: crate::stream::Stream::write
174/// [`Stream::flush()`]: crate::stream::Stream::flush
175/// [`Stream::get_latency()`]: crate::stream::Stream::get_latency
176#[repr(C)]
177#[derive(Debug, Copy, Clone, PartialEq, Eq)]
178pub struct TimingInfo {
179 /* NOTE: This struct must be directly usable by the C API, thus same attributes/layout/etc */
180
181 /// The system clock time when this timing info structure was current.
182 pub timestamp: UnixTs,
183
184 /// Non-zero if the local and the remote machine have synchronized clocks. If synchronized
185 /// clocks are detected `transport_usec` becomes much more reliable. However, the code that
186 /// detects synchronized clocks is very limited and unreliable itself.
187 pub synchronized_clocks: i32,
188
189 /// Time in usecs a sample takes to be played on the sink. For playback streams and record
190 /// streams connected to a monitor source.
191 pub sink_usec: MicroSeconds,
192
193 /// Time in usecs a sample takes from being recorded to being delivered to the application. Only
194 /// for record streams.
195 pub source_usec: MicroSeconds,
196
197 /// Estimated time in usecs a sample takes to be transferred to/from the daemon. For both
198 /// playback and record streams.
199 pub transport_usec: MicroSeconds,
200
201 /// Non-zero when the stream is currently not underrun and data is being passed on to the
202 /// device. Only for playback streams. This field does not say whether the data is actually
203 /// already being played. To determine this check whether `since_underrun` (converted to usec)
204 /// is larger than `sink_usec`.
205 pub playing: i32,
206
207 /// Non-zero if `write_index` is not up-to-date because a local write command that corrupted it
208 /// has been issued in the time since this latency info was current. Only write commands with
209 /// [`SeekMode::RelativeOnRead`] and [`SeekMode::RelativeEnd`] can corrupt `write_index`.
210 ///
211 /// [`SeekMode::RelativeOnRead`]: crate::stream::SeekMode::RelativeOnRead
212 /// [`SeekMode::RelativeEnd`]: crate::stream::SeekMode::RelativeEnd
213 pub write_index_corrupt: i32,
214
215 /// Current write index into the playback buffer in bytes.
216 ///
217 /// Think twice before using this for seeking purposes: it might be out of date at the time you
218 /// want to use it. Consider using [`SeekMode::Relative`] instead.
219 ///
220 /// [`SeekMode::Relative`]: crate::stream::SeekMode::Relative
221 pub write_index: i64,
222
223 /// Non-zero if `read_index` is not up-to-date because a local pause or flush request that
224 /// corrupted it has been issued in the time since this latency info was current.
225 pub read_index_corrupt: i32,
226
227 /// Current read index into the playback buffer in bytes.
228 ///
229 /// Think twice before using this for seeking purposes: it might be out of date at the time you
230 /// want to use it. Consider using [`SeekMode::RelativeOnRead`] instead.
231 ///
232 /// [`SeekMode::RelativeOnRead`]: crate::stream::SeekMode::RelativeOnRead
233 pub read_index: i64,
234
235 /// The configured latency for the sink.
236 pub configured_sink_usec: MicroSeconds,
237
238 /// The configured latency for the source.
239 pub configured_source_usec: MicroSeconds,
240
241 /// Bytes that were handed to the sink since the last underrun happened, or since playback
242 /// started again after the last underrun. `playing` will tell you which case it is.
243 pub since_underrun: i64,
244}
245
246/// Test size is equal to `sys` equivalent (duplicated here for different documentation)
247#[test]
248fn timinginfo_compare_capi() {
249 assert_eq!(std::mem::size_of::<TimingInfo>(), std::mem::size_of::<capi::pa_timing_info>());
250 assert_eq!(std::mem::align_of::<TimingInfo>(), std::mem::align_of::<capi::pa_timing_info>());
251}
252
253impl AsRef<TimingInfo> for capi::pa_timing_info {
254 #[inline]
255 fn as_ref(&self) -> &TimingInfo {
256 unsafe { &*(self as *const Self as *const TimingInfo) }
257 }
258}
259
260/// A structure for the spawn API.
261///
262/// This may be used to integrate auto spawned daemons into your application. For more information
263/// see [`Context::connect()`]. When spawning a new child process the `waitpid()` is used on the
264/// child’s PID. The spawn routine will not block or ignore SIGCHLD signals, since this cannot be
265/// done in a thread compatible way. You might have to do this in prefork/postfork.
266///
267/// [`Context::connect()`]: crate::context::Context::connect
268#[repr(C)]
269#[derive(Debug)]
270pub struct SpawnApi {
271 /* NOTE: This struct must be directly usable by the C API, thus same attributes/layout/etc */
272
273 /// Is called just before the fork in the parent process.
274 pub prefork: Option<extern "C" fn()>,
275
276 /// Is called immediately after the fork in the parent process.
277 pub postfork: Option<extern "C" fn()>,
278
279 /// Is called immediately after the fork in the child process.
280 ///
281 /// It is not safe to close all file descriptors in this function unconditionally, since a UNIX
282 /// socket (created using socketpair()) is passed to the new process.
283 pub atfork: Option<extern "C" fn()>,
284}
285
286/// Test size is equal to `sys` equivalent (duplicated here for different documentation)
287#[test]
288fn spawnapi_compare_capi() {
289 assert_eq!(std::mem::size_of::<SpawnApi>(), std::mem::size_of::<capi::pa_spawn_api>());
290 assert_eq!(std::mem::align_of::<SpawnApi>(), std::mem::align_of::<capi::pa_spawn_api>());
291}
292
293impl AsRef<capi::pa_spawn_api> for SpawnApi {
294 #[inline]
295 fn as_ref(&self) -> &capi::pa_spawn_api {
296 unsafe { &*(self as *const Self as *const capi::pa_spawn_api) }
297 }
298}
299
300bitflags! {
301 /// Set of sink flags.
302 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
303 #[repr(transparent)]
304 pub struct SinkFlagSet: u32 {
305 /// Flag to pass when no specific options are needed.
306 const NOFLAGS = capi::PA_SINK_NOFLAGS;
307
308 /// Supports hardware volume control. This is a dynamic flag and may change at runtime after
309 /// the sink has initialized.
310 const HW_VOLUME_CTRL = capi::PA_SINK_HW_VOLUME_CTRL;
311
312 /// Supports latency querying.
313 const LATENCY = capi::PA_SINK_LATENCY;
314
315 /// Is a hardware sink of some kind, in contrast to “virtual”/software sinks.
316 const HARDWARE = capi::PA_SINK_HARDWARE;
317
318 /// Is a networked sink of some kind.
319 const NETWORK = capi::PA_SINK_NETWORK;
320
321 /// Supports hardware mute control. This is a dynamic flag and may change at runtime after
322 /// the sink has initialized.
323 const HW_MUTE_CTRL = capi::PA_SINK_HW_MUTE_CTRL;
324
325 /// Volume can be translated to dB with the `From` based conversions between [`Volume`],
326 /// [`VolumeLinear`] and [`VolumeDB`] types. This is a dynamic flag and may change at
327 /// runtime after the sink has initialized.
328 ///
329 /// [`Volume`]: crate::volume::Volume
330 /// [`VolumeDB`]: crate::volume::VolumeDB
331 /// [`VolumeLinear`]: crate::volume::VolumeLinear
332 const DECIBEL_VOLUME = capi::PA_SINK_DECIBEL_VOLUME;
333
334 /// This sink is in flat volume mode, i.e. always the maximum of the volume of all
335 /// connected inputs.
336 const FLAT_VOLUME = capi::PA_SINK_FLAT_VOLUME;
337
338 /// The latency can be adjusted dynamically depending on the needs of the connected streams.
339 const DYNAMIC_LATENCY = capi::PA_SINK_DYNAMIC_LATENCY;
340
341 /// The sink allows setting what formats are supported by the connected hardware. The actual
342 /// functionality to do this might be provided by an extension.
343 const SET_FORMATS = capi::PA_SINK_SET_FORMATS;
344 }
345}
346
347/// Sink state.
348#[repr(C)]
349#[derive(Debug, Copy, Clone, PartialEq, Eq)]
350#[derive(FromPrimitive, ToPrimitive)]
351pub enum SinkState {
352 /* NOTE: This enum’s variants and variant values **must** remain identical to the `sys` crate
353 (C API) equivalent */
354
355 /// This state is used when the server does not support sink state introspection.
356 Invalid = -1,
357
358 /// Running, sink is playing and used by at least one non-corked sink-input.
359 Running = 0,
360
361 /// When idle, the sink is playing but there is no non-corked sink-input attached to it.
362 Idle = 1,
363
364 /// When suspended, actual sink access can be closed, for instance.
365 Suspended = 2,
366}
367
368/// Check is equal to `sys` equivalent
369#[test]
370fn sink_state_compare_capi() {
371 assert_eq!(std::mem::size_of::<SinkState>(), std::mem::size_of::<capi::pa_sink_state_t>());
372 assert_eq!(std::mem::align_of::<SinkState>(), std::mem::align_of::<capi::pa_sink_state_t>());
373
374 // Check order and value of variants match
375 // No point checking conversions in both directions since both are a transmute
376 assert_eq!(SinkState::Invalid, SinkState::from(capi::pa_sink_state_t::Invalid));
377 assert_eq!(SinkState::Running, SinkState::from(capi::pa_sink_state_t::Running));
378 assert_eq!(SinkState::Idle, SinkState::from(capi::pa_sink_state_t::Idle));
379 assert_eq!(SinkState::Suspended, SinkState::from(capi::pa_sink_state_t::Suspended));
380}
381
382impl From<SinkState> for capi::pa_sink_state_t {
383 #[inline]
384 fn from(s: SinkState) -> Self {
385 unsafe { std::mem::transmute(s) }
386 }
387}
388impl From<capi::pa_sink_state_t> for SinkState {
389 #[inline]
390 fn from(s: capi::pa_sink_state_t) -> Self {
391 unsafe { std::mem::transmute(s) }
392 }
393}
394
395impl SinkState {
396 /// Checks if sink is playing: running or idle.
397 #[inline]
398 pub fn is_opened(self) -> bool {
399 self == SinkState::Running || self == SinkState::Idle
400 }
401
402 /// Checks if sink is running.
403 #[inline]
404 pub fn is_running(self) -> bool {
405 self == SinkState::Running
406 }
407}
408
409bitflags! {
410 /// Set of source flags.
411 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
412 #[repr(transparent)]
413 pub struct SourceFlagSet: u32 {
414 /// Flag to pass when no specific options are needed.
415 const NOFLAGS = capi::PA_SOURCE_NOFLAGS;
416
417 /// Supports hardware volume control. This is a dynamic flag and may change at runtime after
418 /// the source has initialized.
419 const HW_VOLUME_CTRL = capi::PA_SOURCE_HW_VOLUME_CTRL;
420
421 /// Supports latency querying.
422 const LATENCY = capi::PA_SOURCE_LATENCY;
423
424 /// Is a hardware source of some kind, in contrast to “virtual”/software source.
425 const HARDWARE = capi::PA_SOURCE_HARDWARE;
426
427 /// Is a networked source of some kind.
428 const NETWORK = capi::PA_SOURCE_NETWORK;
429
430 /// Supports hardware mute control. This is a dynamic flag and may change at runtime after
431 /// the source has initialized.
432 const HW_MUTE_CTRL = capi::PA_SOURCE_HW_MUTE_CTRL;
433
434 /// Volume can be translated to dB with the `From` based conversions between [`Volume`],
435 /// [`VolumeLinear`] and [`VolumeDB`] types. This is a dynamic flag and may change at
436 /// runtime after the source has initialized.
437 ///
438 /// [`Volume`]: crate::volume::Volume
439 /// [`VolumeDB`]: crate::volume::VolumeDB
440 /// [`VolumeLinear`]: crate::volume::VolumeLinear
441 const DECIBEL_VOLUME = capi::PA_SOURCE_DECIBEL_VOLUME;
442
443 /// The latency can be adjusted dynamically depending on the needs of the connected streams.
444 const DYNAMIC_LATENCY = capi::PA_SOURCE_DYNAMIC_LATENCY;
445
446 /// This source is in flat volume mode, i.e. always the maximum of the volume of all
447 /// connected outputs.
448 const FLAT_VOLUME = capi::PA_SOURCE_FLAT_VOLUME;
449 }
450}
451
452/// Source state.
453#[repr(C)]
454#[derive(Debug, Copy, Clone, PartialEq, Eq)]
455#[derive(FromPrimitive, ToPrimitive)]
456pub enum SourceState {
457 /* NOTE: This enum’s variants and variant values **must** remain identical to the `sys` crate
458 (C API) equivalent */
459
460 /// This state is used when the server does not support source state introspection.
461 Invalid = -1,
462
463 /// Running, source is recording and used by at least one non-corked source-output.
464 Running = 0,
465
466 /// When idle, the source is still recording but there is no non-corked source-output.
467 Idle = 1,
468
469 /// When suspended, actual source access can be closed, for instance.
470 Suspended = 2,
471}
472
473/// Check is equal to `sys` equivalent
474#[test]
475fn source_state_compare_capi() {
476 assert_eq!(std::mem::size_of::<SourceState>(), std::mem::size_of::<capi::pa_source_state_t>());
477 assert_eq!(std::mem::align_of::<SourceState>(), std::mem::align_of::<capi::pa_source_state_t>());
478
479 // Check order and value of variants match
480 // No point checking conversions in both directions since both are a transmute
481 assert_eq!(SourceState::Invalid, SourceState::from(capi::pa_source_state_t::Invalid));
482 assert_eq!(SourceState::Running, SourceState::from(capi::pa_source_state_t::Running));
483 assert_eq!(SourceState::Idle, SourceState::from(capi::pa_source_state_t::Idle));
484 assert_eq!(SourceState::Suspended, SourceState::from(capi::pa_source_state_t::Suspended));
485}
486
487impl From<SourceState> for capi::pa_source_state_t {
488 #[inline]
489 fn from(s: SourceState) -> Self {
490 unsafe { std::mem::transmute(s) }
491 }
492}
493impl From<capi::pa_source_state_t> for SourceState {
494 #[inline]
495 fn from(s: capi::pa_source_state_t) -> Self {
496 unsafe { std::mem::transmute(s) }
497 }
498}
499
500impl SourceState {
501 /// Checks if source is recording: running or idle.
502 #[inline]
503 pub fn is_opened(self) -> bool {
504 self == SourceState::Running || self == SourceState::Idle
505 }
506
507 /// Checks if source is running.
508 #[inline]
509 pub fn is_running(self) -> bool {
510 self == SourceState::Running
511 }
512}