libpulse_binding/
sample.rs1use std::ffi::{CStr, CString};
67use std::borrow::Cow;
68use num_derive::{FromPrimitive, ToPrimitive};
69use crate::time::MicroSeconds;
70
71#[repr(C)]
77#[derive(Debug, Copy, Clone, PartialEq, Eq)]
78#[derive(FromPrimitive, ToPrimitive)]
79#[allow(non_camel_case_types)]
80pub enum Format {
81 U8,
85 ALaw,
87 ULaw,
89 S16le,
91 S16be,
93 F32le,
95 F32be,
97 S32le,
99 S32be,
101 S24le,
103 S24be,
105 S24_32le,
107 S24_32be,
109
110 Invalid = -1,
112}
113
114#[test]
116fn format_compare_capi() {
117 assert_eq!(std::mem::size_of::<Format>(), std::mem::size_of::<capi::pa_sample_format_t>());
118 assert_eq!(std::mem::align_of::<Format>(), std::mem::align_of::<capi::pa_sample_format_t>());
119
120 assert_eq!(Format::U8, Format::from(capi::pa_sample_format_t::U8));
123 assert_eq!(Format::ALaw, Format::from(capi::pa_sample_format_t::ALaw));
124 assert_eq!(Format::ULaw, Format::from(capi::pa_sample_format_t::ULaw));
125 assert_eq!(Format::S16le, Format::from(capi::pa_sample_format_t::S16le));
126 assert_eq!(Format::S16be, Format::from(capi::pa_sample_format_t::S16be));
127 assert_eq!(Format::F32le, Format::from(capi::pa_sample_format_t::F32le));
128 assert_eq!(Format::F32be, Format::from(capi::pa_sample_format_t::F32be));
129 assert_eq!(Format::S32le, Format::from(capi::pa_sample_format_t::S32le));
130 assert_eq!(Format::S32be, Format::from(capi::pa_sample_format_t::S32be));
131 assert_eq!(Format::S24le, Format::from(capi::pa_sample_format_t::S24le));
132 assert_eq!(Format::S24be, Format::from(capi::pa_sample_format_t::S24be));
133 assert_eq!(Format::S24_32le, Format::from(capi::pa_sample_format_t::S24_32le));
134 assert_eq!(Format::S24_32be, Format::from(capi::pa_sample_format_t::S24_32be));
135 assert_eq!(Format::Invalid, Format::from(capi::pa_sample_format_t::Invalid));
136}
137
138impl From<Format> for capi::pa_sample_format_t {
139 #[inline]
140 fn from(f: Format) -> Self {
141 unsafe { std::mem::transmute(f) }
142 }
143}
144impl From<capi::pa_sample_format_t> for Format {
145 #[inline]
146 fn from(f: capi::pa_sample_format_t) -> Self {
147 unsafe { std::mem::transmute(f) }
148 }
149}
150
151impl Default for Format {
152 #[inline(always)]
153 fn default() -> Self {
154 Format::Invalid
155 }
156}
157
158#[allow(deprecated)]
162#[deprecated(since = "2.20.0", note = "use the `FLOAT32NE` associated constant on `Format` instead")]
163pub const SAMPLE_FLOAT32: Format = SAMPLE_FLOAT32NE;
164
165#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
167pub const SAMPLE_S16NE: Format = self::ei_formats::SAMPLE_S16NE;
168#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
170pub const SAMPLE_FLOAT32NE: Format = self::ei_formats::SAMPLE_FLOAT32NE;
171#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
173pub const SAMPLE_S32NE: Format = self::ei_formats::SAMPLE_S32NE;
174#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
176pub const SAMPLE_S24NE: Format = self::ei_formats::SAMPLE_S24NE;
177#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
179pub const SAMPLE_S24_32NE: Format = self::ei_formats::SAMPLE_S24_32NE;
180
181#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
183pub const SAMPLE_S16RE: Format = self::ei_formats::SAMPLE_S16RE;
184#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
186pub const SAMPLE_FLOAT32RE: Format = self::ei_formats::SAMPLE_FLOAT32RE;
187#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
189pub const SAMPLE_S32RE: Format = self::ei_formats::SAMPLE_S32RE;
190#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
192pub const SAMPLE_S24RE: Format = self::ei_formats::SAMPLE_S24RE;
193#[deprecated(since = "2.20.0", note = "use the associated constant on `Format` instead")]
195pub const SAMPLE_S24_32RE: Format = self::ei_formats::SAMPLE_S24_32RE;
196
197#[cfg(target_endian = "big")]
199mod ei_formats {
200 use super::Format;
201
202 pub const SAMPLE_S16NE: Format = Format::S16be;
203 pub const SAMPLE_FLOAT32NE: Format = Format::F32be;
204 pub const SAMPLE_S32NE: Format = Format::S32be;
205 pub const SAMPLE_S24NE: Format = Format::S24be;
206 pub const SAMPLE_S24_32NE: Format = Format::S24_32be;
207
208 pub const SAMPLE_S16RE: Format = Format::S16le;
209 pub const SAMPLE_FLOAT32RE: Format = Format::F32le;
210 pub const SAMPLE_S32RE: Format = Format::S32le;
211 pub const SAMPLE_S24RE: Format = Format::S24le;
212 pub const SAMPLE_S24_32RE: Format = Format::S24_32le;
213}
214
215#[cfg(target_endian = "little")]
217mod ei_formats {
218 use super::Format;
219
220 pub const SAMPLE_S16NE: Format = Format::S16le;
221 pub const SAMPLE_FLOAT32NE: Format = Format::F32le;
222 pub const SAMPLE_S32NE: Format = Format::S32le;
223 pub const SAMPLE_S24NE: Format = Format::S24le;
224 pub const SAMPLE_S24_32NE: Format = Format::S24_32le;
225
226 pub const SAMPLE_S16RE: Format = Format::S16be;
227 pub const SAMPLE_FLOAT32RE: Format = Format::F32be;
228 pub const SAMPLE_S32RE: Format = Format::S32be;
229 pub const SAMPLE_S24RE: Format = Format::S24be;
230 pub const SAMPLE_S24_32RE: Format = Format::S24_32be;
231}
232
233#[repr(C)]
235#[derive(Debug, Copy, Clone, Eq)]
236pub struct Spec {
237 pub format: Format,
240 pub rate: u32,
242 pub channels: u8,
244}
245
246#[test]
248fn spec_compare_capi() {
249 assert_eq!(std::mem::size_of::<Spec>(), std::mem::size_of::<capi::pa_sample_spec>());
250 assert_eq!(std::mem::align_of::<Spec>(), std::mem::align_of::<capi::pa_sample_spec>());
251}
252
253impl AsRef<capi::pa_sample_spec> for Spec {
254 #[inline]
255 fn as_ref(&self) -> &capi::pa_sample_spec {
256 unsafe { &*(self as *const Self as *const capi::pa_sample_spec) }
257 }
258}
259impl AsMut<capi::pa_sample_spec> for Spec {
260 #[inline]
261 fn as_mut(&mut self) -> &mut capi::pa_sample_spec {
262 unsafe { &mut *(self as *mut Self as *mut capi::pa_sample_spec) }
263 }
264}
265impl AsRef<Spec> for capi::pa_sample_spec {
266 #[inline]
267 fn as_ref(&self) -> &Spec {
268 unsafe { &*(self as *const Self as *const Spec) }
269 }
270}
271
272impl From<capi::pa_sample_spec> for Spec {
273 #[inline]
274 fn from(s: capi::pa_sample_spec) -> Self {
275 unsafe { std::mem::transmute(s) }
276 }
277}
278
279impl PartialEq for Spec {
280 #[inline]
281 fn eq(&self, other: &Self) -> bool {
282 unsafe { capi::pa_sample_spec_equal(self.as_ref(), other.as_ref()) != 0 }
283 }
284}
285
286impl Spec {
287 pub const CHANNELS_MAX: u8 = capi::PA_CHANNELS_MAX;
289 pub const RATE_MAX: u32 = capi::PA_RATE_MAX;
291
292 #[inline]
297 pub fn init(&mut self) {
298 unsafe { capi::pa_sample_spec_init(self.as_mut()); }
299 }
300
301 #[inline]
303 pub fn is_valid(&self) -> bool {
304 unsafe { capi::pa_sample_spec_valid(self.as_ref()) != 0 }
305 }
306
307 #[inline]
311 pub fn format_is_valid(&self) -> bool {
312 unsafe { capi::pa_sample_format_valid(self.format as u32) != 0 }
313 }
314
315 #[inline]
317 pub fn rate_is_valid(&self) -> bool {
318 unsafe { capi::pa_sample_rate_valid(self.rate) != 0 }
319 }
320
321 #[inline]
323 pub fn channels_are_valid(&self) -> bool {
324 unsafe { capi::pa_channels_valid(self.channels) != 0 }
325 }
326
327 #[inline]
330 pub fn bytes_per_second(&self) -> usize {
331 unsafe { capi::pa_bytes_per_second(self.as_ref()) }
332 }
333
334 #[inline]
336 pub fn frame_size(&self) -> usize {
337 unsafe { capi::pa_frame_size(self.as_ref()) }
338 }
339
340 #[inline]
342 pub fn sample_size(&self) -> usize {
343 unsafe { capi::pa_sample_size(self.as_ref()) }
344 }
345
346 #[inline]
352 pub fn bytes_to_usec(&self, length: u64) -> MicroSeconds {
353 MicroSeconds(unsafe { capi::pa_bytes_to_usec(length, self.as_ref()) })
354 }
355
356 #[inline]
362 pub fn usec_to_bytes(&self, t: MicroSeconds) -> usize {
363 unsafe { capi::pa_usec_to_bytes(t.0, self.as_ref()) }
364 }
365
366 pub fn print(&self) -> String {
368 const PRINT_MAX: usize = capi::PA_SAMPLE_SPEC_SNPRINT_MAX;
369 let mut tmp = Vec::with_capacity(PRINT_MAX);
370 unsafe {
371 capi::pa_sample_spec_snprint(tmp.as_mut_ptr(), PRINT_MAX, self.as_ref());
372 CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
373 }
374 }
375}
376
377pub fn bytes_print(bytes: u32) -> String {
379 const PRINT_MAX: usize = capi::PA_BYTES_SNPRINT_MAX;
380 let mut tmp = Vec::with_capacity(PRINT_MAX);
381 unsafe {
382 capi::pa_bytes_snprint(tmp.as_mut_ptr(), PRINT_MAX, bytes);
383 CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
384 }
385}
386
387impl Format {
388 pub const S16NE: Self = self::ei_formats::SAMPLE_S16NE;
390 pub const FLOAT32NE: Self = self::ei_formats::SAMPLE_FLOAT32NE;
392 pub const S32NE: Self = self::ei_formats::SAMPLE_S32NE;
394 pub const S24NE: Self = self::ei_formats::SAMPLE_S24NE;
396 pub const S24_32NE: Self = self::ei_formats::SAMPLE_S24_32NE;
398
399 pub const S16RE: Self = self::ei_formats::SAMPLE_S16RE;
401 pub const FLOAT32RE: Self = self::ei_formats::SAMPLE_FLOAT32RE;
403 pub const S32RE: Self = self::ei_formats::SAMPLE_S32RE;
405 pub const S24RE: Self = self::ei_formats::SAMPLE_S24RE;
407 pub const S24_32RE: Self = self::ei_formats::SAMPLE_S24_32RE;
409
410 #[inline]
412 pub fn size(&self) -> usize {
413 unsafe { capi::pa_sample_size_of_format((*self).into()) }
414 }
415
416 pub fn to_string(&self) -> Option<Cow<'static, str>> {
418 let ptr = unsafe { capi::pa_sample_format_to_string((*self).into()) };
419 match ptr.is_null() {
420 false => Some(unsafe { CStr::from_ptr(ptr).to_string_lossy() }),
421 true => None,
422 }
423 }
424
425 pub fn parse(format: &str) -> Self {
427 let c_format = CString::new(format).unwrap();
430 unsafe { capi::pa_parse_sample_format(c_format.as_ptr()).into() }
431 }
432
433 pub fn is_le(&self) -> Option<bool> {
438 match unsafe { capi::pa_sample_format_is_le((*self).into()) } {
439 0 => Some(false),
440 1 => Some(true),
441 _ => None,
442 }
443 }
444
445 pub fn is_be(&self) -> Option<bool> {
450 match unsafe { capi::pa_sample_format_is_be((*self).into()) } {
451 0 => Some(false),
452 1 => Some(true),
453 _ => None,
454 }
455 }
456
457 #[inline]
462 pub fn is_ne(&self) -> Option<bool> {
463 #[cfg(target_endian = "big")]
464 { Format::is_be(self) }
465 #[cfg(target_endian = "little")]
466 { Format::is_le(self) }
467 }
468
469 #[inline]
474 pub fn is_re(&self) -> Option<bool> {
475 self.is_ne().and_then(|b| Some(!b))
476 }
477}