alsa-0.9.1/.cargo_vcs_info.json0000644000000001360000000000100117630ustar { "git": { "sha1": "3e3195cada635a73685066ec97315cfebd6e3bca" }, "path_in_vcs": "" }alsa-0.9.1/Cargo.lock0000644000000022770000000000100077460ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "alsa" version = "0.9.1" dependencies = [ "alsa-sys", "bitflags", "cfg-if", "libc", ] [[package]] name = "alsa-sys" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" dependencies = [ "libc", "pkg-config", ] [[package]] name = "bitflags" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "libc" version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "pkg-config" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" alsa-0.9.1/Cargo.toml0000644000000023700000000000100077630ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "alsa" version = "0.9.1" authors = ["David Henningsson "] include = [ "README.md", "LICENSE-*", "Cargo.toml", "src/", ] description = "Thin but safe wrappers for ALSA (Linux sound API)" documentation = "http://docs.rs/alsa" readme = "README.md" keywords = [ "ALSA", "audio", "sound", ] categories = [ "multimedia::audio", "api-bindings", ] license = "Apache-2.0/MIT" repository = "https://github.com/diwic/alsa-rs" [dependencies.alsa-sys] version = "0.3.1" [dependencies.bitflags] version = "2.4.0" [dependencies.cfg-if] version = "1.0" [dependencies.libc] version = "0.2" [badges.is-it-maintained-issue-resolution] repository = "diwic/alsa-rs" [badges.is-it-maintained-open-issues] repository = "diwic/alsa-rs" alsa-0.9.1/Cargo.toml.orig000064400000000000000000000012531046102023000134430ustar 00000000000000[package] name = "alsa" version = "0.9.1" authors = ["David Henningsson "] description = "Thin but safe wrappers for ALSA (Linux sound API)" repository = "https://github.com/diwic/alsa-rs" documentation = "http://docs.rs/alsa" keywords = ["ALSA", "audio", "sound"] license = "Apache-2.0/MIT" categories = ["multimedia::audio", "api-bindings"] readme = "README.md" edition = "2021" include = ["README.md", "LICENSE-*", "Cargo.toml", "src/"] [dependencies] libc = "0.2" alsa-sys = "0.3.1" bitflags = "2.4.0" cfg-if = "1.0" [badges] is-it-maintained-issue-resolution = { repository = "diwic/alsa-rs" } is-it-maintained-open-issues = { repository = "diwic/alsa-rs" } alsa-0.9.1/LICENSE-APACHE000064400000000000000000000236761046102023000125150ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS alsa-0.9.1/LICENSE-MIT000064400000000000000000000021201046102023000122020ustar 00000000000000MIT License Copyright (c) 2015-2021 David Henningsson, and other contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. alsa-0.9.1/README.md000064400000000000000000000042621046102023000120360ustar 00000000000000ALSA bindings for Rust ======================= Thin but safe wrappers for [ALSA](https://alsa-project.org), the most common API for accessing audio devices on Linux. [![crates.io](https://img.shields.io/crates/v/alsa.svg)](https://crates.io/crates/alsa) [![API documentation](https://docs.rs/alsa/badge.svg)](https://docs.rs/alsa) [![license](https://img.shields.io/crates/l/alsa.svg)](https://crates.io/crates/alsa) The ALSA API is rather big, so everything is not covered yet, but expect the following to work: * Audio Playback (example in `pcm` module docs) * Audio Recording * Mixer controls * HCtl API (jack detection example in `hctl` module docs) * Raw midi * Midi sequencer (most of it) * Ctl API * Device name hints (example in `device_name` module docs) * Enumerations of all of the above * Poll and/or wait for all of the above The following is not yet implemented (mostly because nobody asked for them) : * Separate timer API (snd_timer_*) * Config API (snd_config_*) * Plug-in API Quickstart guide / API design: * Most functions map 1-to-1 to alsa-lib functions, e g, `ctl::CardInfo::get_id()` is a wrapper around `snd_ctl_card_info_get_id` and the [alsa-lib documentation](https://www.alsa-project.org/alsa-doc/alsa-lib/) can be consulted for additional information. * Structs are RAII and closed/freed on drop, e g, when a `PCM` struct is dropped, `snd_pcm_close` is called. * To read and write buffers, call the `io_*` methods. It will return a separate struct from which you can read or write, and which can also be used for mmap (if supported by the driver). * Error handling - most alsa-lib functions can return errors, so the return value from these is a `Result`. * Enumeration of cards, devices etc is done through structs implementing `Iterator`. * Many structs implement `poll::Descriptors`, to combine with your favorite async framework. Or just use `wait` if you don't need non-blocking functionality. Notes: * To run the tests successfully, there must be a "default" sound card configured. This is usually not a problem when running on normal hardware, but some CI systems, docker images etc, might not have that configured by default. alsa-0.9.1/src/card.rs000064400000000000000000000030151046102023000126200ustar 00000000000000//! Sound card enumeration use libc::{c_int, c_char}; use super::error::*; use crate::alsa; use std::ffi::CStr; /// An ALSA sound card, uniquely identified by its index. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Card(c_int); /// Iterate over existing sound cards. pub struct Iter(c_int); impl Iter { pub fn new() -> Iter { Iter(-1) } } impl Iterator for Iter { type Item = Result; fn next(&mut self) -> Option> { match acheck!(snd_card_next(&mut self.0)) { Ok(_) if self.0 == -1 => None, Ok(_) => Some(Ok(Card(self.0))), Err(e) => Some(Err(e)), } } } impl Card { pub fn new(index: c_int) -> Card { Card(index) } pub fn from_str(s: &CStr) -> Result { acheck!(snd_card_get_index(s.as_ptr())).map(Card) } pub fn get_name(&self) -> Result { let mut c: *mut c_char = ::std::ptr::null_mut(); acheck!(snd_card_get_name(self.0, &mut c)) .and_then(|_| from_alloc("snd_card_get_name", c)) } pub fn get_longname(&self) -> Result { let mut c: *mut c_char = ::std::ptr::null_mut(); acheck!(snd_card_get_longname(self.0, &mut c)) .and_then(|_| from_alloc("snd_card_get_longname", c)) } pub fn get_index(&self) -> c_int { self.0 } } #[test] fn print_cards() { for a in Iter::new().map(|a| a.unwrap()) { println!("Card #{}: {} ({})", a.get_index(), a.get_name().unwrap(), a.get_longname().unwrap()) } } alsa-0.9.1/src/chmap.rs000064400000000000000000000116021046102023000130000ustar 00000000000000use crate::alsa; use std::{fmt, mem, slice}; use super::error::*; alsa_enum!( /// [SND_CHMAP_TYPE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants ChmapType, ALL_CHMAP_TYPES[4], None = SND_CHMAP_TYPE_NONE, Fixed = SND_CHMAP_TYPE_FIXED, Var = SND_CHMAP_TYPE_VAR, Paired = SND_CHMAP_TYPE_PAIRED, ); alsa_enum!( /// [SND_CHMAP_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants ChmapPosition, ALL_CHMAP_POSITIONS[33], Unknown = SND_CHMAP_UNKNOWN, NA = SND_CHMAP_NA, Mono = SND_CHMAP_MONO, FL = SND_CHMAP_FL, FR = SND_CHMAP_FR, RL = SND_CHMAP_RL, SR = SND_CHMAP_SR, RC = SND_CHMAP_RC, FLC = SND_CHMAP_FLC, FRC = SND_CHMAP_FRC, RLC = SND_CHMAP_RLC, RRC = SND_CHMAP_RRC, FLW = SND_CHMAP_FLW, FRW = SND_CHMAP_FRW, FLH = SND_CHMAP_FLH, FCH = SND_CHMAP_FCH, FRH = SND_CHMAP_FRH, TC = SND_CHMAP_TC, TFL = SND_CHMAP_TFL, TFR = SND_CHMAP_TFR, TFC = SND_CHMAP_TFC, TRL = SND_CHMAP_TRL, TRR = SND_CHMAP_TRR, TRC = SND_CHMAP_TRC, TFLC = SND_CHMAP_TFLC, TFRC = SND_CHMAP_TFRC, TSL = SND_CHMAP_TSL, TSR = SND_CHMAP_TSR, LLFE = SND_CHMAP_LLFE, RLFE = SND_CHMAP_RLFE, BC = SND_CHMAP_BC, BLC = SND_CHMAP_BLC, BRC = SND_CHMAP_BRC, ); impl fmt::Display for ChmapPosition { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = unsafe { alsa::snd_pcm_chmap_long_name(*self as libc::c_uint) }; let s = from_const("snd_pcm_chmap_long_name", s)?; write!(f, "{}", s) } } /// [snd_pcm_chmap_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) wrapper pub struct Chmap(*mut alsa::snd_pcm_chmap_t, bool); impl Drop for Chmap { fn drop(&mut self) { if self.1 { unsafe { libc::free(self.0 as *mut libc::c_void) }}} } impl Chmap { fn set_channels(&mut self, c: libc::c_uint) { unsafe { (*self.0) .channels = c }} fn as_slice_mut(&mut self) -> &mut [libc::c_uint] { unsafe { slice::from_raw_parts_mut((*self.0).pos.as_mut_ptr(), (*self.0).channels as usize) } } fn as_slice(&self) -> &[libc::c_uint] { unsafe { slice::from_raw_parts((*self.0).pos.as_ptr(), (*self.0).channels as usize) } } } impl fmt::Display for Chmap { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut buf: Vec = vec![0; 512]; acheck!(snd_pcm_chmap_print(self.0, buf.len() as libc::size_t, buf.as_mut_ptr()))?; let s = from_const("snd_pcm_chmap_print", buf.as_mut_ptr())?; write!(f, "{}", s) } } impl<'a> From<&'a [ChmapPosition]> for Chmap { fn from(a: &'a [ChmapPosition]) -> Chmap { let p = unsafe { libc::malloc((mem::size_of::() + mem::size_of::() * a.len()) as libc::size_t) }; if p.is_null() { panic!("Out of memory") } let mut r = Chmap(p as *mut alsa::snd_pcm_chmap_t, true); r.set_channels(a.len() as libc::c_uint); for (i,v) in r.as_slice_mut().iter_mut().enumerate() { *v = a[i] as libc::c_uint } r } } impl<'a> From<&'a Chmap> for Vec { fn from(a: &'a Chmap) -> Vec { a.as_slice().iter().map(|&v| ChmapPosition::from_c_int(v as libc::c_int, "").unwrap()).collect() } } pub fn chmap_new(a: *mut alsa::snd_pcm_chmap_t) -> Chmap { Chmap(a, true) } pub fn chmap_handle(a: &Chmap) -> *mut alsa::snd_pcm_chmap_t { a.0 } /// Iterator over available channel maps - see [snd_pcm_chmap_query_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) pub struct ChmapsQuery(*mut *mut alsa::snd_pcm_chmap_query_t, isize); impl Drop for ChmapsQuery { fn drop(&mut self) { unsafe { alsa::snd_pcm_free_chmaps(self.0) }} } pub fn chmaps_query_new(a: *mut *mut alsa::snd_pcm_chmap_query_t) -> ChmapsQuery { ChmapsQuery(a, 0) } impl Iterator for ChmapsQuery { type Item = (ChmapType, Chmap); fn next(&mut self) -> Option { if self.0.is_null() { return None; } let p = unsafe { *self.0.offset(self.1) }; if p.is_null() { return None; } self.1 += 1; let t = ChmapType::from_c_int(unsafe { (*p).type_ } as libc::c_int, "snd_pcm_query_chmaps").unwrap(); let m = Chmap(unsafe { &mut (*p).map }, false); Some((t, m)) } } #[test] fn chmap_for_first_pcm() { use super::*; use std::ffi::CString; use crate::device_name::HintIter; let i = HintIter::new(None, &*CString::new("pcm").unwrap()).unwrap(); for p in i.map(|n| n.name.unwrap()) { println!("Chmaps for {:?}:", p); match PCM::open(&CString::new(p).unwrap(), Direction::Playback, false) { Ok(a) => for c in a.query_chmaps() { println!(" {:?}, {}", c.0, c.1); }, Err(a) => println!(" {}", a) // It's okay to have entries in the name hint array that can't be opened } } } alsa-0.9.1/src/ctl_int.rs000064400000000000000000000472011046102023000133500ustar 00000000000000 use crate::alsa; use super::pcm::Info; use std::ffi::{CStr, CString}; use super::Direction; use super::error::*; use super::mixer::MilliBel; use super::Round; use std::{ptr, mem, fmt, cmp}; use crate::{Card, poll}; use std::cell::UnsafeCell; use libc::{c_uint, c_void, size_t, c_long, c_int, pollfd, c_short}; /// We prefer not to allocate for every ElemId, ElemInfo or ElemValue. /// But we don't know if these will increase in the future or on other platforms. /// Unfortunately, Rust does not support alloca, so hard-code the sizes for now. const ELEM_ID_SIZE: usize = 64; // const ELEM_VALUE_SIZE: usize = 1224; // const ELEM_INFO_SIZE: usize = 272; /// [snd_ctl_pcm_next_device](https://www.alsa-project.org/alsa-doc/alsa-lib/control_8c.html#accbb0be6e5ca7361ffec0ea304ed1b05) wrapper. /// Iterate over devices of a card. pub struct DeviceIter<'a>(&'a Ctl, c_int); impl<'a> DeviceIter<'a>{ pub fn new(ctl: &'a Ctl) -> DeviceIter { DeviceIter(ctl, -1) } } impl<'a> Iterator for DeviceIter<'a> { type Item = c_int; fn next(&mut self) -> Option { match acheck!(snd_ctl_pcm_next_device(self.0.0, &mut self.1)) { Ok(_) if self.1 == -1 => None, Ok(_) => Some(self.1), Err(_) => None, } } } /// [snd_ctl_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper pub struct Ctl(*mut alsa::snd_ctl_t); unsafe impl Send for Ctl {} impl Ctl { /// Wrapper around open that takes a &str instead of a &CStr pub fn new(c: &str, nonblock: bool) -> Result { Self::open(&CString::new(c).unwrap(), nonblock) } /// Open does not support async mode (it's not very Rustic anyway) pub fn open(c: &CStr, nonblock: bool) -> Result { let mut r = ptr::null_mut(); let flags = if nonblock { 1 } else { 0 }; // FIXME: alsa::SND_CTL_NONBLOCK does not exist in alsa-sys acheck!(snd_ctl_open(&mut r, c.as_ptr(), flags)).map(|_| Ctl(r)) } pub fn from_card(c: &Card, nonblock: bool) -> Result { let s = format!("hw:{}", c.get_index()); Ctl::open(&CString::new(s).unwrap(), nonblock) } pub fn card_info(&self) -> Result { CardInfo::new().and_then(|c| acheck!(snd_ctl_card_info(self.0, c.0)).map(|_| c)) } pub fn wait(&self, timeout_ms: Option) -> Result { acheck!(snd_ctl_wait(self.0, timeout_ms.map(|x| x as c_int).unwrap_or(-1))).map(|i| i == 1) } pub fn get_db_range(&self, id: &ElemId) -> Result<(MilliBel, MilliBel)> { let mut min: c_long = 0; let mut max: c_long = 0; acheck!(snd_ctl_get_dB_range(self.0, elem_id_ptr(id), &mut min, &mut max)) .map(|_| (MilliBel(min as i64), MilliBel(max as i64))) } pub fn convert_to_db(&self, id: &ElemId, volume: i64) -> Result { let mut m: c_long = 0; acheck!(snd_ctl_convert_to_dB(self.0, elem_id_ptr(id), volume as c_long, &mut m)) .map(|_| (MilliBel(m as i64))) } pub fn convert_from_db(&self, id: &ElemId, mb: MilliBel, dir: Round) -> Result { let mut m: c_long = 0; acheck!(snd_ctl_convert_from_dB(self.0, elem_id_ptr(id), mb.0 as c_long, &mut m, dir as c_int)) .map(|_| m as i64) } pub fn elem_read(&self, val: &mut ElemValue) -> Result<()> { acheck!(snd_ctl_elem_read(self.0, elem_value_ptr(val))).map(|_| ()) } pub fn elem_write(&self, val: &ElemValue) -> Result<()> { acheck!(snd_ctl_elem_write(self.0, elem_value_ptr(val))).map(|_| ()) } pub fn elem_lock(&self, id: &ElemId) -> Result { acheck!(snd_ctl_elem_lock(self.0, elem_id_ptr(id))) } pub fn elem_unlock(&self, id: &ElemId) -> Result { acheck!(snd_ctl_elem_unlock(self.0, elem_id_ptr(id))) } /// Note: According to alsa-lib documentation, you're also supposed to have functionality for /// returning whether or not you are subscribed. This does not work in practice, so I'm not /// including that here. pub fn subscribe_events(&self, subscribe: bool) -> Result<()> { acheck!(snd_ctl_subscribe_events(self.0, if subscribe { 1 } else { 0 })).map(|_| ()) } pub fn read(&self) -> Result> { let e = event_new()?; acheck!(snd_ctl_read(self.0, e.0)).map(|r| if r == 1 { Some(e) } else { None }) } pub fn pcm_info(&self, device: u32, subdevice: u32, direction: Direction) -> Result { Info::new().and_then(|mut info| { info.set_device(device); info.set_subdevice(subdevice); info.set_stream(direction); acheck!(snd_ctl_pcm_info(self.0, info.0)).map(|_| info ) }) } } impl Drop for Ctl { fn drop(&mut self) { unsafe { alsa::snd_ctl_close(self.0) }; } } impl poll::Descriptors for Ctl { fn count(&self) -> usize { unsafe { alsa::snd_ctl_poll_descriptors_count(self.0) as usize } } fn fill(&self, p: &mut [pollfd]) -> Result { let z = unsafe { alsa::snd_ctl_poll_descriptors(self.0, p.as_mut_ptr(), p.len() as c_uint) }; from_code("snd_ctl_poll_descriptors", z).map(|_| z as usize) } fn revents(&self, p: &[pollfd]) -> Result { let mut r = 0; let z = unsafe { alsa::snd_ctl_poll_descriptors_revents(self.0, p.as_ptr() as *mut pollfd, p.len() as c_uint, &mut r) }; from_code("snd_ctl_poll_descriptors_revents", z).map(|_| poll::Flags::from_bits_truncate(r as c_short)) } } pub fn ctl_ptr(a: &Ctl) -> *mut alsa::snd_ctl_t { a.0 } /// [snd_ctl_card_info_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper pub struct CardInfo(*mut alsa::snd_ctl_card_info_t); impl Drop for CardInfo { fn drop(&mut self) { unsafe { alsa::snd_ctl_card_info_free(self.0) }} } impl CardInfo { fn new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_ctl_card_info_malloc(&mut p)).map(|_| CardInfo(p)) } pub fn get_id(&self) -> Result<&str> { from_const("snd_ctl_card_info_get_id", unsafe { alsa::snd_ctl_card_info_get_id(self.0) })} pub fn get_driver(&self) -> Result<&str> { from_const("snd_ctl_card_info_get_driver", unsafe { alsa::snd_ctl_card_info_get_driver(self.0) })} pub fn get_components(&self) -> Result<&str> { from_const("snd_ctl_card_info_get_components", unsafe { alsa::snd_ctl_card_info_get_components(self.0) })} pub fn get_longname(&self) -> Result<&str> { from_const("snd_ctl_card_info_get_longname", unsafe { alsa::snd_ctl_card_info_get_longname(self.0) })} pub fn get_name(&self) -> Result<&str> { from_const("snd_ctl_card_info_get_name", unsafe { alsa::snd_ctl_card_info_get_name(self.0) })} pub fn get_mixername(&self) -> Result<&str> { from_const("snd_ctl_card_info_get_mixername", unsafe { alsa::snd_ctl_card_info_get_mixername(self.0) })} pub fn get_card(&self) -> Card { Card::new(unsafe { alsa::snd_ctl_card_info_get_card(self.0) })} } alsa_enum!( /// [SND_CTL_ELEM_IFACE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) constants ElemIface, ALL_ELEMIFACE[7], Card = SND_CTL_ELEM_IFACE_CARD, Hwdep = SND_CTL_ELEM_IFACE_HWDEP, Mixer = SND_CTL_ELEM_IFACE_MIXER, PCM = SND_CTL_ELEM_IFACE_PCM, Rawmidi = SND_CTL_ELEM_IFACE_RAWMIDI, Timer = SND_CTL_ELEM_IFACE_TIMER, Sequencer = SND_CTL_ELEM_IFACE_SEQUENCER, ); alsa_enum!( /// [SND_CTL_ELEM_TYPE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) constants ElemType, ALL_ELEMTYPE[7], None = SND_CTL_ELEM_TYPE_NONE, Boolean = SND_CTL_ELEM_TYPE_BOOLEAN, Integer = SND_CTL_ELEM_TYPE_INTEGER, Enumerated = SND_CTL_ELEM_TYPE_ENUMERATED, Bytes = SND_CTL_ELEM_TYPE_BYTES, IEC958 = SND_CTL_ELEM_TYPE_IEC958, Integer64 = SND_CTL_ELEM_TYPE_INTEGER64, ); /// [snd_ctl_elem_value_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper pub struct ElemValue { ptr: *mut alsa::snd_ctl_elem_value_t, etype: ElemType, count: u32, } impl Drop for ElemValue { fn drop(&mut self) { unsafe { alsa::snd_ctl_elem_value_free(self.ptr) }; } } pub fn elem_value_ptr(a: &ElemValue) -> *mut alsa::snd_ctl_elem_value_t { a.ptr } pub fn elem_value_new(t: ElemType, count: u32) -> Result { let mut p = ptr::null_mut(); acheck!(snd_ctl_elem_value_malloc(&mut p)) .map(|_| ElemValue { ptr: p, etype: t, count }) } impl ElemValue { pub fn set_id(&mut self, id: &ElemId) { unsafe { alsa::snd_ctl_elem_value_set_id(self.ptr, elem_id_ptr(id)) } } // Note: The get_bytes hands out a reference to inside the object. Therefore, we can't treat // the content as "cell"ed, but must take a "&mut self" (to make sure the reference // from get_bytes has been dropped when calling a set_* function). pub fn get_boolean(&self, idx: u32) -> Option { if self.etype != ElemType::Boolean || idx >= self.count { None } else { Some( unsafe { alsa::snd_ctl_elem_value_get_boolean(self.ptr, idx as c_uint) } != 0) } } pub fn set_boolean(&mut self, idx: u32, val: bool) -> Option<()> { if self.etype != ElemType::Boolean || idx >= self.count { None } else { unsafe { alsa::snd_ctl_elem_value_set_boolean(self.ptr, idx as c_uint, if val {1} else {0}) }; Some(()) } } pub fn get_integer(&self, idx: u32) -> Option { if self.etype != ElemType::Integer || idx >= self.count { None } else { Some( unsafe { alsa::snd_ctl_elem_value_get_integer(self.ptr, idx as c_uint) } as i32) } } pub fn set_integer(&mut self, idx: u32, val: i32) -> Option<()> { if self.etype != ElemType::Integer || idx >= self.count { None } else { unsafe { alsa::snd_ctl_elem_value_set_integer(self.ptr, idx as c_uint, val as c_long) }; Some(()) } } pub fn get_integer64(&self, idx: u32) -> Option { if self.etype != ElemType::Integer64 || idx >= self.count { None } else { Some( unsafe { alsa::snd_ctl_elem_value_get_integer64(self.ptr, idx as c_uint) } as i64) } } pub fn set_integer64(&mut self, idx: u32, val: i64) -> Option<()> { if self.etype != ElemType::Integer || idx >= self.count { None } else { unsafe { alsa::snd_ctl_elem_value_set_integer64(self.ptr, idx as c_uint, val) }; Some(()) } } pub fn get_enumerated(&self, idx: u32) -> Option { if self.etype != ElemType::Enumerated || idx >= self.count { None } else { Some( unsafe { alsa::snd_ctl_elem_value_get_enumerated(self.ptr, idx as c_uint) } as u32) } } pub fn set_enumerated(&mut self, idx: u32, val: u32) -> Option<()> { if self.etype != ElemType::Enumerated || idx >= self.count { None } else { unsafe { alsa::snd_ctl_elem_value_set_enumerated(self.ptr, idx as c_uint, val as c_uint) }; Some(()) } } pub fn get_byte(&self, idx: u32) -> Option { if self.etype != ElemType::Bytes || idx >= self.count { None } else { Some( unsafe { alsa::snd_ctl_elem_value_get_byte(self.ptr, idx as c_uint) } as u8) } } pub fn set_byte(&mut self, idx: u32, val: u8) -> Option<()> { if self.etype != ElemType::Bytes || idx >= self.count { None } else { unsafe { alsa::snd_ctl_elem_value_set_byte(self.ptr, idx as c_uint, val) }; Some(()) } } pub fn get_bytes(&self) -> Option<&[u8]> { if self.etype != ElemType::Bytes { None } else { Some( unsafe { ::std::slice::from_raw_parts( alsa::snd_ctl_elem_value_get_bytes(self.ptr) as *const u8, self.count as usize) } ) } } pub fn set_bytes(&mut self, val: &[u8]) -> Option<()> { if self.etype != ElemType::Bytes || val.len() != self.count as usize { None } // Note: the alsa-lib function definition is broken. First, the pointer is declared as mut even // though it's const, and second, there is a "value" missing between "elem" and "set_bytes". else { unsafe { alsa::snd_ctl_elem_set_bytes(self.ptr, val.as_ptr() as *mut c_void, val.len() as size_t) }; Some(()) } } /// Creates a new ElemValue. pub fn new(t: ElemType) -> Result { // See max length in include/uapi/sound/asound.h in linux kernel for these values let count = match t { ElemType::None => 1, ElemType::Boolean => 128, ElemType::Integer => 128, ElemType::Enumerated => 128, ElemType::Bytes => 512, ElemType::IEC958 => 1, ElemType::Integer64 => 64, }; // if count > maxcount { return Err(Error::new(Some("ElemValue::new - count too large".into()), 1)) } let ev = elem_value_new(t, count)?; unsafe { alsa::snd_ctl_elem_value_clear(elem_value_ptr(&ev)) }; Ok(ev) } } impl fmt::Debug for ElemValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::ElemType::*; write!(f, "ElemValue({:?}", self.etype)?; for a in 0..self.count { match self.etype { Boolean => write!(f, ",{:?}", self.get_boolean(a).unwrap()), Integer => write!(f, ",{:?}", self.get_integer(a).unwrap()), Integer64 => write!(f, ",{:?}", self.get_integer64(a).unwrap()), Enumerated => write!(f, ",{:?}", self.get_enumerated(a).unwrap()), Bytes => write!(f, ",{:?}", self.get_byte(a).unwrap()), _ => Ok(()), }?}; write!(f, ")") } } /// [snd_ctl_elem_info_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper pub struct ElemInfo(*mut alsa::snd_ctl_elem_info_t); pub fn elem_info_ptr(a: &ElemInfo) -> *mut alsa::snd_ctl_elem_info_t { a.0 } impl Drop for ElemInfo { fn drop(&mut self) { unsafe { alsa::snd_ctl_elem_info_free(self.0) }; } } pub fn elem_info_new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_ctl_elem_info_malloc(&mut p)).map(|_| ElemInfo(p)) } impl ElemInfo { pub fn get_type(&self) -> ElemType { ElemType::from_c_int( unsafe { alsa::snd_ctl_elem_info_get_type(self.0) } as c_int, "snd_ctl_elem_info_get_type").unwrap() } pub fn get_count(&self) -> u32 { unsafe { alsa::snd_ctl_elem_info_get_count(self.0) as u32 } } } // // Non-allocating version of ElemId // /// [snd_ctl_elem_id_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper pub struct ElemId(UnsafeCell<[u8; ELEM_ID_SIZE]>); pub fn elem_id_new() -> Result { assert!(unsafe { alsa::snd_ctl_elem_id_sizeof() } as usize <= ELEM_ID_SIZE); Ok(ElemId(UnsafeCell::new(unsafe { mem::zeroed() }))) } #[inline] pub fn elem_id_ptr(a: &ElemId) -> *mut alsa::snd_ctl_elem_id_t { a.0.get() as *mut _ as *mut alsa::snd_ctl_elem_id_t } unsafe impl Send for ElemId {} impl Clone for ElemId { fn clone(&self) -> Self { ElemId(UnsafeCell::new(unsafe { *self.0.get() })) } } // // Allocating version of ElemId // /* /// [snd_ctl_elem_id_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper pub struct ElemId(*mut alsa::snd_ctl_elem_id_t); impl Drop for ElemId { fn drop(&mut self) { unsafe { alsa::snd_ctl_elem_id_free(self.0) }; } } pub fn elem_id_new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_ctl_elem_id_malloc(&mut p)).map(|_| ElemId(p)) } pub fn elem_id_ptr(a: &ElemId) -> *mut alsa::snd_ctl_elem_id_t { a.0 } */ impl ElemId { pub fn get_name(&self) -> Result<&str> { from_const("snd_hctl_elem_id_get_name", unsafe { alsa::snd_ctl_elem_id_get_name(elem_id_ptr(self)) })} pub fn get_device(&self) -> u32 { unsafe { alsa::snd_ctl_elem_id_get_device(elem_id_ptr(self)) as u32 }} pub fn get_subdevice(&self) -> u32 { unsafe { alsa::snd_ctl_elem_id_get_subdevice(elem_id_ptr(self)) as u32 }} pub fn get_numid(&self) -> u32 { unsafe { alsa::snd_ctl_elem_id_get_numid(elem_id_ptr(self)) as u32 }} pub fn get_index(&self) -> u32 { unsafe { alsa::snd_ctl_elem_id_get_index(elem_id_ptr(self)) as u32 }} pub fn get_interface(&self) -> ElemIface { ElemIface::from_c_int( unsafe { alsa::snd_ctl_elem_id_get_interface(elem_id_ptr(self)) } as c_int, "snd_ctl_elem_id_get_interface").unwrap() } pub fn set_device(&mut self, v: u32) { unsafe { alsa::snd_ctl_elem_id_set_device(elem_id_ptr(self), v) }} pub fn set_subdevice(&mut self, v: u32) { unsafe { alsa::snd_ctl_elem_id_set_subdevice(elem_id_ptr(self), v) }} pub fn set_numid(&mut self, v: u32) { unsafe { alsa::snd_ctl_elem_id_set_numid(elem_id_ptr(self), v) }} pub fn set_index(&mut self, v: u32) { unsafe { alsa::snd_ctl_elem_id_set_index(elem_id_ptr(self), v) }} pub fn set_interface(&mut self, v: ElemIface) { unsafe { alsa::snd_ctl_elem_id_set_interface(elem_id_ptr(self), v as u32) }} pub fn set_name(&mut self, v: &CStr) { unsafe { alsa::snd_ctl_elem_id_set_name(elem_id_ptr(self), v.as_ptr()) }} /// Creates a new ElemId. /// /// To ensure safety (i e make sure we never have an invalid interface enum), we need to supply it to the "new" function. pub fn new(iface: ElemIface) -> Self { let mut r = elem_id_new().unwrap(); r.set_interface(iface); r } } impl cmp::Eq for ElemId {} impl cmp::PartialEq for ElemId { fn eq(&self, a: &ElemId) -> bool { self.get_numid() == a.get_numid() && self.get_interface() == a.get_interface() && self.get_index() == a.get_index() && self.get_device() == a.get_device() && self.get_subdevice() == a.get_subdevice() && self.get_name().ok() == a.get_name().ok() } } impl fmt::Debug for ElemId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let index = self.get_index(); let device = self.get_device(); let subdevice = self.get_subdevice(); write!(f, "ElemId(#{}, {:?}, {:?}", self.get_numid(), self.get_interface(), self.get_name())?; if index > 0 { write!(f, ", index={}", index)? }; if device > 0 || subdevice > 0 { write!(f, ", device={}", device)? }; if subdevice > 0 { write!(f, ", subdevice={}", device)? }; write!(f, ")") } } /// [snd_ctl_event_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper pub struct Event(*mut alsa::snd_ctl_event_t); impl Drop for Event { fn drop(&mut self) { unsafe { alsa::snd_ctl_event_free(self.0) }; } } pub fn event_new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_ctl_event_malloc(&mut p)).map(|_| Event(p)) } impl Event { pub fn get_mask(&self) -> EventMask { EventMask(unsafe { alsa::snd_ctl_event_elem_get_mask(self.0) as u32 })} pub fn get_id(&self) -> ElemId { let r = elem_id_new().unwrap(); unsafe { alsa::snd_ctl_event_elem_get_id(self.0, elem_id_ptr(&r)) }; r } } /// [SND_CTL_EVENT_MASK_XXX](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) bitmask #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] pub struct EventMask(pub u32); impl EventMask { pub fn remove(&self) -> bool { return self.0 & 0xffffffff == 0xffffffff } pub fn value(&self) -> bool { return (!self.remove()) && (self.0 & (1 << 0) != 0); } pub fn info(&self) -> bool { return (!self.remove()) && (self.0 & (1 << 1) != 0); } pub fn add(&self) -> bool { return (!self.remove()) && (self.0 & (1 << 2) != 0); } pub fn tlv(&self) -> bool { return (!self.remove()) && (self.0 & (1 << 3) != 0); } } #[test] fn print_sizeof() { let elemid = unsafe { alsa::snd_ctl_elem_id_sizeof() } as usize; let elemvalue = unsafe { alsa::snd_ctl_elem_value_sizeof() } as usize; let eleminfo = unsafe { alsa::snd_ctl_elem_info_sizeof() } as usize; assert!(elemid <= ELEM_ID_SIZE); // assert!(elemvalue <= ELEM_VALUE_SIZE); // assert!(eleminfo <= ELEM_INFO_SIZE); println!("Elem id: {}, Elem value: {}, Elem info: {}", elemid, elemvalue, eleminfo); } alsa-0.9.1/src/device_name.rs000064400000000000000000000054431046102023000141550ustar 00000000000000//! Enumerate devices in the alsa library configuration //! //! # Example //! Print all devices found in various categories. //! //! ``` //! use std::ffi::CString; //! use alsa::device_name::HintIter; //! //! for t in &["pcm", "ctl", "rawmidi", "timer", "seq", "hwdep"] { //! println!("{} devices:", t); //! let i = HintIter::new(None, &*CString::new(*t).unwrap()).unwrap(); //! for a in i { println!(" {:?}", a) } //! } //! ``` use std::ptr; use libc::{c_void, c_int}; use crate::alsa; use super::{Card, Direction}; use super::error::*; use std::ffi::{CStr, CString}; /// [snd_device_name_hint](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper pub struct HintIter(*mut *mut c_void, isize); impl Drop for HintIter { fn drop(&mut self) { unsafe { alsa::snd_device_name_free_hint(self.0); }} } impl HintIter { /// typical interfaces are: "pcm", "ctl", "rawmidi", "timer", "seq" and "hwdep". pub fn new(card: Option<&Card>, iface: &CStr) -> Result { let mut p = ptr::null_mut(); let cnr = card.map(|c| c.get_index()).unwrap_or(-1) as c_int; acheck!(snd_device_name_hint(cnr, iface.as_ptr(), &mut p)) .map(|_| HintIter(p, 0)) } /// A constructor variant that takes the interface as a Rust string slice. pub fn new_str(card: Option<&Card>, iface: &str) -> Result { HintIter::new(card, &CString::new(iface).unwrap()) } } impl Iterator for HintIter { type Item = Hint; fn next(&mut self) -> Option { if self.0.is_null() { return None; } let p = unsafe { *self.0.offset(self.1) }; if p.is_null() { return None; } self.1 += 1; Some(Hint::new(p)) } } /// [snd_device_name_get_hint](http://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html) wrapper #[derive(Debug, Clone)] pub struct Hint { pub name: Option, pub desc: Option, pub direction: Option, } impl Hint { fn get_str(p: *const c_void, name: &str) -> Option { let name = CString::new(name).unwrap(); let c = unsafe { alsa::snd_device_name_get_hint(p, name.as_ptr()) }; from_alloc("snd_device_name_get_hint", c).ok() } fn new(p: *const c_void) -> Hint { let d = Hint::get_str(p, "IOID").and_then(|x| match &*x { "Input" => Some(Direction::Capture), "Output" => Some(Direction::Playback), _ => None, }); Hint { name: Hint::get_str(p, "NAME"), desc: Hint::get_str(p, "DESC"), direction: d } } } #[test] fn print_hints() { for t in &["pcm", "ctl", "rawmidi", "timer", "seq", "hwdep"] { println!("{} devices:", t); let i = HintIter::new(None, &*CString::new(*t).unwrap()).unwrap(); for a in i { println!(" {:?}", a) } } } alsa-0.9.1/src/direct/asound_ioctl.rs000064400000000000000000006113351046102023000156560ustar 00000000000000/* automatically generated by rust-bindgen */ #[repr(C)] #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct __BindgenBitfieldUnit where Storage: AsRef<[u8]> + AsMut<[u8]>, { storage: Storage, align: [Align; 0], } impl __BindgenBitfieldUnit where Storage: AsRef<[u8]> + AsMut<[u8]>, { #[inline] pub fn new(storage: Storage) -> Self { Self { storage, align: [] } } #[inline] pub fn get_bit(&self, index: usize) -> bool { debug_assert!(index / 8 < self.storage.as_ref().len()); let byte_index = index / 8; let byte = self.storage.as_ref()[byte_index]; let bit_index = index % 8; let mask = 1 << bit_index; byte & mask == mask } #[inline] pub fn set_bit(&mut self, index: usize, val: bool) { debug_assert!(index / 8 < self.storage.as_ref().len()); let byte_index = index / 8; let byte = &mut self.storage.as_mut()[byte_index]; let bit_index = index % 8; let mask = 1 << bit_index; if val { *byte |= mask; } else { *byte &= !mask; } } #[inline] pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { debug_assert!(bit_width <= 64); debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); let mut val = 0; for i in 0..(bit_width as usize) { if self.get_bit(i + bit_offset) { val |= 1 << i; } } val } #[inline] pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { debug_assert!(bit_width <= 64); debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); for i in 0..(bit_width as usize) { let mask = 1 << i; let val_bit_is_set = val & mask == mask; self.set_bit(i + bit_offset, val_bit_is_set); } } } #[repr(C)] #[derive(Default)] pub struct __IncompleteArrayField(::std::marker::PhantomData); impl __IncompleteArrayField { #[inline] pub fn new() -> Self { __IncompleteArrayField(::std::marker::PhantomData) } #[inline] pub unsafe fn as_ptr(&self) -> *const T { ::std::mem::transmute(self) } #[inline] pub unsafe fn as_mut_ptr(&mut self) -> *mut T { ::std::mem::transmute(self) } #[inline] pub unsafe fn as_slice(&self, len: usize) -> &[T] { ::std::slice::from_raw_parts(self.as_ptr(), len) } #[inline] pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) } } impl ::std::fmt::Debug for __IncompleteArrayField { fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fmt.write_str("__IncompleteArrayField") } } impl ::std::clone::Clone for __IncompleteArrayField { #[inline] fn clone(&self) -> Self { Self::new() } } impl ::std::marker::Copy for __IncompleteArrayField {} pub const __BITS_PER_LONG: u32 = 64; pub const __FD_SETSIZE: u32 = 1024; pub const _FEATURES_H: u32 = 1; pub const _DEFAULT_SOURCE: u32 = 1; pub const __USE_ISOC11: u32 = 1; pub const __USE_ISOC99: u32 = 1; pub const __USE_ISOC95: u32 = 1; pub const __USE_POSIX_IMPLICITLY: u32 = 1; pub const _POSIX_SOURCE: u32 = 1; pub const _POSIX_C_SOURCE: u32 = 200809; pub const __USE_POSIX: u32 = 1; pub const __USE_POSIX2: u32 = 1; pub const __USE_POSIX199309: u32 = 1; pub const __USE_POSIX199506: u32 = 1; pub const __USE_XOPEN2K: u32 = 1; pub const __USE_XOPEN2K8: u32 = 1; pub const _ATFILE_SOURCE: u32 = 1; pub const __USE_MISC: u32 = 1; pub const __USE_ATFILE: u32 = 1; pub const __USE_FORTIFY_LEVEL: u32 = 0; pub const _STDC_PREDEF_H: u32 = 1; pub const __STDC_IEC_559__: u32 = 1; pub const __STDC_IEC_559_COMPLEX__: u32 = 1; pub const __STDC_ISO_10646__: u32 = 201505; pub const __STDC_NO_THREADS__: u32 = 1; pub const __GNU_LIBRARY__: u32 = 6; pub const __GLIBC__: u32 = 2; pub const __GLIBC_MINOR__: u32 = 23; pub const _SYS_CDEFS_H: u32 = 1; pub const __WORDSIZE: u32 = 64; pub const __WORDSIZE_TIME64_COMPAT32: u32 = 1; pub const __SYSCALL_WORDSIZE: u32 = 64; pub const _STDLIB_H: u32 = 1; pub const WNOHANG: u32 = 1; pub const WUNTRACED: u32 = 2; pub const WSTOPPED: u32 = 2; pub const WEXITED: u32 = 4; pub const WCONTINUED: u32 = 8; pub const WNOWAIT: u32 = 16777216; pub const __WNOTHREAD: u32 = 536870912; pub const __WALL: u32 = 1073741824; pub const __WCLONE: u32 = 2147483648; pub const __ENUM_IDTYPE_T: u32 = 1; pub const __W_CONTINUED: u32 = 65535; pub const __WCOREFLAG: u32 = 128; pub const _ENDIAN_H: u32 = 1; pub const __LITTLE_ENDIAN: u32 = 1234; pub const __BIG_ENDIAN: u32 = 4321; pub const __PDP_ENDIAN: u32 = 3412; pub const __BYTE_ORDER: u32 = 1234; pub const __FLOAT_WORD_ORDER: u32 = 1234; pub const LITTLE_ENDIAN: u32 = 1234; pub const BIG_ENDIAN: u32 = 4321; pub const PDP_ENDIAN: u32 = 3412; pub const BYTE_ORDER: u32 = 1234; pub const _BITS_BYTESWAP_H: u32 = 1; pub const _BITS_TYPES_H: u32 = 1; pub const _BITS_TYPESIZES_H: u32 = 1; pub const __OFF_T_MATCHES_OFF64_T: u32 = 1; pub const __INO_T_MATCHES_INO64_T: u32 = 1; pub const __ldiv_t_defined: u32 = 1; pub const __lldiv_t_defined: u32 = 1; pub const RAND_MAX: u32 = 2147483647; pub const EXIT_FAILURE: u32 = 1; pub const EXIT_SUCCESS: u32 = 0; pub const _SYS_TYPES_H: u32 = 1; pub const __clock_t_defined: u32 = 1; pub const __time_t_defined: u32 = 1; pub const __clockid_t_defined: u32 = 1; pub const __timer_t_defined: u32 = 1; pub const __BIT_TYPES_DEFINED__: u32 = 1; pub const _SYS_SELECT_H: u32 = 1; pub const __FD_ZERO_STOS: &'static [u8; 6usize] = b"stosq\0"; pub const _SIGSET_H_types: u32 = 1; pub const __timespec_defined: u32 = 1; pub const _STRUCT_TIMEVAL: u32 = 1; pub const FD_SETSIZE: u32 = 1024; pub const _SYS_SYSMACROS_H: u32 = 1; pub const _BITS_PTHREADTYPES_H: u32 = 1; pub const __SIZEOF_PTHREAD_ATTR_T: u32 = 56; pub const __SIZEOF_PTHREAD_MUTEX_T: u32 = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: u32 = 4; pub const __SIZEOF_PTHREAD_COND_T: u32 = 48; pub const __SIZEOF_PTHREAD_CONDATTR_T: u32 = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: u32 = 56; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: u32 = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: u32 = 32; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: u32 = 4; pub const __have_pthread_attr_t: u32 = 1; pub const __PTHREAD_MUTEX_HAVE_PREV: u32 = 1; pub const __PTHREAD_RWLOCK_INT_FLAGS_SHARED: u32 = 1; pub const _ALLOCA_H: u32 = 1; pub const SNDRV_PCM_INFO_MMAP: u32 = 1; pub const SNDRV_PCM_INFO_MMAP_VALID: u32 = 2; pub const SNDRV_PCM_INFO_DOUBLE: u32 = 4; pub const SNDRV_PCM_INFO_BATCH: u32 = 16; pub const SNDRV_PCM_INFO_SYNC_APPLPTR: u32 = 32; pub const SNDRV_PCM_INFO_INTERLEAVED: u32 = 256; pub const SNDRV_PCM_INFO_NONINTERLEAVED: u32 = 512; pub const SNDRV_PCM_INFO_COMPLEX: u32 = 1024; pub const SNDRV_PCM_INFO_BLOCK_TRANSFER: u32 = 65536; pub const SNDRV_PCM_INFO_OVERRANGE: u32 = 131072; pub const SNDRV_PCM_INFO_RESUME: u32 = 262144; pub const SNDRV_PCM_INFO_PAUSE: u32 = 524288; pub const SNDRV_PCM_INFO_HALF_DUPLEX: u32 = 1048576; pub const SNDRV_PCM_INFO_JOINT_DUPLEX: u32 = 2097152; pub const SNDRV_PCM_INFO_SYNC_START: u32 = 4194304; pub const SNDRV_PCM_INFO_NO_PERIOD_WAKEUP: u32 = 8388608; pub const SNDRV_PCM_INFO_HAS_WALL_CLOCK: u32 = 16777216; pub const SNDRV_PCM_INFO_HAS_LINK_ATIME: u32 = 16777216; pub const SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME: u32 = 33554432; pub const SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME: u32 = 67108864; pub const SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME: u32 = 134217728; pub const SNDRV_PCM_INFO_DRAIN_TRIGGER: u32 = 1073741824; pub const SNDRV_PCM_INFO_FIFO_IN_FRAMES: u32 = 2147483648; pub const SNDRV_PCM_HW_PARAM_ACCESS: u32 = 0; pub const SNDRV_PCM_HW_PARAM_FORMAT: u32 = 1; pub const SNDRV_PCM_HW_PARAM_SUBFORMAT: u32 = 2; pub const SNDRV_PCM_HW_PARAM_FIRST_MASK: u32 = 0; pub const SNDRV_PCM_HW_PARAM_LAST_MASK: u32 = 2; pub const SNDRV_PCM_HW_PARAM_SAMPLE_BITS: u32 = 8; pub const SNDRV_PCM_HW_PARAM_FRAME_BITS: u32 = 9; pub const SNDRV_PCM_HW_PARAM_CHANNELS: u32 = 10; pub const SNDRV_PCM_HW_PARAM_RATE: u32 = 11; pub const SNDRV_PCM_HW_PARAM_PERIOD_TIME: u32 = 12; pub const SNDRV_PCM_HW_PARAM_PERIOD_SIZE: u32 = 13; pub const SNDRV_PCM_HW_PARAM_PERIOD_BYTES: u32 = 14; pub const SNDRV_PCM_HW_PARAM_PERIODS: u32 = 15; pub const SNDRV_PCM_HW_PARAM_BUFFER_TIME: u32 = 16; pub const SNDRV_PCM_HW_PARAM_BUFFER_SIZE: u32 = 17; pub const SNDRV_PCM_HW_PARAM_BUFFER_BYTES: u32 = 18; pub const SNDRV_PCM_HW_PARAM_TICK_TIME: u32 = 19; pub const SNDRV_PCM_HW_PARAM_FIRST_INTERVAL: u32 = 8; pub const SNDRV_PCM_HW_PARAM_LAST_INTERVAL: u32 = 19; pub const SNDRV_PCM_HW_PARAMS_NORESAMPLE: u32 = 1; pub const SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER: u32 = 2; pub const SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP: u32 = 4; pub const SNDRV_MASK_MAX: u32 = 256; pub const SNDRV_PCM_SYNC_PTR_HWSYNC: u32 = 1; pub const SNDRV_PCM_SYNC_PTR_APPL: u32 = 2; pub const SNDRV_PCM_SYNC_PTR_AVAIL_MIN: u32 = 4; pub const SNDRV_CHMAP_POSITION_MASK: u32 = 65535; pub const SNDRV_CHMAP_PHASE_INVERSE: u32 = 65536; pub const SNDRV_CHMAP_DRIVER_SPEC: u32 = 131072; pub const SNDRV_RAWMIDI_INFO_OUTPUT: u32 = 1; pub const SNDRV_RAWMIDI_INFO_INPUT: u32 = 2; pub const SNDRV_RAWMIDI_INFO_DUPLEX: u32 = 4; pub const SNDRV_TIMER_GLOBAL_SYSTEM: u32 = 0; pub const SNDRV_TIMER_GLOBAL_RTC: u32 = 1; pub const SNDRV_TIMER_GLOBAL_HPET: u32 = 2; pub const SNDRV_TIMER_GLOBAL_HRTIMER: u32 = 3; pub const SNDRV_TIMER_FLG_SLAVE: u32 = 1; pub const SNDRV_TIMER_PSFLG_AUTO: u32 = 1; pub const SNDRV_TIMER_PSFLG_EXCLUSIVE: u32 = 2; pub const SNDRV_TIMER_PSFLG_EARLY_EVENT: u32 = 4; pub const SNDRV_CTL_ELEM_ACCESS_READ: u32 = 1; pub const SNDRV_CTL_ELEM_ACCESS_WRITE: u32 = 2; pub const SNDRV_CTL_ELEM_ACCESS_READWRITE: u32 = 3; pub const SNDRV_CTL_ELEM_ACCESS_VOLATILE: u32 = 4; pub const SNDRV_CTL_ELEM_ACCESS_TIMESTAMP: u32 = 8; pub const SNDRV_CTL_ELEM_ACCESS_TLV_READ: u32 = 16; pub const SNDRV_CTL_ELEM_ACCESS_TLV_WRITE: u32 = 32; pub const SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE: u32 = 48; pub const SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND: u32 = 64; pub const SNDRV_CTL_ELEM_ACCESS_INACTIVE: u32 = 256; pub const SNDRV_CTL_ELEM_ACCESS_LOCK: u32 = 512; pub const SNDRV_CTL_ELEM_ACCESS_OWNER: u32 = 1024; pub const SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK: u32 = 268435456; pub const SNDRV_CTL_ELEM_ACCESS_USER: u32 = 536870912; pub const SNDRV_CTL_POWER_D0: u32 = 0; pub const SNDRV_CTL_POWER_D1: u32 = 256; pub const SNDRV_CTL_POWER_D2: u32 = 512; pub const SNDRV_CTL_POWER_D3: u32 = 768; pub const SNDRV_CTL_POWER_D3hot: u32 = 768; pub const SNDRV_CTL_POWER_D3cold: u32 = 769; pub const SNDRV_CTL_ELEM_ID_NAME_MAXLEN: u32 = 44; pub const SNDRV_CTL_EVENT_MASK_VALUE: u32 = 1; pub const SNDRV_CTL_EVENT_MASK_INFO: u32 = 2; pub const SNDRV_CTL_EVENT_MASK_ADD: u32 = 4; pub const SNDRV_CTL_EVENT_MASK_TLV: u32 = 8; pub const SNDRV_CTL_EVENT_MASK_REMOVE: i32 = -1; pub const SNDRV_CTL_NAME_NONE: &'static [u8; 1usize] = b"\0"; pub const SNDRV_CTL_NAME_PLAYBACK: &'static [u8; 10usize] = b"Playback \0"; pub const SNDRV_CTL_NAME_CAPTURE: &'static [u8; 9usize] = b"Capture \0"; pub const SNDRV_CTL_NAME_IEC958_NONE: &'static [u8; 1usize] = b"\0"; pub const SNDRV_CTL_NAME_IEC958_SWITCH: &'static [u8; 7usize] = b"Switch\0"; pub const SNDRV_CTL_NAME_IEC958_VOLUME: &'static [u8; 7usize] = b"Volume\0"; pub const SNDRV_CTL_NAME_IEC958_DEFAULT: &'static [u8; 8usize] = b"Default\0"; pub const SNDRV_CTL_NAME_IEC958_MASK: &'static [u8; 5usize] = b"Mask\0"; pub const SNDRV_CTL_NAME_IEC958_CON_MASK: &'static [u8; 9usize] = b"Con Mask\0"; pub const SNDRV_CTL_NAME_IEC958_PRO_MASK: &'static [u8; 9usize] = b"Pro Mask\0"; pub const SNDRV_CTL_NAME_IEC958_PCM_STREAM: &'static [u8; 11usize] = b"PCM Stream\0"; pub type __s8 = ::std::os::raw::c_schar; pub type __u8 = ::std::os::raw::c_uchar; pub type __s16 = ::std::os::raw::c_short; pub type __u16 = ::std::os::raw::c_ushort; pub type __s32 = ::std::os::raw::c_int; pub type __u32 = ::std::os::raw::c_uint; pub type __s64 = ::std::os::raw::c_longlong; pub type __u64 = ::std::os::raw::c_ulonglong; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __kernel_fd_set { pub fds_bits: [::std::os::raw::c_ulong; 16usize], } #[test] fn bindgen_test_layout___kernel_fd_set() { assert_eq!( ::std::mem::size_of::<__kernel_fd_set>(), 128usize, concat!("Size of: ", stringify!(__kernel_fd_set)) ); assert_eq!( ::std::mem::align_of::<__kernel_fd_set>(), 8usize, concat!("Alignment of ", stringify!(__kernel_fd_set)) ); assert_eq!( unsafe { &(*(::std::ptr::null::<__kernel_fd_set>())).fds_bits as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(__kernel_fd_set), "::", stringify!(fds_bits) ) ); } pub type __kernel_sighandler_t = ::std::option::Option; pub type __kernel_key_t = ::std::os::raw::c_int; pub type __kernel_mqd_t = ::std::os::raw::c_int; pub type __kernel_old_uid_t = ::std::os::raw::c_ushort; pub type __kernel_old_gid_t = ::std::os::raw::c_ushort; pub type __kernel_old_dev_t = ::std::os::raw::c_ulong; pub type __kernel_long_t = ::std::os::raw::c_long; pub type __kernel_ulong_t = ::std::os::raw::c_ulong; pub type __kernel_ino_t = __kernel_ulong_t; pub type __kernel_mode_t = ::std::os::raw::c_uint; pub type __kernel_pid_t = ::std::os::raw::c_int; pub type __kernel_ipc_pid_t = ::std::os::raw::c_int; pub type __kernel_uid_t = ::std::os::raw::c_uint; pub type __kernel_gid_t = ::std::os::raw::c_uint; pub type __kernel_suseconds_t = __kernel_long_t; pub type __kernel_daddr_t = ::std::os::raw::c_int; pub type __kernel_uid32_t = ::std::os::raw::c_uint; pub type __kernel_gid32_t = ::std::os::raw::c_uint; pub type __kernel_size_t = __kernel_ulong_t; pub type __kernel_ssize_t = __kernel_long_t; pub type __kernel_ptrdiff_t = __kernel_long_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __kernel_fsid_t { pub val: [::std::os::raw::c_int; 2usize], } #[test] fn bindgen_test_layout___kernel_fsid_t() { assert_eq!( ::std::mem::size_of::<__kernel_fsid_t>(), 8usize, concat!("Size of: ", stringify!(__kernel_fsid_t)) ); assert_eq!( ::std::mem::align_of::<__kernel_fsid_t>(), 4usize, concat!("Alignment of ", stringify!(__kernel_fsid_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::<__kernel_fsid_t>())).val as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(__kernel_fsid_t), "::", stringify!(val) ) ); } pub type __kernel_off_t = __kernel_long_t; pub type __kernel_loff_t = ::std::os::raw::c_longlong; pub type __kernel_time_t = __kernel_long_t; pub type __kernel_clock_t = __kernel_long_t; pub type __kernel_timer_t = ::std::os::raw::c_int; pub type __kernel_clockid_t = ::std::os::raw::c_int; pub type __kernel_caddr_t = *mut ::std::os::raw::c_char; pub type __kernel_uid16_t = ::std::os::raw::c_ushort; pub type __kernel_gid16_t = ::std::os::raw::c_ushort; pub type __le16 = __u16; pub type __be16 = __u16; pub type __le32 = __u32; pub type __be32 = __u32; pub type __le64 = __u64; pub type __be64 = __u64; pub type __sum16 = __u16; pub type __wsum = __u32; pub type wchar_t = ::std::os::raw::c_int; pub const idtype_t_P_ALL: idtype_t = 0; pub const idtype_t_P_PID: idtype_t = 1; pub const idtype_t_P_PGID: idtype_t = 2; pub type idtype_t = u32; pub type __u_char = ::std::os::raw::c_uchar; pub type __u_short = ::std::os::raw::c_ushort; pub type __u_int = ::std::os::raw::c_uint; pub type __u_long = ::std::os::raw::c_ulong; pub type __int8_t = ::std::os::raw::c_schar; pub type __uint8_t = ::std::os::raw::c_uchar; pub type __int16_t = ::std::os::raw::c_short; pub type __uint16_t = ::std::os::raw::c_ushort; pub type __int32_t = ::std::os::raw::c_int; pub type __uint32_t = ::std::os::raw::c_uint; pub type __int64_t = ::std::os::raw::c_long; pub type __uint64_t = ::std::os::raw::c_ulong; pub type __quad_t = ::std::os::raw::c_long; pub type __u_quad_t = ::std::os::raw::c_ulong; pub type __dev_t = ::std::os::raw::c_ulong; pub type __uid_t = ::std::os::raw::c_uint; pub type __gid_t = ::std::os::raw::c_uint; pub type __ino_t = ::std::os::raw::c_ulong; pub type __ino64_t = ::std::os::raw::c_ulong; pub type __mode_t = ::std::os::raw::c_uint; pub type __nlink_t = ::std::os::raw::c_ulong; pub type __off_t = ::std::os::raw::c_long; pub type __off64_t = ::std::os::raw::c_long; pub type __pid_t = ::std::os::raw::c_int; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __fsid_t { pub __val: [::std::os::raw::c_int; 2usize], } #[test] fn bindgen_test_layout___fsid_t() { assert_eq!( ::std::mem::size_of::<__fsid_t>(), 8usize, concat!("Size of: ", stringify!(__fsid_t)) ); assert_eq!( ::std::mem::align_of::<__fsid_t>(), 4usize, concat!("Alignment of ", stringify!(__fsid_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::<__fsid_t>())).__val as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(__fsid_t), "::", stringify!(__val) ) ); } pub type __clock_t = ::std::os::raw::c_long; pub type __rlim_t = ::std::os::raw::c_ulong; pub type __rlim64_t = ::std::os::raw::c_ulong; pub type __id_t = ::std::os::raw::c_uint; pub type __time_t = ::std::os::raw::c_long; pub type __useconds_t = ::std::os::raw::c_uint; pub type __suseconds_t = ::std::os::raw::c_long; pub type __daddr_t = ::std::os::raw::c_int; pub type __key_t = ::std::os::raw::c_int; pub type __clockid_t = ::std::os::raw::c_int; pub type __timer_t = *mut ::std::os::raw::c_void; pub type __blksize_t = ::std::os::raw::c_long; pub type __blkcnt_t = ::std::os::raw::c_long; pub type __blkcnt64_t = ::std::os::raw::c_long; pub type __fsblkcnt_t = ::std::os::raw::c_ulong; pub type __fsblkcnt64_t = ::std::os::raw::c_ulong; pub type __fsfilcnt_t = ::std::os::raw::c_ulong; pub type __fsfilcnt64_t = ::std::os::raw::c_ulong; pub type __fsword_t = ::std::os::raw::c_long; pub type __ssize_t = ::std::os::raw::c_long; pub type __syscall_slong_t = ::std::os::raw::c_long; pub type __syscall_ulong_t = ::std::os::raw::c_ulong; pub type __loff_t = __off64_t; pub type __qaddr_t = *mut __quad_t; pub type __caddr_t = *mut ::std::os::raw::c_char; pub type __intptr_t = ::std::os::raw::c_long; pub type __socklen_t = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub union wait { pub w_status: ::std::os::raw::c_int, pub __wait_terminated: wait__bindgen_ty_1, pub __wait_stopped: wait__bindgen_ty_2, _bindgen_union_align: u32, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct wait__bindgen_ty_1 { pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u8>, pub __bindgen_align: [u32; 0usize], } #[test] fn bindgen_test_layout_wait__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(wait__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(wait__bindgen_ty_1)) ); } impl wait__bindgen_ty_1 { #[inline] pub fn __w_termsig(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 7u8) as u32) } } #[inline] pub fn set___w_termsig(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 7u8, val as u64) } } #[inline] pub fn __w_coredump(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u32) } } #[inline] pub fn set___w_coredump(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(7usize, 1u8, val as u64) } } #[inline] pub fn __w_retcode(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) } } #[inline] pub fn set___w_retcode(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(8usize, 8u8, val as u64) } } #[inline] pub fn new_bitfield_1( __w_termsig: ::std::os::raw::c_uint, __w_coredump: ::std::os::raw::c_uint, __w_retcode: ::std::os::raw::c_uint, ) -> __BindgenBitfieldUnit<[u8; 4usize], u8> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u8> = Default::default(); __bindgen_bitfield_unit.set(0usize, 7u8, { let __w_termsig: u32 = unsafe { ::std::mem::transmute(__w_termsig) }; __w_termsig as u64 }); __bindgen_bitfield_unit.set(7usize, 1u8, { let __w_coredump: u32 = unsafe { ::std::mem::transmute(__w_coredump) }; __w_coredump as u64 }); __bindgen_bitfield_unit.set(8usize, 8u8, { let __w_retcode: u32 = unsafe { ::std::mem::transmute(__w_retcode) }; __w_retcode as u64 }); __bindgen_bitfield_unit } } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct wait__bindgen_ty_2 { pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize], u8>, pub __bindgen_align: [u32; 0usize], } #[test] fn bindgen_test_layout_wait__bindgen_ty_2() { assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(wait__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(wait__bindgen_ty_2)) ); } impl wait__bindgen_ty_2 { #[inline] pub fn __w_stopval(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u32) } } #[inline] pub fn set___w_stopval(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 8u8, val as u64) } } #[inline] pub fn __w_stopsig(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) } } #[inline] pub fn set___w_stopsig(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(8usize, 8u8, val as u64) } } #[inline] pub fn new_bitfield_1( __w_stopval: ::std::os::raw::c_uint, __w_stopsig: ::std::os::raw::c_uint, ) -> __BindgenBitfieldUnit<[u8; 4usize], u8> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize], u8> = Default::default(); __bindgen_bitfield_unit.set(0usize, 8u8, { let __w_stopval: u32 = unsafe { ::std::mem::transmute(__w_stopval) }; __w_stopval as u64 }); __bindgen_bitfield_unit.set(8usize, 8u8, { let __w_stopsig: u32 = unsafe { ::std::mem::transmute(__w_stopsig) }; __w_stopsig as u64 }); __bindgen_bitfield_unit } } #[test] fn bindgen_test_layout_wait() { assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(wait)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(wait)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).w_status as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(wait), "::", stringify!(w_status) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__wait_terminated as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(wait), "::", stringify!(__wait_terminated) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__wait_stopped as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(wait), "::", stringify!(__wait_stopped) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union __WAIT_STATUS { pub __uptr: *mut wait, pub __iptr: *mut ::std::os::raw::c_int, _bindgen_union_align: u64, } #[test] fn bindgen_test_layout___WAIT_STATUS() { assert_eq!( ::std::mem::size_of::<__WAIT_STATUS>(), 8usize, concat!("Size of: ", stringify!(__WAIT_STATUS)) ); assert_eq!( ::std::mem::align_of::<__WAIT_STATUS>(), 8usize, concat!("Alignment of ", stringify!(__WAIT_STATUS)) ); assert_eq!( unsafe { &(*(::std::ptr::null::<__WAIT_STATUS>())).__uptr as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(__WAIT_STATUS), "::", stringify!(__uptr) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::<__WAIT_STATUS>())).__iptr as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(__WAIT_STATUS), "::", stringify!(__iptr) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct div_t { pub quot: ::std::os::raw::c_int, pub rem: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_div_t() { assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(div_t)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(div_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).quot as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(div_t), "::", stringify!(quot) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rem as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(div_t), "::", stringify!(rem) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ldiv_t { pub quot: ::std::os::raw::c_long, pub rem: ::std::os::raw::c_long, } #[test] fn bindgen_test_layout_ldiv_t() { assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ldiv_t)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ldiv_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).quot as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(ldiv_t), "::", stringify!(quot) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rem as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(ldiv_t), "::", stringify!(rem) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct lldiv_t { pub quot: ::std::os::raw::c_longlong, pub rem: ::std::os::raw::c_longlong, } #[test] fn bindgen_test_layout_lldiv_t() { assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(lldiv_t)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(lldiv_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).quot as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(lldiv_t), "::", stringify!(quot) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rem as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(lldiv_t), "::", stringify!(rem) ) ); } extern "C" { pub fn __ctype_get_mb_cur_max() -> usize; } extern "C" { pub fn atof(__nptr: *const ::std::os::raw::c_char) -> f64; } extern "C" { pub fn atoi(__nptr: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; } extern "C" { pub fn atol(__nptr: *const ::std::os::raw::c_char) -> ::std::os::raw::c_long; } extern "C" { pub fn atoll(__nptr: *const ::std::os::raw::c_char) -> ::std::os::raw::c_longlong; } extern "C" { pub fn strtod( __nptr: *const ::std::os::raw::c_char, __endptr: *mut *mut ::std::os::raw::c_char, ) -> f64; } extern "C" { pub fn strtof( __nptr: *const ::std::os::raw::c_char, __endptr: *mut *mut ::std::os::raw::c_char, ) -> f32; } extern "C" { pub fn strtold( __nptr: *const ::std::os::raw::c_char, __endptr: *mut *mut ::std::os::raw::c_char, ) -> f64; } extern "C" { pub fn strtol( __nptr: *const ::std::os::raw::c_char, __endptr: *mut *mut ::std::os::raw::c_char, __base: ::std::os::raw::c_int, ) -> ::std::os::raw::c_long; } extern "C" { pub fn strtoul( __nptr: *const ::std::os::raw::c_char, __endptr: *mut *mut ::std::os::raw::c_char, __base: ::std::os::raw::c_int, ) -> ::std::os::raw::c_ulong; } extern "C" { pub fn strtoq( __nptr: *const ::std::os::raw::c_char, __endptr: *mut *mut ::std::os::raw::c_char, __base: ::std::os::raw::c_int, ) -> ::std::os::raw::c_longlong; } extern "C" { pub fn strtouq( __nptr: *const ::std::os::raw::c_char, __endptr: *mut *mut ::std::os::raw::c_char, __base: ::std::os::raw::c_int, ) -> ::std::os::raw::c_ulonglong; } extern "C" { pub fn strtoll( __nptr: *const ::std::os::raw::c_char, __endptr: *mut *mut ::std::os::raw::c_char, __base: ::std::os::raw::c_int, ) -> ::std::os::raw::c_longlong; } extern "C" { pub fn strtoull( __nptr: *const ::std::os::raw::c_char, __endptr: *mut *mut ::std::os::raw::c_char, __base: ::std::os::raw::c_int, ) -> ::std::os::raw::c_ulonglong; } extern "C" { pub fn l64a(__n: ::std::os::raw::c_long) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn a64l(__s: *const ::std::os::raw::c_char) -> ::std::os::raw::c_long; } pub type u_char = __u_char; pub type u_short = __u_short; pub type u_int = __u_int; pub type u_long = __u_long; pub type quad_t = __quad_t; pub type u_quad_t = __u_quad_t; pub type fsid_t = __fsid_t; pub type loff_t = __loff_t; pub type ino_t = __ino_t; pub type dev_t = __dev_t; pub type gid_t = __gid_t; pub type mode_t = __mode_t; pub type nlink_t = __nlink_t; pub type uid_t = __uid_t; pub type off_t = __off_t; pub type pid_t = __pid_t; pub type id_t = __id_t; pub type daddr_t = __daddr_t; pub type caddr_t = __caddr_t; pub type key_t = __key_t; pub type clock_t = __clock_t; pub type time_t = __time_t; pub type clockid_t = __clockid_t; pub type timer_t = __timer_t; pub type ulong = ::std::os::raw::c_ulong; pub type ushort = ::std::os::raw::c_ushort; pub type uint = ::std::os::raw::c_uint; pub type u_int8_t = ::std::os::raw::c_uchar; pub type u_int16_t = ::std::os::raw::c_ushort; pub type u_int32_t = ::std::os::raw::c_uint; pub type u_int64_t = ::std::os::raw::c_ulong; pub type register_t = ::std::os::raw::c_long; pub type __sig_atomic_t = ::std::os::raw::c_int; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __sigset_t { pub __val: [::std::os::raw::c_ulong; 16usize], } #[test] fn bindgen_test_layout___sigset_t() { assert_eq!( ::std::mem::size_of::<__sigset_t>(), 128usize, concat!("Size of: ", stringify!(__sigset_t)) ); assert_eq!( ::std::mem::align_of::<__sigset_t>(), 8usize, concat!("Alignment of ", stringify!(__sigset_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::<__sigset_t>())).__val as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(__sigset_t), "::", stringify!(__val) ) ); } pub type sigset_t = __sigset_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timespec { pub tv_sec: __time_t, pub tv_nsec: __syscall_slong_t, } #[test] fn bindgen_test_layout_timespec() { assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(timespec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timespec)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tv_sec as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(timespec), "::", stringify!(tv_sec) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tv_nsec as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(timespec), "::", stringify!(tv_nsec) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timeval { pub tv_sec: __time_t, pub tv_usec: __suseconds_t, } #[test] fn bindgen_test_layout_timeval() { assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(timeval)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timeval)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tv_sec as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(timeval), "::", stringify!(tv_sec) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tv_usec as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(timeval), "::", stringify!(tv_usec) ) ); } pub type suseconds_t = __suseconds_t; pub type __fd_mask = ::std::os::raw::c_long; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct fd_set { pub __fds_bits: [__fd_mask; 16usize], } #[test] fn bindgen_test_layout_fd_set() { assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(fd_set)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(fd_set)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__fds_bits as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(fd_set), "::", stringify!(__fds_bits) ) ); } pub type fd_mask = __fd_mask; extern "C" { pub fn select( __nfds: ::std::os::raw::c_int, __readfds: *mut fd_set, __writefds: *mut fd_set, __exceptfds: *mut fd_set, __timeout: *mut timeval, ) -> ::std::os::raw::c_int; } extern "C" { pub fn pselect( __nfds: ::std::os::raw::c_int, __readfds: *mut fd_set, __writefds: *mut fd_set, __exceptfds: *mut fd_set, __timeout: *const timespec, __sigmask: *const __sigset_t, ) -> ::std::os::raw::c_int; } extern "C" { pub fn gnu_dev_major(__dev: ::std::os::raw::c_ulonglong) -> ::std::os::raw::c_uint; } extern "C" { pub fn gnu_dev_minor(__dev: ::std::os::raw::c_ulonglong) -> ::std::os::raw::c_uint; } extern "C" { pub fn gnu_dev_makedev( __major: ::std::os::raw::c_uint, __minor: ::std::os::raw::c_uint, ) -> ::std::os::raw::c_ulonglong; } pub type blksize_t = __blksize_t; pub type blkcnt_t = __blkcnt_t; pub type fsblkcnt_t = __fsblkcnt_t; pub type fsfilcnt_t = __fsfilcnt_t; pub type pthread_t = ::std::os::raw::c_ulong; #[repr(C)] #[derive(Copy, Clone)] pub union pthread_attr_t { pub __size: [::std::os::raw::c_char; 56usize], pub __align: ::std::os::raw::c_long, _bindgen_union_align: [u64; 7usize], } #[test] fn bindgen_test_layout_pthread_attr_t() { assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(pthread_attr_t)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pthread_attr_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__size as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_attr_t), "::", stringify!(__size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__align as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_attr_t), "::", stringify!(__align) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __pthread_internal_list { pub __prev: *mut __pthread_internal_list, pub __next: *mut __pthread_internal_list, } #[test] fn bindgen_test_layout___pthread_internal_list() { assert_eq!( ::std::mem::size_of::<__pthread_internal_list>(), 16usize, concat!("Size of: ", stringify!(__pthread_internal_list)) ); assert_eq!( ::std::mem::align_of::<__pthread_internal_list>(), 8usize, concat!("Alignment of ", stringify!(__pthread_internal_list)) ); assert_eq!( unsafe { &(*(::std::ptr::null::<__pthread_internal_list>())).__prev as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(__pthread_internal_list), "::", stringify!(__prev) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::<__pthread_internal_list>())).__next as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(__pthread_internal_list), "::", stringify!(__next) ) ); } pub type __pthread_list_t = __pthread_internal_list; #[repr(C)] #[derive(Copy, Clone)] pub union pthread_mutex_t { pub __data: pthread_mutex_t___pthread_mutex_s, pub __size: [::std::os::raw::c_char; 40usize], pub __align: ::std::os::raw::c_long, _bindgen_union_align: [u64; 5usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_mutex_t___pthread_mutex_s { pub __lock: ::std::os::raw::c_int, pub __count: ::std::os::raw::c_uint, pub __owner: ::std::os::raw::c_int, pub __nusers: ::std::os::raw::c_uint, pub __kind: ::std::os::raw::c_int, pub __spins: ::std::os::raw::c_short, pub __elision: ::std::os::raw::c_short, pub __list: __pthread_list_t, } #[test] fn bindgen_test_layout_pthread_mutex_t___pthread_mutex_s() { assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pthread_mutex_t___pthread_mutex_s)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", stringify!(pthread_mutex_t___pthread_mutex_s) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__lock as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t___pthread_mutex_s), "::", stringify!(__lock) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__count as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t___pthread_mutex_s), "::", stringify!(__count) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__owner as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t___pthread_mutex_s), "::", stringify!(__owner) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__nusers as *const _ as usize }, 12usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t___pthread_mutex_s), "::", stringify!(__nusers) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__kind as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t___pthread_mutex_s), "::", stringify!(__kind) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__spins as *const _ as usize }, 20usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t___pthread_mutex_s), "::", stringify!(__spins) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__elision as *const _ as usize }, 22usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t___pthread_mutex_s), "::", stringify!(__elision) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__list as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t___pthread_mutex_s), "::", stringify!(__list) ) ); } #[test] fn bindgen_test_layout_pthread_mutex_t() { assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pthread_mutex_t)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pthread_mutex_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__data as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t), "::", stringify!(__data) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__size as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t), "::", stringify!(__size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__align as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_mutex_t), "::", stringify!(__align) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pthread_mutexattr_t { pub __size: [::std::os::raw::c_char; 4usize], pub __align: ::std::os::raw::c_int, _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_pthread_mutexattr_t() { assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(pthread_mutexattr_t)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pthread_mutexattr_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__size as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_mutexattr_t), "::", stringify!(__size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__align as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_mutexattr_t), "::", stringify!(__align) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pthread_cond_t { pub __data: pthread_cond_t__bindgen_ty_1, pub __size: [::std::os::raw::c_char; 48usize], pub __align: ::std::os::raw::c_longlong, _bindgen_union_align: [u64; 6usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_cond_t__bindgen_ty_1 { pub __lock: ::std::os::raw::c_int, pub __futex: ::std::os::raw::c_uint, pub __total_seq: ::std::os::raw::c_ulonglong, pub __wakeup_seq: ::std::os::raw::c_ulonglong, pub __woken_seq: ::std::os::raw::c_ulonglong, pub __mutex: *mut ::std::os::raw::c_void, pub __nwaiters: ::std::os::raw::c_uint, pub __broadcast_seq: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_pthread_cond_t__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(pthread_cond_t__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pthread_cond_t__bindgen_ty_1)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__lock as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_cond_t__bindgen_ty_1), "::", stringify!(__lock) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__futex as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(pthread_cond_t__bindgen_ty_1), "::", stringify!(__futex) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__total_seq as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(pthread_cond_t__bindgen_ty_1), "::", stringify!(__total_seq) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__wakeup_seq as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(pthread_cond_t__bindgen_ty_1), "::", stringify!(__wakeup_seq) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__woken_seq as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(pthread_cond_t__bindgen_ty_1), "::", stringify!(__woken_seq) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__mutex as *const _ as usize }, 32usize, concat!( "Offset of field: ", stringify!(pthread_cond_t__bindgen_ty_1), "::", stringify!(__mutex) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__nwaiters as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(pthread_cond_t__bindgen_ty_1), "::", stringify!(__nwaiters) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__broadcast_seq as *const _ as usize }, 44usize, concat!( "Offset of field: ", stringify!(pthread_cond_t__bindgen_ty_1), "::", stringify!(__broadcast_seq) ) ); } #[test] fn bindgen_test_layout_pthread_cond_t() { assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(pthread_cond_t)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pthread_cond_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__data as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_cond_t), "::", stringify!(__data) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__size as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_cond_t), "::", stringify!(__size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__align as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_cond_t), "::", stringify!(__align) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pthread_condattr_t { pub __size: [::std::os::raw::c_char; 4usize], pub __align: ::std::os::raw::c_int, _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_pthread_condattr_t() { assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(pthread_condattr_t)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pthread_condattr_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__size as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_condattr_t), "::", stringify!(__size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__align as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_condattr_t), "::", stringify!(__align) ) ); } pub type pthread_key_t = ::std::os::raw::c_uint; pub type pthread_once_t = ::std::os::raw::c_int; #[repr(C)] #[derive(Copy, Clone)] pub union pthread_rwlock_t { pub __data: pthread_rwlock_t__bindgen_ty_1, pub __size: [::std::os::raw::c_char; 56usize], pub __align: ::std::os::raw::c_long, _bindgen_union_align: [u64; 7usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_rwlock_t__bindgen_ty_1 { pub __lock: ::std::os::raw::c_int, pub __nr_readers: ::std::os::raw::c_uint, pub __readers_wakeup: ::std::os::raw::c_uint, pub __writer_wakeup: ::std::os::raw::c_uint, pub __nr_readers_queued: ::std::os::raw::c_uint, pub __nr_writers_queued: ::std::os::raw::c_uint, pub __writer: ::std::os::raw::c_int, pub __shared: ::std::os::raw::c_int, pub __rwelision: ::std::os::raw::c_schar, pub __pad1: [::std::os::raw::c_uchar; 7usize], pub __pad2: ::std::os::raw::c_ulong, pub __flags: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_pthread_rwlock_t__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(pthread_rwlock_t__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pthread_rwlock_t__bindgen_ty_1)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__lock as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__lock) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__nr_readers as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__nr_readers) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__readers_wakeup as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__readers_wakeup) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__writer_wakeup as *const _ as usize }, 12usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__writer_wakeup) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__nr_readers_queued as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__nr_readers_queued) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__nr_writers_queued as *const _ as usize }, 20usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__nr_writers_queued) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__writer as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__writer) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__shared as *const _ as usize }, 28usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__shared) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__rwelision as *const _ as usize }, 32usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__rwelision) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__pad1 as *const _ as usize }, 33usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__pad1) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__pad2 as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__pad2) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__flags as *const _ as usize }, 48usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t__bindgen_ty_1), "::", stringify!(__flags) ) ); } #[test] fn bindgen_test_layout_pthread_rwlock_t() { assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(pthread_rwlock_t)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pthread_rwlock_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__data as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t), "::", stringify!(__data) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__size as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t), "::", stringify!(__size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__align as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_rwlock_t), "::", stringify!(__align) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pthread_rwlockattr_t { pub __size: [::std::os::raw::c_char; 8usize], pub __align: ::std::os::raw::c_long, _bindgen_union_align: u64, } #[test] fn bindgen_test_layout_pthread_rwlockattr_t() { assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pthread_rwlockattr_t)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pthread_rwlockattr_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__size as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_rwlockattr_t), "::", stringify!(__size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__align as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_rwlockattr_t), "::", stringify!(__align) ) ); } pub type pthread_spinlock_t = ::std::os::raw::c_int; #[repr(C)] #[derive(Copy, Clone)] pub union pthread_barrier_t { pub __size: [::std::os::raw::c_char; 32usize], pub __align: ::std::os::raw::c_long, _bindgen_union_align: [u64; 4usize], } #[test] fn bindgen_test_layout_pthread_barrier_t() { assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pthread_barrier_t)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pthread_barrier_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__size as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_barrier_t), "::", stringify!(__size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__align as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_barrier_t), "::", stringify!(__align) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pthread_barrierattr_t { pub __size: [::std::os::raw::c_char; 4usize], pub __align: ::std::os::raw::c_int, _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_pthread_barrierattr_t() { assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(pthread_barrierattr_t)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pthread_barrierattr_t)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__size as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_barrierattr_t), "::", stringify!(__size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__align as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(pthread_barrierattr_t), "::", stringify!(__align) ) ); } extern "C" { pub fn random() -> ::std::os::raw::c_long; } extern "C" { pub fn srandom(__seed: ::std::os::raw::c_uint); } extern "C" { pub fn initstate( __seed: ::std::os::raw::c_uint, __statebuf: *mut ::std::os::raw::c_char, __statelen: usize, ) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn setstate(__statebuf: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct random_data { pub fptr: *mut i32, pub rptr: *mut i32, pub state: *mut i32, pub rand_type: ::std::os::raw::c_int, pub rand_deg: ::std::os::raw::c_int, pub rand_sep: ::std::os::raw::c_int, pub end_ptr: *mut i32, } #[test] fn bindgen_test_layout_random_data() { assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(random_data)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(random_data)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).fptr as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(random_data), "::", stringify!(fptr) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rptr as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(random_data), "::", stringify!(rptr) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).state as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(random_data), "::", stringify!(state) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rand_type as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(random_data), "::", stringify!(rand_type) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rand_deg as *const _ as usize }, 28usize, concat!( "Offset of field: ", stringify!(random_data), "::", stringify!(rand_deg) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rand_sep as *const _ as usize }, 32usize, concat!( "Offset of field: ", stringify!(random_data), "::", stringify!(rand_sep) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).end_ptr as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(random_data), "::", stringify!(end_ptr) ) ); } extern "C" { pub fn random_r(__buf: *mut random_data, __result: *mut i32) -> ::std::os::raw::c_int; } extern "C" { pub fn srandom_r( __seed: ::std::os::raw::c_uint, __buf: *mut random_data, ) -> ::std::os::raw::c_int; } extern "C" { pub fn initstate_r( __seed: ::std::os::raw::c_uint, __statebuf: *mut ::std::os::raw::c_char, __statelen: usize, __buf: *mut random_data, ) -> ::std::os::raw::c_int; } extern "C" { pub fn setstate_r( __statebuf: *mut ::std::os::raw::c_char, __buf: *mut random_data, ) -> ::std::os::raw::c_int; } extern "C" { pub fn rand() -> ::std::os::raw::c_int; } extern "C" { pub fn srand(__seed: ::std::os::raw::c_uint); } extern "C" { pub fn rand_r(__seed: *mut ::std::os::raw::c_uint) -> ::std::os::raw::c_int; } extern "C" { pub fn drand48() -> f64; } extern "C" { pub fn erand48(__xsubi: *mut ::std::os::raw::c_ushort) -> f64; } extern "C" { pub fn lrand48() -> ::std::os::raw::c_long; } extern "C" { pub fn nrand48(__xsubi: *mut ::std::os::raw::c_ushort) -> ::std::os::raw::c_long; } extern "C" { pub fn mrand48() -> ::std::os::raw::c_long; } extern "C" { pub fn jrand48(__xsubi: *mut ::std::os::raw::c_ushort) -> ::std::os::raw::c_long; } extern "C" { pub fn srand48(__seedval: ::std::os::raw::c_long); } extern "C" { pub fn seed48(__seed16v: *mut ::std::os::raw::c_ushort) -> *mut ::std::os::raw::c_ushort; } extern "C" { pub fn lcong48(__param: *mut ::std::os::raw::c_ushort); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct drand48_data { pub __x: [::std::os::raw::c_ushort; 3usize], pub __old_x: [::std::os::raw::c_ushort; 3usize], pub __c: ::std::os::raw::c_ushort, pub __init: ::std::os::raw::c_ushort, pub __a: ::std::os::raw::c_ulonglong, } #[test] fn bindgen_test_layout_drand48_data() { assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(drand48_data)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(drand48_data)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__x as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(drand48_data), "::", stringify!(__x) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__old_x as *const _ as usize }, 6usize, concat!( "Offset of field: ", stringify!(drand48_data), "::", stringify!(__old_x) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__c as *const _ as usize }, 12usize, concat!( "Offset of field: ", stringify!(drand48_data), "::", stringify!(__c) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__init as *const _ as usize }, 14usize, concat!( "Offset of field: ", stringify!(drand48_data), "::", stringify!(__init) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).__a as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(drand48_data), "::", stringify!(__a) ) ); } extern "C" { pub fn drand48_r(__buffer: *mut drand48_data, __result: *mut f64) -> ::std::os::raw::c_int; } extern "C" { pub fn erand48_r( __xsubi: *mut ::std::os::raw::c_ushort, __buffer: *mut drand48_data, __result: *mut f64, ) -> ::std::os::raw::c_int; } extern "C" { pub fn lrand48_r( __buffer: *mut drand48_data, __result: *mut ::std::os::raw::c_long, ) -> ::std::os::raw::c_int; } extern "C" { pub fn nrand48_r( __xsubi: *mut ::std::os::raw::c_ushort, __buffer: *mut drand48_data, __result: *mut ::std::os::raw::c_long, ) -> ::std::os::raw::c_int; } extern "C" { pub fn mrand48_r( __buffer: *mut drand48_data, __result: *mut ::std::os::raw::c_long, ) -> ::std::os::raw::c_int; } extern "C" { pub fn jrand48_r( __xsubi: *mut ::std::os::raw::c_ushort, __buffer: *mut drand48_data, __result: *mut ::std::os::raw::c_long, ) -> ::std::os::raw::c_int; } extern "C" { pub fn srand48_r( __seedval: ::std::os::raw::c_long, __buffer: *mut drand48_data, ) -> ::std::os::raw::c_int; } extern "C" { pub fn seed48_r( __seed16v: *mut ::std::os::raw::c_ushort, __buffer: *mut drand48_data, ) -> ::std::os::raw::c_int; } extern "C" { pub fn lcong48_r( __param: *mut ::std::os::raw::c_ushort, __buffer: *mut drand48_data, ) -> ::std::os::raw::c_int; } extern "C" { pub fn malloc(__size: usize) -> *mut ::std::os::raw::c_void; } extern "C" { pub fn calloc(__nmemb: usize, __size: usize) -> *mut ::std::os::raw::c_void; } extern "C" { pub fn realloc( __ptr: *mut ::std::os::raw::c_void, __size: usize, ) -> *mut ::std::os::raw::c_void; } extern "C" { pub fn free(__ptr: *mut ::std::os::raw::c_void); } extern "C" { pub fn cfree(__ptr: *mut ::std::os::raw::c_void); } extern "C" { pub fn alloca(__size: usize) -> *mut ::std::os::raw::c_void; } extern "C" { pub fn valloc(__size: usize) -> *mut ::std::os::raw::c_void; } extern "C" { pub fn posix_memalign( __memptr: *mut *mut ::std::os::raw::c_void, __alignment: usize, __size: usize, ) -> ::std::os::raw::c_int; } extern "C" { pub fn aligned_alloc(__alignment: usize, __size: usize) -> *mut ::std::os::raw::c_void; } extern "C" { pub fn abort(); } extern "C" { pub fn atexit(__func: ::std::option::Option) -> ::std::os::raw::c_int; } extern "C" { pub fn at_quick_exit( __func: ::std::option::Option, ) -> ::std::os::raw::c_int; } extern "C" { pub fn on_exit( __func: ::std::option::Option< unsafe extern "C" fn( __status: ::std::os::raw::c_int, __arg: *mut ::std::os::raw::c_void, ), >, __arg: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } extern "C" { pub fn exit(__status: ::std::os::raw::c_int); } extern "C" { pub fn quick_exit(__status: ::std::os::raw::c_int); } extern "C" { pub fn _Exit(__status: ::std::os::raw::c_int); } extern "C" { pub fn getenv(__name: *const ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn putenv(__string: *mut ::std::os::raw::c_char) -> ::std::os::raw::c_int; } extern "C" { pub fn setenv( __name: *const ::std::os::raw::c_char, __value: *const ::std::os::raw::c_char, __replace: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } extern "C" { pub fn unsetenv(__name: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; } extern "C" { pub fn clearenv() -> ::std::os::raw::c_int; } extern "C" { pub fn mktemp(__template: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn mkstemp(__template: *mut ::std::os::raw::c_char) -> ::std::os::raw::c_int; } extern "C" { pub fn mkstemps( __template: *mut ::std::os::raw::c_char, __suffixlen: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } extern "C" { pub fn mkdtemp(__template: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn system(__command: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; } extern "C" { pub fn realpath( __name: *const ::std::os::raw::c_char, __resolved: *mut ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_char; } pub type __compar_fn_t = ::std::option::Option< unsafe extern "C" fn(arg1: *const ::std::os::raw::c_void, arg2: *const ::std::os::raw::c_void) -> ::std::os::raw::c_int, >; extern "C" { pub fn bsearch( __key: *const ::std::os::raw::c_void, __base: *const ::std::os::raw::c_void, __nmemb: usize, __size: usize, __compar: __compar_fn_t, ) -> *mut ::std::os::raw::c_void; } extern "C" { pub fn qsort( __base: *mut ::std::os::raw::c_void, __nmemb: usize, __size: usize, __compar: __compar_fn_t, ); } extern "C" { pub fn abs(__x: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } extern "C" { pub fn labs(__x: ::std::os::raw::c_long) -> ::std::os::raw::c_long; } extern "C" { pub fn llabs(__x: ::std::os::raw::c_longlong) -> ::std::os::raw::c_longlong; } extern "C" { pub fn div(__numer: ::std::os::raw::c_int, __denom: ::std::os::raw::c_int) -> div_t; } extern "C" { pub fn ldiv(__numer: ::std::os::raw::c_long, __denom: ::std::os::raw::c_long) -> ldiv_t; } extern "C" { pub fn lldiv( __numer: ::std::os::raw::c_longlong, __denom: ::std::os::raw::c_longlong, ) -> lldiv_t; } extern "C" { pub fn ecvt( __value: f64, __ndigit: ::std::os::raw::c_int, __decpt: *mut ::std::os::raw::c_int, __sign: *mut ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn fcvt( __value: f64, __ndigit: ::std::os::raw::c_int, __decpt: *mut ::std::os::raw::c_int, __sign: *mut ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn gcvt( __value: f64, __ndigit: ::std::os::raw::c_int, __buf: *mut ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn qecvt( __value: f64, __ndigit: ::std::os::raw::c_int, __decpt: *mut ::std::os::raw::c_int, __sign: *mut ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn qfcvt( __value: f64, __ndigit: ::std::os::raw::c_int, __decpt: *mut ::std::os::raw::c_int, __sign: *mut ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn qgcvt( __value: f64, __ndigit: ::std::os::raw::c_int, __buf: *mut ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_char; } extern "C" { pub fn ecvt_r( __value: f64, __ndigit: ::std::os::raw::c_int, __decpt: *mut ::std::os::raw::c_int, __sign: *mut ::std::os::raw::c_int, __buf: *mut ::std::os::raw::c_char, __len: usize, ) -> ::std::os::raw::c_int; } extern "C" { pub fn fcvt_r( __value: f64, __ndigit: ::std::os::raw::c_int, __decpt: *mut ::std::os::raw::c_int, __sign: *mut ::std::os::raw::c_int, __buf: *mut ::std::os::raw::c_char, __len: usize, ) -> ::std::os::raw::c_int; } extern "C" { pub fn qecvt_r( __value: f64, __ndigit: ::std::os::raw::c_int, __decpt: *mut ::std::os::raw::c_int, __sign: *mut ::std::os::raw::c_int, __buf: *mut ::std::os::raw::c_char, __len: usize, ) -> ::std::os::raw::c_int; } extern "C" { pub fn qfcvt_r( __value: f64, __ndigit: ::std::os::raw::c_int, __decpt: *mut ::std::os::raw::c_int, __sign: *mut ::std::os::raw::c_int, __buf: *mut ::std::os::raw::c_char, __len: usize, ) -> ::std::os::raw::c_int; } extern "C" { pub fn mblen(__s: *const ::std::os::raw::c_char, __n: usize) -> ::std::os::raw::c_int; } extern "C" { pub fn mbtowc( __pwc: *mut wchar_t, __s: *const ::std::os::raw::c_char, __n: usize, ) -> ::std::os::raw::c_int; } extern "C" { pub fn wctomb(__s: *mut ::std::os::raw::c_char, __wchar: wchar_t) -> ::std::os::raw::c_int; } extern "C" { pub fn mbstowcs(__pwcs: *mut wchar_t, __s: *const ::std::os::raw::c_char, __n: usize) -> usize; } extern "C" { pub fn wcstombs(__s: *mut ::std::os::raw::c_char, __pwcs: *const wchar_t, __n: usize) -> usize; } extern "C" { pub fn rpmatch(__response: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; } extern "C" { pub fn getsubopt( __optionp: *mut *mut ::std::os::raw::c_char, __tokens: *const *const ::std::os::raw::c_char, __valuep: *mut *mut ::std::os::raw::c_char, ) -> ::std::os::raw::c_int; } extern "C" { pub fn getloadavg(__loadavg: *mut f64, __nelem: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } /// * /// Digital audio interface * /// * #[repr(C)] #[derive(Copy, Clone)] pub struct snd_aes_iec958 { pub status: [::std::os::raw::c_uchar; 24usize], pub subcode: [::std::os::raw::c_uchar; 147usize], pub pad: ::std::os::raw::c_uchar, pub dig_subframe: [::std::os::raw::c_uchar; 4usize], } #[test] fn bindgen_test_layout_snd_aes_iec958() { assert_eq!( ::std::mem::size_of::(), 176usize, concat!("Size of: ", stringify!(snd_aes_iec958)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(snd_aes_iec958)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).status as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_aes_iec958), "::", stringify!(status) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subcode as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_aes_iec958), "::", stringify!(subcode) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).pad as *const _ as usize }, 171usize, concat!( "Offset of field: ", stringify!(snd_aes_iec958), "::", stringify!(pad) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).dig_subframe as *const _ as usize }, 172usize, concat!( "Offset of field: ", stringify!(snd_aes_iec958), "::", stringify!(dig_subframe) ) ); } /// * /// CEA-861 Audio InfoFrame. Used in HDMI and DisplayPort * /// * #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_cea_861_aud_if { pub db1_ct_cc: ::std::os::raw::c_uchar, pub db2_sf_ss: ::std::os::raw::c_uchar, pub db3: ::std::os::raw::c_uchar, pub db4_ca: ::std::os::raw::c_uchar, pub db5_dminh_lsv: ::std::os::raw::c_uchar, } #[test] fn bindgen_test_layout_snd_cea_861_aud_if() { assert_eq!( ::std::mem::size_of::(), 5usize, concat!("Size of: ", stringify!(snd_cea_861_aud_if)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(snd_cea_861_aud_if)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).db1_ct_cc as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_cea_861_aud_if), "::", stringify!(db1_ct_cc) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).db2_sf_ss as *const _ as usize }, 1usize, concat!( "Offset of field: ", stringify!(snd_cea_861_aud_if), "::", stringify!(db2_sf_ss) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).db3 as *const _ as usize }, 2usize, concat!( "Offset of field: ", stringify!(snd_cea_861_aud_if), "::", stringify!(db3) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).db4_ca as *const _ as usize }, 3usize, concat!( "Offset of field: ", stringify!(snd_cea_861_aud_if), "::", stringify!(db4_ca) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).db5_dminh_lsv as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_cea_861_aud_if), "::", stringify!(db5_dminh_lsv) ) ); } pub const SNDRV_HWDEP_IFACE_OPL2: _bindgen_ty_1 = 0; pub const SNDRV_HWDEP_IFACE_OPL3: _bindgen_ty_1 = 1; pub const SNDRV_HWDEP_IFACE_OPL4: _bindgen_ty_1 = 2; pub const SNDRV_HWDEP_IFACE_SB16CSP: _bindgen_ty_1 = 3; pub const SNDRV_HWDEP_IFACE_EMU10K1: _bindgen_ty_1 = 4; pub const SNDRV_HWDEP_IFACE_YSS225: _bindgen_ty_1 = 5; pub const SNDRV_HWDEP_IFACE_ICS2115: _bindgen_ty_1 = 6; pub const SNDRV_HWDEP_IFACE_SSCAPE: _bindgen_ty_1 = 7; pub const SNDRV_HWDEP_IFACE_VX: _bindgen_ty_1 = 8; pub const SNDRV_HWDEP_IFACE_MIXART: _bindgen_ty_1 = 9; pub const SNDRV_HWDEP_IFACE_USX2Y: _bindgen_ty_1 = 10; pub const SNDRV_HWDEP_IFACE_EMUX_WAVETABLE: _bindgen_ty_1 = 11; pub const SNDRV_HWDEP_IFACE_BLUETOOTH: _bindgen_ty_1 = 12; pub const SNDRV_HWDEP_IFACE_USX2Y_PCM: _bindgen_ty_1 = 13; pub const SNDRV_HWDEP_IFACE_PCXHR: _bindgen_ty_1 = 14; pub const SNDRV_HWDEP_IFACE_SB_RC: _bindgen_ty_1 = 15; pub const SNDRV_HWDEP_IFACE_HDA: _bindgen_ty_1 = 16; pub const SNDRV_HWDEP_IFACE_USB_STREAM: _bindgen_ty_1 = 17; pub const SNDRV_HWDEP_IFACE_FW_DICE: _bindgen_ty_1 = 18; pub const SNDRV_HWDEP_IFACE_FW_FIREWORKS: _bindgen_ty_1 = 19; pub const SNDRV_HWDEP_IFACE_FW_BEBOB: _bindgen_ty_1 = 20; pub const SNDRV_HWDEP_IFACE_FW_OXFW: _bindgen_ty_1 = 21; pub const SNDRV_HWDEP_IFACE_FW_DIGI00X: _bindgen_ty_1 = 22; pub const SNDRV_HWDEP_IFACE_FW_TASCAM: _bindgen_ty_1 = 23; pub const SNDRV_HWDEP_IFACE_LINE6: _bindgen_ty_1 = 24; pub const SNDRV_HWDEP_IFACE_FW_MOTU: _bindgen_ty_1 = 25; pub const SNDRV_HWDEP_IFACE_FW_FIREFACE: _bindgen_ty_1 = 26; pub const SNDRV_HWDEP_IFACE_LAST: _bindgen_ty_1 = 26; pub type _bindgen_ty_1 = u32; #[repr(C)] #[derive(Copy, Clone)] pub struct snd_hwdep_info { pub device: ::std::os::raw::c_uint, pub card: ::std::os::raw::c_int, pub id: [::std::os::raw::c_uchar; 64usize], pub name: [::std::os::raw::c_uchar; 80usize], pub iface: ::std::os::raw::c_int, pub reserved: [::std::os::raw::c_uchar; 64usize], } #[test] fn bindgen_test_layout_snd_hwdep_info() { assert_eq!( ::std::mem::size_of::(), 220usize, concat!("Size of: ", stringify!(snd_hwdep_info)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_hwdep_info)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).device as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_hwdep_info), "::", stringify!(device) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).card as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_hwdep_info), "::", stringify!(card) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_hwdep_info), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_hwdep_info), "::", stringify!(name) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).iface as *const _ as usize }, 152usize, concat!( "Offset of field: ", stringify!(snd_hwdep_info), "::", stringify!(iface) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 156usize, concat!( "Offset of field: ", stringify!(snd_hwdep_info), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_hwdep_dsp_status { pub version: ::std::os::raw::c_uint, pub id: [::std::os::raw::c_uchar; 32usize], pub num_dsps: ::std::os::raw::c_uint, pub dsp_loaded: ::std::os::raw::c_uint, pub chip_ready: ::std::os::raw::c_uint, pub reserved: [::std::os::raw::c_uchar; 16usize], } #[test] fn bindgen_test_layout_snd_hwdep_dsp_status() { assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(snd_hwdep_dsp_status)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_hwdep_dsp_status)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).version as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_status), "::", stringify!(version) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_status), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).num_dsps as *const _ as usize }, 36usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_status), "::", stringify!(num_dsps) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).dsp_loaded as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_status), "::", stringify!(dsp_loaded) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).chip_ready as *const _ as usize }, 44usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_status), "::", stringify!(chip_ready) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 48usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_status), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_hwdep_dsp_image { pub index: ::std::os::raw::c_uint, pub name: [::std::os::raw::c_uchar; 64usize], pub image: *mut ::std::os::raw::c_uchar, pub length: usize, pub driver_data: ::std::os::raw::c_ulong, } #[test] fn bindgen_test_layout_snd_hwdep_dsp_image() { assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(snd_hwdep_dsp_image)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_hwdep_dsp_image)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).index as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_image), "::", stringify!(index) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_image), "::", stringify!(name) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).image as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_image), "::", stringify!(image) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).length as *const _ as usize }, 80usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_image), "::", stringify!(length) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).driver_data as *const _ as usize }, 88usize, concat!( "Offset of field: ", stringify!(snd_hwdep_dsp_image), "::", stringify!(driver_data) ) ); } pub type snd_pcm_uframes_t = ::std::os::raw::c_ulong; pub type snd_pcm_sframes_t = ::std::os::raw::c_long; pub const SNDRV_PCM_CLASS_GENERIC: _bindgen_ty_2 = 0; pub const SNDRV_PCM_CLASS_MULTI: _bindgen_ty_2 = 1; pub const SNDRV_PCM_CLASS_MODEM: _bindgen_ty_2 = 2; pub const SNDRV_PCM_CLASS_DIGITIZER: _bindgen_ty_2 = 3; pub const SNDRV_PCM_CLASS_LAST: _bindgen_ty_2 = 3; pub type _bindgen_ty_2 = u32; pub const SNDRV_PCM_SUBCLASS_GENERIC_MIX: _bindgen_ty_3 = 0; pub const SNDRV_PCM_SUBCLASS_MULTI_MIX: _bindgen_ty_3 = 1; pub const SNDRV_PCM_SUBCLASS_LAST: _bindgen_ty_3 = 1; pub type _bindgen_ty_3 = u32; pub const SNDRV_PCM_STREAM_PLAYBACK: _bindgen_ty_4 = 0; pub const SNDRV_PCM_STREAM_CAPTURE: _bindgen_ty_4 = 1; pub const SNDRV_PCM_STREAM_LAST: _bindgen_ty_4 = 1; pub type _bindgen_ty_4 = u32; pub type snd_pcm_access_t = ::std::os::raw::c_int; pub type snd_pcm_format_t = ::std::os::raw::c_int; pub type snd_pcm_subformat_t = ::std::os::raw::c_int; pub type snd_pcm_state_t = ::std::os::raw::c_int; pub const SNDRV_PCM_MMAP_OFFSET_DATA: _bindgen_ty_5 = 0; pub const SNDRV_PCM_MMAP_OFFSET_STATUS: _bindgen_ty_5 = 2147483648; pub const SNDRV_PCM_MMAP_OFFSET_CONTROL: _bindgen_ty_5 = 2164260864; pub type _bindgen_ty_5 = u32; #[repr(C)] #[derive(Copy, Clone)] pub union snd_pcm_sync_id { pub id: [::std::os::raw::c_uchar; 16usize], pub id16: [::std::os::raw::c_ushort; 8usize], pub id32: [::std::os::raw::c_uint; 4usize], _bindgen_union_align: [u32; 4usize], } #[test] fn bindgen_test_layout_snd_pcm_sync_id() { assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(snd_pcm_sync_id)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_pcm_sync_id)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_id), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id16 as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_id), "::", stringify!(id16) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id32 as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_id), "::", stringify!(id32) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_pcm_info { pub device: ::std::os::raw::c_uint, pub subdevice: ::std::os::raw::c_uint, pub stream: ::std::os::raw::c_int, pub card: ::std::os::raw::c_int, pub id: [::std::os::raw::c_uchar; 64usize], pub name: [::std::os::raw::c_uchar; 80usize], pub subname: [::std::os::raw::c_uchar; 32usize], pub dev_class: ::std::os::raw::c_int, pub dev_subclass: ::std::os::raw::c_int, pub subdevices_count: ::std::os::raw::c_uint, pub subdevices_avail: ::std::os::raw::c_uint, pub sync: snd_pcm_sync_id, pub reserved: [::std::os::raw::c_uchar; 64usize], } #[test] fn bindgen_test_layout_snd_pcm_info() { assert_eq!( ::std::mem::size_of::(), 288usize, concat!("Size of: ", stringify!(snd_pcm_info)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_pcm_info)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).device as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(device) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subdevice as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(subdevice) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).stream as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(stream) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).card as *const _ as usize }, 12usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(card) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, 80usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(name) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subname as *const _ as usize }, 160usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(subname) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).dev_class as *const _ as usize }, 192usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(dev_class) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).dev_subclass as *const _ as usize }, 196usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(dev_subclass) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subdevices_count as *const _ as usize }, 200usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(subdevices_count) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subdevices_avail as *const _ as usize }, 204usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(subdevices_avail) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).sync as *const _ as usize }, 208usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(sync) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 224usize, concat!( "Offset of field: ", stringify!(snd_pcm_info), "::", stringify!(reserved) ) ); } pub type snd_pcm_hw_param_t = ::std::os::raw::c_int; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_interval { pub min: ::std::os::raw::c_uint, pub max: ::std::os::raw::c_uint, pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, pub __bindgen_padding_0: [u8; 3usize], } #[test] fn bindgen_test_layout_snd_interval() { assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(snd_interval)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_interval)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).min as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_interval), "::", stringify!(min) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).max as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_interval), "::", stringify!(max) ) ); } impl snd_interval { #[inline] pub fn openmin(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } } #[inline] pub fn set_openmin(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] pub fn openmax(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } } #[inline] pub fn set_openmax(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(1usize, 1u8, val as u64) } } #[inline] pub fn integer(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) } } #[inline] pub fn set_integer(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(2usize, 1u8, val as u64) } } #[inline] pub fn empty(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u32) } } #[inline] pub fn set_empty(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(3usize, 1u8, val as u64) } } #[inline] pub fn new_bitfield_1( openmin: ::std::os::raw::c_uint, openmax: ::std::os::raw::c_uint, integer: ::std::os::raw::c_uint, empty: ::std::os::raw::c_uint, ) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { let openmin: u32 = unsafe { ::std::mem::transmute(openmin) }; openmin as u64 }); __bindgen_bitfield_unit.set(1usize, 1u8, { let openmax: u32 = unsafe { ::std::mem::transmute(openmax) }; openmax as u64 }); __bindgen_bitfield_unit.set(2usize, 1u8, { let integer: u32 = unsafe { ::std::mem::transmute(integer) }; integer as u64 }); __bindgen_bitfield_unit.set(3usize, 1u8, { let empty: u32 = unsafe { ::std::mem::transmute(empty) }; empty as u64 }); __bindgen_bitfield_unit } } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_mask { pub bits: [__u32; 8usize], } #[test] fn bindgen_test_layout_snd_mask() { assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(snd_mask)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_mask)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).bits as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_mask), "::", stringify!(bits) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_pcm_hw_params { pub flags: ::std::os::raw::c_uint, pub masks: [snd_mask; 3usize], pub mres: [snd_mask; 5usize], pub intervals: [snd_interval; 12usize], pub ires: [snd_interval; 9usize], pub rmask: ::std::os::raw::c_uint, pub cmask: ::std::os::raw::c_uint, pub info: ::std::os::raw::c_uint, pub msbits: ::std::os::raw::c_uint, pub rate_num: ::std::os::raw::c_uint, pub rate_den: ::std::os::raw::c_uint, pub fifo_size: snd_pcm_uframes_t, pub reserved: [::std::os::raw::c_uchar; 64usize], } #[test] fn bindgen_test_layout_snd_pcm_hw_params() { assert_eq!( ::std::mem::size_of::(), 608usize, concat!("Size of: ", stringify!(snd_pcm_hw_params)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_pcm_hw_params)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(flags) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).masks as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(masks) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).mres as *const _ as usize }, 100usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(mres) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).intervals as *const _ as usize }, 260usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(intervals) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).ires as *const _ as usize }, 404usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(ires) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rmask as *const _ as usize }, 512usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(rmask) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).cmask as *const _ as usize }, 516usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(cmask) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).info as *const _ as usize }, 520usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(info) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).msbits as *const _ as usize }, 524usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(msbits) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rate_num as *const _ as usize }, 528usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(rate_num) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).rate_den as *const _ as usize }, 532usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(rate_den) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).fifo_size as *const _ as usize }, 536usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(fifo_size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 544usize, concat!( "Offset of field: ", stringify!(snd_pcm_hw_params), "::", stringify!(reserved) ) ); } pub const SNDRV_PCM_TSTAMP_NONE: _bindgen_ty_6 = 0; pub const SNDRV_PCM_TSTAMP_ENABLE: _bindgen_ty_6 = 1; pub const SNDRV_PCM_TSTAMP_LAST: _bindgen_ty_6 = 1; pub type _bindgen_ty_6 = u32; #[repr(C)] #[derive(Copy, Clone)] pub struct snd_pcm_sw_params { pub tstamp_mode: ::std::os::raw::c_int, pub period_step: ::std::os::raw::c_uint, pub sleep_min: ::std::os::raw::c_uint, pub avail_min: snd_pcm_uframes_t, pub xfer_align: snd_pcm_uframes_t, pub start_threshold: snd_pcm_uframes_t, pub stop_threshold: snd_pcm_uframes_t, pub silence_threshold: snd_pcm_uframes_t, pub silence_size: snd_pcm_uframes_t, pub boundary: snd_pcm_uframes_t, pub proto: ::std::os::raw::c_uint, pub tstamp_type: ::std::os::raw::c_uint, pub reserved: [::std::os::raw::c_uchar; 56usize], } #[test] fn bindgen_test_layout_snd_pcm_sw_params() { assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(snd_pcm_sw_params)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_pcm_sw_params)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tstamp_mode as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(tstamp_mode) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).period_step as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(period_step) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).sleep_min as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(sleep_min) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).avail_min as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(avail_min) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).xfer_align as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(xfer_align) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).start_threshold as *const _ as usize }, 32usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(start_threshold) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).stop_threshold as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(stop_threshold) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).silence_threshold as *const _ as usize }, 48usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(silence_threshold) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).silence_size as *const _ as usize }, 56usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(silence_size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).boundary as *const _ as usize }, 64usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(boundary) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).proto as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(proto) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tstamp_type as *const _ as usize }, 76usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(tstamp_type) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 80usize, concat!( "Offset of field: ", stringify!(snd_pcm_sw_params), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_pcm_channel_info { pub channel: ::std::os::raw::c_uint, pub offset: __kernel_off_t, pub first: ::std::os::raw::c_uint, pub step: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_snd_pcm_channel_info() { assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(snd_pcm_channel_info)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_pcm_channel_info)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).channel as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_channel_info), "::", stringify!(channel) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).offset as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_pcm_channel_info), "::", stringify!(offset) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).first as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_pcm_channel_info), "::", stringify!(first) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).step as *const _ as usize }, 20usize, concat!( "Offset of field: ", stringify!(snd_pcm_channel_info), "::", stringify!(step) ) ); } pub const SNDRV_PCM_AUDIO_TSTAMP_TYPE_COMPAT: _bindgen_ty_7 = 0; pub const SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT: _bindgen_ty_7 = 1; pub const SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK: _bindgen_ty_7 = 2; pub const SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE: _bindgen_ty_7 = 3; pub const SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED: _bindgen_ty_7 = 4; pub const SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED: _bindgen_ty_7 = 5; pub const SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST: _bindgen_ty_7 = 5; pub type _bindgen_ty_7 = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_pcm_status { pub state: snd_pcm_state_t, pub trigger_tstamp: timespec, pub tstamp: timespec, pub appl_ptr: snd_pcm_uframes_t, pub hw_ptr: snd_pcm_uframes_t, pub delay: snd_pcm_sframes_t, pub avail: snd_pcm_uframes_t, pub avail_max: snd_pcm_uframes_t, pub overrange: snd_pcm_uframes_t, pub suspended_state: snd_pcm_state_t, pub audio_tstamp_data: __u32, pub audio_tstamp: timespec, pub driver_tstamp: timespec, pub audio_tstamp_accuracy: __u32, pub reserved: [::std::os::raw::c_uchar; 20usize], } #[test] fn bindgen_test_layout_snd_pcm_status() { assert_eq!( ::std::mem::size_of::(), 152usize, concat!("Size of: ", stringify!(snd_pcm_status)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_pcm_status)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).state as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(state) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).trigger_tstamp as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(trigger_tstamp) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tstamp as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(tstamp) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).appl_ptr as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(appl_ptr) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).hw_ptr as *const _ as usize }, 48usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(hw_ptr) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).delay as *const _ as usize }, 56usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(delay) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).avail as *const _ as usize }, 64usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(avail) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).avail_max as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(avail_max) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).overrange as *const _ as usize }, 80usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(overrange) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).suspended_state as *const _ as usize }, 88usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(suspended_state) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).audio_tstamp_data as *const _ as usize }, 92usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(audio_tstamp_data) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).audio_tstamp as *const _ as usize }, 96usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(audio_tstamp) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).driver_tstamp as *const _ as usize }, 112usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(driver_tstamp) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).audio_tstamp_accuracy as *const _ as usize }, 128usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(audio_tstamp_accuracy) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 132usize, concat!( "Offset of field: ", stringify!(snd_pcm_status), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_pcm_mmap_status { pub state: snd_pcm_state_t, pub pad1: ::std::os::raw::c_int, pub hw_ptr: snd_pcm_uframes_t, pub tstamp: timespec, pub suspended_state: snd_pcm_state_t, pub audio_tstamp: timespec, } #[test] fn bindgen_test_layout_snd_pcm_mmap_status() { assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(snd_pcm_mmap_status)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_pcm_mmap_status)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).state as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_mmap_status), "::", stringify!(state) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).pad1 as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_pcm_mmap_status), "::", stringify!(pad1) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).hw_ptr as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_pcm_mmap_status), "::", stringify!(hw_ptr) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tstamp as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_pcm_mmap_status), "::", stringify!(tstamp) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).suspended_state as *const _ as usize }, 32usize, concat!( "Offset of field: ", stringify!(snd_pcm_mmap_status), "::", stringify!(suspended_state) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).audio_tstamp as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(snd_pcm_mmap_status), "::", stringify!(audio_tstamp) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_pcm_mmap_control { pub appl_ptr: snd_pcm_uframes_t, pub avail_min: snd_pcm_uframes_t, } #[test] fn bindgen_test_layout_snd_pcm_mmap_control() { assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(snd_pcm_mmap_control)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_pcm_mmap_control)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).appl_ptr as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_mmap_control), "::", stringify!(appl_ptr) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).avail_min as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_pcm_mmap_control), "::", stringify!(avail_min) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_pcm_sync_ptr { pub flags: ::std::os::raw::c_uint, pub s: snd_pcm_sync_ptr__bindgen_ty_1, pub c: snd_pcm_sync_ptr__bindgen_ty_2, } #[repr(C)] #[derive(Copy, Clone)] pub union snd_pcm_sync_ptr__bindgen_ty_1 { pub status: snd_pcm_mmap_status, pub reserved: [::std::os::raw::c_uchar; 64usize], _bindgen_union_align: [u64; 8usize], } #[test] fn bindgen_test_layout_snd_pcm_sync_ptr__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(snd_pcm_sync_ptr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_pcm_sync_ptr__bindgen_ty_1)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).status as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_ptr__bindgen_ty_1), "::", stringify!(status) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_ptr__bindgen_ty_1), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union snd_pcm_sync_ptr__bindgen_ty_2 { pub control: snd_pcm_mmap_control, pub reserved: [::std::os::raw::c_uchar; 64usize], _bindgen_union_align: [u64; 8usize], } #[test] fn bindgen_test_layout_snd_pcm_sync_ptr__bindgen_ty_2() { assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(snd_pcm_sync_ptr__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_pcm_sync_ptr__bindgen_ty_2)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).control as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_ptr__bindgen_ty_2), "::", stringify!(control) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_ptr__bindgen_ty_2), "::", stringify!(reserved) ) ); } #[test] fn bindgen_test_layout_snd_pcm_sync_ptr() { assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(snd_pcm_sync_ptr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_pcm_sync_ptr)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_ptr), "::", stringify!(flags) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).s as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_ptr), "::", stringify!(s) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).c as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_pcm_sync_ptr), "::", stringify!(c) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_xferi { pub result: snd_pcm_sframes_t, pub buf: *mut ::std::os::raw::c_void, pub frames: snd_pcm_uframes_t, } #[test] fn bindgen_test_layout_snd_xferi() { assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(snd_xferi)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_xferi)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).result as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_xferi), "::", stringify!(result) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).buf as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_xferi), "::", stringify!(buf) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).frames as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_xferi), "::", stringify!(frames) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_xfern { pub result: snd_pcm_sframes_t, pub bufs: *mut *mut ::std::os::raw::c_void, pub frames: snd_pcm_uframes_t, } #[test] fn bindgen_test_layout_snd_xfern() { assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(snd_xfern)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_xfern)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).result as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_xfern), "::", stringify!(result) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).bufs as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_xfern), "::", stringify!(bufs) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).frames as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_xfern), "::", stringify!(frames) ) ); } pub const SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY: _bindgen_ty_8 = 0; pub const SNDRV_PCM_TSTAMP_TYPE_MONOTONIC: _bindgen_ty_8 = 1; pub const SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW: _bindgen_ty_8 = 2; pub const SNDRV_PCM_TSTAMP_TYPE_LAST: _bindgen_ty_8 = 2; pub type _bindgen_ty_8 = u32; pub const SNDRV_CHMAP_UNKNOWN: _bindgen_ty_9 = 0; pub const SNDRV_CHMAP_NA: _bindgen_ty_9 = 1; pub const SNDRV_CHMAP_MONO: _bindgen_ty_9 = 2; pub const SNDRV_CHMAP_FL: _bindgen_ty_9 = 3; pub const SNDRV_CHMAP_FR: _bindgen_ty_9 = 4; pub const SNDRV_CHMAP_RL: _bindgen_ty_9 = 5; pub const SNDRV_CHMAP_RR: _bindgen_ty_9 = 6; pub const SNDRV_CHMAP_FC: _bindgen_ty_9 = 7; pub const SNDRV_CHMAP_LFE: _bindgen_ty_9 = 8; pub const SNDRV_CHMAP_SL: _bindgen_ty_9 = 9; pub const SNDRV_CHMAP_SR: _bindgen_ty_9 = 10; pub const SNDRV_CHMAP_RC: _bindgen_ty_9 = 11; pub const SNDRV_CHMAP_FLC: _bindgen_ty_9 = 12; pub const SNDRV_CHMAP_FRC: _bindgen_ty_9 = 13; pub const SNDRV_CHMAP_RLC: _bindgen_ty_9 = 14; pub const SNDRV_CHMAP_RRC: _bindgen_ty_9 = 15; pub const SNDRV_CHMAP_FLW: _bindgen_ty_9 = 16; pub const SNDRV_CHMAP_FRW: _bindgen_ty_9 = 17; pub const SNDRV_CHMAP_FLH: _bindgen_ty_9 = 18; pub const SNDRV_CHMAP_FCH: _bindgen_ty_9 = 19; pub const SNDRV_CHMAP_FRH: _bindgen_ty_9 = 20; pub const SNDRV_CHMAP_TC: _bindgen_ty_9 = 21; pub const SNDRV_CHMAP_TFL: _bindgen_ty_9 = 22; pub const SNDRV_CHMAP_TFR: _bindgen_ty_9 = 23; pub const SNDRV_CHMAP_TFC: _bindgen_ty_9 = 24; pub const SNDRV_CHMAP_TRL: _bindgen_ty_9 = 25; pub const SNDRV_CHMAP_TRR: _bindgen_ty_9 = 26; pub const SNDRV_CHMAP_TRC: _bindgen_ty_9 = 27; pub const SNDRV_CHMAP_TFLC: _bindgen_ty_9 = 28; pub const SNDRV_CHMAP_TFRC: _bindgen_ty_9 = 29; pub const SNDRV_CHMAP_TSL: _bindgen_ty_9 = 30; pub const SNDRV_CHMAP_TSR: _bindgen_ty_9 = 31; pub const SNDRV_CHMAP_LLFE: _bindgen_ty_9 = 32; pub const SNDRV_CHMAP_RLFE: _bindgen_ty_9 = 33; pub const SNDRV_CHMAP_BC: _bindgen_ty_9 = 34; pub const SNDRV_CHMAP_BLC: _bindgen_ty_9 = 35; pub const SNDRV_CHMAP_BRC: _bindgen_ty_9 = 36; pub const SNDRV_CHMAP_LAST: _bindgen_ty_9 = 36; pub type _bindgen_ty_9 = u32; pub const SNDRV_RAWMIDI_STREAM_OUTPUT: _bindgen_ty_10 = 0; pub const SNDRV_RAWMIDI_STREAM_INPUT: _bindgen_ty_10 = 1; pub const SNDRV_RAWMIDI_STREAM_LAST: _bindgen_ty_10 = 1; pub type _bindgen_ty_10 = u32; #[repr(C)] #[derive(Copy, Clone)] pub struct snd_rawmidi_info { pub device: ::std::os::raw::c_uint, pub subdevice: ::std::os::raw::c_uint, pub stream: ::std::os::raw::c_int, pub card: ::std::os::raw::c_int, pub flags: ::std::os::raw::c_uint, pub id: [::std::os::raw::c_uchar; 64usize], pub name: [::std::os::raw::c_uchar; 80usize], pub subname: [::std::os::raw::c_uchar; 32usize], pub subdevices_count: ::std::os::raw::c_uint, pub subdevices_avail: ::std::os::raw::c_uint, pub reserved: [::std::os::raw::c_uchar; 64usize], } #[test] fn bindgen_test_layout_snd_rawmidi_info() { assert_eq!( ::std::mem::size_of::(), 268usize, concat!("Size of: ", stringify!(snd_rawmidi_info)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_rawmidi_info)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).device as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(device) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subdevice as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(subdevice) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).stream as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(stream) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).card as *const _ as usize }, 12usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(card) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(flags) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 20usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, 84usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(name) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subname as *const _ as usize }, 164usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(subname) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subdevices_count as *const _ as usize }, 196usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(subdevices_count) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subdevices_avail as *const _ as usize }, 200usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(subdevices_avail) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 204usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_info), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_rawmidi_params { pub stream: ::std::os::raw::c_int, pub buffer_size: usize, pub avail_min: usize, pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, pub reserved: [::std::os::raw::c_uchar; 16usize], } #[test] fn bindgen_test_layout_snd_rawmidi_params() { assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(snd_rawmidi_params)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_rawmidi_params)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).stream as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_params), "::", stringify!(stream) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).buffer_size as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_params), "::", stringify!(buffer_size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).avail_min as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_params), "::", stringify!(avail_min) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 25usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_params), "::", stringify!(reserved) ) ); } impl snd_rawmidi_params { #[inline] pub fn no_active_sensing(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } } #[inline] pub fn set_no_active_sensing(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] pub fn new_bitfield_1( no_active_sensing: ::std::os::raw::c_uint, ) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { let no_active_sensing: u32 = unsafe { ::std::mem::transmute(no_active_sensing) }; no_active_sensing as u64 }); __bindgen_bitfield_unit } } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_rawmidi_status { pub stream: ::std::os::raw::c_int, pub tstamp: timespec, pub avail: usize, pub xruns: usize, pub reserved: [::std::os::raw::c_uchar; 16usize], } #[test] fn bindgen_test_layout_snd_rawmidi_status() { assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(snd_rawmidi_status)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_rawmidi_status)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).stream as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_status), "::", stringify!(stream) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tstamp as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_status), "::", stringify!(tstamp) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).avail as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_status), "::", stringify!(avail) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).xruns as *const _ as usize }, 32usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_status), "::", stringify!(xruns) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(snd_rawmidi_status), "::", stringify!(reserved) ) ); } pub const SNDRV_TIMER_CLASS_NONE: _bindgen_ty_11 = -1; pub const SNDRV_TIMER_CLASS_SLAVE: _bindgen_ty_11 = 0; pub const SNDRV_TIMER_CLASS_GLOBAL: _bindgen_ty_11 = 1; pub const SNDRV_TIMER_CLASS_CARD: _bindgen_ty_11 = 2; pub const SNDRV_TIMER_CLASS_PCM: _bindgen_ty_11 = 3; pub const SNDRV_TIMER_CLASS_LAST: _bindgen_ty_11 = 3; pub type _bindgen_ty_11 = i32; pub const SNDRV_TIMER_SCLASS_NONE: _bindgen_ty_12 = 0; pub const SNDRV_TIMER_SCLASS_APPLICATION: _bindgen_ty_12 = 1; pub const SNDRV_TIMER_SCLASS_SEQUENCER: _bindgen_ty_12 = 2; pub const SNDRV_TIMER_SCLASS_OSS_SEQUENCER: _bindgen_ty_12 = 3; pub const SNDRV_TIMER_SCLASS_LAST: _bindgen_ty_12 = 3; pub type _bindgen_ty_12 = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_timer_id { pub dev_class: ::std::os::raw::c_int, pub dev_sclass: ::std::os::raw::c_int, pub card: ::std::os::raw::c_int, pub device: ::std::os::raw::c_int, pub subdevice: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_snd_timer_id() { assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(snd_timer_id)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_timer_id)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).dev_class as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_id), "::", stringify!(dev_class) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).dev_sclass as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_timer_id), "::", stringify!(dev_sclass) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).card as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_timer_id), "::", stringify!(card) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).device as *const _ as usize }, 12usize, concat!( "Offset of field: ", stringify!(snd_timer_id), "::", stringify!(device) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subdevice as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_timer_id), "::", stringify!(subdevice) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_timer_ginfo { pub tid: snd_timer_id, pub flags: ::std::os::raw::c_uint, pub card: ::std::os::raw::c_int, pub id: [::std::os::raw::c_uchar; 64usize], pub name: [::std::os::raw::c_uchar; 80usize], pub reserved0: ::std::os::raw::c_ulong, pub resolution: ::std::os::raw::c_ulong, pub resolution_min: ::std::os::raw::c_ulong, pub resolution_max: ::std::os::raw::c_ulong, pub clients: ::std::os::raw::c_uint, pub reserved: [::std::os::raw::c_uchar; 32usize], } #[test] fn bindgen_test_layout_snd_timer_ginfo() { assert_eq!( ::std::mem::size_of::(), 248usize, concat!("Size of: ", stringify!(snd_timer_ginfo)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_timer_ginfo)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tid as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(tid) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, 20usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(flags) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).card as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(card) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 28usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, 92usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(name) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved0 as *const _ as usize }, 176usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(reserved0) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).resolution as *const _ as usize }, 184usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(resolution) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).resolution_min as *const _ as usize }, 192usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(resolution_min) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).resolution_max as *const _ as usize }, 200usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(resolution_max) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).clients as *const _ as usize }, 208usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(clients) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 212usize, concat!( "Offset of field: ", stringify!(snd_timer_ginfo), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_timer_gparams { pub tid: snd_timer_id, pub period_num: ::std::os::raw::c_ulong, pub period_den: ::std::os::raw::c_ulong, pub reserved: [::std::os::raw::c_uchar; 32usize], } #[test] fn bindgen_test_layout_snd_timer_gparams() { assert_eq!( ::std::mem::size_of::(), 72usize, concat!("Size of: ", stringify!(snd_timer_gparams)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_timer_gparams)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tid as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_gparams), "::", stringify!(tid) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).period_num as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_timer_gparams), "::", stringify!(period_num) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).period_den as *const _ as usize }, 32usize, concat!( "Offset of field: ", stringify!(snd_timer_gparams), "::", stringify!(period_den) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(snd_timer_gparams), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_timer_gstatus { pub tid: snd_timer_id, pub resolution: ::std::os::raw::c_ulong, pub resolution_num: ::std::os::raw::c_ulong, pub resolution_den: ::std::os::raw::c_ulong, pub reserved: [::std::os::raw::c_uchar; 32usize], } #[test] fn bindgen_test_layout_snd_timer_gstatus() { assert_eq!( ::std::mem::size_of::(), 80usize, concat!("Size of: ", stringify!(snd_timer_gstatus)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_timer_gstatus)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tid as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_gstatus), "::", stringify!(tid) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).resolution as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_timer_gstatus), "::", stringify!(resolution) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).resolution_num as *const _ as usize }, 32usize, concat!( "Offset of field: ", stringify!(snd_timer_gstatus), "::", stringify!(resolution_num) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).resolution_den as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(snd_timer_gstatus), "::", stringify!(resolution_den) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 48usize, concat!( "Offset of field: ", stringify!(snd_timer_gstatus), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_timer_select { pub id: snd_timer_id, pub reserved: [::std::os::raw::c_uchar; 32usize], } #[test] fn bindgen_test_layout_snd_timer_select() { assert_eq!( ::std::mem::size_of::(), 52usize, concat!("Size of: ", stringify!(snd_timer_select)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_timer_select)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_select), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 20usize, concat!( "Offset of field: ", stringify!(snd_timer_select), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_timer_info { pub flags: ::std::os::raw::c_uint, pub card: ::std::os::raw::c_int, pub id: [::std::os::raw::c_uchar; 64usize], pub name: [::std::os::raw::c_uchar; 80usize], pub reserved0: ::std::os::raw::c_ulong, pub resolution: ::std::os::raw::c_ulong, pub reserved: [::std::os::raw::c_uchar; 64usize], } #[test] fn bindgen_test_layout_snd_timer_info() { assert_eq!( ::std::mem::size_of::(), 232usize, concat!("Size of: ", stringify!(snd_timer_info)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_timer_info)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_info), "::", stringify!(flags) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).card as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_timer_info), "::", stringify!(card) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_timer_info), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_timer_info), "::", stringify!(name) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved0 as *const _ as usize }, 152usize, concat!( "Offset of field: ", stringify!(snd_timer_info), "::", stringify!(reserved0) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).resolution as *const _ as usize }, 160usize, concat!( "Offset of field: ", stringify!(snd_timer_info), "::", stringify!(resolution) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 168usize, concat!( "Offset of field: ", stringify!(snd_timer_info), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_timer_params { pub flags: ::std::os::raw::c_uint, pub ticks: ::std::os::raw::c_uint, pub queue_size: ::std::os::raw::c_uint, pub reserved0: ::std::os::raw::c_uint, pub filter: ::std::os::raw::c_uint, pub reserved: [::std::os::raw::c_uchar; 60usize], } #[test] fn bindgen_test_layout_snd_timer_params() { assert_eq!( ::std::mem::size_of::(), 80usize, concat!("Size of: ", stringify!(snd_timer_params)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_timer_params)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).flags as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_params), "::", stringify!(flags) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).ticks as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_timer_params), "::", stringify!(ticks) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).queue_size as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_timer_params), "::", stringify!(queue_size) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved0 as *const _ as usize }, 12usize, concat!( "Offset of field: ", stringify!(snd_timer_params), "::", stringify!(reserved0) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).filter as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_timer_params), "::", stringify!(filter) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 20usize, concat!( "Offset of field: ", stringify!(snd_timer_params), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_timer_status { pub tstamp: timespec, pub resolution: ::std::os::raw::c_uint, pub lost: ::std::os::raw::c_uint, pub overrun: ::std::os::raw::c_uint, pub queue: ::std::os::raw::c_uint, pub reserved: [::std::os::raw::c_uchar; 64usize], } #[test] fn bindgen_test_layout_snd_timer_status() { assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(snd_timer_status)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_timer_status)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tstamp as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_status), "::", stringify!(tstamp) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).resolution as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_timer_status), "::", stringify!(resolution) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).lost as *const _ as usize }, 20usize, concat!( "Offset of field: ", stringify!(snd_timer_status), "::", stringify!(lost) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).overrun as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_timer_status), "::", stringify!(overrun) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).queue as *const _ as usize }, 28usize, concat!( "Offset of field: ", stringify!(snd_timer_status), "::", stringify!(queue) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 32usize, concat!( "Offset of field: ", stringify!(snd_timer_status), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_timer_read { pub resolution: ::std::os::raw::c_uint, pub ticks: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_snd_timer_read() { assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(snd_timer_read)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_timer_read)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).resolution as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_read), "::", stringify!(resolution) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).ticks as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_timer_read), "::", stringify!(ticks) ) ); } pub const SNDRV_TIMER_EVENT_RESOLUTION: _bindgen_ty_13 = 0; pub const SNDRV_TIMER_EVENT_TICK: _bindgen_ty_13 = 1; pub const SNDRV_TIMER_EVENT_START: _bindgen_ty_13 = 2; pub const SNDRV_TIMER_EVENT_STOP: _bindgen_ty_13 = 3; pub const SNDRV_TIMER_EVENT_CONTINUE: _bindgen_ty_13 = 4; pub const SNDRV_TIMER_EVENT_PAUSE: _bindgen_ty_13 = 5; pub const SNDRV_TIMER_EVENT_EARLY: _bindgen_ty_13 = 6; pub const SNDRV_TIMER_EVENT_SUSPEND: _bindgen_ty_13 = 7; pub const SNDRV_TIMER_EVENT_RESUME: _bindgen_ty_13 = 8; pub const SNDRV_TIMER_EVENT_MSTART: _bindgen_ty_13 = 12; pub const SNDRV_TIMER_EVENT_MSTOP: _bindgen_ty_13 = 13; pub const SNDRV_TIMER_EVENT_MCONTINUE: _bindgen_ty_13 = 14; pub const SNDRV_TIMER_EVENT_MPAUSE: _bindgen_ty_13 = 15; pub const SNDRV_TIMER_EVENT_MSUSPEND: _bindgen_ty_13 = 17; pub const SNDRV_TIMER_EVENT_MRESUME: _bindgen_ty_13 = 18; pub type _bindgen_ty_13 = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_timer_tread { pub event: ::std::os::raw::c_int, pub tstamp: timespec, pub val: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_snd_timer_tread() { assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(snd_timer_tread)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_timer_tread)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).event as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_timer_tread), "::", stringify!(event) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tstamp as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_timer_tread), "::", stringify!(tstamp) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).val as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_timer_tread), "::", stringify!(val) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_ctl_card_info { pub card: ::std::os::raw::c_int, pub pad: ::std::os::raw::c_int, pub id: [::std::os::raw::c_uchar; 16usize], pub driver: [::std::os::raw::c_uchar; 16usize], pub name: [::std::os::raw::c_uchar; 32usize], pub longname: [::std::os::raw::c_uchar; 80usize], pub reserved_: [::std::os::raw::c_uchar; 16usize], pub mixername: [::std::os::raw::c_uchar; 80usize], pub components: [::std::os::raw::c_uchar; 128usize], } #[test] fn bindgen_test_layout_snd_ctl_card_info() { assert_eq!( ::std::mem::size_of::(), 376usize, concat!("Size of: ", stringify!(snd_ctl_card_info)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_ctl_card_info)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).card as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_card_info), "::", stringify!(card) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).pad as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_ctl_card_info), "::", stringify!(pad) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_ctl_card_info), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).driver as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_ctl_card_info), "::", stringify!(driver) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, 40usize, concat!( "Offset of field: ", stringify!(snd_ctl_card_info), "::", stringify!(name) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).longname as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_ctl_card_info), "::", stringify!(longname) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved_ as *const _ as usize }, 152usize, concat!( "Offset of field: ", stringify!(snd_ctl_card_info), "::", stringify!(reserved_) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).mixername as *const _ as usize }, 168usize, concat!( "Offset of field: ", stringify!(snd_ctl_card_info), "::", stringify!(mixername) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).components as *const _ as usize }, 248usize, concat!( "Offset of field: ", stringify!(snd_ctl_card_info), "::", stringify!(components) ) ); } pub type snd_ctl_elem_type_t = ::std::os::raw::c_int; pub type snd_ctl_elem_iface_t = ::std::os::raw::c_int; #[repr(C)] #[derive(Copy, Clone)] pub struct snd_ctl_elem_id { pub numid: ::std::os::raw::c_uint, pub iface: snd_ctl_elem_iface_t, pub device: ::std::os::raw::c_uint, pub subdevice: ::std::os::raw::c_uint, pub name: [::std::os::raw::c_uchar; 44usize], pub index: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_snd_ctl_elem_id() { assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(snd_ctl_elem_id)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_ctl_elem_id)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).numid as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_id), "::", stringify!(numid) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).iface as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_id), "::", stringify!(iface) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).device as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_id), "::", stringify!(device) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).subdevice as *const _ as usize }, 12usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_id), "::", stringify!(subdevice) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_id), "::", stringify!(name) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).index as *const _ as usize }, 60usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_id), "::", stringify!(index) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_ctl_elem_list { pub offset: ::std::os::raw::c_uint, pub space: ::std::os::raw::c_uint, pub used: ::std::os::raw::c_uint, pub count: ::std::os::raw::c_uint, pub pids: *mut snd_ctl_elem_id, pub reserved: [::std::os::raw::c_uchar; 50usize], } #[test] fn bindgen_test_layout_snd_ctl_elem_list() { assert_eq!( ::std::mem::size_of::(), 80usize, concat!("Size of: ", stringify!(snd_ctl_elem_list)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_ctl_elem_list)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).offset as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_list), "::", stringify!(offset) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).space as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_list), "::", stringify!(space) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).used as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_list), "::", stringify!(used) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).count as *const _ as usize }, 12usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_list), "::", stringify!(count) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).pids as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_list), "::", stringify!(pids) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 24usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_list), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_ctl_elem_info { pub id: snd_ctl_elem_id, pub type_: snd_ctl_elem_type_t, pub access: ::std::os::raw::c_uint, pub count: ::std::os::raw::c_uint, pub owner: __kernel_pid_t, pub value: snd_ctl_elem_info__bindgen_ty_1, pub dimen: snd_ctl_elem_info__bindgen_ty_2, pub reserved: [::std::os::raw::c_uchar; 56usize], } #[repr(C)] #[derive(Copy, Clone)] pub union snd_ctl_elem_info__bindgen_ty_1 { pub integer: snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1, pub integer64: snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2, pub enumerated: snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3, pub reserved: [::std::os::raw::c_uchar; 128usize], _bindgen_union_align: [u64; 16usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1 { pub min: ::std::os::raw::c_long, pub max: ::std::os::raw::c_long, pub step: ::std::os::raw::c_long, } #[test] fn bindgen_test_layout_snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 24usize, concat!( "Size of: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1) ) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).min as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1), "::", stringify!(min) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).max as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1), "::", stringify!(max) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).step as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1), "::", stringify!(step) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2 { pub min: ::std::os::raw::c_longlong, pub max: ::std::os::raw::c_longlong, pub step: ::std::os::raw::c_longlong, } #[test] fn bindgen_test_layout_snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2() { assert_eq!( ::std::mem::size_of::(), 24usize, concat!( "Size of: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2) ) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).min as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2), "::", stringify!(min) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).max as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2), "::", stringify!(max) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).step as *const _ as usize }, 16usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2), "::", stringify!(step) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3 { pub items: ::std::os::raw::c_uint, pub item: ::std::os::raw::c_uint, pub name: [::std::os::raw::c_char; 64usize], pub names_ptr: __u64, pub names_length: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3() { assert_eq!( ::std::mem::size_of::(), 88usize, concat!( "Size of: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3) ) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).items as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3), "::", stringify!(items) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).item as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3), "::", stringify!(item) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).name as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3), "::", stringify!(name) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).names_ptr as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3), "::", stringify!(names_ptr) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).names_length as *const _ as usize }, 80usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3), "::", stringify!(names_length) ) ); } #[test] fn bindgen_test_layout_snd_ctl_elem_info__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(snd_ctl_elem_info__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_ctl_elem_info__bindgen_ty_1)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).integer as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1), "::", stringify!(integer) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).integer64 as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1), "::", stringify!(integer64) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).enumerated as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1), "::", stringify!(enumerated) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_1), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union snd_ctl_elem_info__bindgen_ty_2 { pub d: [::std::os::raw::c_ushort; 4usize], pub d_ptr: *mut ::std::os::raw::c_ushort, _bindgen_union_align: u64, } #[test] fn bindgen_test_layout_snd_ctl_elem_info__bindgen_ty_2() { assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(snd_ctl_elem_info__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_ctl_elem_info__bindgen_ty_2)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).d as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_2), "::", stringify!(d) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).d_ptr as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info__bindgen_ty_2), "::", stringify!(d_ptr) ) ); } #[test] fn bindgen_test_layout_snd_ctl_elem_info() { assert_eq!( ::std::mem::size_of::(), 272usize, concat!("Size of: ", stringify!(snd_ctl_elem_info)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_ctl_elem_info)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).type_ as *const _ as usize }, 64usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info), "::", stringify!(type_) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).access as *const _ as usize }, 68usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info), "::", stringify!(access) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).count as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info), "::", stringify!(count) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).owner as *const _ as usize }, 76usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info), "::", stringify!(owner) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).value as *const _ as usize }, 80usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info), "::", stringify!(value) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).dimen as *const _ as usize }, 208usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info), "::", stringify!(dimen) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 216usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_info), "::", stringify!(reserved) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_ctl_elem_value { pub id: snd_ctl_elem_id, pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize], u8>, pub value: snd_ctl_elem_value__bindgen_ty_1, pub tstamp: timespec, pub reserved: [::std::os::raw::c_uchar; 112usize], } #[repr(C)] #[derive(Copy, Clone)] pub union snd_ctl_elem_value__bindgen_ty_1 { pub integer: snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1, pub integer64: snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2, pub enumerated: snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3, pub bytes: snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4, pub iec958: snd_aes_iec958, _bindgen_union_align: [u64; 128usize], } #[repr(C)] #[derive(Copy, Clone)] pub union snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1 { pub value: [::std::os::raw::c_long; 128usize], pub value_ptr: *mut ::std::os::raw::c_long, _bindgen_union_align: [u64; 128usize], } #[test] fn bindgen_test_layout_snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 1024usize, concat!( "Size of: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1) ) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).value as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1), "::", stringify!(value) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).value_ptr as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1), "::", stringify!(value_ptr) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2 { pub value: [::std::os::raw::c_longlong; 64usize], pub value_ptr: *mut ::std::os::raw::c_longlong, _bindgen_union_align: [u64; 64usize], } #[test] fn bindgen_test_layout_snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2() { assert_eq!( ::std::mem::size_of::(), 512usize, concat!( "Size of: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2) ) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).value as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2), "::", stringify!(value) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).value_ptr as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2), "::", stringify!(value_ptr) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3 { pub item: [::std::os::raw::c_uint; 128usize], pub item_ptr: *mut ::std::os::raw::c_uint, _bindgen_union_align: [u64; 64usize], } #[test] fn bindgen_test_layout_snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3() { assert_eq!( ::std::mem::size_of::(), 512usize, concat!( "Size of: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3) ) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).item as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3), "::", stringify!(item) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).item_ptr as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3), "::", stringify!(item_ptr) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4 { pub data: [::std::os::raw::c_uchar; 512usize], pub data_ptr: *mut ::std::os::raw::c_uchar, _bindgen_union_align: [u64; 64usize], } #[test] fn bindgen_test_layout_snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4() { assert_eq!( ::std::mem::size_of::(), 512usize, concat!( "Size of: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4) ) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).data as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4), "::", stringify!(data) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).data_ptr as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4), "::", stringify!(data_ptr) ) ); } #[test] fn bindgen_test_layout_snd_ctl_elem_value__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 1024usize, concat!("Size of: ", stringify!(snd_ctl_elem_value__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!( "Alignment of ", stringify!(snd_ctl_elem_value__bindgen_ty_1) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).integer as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1), "::", stringify!(integer) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).integer64 as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1), "::", stringify!(integer64) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).enumerated as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1), "::", stringify!(enumerated) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).bytes as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1), "::", stringify!(bytes) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).iec958 as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value__bindgen_ty_1), "::", stringify!(iec958) ) ); } #[test] fn bindgen_test_layout_snd_ctl_elem_value() { assert_eq!( ::std::mem::size_of::(), 1224usize, concat!("Size of: ", stringify!(snd_ctl_elem_value)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(snd_ctl_elem_value)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value), "::", stringify!(id) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).value as *const _ as usize }, 72usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value), "::", stringify!(value) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tstamp as *const _ as usize }, 1096usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value), "::", stringify!(tstamp) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).reserved as *const _ as usize }, 1112usize, concat!( "Offset of field: ", stringify!(snd_ctl_elem_value), "::", stringify!(reserved) ) ); } impl snd_ctl_elem_value { #[inline] pub fn indirect(&self) -> ::std::os::raw::c_uint { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } } #[inline] pub fn set_indirect(&mut self, val: ::std::os::raw::c_uint) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] pub fn new_bitfield_1( indirect: ::std::os::raw::c_uint, ) -> __BindgenBitfieldUnit<[u8; 1usize], u8> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize], u8> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { let indirect: u32 = unsafe { ::std::mem::transmute(indirect) }; indirect as u64 }); __bindgen_bitfield_unit } } #[repr(C)] #[derive(Debug)] pub struct snd_ctl_tlv { pub numid: ::std::os::raw::c_uint, pub length: ::std::os::raw::c_uint, pub tlv: __IncompleteArrayField<::std::os::raw::c_uint>, } #[test] fn bindgen_test_layout_snd_ctl_tlv() { assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(snd_ctl_tlv)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_ctl_tlv)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).numid as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_tlv), "::", stringify!(numid) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).length as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_ctl_tlv), "::", stringify!(length) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).tlv as *const _ as usize }, 8usize, concat!( "Offset of field: ", stringify!(snd_ctl_tlv), "::", stringify!(tlv) ) ); } pub const sndrv_ctl_event_type_SNDRV_CTL_EVENT_ELEM: sndrv_ctl_event_type = 0; pub const sndrv_ctl_event_type_SNDRV_CTL_EVENT_LAST: sndrv_ctl_event_type = 0; pub type sndrv_ctl_event_type = u32; #[repr(C)] #[derive(Copy, Clone)] pub struct snd_ctl_event { pub type_: ::std::os::raw::c_int, pub data: snd_ctl_event__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union snd_ctl_event__bindgen_ty_1 { pub elem: snd_ctl_event__bindgen_ty_1__bindgen_ty_1, pub data8: [::std::os::raw::c_uchar; 60usize], _bindgen_union_align: [u32; 17usize], } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_ctl_event__bindgen_ty_1__bindgen_ty_1 { pub mask: ::std::os::raw::c_uint, pub id: snd_ctl_elem_id, } #[test] fn bindgen_test_layout_snd_ctl_event__bindgen_ty_1__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 68usize, concat!( "Size of: ", stringify!(snd_ctl_event__bindgen_ty_1__bindgen_ty_1) ) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!( "Alignment of ", stringify!(snd_ctl_event__bindgen_ty_1__bindgen_ty_1) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).mask as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_event__bindgen_ty_1__bindgen_ty_1), "::", stringify!(mask) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).id as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_ctl_event__bindgen_ty_1__bindgen_ty_1), "::", stringify!(id) ) ); } #[test] fn bindgen_test_layout_snd_ctl_event__bindgen_ty_1() { assert_eq!( ::std::mem::size_of::(), 68usize, concat!("Size of: ", stringify!(snd_ctl_event__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_ctl_event__bindgen_ty_1)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).elem as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_event__bindgen_ty_1), "::", stringify!(elem) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).data8 as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_event__bindgen_ty_1), "::", stringify!(data8) ) ); } #[test] fn bindgen_test_layout_snd_ctl_event() { assert_eq!( ::std::mem::size_of::(), 72usize, concat!("Size of: ", stringify!(snd_ctl_event)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(snd_ctl_event)) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).type_ as *const _ as usize }, 0usize, concat!( "Offset of field: ", stringify!(snd_ctl_event), "::", stringify!(type_) ) ); assert_eq!( unsafe { &(*(::std::ptr::null::())).data as *const _ as usize }, 4usize, concat!( "Offset of field: ", stringify!(snd_ctl_event), "::", stringify!(data) ) ); } alsa-0.9.1/src/direct/ffi.rs000064400000000000000000000152161046102023000137330ustar 00000000000000//! Some definitions from the kernel headers #![allow(non_camel_case_types)] use cfg_if::cfg_if; // const SNDRV_PCM_MMAP_OFFSET_DATA: c_uint = 0x00000000; pub const SNDRV_PCM_MMAP_OFFSET_STATUS: libc::c_uint = 0x80000000; pub const SNDRV_PCM_MMAP_OFFSET_CONTROL: libc::c_uint = 0x81000000; pub const SNDRV_PCM_SYNC_PTR_HWSYNC: libc::c_uint = 1; pub const SNDRV_PCM_SYNC_PTR_APPL: libc::c_uint = 2; pub const SNDRV_PCM_SYNC_PTR_AVAIL_MIN: libc::c_uint = 4; // #[repr(C)] #[allow(non_camel_case_types)] pub type snd_pcm_state_t = libc::c_int; // #[repr(C)] #[allow(non_camel_case_types)] pub type snd_pcm_uframes_t = libc::c_ulong; // I think?! Not sure how this will work with X32 ABI?! #[allow(non_camel_case_types)] pub type __kernel_off_t = libc::c_long; #[repr(C)] #[derive(Copy, Clone)] pub struct snd_pcm_mmap_status { pub state: snd_pcm_state_t, /* RO: state - SNDRV_PCM_STATE_XXXX */ pub pad1: libc::c_int, /* Needed for 64 bit alignment */ pub hw_ptr: snd_pcm_uframes_t, /* RO: hw ptr (0...boundary-1) */ pub tstamp: libc::timespec, /* Timestamp */ pub suspended_state: snd_pcm_state_t, /* RO: suspended stream state */ pub audio_tstamp: libc::timespec, /* from sample counter or wall clock */ } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct snd_pcm_mmap_control { pub appl_ptr: snd_pcm_uframes_t, /* RW: appl ptr (0...boundary-1) */ pub avail_min: snd_pcm_uframes_t, /* RW: min available frames for wakeup */ } #[repr(C)] #[derive(Debug)] pub struct snd_pcm_channel_info { pub channel: libc::c_uint, pub offset: __kernel_off_t, /* mmap offset */ pub first: libc::c_uint, /* offset to first sample in bits */ pub step: libc::c_uint, /* samples distance in bits */ } #[repr(C)] #[derive(Copy, Clone)] pub union snd_pcm_mmap_status_r { pub status: snd_pcm_mmap_status, pub reserved: [libc::c_uchar; 64], } #[repr(C)] #[derive(Copy, Clone)] pub union snd_pcm_mmap_control_r { pub control: snd_pcm_mmap_control, pub reserved: [libc::c_uchar; 64], } #[repr(C)] #[derive(Copy, Clone)] pub struct snd_pcm_sync_ptr { pub flags: libc::c_uint, pub s: snd_pcm_mmap_status_r, pub c: snd_pcm_mmap_control_r, } cfg_if! { if #[cfg(any(target_os = "linux", target_os = "android"))] { // See cfg_if! { if #[cfg(any(target_os = "android", target_env = "musl"))] { pub(super) type ioctl_num_type = libc::c_int; } else { pub(super) type ioctl_num_type = libc::c_ulong; } } // The READ dir is consistent across arches pub(super) const READ: ioctl_num_type = 2; // But WRITE is not, as well as having a different number of bits for the SIZEBITS cfg_if!{ if #[cfg(any( target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "sparc64" ))] { pub(super) const WRITE: ioctl_num_type = 4; const SIZEBITS: ioctl_num_type = 13; } else { pub(super) const WRITE: ioctl_num_type = 1; const SIZEBITS: ioctl_num_type = 14; } } const NRSHIFT: ioctl_num_type = 0; const NRBITS: ioctl_num_type = 8; const TYPEBITS: ioctl_num_type = 8; const TYPESHIFT: ioctl_num_type = NRSHIFT + NRBITS; const SIZESHIFT: ioctl_num_type = TYPESHIFT + TYPEBITS; const DIRSHIFT: ioctl_num_type = SIZESHIFT + SIZEBITS; /// Replication of the [`nix::ioc!`](https://github.com/nix-rust/nix/blob/197f55b3ccbce3273bf6ce119d1a8541b5df5d66/src/sys/ioctl/linux.rs#L78-L96) pub(super) const fn make_request( dir: ioctl_num_type, typ: u8, nr: u8, size: usize, ) -> ioctl_num_type { dir << DIRSHIFT | (typ as ioctl_num_type) << TYPESHIFT | (nr as ioctl_num_type) << NRSHIFT | (size as ioctl_num_type) << SIZESHIFT } } else if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", target_os = "solaris", target_os = "illumos" ))] { // See cfg_if! { if #[cfg(not(any(target_os = "illumos", target_os = "solaris")))] { pub(super) type ioctl_num_type = libc::c_ulong; } else { pub(super) type ioctl_num_type = libc::c_int; } } #[allow(overflowing_literals)] pub(super) const READ: ioctl_num_type = 0x4000_0000; #[allow(overflowing_literals)] pub(super) const WRITE: ioctl_num_type = 0x8000_0000; const IOCPARM_MASK: ioctl_num_type = 0x1fff; /// Replication of [`nix::ioc!`](https://github.com/nix-rust/nix/blob/197f55b3ccbce3273bf6ce119d1a8541b5df5d66/src/sys/ioctl/bsd.rs#L31-L42) pub(super) const fn make_request( dir: ioctl_num_type, typ: u8, nr: u8, size: usize, ) -> ioctl_num_type { dir | ((size as ioctl_num_type) & IOCPARM_MASK) << 16 | (typ as ioctl_num_type) << 8 | nr as ioctl_num_type } } else { compile_error!("unknown target platform"); } } pub(crate) unsafe fn sndrv_pcm_ioctl_channel_info( fd: libc::c_int, data: *mut snd_pcm_channel_info, ) -> Result<(), crate::Error> { const REQUEST: ioctl_num_type = make_request( READ, b'A', 0x32, std::mem::size_of::(), ); unsafe { if libc::ioctl(fd, REQUEST, data) == -1 { Err(crate::Error::last("SNDRV_PCM_IOCTL_CHANNEL_INFO")) } else { Ok(()) } } } pub(crate) unsafe fn sndrv_pcm_ioctl_sync_ptr( fd: libc::c_int, data: *mut snd_pcm_sync_ptr, ) -> Result<(), crate::Error> { const REQUEST: ioctl_num_type = make_request( READ | WRITE, b'A', 0x23, std::mem::size_of::(), ); unsafe { if libc::ioctl(fd, REQUEST, data) == -1 { Err(crate::Error::last("SNDRV_PCM_IOCTL_SYNC_PTR")) } else { Ok(()) } } } pub fn pagesize() -> usize { unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } } alsa-0.9.1/src/direct/pcm.rs000064400000000000000000000535171046102023000137540ustar 00000000000000/*! This module bypasses alsa-lib and directly read and write into memory mapped kernel memory. In case of the sample memory, this is in many cases the DMA buffers that is transferred to the sound card. The reasons for doing this are: * Minimum overhead where it matters most: let alsa-lib do the code heavy setup - then steal its file descriptor and deal with sample streaming from Rust. * RT-safety to the maximum extent possible. Creating/dropping any of these structs causes syscalls, but function calls on these are just read and write from memory. No syscalls, no memory allocations, not even loops (with the exception of `MmapPlayback::write` that loops over samples to write). * Possibility to allow Send + Sync for structs * It's a fun experiment and an interesting deep dive into how alsa-lib does things. Note: Not all sound card drivers support this direct method of communication; although almost all modern/common ones do. It only works with hardware devices though (such as "hw:xxx" device strings), don't expect it to work with, e g, the PulseAudio plugin or so. For an example of how to use this mode, look in the "synth-example" directory. */ use libc; use std::{mem, ptr, fmt, cmp}; use crate::error::{Error, Result}; use std::os::unix::io::RawFd; use crate::{pcm, PollDescriptors, Direction}; use crate::pcm::Frames; use std::marker::PhantomData; use super::ffi::*; /// Read PCM status via a simple kernel syscall, bypassing alsa-lib. /// /// If Status is not available on your architecture, this is the second best option. pub struct SyncPtrStatus(snd_pcm_mmap_status); impl SyncPtrStatus { /// Executes sync_ptr syscall. /// /// Unsafe because /// - setting appl_ptr and avail_min might make alsa-lib confused /// - no check that the fd is really a PCM pub unsafe fn sync_ptr(fd: RawFd, hwsync: bool, appl_ptr: Option, avail_min: Option) -> Result { let mut data = snd_pcm_sync_ptr { flags: (if hwsync { SNDRV_PCM_SYNC_PTR_HWSYNC } else { 0 }) + (if appl_ptr.is_some() { SNDRV_PCM_SYNC_PTR_APPL } else { 0 }) + (if avail_min.is_some() { SNDRV_PCM_SYNC_PTR_AVAIL_MIN } else { 0 }), c: snd_pcm_mmap_control_r { control: snd_pcm_mmap_control { appl_ptr: appl_ptr.unwrap_or(0) as snd_pcm_uframes_t, avail_min: avail_min.unwrap_or(0) as snd_pcm_uframes_t, } }, s: mem::zeroed() }; sndrv_pcm_ioctl_sync_ptr(fd, &mut data)?; let i = data.s.status.state; if (i >= (pcm::State::Open as snd_pcm_state_t)) && (i <= (pcm::State::Disconnected as snd_pcm_state_t)) { Ok(SyncPtrStatus(data.s.status)) } else { Err(Error::unsupported("SNDRV_PCM_IOCTL_SYNC_PTR returned broken state")) } } pub fn hw_ptr(&self) -> pcm::Frames { self.0.hw_ptr as pcm::Frames } pub fn state(&self) -> pcm::State { unsafe { mem::transmute(self.0.state as u8) } /* valid range checked in sync_ptr */ } pub fn htstamp(&self) -> libc::timespec { self.0.tstamp } } /// Read PCM status directly from memory, bypassing alsa-lib. /// /// This means that it's /// 1) less overhead for reading status (no syscall, no allocations, no virtual dispatch, just a read from memory) /// 2) Send + Sync, and /// 3) will only work for "hw" / "plughw" devices (not e g PulseAudio plugins), and not /// all of those are supported, although all common ones are (as of 2017, and a kernel from the same decade). /// Kernel supported archs are: x86, PowerPC, Alpha. Use "SyncPtrStatus" for other archs. /// /// The values are updated every now and then by the kernel. Many functions will force an update to happen, /// e g `PCM::avail()` and `PCM::delay()`. /// /// Note: Even if you close the original PCM device, ALSA will not actually close the device until all /// Status structs are dropped too. /// #[derive(Debug)] pub struct Status(DriverMemory); fn pcm_to_fd(p: &pcm::PCM) -> Result { let mut fds: [libc::pollfd; 1] = unsafe { mem::zeroed() }; let c = PollDescriptors::fill(p, &mut fds)?; if c != 1 { return Err(Error::unsupported("snd_pcm_poll_descriptors returned wrong number of fds")) } Ok(fds[0].fd) } impl Status { pub fn new(p: &pcm::PCM) -> Result { Status::from_fd(pcm_to_fd(p)?) } pub fn from_fd(fd: RawFd) -> Result { DriverMemory::new(fd, 1, SNDRV_PCM_MMAP_OFFSET_STATUS as libc::off_t, false).map(Status) } /// Current PCM state. pub fn state(&self) -> pcm::State { unsafe { let i = ptr::read_volatile(&(*self.0.ptr).state); assert!((i >= (pcm::State::Open as snd_pcm_state_t)) && (i <= (pcm::State::Disconnected as snd_pcm_state_t))); mem::transmute(i as u8) } } /// Number of frames hardware has read or written /// /// This number is updated every now and then by the kernel. /// Calling most functions on the PCM will update it, so will usually a period interrupt. /// No guarantees given. /// /// This value wraps at "boundary" (a large value you can read from SwParams). pub fn hw_ptr(&self) -> pcm::Frames { unsafe { ptr::read_volatile(&(*self.0.ptr).hw_ptr) as pcm::Frames } } /// Timestamp - fast version of alsa-lib's Status::get_htstamp /// /// Note: This just reads the actual value in memory. /// Unfortunately, the timespec is too big to be read atomically on most archs. /// Therefore, this function can potentially give bogus result at times, at least in theory...? pub fn htstamp(&self) -> libc::timespec { unsafe { ptr::read_volatile(&(*self.0.ptr).tstamp) } } /// Audio timestamp - fast version of alsa-lib's Status::get_audio_htstamp /// /// Note: This just reads the actual value in memory. /// Unfortunately, the timespec is too big to be read atomically on most archs. /// Therefore, this function can potentially give bogus result at times, at least in theory...? pub fn audio_htstamp(&self) -> libc::timespec { unsafe { ptr::read_volatile(&(*self.0.ptr).audio_tstamp) } } } /// Write PCM appl ptr directly, bypassing alsa-lib. /// /// Provides direct access to appl ptr and avail min, without the overhead of /// alsa-lib or a syscall. Caveats that apply to Status applies to this struct too. #[derive(Debug)] pub struct Control(DriverMemory); impl Control { pub fn new(p: &pcm::PCM) -> Result { Self::from_fd(pcm_to_fd(p)?) } pub fn from_fd(fd: RawFd) -> Result { DriverMemory::new(fd, 1, SNDRV_PCM_MMAP_OFFSET_CONTROL as libc::off_t, true).map(Control) } /// Read number of frames application has read or written /// /// This value wraps at "boundary" (a large value you can read from SwParams). pub fn appl_ptr(&self) -> pcm::Frames { unsafe { ptr::read_volatile(&(*self.0.ptr).appl_ptr) as pcm::Frames } } /// Set number of frames application has read or written /// /// When the kernel wakes up due to a period interrupt, this value will /// be checked by the kernel. An XRUN will happen in case the application /// has not read or written enough data. pub fn set_appl_ptr(&self, value: pcm::Frames) { unsafe { ptr::write_volatile(&mut (*self.0.ptr).appl_ptr, value as snd_pcm_uframes_t) } } /// Read minimum number of frames in buffer in order to wakeup process pub fn avail_min(&self) -> pcm::Frames { unsafe { ptr::read_volatile(&(*self.0.ptr).avail_min) as pcm::Frames } } /// Write minimum number of frames in buffer in order to wakeup process pub fn set_avail_min(&self, value: pcm::Frames) { unsafe { ptr::write_volatile(&mut (*self.0.ptr).avail_min, value as snd_pcm_uframes_t) } } } struct DriverMemory { ptr: *mut S, size: libc::size_t, } impl fmt::Debug for DriverMemory { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "DriverMemory({:?})", self.ptr) } } impl DriverMemory { fn new(fd: RawFd, count: usize, offs: libc::off_t, writable: bool) -> Result { let mut total = count * mem::size_of::(); let ps = pagesize(); assert!(total > 0); if total % ps != 0 { total += ps - total % ps }; let flags = if writable { libc::PROT_WRITE | libc::PROT_READ } else { libc::PROT_READ }; let p = unsafe { libc::mmap(ptr::null_mut(), total, flags, libc::MAP_FILE | libc::MAP_SHARED, fd, offs) }; if p.is_null() || p == libc::MAP_FAILED { Err(Error::last("mmap (of driver memory)")) } else { Ok(DriverMemory { ptr: p as *mut S, size: total }) } } } unsafe impl Send for DriverMemory {} unsafe impl Sync for DriverMemory {} impl Drop for DriverMemory { fn drop(&mut self) { unsafe {{ libc::munmap(self.ptr as *mut libc::c_void, self.size); } } } } #[derive(Debug)] struct SampleData { mem: DriverMemory, frames: pcm::Frames, channels: u32, } impl SampleData { pub fn new(p: &pcm::PCM) -> Result { let params = p.hw_params_current()?; let bufsize = params.get_buffer_size()?; let channels = params.get_channels()?; if params.get_access()? != pcm::Access::MMapInterleaved { return Err(Error::unsupported("Not MMAP interleaved data")) } let fd = pcm_to_fd(p)?; let info = unsafe { let mut info: snd_pcm_channel_info = mem::zeroed(); sndrv_pcm_ioctl_channel_info(fd, &mut info)?; info }; // println!("{:?}", info); if (info.step != channels * mem::size_of::() as u32 * 8) || (info.first != 0) { return Err(Error::unsupported("MMAP data size mismatch")) } Ok(SampleData { mem: DriverMemory::new(fd, (bufsize as usize) * (channels as usize), info.offset as libc::off_t, true)?, frames: bufsize, channels, }) } } /// Dummy trait for better generics pub trait MmapDir: fmt::Debug { const DIR: Direction; fn avail(hwptr: Frames, applptr: Frames, buffersize: Frames, boundary: Frames) -> Frames; } /// Dummy struct for better generics #[derive(Copy, Clone, Debug)] pub struct Playback; impl MmapDir for Playback { const DIR: Direction = Direction::Playback; #[inline] fn avail(hwptr: Frames, applptr: Frames, buffersize: Frames, boundary: Frames) -> Frames { let r = hwptr.wrapping_add(buffersize).wrapping_sub(applptr); let r = if r < 0 { r.wrapping_add(boundary) } else { r }; if r as usize >= boundary as usize { r.wrapping_sub(boundary) } else { r } } } /// Dummy struct for better generics #[derive(Copy, Clone, Debug)] pub struct Capture; impl MmapDir for Capture { const DIR: Direction = Direction::Capture; #[inline] fn avail(hwptr: Frames, applptr: Frames, _buffersize: Frames, boundary: Frames) -> Frames { let r = hwptr.wrapping_sub(applptr); if r < 0 { r.wrapping_add(boundary) } else { r } } } pub type MmapPlayback = MmapIO; pub type MmapCapture = MmapIO; #[derive(Debug)] /// Struct containing direct I/O functions shared between playback and capture. pub struct MmapIO { data: SampleData, c: Control, ss: Status, bound: Frames, dir: PhantomData<*const D>, } #[derive(Debug, Clone, Copy)] /// A raw pointer to samples, and the amount of samples readable or writable. pub struct RawSamples { pub ptr: *mut S, pub frames: Frames, pub channels: u32, } impl RawSamples { #[inline] /// Returns `frames` * `channels`, i e the amount of samples (of type `S`) that can be read/written. pub fn samples(&self) -> isize { self.frames as isize * (self.channels as isize) } /// Writes samples from an iterator. /// /// Returns true if iterator was depleted, and the number of samples written. /// This is just raw read/write of memory. pub unsafe fn write_samples>(&self, i: &mut I) -> (bool, isize) { let mut z = 0; let max_samples = self.samples(); while z < max_samples { let b = if let Some(b) = i.next() { b } else { return (true, z) }; ptr::write_volatile(self.ptr.offset(z), b); z += 1; }; (false, z) } } impl MmapIO { fn new(p: &pcm::PCM) -> Result { if p.info()?.get_stream() != D::DIR { return Err(Error::unsupported("Wrong direction")); } let boundary = p.sw_params_current()?.get_boundary()?; Ok(MmapIO { data: SampleData::new(p)?, c: Control::new(p)?, ss: Status::new(p)?, bound: boundary, dir: PhantomData, }) } } pub (crate) fn new_mmap(p: &pcm::PCM) -> Result> { MmapIO::new(p) } impl MmapIO { /// Read current status pub fn status(&self) -> &Status { &self.ss } /// Read current number of frames committed by application /// /// This number wraps at 'boundary'. #[inline] pub fn appl_ptr(&self) -> Frames { self.c.appl_ptr() } /// Read current number of frames read / written by hardware /// /// This number wraps at 'boundary'. #[inline] pub fn hw_ptr(&self) -> Frames { self.ss.hw_ptr() } /// The number at which hw_ptr and appl_ptr wraps. #[inline] pub fn boundary(&self) -> Frames { self.bound } /// Total number of frames in hardware buffer #[inline] pub fn buffer_size(&self) -> Frames { self.data.frames } /// Number of channels in stream #[inline] pub fn channels(&self) -> u32 { self.data.channels } /// Notifies the kernel that frames have now been read / written by the application /// /// This will allow the kernel to write new data into this part of the buffer. pub fn commit(&self, v: Frames) { let mut z = self.appl_ptr() + v; if z + v >= self.boundary() { z -= self.boundary() }; self.c.set_appl_ptr(z) } /// Number of frames available to read / write. /// /// In case of an underrun, this value might be bigger than the buffer size. pub fn avail(&self) -> Frames { D::avail(self.hw_ptr(), self.appl_ptr(), self.buffer_size(), self.boundary()) } /// Returns raw pointers to data to read / write. /// /// Use this if you want to read/write data yourself (instead of using iterators). If you do, /// using `write_volatile` or `read_volatile` is recommended, since it's DMA memory and can /// change at any time. /// /// Since this is a ring buffer, there might be more data to read/write in the beginning /// of the buffer as well. If so this is returned as the second return value. pub fn data_ptr(&self) -> (RawSamples, Option>) { let (hwptr, applptr) = (self.hw_ptr(), self.appl_ptr()); let c = self.channels(); let bufsize = self.buffer_size(); // These formulas mostly mimic the behaviour of // snd_pcm_mmap_begin (in alsa-lib/src/pcm/pcm.c). let offs = applptr % bufsize; let mut a = D::avail(hwptr, applptr, bufsize, self.boundary()); a = cmp::min(a, bufsize); let b = bufsize - offs; let more_data = if b < a { let z = a - b; a = b; Some( RawSamples { ptr: self.data.mem.ptr, frames: z, channels: c }) } else { None }; let p = unsafe { self.data.mem.ptr.offset(offs as isize * self.data.channels as isize) }; (RawSamples { ptr: p, frames: a, channels: c }, more_data) } } impl MmapPlayback { /// Write samples to the kernel ringbuffer. pub fn write>(&mut self, i: &mut I) -> Frames { let (data, more_data) = self.data_ptr(); let (iter_end, samples) = unsafe { data.write_samples(i) }; let mut z = samples / data.channels as isize; if !iter_end { if let Some(data2) = more_data { let (_, samples2) = unsafe { data2.write_samples(i) }; z += samples2 / data2.channels as isize; } } let z = z as Frames; self.commit(z); z } } impl MmapCapture { /// Read samples from the kernel ringbuffer. /// /// When the iterator is dropped or depleted, the read samples will be committed, i e, /// the kernel can then write data to the location again. So do this ASAP. pub fn iter(&mut self) -> CaptureIter { let (data, more_data) = self.data_ptr(); CaptureIter { m: self, samples: data, p_offs: 0, read_samples: 0, next_p: more_data, } } } /// Iterator over captured samples pub struct CaptureIter<'a, S: 'static> { m: &'a MmapCapture, samples: RawSamples, p_offs: isize, read_samples: isize, next_p: Option>, } impl<'a, S: 'static + Copy> CaptureIter<'a, S> { fn handle_max(&mut self) { self.p_offs = 0; if let Some(p2) = self.next_p.take() { self.samples = p2; } else { self.m.commit((self.read_samples / self.samples.channels as isize) as Frames); self.read_samples = 0; self.samples.frames = 0; // Shortcut to "None" in case anyone calls us again } } } impl<'a, S: 'static + Copy> Iterator for CaptureIter<'a, S> { type Item = S; #[inline] fn next(&mut self) -> Option { if self.p_offs >= self.samples.samples() { self.handle_max(); if self.samples.frames <= 0 { return None; } } let s = unsafe { ptr::read_volatile(self.samples.ptr.offset(self.p_offs)) }; self.p_offs += 1; self.read_samples += 1; Some(s) } } impl<'a, S: 'static> Drop for CaptureIter<'a, S> { fn drop(&mut self) { self.m.commit((self.read_samples / self.m.data.channels as isize) as Frames); } } #[test] #[ignore] // Not everyone has a recording device on plughw:1. So let's ignore this test by default. fn record_from_plughw_rw() { use crate::pcm::*; use crate::{ValueOr, Direction}; use std::ffi::CString; let pcm = PCM::open(&*CString::new("plughw:1").unwrap(), Direction::Capture, false).unwrap(); let ss = self::Status::new(&pcm).unwrap(); let c = self::Control::new(&pcm).unwrap(); let hwp = HwParams::any(&pcm).unwrap(); hwp.set_channels(2).unwrap(); hwp.set_rate(44100, ValueOr::Nearest).unwrap(); hwp.set_format(Format::s16()).unwrap(); hwp.set_access(Access::RWInterleaved).unwrap(); pcm.hw_params(&hwp).unwrap(); { let swp = pcm.sw_params_current().unwrap(); swp.set_tstamp_mode(true).unwrap(); pcm.sw_params(&swp).unwrap(); } assert_eq!(ss.state(), State::Prepared); pcm.start().unwrap(); assert_eq!(c.appl_ptr(), 0); println!("{:?}, {:?}", ss, c); let mut buf = [0i16; 512*2]; assert_eq!(pcm.io_i16().unwrap().readi(&mut buf).unwrap(), 512); assert_eq!(c.appl_ptr(), 512); assert_eq!(ss.state(), State::Running); assert!(ss.hw_ptr() >= 512); let t2 = ss.htstamp(); assert!(t2.tv_sec > 0 || t2.tv_nsec > 0); } #[test] #[ignore] // Not everyone has a record device on plughw:1. So let's ignore this test by default. fn record_from_plughw_mmap() { use crate::pcm::*; use crate::{ValueOr, Direction}; use std::ffi::CString; use std::{thread, time}; let pcm = PCM::open(&*CString::new("plughw:1").unwrap(), Direction::Capture, false).unwrap(); let hwp = HwParams::any(&pcm).unwrap(); hwp.set_channels(2).unwrap(); hwp.set_rate(44100, ValueOr::Nearest).unwrap(); hwp.set_format(Format::s16()).unwrap(); hwp.set_access(Access::MMapInterleaved).unwrap(); pcm.hw_params(&hwp).unwrap(); let ss = unsafe { SyncPtrStatus::sync_ptr(pcm_to_fd(&pcm).unwrap(), false, None, None).unwrap() }; assert_eq!(ss.state(), State::Prepared); let mut m = pcm.direct_mmap_capture::().unwrap(); assert_eq!(m.status().state(), State::Prepared); assert_eq!(m.appl_ptr(), 0); assert_eq!(m.hw_ptr(), 0); println!("{:?}", m); let now = time::Instant::now(); pcm.start().unwrap(); while m.avail() < 256 { thread::sleep(time::Duration::from_millis(1)) }; assert!(now.elapsed() >= time::Duration::from_millis(256 * 1000 / 44100)); let (ptr1, md) = m.data_ptr(); assert_eq!(ptr1.channels, 2); assert!(ptr1.frames >= 256); assert!(md.is_none()); println!("Has {:?} frames at {:?} in {:?}", m.avail(), ptr1.ptr, now.elapsed()); let samples: Vec = m.iter().collect(); assert!(samples.len() >= ptr1.frames as usize * 2); println!("Collected {} samples", samples.len()); let (ptr2, _md) = m.data_ptr(); assert!(unsafe { ptr1.ptr.offset(256 * 2) } <= ptr2.ptr); } #[test] #[ignore] fn playback_to_plughw_mmap() { use crate::pcm::*; use crate::{ValueOr, Direction}; use std::ffi::CString; let pcm = PCM::open(&*CString::new("plughw:1").unwrap(), Direction::Playback, false).unwrap(); let hwp = HwParams::any(&pcm).unwrap(); hwp.set_channels(2).unwrap(); hwp.set_rate(44100, ValueOr::Nearest).unwrap(); hwp.set_format(Format::s16()).unwrap(); hwp.set_access(Access::MMapInterleaved).unwrap(); pcm.hw_params(&hwp).unwrap(); let mut m = pcm.direct_mmap_playback::().unwrap(); assert_eq!(m.status().state(), State::Prepared); assert_eq!(m.appl_ptr(), 0); assert_eq!(m.hw_ptr(), 0); println!("{:?}", m); let mut i = (0..(m.buffer_size() * 2)).map(|i| (((i / 2) as f32 * 2.0 * ::std::f32::consts::PI / 128.0).sin() * 8192.0) as i16); m.write(&mut i); assert_eq!(m.appl_ptr(), m.buffer_size()); pcm.start().unwrap(); pcm.drain().unwrap(); assert_eq!(m.appl_ptr(), m.buffer_size()); assert!(m.hw_ptr() >= m.buffer_size()); } alsa-0.9.1/src/direct.rs000064400000000000000000000001341046102023000131600ustar 00000000000000//! Functions that bypass alsa-lib and talk directly to the kernel. pub mod pcm; mod ffi; alsa-0.9.1/src/error.rs000064400000000000000000000163011046102023000130420ustar 00000000000000#![macro_use] use libc::{c_char, c_int, c_void, free}; use std::error::Error as StdError; use std::ffi::CStr; use std::{fmt, str}; /// ALSA error /// /// Most ALSA functions can return a negative error code. /// If so, then that error code is wrapped into this `Error` struct. /// An Error is also returned in case ALSA returns a string that /// cannot be translated into Rust's UTF-8 strings. #[derive(Clone, PartialEq, Copy)] pub struct Error(&'static str, i32); pub type Result = ::std::result::Result; macro_rules! acheck { ($f: ident ( $($x: expr),* ) ) => {{ let r = unsafe { alsa::$f( $($x),* ) }; if r < 0 { Err(Error::new(stringify!($f), -r as ::libc::c_int)) } else { Ok(r) } }} } pub fn from_const<'a>(func: &'static str, s: *const c_char) -> Result<&'a str> { if s.is_null() { return Err(invalid_str(func)); }; let cc = unsafe { CStr::from_ptr(s) }; str::from_utf8(cc.to_bytes()).map_err(|_| invalid_str(func)) } pub fn from_alloc(func: &'static str, s: *mut c_char) -> Result { if s.is_null() { return Err(invalid_str(func)); }; let c = unsafe { CStr::from_ptr(s) }; let ss = str::from_utf8(c.to_bytes()) .map_err(|_| { unsafe { free(s as *mut c_void); } invalid_str(func) })? .to_string(); unsafe { free(s as *mut c_void); } Ok(ss) } pub fn from_code(func: &'static str, r: c_int) -> Result { if r < 0 { Err(Error::new(func, r)) } else { Ok(r) } } impl Error { pub fn new(func: &'static str, res: c_int) -> Error { Self(func, res) } pub fn last(func: &'static str) -> Error { Self( func, std::io::Error::last_os_error() .raw_os_error() .unwrap_or_default(), ) } pub fn unsupported(func: &'static str) -> Error { Error(func, libc::ENOTSUP) } /// The function which failed. pub fn func(&self) -> &'static str { self.0 } /// Underlying error /// /// Match this against the re-export of `nix::Error` in this crate, not against a specific version /// of the nix crate. The nix crate version might be updated with minor updates of this library. pub fn errno(&self) -> i32 { self.1 } } pub fn invalid_str(func: &'static str) -> Error { Error(func, libc::EILSEQ) } impl StdError for Error { fn description(&self) -> &str { "ALSA error" } } impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "ALSA function '{}' failed with error '{} ({})'", self.0, desc(self.1), self.1, ) } } /// See /// /// Note this doesn't include the total set of possible errno variants, but they /// can easily be added in the future for better error messages fn desc(errno: i32) -> &'static str { match errno { libc::EPERM => "Operation not permitted", libc::ENOENT => "No such file or directory", libc::ESRCH => "No such process", libc::EINTR => "Interrupted system call", libc::EIO => "I/O error", libc::ENXIO => "No such device or address", libc::E2BIG => "Argument list too long", libc::ENOEXEC => "Exec format error", libc::EBADF => "Bad file number", libc::ECHILD => "No child processes", libc::EAGAIN => "Try again", libc::ENOMEM => "Out of memory", libc::EACCES => "Permission denied", libc::EFAULT => "Bad address", libc::ENOTBLK => "Block device required", libc::EBUSY => "Device or resource busy", libc::EEXIST => "File exists", libc::EXDEV => "Cross-device link", libc::ENODEV => "No such device", libc::ENOTDIR => "Not a directory", libc::EISDIR => "Is a directory", libc::EINVAL => "Invalid argument", libc::ENFILE => "File table overflow", libc::EMFILE => "Too many open files", libc::ENOTTY => "Not a typewriter", libc::ETXTBSY => "Text file busy", libc::EFBIG => "File too large", libc::ENOSPC => "No space left on device", libc::ESPIPE => "Illegal seek", libc::EROFS => "Read-only file system", libc::EMLINK => "Too many links", libc::EPIPE => "Broken pipe", libc::EDOM => "Math argument out of domain of func", libc::ERANGE => "Math result not representable", libc::EDEADLK => "Resource deadlock would occur", libc::ENAMETOOLONG => "File name too long", libc::ENOLCK => "No record locks available", libc::ENOSYS => "Function not implemented", libc::ENOTEMPTY => "Directory not empty", libc::ELOOP => "Too many symbolic links encountered", libc::ENOMSG => "No message of desired type", libc::EIDRM => "Identifier removed", libc::EINPROGRESS => "Operation now in progress", libc::EALREADY => "Operation already in progress", libc::ENOTSOCK => "Socket operation on non-socket", libc::EDESTADDRREQ => "Destination address required", libc::EMSGSIZE => "Message too long", libc::EPROTOTYPE => "Protocol wrong type for socket", libc::ENOPROTOOPT => "Protocol not available", libc::EPROTONOSUPPORT => "Protocol not supported", libc::ESOCKTNOSUPPORT => "Socket type not supported", libc::EPFNOSUPPORT => "Protocol family not supported", libc::EAFNOSUPPORT => "Address family not supported by protocol", libc::EADDRINUSE => "Address already in use", libc::EADDRNOTAVAIL => "Cannot assign requested address", libc::ENETDOWN => "Network is down", libc::ENETUNREACH => "Network is unreachable", libc::ENETRESET => "Network dropped connection because of reset", libc::ECONNABORTED => "Software caused connection abort", libc::ECONNRESET => "Connection reset by peer", libc::ENOBUFS => "No buffer space available", libc::EISCONN => "Transport endpoint is already connected", libc::ENOTCONN => "Transport endpoint is not connected", libc::ESHUTDOWN => "Cannot send after transport endpoint shutdown", libc::ETOOMANYREFS => "Too many references: cannot splice", libc::ETIMEDOUT => "Connection timed out", libc::ECONNREFUSED => "Connection refused", libc::EHOSTDOWN => "Host is down", libc::EHOSTUNREACH => "No route to host", libc::ENOTSUP => "Operation not supported", _ => "Unknown errno", } } impl From for fmt::Error { fn from(_: Error) -> fmt::Error { fmt::Error } } #[test] fn broken_pcm_name() { use std::ffi::CString; let e = crate::PCM::open( &*CString::new("this_PCM_does_not_exist").unwrap(), crate::Direction::Playback, false, ) .err() .unwrap(); assert_eq!(e.func(), "snd_pcm_open"); assert_eq!(e.errno(), libc::ENOENT); } alsa-0.9.1/src/hctl.rs000064400000000000000000000143261046102023000126500ustar 00000000000000//! HCtl API - for mixer control and jack detection //! //! # Example //! Print all jacks and their status //! //! ``` //! for a in ::alsa::card::Iter::new().map(|x| x.unwrap()) { //! use std::ffi::CString; //! use alsa::hctl::HCtl; //! let h = HCtl::open(&CString::new(format!("hw:{}", a.get_index())).unwrap(), false).unwrap(); //! h.load().unwrap(); //! for b in h.elem_iter() { //! use alsa::ctl::ElemIface; //! let id = b.get_id().unwrap(); //! if id.get_interface() != ElemIface::Card { continue; } //! let name = id.get_name().unwrap(); //! if !name.ends_with(" Jack") { continue; } //! if name.ends_with(" Phantom Jack") { //! println!("{} is always present", &name[..name.len()-13]) //! } //! else { println!("{} is {}", &name[..name.len()-5], //! if b.read().unwrap().get_boolean(0).unwrap() { "plugged in" } else { "unplugged" }) //! } //! } //! } //! ``` use crate::{alsa, Card}; use std::ffi::{CStr, CString}; use super::error::*; use std::ptr; use super::{ctl_int, poll}; use libc::{c_short, c_uint, c_int, pollfd}; /// [snd_hctl_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___h_control.html) wrapper pub struct HCtl(*mut alsa::snd_hctl_t); unsafe impl Send for HCtl {} impl Drop for HCtl { fn drop(&mut self) { unsafe { alsa::snd_hctl_close(self.0) }; } } impl HCtl { /// Wrapper around open that takes a &str instead of a &CStr pub fn new(c: &str, nonblock: bool) -> Result { Self::open(&CString::new(c).unwrap(), nonblock) } /// Open does not support async mode (it's not very Rustic anyway) /// Note: You probably want to call `load` afterwards. pub fn open(c: &CStr, nonblock: bool) -> Result { let mut r = ptr::null_mut(); let flags = if nonblock { 1 } else { 0 }; // FIXME: alsa::SND_CTL_NONBLOCK does not exist in alsa-sys acheck!(snd_hctl_open(&mut r, c.as_ptr(), flags)) .map(|_| HCtl(r)) } /// Wrapper around open. You probably want to call `load` afterwards. pub fn from_card(c: &Card, nonblock: bool) -> Result { let s = format!("hw:{}", c.get_index()); HCtl::new(&s, nonblock) } pub fn load(&self) -> Result<()> { acheck!(snd_hctl_load(self.0)).map(|_| ()) } pub fn elem_iter(&self) -> ElemIter { ElemIter(self, ptr::null_mut()) } pub fn find_elem(&self, id: &ctl_int::ElemId) -> Option { let p = unsafe { alsa::snd_hctl_find_elem(self.0, ctl_int::elem_id_ptr(id)) }; if p.is_null() { None } else { Some(Elem(self, p)) } } pub fn handle_events(&self) -> Result { acheck!(snd_hctl_handle_events(self.0)).map(|x| x as u32) } pub fn wait(&self, timeout_ms: Option) -> Result { acheck!(snd_hctl_wait(self.0, timeout_ms.map(|x| x as c_int).unwrap_or(-1))).map(|i| i == 1) } } impl poll::Descriptors for HCtl { fn count(&self) -> usize { unsafe { alsa::snd_hctl_poll_descriptors_count(self.0) as usize } } fn fill(&self, p: &mut [pollfd]) -> Result { let z = unsafe { alsa::snd_hctl_poll_descriptors(self.0, p.as_mut_ptr(), p.len() as c_uint) }; from_code("snd_hctl_poll_descriptors", z).map(|_| z as usize) } fn revents(&self, p: &[pollfd]) -> Result { let mut r = 0; let z = unsafe { alsa::snd_hctl_poll_descriptors_revents(self.0, p.as_ptr() as *mut pollfd, p.len() as c_uint, &mut r) }; from_code("snd_hctl_poll_descriptors_revents", z).map(|_| poll::Flags::from_bits_truncate(r as c_short)) } } /// Iterates over elements for a `HCtl` pub struct ElemIter<'a>(&'a HCtl, *mut alsa::snd_hctl_elem_t); impl<'a> Iterator for ElemIter<'a> { type Item = Elem<'a>; fn next(&mut self) -> Option> { self.1 = if self.1.is_null() { unsafe { alsa::snd_hctl_first_elem((self.0).0) }} else { unsafe { alsa::snd_hctl_elem_next(self.1) }}; if self.1.is_null() { None } else { Some(Elem(self.0, self.1)) } } } /// [snd_hctl_elem_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___h_control.html) wrapper pub struct Elem<'a>(&'a HCtl, *mut alsa::snd_hctl_elem_t); impl<'a> Elem<'a> { pub fn get_id(&self) -> Result { let v = ctl_int::elem_id_new()?; unsafe { alsa::snd_hctl_elem_get_id(self.1, ctl_int::elem_id_ptr(&v)) }; Ok(v) } pub fn info(&self) -> Result { let v = ctl_int::elem_info_new()?; acheck!(snd_hctl_elem_info(self.1, ctl_int::elem_info_ptr(&v))).map(|_| v) } pub fn read(&self) -> Result { let i = self.info()?; let v = ctl_int::elem_value_new(i.get_type(), i.get_count())?; acheck!(snd_hctl_elem_read(self.1, ctl_int::elem_value_ptr(&v))).map(|_| v) } pub fn write(&self, v: &ctl_int::ElemValue) -> Result { acheck!(snd_hctl_elem_write(self.1, ctl_int::elem_value_ptr(v))).map(|e| e > 0) } } #[test] fn print_hctls() { for a in super::card::Iter::new().map(|x| x.unwrap()) { use std::ffi::CString; let h = HCtl::open(&CString::new(format!("hw:{}", a.get_index())).unwrap(), false).unwrap(); h.load().unwrap(); println!("Card {}:", a.get_name().unwrap()); for b in h.elem_iter() { println!(" {:?} - {:?}", b.get_id().unwrap(), b.read().unwrap()); } } } #[test] fn print_jacks() { for a in super::card::Iter::new().map(|x| x.unwrap()) { use std::ffi::CString; let h = HCtl::open(&CString::new(format!("hw:{}", a.get_index())).unwrap(), false).unwrap(); h.load().unwrap(); for b in h.elem_iter() { let id = b.get_id().unwrap(); if id.get_interface() != super::ctl_int::ElemIface::Card { continue; } let name = id.get_name().unwrap(); if !name.ends_with(" Jack") { continue; } if name.ends_with(" Phantom Jack") { println!("{} is always present", &name[..name.len()-13]) } else { println!("{} is {}", &name[..name.len()-5], if b.read().unwrap().get_boolean(0).unwrap() { "plugged in" } else { "unplugged" }) } } } } alsa-0.9.1/src/io.rs000064400000000000000000000025441046102023000123240ustar 00000000000000use crate::alsa; use super::error::*; use std::{slice, ptr, fmt}; /// [snd_output_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___output.html) wrapper pub struct Output(*mut alsa::snd_output_t); unsafe impl Send for Output {} impl Drop for Output { fn drop(&mut self) { unsafe { alsa::snd_output_close(self.0) }; } } impl Output { pub fn buffer_open() -> Result { let mut q = ptr::null_mut(); acheck!(snd_output_buffer_open(&mut q)).map(|_| Output(q)) } pub fn buffer_string T>(&self, f: F) -> T { let b = unsafe { let mut q = ptr::null_mut(); let s = alsa::snd_output_buffer_string(self.0, &mut q); slice::from_raw_parts(q as *const u8, s as usize) }; f(b) } } impl fmt::Debug for Output { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Output(")?; fmt::Display::fmt(self, f)?; write!(f, ")") /* self.buffer_string(|b| f.write_str(try!(str::from_utf8(b).map_err(|_| fmt::Error)))) */ } } impl fmt::Display for Output { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.buffer_string(|b| { let s = String::from_utf8_lossy(b); f.write_str(&*s) }) } } pub fn output_handle(o: &Output) -> *mut alsa::snd_output_t { o.0 } alsa-0.9.1/src/lib.rs000064400000000000000000000064641046102023000124700ustar 00000000000000//! Thin but safe wrappers for [ALSA](https://alsa-project.org). //! //! [GitHub repo](https://github.com/diwic/alsa-rs) //! //! [Crates.io](https://crates.io/crates/alsa) //! //! This ALSA API wrapper/binding is WIP - the ALSA API is huge, and new //! functions and structs might be added as requested. //! //! Most functions map 1-to-1 to alsa-lib functions, e g, `ctl::CardInfo::get_id()` is a wrapper around //! `snd_ctl_card_info_get_id` and the [alsa-lib documentation](https://www.alsa-project.org/alsa-doc/alsa-lib/) //! can be consulted for additional information. //! //! Enjoy! #![allow(clippy::all)] #![warn(clippy::correctness, clippy::suspicious, clippy::perf)] extern crate alsa_sys as alsa; extern crate libc; #[macro_use] extern crate bitflags; macro_rules! alsa_enum { ($(#[$attr:meta])+ $name:ident, $static_name:ident [$count:expr], $( $a:ident = $b:ident),* ,) => { #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] $(#[$attr])* pub enum $name { $( $a = alsa::$b as isize, )* } static $static_name: [$name; $count] = [ $( $name::$a, )* ]; impl $name { /// Returns a slice of all possible values; useful for iteration pub fn all() -> &'static [$name] { &$static_name[..] } #[allow(dead_code)] fn from_c_int(c: ::libc::c_int, s: &'static str) -> Result<$name> { Self::all().iter().find(|&&x| c == x as ::libc::c_int).map(|&x| x) .ok_or_else(|| Error::unsupported(s)) } #[allow(dead_code)] fn to_c_int(&self) -> ::libc::c_int { return *self as ::libc::c_int; } } } } /// Replaces constants ending with PLAYBACK/CAPTURE as well as /// INPUT/OUTPUT #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum Direction { Playback, Capture } impl Direction { #[inline] pub fn input() -> Direction { Direction::Capture } #[inline] pub fn output() -> Direction { Direction::Playback } } /// Used to restrict hw parameters. In case the submitted /// value is unavailable, in which direction should one search /// for available values? #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum ValueOr { /// The value set is the submitted value, or less Less = -1, /// The value set is the submitted value, or the nearest Nearest = 0, /// The value set is the submitted value, or greater Greater = 1, } /// Rounding mode (used in some mixer related calls) #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum Round { /// Round down (towards negative infinity) Floor = 0, /// Round up (towards positive infinity) Ceil = 1, } mod error; pub use crate::error::{Error, Result}; pub mod card; pub use crate::card::Card as Card; mod ctl_int; pub mod ctl { //! Control device API pub use super::ctl_int::{Ctl, CardInfo, DeviceIter, ElemIface, ElemId, ElemType, ElemValue, ElemInfo}; } pub use crate::ctl::Ctl as Ctl; pub mod hctl; pub use crate::hctl::HCtl as HCtl; pub mod pcm; pub use crate::pcm::PCM as PCM; pub mod rawmidi; pub use crate::rawmidi::Rawmidi as Rawmidi; pub mod device_name; pub mod poll; pub use crate::poll::Descriptors as PollDescriptors; pub mod mixer; pub use crate::mixer::Mixer as Mixer; pub mod seq; pub use crate::seq::Seq as Seq; mod io; pub use crate::io::Output; // Reexported inside PCM module mod chmap; pub mod direct; alsa-0.9.1/src/mixer.rs000064400000000000000000000603001046102023000130330ustar 00000000000000//! Mixer API - Simple Mixer API for mixer control //! use std::ffi::{CStr, CString}; use std::{ptr, mem, fmt, ops}; use libc::{c_long, c_int, c_uint, c_short, pollfd}; use crate::poll; use crate::alsa; use super::Round; use super::error::*; const SELEM_ID_SIZE: usize = 64; /// wraps [snd_mixer_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___mixer.html) #[derive(Debug)] pub struct Mixer(*mut alsa::snd_mixer_t); unsafe impl Send for Mixer {} impl Mixer { /// Opens a mixer and attaches it to a card identified by its name (like hw:0) and loads the /// mixer after registering a Selem. pub fn new(name: &str, nonblock: bool) -> Result { let mut mixer = Mixer::open(nonblock)?; mixer.attach(&CString::new(name).unwrap())?; Selem::register(&mut mixer)?; mixer.load()?; Ok(mixer) } /// Creates a Selem by looking for a specific selem by name given a mixer (of a card) pub fn find_selem(&self, id: &SelemId) -> Option { let selem = unsafe { alsa::snd_mixer_find_selem(self.0, id.as_ptr()) }; if selem.is_null() { None } else { Some(Selem(Elem {handle: selem, _mixer: self})) } } pub fn open(nonblock: bool) -> Result { let mut r = ptr::null_mut(); let flags = if nonblock { 1 } else { 0 }; // FIXME: alsa::SND_CTL_NONBLOCK does not exist in alsa-sys acheck!(snd_mixer_open(&mut r, flags)).map(|_| Mixer(r)) } pub fn attach(&mut self, name: &CStr) -> Result<()> { acheck!(snd_mixer_attach(self.0, name.as_ptr())).map(|_| ()) } pub fn load(&mut self) -> Result<()> { acheck!(snd_mixer_load(self.0)).map(|_| ()) } pub fn iter(&self) -> Iter { Iter { last_handle: ptr::null_mut(), mixer: self } } pub fn handle_events(&self) -> Result { acheck!(snd_mixer_handle_events(self.0)).map(|x| x as u32) } pub fn wait(&self, timeout_ms: Option) -> Result<()> { acheck!(snd_mixer_wait(self.0, timeout_ms.map(|x| x as c_int).unwrap_or(-1))).map(|_| ()) } } /// Closes mixer and frees used resources impl Drop for Mixer { fn drop(&mut self) { unsafe { alsa::snd_mixer_close(self.0) }; } } impl poll::Descriptors for Mixer { fn count(&self) -> usize { unsafe { alsa::snd_mixer_poll_descriptors_count(self.0) as usize } } fn fill(&self, p: &mut [pollfd]) -> Result { let z = unsafe { alsa::snd_mixer_poll_descriptors(self.0, p.as_mut_ptr(), p.len() as c_uint) }; from_code("snd_mixer_poll_descriptors", z).map(|_| z as usize) } fn revents(&self, p: &[pollfd]) -> Result { let mut r = 0; let z = unsafe { alsa::snd_mixer_poll_descriptors_revents(self.0, p.as_ptr() as *mut pollfd, p.len() as c_uint, &mut r) }; from_code("snd_mixer_poll_descriptors_revents", z).map(|_| poll::Flags::from_bits_truncate(r as c_short)) } } /// Wrapper for a mB (millibel) value. /// /// Despite some ALSA functions named "dB", they actually take mB values instead. /// This is a wrapper type to help with those calculations. Its interior is the /// actual mB value. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct MilliBel(pub i64); impl MilliBel { pub fn to_db(self) -> f32 { (self.0 as f32) / 100.0 } pub fn from_db(db: f32) -> Self { MilliBel((db * 100.0) as i64) } } impl ops::Deref for MilliBel { type Target = i64; fn deref(&self) -> &i64 { &self.0 } } impl ops::Add for MilliBel { type Output = MilliBel; fn add(self, rhs: Self) -> Self { MilliBel(self.0 + rhs.0) } } impl ops::AddAssign for MilliBel { fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0 } } impl ops::Sub for MilliBel { type Output = MilliBel; fn sub(self, rhs: Self) -> Self { MilliBel(self.0 - rhs.0) } } impl ops::SubAssign for MilliBel { fn sub_assign(&mut self, rhs: Self) { self.0 -= rhs.0 } } /// Wraps [snd_mixer_elem_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___mixer.html) #[derive(Copy, Clone, Debug)] pub struct Elem<'a>{ handle: *mut alsa::snd_mixer_elem_t, _mixer: &'a Mixer } /// Iterator for all elements of mixer #[derive(Copy, Clone)] pub struct Iter<'a>{ last_handle: *mut alsa::snd_mixer_elem_t, mixer: &'a Mixer } impl<'a> Iterator for Iter<'a> { type Item = Elem<'a>; fn next(&mut self) -> Option> { let elem = if self.last_handle.is_null() { unsafe { alsa::snd_mixer_first_elem(self.mixer.0) } } else { unsafe { alsa::snd_mixer_elem_next(self.last_handle) } }; if elem.is_null() { None } else { self.last_handle = elem; Some(Elem { handle: elem, _mixer: self.mixer}) } } } /// Wrapper for [snd_mixer_selem_id_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___simple_mixer.html) /// No allocation (uses fixed array) // #[derive(Copy, Clone, Debug)] pub struct SelemId([u8; SELEM_ID_SIZE]); impl SelemId { pub fn new(name: &str, index: u32) -> SelemId { let mut s = SelemId::empty(); s.set_name(&CString::new(name).unwrap()); s.set_index(index); s } /// Returns an empty (zeroed) SelemId. This id is not a usable id and need to be initialized /// like `SelemId::new()` does pub fn empty() -> SelemId { assert!(unsafe { alsa::snd_mixer_selem_id_sizeof() } as usize <= SELEM_ID_SIZE); // Create empty selem_id and fill from mixer SelemId(unsafe { mem::zeroed() }) } /// Convert SelemId into ``*mut snd_mixer_selem_id_t` that the alsa call needs. /// See [snd_mixer_selem_id_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___simple_mixer.html) #[inline] fn as_ptr(&self) -> *mut alsa::snd_mixer_selem_id_t { self.0.as_ptr() as *const _ as *mut alsa::snd_mixer_selem_id_t } pub fn get_name(&self) -> Result<&str> { let c = unsafe { alsa::snd_mixer_selem_id_get_name(self.as_ptr()) }; from_const("snd_mixer_selem_id_get_name", c) } pub fn get_index(&self) -> u32 { unsafe { alsa::snd_mixer_selem_id_get_index(self.as_ptr()) } } pub fn set_name(&mut self, name: &CStr) { unsafe { alsa::snd_mixer_selem_id_set_name(self.as_ptr(), name.as_ptr()) }; } pub fn set_index(&mut self, index: u32) { unsafe { alsa::snd_mixer_selem_id_set_index(self.as_ptr(), index) }; } } /// Wraps an Elem as a Selem // #[derive(Copy, Clone)] pub struct Selem<'a>(Elem<'a>); impl<'a> Selem<'a> { /// Creates a Selem by wrapping `elem`. pub fn new(elem: Elem<'a>) -> Option> { if unsafe { alsa::snd_mixer_elem_get_type(elem.handle) } == alsa::SND_MIXER_ELEM_SIMPLE { Some(Selem(elem)) } else { None } } /// TODO: This function might change to support regopt and to return the mixer class pub fn register(mixer: &mut Mixer) -> Result<()> { acheck!(snd_mixer_selem_register(mixer.0, ptr::null_mut(), ptr::null_mut())).map(|_| ()) } pub fn get_id(&self) -> SelemId { let id = SelemId::empty(); unsafe { alsa::snd_mixer_selem_get_id(self.handle, id.as_ptr()) }; id } pub fn has_capture_volume(&self) -> bool { unsafe { alsa::snd_mixer_selem_has_capture_volume(self.handle) > 0 } } pub fn has_capture_switch(&self) -> bool { unsafe { alsa::snd_mixer_selem_has_capture_switch(self.handle) > 0 } } pub fn has_playback_volume(&self) -> bool { unsafe { alsa::snd_mixer_selem_has_playback_volume(self.handle) > 0 } } pub fn has_playback_switch(&self) -> bool { unsafe { alsa::snd_mixer_selem_has_playback_switch(self.handle) > 0 } } pub fn can_capture(&self) -> bool { self.has_capture_volume() || self.has_capture_switch() } pub fn can_playback(&self) -> bool { self.has_playback_volume() || self.has_playback_switch() } pub fn has_volume(&self) -> bool { self.has_capture_volume() || self.has_playback_volume() } /// returns range for capture volume as (min, max) values pub fn get_capture_volume_range(&self) -> (i64, i64) { let mut min: c_long = 0; let mut max: c_long = 0; unsafe { alsa::snd_mixer_selem_get_capture_volume_range(self.handle, &mut min, &mut max) }; (min as i64, max as i64) } /// returns (min, max) values. pub fn get_capture_db_range(&self) -> (MilliBel, MilliBel) { let mut min: c_long = 0; let mut max: c_long = 0; unsafe { alsa::snd_mixer_selem_get_capture_dB_range(self.handle, &mut min, &mut max) }; (MilliBel(min as i64), MilliBel(max as i64)) } /// returns (min, max) values. pub fn get_playback_volume_range(&self) -> (i64, i64) { let mut min: c_long = 0; let mut max: c_long = 0; unsafe { alsa::snd_mixer_selem_get_playback_volume_range(self.handle, &mut min, &mut max) }; (min as i64, max as i64) } /// returns (min, max) values. pub fn get_playback_db_range(&self) -> (MilliBel, MilliBel) { let mut min: c_long = 0; let mut max: c_long = 0; unsafe { alsa::snd_mixer_selem_get_playback_dB_range(self.handle, &mut min, &mut max) }; (MilliBel(min as i64), MilliBel(max as i64)) } pub fn is_capture_mono(&self) -> bool { unsafe { alsa::snd_mixer_selem_is_capture_mono(self.handle) == 1 } } pub fn is_playback_mono(&self) -> bool { unsafe { alsa::snd_mixer_selem_is_playback_mono(self.handle) == 1 } } pub fn has_capture_channel(&self, channel: SelemChannelId) -> bool { unsafe { alsa::snd_mixer_selem_has_capture_channel(self.handle, channel as i32) > 0 } } pub fn has_playback_channel(&self, channel: SelemChannelId) -> bool { unsafe { alsa::snd_mixer_selem_has_playback_channel(self.handle, channel as i32) > 0 } } /// Gets name from snd_mixer_selem_channel_name pub fn channel_name(channel: SelemChannelId) -> Result<&'static str> { let c = unsafe { alsa::snd_mixer_selem_channel_name(channel as i32) }; from_const("snd_mixer_selem_channel_name", c) } pub fn get_playback_volume(&self, channel: SelemChannelId) -> Result { let mut value: c_long = 0; acheck!(snd_mixer_selem_get_playback_volume(self.handle, channel as i32, &mut value)).and_then(|_| Ok(value as i64)) } /// returns volume in millibels. pub fn get_playback_vol_db(&self, channel: SelemChannelId) -> Result { self.get_playback_volume(channel) .and_then(|volume| self.ask_playback_vol_db(volume)) } /// Asks alsa to convert playback volume to millibels. pub fn ask_playback_vol_db(&self, volume: i64) -> Result { let mut decibel_value: c_long = 0; acheck!(snd_mixer_selem_ask_playback_vol_dB(self.handle, volume as c_long, &mut decibel_value)) .map(|_| MilliBel(decibel_value as i64)) } // Asks alsa to convert millibels to playback volume. pub fn ask_playback_db_vol(&self, db: MilliBel, dir: Round) -> Result { let mut raw_volume: c_long = 0; acheck!(snd_mixer_selem_ask_playback_dB_vol(self.handle, db.0 as c_long, dir as c_int, &mut raw_volume)) .map(|_| raw_volume as i64) } pub fn get_capture_volume(&self, channel: SelemChannelId) -> Result { let mut value: c_long = 0; acheck!(snd_mixer_selem_get_capture_volume(self.handle, channel as i32, &mut value)).map(|_| value as i64) } /// returns volume in millibels. pub fn get_capture_vol_db(&self, channel: SelemChannelId) -> Result { self.get_capture_volume(channel) .and_then(|volume| self.ask_capture_vol_db(volume)) } /// Asks alsa to convert capture volume to millibels pub fn ask_capture_vol_db(&self, volume: i64) -> Result { let mut decibel_value: c_long = 0; acheck!(snd_mixer_selem_ask_capture_vol_dB (self.handle, volume as c_long, &mut decibel_value)) .map(|_| MilliBel(decibel_value as i64)) } // Asks alsa to convert millibels to capture volume. pub fn ask_capture_db_vol(&self, db: MilliBel, dir: Round) -> Result { let mut raw_volume: c_long = 0; acheck!(snd_mixer_selem_ask_capture_dB_vol(self.handle, db.0 as c_long, dir as c_int, &mut raw_volume)) .map(|_| raw_volume as i64) } pub fn set_playback_volume(&self, channel: SelemChannelId, value: i64) -> Result<()> { acheck!(snd_mixer_selem_set_playback_volume(self.handle, channel as i32, value as c_long)).map(|_| ()) } pub fn set_playback_volume_range(&self, min: i64, max: i64) -> Result<()> { acheck!(snd_mixer_selem_set_playback_volume_range(self.handle, min as c_long, max as c_long)).map(|_| ()) } pub fn set_playback_volume_all(&self, value: i64) -> Result<()> { acheck!(snd_mixer_selem_set_playback_volume_all(self.handle, value as c_long)).map(|_| ()) } pub fn set_playback_db(&self, channel: SelemChannelId, value: MilliBel, dir: Round) -> Result<()> { acheck!(snd_mixer_selem_set_playback_dB(self.handle, channel as i32, *value as c_long, dir as c_int)).map(|_| ()) } pub fn set_capture_db(&self, channel: SelemChannelId, value: MilliBel, dir: Round) -> Result<()> { acheck!(snd_mixer_selem_set_capture_dB(self.handle, channel as i32, *value as c_long, dir as c_int)).map(|_| ()) } pub fn set_playback_db_all(&self, value: MilliBel, dir: Round) -> Result<()> { acheck!(snd_mixer_selem_set_playback_dB_all(self.handle, *value as c_long, dir as c_int)).map(|_| ()) } pub fn set_capture_db_all(&self, value: MilliBel, dir: Round) -> Result<()> { acheck!(snd_mixer_selem_set_capture_dB_all(self.handle, *value as c_long, dir as c_int)).map(|_| ()) } pub fn set_capture_volume(&self, channel: SelemChannelId, value: i64) -> Result<()> { acheck!(snd_mixer_selem_set_capture_volume(self.handle, channel as i32, value as c_long)).map(|_| ()) } pub fn set_capture_volume_range(&self, min: i64, max: i64) -> Result<()> { acheck!(snd_mixer_selem_set_capture_volume_range(self.handle, min as c_long, max as c_long)).map(|_| ()) } pub fn set_capture_volume_all(&self, value: i64) -> Result<()> { acheck!(snd_mixer_selem_set_capture_volume_all(self.handle, value as c_long)).map(|_| ()) } pub fn set_playback_switch(&self, channel: SelemChannelId, value: i32) -> Result<()> { acheck!(snd_mixer_selem_set_playback_switch(self.handle, channel as i32, value)).map(|_| ()) } pub fn set_playback_switch_all(&self, value: i32) -> Result<()> { acheck!(snd_mixer_selem_set_playback_switch_all(self.handle, value)).map(|_| ()) } pub fn set_capture_switch(&self, channel: SelemChannelId, value: i32) -> Result<()> { acheck!(snd_mixer_selem_set_capture_switch(self.handle, channel as i32, value)).map(|_| ()) } pub fn set_capture_switch_all(&self, value: i32) -> Result<()> { acheck!(snd_mixer_selem_set_capture_switch_all(self.handle, value)).map(|_| ()) } pub fn get_playback_switch(&self, channel: SelemChannelId) -> Result { let mut value: i32 = 0; acheck!(snd_mixer_selem_get_playback_switch(self.handle, channel as i32, &mut value)).map(|_| value) } pub fn get_capture_switch(&self, channel: SelemChannelId) -> Result { let mut value: i32 = 0; acheck!(snd_mixer_selem_get_capture_switch(self.handle, channel as i32, &mut value)).map(|_| value) } pub fn is_enumerated(&self) -> bool { unsafe { alsa::snd_mixer_selem_is_enumerated(self.handle) == 1 } } pub fn is_enum_playback(&self) -> bool { unsafe { alsa::snd_mixer_selem_is_enum_playback(self.handle) == 1 } } pub fn is_enum_capture(&self) -> bool { unsafe { alsa::snd_mixer_selem_is_enum_capture(self.handle) == 1 } } pub fn get_enum_items(&self) -> Result { acheck!(snd_mixer_selem_get_enum_items(self.handle)).map(|v| v as u32) } pub fn get_enum_item_name(&self, idx: u32) -> Result { let mut temp = [0 as ::libc::c_char; 128]; acheck!(snd_mixer_selem_get_enum_item_name(self.handle, idx, temp.len()-1, temp.as_mut_ptr())) .and_then(|_| from_const("snd_mixer_selem_get_enum_item_name", temp.as_ptr())) .map(|v| v.into()) } /// Enumerates over valid Enum values pub fn iter_enum(&self) -> Result { Ok(IterEnum(self, 0, self.get_enum_items()?)) } pub fn get_enum_item(&self, channel: SelemChannelId) -> Result { let mut temp = 0; acheck!(snd_mixer_selem_get_enum_item(self.handle, channel as i32, &mut temp)) .map(|_| temp) } pub fn set_enum_item(&self, channel: SelemChannelId, idx: u32) -> Result<()> { acheck!(snd_mixer_selem_set_enum_item(self.handle, channel as i32, idx)) .map(|_| ()) } } impl<'a> ops::Deref for Selem<'a> { type Target = Elem<'a>; /// returns the elem of this selem fn deref(&self) -> &Elem<'a> { &self.0 } } pub struct IterEnum<'a>(&'a Selem<'a>, u32, u32); impl<'a> Iterator for IterEnum<'a> { type Item = Result; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { self.1 += 1; Some(self.0.get_enum_item_name(self.1-1)) } } } alsa_enum!( /// Wrapper for [SND_MIXER_SCHN_*](http://www.alsa-project.org/alsa-doc/alsa-lib/group___simple_mixer.html) constants SelemChannelId, ALL_SELEM_CHANNEL_ID[11], Unknown = SND_MIXER_SCHN_UNKNOWN, FrontLeft = SND_MIXER_SCHN_FRONT_LEFT, FrontRight = SND_MIXER_SCHN_FRONT_RIGHT, RearLeft = SND_MIXER_SCHN_REAR_LEFT, RearRight = SND_MIXER_SCHN_REAR_RIGHT, FrontCenter = SND_MIXER_SCHN_FRONT_CENTER, Woofer = SND_MIXER_SCHN_WOOFER, SideLeft = SND_MIXER_SCHN_SIDE_LEFT, SideRight = SND_MIXER_SCHN_SIDE_RIGHT, RearCenter = SND_MIXER_SCHN_REAR_CENTER, Last = SND_MIXER_SCHN_LAST, ); impl SelemChannelId { pub fn mono() -> SelemChannelId { SelemChannelId::FrontLeft } } impl fmt::Display for SelemChannelId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", Selem::channel_name(*self).unwrap()) } } #[test] fn print_mixer_of_cards() { use super::card; for card in card::Iter::new().map(|c| c.unwrap()) { println!("Card #{}: {} ({})", card.get_index(), card.get_name().unwrap(), card.get_longname().unwrap()); let mixer = Mixer::new(&format!("hw:{}", card.get_index()), false).unwrap(); for selem in mixer.iter().filter_map(|e| Selem::new(e)) { let sid = selem.get_id(); println!("\tMixer element {},{}:", sid.get_name().unwrap(), sid.get_index()); if selem.has_volume() { print!("\t Volume limits: "); if selem.has_capture_volume() { let (vmin, vmax) = selem.get_capture_volume_range(); let (mbmin, mbmax) = selem.get_capture_db_range(); print!("Capture = {} - {}", vmin, vmax); print!(" ({} dB - {} dB)", mbmin.to_db(), mbmax.to_db()); } if selem.has_playback_volume() { let (vmin, vmax) = selem.get_playback_volume_range(); let (mbmin, mbmax) = selem.get_playback_db_range(); print!("Playback = {} - {}", vmin, vmax); print!(" ({} dB - {} dB)", mbmin.to_db(), mbmax.to_db()); } println!(); } if selem.is_enumerated() { print!("\t Valid values: "); for v in selem.iter_enum().unwrap() { print!("{}, ", v.unwrap()) }; print!("\n\t Current values: "); for v in SelemChannelId::all().iter().filter_map(|&v| selem.get_enum_item(v).ok()) { print!("{}, ", selem.get_enum_item_name(v).unwrap()); } println!(); } if selem.can_capture() { print!("\t Capture channels: "); if selem.is_capture_mono() { print!("Mono"); } else { for channel in SelemChannelId::all() { if selem.has_capture_channel(*channel) { print!("{}, ", channel) }; } } println!(); print!("\t Capture volumes: "); for channel in SelemChannelId::all() { if selem.has_capture_channel(*channel) { print!("{}: {} ({} dB), ", channel, match selem.get_capture_volume(*channel) {Ok(v) => format!("{}", v), Err(_) => "n/a".to_string()}, match selem.get_capture_vol_db(*channel) {Ok(v) => format!("{}", v.to_db()), Err(_) => "n/a".to_string()} );} } println!(); } if selem.can_playback() { print!("\t Playback channels: "); if selem.is_playback_mono() { print!("Mono"); } else { for channel in SelemChannelId::all() { if selem.has_playback_channel(*channel) { print!("{}, ", channel) }; } } println!(); if selem.has_playback_volume() { print!("\t Playback volumes: "); for channel in SelemChannelId::all() { if selem.has_playback_channel(*channel) { print!("{}: {} / {}dB, ", channel, match selem.get_playback_volume(*channel) {Ok(v) => format!("{}", v), Err(_) => "n/a".to_string()}, match selem.get_playback_vol_db(*channel) {Ok(v) => format!("{}", v.to_db()), Err(_) => "n/a".to_string()} );} } println!(); } } } } } #[test] #[ignore] fn get_and_set_playback_volume() { let mixer = Mixer::new("hw:1", false).unwrap(); let selem = mixer.find_selem(&SelemId::new("Master", 0)).unwrap(); let (rmin, rmax) = selem.get_playback_volume_range(); let mut channel = SelemChannelId::mono(); for c in SelemChannelId::all().iter() { if selem.has_playback_channel(*c) { channel = *c; break } } println!("Testing on {} with limits {}-{} on channel {}", selem.get_id().get_name().unwrap(), rmin, rmax, channel); let old: i64 = selem.get_playback_volume(channel).unwrap(); let new: i64 = rmax / 2; assert_ne!(new, old); println!("Changing volume of {} from {} to {}", channel, old, new); selem.set_playback_volume(channel, new).unwrap(); let mut result: i64 = selem.get_playback_volume(channel).unwrap(); assert_eq!(new, result); // return volume to old value selem.set_playback_volume(channel, old).unwrap(); result = selem.get_playback_volume(channel).unwrap(); assert_eq!(old, result); } #[test] #[ignore] fn get_and_set_capture_volume() { let mixer = Mixer::new("hw:1", false).unwrap(); let selem = mixer.find_selem(&SelemId::new("Capture", 0)).unwrap(); let (rmin, rmax) = selem.get_capture_volume_range(); let mut channel = SelemChannelId::mono(); for c in SelemChannelId::all().iter() { if selem.has_playback_channel(*c) { channel = *c; break } } println!("Testing on {} with limits {}-{} on channel {}", selem.get_id().get_name().unwrap(), rmin, rmax, channel); let old: i64 = selem.get_capture_volume(channel).unwrap(); let new: i64 = rmax / 2; assert_ne!(new, old); println!("Changing volume of {} from {} to {}", channel, old, new); selem.set_capture_volume(channel, new).unwrap(); let mut result: i64 = selem.get_capture_volume(channel).unwrap(); assert_eq!(new, result); // return volume to old value selem.set_capture_volume(channel, old).unwrap(); result = selem.get_capture_volume(channel).unwrap(); assert_eq!(old, result); } #[test] fn print_sizeof() { let selemid = unsafe { alsa::snd_mixer_selem_id_sizeof() } as usize; assert!(selemid <= SELEM_ID_SIZE); println!("Selem id: {}", selemid); } alsa-0.9.1/src/pcm.rs000064400000000000000000001376171046102023000125060ustar 00000000000000//! Audio playback and capture //! //! # Example //! Playback a sine wave through the "default" device. //! //! ``` //! use alsa::{Direction, ValueOr}; //! use alsa::pcm::{PCM, HwParams, Format, Access, State}; //! //! // Open default playback device //! let pcm = PCM::new("default", Direction::Playback, false).unwrap(); //! //! // Set hardware parameters: 44100 Hz / Mono / 16 bit //! let hwp = HwParams::any(&pcm).unwrap(); //! hwp.set_channels(1).unwrap(); //! hwp.set_rate(44100, ValueOr::Nearest).unwrap(); //! hwp.set_format(Format::s16()).unwrap(); //! hwp.set_access(Access::RWInterleaved).unwrap(); //! pcm.hw_params(&hwp).unwrap(); //! let io = pcm.io_i16().unwrap(); //! //! // Make sure we don't start the stream too early //! let hwp = pcm.hw_params_current().unwrap(); //! let swp = pcm.sw_params_current().unwrap(); //! swp.set_start_threshold(hwp.get_buffer_size().unwrap()).unwrap(); //! pcm.sw_params(&swp).unwrap(); //! //! // Make a sine wave //! let mut buf = [0i16; 1024]; //! for (i, a) in buf.iter_mut().enumerate() { //! *a = ((i as f32 * 2.0 * ::std::f32::consts::PI / 128.0).sin() * 8192.0) as i16 //! } //! //! // Play it back for 2 seconds. //! for _ in 0..2*44100/1024 { //! assert_eq!(io.writei(&buf[..]).unwrap(), 1024); //! } //! //! // In case the buffer was larger than 2 seconds, start the stream manually. //! if pcm.state() != State::Running { pcm.start().unwrap() }; //! // Wait for the stream to finish playback. //! pcm.drain().unwrap(); //! ``` use libc::{c_int, c_uint, c_void, ssize_t, c_short, timespec, pollfd}; use crate::alsa; use std::convert::Infallible; use std::marker::PhantomData; use std::mem::size_of; use std::ffi::{CStr, CString}; use std::str::FromStr; use std::{io, fmt, ptr, cell}; use super::error::*; use super::{Direction, Output, poll, ValueOr, chmap}; pub use super::chmap::{Chmap, ChmapPosition, ChmapType, ChmapsQuery}; /// [snd_pcm_sframes_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) pub type Frames = alsa::snd_pcm_sframes_t; /// [snd_pcm_info_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) wrapper - PCM generic info container pub struct Info(pub(crate) *mut alsa::snd_pcm_info_t); impl Info { pub fn new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_pcm_info_malloc(&mut p)).map(|_| Info(p)) } pub fn get_card(&self) -> i32 { unsafe { alsa::snd_pcm_info_get_card(self.0) } } pub fn get_device(&self) -> u32 { unsafe { alsa::snd_pcm_info_get_device(self.0) } } pub fn get_subdevice(&self) -> u32 { unsafe { alsa::snd_pcm_info_get_subdevice(self.0) } } pub fn get_id(&self) -> Result<&str> { let c = unsafe { alsa::snd_pcm_info_get_id(self.0) }; from_const("snd_pcm_info_get_id", c) } pub fn get_name(&self) -> Result<&str> { let c = unsafe { alsa::snd_pcm_info_get_name(self.0) }; from_const("snd_pcm_info_get_name", c) } pub fn get_subdevice_name(&self) -> Result<&str> { let c = unsafe { alsa::snd_pcm_info_get_subdevice_name(self.0) }; from_const("snd_pcm_info_get_subdevice_name", c) } pub fn get_stream(&self) -> Direction { match unsafe { alsa::snd_pcm_info_get_stream(self.0) } { alsa::SND_PCM_STREAM_CAPTURE => Direction::Capture, alsa::SND_PCM_STREAM_PLAYBACK => Direction::Playback, n @ _ => panic!("snd_pcm_info_get_stream invalid direction '{}'", n), } } pub fn get_subdevices_count(&self) -> u32 { unsafe { alsa::snd_pcm_info_get_subdevices_count(self.0) } } pub fn get_subdevices_avail(&self) -> u32 { unsafe { alsa::snd_pcm_info_get_subdevices_avail(self.0) } } pub(crate) fn set_device(&mut self, device: u32) { unsafe { alsa::snd_pcm_info_set_device(self.0, device) } } pub(crate) fn set_stream(&mut self, direction: Direction) { let stream = match direction { Direction::Capture => alsa::SND_PCM_STREAM_CAPTURE, Direction::Playback => alsa::SND_PCM_STREAM_PLAYBACK, }; unsafe { alsa::snd_pcm_info_set_stream(self.0, stream) } } pub(crate) fn set_subdevice(&mut self, subdevice: u32) { unsafe { alsa::snd_pcm_info_set_subdevice(self.0, subdevice) } } } impl Drop for Info { fn drop(&mut self) { unsafe { alsa::snd_pcm_info_free(self.0) }; } } /// [snd_pcm_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) wrapper - start here for audio playback and recording pub struct PCM(*mut alsa::snd_pcm_t, cell::Cell); unsafe impl Send for PCM {} impl PCM { fn check_has_io(&self) { if self.1.get() { panic!("No hw_params call or additional IO objects allowed") } } /// Wrapper around open that takes a &str instead of a &CStr pub fn new(name: &str, dir: Direction, nonblock: bool) -> Result { Self::open(&CString::new(name).unwrap(), dir, nonblock) } // Does not offer async mode (it's not very Rustic anyway) pub fn open(name: &CStr, dir: Direction, nonblock: bool) -> Result { let mut r = ptr::null_mut(); let stream = match dir { Direction::Capture => alsa::SND_PCM_STREAM_CAPTURE, Direction::Playback => alsa::SND_PCM_STREAM_PLAYBACK }; let flags = if nonblock { alsa::SND_PCM_NONBLOCK } else { 0 }; acheck!(snd_pcm_open(&mut r, name.as_ptr(), stream, flags)).map(|_| PCM(r, cell::Cell::new(false))) } pub fn start(&self) -> Result<()> { acheck!(snd_pcm_start(self.0)).map(|_| ()) } pub fn drop(&self) -> Result<()> { acheck!(snd_pcm_drop(self.0)).map(|_| ()) } pub fn pause(&self, pause: bool) -> Result<()> { acheck!(snd_pcm_pause(self.0, if pause { 1 } else { 0 })).map(|_| ()) } pub fn resume(&self) -> Result<()> { acheck!(snd_pcm_resume(self.0)).map(|_| ()) } pub fn drain(&self) -> Result<()> { acheck!(snd_pcm_drain(self.0)).map(|_| ()) } pub fn prepare(&self) -> Result<()> { acheck!(snd_pcm_prepare(self.0)).map(|_| ()) } pub fn reset(&self) -> Result<()> { acheck!(snd_pcm_reset(self.0)).map(|_| ()) } pub fn recover(&self, err: c_int, silent: bool) -> Result<()> { acheck!(snd_pcm_recover(self.0, err, if silent { 1 } else { 0 })).map(|_| ()) } /// Wrapper around snd_pcm_recover. /// /// Returns Ok if the error was successfully recovered from, or the original /// error if the error was unhandled. pub fn try_recover(&self, err: Error, silent: bool) -> Result<()> { self.recover(err.errno() as c_int, silent) } pub fn wait(&self, timeout_ms: Option) -> Result { acheck!(snd_pcm_wait(self.0, timeout_ms.map(|x| x as c_int).unwrap_or(-1))).map(|i| i == 1) } pub fn state(&self) -> State { let rawstate = self.state_raw(); if let Ok(state) = State::from_c_int(rawstate, "snd_pcm_state") { state } else { panic!("snd_pcm_state returned an invalid value of {}", rawstate); } } /// Only used internally, and for debugging the alsa library. Please use the "state" function instead. pub fn state_raw(&self) -> c_int { unsafe { alsa::snd_pcm_state(self.0) as c_int } } pub fn bytes_to_frames(&self, i: isize) -> Frames { unsafe { alsa::snd_pcm_bytes_to_frames(self.0, i as ssize_t) }} pub fn frames_to_bytes(&self, i: Frames) -> isize { unsafe { alsa::snd_pcm_frames_to_bytes(self.0, i) as isize }} pub fn avail_update(&self) -> Result { acheck!(snd_pcm_avail_update(self.0)) } pub fn avail(&self) -> Result { acheck!(snd_pcm_avail(self.0)) } pub fn avail_delay(&self) -> Result<(Frames, Frames)> { let (mut a, mut d) = (0, 0); acheck!(snd_pcm_avail_delay(self.0, &mut a, &mut d)).map(|_| (a, d)) } pub fn delay(&self) -> Result { let mut d = 0; acheck!(snd_pcm_delay(self.0, &mut d)).map(|_| d) } pub fn status(&self) -> Result { StatusBuilder::new().build(self) } fn verify_format(&self, f: Format) -> Result<()> { let ff = self.hw_params_current().and_then(|h| h.get_format())?; if ff == f { Ok(()) } else { // let s = format!("Invalid sample format ({:?}, expected {:?})", ff, f); Err(Error::unsupported("io_xx")) } } pub fn io_i8(&self) -> Result> { self.io_checked() } pub fn io_u8(&self) -> Result> { self.io_checked() } pub fn io_i16(&self) -> Result> { self.io_checked() } pub fn io_u16(&self) -> Result> { self.io_checked() } pub fn io_i32(&self) -> Result> { self.io_checked() } pub fn io_u32(&self) -> Result> { self.io_checked() } pub fn io_f32(&self) -> Result> { self.io_checked() } pub fn io_f64(&self) -> Result> { self.io_checked() } pub fn io_checked(&self) -> Result> { self.verify_format(S::FORMAT).map(|_| IO::new(self)) } /// Creates IO without checking [`S`] is valid type. /// /// SAFETY: Caller must guarantee [`S`] is valid type for this PCM stream /// and that no other IO objects exist at the same time for the same stream /// (or in some other way guarantee mmap safety) pub unsafe fn io_unchecked(&self) -> IO { IO::new_unchecked(self) } #[deprecated(note = "renamed to io_bytes")] pub fn io(&self) -> IO { IO::new(self) } pub fn io_bytes(&self) -> IO { IO::new(self) } /// Read buffers by talking to the kernel directly, bypassing alsa-lib. pub fn direct_mmap_capture(&self) -> Result> { self.check_has_io(); crate::direct::pcm::new_mmap(self) } /// Write buffers by talking to the kernel directly, bypassing alsa-lib. pub fn direct_mmap_playback(&self) -> Result> { self.check_has_io(); crate::direct::pcm::new_mmap(self) } /// Sets hw parameters. Note: No IO object can exist for this PCM /// when hw parameters are set. pub fn hw_params(&self, h: &HwParams) -> Result<()> { self.check_has_io(); acheck!(snd_pcm_hw_params(self.0, h.0)).map(|_| ()) } /// Retreive current PCM hardware configuration. pub fn hw_params_current(&self) -> Result { HwParams::new(self).and_then(|h| acheck!(snd_pcm_hw_params_current(self.0, h.0)).map(|_| h)) } pub fn sw_params(&self, h: &SwParams) -> Result<()> { acheck!(snd_pcm_sw_params(self.0, h.0)).map(|_| ()) } pub fn sw_params_current(&self) -> Result { SwParams::new(self).and_then(|h| acheck!(snd_pcm_sw_params_current(self.0, h.0)).map(|_| h)) } /// Wraps `snd_pcm_get_params`, returns `(buffer_size, period_size)`. pub fn get_params(&self) -> Result<(u64, u64)> { let mut buffer_size = 0; let mut period_size = 0; acheck!(snd_pcm_get_params(self.0, &mut buffer_size, &mut period_size)) .map(|_| (buffer_size as u64, period_size as u64)) } pub fn info(&self) -> Result { Info::new().and_then(|info| acheck!(snd_pcm_info(self.0, info.0)).map(|_| info )) } pub fn dump(&self, o: &mut Output) -> Result<()> { acheck!(snd_pcm_dump(self.0, super::io::output_handle(o))).map(|_| ()) } pub fn dump_hw_setup(&self, o: &mut Output) -> Result<()> { acheck!(snd_pcm_dump_hw_setup(self.0, super::io::output_handle(o))).map(|_| ()) } pub fn dump_sw_setup(&self, o: &mut Output) -> Result<()> { acheck!(snd_pcm_dump_sw_setup(self.0, super::io::output_handle(o))).map(|_| ()) } pub fn query_chmaps(&self) -> ChmapsQuery { chmap::chmaps_query_new(unsafe { alsa::snd_pcm_query_chmaps(self.0) }) } pub fn set_chmap(&self, c: &Chmap) -> Result<()> { acheck!(snd_pcm_set_chmap(self.0, chmap::chmap_handle(c))).map(|_| ()) } pub fn get_chmap(&self) -> Result { let p = unsafe { alsa::snd_pcm_get_chmap(self.0) }; if p.is_null() { Err(Error::unsupported("snd_pcm_get_chmap")) } else { Ok(chmap::chmap_new(p)) } } pub fn link(&self, other: &PCM) -> Result<()> { acheck!(snd_pcm_link(self.0, other.0)).map(|_| ()) } pub fn unlink(&self) -> Result<()> { acheck!(snd_pcm_unlink(self.0)).map(|_| ()) } } impl Drop for PCM { fn drop(&mut self) { unsafe { alsa::snd_pcm_close(self.0) }; } } impl poll::Descriptors for PCM { fn count(&self) -> usize { unsafe { alsa::snd_pcm_poll_descriptors_count(self.0) as usize } } fn fill(&self, p: &mut [pollfd]) -> Result { let z = unsafe { alsa::snd_pcm_poll_descriptors(self.0, p.as_mut_ptr(), p.len() as c_uint) }; from_code("snd_pcm_poll_descriptors", z).map(|_| z as usize) } fn revents(&self, p: &[pollfd]) -> Result { let mut r = 0; let z = unsafe { alsa::snd_pcm_poll_descriptors_revents(self.0, p.as_ptr() as *mut pollfd, p.len() as c_uint, &mut r) }; from_code("snd_pcm_poll_descriptors_revents", z).map(|_| poll::Flags::from_bits_truncate(r as c_short)) } } /// Sample format dependent struct for reading from and writing data to a `PCM`. /// Also implements `std::io::Read` and `std::io::Write`. /// /// Note: Only one IO object is allowed in scope at a time (for mmap safety). pub struct IO<'a, S: Copy>(&'a PCM, PhantomData); impl<'a, S: Copy> Drop for IO<'a, S> { fn drop(&mut self) { (self.0).1.set(false) } } impl<'a, S: Copy> IO<'a, S> { fn new(a: &'a PCM) -> IO<'a, S> { a.check_has_io(); a.1.set(true); IO(a, PhantomData) } unsafe fn new_unchecked(a: &'a PCM) -> IO<'a, S> { a.1.set(true); IO(a, PhantomData) } fn to_frames(&self, b: usize) -> alsa::snd_pcm_uframes_t { // TODO: Do we need to check for overflow here? self.0.bytes_to_frames((b * size_of::()) as isize) as alsa::snd_pcm_uframes_t } fn from_frames(&self, b: alsa::snd_pcm_uframes_t) -> usize { // TODO: Do we need to check for overflow here? (self.0.frames_to_bytes(b as Frames) as usize) / size_of::() } /// On success, returns number of *frames* written. /// (Multiply with number of channels to get number of items in buf successfully written.) pub fn writei(&self, buf: &[S]) -> Result { acheck!(snd_pcm_writei((self.0).0, buf.as_ptr() as *const c_void, self.to_frames(buf.len()))).map(|r| r as usize) } /// On success, returns number of *frames* read. /// (Multiply with number of channels to get number of items in buf successfully read.) pub fn readi(&self, buf: &mut [S]) -> Result { acheck!(snd_pcm_readi((self.0).0, buf.as_mut_ptr() as *mut c_void, self.to_frames(buf.len()))).map(|r| r as usize) } /// Wrapper around snd_pcm_mmap_begin and snd_pcm_mmap_commit. /// /// You can read/write into the sound card's buffer during the call to the closure. /// According to alsa-lib docs, you should call avail_update before calling this function. /// /// All calculations are in *frames*, i e, the closure should return number of frames processed. /// Also, there might not be as many frames to read/write as requested, and there can even be /// an empty buffer supplied to the closure. /// /// Note: This function works only with interleaved access mode. pub fn mmap usize>(&self, frames: usize, func: F) -> Result { let mut f = frames as alsa::snd_pcm_uframes_t; let mut offs: alsa::snd_pcm_uframes_t = 0; let mut areas = ptr::null(); acheck!(snd_pcm_mmap_begin((self.0).0, &mut areas, &mut offs, &mut f))?; let (first, step) = unsafe { ((*areas).first, (*areas).step) }; if first != 0 || step as isize != self.0.frames_to_bytes(1) * 8 { unsafe { alsa::snd_pcm_mmap_commit((self.0).0, offs, 0) }; // let s = format!("Can only mmap a single interleaved buffer (first = {:?}, step = {:?})", first, step); return Err(Error::unsupported("snd_pcm_mmap_begin")); } let buf = unsafe { let p = ((*areas).addr as *mut S).add(self.from_frames(offs)); ::std::slice::from_raw_parts_mut(p, self.from_frames(f)) }; let fres = func(buf); debug_assert!(fres <= f as usize); acheck!(snd_pcm_mmap_commit((self.0).0, offs, fres as alsa::snd_pcm_uframes_t)).map(|r| r as usize) } } impl<'a, S: Copy> io::Read for IO<'a, S> { fn read(&mut self, buf: &mut [u8]) -> io::Result { let size = self.0.bytes_to_frames(buf.len() as isize) as alsa::snd_pcm_uframes_t; // TODO: Do we need to check for overflow here? let r = unsafe { alsa::snd_pcm_readi((self.0).0, buf.as_mut_ptr() as *mut c_void, size) }; if r < 0 { Err(io::Error::from_raw_os_error(r as i32)) } else { Ok(self.0.frames_to_bytes(r) as usize) } } } impl<'a, S: Copy> io::Write for IO<'a, S> { fn write(&mut self, buf: &[u8]) -> io::Result { let size = self.0.bytes_to_frames(buf.len() as isize) as alsa::snd_pcm_uframes_t; // TODO: Do we need to check for overflow here? let r = unsafe { alsa::snd_pcm_writei((self.0).0, buf.as_ptr() as *const c_void, size) }; if r < 0 { Err(io::Error::from_raw_os_error(r as i32)) } else { Ok(self.0.frames_to_bytes(r) as usize) } } fn flush(&mut self) -> io::Result<()> { Ok(()) } } alsa_enum!( /// [SND_PCM_STATE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants State, ALL_STATES[9], Open = SND_PCM_STATE_OPEN, Setup = SND_PCM_STATE_SETUP, Prepared = SND_PCM_STATE_PREPARED, Running = SND_PCM_STATE_RUNNING, XRun = SND_PCM_STATE_XRUN, Draining = SND_PCM_STATE_DRAINING, Paused = SND_PCM_STATE_PAUSED, Suspended = SND_PCM_STATE_SUSPENDED, Disconnected = SND_PCM_STATE_DISCONNECTED, ); alsa_enum!( #[non_exhaustive] /// [SND_PCM_FORMAT_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants Format, ALL_FORMATS[48], Unknown = SND_PCM_FORMAT_UNKNOWN, S8 = SND_PCM_FORMAT_S8, U8 = SND_PCM_FORMAT_U8, S16LE = SND_PCM_FORMAT_S16_LE, S16BE = SND_PCM_FORMAT_S16_BE, U16LE = SND_PCM_FORMAT_U16_LE, U16BE = SND_PCM_FORMAT_U16_BE, S24LE = SND_PCM_FORMAT_S24_LE, S24BE = SND_PCM_FORMAT_S24_BE, U24LE = SND_PCM_FORMAT_U24_LE, U24BE = SND_PCM_FORMAT_U24_BE, S32LE = SND_PCM_FORMAT_S32_LE, S32BE = SND_PCM_FORMAT_S32_BE, U32LE = SND_PCM_FORMAT_U32_LE, U32BE = SND_PCM_FORMAT_U32_BE, FloatLE = SND_PCM_FORMAT_FLOAT_LE, FloatBE = SND_PCM_FORMAT_FLOAT_BE, Float64LE = SND_PCM_FORMAT_FLOAT64_LE, Float64BE = SND_PCM_FORMAT_FLOAT64_BE, IEC958SubframeLE = SND_PCM_FORMAT_IEC958_SUBFRAME_LE, IEC958SubframeBE = SND_PCM_FORMAT_IEC958_SUBFRAME_BE, MuLaw = SND_PCM_FORMAT_MU_LAW, ALaw = SND_PCM_FORMAT_A_LAW, ImaAdPCM = SND_PCM_FORMAT_IMA_ADPCM, MPEG = SND_PCM_FORMAT_MPEG, GSM = SND_PCM_FORMAT_GSM, Special = SND_PCM_FORMAT_SPECIAL, S243LE = SND_PCM_FORMAT_S24_3LE, S243BE = SND_PCM_FORMAT_S24_3BE, U243LE = SND_PCM_FORMAT_U24_3LE, U243BE = SND_PCM_FORMAT_U24_3BE, S203LE = SND_PCM_FORMAT_S20_3LE, S203BE = SND_PCM_FORMAT_S20_3BE, U203LE = SND_PCM_FORMAT_U20_3LE, U203BE = SND_PCM_FORMAT_U20_3BE, S183LE = SND_PCM_FORMAT_S18_3LE, S183BE = SND_PCM_FORMAT_S18_3BE, U183LE = SND_PCM_FORMAT_U18_3LE, U183BE = SND_PCM_FORMAT_U18_3BE, G72324 = SND_PCM_FORMAT_G723_24, G723241B = SND_PCM_FORMAT_G723_24_1B, G72340 = SND_PCM_FORMAT_G723_40, G723401B = SND_PCM_FORMAT_G723_40_1B, DSDU8 = SND_PCM_FORMAT_DSD_U8, DSDU16LE = SND_PCM_FORMAT_DSD_U16_LE, DSDU32LE = SND_PCM_FORMAT_DSD_U32_LE, DSDU16BE = SND_PCM_FORMAT_DSD_U16_BE, DSDU32BE = SND_PCM_FORMAT_DSD_U32_BE, ); impl fmt::Display for Format { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use Format::*; match *self { S8 => write!(f, "S8"), U8 => write!(f, "U8"), S16LE => write!(f, "S16_LE"), S16BE => write!(f, "S16_BE"), U16LE => write!(f, "U16_LE"), U16BE => write!(f, "U16_BE"), S24LE => write!(f, "S24_LE"), S24BE => write!(f, "S24_BE"), U24LE => write!(f, "U24_LE"), U24BE => write!(f, "U24_BE"), S32LE => write!(f, "S32_LE"), S32BE => write!(f, "S32_BE"), U32LE => write!(f, "U32_LE"), U32BE => write!(f, "U32_BE"), FloatLE => write!(f, "FLOAT_LE"), FloatBE => write!(f, "FLOAT_BE"), Float64LE => write!(f, "FLOAT64_LE"), Float64BE => write!(f, "FLOAT64_BE"), IEC958SubframeLE => write!(f, "IEC958_SUBFRAME_LE"), IEC958SubframeBE => write!(f, "IEC958_SUBFRAME_BE"), MuLaw => write!(f, "MU_LAW"), ALaw => write!(f, "A_LAW"), ImaAdPCM => write!(f, "IMA_ADPCM"), MPEG => write!(f, "MPEG"), GSM => write!(f, "GSM"), Special => write!(f, "SPECIAL"), S243LE => write!(f, "S24_3LE"), S243BE => write!(f, "S24_3BE"), U243LE => write!(f, "U24_3LE"), U243BE => write!(f, "U24_3BE"), S203LE => write!(f, "S20_3LE"), S203BE => write!(f, "S20_3BE"), U203LE => write!(f, "U20_3LE"), U203BE => write!(f, "U20_3BE"), S183LE => write!(f, "S18_3LE"), S183BE => write!(f, "S18_3BE"), U183LE => write!(f, "U18_3LE"), U183BE => write!(f, "U18_3BE"), G72324 => write!(f, "G723_24"), G723241B => write!(f, "G723_24_1B"), G72340 => write!(f, "G723_40"), G723401B => write!(f, "G723_40_1B"), DSDU8 => write!(f, "DSD_U8"), DSDU16LE => write!(f, "DSD_U16_LE"), DSDU32LE => write!(f, "DSD_U32_LE"), DSDU16BE => write!(f, "DSD_U16_BE"), DSDU32BE => write!(f, "DSD_U32_BE"), _ => write!(f, "UNKNOWN"), } } } impl FromStr for Format { type Err = Infallible; fn from_str(s: &str) -> std::result::Result { use Format::*; Ok(match s.to_ascii_uppercase().as_str() { "S8" => S8, "U8" => U8, "S16_LE" => S16LE, "S16_BE" => S16BE, "U16_LE" => U16LE, "U16_BE" => U16BE, "S24_LE" => S24LE, "S24_BE" => S24BE, "U24_LE" => U24LE, "U24_BE" => U24BE, "S32_LE" => S32LE, "S32_BE" => S32BE, "U32_LE" => U32LE, "U32_BE" => U32BE, "FLOAT_LE" => FloatLE, "FLOAT_BE" => FloatBE, "FLOAT64_LE" => Float64LE, "FLOAT64_BE" => Float64BE, "IEC958_SUBFRAME_LE" => IEC958SubframeLE, "IEC958_SUBFRAME_BE" => IEC958SubframeBE, "MU_LAW" => MuLaw, "A_LAW" => ALaw, "IMA_ADPCM" => ImaAdPCM, "MPEG" => MPEG, "GSM" => GSM, "SPECIAL" => Special, "S24_3LE" => S243LE, "S24_3BE" => S243BE, "U24_3LE" => U243LE, "U24_3BE" => U243BE, "S20_3LE" => S203LE, "S20_3BE" => S203BE, "U20_3LE" => U203LE, "U20_3BE" => U203BE, "S18_3LE" => S183LE, "S18_3BE" => S183BE, "U18_3LE" => U183LE, "U18_3BE" => U183BE, "G723_24" => G72324, "G723_24_1B" => G723241B, "G723_40" => G72340, "G723_40_1B" => G723401B, "DSD_U8" => DSDU8, "DSD_U16_LE" => DSDU16LE, "DSD_U32_LE" => DSDU32LE, "DSD_U16_BE" => DSDU16BE, "DSD_U32_BE" => DSDU32BE, _ => Unknown, }) } } impl Format { pub const fn s16() -> Format { ::FORMAT } pub const fn u16() -> Format { ::FORMAT } pub const fn s32() -> Format { ::FORMAT } pub const fn u32() -> Format { ::FORMAT } pub const fn float() -> Format { ::FORMAT } pub const fn float64() -> Format { ::FORMAT } #[cfg(target_endian = "little")] pub const fn s24() -> Format { Format::S24LE } #[cfg(target_endian = "big")] pub const fn s24() -> Format { Format::S24BE } #[cfg(target_endian = "little")] pub const fn s24_3() -> Format { Format::S243LE } #[cfg(target_endian = "big")] pub const fn s24_3() -> Format { Format::S243BE } #[cfg(target_endian = "little")] pub const fn u24() -> Format { Format::U24LE } #[cfg(target_endian = "big")] pub const fn u24() -> Format { Format::U24BE } #[cfg(target_endian = "little")] pub const fn u24_3() -> Format { Format::U243LE } #[cfg(target_endian = "big")] pub const fn u24_3() -> Format { Format::U243BE } #[cfg(target_endian = "little")] pub const fn s20_3() -> Format { Format::S203LE } #[cfg(target_endian = "big")] pub const fn s20_3() -> Format { Format::S203BE } #[cfg(target_endian = "little")] pub const fn u20_3() -> Format { Format::U203LE } #[cfg(target_endian = "big")] pub const fn u20_3() -> Format { Format::U203BE } #[cfg(target_endian = "little")] pub const fn s18_3() -> Format { Format::S183LE } #[cfg(target_endian = "big")] pub const fn s18_3() -> Format { Format::S183BE } #[cfg(target_endian = "little")] pub const fn u18_3() -> Format { Format::U183LE } #[cfg(target_endian = "big")] pub const fn u18_3() -> Format { Format::U183BE } #[cfg(target_endian = "little")] pub const fn dsd_u16() -> Format { Format::DSDU16LE } #[cfg(target_endian = "big")] pub const fn dsd_u16() -> Format { Format::DSDU16BE } #[cfg(target_endian = "little")] pub const fn dsd_u32() -> Format { Format::DSDU32LE } #[cfg(target_endian = "big")] pub const fn dsd_u32() -> Format { Format::DSDU32BE } #[cfg(target_endian = "little")] pub const fn iec958_subframe() -> Format { Format::IEC958SubframeLE } #[cfg(target_endian = "big")] pub const fn iec958_subframe() -> Format { Format::IEC958SubframeBE } pub fn physical_width(&self) -> Result { acheck!(snd_pcm_format_physical_width(self.to_c_int())) } pub fn width(&self) -> Result { acheck!(snd_pcm_format_width(self.to_c_int())) } pub fn silence_16(&self) -> u16 { unsafe { alsa::snd_pcm_format_silence_16(self.to_c_int()) } } pub fn little_endian(&self) -> Result { acheck!(snd_pcm_format_little_endian(self.to_c_int())).map(|v| v != 0) } } pub trait IoFormat: Copy { const FORMAT: Format; } impl IoFormat for i8 { const FORMAT: Format = Format::S8; } impl IoFormat for u8 { const FORMAT: Format = Format::U8; } impl IoFormat for i16 { #[cfg(target_endian = "little")] const FORMAT: Format = Format::S16LE; #[cfg(target_endian = "big")] const FORMAT: Format = Format::S16BE; } impl IoFormat for u16 { #[cfg(target_endian = "little")] const FORMAT: Format = Format::U16LE; #[cfg(target_endian = "big")] const FORMAT: Format = Format::U16BE; } impl IoFormat for i32 { #[cfg(target_endian = "little")] const FORMAT: Format = Format::S32LE; #[cfg(target_endian = "big")] const FORMAT: Format = Format::S32BE; } impl IoFormat for u32 { #[cfg(target_endian = "little")] const FORMAT: Format = Format::U32LE; #[cfg(target_endian = "big")] const FORMAT: Format = Format::U32BE; } impl IoFormat for f32 { #[cfg(target_endian = "little")] const FORMAT: Format = Format::FloatLE; #[cfg(target_endian = "big")] const FORMAT: Format = Format::FloatBE; } impl IoFormat for f64 { #[cfg(target_endian = "little")] const FORMAT: Format = Format::Float64LE; #[cfg(target_endian = "big")] const FORMAT: Format = Format::Float64BE; } alsa_enum!( /// [SND_PCM_ACCESS_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants Access, ALL_ACCESSES[5], MMapInterleaved = SND_PCM_ACCESS_MMAP_INTERLEAVED, MMapNonInterleaved = SND_PCM_ACCESS_MMAP_NONINTERLEAVED, MMapComplex = SND_PCM_ACCESS_MMAP_COMPLEX, RWInterleaved = SND_PCM_ACCESS_RW_INTERLEAVED, RWNonInterleaved = SND_PCM_ACCESS_RW_NONINTERLEAVED, ); alsa_enum!( /// [SND_PCM_TSTAMP_TYPE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants TstampType, ALL_TSTAMP_TYPES[3], Gettimeofday = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY, Monotonic = SND_PCM_TSTAMP_TYPE_MONOTONIC, MonotonicRaw = SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW, ); /// [snd_pcm_hw_params_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___h_w___params.html) wrapper pub struct HwParams<'a>(*mut alsa::snd_pcm_hw_params_t, &'a PCM); impl<'a> Drop for HwParams<'a> { fn drop(&mut self) { unsafe { alsa::snd_pcm_hw_params_free(self.0) }; } } impl<'a> HwParams<'a> { fn new(a: &'a PCM) -> Result> { let mut p = ptr::null_mut(); acheck!(snd_pcm_hw_params_malloc(&mut p)).map(|_| HwParams(p, a)) } pub fn any(a: &'a PCM) -> Result> { HwParams::new(a).and_then(|p| acheck!(snd_pcm_hw_params_any(a.0, p.0)).map(|_| p) )} pub fn get_rate_resample(&self) -> Result { let mut v = 0; acheck!(snd_pcm_hw_params_get_rate_resample((self.1).0, self.0, &mut v)).map(|_| v != 0) } pub fn set_rate_resample(&self, resample: bool) -> Result<()> { acheck!(snd_pcm_hw_params_set_rate_resample((self.1).0, self.0, if resample {1} else {0})).map(|_| ()) } pub fn set_channels_near(&self, v: u32) -> Result { let mut r = v as c_uint; acheck!(snd_pcm_hw_params_set_channels_near((self.1).0, self.0, &mut r)).map(|_| r) } pub fn set_channels(&self, v: u32) -> Result<()> { acheck!(snd_pcm_hw_params_set_channels((self.1).0, self.0, v as c_uint)).map(|_| ()) } pub fn get_channels(&self) -> Result { let mut v = 0; acheck!(snd_pcm_hw_params_get_channels(self.0, &mut v)).map(|_| v as u32) } pub fn get_channels_max(&self) -> Result { let mut v = 0; acheck!(snd_pcm_hw_params_get_channels_max(self.0, &mut v)).map(|_| v as u32) } pub fn get_channels_min(&self) -> Result { let mut v = 0; acheck!(snd_pcm_hw_params_get_channels_min(self.0, &mut v)).map(|_| v as u32) } pub fn test_channels(&self, v: u32) -> Result<()> { acheck!(snd_pcm_hw_params_test_channels((self.1).0, self.0, v as c_uint)).map(|_| ()) } pub fn set_rate_near(&self, v: u32, dir: ValueOr) -> Result { let mut d = dir as c_int; let mut r = v as c_uint; acheck!(snd_pcm_hw_params_set_rate_near((self.1).0, self.0, &mut r, &mut d)).map(|_| r) } pub fn set_rate(&self, v: u32, dir: ValueOr) -> Result<()> { acheck!(snd_pcm_hw_params_set_rate((self.1).0, self.0, v as c_uint, dir as c_int)).map(|_| ()) } pub fn get_rate(&self) -> Result { let (mut v, mut d) = (0,0); acheck!(snd_pcm_hw_params_get_rate(self.0, &mut v, &mut d)).map(|_| v as u32) } pub fn get_rate_max(&self) -> Result { let mut v = 0; // Note on the null ptr: if this ptr is not null, then the value behind it is replaced with // -1 if the suprenum is not in the set (i.e. it's an open range), 0 otherwise. This could // be returned along with the value, but it's safe to pass a null ptr in, in which case the // pointer is not dereferenced. acheck!(snd_pcm_hw_params_get_rate_max(self.0, &mut v, ptr::null_mut())).map(|_| v as u32) } pub fn get_rate_min(&self) -> Result { let mut v = 0; // Note on the null ptr: see get_rate_max but read +1 and infinum instead of -1 and // suprenum. acheck!(snd_pcm_hw_params_get_rate_min(self.0, &mut v, ptr::null_mut())).map(|_| v as u32) } pub fn test_rate(&self, rate: u32) -> Result<()> { acheck!(snd_pcm_hw_params_test_rate((self.1).0, self.0, rate as c_uint, 0)).map(|_| ()) } pub fn set_format(&self, v: Format) -> Result<()> { acheck!(snd_pcm_hw_params_set_format((self.1).0, self.0, v as c_int)).map(|_| ()) } pub fn get_format(&self) -> Result { let mut v = 0; acheck!(snd_pcm_hw_params_get_format(self.0, &mut v)) .and_then(|_| Format::from_c_int(v, "snd_pcm_hw_params_get_format")) } pub fn test_format(&self, v: Format) -> Result<()> { acheck!(snd_pcm_hw_params_test_format((self.1).0, self.0, v as c_int)).map(|_| ()) } pub fn set_access(&self, v: Access) -> Result<()> { acheck!(snd_pcm_hw_params_set_access((self.1).0, self.0, v as c_uint)).map(|_| ()) } pub fn get_access(&self) -> Result { let mut v = 0; acheck!(snd_pcm_hw_params_get_access(self.0, &mut v)) .and_then(|_| Access::from_c_int(v as c_int, "snd_pcm_hw_params_get_access")) } pub fn set_period_size_near(&self, v: Frames, dir: ValueOr) -> Result { let mut d = dir as c_int; let mut r = v as alsa::snd_pcm_uframes_t; acheck!(snd_pcm_hw_params_set_period_size_near((self.1).0, self.0, &mut r, &mut d)).map(|_| r as Frames) } pub fn set_period_size(&self, v: Frames, dir: ValueOr) -> Result<()> { acheck!(snd_pcm_hw_params_set_period_size((self.1).0, self.0, v as alsa::snd_pcm_uframes_t, dir as c_int)).map(|_| ()) } pub fn set_period_time_near(&self, v: u32, dir: ValueOr) -> Result { let mut d = dir as c_int; let mut r = v as c_uint; acheck!(snd_pcm_hw_params_set_period_time_near((self.1).0, self.0, &mut r, &mut d)).map(|_| r as u32) } pub fn get_period_size(&self) -> Result { let (mut v, mut d) = (0,0); acheck!(snd_pcm_hw_params_get_period_size(self.0, &mut v, &mut d)).map(|_| v as Frames) } pub fn get_period_size_min(&self) -> Result { let (mut v, mut d) = (0,0); acheck!(snd_pcm_hw_params_get_period_size_min(self.0, &mut v, &mut d)).map(|_| v as Frames) } pub fn get_period_size_max(&self) -> Result { let (mut v, mut d) = (0,0); acheck!(snd_pcm_hw_params_get_period_size_max(self.0, &mut v, &mut d)).map(|_| v as Frames) } pub fn set_periods(&self, v: u32, dir: ValueOr) -> Result<()> { acheck!(snd_pcm_hw_params_set_periods((self.1).0, self.0, v as c_uint, dir as c_int)).map(|_| ()) } pub fn get_periods(&self) -> Result { let (mut v, mut d) = (0,0); acheck!(snd_pcm_hw_params_get_periods(self.0, &mut v, &mut d)).map(|_| v as u32) } pub fn set_buffer_size_near(&self, v: Frames) -> Result { let mut r = v as alsa::snd_pcm_uframes_t; acheck!(snd_pcm_hw_params_set_buffer_size_near((self.1).0, self.0, &mut r)).map(|_| r as Frames) } pub fn set_buffer_size_max(&self, v: Frames) -> Result { let mut r = v as alsa::snd_pcm_uframes_t; acheck!(snd_pcm_hw_params_set_buffer_size_max((self.1).0, self.0, &mut r)).map(|_| r as Frames) } pub fn set_buffer_size_min(&self, v: Frames) -> Result { let mut r = v as alsa::snd_pcm_uframes_t; acheck!(snd_pcm_hw_params_set_buffer_size_min((self.1).0, self.0, &mut r)).map(|_| r as Frames) } pub fn set_buffer_size(&self, v: Frames) -> Result<()> { acheck!(snd_pcm_hw_params_set_buffer_size((self.1).0, self.0, v as alsa::snd_pcm_uframes_t)).map(|_| ()) } pub fn set_buffer_time_near(&self, v: u32, dir: ValueOr) -> Result { let mut d = dir as c_int; let mut r = v as c_uint; acheck!(snd_pcm_hw_params_set_buffer_time_near((self.1).0, self.0, &mut r, &mut d)).map(|_| r as u32) } pub fn get_buffer_size(&self) -> Result { let mut v = 0; acheck!(snd_pcm_hw_params_get_buffer_size(self.0, &mut v)).map(|_| v as Frames) } pub fn get_buffer_size_min(&self) -> Result { let mut v = 0; acheck!(snd_pcm_hw_params_get_buffer_size_min(self.0, &mut v)).map(|_| v as Frames) } pub fn get_buffer_size_max(&self) -> Result { let mut v = 0; acheck!(snd_pcm_hw_params_get_buffer_size_max(self.0, &mut v)).map(|_| v as Frames) } pub fn get_buffer_time_min(&self) -> Result { let (mut v, mut d) = (0,0); acheck!(snd_pcm_hw_params_get_buffer_time_min(self.0, &mut v, &mut d)).map(|_| v as u32) } pub fn get_buffer_time_max(&self) -> Result { let (mut v, mut d) = (0,0); acheck!(snd_pcm_hw_params_get_buffer_time_max(self.0, &mut v, &mut d)).map(|_| v as u32) } /// Returns true if the alsa stream can be paused, false if not. /// /// This function should only be called when the configuration space contains a single /// configuration. Call `PCM::hw_params` to choose a single configuration from the /// configuration space. pub fn can_pause(&self) -> bool { unsafe { alsa::snd_pcm_hw_params_can_pause(self.0) != 0 } } /// Returns true if the alsa stream can be resumed, false if not. /// /// This function should only be called when the configuration space contains a single /// configuration. Call `PCM::hw_params` to choose a single configuration from the /// configuration space. pub fn can_resume(&self) -> bool { unsafe { alsa::snd_pcm_hw_params_can_resume(self.0) != 0 } } /// Returns true if the alsa stream supports the provided `AudioTstampType`, false if not. /// /// This function should only be called when the configuration space contains a single /// configuration. Call `PCM::hw_params` to choose a single configuration from the /// configuration space. pub fn supports_audio_ts_type(&self, type_: AudioTstampType) -> bool { unsafe { alsa::snd_pcm_hw_params_supports_audio_ts_type(self.0, type_ as libc::c_int) != 0 } } pub fn dump(&self, o: &mut Output) -> Result<()> { acheck!(snd_pcm_hw_params_dump(self.0, super::io::output_handle(o))).map(|_| ()) } pub fn copy_from(&mut self, other: &HwParams<'a>) { self.1 = other.1; unsafe { alsa::snd_pcm_hw_params_copy(self.0, other.0) }; } } impl<'a> Clone for HwParams<'a> { fn clone(&self) -> HwParams<'a> { let mut r = HwParams::new(self.1).unwrap(); r.copy_from(self); r } } impl<'a> fmt::Debug for HwParams<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("HwParams") .field("channels", &self.get_channels()) .field("rate", &format!("{:?} Hz", self.get_rate())) .field("format", &self.get_format()) .field("access", &self.get_access()) .field("period_size", &format!("{:?} frames", self.get_period_size())) .field("buffer_size", &format!("{:?} frames", self.get_buffer_size())) .finish() } } /// [snd_pcm_sw_params_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___s_w___params.html) wrapper pub struct SwParams<'a>(*mut alsa::snd_pcm_sw_params_t, &'a PCM); impl<'a> Drop for SwParams<'a> { fn drop(&mut self) { unsafe { alsa::snd_pcm_sw_params_free(self.0) }; } } impl<'a> SwParams<'a> { fn new(a: &'a PCM) -> Result> { let mut p = ptr::null_mut(); acheck!(snd_pcm_sw_params_malloc(&mut p)).map(|_| SwParams(p, a)) } pub fn set_avail_min(&self, v: Frames) -> Result<()> { acheck!(snd_pcm_sw_params_set_avail_min((self.1).0, self.0, v as alsa::snd_pcm_uframes_t)).map(|_| ()) } pub fn get_avail_min(&self) -> Result { let mut v = 0; acheck!(snd_pcm_sw_params_get_avail_min(self.0, &mut v)).map(|_| v as Frames) } pub fn get_boundary(&self) -> Result { let mut v = 0; acheck!(snd_pcm_sw_params_get_boundary(self.0, &mut v)).map(|_| v as Frames) } pub fn set_start_threshold(&self, v: Frames) -> Result<()> { acheck!(snd_pcm_sw_params_set_start_threshold((self.1).0, self.0, v as alsa::snd_pcm_uframes_t)).map(|_| ()) } pub fn get_start_threshold(&self) -> Result { let mut v = 0; acheck!(snd_pcm_sw_params_get_start_threshold(self.0, &mut v)).map(|_| v as Frames) } pub fn set_stop_threshold(&self, v: Frames) -> Result<()> { acheck!(snd_pcm_sw_params_set_stop_threshold((self.1).0, self.0, v as alsa::snd_pcm_uframes_t)).map(|_| ()) } pub fn get_stop_threshold(&self) -> Result { let mut v = 0; acheck!(snd_pcm_sw_params_get_stop_threshold(self.0, &mut v)).map(|_| v as Frames) } pub fn set_tstamp_mode(&self, v: bool) -> Result<()> { let z = if v { alsa::SND_PCM_TSTAMP_ENABLE } else { alsa::SND_PCM_TSTAMP_NONE }; acheck!(snd_pcm_sw_params_set_tstamp_mode((self.1).0, self.0, z)).map(|_| ()) } pub fn get_tstamp_mode(&self) -> Result { let mut v = 0; acheck!(snd_pcm_sw_params_get_tstamp_mode(self.0, &mut v)).map(|_| v != 0) } pub fn set_tstamp_type(&self, v: TstampType) -> Result<()> { acheck!(snd_pcm_sw_params_set_tstamp_type((self.1).0, self.0, v as u32)).map(|_| ()) } pub fn get_tstamp_type(&self) -> Result { let mut v = 0; acheck!(snd_pcm_sw_params_get_tstamp_type(self.0, &mut v))?; TstampType::from_c_int(v as c_int, "snd_pcm_sw_params_get_tstamp_type") } pub fn dump(&self, o: &mut Output) -> Result<()> { acheck!(snd_pcm_sw_params_dump(self.0, super::io::output_handle(o))).map(|_| ()) } } impl<'a> fmt::Debug for SwParams<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "SwParams(avail_min: {:?} frames, start_threshold: {:?} frames, stop_threshold: {:?} frames)", self.get_avail_min(), self.get_start_threshold(), self.get_stop_threshold()) } } const STATUS_SIZE: usize = 152; /// [snd_pcm_status_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___status.html) wrapper pub struct Status([u8; STATUS_SIZE]); impl Status { fn new() -> Status { assert!(unsafe { alsa::snd_pcm_status_sizeof() } as usize <= STATUS_SIZE); Status([0; STATUS_SIZE]) } fn ptr(&self) -> *mut alsa::snd_pcm_status_t { self.0.as_ptr() as *const _ as *mut alsa::snd_pcm_status_t } pub fn get_htstamp(&self) -> timespec { let mut h = timespec {tv_sec: 0, tv_nsec: 0}; unsafe { alsa::snd_pcm_status_get_htstamp(self.ptr(), &mut h) }; h } pub fn get_trigger_htstamp(&self) -> timespec { let mut h = timespec {tv_sec: 0, tv_nsec: 0}; unsafe { alsa::snd_pcm_status_get_trigger_htstamp(self.ptr(), &mut h) }; h } pub fn get_audio_htstamp(&self) -> timespec { let mut h = timespec {tv_sec: 0, tv_nsec: 0}; unsafe { alsa::snd_pcm_status_get_audio_htstamp(self.ptr(), &mut h) }; h } pub fn get_state(&self) -> State { State::from_c_int( unsafe { alsa::snd_pcm_status_get_state(self.ptr()) } as c_int, "snd_pcm_status_get_state").unwrap() } pub fn get_avail(&self) -> Frames { unsafe { alsa::snd_pcm_status_get_avail(self.ptr()) as Frames }} pub fn get_delay(&self) -> Frames { unsafe { alsa::snd_pcm_status_get_delay(self.ptr()) }} pub fn get_avail_max(&self) -> Frames { unsafe { alsa::snd_pcm_status_get_avail_max(self.ptr()) as Frames }} pub fn get_overrange(&self) -> Frames { unsafe { alsa::snd_pcm_status_get_overrange(self.ptr()) as Frames }} pub fn dump(&self, o: &mut Output) -> Result<()> { acheck!(snd_pcm_status_dump(self.ptr(), super::io::output_handle(o))).map(|_| ()) } } /// Builder for [`Status`]. /// /// Allows setting the audio timestamp configuration before retrieving the /// status from the stream. pub struct StatusBuilder(Status); impl StatusBuilder { pub fn new() -> Self { StatusBuilder(Status::new()) } pub fn audio_htstamp_config( self, type_requested: AudioTstampType, report_delay: bool, ) -> Self { let mut cfg: alsa::snd_pcm_audio_tstamp_config_t = unsafe { std::mem::zeroed() }; cfg.set_type_requested(type_requested as _); cfg.set_report_delay(report_delay as _); unsafe { alsa::snd_pcm_status_set_audio_htstamp_config(self.0.ptr(), &mut cfg) }; self } pub fn build(self, pcm: &PCM) -> Result { acheck!(snd_pcm_status(pcm.0, self.0.ptr())).map(|_| self.0) } } alsa_enum!( #[non_exhaustive] /// [SND_PCM_AUDIO_TSTAMP_TYPE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants AudioTstampType, ALL_AUDIO_TSTAMP_TYPES[6], Compat = SND_PCM_AUDIO_TSTAMP_TYPE_COMPAT, Default = SND_PCM_AUDIO_TSTAMP_TYPE_DEFAULT, Link = SND_PCM_AUDIO_TSTAMP_TYPE_LINK, LinkAbsolute = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE, LinkEstimated = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED, LinkSynchronized = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED, ); #[test] fn info_from_default() { use std::ffi::CString; let pcm = PCM::open(&*CString::new("default").unwrap(), Direction::Capture, false).unwrap(); let info = pcm.info().unwrap(); println!("PCM Info:"); println!("\tCard: {}", info.get_card()); println!("\tDevice: {}", info.get_device()); println!("\tSubdevice: {}", info.get_subdevice()); println!("\tId: {}", info.get_id().unwrap()); println!("\tName: {}", info.get_name().unwrap()); println!("\tSubdevice Name: {}", info.get_subdevice_name().unwrap()); } #[test] fn drop() { use std::ffi::CString; let pcm = PCM::open(&*CString::new("default").unwrap(), Direction::Capture, false).unwrap(); // Verify that this does not cause a naming conflict (issue #14) let _ = pcm.drop(); } #[test] fn record_from_default() { use std::ffi::CString; let pcm = PCM::open(&*CString::new("default").unwrap(), Direction::Capture, false).unwrap(); let hwp = HwParams::any(&pcm).unwrap(); hwp.set_channels(2).unwrap(); hwp.set_rate(44100, ValueOr::Nearest).unwrap(); hwp.set_format(Format::s16()).unwrap(); hwp.set_access(Access::RWInterleaved).unwrap(); pcm.hw_params(&hwp).unwrap(); pcm.start().unwrap(); let mut buf = [0i16; 1024]; assert_eq!(pcm.io_i16().unwrap().readi(&mut buf).unwrap(), 1024/2); } #[test] fn playback_to_default() { use std::ffi::CString; let pcm = PCM::open(&*CString::new("default").unwrap(), Direction::Playback, false).unwrap(); let hwp = HwParams::any(&pcm).unwrap(); hwp.set_channels(1).unwrap(); hwp.set_rate(44100, ValueOr::Nearest).unwrap(); hwp.set_format(Format::s16()).unwrap(); hwp.set_access(Access::RWInterleaved).unwrap(); pcm.hw_params(&hwp).unwrap(); let hwp = pcm.hw_params_current().unwrap(); let swp = pcm.sw_params_current().unwrap(); swp.set_start_threshold(hwp.get_buffer_size().unwrap()).unwrap(); pcm.sw_params(&swp).unwrap(); println!("PCM status: {:?}, {:?}", pcm.state(), pcm.hw_params_current().unwrap()); let mut outp = Output::buffer_open().unwrap(); pcm.dump(&mut outp).unwrap(); println!("== PCM dump ==\n{}", outp); let mut buf = [0i16; 1024]; for (i, a) in buf.iter_mut().enumerate() { *a = ((i as f32 * 2.0 * ::std::f32::consts::PI / 128.0).sin() * 8192.0) as i16 } let io = pcm.io_i16().unwrap(); for _ in 0..2*44100/1024 { // 2 seconds of playback println!("PCM state: {:?}", pcm.state()); assert_eq!(io.writei(&buf[..]).unwrap(), 1024); } if pcm.state() != State::Running { pcm.start().unwrap() }; let mut outp2 = Output::buffer_open().unwrap(); pcm.status().unwrap().dump(&mut outp2).unwrap(); println!("== PCM status dump ==\n{}", outp2); pcm.drain().unwrap(); } #[test] fn print_sizeof() { let s = unsafe { alsa::snd_pcm_status_sizeof() } as usize; println!("Status size: {}", s); assert!(s <= STATUS_SIZE); } #[test] fn format_display_from_str() { for format in ALL_FORMATS { assert_eq!(format, format.to_string().parse().unwrap()); } } alsa-0.9.1/src/poll.rs000064400000000000000000000043651046102023000126660ustar 00000000000000//! Tiny poll ffi //! //! A tiny wrapper around libc's poll system call. use libc; use super::error::*; use std::io; pub use libc::pollfd; bitflags! { #[repr(transparent)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Flags: ::libc::c_short { const IN = ::libc::POLLIN; const PRI = ::libc::POLLPRI; const OUT = ::libc::POLLOUT; const ERR = ::libc::POLLERR; const HUP = ::libc::POLLHUP; const NVAL = ::libc::POLLNVAL; } } pub trait Descriptors { fn count(&self) -> usize; fn fill(&self, _: &mut [pollfd]) -> Result; fn revents(&self, _: &[pollfd]) -> Result; /// Wrapper around count and fill - returns an array of pollfds fn get(&self) -> Result> { let mut v = vec![pollfd { fd: 0, events: 0, revents: 0 }; self.count()]; if self.fill(&mut v)? != v.len() { Err(Error::unsupported("did not fill the poll descriptors array")) } else { Ok(v) } } } impl Descriptors for pollfd { fn count(&self) -> usize { 1 } fn fill(&self, a: &mut [pollfd]) -> Result { a[0] = *self; Ok(1) } fn revents(&self, a: &[pollfd]) -> Result { Ok(Flags::from_bits_truncate(a[0].revents)) } } /// Wrapper around the libc poll call. pub fn poll(fds: &mut[pollfd], timeout: i32) -> Result { let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::nfds_t, timeout as libc::c_int) }; if r >= 0 { Ok(r as usize) } else { from_code("poll", -io::Error::last_os_error().raw_os_error().unwrap()).map(|_| unreachable!()) } } /// Builds a pollfd array, polls it, and returns the poll descriptors which have non-zero revents. pub fn poll_all<'a>(desc: &[&'a dyn Descriptors], timeout: i32) -> Result> { let mut pollfds: Vec = vec!(); let mut indices = vec!(); for v2 in desc.iter().map(|q| q.get()) { let v = v2?; indices.push(pollfds.len() .. pollfds.len()+v.len()); pollfds.extend(v); }; poll(&mut pollfds, timeout)?; let mut res = vec!(); for (i, r) in indices.into_iter().enumerate() { let z = desc[i].revents(&pollfds[r])?; if !z.is_empty() { res.push((desc[i], z)); } } Ok(res) } alsa-0.9.1/src/rawmidi.rs000064400000000000000000000176321046102023000133550ustar 00000000000000//! MIDI devices I/O and enumeration use libc::{c_int, c_uint, c_void, size_t, c_short, pollfd}; use super::ctl_int::{ctl_ptr, Ctl}; use super::{Direction, poll}; use super::error::*; use crate::alsa; use std::{ptr, io}; use std::ffi::{CStr, CString}; /// Iterator over [Rawmidi](http://www.alsa-project.org/alsa-doc/alsa-lib/group___raw_midi.html) devices and subdevices pub struct Iter<'a> { ctl: &'a Ctl, device: c_int, in_count: i32, out_count: i32, current: i32, } /// [snd_rawmidi_info_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___raw_midi.html) wrapper pub struct Info(*mut alsa::snd_rawmidi_info_t); impl Drop for Info { fn drop(&mut self) { unsafe { alsa::snd_rawmidi_info_free(self.0) }; } } impl Info { fn new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_rawmidi_info_malloc(&mut p)).map(|_| Info(p)) } fn from_iter(c: &Ctl, device: i32, sub: i32, dir: Direction) -> Result { let r = Info::new()?; unsafe { alsa::snd_rawmidi_info_set_device(r.0, device as c_uint) }; let d = match dir { Direction::Playback => alsa::SND_RAWMIDI_STREAM_OUTPUT, Direction::Capture => alsa::SND_RAWMIDI_STREAM_INPUT, }; unsafe { alsa::snd_rawmidi_info_set_stream(r.0, d) }; unsafe { alsa::snd_rawmidi_info_set_subdevice(r.0, sub as c_uint) }; acheck!(snd_ctl_rawmidi_info(ctl_ptr(c), r.0)).map(|_| r) } fn subdev_count(c: &Ctl, device: c_int) -> Result<(i32, i32)> { let i = Info::from_iter(c, device, 0, Direction::Capture)?; let o = Info::from_iter(c, device, 0, Direction::Playback)?; Ok((unsafe { alsa::snd_rawmidi_info_get_subdevices_count(o.0) as i32 }, unsafe { alsa::snd_rawmidi_info_get_subdevices_count(i.0) as i32 })) } pub fn get_device(&self) -> i32 { unsafe { alsa::snd_rawmidi_info_get_device(self.0) as i32 }} pub fn get_subdevice(&self) -> i32 { unsafe { alsa::snd_rawmidi_info_get_subdevice(self.0) as i32 }} pub fn get_stream(&self) -> super::Direction { if unsafe { alsa::snd_rawmidi_info_get_stream(self.0) } == alsa::SND_RAWMIDI_STREAM_OUTPUT { super::Direction::Playback } else { super::Direction::Capture } } pub fn get_subdevice_name(&self) -> Result { let c = unsafe { alsa::snd_rawmidi_info_get_subdevice_name(self.0) }; from_const("snd_rawmidi_info_get_subdevice_name", c).map(|s| s.to_string()) } pub fn get_id(&self) -> Result { let c = unsafe { alsa::snd_rawmidi_info_get_id(self.0) }; from_const("snd_rawmidi_info_get_id", c).map(|s| s.to_string()) } } /// [snd_rawmidi_info_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___raw_midi.html) wrapper pub struct Status(*mut alsa::snd_rawmidi_status_t); impl Status { fn new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_rawmidi_status_malloc(&mut p)).map(|_| Status(p)) } } impl Status { pub fn get_avail(&self) -> usize { unsafe { alsa::snd_rawmidi_status_get_avail(self.0 as *const _) } } pub fn get_xruns(&self) -> usize { unsafe { alsa::snd_rawmidi_status_get_xruns(self.0 as *const _) } } } impl Drop for Status { fn drop(&mut self) { unsafe { alsa::snd_rawmidi_status_free(self.0) }; } } impl<'a> Iter<'a> { pub fn new(c: &'a Ctl) -> Iter<'a> { Iter { ctl: c, device: -1, in_count: 0, out_count: 0, current: 0 }} } impl<'a> Iterator for Iter<'a> { type Item = Result; fn next(&mut self) -> Option> { if self.current < self.in_count { self.current += 1; return Some(Info::from_iter(self.ctl, self.device, self.current-1, Direction::Capture)); } if self.current - self.in_count < self.out_count { self.current += 1; return Some(Info::from_iter(self.ctl, self.device, self.current-1-self.in_count, Direction::Playback)); } let r = acheck!(snd_ctl_rawmidi_next_device(ctl_ptr(self.ctl), &mut self.device)); match r { Err(e) => return Some(Err(e)), Ok(_) if self.device == -1 => return None, _ => {}, } self.current = 0; match Info::subdev_count(self.ctl, self.device) { Err(e) => Some(Err(e)), Ok((oo, ii)) => { self.in_count = ii; self.out_count = oo; self.next() } } } } /// [snd_rawmidi_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___raw_midi.html) wrapper pub struct Rawmidi(*mut alsa::snd_rawmidi_t); unsafe impl Send for Rawmidi {} impl Drop for Rawmidi { fn drop(&mut self) { unsafe { alsa::snd_rawmidi_close(self.0) }; } } impl Rawmidi { /// Wrapper around open that takes a &str instead of a &CStr pub fn new(name: &str, dir: Direction, nonblock: bool) -> Result { Self::open(&CString::new(name).unwrap(), dir, nonblock) } pub fn open(name: &CStr, dir: Direction, nonblock: bool) -> Result { let mut h = ptr::null_mut(); let flags = if nonblock { 2 } else { 0 }; // FIXME: alsa::SND_RAWMIDI_NONBLOCK does not exist in alsa-sys acheck!(snd_rawmidi_open( if dir == Direction::Capture { &mut h } else { ptr::null_mut() }, if dir == Direction::Playback { &mut h } else { ptr::null_mut() }, name.as_ptr(), flags)) .map(|_| Rawmidi(h)) } pub fn info(&self) -> Result { Info::new().and_then(|i| acheck!(snd_rawmidi_info(self.0, i.0)).map(|_| i)) } pub fn status(&self) -> Result { Status::new().and_then(|i| acheck!(snd_rawmidi_status(self.0, i.0)).map(|_| i)) } pub fn drop(&self) -> Result<()> { acheck!(snd_rawmidi_drop(self.0)).map(|_| ()) } pub fn drain(&self) -> Result<()> { acheck!(snd_rawmidi_drain(self.0)).map(|_| ()) } pub fn name(&self) -> Result { let c = unsafe { alsa::snd_rawmidi_name(self.0) }; from_const("snd_rawmidi_name", c).map(|s| s.to_string()) } pub fn io(&self) -> IO { IO(self) } } impl poll::Descriptors for Rawmidi { fn count(&self) -> usize { unsafe { alsa::snd_rawmidi_poll_descriptors_count(self.0) as usize } } fn fill(&self, p: &mut [pollfd]) -> Result { let z = unsafe { alsa::snd_rawmidi_poll_descriptors(self.0, p.as_mut_ptr(), p.len() as c_uint) }; from_code("snd_rawmidi_poll_descriptors", z).map(|_| z as usize) } fn revents(&self, p: &[pollfd]) -> Result { let mut r = 0; let z = unsafe { alsa::snd_rawmidi_poll_descriptors_revents(self.0, p.as_ptr() as *mut pollfd, p.len() as c_uint, &mut r) }; from_code("snd_rawmidi_poll_descriptors_revents", z).map(|_| poll::Flags::from_bits_truncate(r as c_short)) } } /// Implements `std::io::Read` and `std::io::Write` for `Rawmidi` pub struct IO<'a>(&'a Rawmidi); impl<'a> io::Read for IO<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result { let r = unsafe { alsa::snd_rawmidi_read((self.0).0, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) }; if r < 0 { Err(io::Error::from_raw_os_error(r as i32)) } else { Ok(r as usize) } } } impl<'a> io::Write for IO<'a> { fn write(&mut self, buf: &[u8]) -> io::Result { let r = unsafe { alsa::snd_rawmidi_write((self.0).0, buf.as_ptr() as *const c_void, buf.len() as size_t) }; if r < 0 { Err(io::Error::from_raw_os_error(r as i32)) } else { Ok(r as usize) } } fn flush(&mut self) -> io::Result<()> { Ok(()) } } #[test] fn print_rawmidis() { for a in super::card::Iter::new().map(|a| a.unwrap()) { for b in Iter::new(&Ctl::from_card(&a, false).unwrap()).map(|b| b.unwrap()) { println!("Rawmidi {:?} (hw:{},{},{}) {} - {}", b.get_stream(), a.get_index(), b.get_device(), b.get_subdevice(), a.get_name().unwrap(), b.get_subdevice_name().unwrap()) } } } alsa-0.9.1/src/seq.rs000064400000000000000000001725621046102023000125150ustar 00000000000000//! MIDI sequencer I/O and enumeration use libc::{c_uint, c_int, c_short, c_uchar, c_void, c_long, size_t, pollfd}; use super::error::*; use crate::alsa; use super::{Direction, poll}; use std::{ptr, fmt, mem, slice, time, cell}; use std::str::{FromStr, Split}; use std::ffi::CStr; use std::borrow::Cow; // Workaround for improper alignment of snd_seq_ev_ext_t in alsa-sys #[repr(packed)] struct EvExtPacked { len: c_uint, ptr: *mut c_void, } /// [snd_seq_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___sequencer.html) wrapper /// /// To access the functions `event_input`, `event_input_pending` and `set_input_buffer_size`, /// you first have to obtain an instance of `Input` by calling `input()`. Only one instance of /// `Input` may exist at any time for a given `Seq`. pub struct Seq(*mut alsa::snd_seq_t, cell::Cell); unsafe impl Send for Seq {} impl Drop for Seq { fn drop(&mut self) { unsafe { alsa::snd_seq_close(self.0) }; } } impl Seq { fn check_has_input(&self) { if self.1.get() { panic!("No additional Input object allowed")} } /// Opens the sequencer. /// /// If name is None, "default" will be used. That's almost always what you usually want to use anyway. pub fn open(name: Option<&CStr>, dir: Option, nonblock: bool) -> Result { let n2 = name.unwrap_or(unsafe { CStr::from_bytes_with_nul_unchecked(b"default\0") }); let mut h = ptr::null_mut(); let mode = if nonblock { alsa::SND_SEQ_NONBLOCK } else { 0 }; let streams = match dir { None => alsa::SND_SEQ_OPEN_DUPLEX, Some(Direction::Playback) => alsa::SND_SEQ_OPEN_OUTPUT, Some(Direction::Capture) => alsa::SND_SEQ_OPEN_INPUT, }; acheck!(snd_seq_open(&mut h, n2.as_ptr(), streams, mode)) .map(|_| Seq(h, cell::Cell::new(false))) } pub fn set_client_name(&self, name: &CStr) -> Result<()> { acheck!(snd_seq_set_client_name(self.0, name.as_ptr())).map(|_| ()) } pub fn set_client_event_filter(&self, event_type: i32) -> Result<()> { acheck!(snd_seq_set_client_event_filter(self.0, event_type as c_int)).map(|_| ()) } pub fn set_client_pool_output(&self, size: u32) -> Result<()> { acheck!(snd_seq_set_client_pool_output(self.0, size as size_t)).map(|_| ()) } pub fn set_client_pool_input(&self, size: u32) -> Result<()> { acheck!(snd_seq_set_client_pool_input(self.0, size as size_t)).map(|_| ()) } pub fn set_client_pool_output_room(&self, size: u32) -> Result<()> { acheck!(snd_seq_set_client_pool_output_room(self.0, size as size_t)).map(|_| ()) } pub fn client_id(&self) -> Result { acheck!(snd_seq_client_id(self.0)).map(|q| q as i32) } pub fn drain_output(&self) -> Result { acheck!(snd_seq_drain_output(self.0)).map(|q| q as i32) } pub fn get_any_client_info(&self, client: i32) -> Result { let c = ClientInfo::new()?; acheck!(snd_seq_get_any_client_info(self.0, client, c.0)).map(|_| c) } pub fn get_any_port_info(&self, a: Addr) -> Result { let c = PortInfo::new()?; acheck!(snd_seq_get_any_port_info(self.0, a.client as c_int, a.port as c_int, c.0)).map(|_| c) } pub fn create_port(&self, port: &PortInfo) -> Result<()> { acheck!(snd_seq_create_port(self.0, port.0)).map(|_| ()) } pub fn create_simple_port(&self, name: &CStr, caps: PortCap, t: PortType) -> Result { acheck!(snd_seq_create_simple_port(self.0, name.as_ptr(), caps.bits() as c_uint, t.bits() as c_uint)).map(|q| q as i32) } pub fn set_port_info(&self, port: i32, info: &mut PortInfo) -> Result<()> { acheck!(snd_seq_set_port_info(self.0, port, info.0)).map(|_| ()) } pub fn delete_port(&self, port: i32) -> Result<()> { acheck!(snd_seq_delete_port(self.0, port as c_int)).map(|_| ()) } pub fn subscribe_port(&self, info: &PortSubscribe) -> Result<()> { acheck!(snd_seq_subscribe_port(self.0, info.0)).map(|_| ()) } pub fn unsubscribe_port(&self, sender: Addr, dest: Addr) -> Result<()> { let z = PortSubscribe::new()?; z.set_sender(sender); z.set_dest(dest); acheck!(snd_seq_unsubscribe_port(self.0, z.0)).map(|_| ()) } pub fn control_queue(&self, q: i32, t: EventType, value: i32, e: Option<&mut Event>) -> Result<()> { assert!(EvQueueControl::<()>::has_data(t) || EvQueueControl::::has_data(t) || EvQueueControl::::has_data(t)); let p = e.map(|e| &mut e.0 as *mut _).unwrap_or(ptr::null_mut()); acheck!(snd_seq_control_queue(self.0, q as c_int, t as c_int, value as c_int, p)).map(|_| ()) } pub fn event_output(&self, e: &mut Event) -> Result { e.ensure_buf(); acheck!(snd_seq_event_output(self.0, &mut e.0)).map(|q| q as u32) } pub fn event_output_buffer(&self, e: &mut Event) -> Result { e.ensure_buf(); acheck!(snd_seq_event_output_buffer(self.0, &mut e.0)).map(|q| q as u32) } pub fn event_output_direct(&self, e: &mut Event) -> Result { e.ensure_buf(); acheck!(snd_seq_event_output_direct(self.0, &mut e.0)).map(|q| q as u32) } pub fn get_queue_tempo(&self, q: i32) -> Result { let value = QueueTempo::new()?; acheck!(snd_seq_get_queue_tempo(self.0, q as c_int, value.0)).map(|_| value) } pub fn set_queue_tempo(&self, q: i32, value: &QueueTempo) -> Result<()> { acheck!(snd_seq_set_queue_tempo(self.0, q as c_int, value.0)).map(|_| ()) } pub fn get_queue_status(&self, q: i32) -> Result { let value = QueueStatus::new()?; acheck!(snd_seq_get_queue_status(self.0, q as c_int, value.0)).map(|_| value) } pub fn free_queue(&self, q: i32) -> Result<()> { acheck!(snd_seq_free_queue(self.0, q)).map(|_| ()) } pub fn alloc_queue(&self) -> Result { acheck!(snd_seq_alloc_queue(self.0)).map(|q| q as i32) } pub fn alloc_named_queue(&self, n: &CStr) -> Result { acheck!(snd_seq_alloc_named_queue(self.0, n.as_ptr())).map(|q| q as i32) } pub fn sync_output_queue(&self) -> Result<()> { acheck!(snd_seq_sync_output_queue(self.0)).map(|_| ()) } pub fn drop_output(&self) -> Result<()> { acheck!(snd_seq_drop_output(self.0)).map(|_| ()) } /// Call this function to obtain an instance of `Input` to access the functions `event_input`, /// `event_input_pending` and `set_input_buffer_size`. See the documentation of `Input` for details. pub fn input(&self) -> Input { Input::new(self) } pub fn remove_events(&self, condition: RemoveEvents) -> Result<()> { acheck!(snd_seq_remove_events(self.0, condition.0)).map(|_| ()) } } /// Struct for receiving input events from a sequencer. The methods offered by this /// object may modify the internal input buffer of the sequencer, which must not happen /// while an `Event` is alive that has been obtained from a call to `event_input` (which /// takes `Input` by mutable reference for this reason). This is because the event might /// directly reference the sequencer's input buffer for variable-length messages (e.g. Sysex). /// /// Note: Only one `Input` object is allowed in scope at a time. pub struct Input<'a>(&'a Seq); impl<'a> Drop for Input<'a> { fn drop(&mut self) { (self.0).1.set(false) } } impl<'a> Input<'a> { fn new(s: &'a Seq) -> Input<'a> { s.check_has_input(); s.1.set(true); Input(s) } pub fn event_input(&mut self) -> Result { // The returned event might reference the input buffer of the `Seq`. // Therefore we mutably borrow the `Input` structure, preventing any // other function call that might change the input buffer while the // event is alive. let mut z = ptr::null_mut(); acheck!(snd_seq_event_input((self.0).0, &mut z))?; unsafe { Event::extract (&mut *z, "snd_seq_event_input") } } pub fn event_input_pending(&self, fetch_sequencer: bool) -> Result { acheck!(snd_seq_event_input_pending((self.0).0, if fetch_sequencer {1} else {0})).map(|q| q as u32) } pub fn set_input_buffer_size(&self, size: u32) -> Result<()> { acheck!(snd_seq_set_input_buffer_size((self.0).0, size as size_t)).map(|_| ()) } pub fn drop_input(&self) -> Result<()> { acheck!(snd_seq_drop_input((self.0).0)).map(|_| ()) } } fn polldir(o: Option) -> c_short { match o { None => poll::Flags::IN | poll::Flags::OUT, Some(Direction::Playback) => poll::Flags::OUT, Some(Direction::Capture) => poll::Flags::IN, }.bits() } impl<'a> poll::Descriptors for (&'a Seq, Option) { fn count(&self) -> usize { unsafe { alsa::snd_seq_poll_descriptors_count((self.0).0, polldir(self.1)) as usize } } fn fill(&self, p: &mut [pollfd]) -> Result { let z = unsafe { alsa::snd_seq_poll_descriptors((self.0).0, p.as_mut_ptr(), p.len() as c_uint, polldir(self.1)) }; from_code("snd_seq_poll_descriptors", z).map(|_| z as usize) } fn revents(&self, p: &[pollfd]) -> Result { let mut r = 0; let z = unsafe { alsa::snd_seq_poll_descriptors_revents((self.0).0, p.as_ptr() as *mut pollfd, p.len() as c_uint, &mut r) }; from_code("snd_seq_poll_descriptors_revents", z).map(|_| poll::Flags::from_bits_truncate(r as c_short)) } } /// [snd_seq_client_info_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_client.html) wrapper pub struct ClientInfo(*mut alsa::snd_seq_client_info_t); unsafe impl Send for ClientInfo {} impl Drop for ClientInfo { fn drop(&mut self) { unsafe { alsa::snd_seq_client_info_free(self.0) }; } } impl ClientInfo { fn new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_seq_client_info_malloc(&mut p)).map(|_| ClientInfo(p)) } // Not sure if it's useful for this one to be public. fn set_client(&self, client: i32) { unsafe { alsa::snd_seq_client_info_set_client(self.0, client as c_int) }; } pub fn get_client(&self) -> i32 { unsafe { alsa::snd_seq_client_info_get_client(self.0) as i32 } } pub fn get_name(&self) -> Result<&str> { let c = unsafe { alsa::snd_seq_client_info_get_name(self.0) }; from_const("snd_seq_client_info_get_name", c) } } impl fmt::Debug for ClientInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ClientInfo({},{:?})", self.get_client(), self.get_name()) } } #[derive(Copy, Clone)] /// Iterates over clients connected to the seq API (both kernel and userspace clients). pub struct ClientIter<'a>(&'a Seq, i32); impl<'a> ClientIter<'a> { pub fn new(seq: &'a Seq) -> Self { ClientIter(seq, -1) } } impl<'a> Iterator for ClientIter<'a> { type Item = ClientInfo; fn next(&mut self) -> Option { let z = ClientInfo::new().unwrap(); z.set_client(self.1); let r = unsafe { alsa::snd_seq_query_next_client((self.0).0, z.0) }; if r < 0 { self.1 = -1; return None }; self.1 = z.get_client(); Some(z) } } /// [snd_seq_port_info_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html) wrapper pub struct PortInfo(*mut alsa::snd_seq_port_info_t); unsafe impl Send for PortInfo {} impl Drop for PortInfo { fn drop(&mut self) { unsafe { alsa::snd_seq_port_info_free(self.0) }; } } impl PortInfo { fn new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_seq_port_info_malloc(&mut p)).map(|_| PortInfo(p)) } /// Creates a new PortInfo with all fields set to zero. pub fn empty() -> Result { let z = Self::new()?; unsafe { ptr::write_bytes(z.0 as *mut u8, 0, alsa::snd_seq_port_info_sizeof()) }; Ok(z) } pub fn get_client(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_client(self.0) as i32 } } pub fn get_port(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_port(self.0) as i32 } } // Not sure if it's useful for this one to be public. fn set_client(&self, client: i32) { unsafe { alsa::snd_seq_port_info_set_client(self.0, client as c_int) }; } // Not sure if it's useful for this one to be public. fn set_port(&self, port: i32) { unsafe { alsa::snd_seq_port_info_set_port(self.0, port as c_int) }; } pub fn get_name(&self) -> Result<&str> { let c = unsafe { alsa::snd_seq_port_info_get_name(self.0) }; from_const("snd_seq_port_info_get_name", c) } pub fn set_name(&mut self, name: &CStr) { // Note: get_name returns an interior reference, so this one must take &mut self unsafe { alsa::snd_seq_port_info_set_name(self.0, name.as_ptr()) }; } pub fn get_capability(&self) -> PortCap { PortCap::from_bits_truncate(unsafe { alsa::snd_seq_port_info_get_capability(self.0) as u32 }) } pub fn get_type(&self) -> PortType { PortType::from_bits_truncate(unsafe { alsa::snd_seq_port_info_get_type(self.0) as u32 }) } pub fn set_capability(&self, c: PortCap) { unsafe { alsa::snd_seq_port_info_set_capability(self.0, c.bits() as c_uint) } } pub fn set_type(&self, c: PortType) { unsafe { alsa::snd_seq_port_info_set_type(self.0, c.bits() as c_uint) } } /// Returns an Addr containing this PortInfo's client and port id. pub fn addr(&self) -> Addr { Addr { client: self.get_client(), port: self.get_port(), } } pub fn get_midi_channels(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_midi_channels(self.0) as i32 } } pub fn get_midi_voices(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_midi_voices(self.0) as i32 } } pub fn get_synth_voices(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_synth_voices(self.0) as i32 } } pub fn get_read_use(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_read_use(self.0) as i32 } } pub fn get_write_use(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_write_use(self.0) as i32 } } pub fn get_port_specified(&self) -> bool { unsafe { alsa::snd_seq_port_info_get_port_specified(self.0) == 1 } } pub fn get_timestamping(&self) -> bool { unsafe { alsa::snd_seq_port_info_get_timestamping(self.0) == 1 } } pub fn get_timestamp_real(&self) -> bool { unsafe { alsa::snd_seq_port_info_get_timestamp_real(self.0) == 1 } } pub fn get_timestamp_queue(&self) -> i32 { unsafe { alsa::snd_seq_port_info_get_timestamp_queue(self.0) as i32 } } pub fn set_midi_channels(&self, value: i32) { unsafe { alsa::snd_seq_port_info_set_midi_channels(self.0, value as c_int) } } pub fn set_midi_voices(&self, value: i32) { unsafe { alsa::snd_seq_port_info_set_midi_voices(self.0, value as c_int) } } pub fn set_synth_voices(&self, value: i32) { unsafe { alsa::snd_seq_port_info_set_synth_voices(self.0, value as c_int) } } pub fn set_port_specified(&self, value: bool) { unsafe { alsa::snd_seq_port_info_set_port_specified(self.0, if value { 1 } else { 0 } ) } } pub fn set_timestamping(&self, value: bool) { unsafe { alsa::snd_seq_port_info_set_timestamping(self.0, if value { 1 } else { 0 } ) } } pub fn set_timestamp_real(&self, value: bool) { unsafe { alsa::snd_seq_port_info_set_timestamp_real(self.0, if value { 1 } else { 0 } ) } } pub fn set_timestamp_queue(&self, value: i32) { unsafe { alsa::snd_seq_port_info_set_timestamp_queue(self.0, value as c_int) } } } impl fmt::Debug for PortInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "PortInfo({}:{},{:?})", self.get_client(), self.get_port(), self.get_name()) } } #[derive(Copy, Clone)] /// Iterates over clients connected to the seq API (both kernel and userspace clients). pub struct PortIter<'a>(&'a Seq, i32, i32); impl<'a> PortIter<'a> { pub fn new(seq: &'a Seq, client: i32) -> Self { PortIter(seq, client, -1) } } impl<'a> Iterator for PortIter<'a> { type Item = PortInfo; fn next(&mut self) -> Option { let z = PortInfo::new().unwrap(); z.set_client(self.1); z.set_port(self.2); let r = unsafe { alsa::snd_seq_query_next_port((self.0).0, z.0) }; if r < 0 { self.2 = -1; return None }; self.2 = z.get_port(); Some(z) } } bitflags! { #[repr(transparent)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] /// [SND_SEQ_PORT_CAP_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html) constants pub struct PortCap: u32 { const READ = 1<<0; const WRITE = 1<<1; const SYNC_READ = 1<<2; const SYNC_WRITE = 1<<3; const DUPLEX = 1<<4; const SUBS_READ = 1<<5; const SUBS_WRITE = 1<<6; const NO_EXPORT = 1<<7; } } bitflags! { #[repr(transparent)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] /// [SND_SEQ_PORT_TYPE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html) constants pub struct PortType: u32 { const SPECIFIC = (1<<0); const MIDI_GENERIC = (1<<1); const MIDI_GM = (1<<2); const MIDI_GS = (1<<3); const MIDI_XG = (1<<4); const MIDI_MT32 = (1<<5); const MIDI_GM2 = (1<<6); const SYNTH = (1<<10); const DIRECT_SAMPLE = (1<<11); const SAMPLE = (1<<12); const HARDWARE = (1<<16); const SOFTWARE = (1<<17); const SYNTHESIZER = (1<<18); const PORT = (1<<19); const APPLICATION = (1<<20); } } bitflags! { #[repr(transparent)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] /// [SND_SEQ_REMOVE_xxx](https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_event.html) constants pub struct Remove: u32 { const INPUT = (1<<0); const OUTPUT = (1<<1); const DEST = (1<<2); const DEST_CHANNEL = (1<<3); const TIME_BEFORE = (1<<4); const TIME_AFTER = (1<<5); const TIME_TICK = (1<<6); const EVENT_TYPE = (1<<7); const IGNORE_OFF = (1<<8); const TAG_MATCH = (1<<9); } } /// [snd_seq_addr_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__addr__t.html) wrapper #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default)] pub struct Addr { pub client: i32, pub port: i32, } impl FromStr for Addr { type Err = Box; fn from_str(s: &str) -> std::result::Result { let mut split: Split<'_, char> = s.trim().split(':'); let client = split.next() .ok_or("no client provided")? .parse::()?; let port = split.next() .ok_or("no port provided")? .parse::()?; match split.next() { Some(_) => { Err("too many arguments".into()) }, None => { Ok(Addr { client, port }) } } } } impl Addr { pub fn system_timer() -> Addr { Addr { client: alsa::SND_SEQ_CLIENT_SYSTEM as i32, port: alsa::SND_SEQ_PORT_SYSTEM_TIMER as i32 } } pub fn system_announce() -> Addr { Addr { client: alsa::SND_SEQ_CLIENT_SYSTEM as i32, port: alsa::SND_SEQ_PORT_SYSTEM_ANNOUNCE as i32 } } pub fn broadcast() -> Addr { Addr { client: alsa::SND_SEQ_ADDRESS_BROADCAST as i32, port: alsa::SND_SEQ_ADDRESS_BROADCAST as i32 } } } /// [snd_seq_port_subscribe_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html) wrapper pub struct PortSubscribe(*mut alsa::snd_seq_port_subscribe_t); unsafe impl Send for PortSubscribe {} impl Drop for PortSubscribe { fn drop(&mut self) { unsafe { alsa::snd_seq_port_subscribe_free(self.0) }; } } impl PortSubscribe { fn new() -> Result { let mut p = ptr::null_mut(); acheck!(snd_seq_port_subscribe_malloc(&mut p)).map(|_| PortSubscribe(p)) } /// Creates a new PortSubscribe with all fields set to zero. pub fn empty() -> Result { let z = Self::new()?; unsafe { ptr::write_bytes(z.0 as *mut u8, 0, alsa::snd_seq_port_subscribe_sizeof()) }; Ok(z) } pub fn get_sender(&self) -> Addr { unsafe { let z = alsa::snd_seq_port_subscribe_get_sender(self.0); Addr { client: (*z).client as i32, port: (*z).port as i32 } } } pub fn get_dest(&self) -> Addr { unsafe { let z = alsa::snd_seq_port_subscribe_get_dest(self.0); Addr { client: (*z).client as i32, port: (*z).port as i32 } } } pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_port_subscribe_get_queue(self.0) as i32 } } pub fn get_exclusive(&self) -> bool { unsafe { alsa::snd_seq_port_subscribe_get_exclusive(self.0) == 1 } } pub fn get_time_update(&self) -> bool { unsafe { alsa::snd_seq_port_subscribe_get_time_update(self.0) == 1 } } pub fn get_time_real(&self) -> bool { unsafe { alsa::snd_seq_port_subscribe_get_time_real(self.0) == 1 } } pub fn set_sender(&self, value: Addr) { let z = alsa::snd_seq_addr_t { client: value.client as c_uchar, port: value.port as c_uchar }; unsafe { alsa::snd_seq_port_subscribe_set_sender(self.0, &z) }; } pub fn set_dest(&self, value: Addr) { let z = alsa::snd_seq_addr_t { client: value.client as c_uchar, port: value.port as c_uchar }; unsafe { alsa::snd_seq_port_subscribe_set_dest(self.0, &z) }; } pub fn set_queue(&self, value: i32) { unsafe { alsa::snd_seq_port_subscribe_set_queue(self.0, value as c_int) } } pub fn set_exclusive(&self, value: bool) { unsafe { alsa::snd_seq_port_subscribe_set_exclusive(self.0, if value { 1 } else { 0 } ) } } pub fn set_time_update(&self, value: bool) { unsafe { alsa::snd_seq_port_subscribe_set_time_update(self.0, if value { 1 } else { 0 } ) } } pub fn set_time_real(&self, value: bool) { unsafe { alsa::snd_seq_port_subscribe_set_time_real(self.0, if value { 1 } else { 0 } ) } } } /// [snd_seq_query_subs_type_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html) wrapper #[derive(Copy, Clone)] pub enum QuerySubsType { READ = alsa::SND_SEQ_QUERY_SUBS_READ as isize, WRITE = alsa::SND_SEQ_QUERY_SUBS_WRITE as isize, } /// [snd_seq_query_subscribe_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html) wrapper //(kept private, functionality exposed by PortSubscribeIter) struct QuerySubscribe(*mut alsa::snd_seq_query_subscribe_t); unsafe impl Send for QuerySubscribe {} impl Drop for QuerySubscribe { fn drop(&mut self) { unsafe { alsa::snd_seq_query_subscribe_free(self.0) } } } impl QuerySubscribe { pub fn new() -> Result { let mut q = ptr::null_mut(); acheck!(snd_seq_query_subscribe_malloc(&mut q)).map(|_| QuerySubscribe(q)) } pub fn get_index(&self) -> i32 { unsafe { alsa::snd_seq_query_subscribe_get_index(self.0) as i32 } } pub fn get_addr(&self) -> Addr { unsafe { let a = &(*alsa::snd_seq_query_subscribe_get_addr(self.0)); Addr { client: a.client as i32, port: a.port as i32 } } } pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_query_subscribe_get_queue(self.0) as i32 } } pub fn get_exclusive(&self) -> bool { unsafe { alsa::snd_seq_query_subscribe_get_exclusive(self.0) == 1 } } pub fn get_time_update(&self) -> bool { unsafe { alsa::snd_seq_query_subscribe_get_time_update(self.0) == 1 } } pub fn get_time_real(&self) -> bool { unsafe { alsa::snd_seq_query_subscribe_get_time_real(self.0) == 1 } } pub fn set_root(&self, value: Addr) { unsafe { let a = alsa::snd_seq_addr_t { client: value.client as c_uchar, port: value.port as c_uchar}; alsa::snd_seq_query_subscribe_set_root(self.0, &a); } } pub fn set_type(&self, value: QuerySubsType) { unsafe { alsa::snd_seq_query_subscribe_set_type(self.0, value as alsa::snd_seq_query_subs_type_t) } } pub fn set_index(&self, value: i32) { unsafe { alsa::snd_seq_query_subscribe_set_index(self.0, value as c_int) } } } #[derive(Copy, Clone)] /// Iterates over port subscriptions for a given client:port/type. pub struct PortSubscribeIter<'a> { seq: &'a Seq, addr: Addr, query_subs_type: QuerySubsType, index: i32 } impl<'a> PortSubscribeIter<'a> { pub fn new(seq: &'a Seq, addr: Addr, query_subs_type: QuerySubsType) -> Self { PortSubscribeIter {seq, addr, query_subs_type, index: 0 } } } impl<'a> Iterator for PortSubscribeIter<'a> { type Item = PortSubscribe; fn next(&mut self) -> Option { let query = QuerySubscribe::new().unwrap(); query.set_root(self.addr); query.set_type(self.query_subs_type); query.set_index(self.index); let r = unsafe { alsa::snd_seq_query_port_subscribers((self.seq).0, query.0) }; if r < 0 { self.index = 0; return None; } self.index = query.get_index() + 1; let vtr = PortSubscribe::new().unwrap(); match self.query_subs_type { QuerySubsType::READ => { vtr.set_sender(self.addr); vtr.set_dest(query.get_addr()); }, QuerySubsType:: WRITE => { vtr.set_sender(query.get_addr()); vtr.set_dest(self.addr); } }; vtr.set_queue(query.get_queue()); vtr.set_exclusive(query.get_exclusive()); vtr.set_time_update(query.get_time_update()); vtr.set_time_real(query.get_time_real()); Some(vtr) } } /// [snd_seq_event_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event__t.html) wrapper /// /// Fields of the event is not directly exposed. Instead call `Event::new` to set data (which can be, e g, an EvNote). /// Use `get_type` and `get_data` to retrieve data. /// /// The lifetime parameter refers to the lifetime of an associated external buffer that might be used for /// variable-length messages (e.g. SysEx). pub struct Event<'a>(alsa::snd_seq_event_t, EventType, Option>); unsafe impl<'a> Send for Event<'a> {} impl<'a> Event<'a> { /// Creates a new event. For events that carry variable-length data (e.g. Sysex), `new_ext` has to be used instead. pub fn new(t: EventType, data: &D) -> Event<'static> { assert!(!Event::has_ext_data(t), "event type must not carry variable-length data"); let mut z = Event(unsafe { mem::zeroed() }, t, None); (z.0).type_ = t as c_uchar; (z.0).flags |= Event::get_length_flag(t); debug_assert!(D::has_data(t)); data.set_data(&mut z); z } /// Creates a new event carrying variable-length data. This is required for event types `Sysex`, `Bounce`, and the `UsrVar` types. pub fn new_ext>>(t: EventType, data: D) -> Event<'a> { assert!(Event::has_ext_data(t), "event type must carry variable-length data"); let mut z = Event(unsafe { mem::zeroed() }, t, Some(data.into())); (z.0).type_ = t as c_uchar; (z.0).flags |= Event::get_length_flag(t); z } /// Consumes this event and returns an (otherwise unchanged) event where the externally referenced /// buffer for variable length messages (e.g. SysEx) has been copied into the event. /// The returned event has a static lifetime, i e, it's decoupled from the original buffer. pub fn into_owned(self) -> Event<'static> { Event(self.0, self.1, self.2.map(|cow| Cow::Owned(cow.into_owned()))) } fn get_length_flag(t: EventType) -> u8 { match t { EventType::Sysex => alsa::SND_SEQ_EVENT_LENGTH_VARIABLE, EventType::Bounce => alsa::SND_SEQ_EVENT_LENGTH_VARIABLE, // not clear whether this should be VARIABLE or VARUSR EventType::UsrVar0 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR, EventType::UsrVar1 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR, EventType::UsrVar2 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR, EventType::UsrVar3 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR, EventType::UsrVar4 => alsa::SND_SEQ_EVENT_LENGTH_VARUSR, _ => alsa::SND_SEQ_EVENT_LENGTH_FIXED } } fn has_ext_data(t: EventType) -> bool { Event::get_length_flag(t) != alsa::SND_SEQ_EVENT_LENGTH_FIXED } /// Extracts event type and data. Produces a result with an arbitrary lifetime, hence the unsafety. unsafe fn extract<'any>(z: &mut alsa::snd_seq_event_t, func: &'static str) -> Result> { let t = EventType::from_c_int((*z).type_ as c_int, func)?; let ext_data = if Event::has_ext_data(t) { assert_ne!((*z).flags & alsa::SND_SEQ_EVENT_LENGTH_MASK, alsa::SND_SEQ_EVENT_LENGTH_FIXED); Some(Cow::Borrowed({ let zz: &EvExtPacked = &*(&(*z).data as *const alsa::snd_seq_event__bindgen_ty_1 as *const _); slice::from_raw_parts((*zz).ptr as *mut u8, (*zz).len as usize) })) } else { None }; Ok(Event(ptr::read(z), t, ext_data)) } /// Ensures that the ev.ext union element points to the correct resize_buffer for events /// with variable length content fn ensure_buf(&mut self) { if !Event::has_ext_data(self.1) { return; } let slice: &[u8] = match self.2 { Some(Cow::Owned(ref mut vec)) => &vec[..], Some(Cow::Borrowed(buf)) => buf, // The following case is always a logic error in the program, thus panicking is okay. None => panic!("event type requires variable-length data, but none was provided") }; let z: &mut EvExtPacked = unsafe { &mut *(&mut self.0.data as *mut alsa::snd_seq_event__bindgen_ty_1 as *mut _) }; z.len = slice.len() as c_uint; z.ptr = slice.as_ptr() as *mut c_void; } #[inline] pub fn get_type(&self) -> EventType { self.1 } /// Extract the event data from an event. /// Use `get_ext` instead for events carrying variable-length data. pub fn get_data(&self) -> Option { if D::has_data(self.1) { Some(D::get_data(self)) } else { None } } /// Extract the variable-length data carried by events of type `Sysex`, `Bounce`, or the `UsrVar` types. pub fn get_ext(&self) -> Option<&[u8]> { if Event::has_ext_data(self.1) { match self.2 { Some(Cow::Owned(ref vec)) => Some(&vec[..]), Some(Cow::Borrowed(buf)) => Some(buf), // The following case is always a logic error in the program, thus panicking is okay. None => panic!("event type requires variable-length data, but none was found") } } else { None } } pub fn set_subs(&mut self) { self.0.dest.client = alsa::SND_SEQ_ADDRESS_SUBSCRIBERS; self.0.dest.port = alsa::SND_SEQ_ADDRESS_UNKNOWN; } pub fn set_source(&mut self, p: i32) { self.0.source.port = p as u8 } pub fn set_dest(&mut self, d: Addr) { self.0.dest.client = d.client as c_uchar; self.0.dest.port = d.port as c_uchar; } pub fn set_tag(&mut self, t: u8) { self.0.tag = t as c_uchar; } pub fn set_queue(&mut self, q: i32) { self.0.queue = q as c_uchar; } pub fn get_source(&self) -> Addr { Addr { client: self.0.source.client as i32, port: self.0.source.port as i32 } } pub fn get_dest(&self) -> Addr { Addr { client: self.0.dest.client as i32, port: self.0.dest.port as i32 } } pub fn get_tag(&self) -> u8 { self.0.tag as u8 } pub fn get_queue(&self) -> i32 { self.0.queue as i32 } pub fn schedule_real(&mut self, queue: i32, relative: bool, rtime: time::Duration) { self.0.flags &= !(alsa::SND_SEQ_TIME_STAMP_MASK | alsa::SND_SEQ_TIME_MODE_MASK); self.0.flags |= alsa::SND_SEQ_TIME_STAMP_REAL | (if relative { alsa::SND_SEQ_TIME_MODE_REL } else { alsa::SND_SEQ_TIME_MODE_ABS }); self.0.queue = queue as u8; let t = unsafe { &mut self.0.time.time }; t.tv_sec = rtime.as_secs() as c_uint; t.tv_nsec = rtime.subsec_nanos() as c_uint; } pub fn schedule_tick(&mut self, queue: i32, relative: bool, ttime: u32) { self.0.flags &= !(alsa::SND_SEQ_TIME_STAMP_MASK | alsa::SND_SEQ_TIME_MODE_MASK); self.0.flags |= alsa::SND_SEQ_TIME_STAMP_TICK | (if relative { alsa::SND_SEQ_TIME_MODE_REL } else { alsa::SND_SEQ_TIME_MODE_ABS }); self.0.queue = queue as u8; let t = unsafe { &mut self.0.time.tick }; *t = ttime as c_uint; } pub fn set_direct(&mut self) { self.0.queue = alsa::SND_SEQ_QUEUE_DIRECT } pub fn get_relative(&self) -> bool { (self.0.flags & alsa::SND_SEQ_TIME_MODE_REL) != 0 } pub fn get_time(&self) -> Option { if (self.0.flags & alsa::SND_SEQ_TIME_STAMP_REAL) != 0 { let d = self.0.time; let t = unsafe { &d.time }; Some(time::Duration::new(t.tv_sec as u64, t.tv_nsec as u32)) } else { None } } pub fn get_tick(&self) -> Option { if (self.0.flags & alsa::SND_SEQ_TIME_STAMP_REAL) == 0 { let d = self.0.time; let t = unsafe { &d.tick }; Some(*t) } else { None } } /// Returns true if the message is high priority. pub fn get_priority(&self) -> bool { (self.0.flags & alsa::SND_SEQ_PRIORITY_HIGH) != 0 } pub fn set_priority(&mut self, is_high_prio: bool) { if is_high_prio { self.0.flags |= alsa::SND_SEQ_PRIORITY_HIGH; } else { self.0.flags &= !alsa::SND_SEQ_PRIORITY_HIGH; } } } impl<'a> Clone for Event<'a> { fn clone(&self) -> Self { Event(unsafe { ptr::read(&self.0) }, self.1, self.2.clone()) } } impl<'a> fmt::Debug for Event<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut x = f.debug_tuple("Event"); x.field(&self.1); if let Some(z) = self.get_data::() { x.field(&z); } if let Some(z) = self.get_data::() { x.field(&z); } if let Some(z) = self.get_data::() { x.field(&z); } if let Some(z) = self.get_data::() { x.field(&z); } if let Some(z) = self.get_data::>() { x.field(&z); } if let Some(z) = self.get_data::>() { x.field(&z); } if let Some(z) = self.get_data::>() { x.field(&z); } if let Some(z) = self.get_data::>() { x.field(&z); } if let Some(z) = self.get_data::() { x.field(&z); } if let Some(z) = self.get_data::<[u8; 12]>() { x.field(&z); } if let Some(z) = self.get_ext() { x.field(&z); } x.finish() } } /// Internal trait implemented for different event type structs (`EvNote`, `EvCtrl`, etc). /// /// Use it through `Event::get_data` and `Event::new`. pub trait EventData { #[doc(hidden)] fn get_data(ev: &Event) -> Self; #[doc(hidden)] fn has_data(e: EventType) -> bool; #[doc(hidden)] fn set_data(&self, ev: &mut Event); } impl EventData for () { fn get_data(_: &Event) -> Self {} fn has_data(e: EventType) -> bool { matches!(e, EventType::TuneRequest | EventType::Reset | EventType::Sensing | EventType::None) } fn set_data(&self, _: &mut Event) {} } impl EventData for [u8; 12] { fn get_data(ev: &Event) -> Self { let d = unsafe { ptr::read(&ev.0.data) }; let z = unsafe { &d.raw8 }; z.d } fn has_data(e: EventType) -> bool { matches!(e, EventType::Echo | EventType::Oss | EventType::Usr0 | EventType::Usr1 | EventType::Usr2 | EventType::Usr3 | EventType::Usr4 | EventType::Usr5 | EventType::Usr6 | EventType::Usr7 | EventType::Usr8 | EventType::Usr9) } fn set_data(&self, ev: &mut Event) { let z = unsafe { &mut ev.0.data.raw8 }; z.d = *self; } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)] pub struct EvNote { pub channel: u8, pub note: u8, pub velocity: u8, pub off_velocity: u8, pub duration: u32, } impl EventData for EvNote { fn get_data(ev: &Event) -> Self { let z: &alsa::snd_seq_ev_note_t = unsafe { &*(&ev.0.data as *const alsa::snd_seq_event__bindgen_ty_1 as *const _) }; EvNote { channel: z.channel as u8, note: z.note as u8, velocity: z.velocity as u8, off_velocity: z.off_velocity as u8, duration: z.duration as u32 } } fn has_data(e: EventType) -> bool { matches!(e, EventType::Note | EventType::Noteon | EventType::Noteoff | EventType::Keypress) } fn set_data(&self, ev: &mut Event) { let z: &mut alsa::snd_seq_ev_note_t = unsafe { &mut *(&mut ev.0.data as *mut alsa::snd_seq_event__bindgen_ty_1 as *mut _) }; z.channel = self.channel as c_uchar; z.note = self.note as c_uchar; z.velocity = self.velocity as c_uchar; z.off_velocity = self.off_velocity as c_uchar; z.duration = self.duration as c_uint; } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)] pub struct EvCtrl { pub channel: u8, pub param: u32, pub value: i32, } impl EventData for EvCtrl { fn get_data(ev: &Event) -> Self { let z: &alsa::snd_seq_ev_ctrl_t = unsafe { &*(&ev.0.data as *const alsa::snd_seq_event__bindgen_ty_1 as *const _) }; EvCtrl { channel: z.channel as u8, param: z.param as u32, value: z.value as i32 } } fn has_data(e: EventType) -> bool { matches!(e, EventType::Controller | EventType::Pgmchange | EventType::Chanpress | EventType::Pitchbend | EventType::Control14 | EventType::Nonregparam | EventType::Regparam | EventType::Songpos | EventType::Songsel | EventType::Qframe | EventType::Timesign | EventType::Keysign) } fn set_data(&self, ev: &mut Event) { let z: &mut alsa::snd_seq_ev_ctrl_t = unsafe { &mut *(&mut ev.0.data as *mut alsa::snd_seq_event__bindgen_ty_1 as *mut _) }; z.channel = self.channel as c_uchar; z.param = self.param as c_uint; z.value = self.value as c_int; } } impl EventData for Addr { fn get_data(ev: &Event) -> Self { let z: &alsa::snd_seq_addr_t = unsafe { &*(&ev.0.data as *const alsa::snd_seq_event__bindgen_ty_1 as *const _) }; Addr { client: z.client as i32, port: z.port as i32 } } fn has_data(e: EventType) -> bool { matches!(e, EventType::ClientStart | EventType::ClientExit | EventType::ClientChange | EventType::PortStart | EventType::PortExit | EventType::PortChange) } fn set_data(&self, ev: &mut Event) { let z: &mut alsa::snd_seq_addr_t = unsafe { &mut *(&mut ev.0.data as *mut alsa::snd_seq_event__bindgen_ty_1 as *mut _) }; z.client = self.client as c_uchar; z.port = self.port as c_uchar; } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)] /// [snd_seq_connect_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__connect__t.html) wrapper pub struct Connect { pub sender: Addr, pub dest: Addr, } impl EventData for Connect { fn get_data(ev: &Event) -> Self { let d = unsafe { ptr::read(&ev.0.data) }; let z = unsafe { &d.connect }; Connect { sender: Addr { client: z.sender.client as i32, port: z.sender.port as i32 }, dest: Addr { client: z.dest.client as i32, port: z.dest.port as i32 } } } fn has_data(e: EventType) -> bool { matches!(e, EventType::PortSubscribed | EventType::PortUnsubscribed) } fn set_data(&self, ev: &mut Event) { let z = unsafe { &mut ev.0.data.connect }; z.sender.client = self.sender.client as c_uchar; z.sender.port = self.sender.port as c_uchar; z.dest.client = self.dest.client as c_uchar; z.dest.port = self.dest.port as c_uchar; } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)] /// [snd_seq_ev_queue_control_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__ev__queue__control__t.html) wrapper /// /// Note: This struct is generic, but what types of T are required for the different EvQueueControl messages is /// not very well documented in alsa-lib. Right now, Tempo is i32, Tick, SetposTick and SyncPos are u32, SetposTime is time::Duration, /// and the rest is (). If I guessed wrong, let me know. pub struct EvQueueControl { pub queue: i32, pub value: T, } impl EventData for EvQueueControl<()> { fn get_data(ev: &Event) -> Self { let d = unsafe { ptr::read(&ev.0.data) }; let z = unsafe { &d.queue }; EvQueueControl { queue: z.queue as i32, value: () } } fn has_data(e: EventType) -> bool { matches!(e, EventType::Start | EventType::Continue | EventType::Stop | EventType::Clock | EventType::QueueSkew) } fn set_data(&self, ev: &mut Event) { let z = unsafe { &mut ev.0.data.queue }; z.queue = self.queue as c_uchar; } } impl EventData for EvQueueControl { fn get_data(ev: &Event) -> Self { unsafe { let mut d = ptr::read(&ev.0.data); let z = &mut d.queue; EvQueueControl { queue: z.queue as i32, value: z.param.value as i32 } } } fn has_data(e: EventType) -> bool { matches!(e, EventType::Tempo) } fn set_data(&self, ev: &mut Event) { unsafe { let z = &mut ev.0.data.queue; z.queue = self.queue as c_uchar; z.param.value = self.value as c_int; } } } impl EventData for EvQueueControl { fn get_data(ev: &Event) -> Self { unsafe { let mut d = ptr::read(&ev.0.data); let z = &mut d.queue; EvQueueControl { queue: z.queue as i32, value: z.param.position as u32 } } } fn has_data(e: EventType) -> bool { matches!(e, EventType::SyncPos | EventType::Tick | EventType::SetposTick) } fn set_data(&self, ev: &mut Event) { unsafe { let z = &mut ev.0.data.queue; z.queue = self.queue as c_uchar; z.param.position = self.value as c_uint; } } } impl EventData for EvQueueControl { fn get_data(ev: &Event) -> Self { unsafe { let mut d = ptr::read(&ev.0.data); let z = &mut d.queue; let t = &mut z.param.time.time; EvQueueControl { queue: z.queue as i32, value: time::Duration::new(t.tv_sec as u64, t.tv_nsec as u32) } } } fn has_data(e: EventType) -> bool { matches!(e, EventType::SetposTime) } fn set_data(&self, ev: &mut Event) { unsafe { let z = &mut ev.0.data.queue; z.queue = self.queue as c_uchar; let t = &mut z.param.time.time; t.tv_sec = self.value.as_secs() as c_uint; t.tv_nsec = self.value.subsec_nanos() as c_uint; } } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Default)] /// [snd_seq_result_t](http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__result__t.html) wrapper /// /// It's called EvResult instead of Result, in order to not be confused with Rust's Result type. pub struct EvResult { pub event: i32, pub result: i32, } impl EventData for EvResult { fn get_data(ev: &Event) -> Self { let d = unsafe { ptr::read(&ev.0.data) }; let z = unsafe { &d.result }; EvResult { event: z.event as i32, result: z.result as i32 } } fn has_data(e: EventType) -> bool { matches!(e, EventType::System | EventType::Result) } fn set_data(&self, ev: &mut Event) { let z = unsafe { &mut ev.0.data.result }; z.event = self.event as c_int; z.result = self.result as c_int; } } alsa_enum!( /// [SND_SEQ_EVENT_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_events.html) constants EventType, ALL_EVENT_TYPES[59], Bounce = SND_SEQ_EVENT_BOUNCE, Chanpress = SND_SEQ_EVENT_CHANPRESS, ClientChange = SND_SEQ_EVENT_CLIENT_CHANGE, ClientExit = SND_SEQ_EVENT_CLIENT_EXIT, ClientStart = SND_SEQ_EVENT_CLIENT_START, Clock = SND_SEQ_EVENT_CLOCK, Continue = SND_SEQ_EVENT_CONTINUE, Control14 = SND_SEQ_EVENT_CONTROL14, Controller = SND_SEQ_EVENT_CONTROLLER, Echo = SND_SEQ_EVENT_ECHO, Keypress = SND_SEQ_EVENT_KEYPRESS, Keysign = SND_SEQ_EVENT_KEYSIGN, None = SND_SEQ_EVENT_NONE, Nonregparam = SND_SEQ_EVENT_NONREGPARAM, Note = SND_SEQ_EVENT_NOTE, Noteoff = SND_SEQ_EVENT_NOTEOFF, Noteon = SND_SEQ_EVENT_NOTEON, Oss = SND_SEQ_EVENT_OSS, Pgmchange = SND_SEQ_EVENT_PGMCHANGE, Pitchbend = SND_SEQ_EVENT_PITCHBEND, PortChange = SND_SEQ_EVENT_PORT_CHANGE, PortExit = SND_SEQ_EVENT_PORT_EXIT, PortStart = SND_SEQ_EVENT_PORT_START, PortSubscribed = SND_SEQ_EVENT_PORT_SUBSCRIBED, PortUnsubscribed = SND_SEQ_EVENT_PORT_UNSUBSCRIBED, Qframe = SND_SEQ_EVENT_QFRAME, QueueSkew = SND_SEQ_EVENT_QUEUE_SKEW, Regparam = SND_SEQ_EVENT_REGPARAM, Reset = SND_SEQ_EVENT_RESET, Result = SND_SEQ_EVENT_RESULT, Sensing = SND_SEQ_EVENT_SENSING, SetposTick = SND_SEQ_EVENT_SETPOS_TICK, SetposTime = SND_SEQ_EVENT_SETPOS_TIME, Songpos = SND_SEQ_EVENT_SONGPOS, Songsel = SND_SEQ_EVENT_SONGSEL, Start = SND_SEQ_EVENT_START, Stop = SND_SEQ_EVENT_STOP, SyncPos = SND_SEQ_EVENT_SYNC_POS, Sysex = SND_SEQ_EVENT_SYSEX, System = SND_SEQ_EVENT_SYSTEM, Tempo = SND_SEQ_EVENT_TEMPO, Tick = SND_SEQ_EVENT_TICK, Timesign = SND_SEQ_EVENT_TIMESIGN, TuneRequest = SND_SEQ_EVENT_TUNE_REQUEST, Usr0 = SND_SEQ_EVENT_USR0, Usr1 = SND_SEQ_EVENT_USR1, Usr2 = SND_SEQ_EVENT_USR2, Usr3 = SND_SEQ_EVENT_USR3, Usr4 = SND_SEQ_EVENT_USR4, Usr5 = SND_SEQ_EVENT_USR5, Usr6 = SND_SEQ_EVENT_USR6, Usr7 = SND_SEQ_EVENT_USR7, Usr8 = SND_SEQ_EVENT_USR8, Usr9 = SND_SEQ_EVENT_USR9, UsrVar0 = SND_SEQ_EVENT_USR_VAR0, UsrVar1 = SND_SEQ_EVENT_USR_VAR1, UsrVar2 = SND_SEQ_EVENT_USR_VAR2, UsrVar3 = SND_SEQ_EVENT_USR_VAR3, UsrVar4 = SND_SEQ_EVENT_USR_VAR4, ); /// [snd_seq_queue_tempo_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html) wrapper pub struct QueueTempo(*mut alsa::snd_seq_queue_tempo_t); unsafe impl Send for QueueTempo {} impl Drop for QueueTempo { fn drop(&mut self) { unsafe { alsa::snd_seq_queue_tempo_free(self.0) } } } impl QueueTempo { fn new() -> Result { let mut q = ptr::null_mut(); acheck!(snd_seq_queue_tempo_malloc(&mut q)).map(|_| QueueTempo(q)) } /// Creates a new QueueTempo with all fields set to zero. pub fn empty() -> Result { let q = QueueTempo::new()?; unsafe { ptr::write_bytes(q.0 as *mut u8, 0, alsa::snd_seq_queue_tempo_sizeof()) }; Ok(q) } pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_queue_tempo_get_queue(self.0) as i32 } } pub fn get_tempo(&self) -> u32 { unsafe { alsa::snd_seq_queue_tempo_get_tempo(self.0) as u32 } } pub fn get_ppq(&self) -> i32 { unsafe { alsa::snd_seq_queue_tempo_get_ppq(self.0) as i32 } } pub fn get_skew(&self) -> u32 { unsafe { alsa::snd_seq_queue_tempo_get_skew(self.0) as u32 } } pub fn get_skew_base(&self) -> u32 { unsafe { alsa::snd_seq_queue_tempo_get_skew_base(self.0) as u32 } } // pub fn set_queue(&self, value: i32) { unsafe { alsa::snd_seq_queue_tempo_set_queue(self.0, value as c_int) } } pub fn set_tempo(&self, value: u32) { unsafe { alsa::snd_seq_queue_tempo_set_tempo(self.0, value as c_uint) } } pub fn set_ppq(&self, value: i32) { unsafe { alsa::snd_seq_queue_tempo_set_ppq(self.0, value as c_int) } } pub fn set_skew(&self, value: u32) { unsafe { alsa::snd_seq_queue_tempo_set_skew(self.0, value as c_uint) } } pub fn set_skew_base(&self, value: u32) { unsafe { alsa::snd_seq_queue_tempo_set_skew_base(self.0, value as c_uint) } } } /// [snd_seq_queue_status_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html) wrapper pub struct QueueStatus(*mut alsa::snd_seq_queue_status_t); unsafe impl Send for QueueStatus {} impl Drop for QueueStatus { fn drop(&mut self) { unsafe { alsa::snd_seq_queue_status_free(self.0) } } } impl QueueStatus { fn new() -> Result { let mut q = ptr::null_mut(); acheck!(snd_seq_queue_status_malloc(&mut q)).map(|_| QueueStatus(q)) } /// Creates a new QueueStatus with all fields set to zero. pub fn empty() -> Result { let q = QueueStatus::new()?; unsafe { ptr::write_bytes(q.0 as *mut u8, 0, alsa::snd_seq_queue_status_sizeof()) }; Ok(q) } pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_queue_status_get_queue(self.0) as i32 } } pub fn get_events(&self) -> i32 { unsafe { alsa::snd_seq_queue_status_get_events(self.0) as i32 } } pub fn get_tick_time(&self) -> u32 { unsafe {alsa::snd_seq_queue_status_get_tick_time(self.0) as u32 } } pub fn get_real_time(&self) -> time::Duration { unsafe { let t = &(*alsa::snd_seq_queue_status_get_real_time(self.0)); time::Duration::new(t.tv_sec as u64, t.tv_nsec as u32) } } pub fn get_status(&self) -> u32 { unsafe { alsa::snd_seq_queue_status_get_status(self.0) as u32 } } } /// [snd_seq_remove_events_t](https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_event.html) wrapper pub struct RemoveEvents(*mut alsa::snd_seq_remove_events_t); unsafe impl Send for RemoveEvents {} impl Drop for RemoveEvents { fn drop(&mut self) { unsafe { alsa::snd_seq_remove_events_free(self.0) } } } impl RemoveEvents { pub fn new() -> Result { let mut q = ptr::null_mut(); acheck!(snd_seq_remove_events_malloc(&mut q)).map(|_| RemoveEvents(q)) } pub fn get_condition(&self) -> Remove { unsafe { Remove::from_bits_truncate(alsa::snd_seq_remove_events_get_condition(self.0) as u32) } } pub fn get_queue(&self) -> i32 { unsafe { alsa::snd_seq_remove_events_get_queue(self.0) as i32 } } pub fn get_time(&self) -> time::Duration { unsafe { let d = ptr::read(alsa::snd_seq_remove_events_get_time(self.0)); let t = &d.time; time::Duration::new(t.tv_sec as u64, t.tv_nsec as u32) } } pub fn get_dest(&self) -> Addr { unsafe { let a = &(*alsa::snd_seq_remove_events_get_dest(self.0)); Addr { client: a.client as i32, port: a.port as i32 } } } pub fn get_channel(&self) -> i32 { unsafe { alsa::snd_seq_remove_events_get_channel(self.0) as i32 } } pub fn get_event_type(&self) -> Result { unsafe { EventType::from_c_int(alsa::snd_seq_remove_events_get_event_type(self.0), "snd_seq_remove_events_get_event_type") } } pub fn get_tag(&self) -> u8 { unsafe { alsa::snd_seq_remove_events_get_tag(self.0) as u8 } } pub fn set_condition(&self, value: Remove) { unsafe { alsa::snd_seq_remove_events_set_condition(self.0, value.bits() as c_uint); } } pub fn set_queue(&self, value: i32) { unsafe { alsa::snd_seq_remove_events_set_queue(self.0, value as c_int) } } pub fn set_time(&self, value: time::Duration) { unsafe { let mut d: alsa::snd_seq_timestamp_t = mem::zeroed(); let t = &mut d.time; t.tv_sec = value.as_secs() as c_uint; t.tv_nsec = value.subsec_nanos() as c_uint; alsa::snd_seq_remove_events_set_time(self.0, &d); } } pub fn set_dest(&self, value: Addr) { unsafe { let a = alsa::snd_seq_addr_t { client: value.client as c_uchar, port: value.port as c_uchar}; alsa::snd_seq_remove_events_set_dest(self.0, &a); } } pub fn set_channel(&self, value: i32) { unsafe { alsa::snd_seq_remove_events_set_channel(self.0, value as c_int) } } pub fn set_event_type(&self, value: EventType) { unsafe { alsa::snd_seq_remove_events_set_event_type(self.0, value as i32); } } pub fn set_tag(&self, value: u8) { unsafe { alsa::snd_seq_remove_events_set_tag(self.0, value as c_int) } } } /// [snd_midi_event_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___m_i_d_i___event.html) Wrapper /// /// Sequencer event <-> MIDI byte stream coder pub struct MidiEvent(*mut alsa::snd_midi_event_t); impl Drop for MidiEvent { fn drop(&mut self) { unsafe { alsa::snd_midi_event_free(self.0) } } } impl MidiEvent { pub fn new(bufsize: u32) -> Result { let mut q = ptr::null_mut(); acheck!(snd_midi_event_new(bufsize as size_t, &mut q)).map(|_| MidiEvent(q)) } pub fn resize_buffer(&self, bufsize: u32) -> Result<()> { acheck!(snd_midi_event_resize_buffer(self.0, bufsize as size_t)).map(|_| ()) } /// Note: this corresponds to snd_midi_event_no_status, but on and off are switched. /// /// Alsa-lib is a bit confusing here. Anyhow, set "enable" to true to enable running status. pub fn enable_running_status(&self, enable: bool) { unsafe { alsa::snd_midi_event_no_status(self.0, if enable {0} else {1}) } } /// Resets both encoder and decoder pub fn init(&self) { unsafe { alsa::snd_midi_event_init(self.0) } } pub fn reset_encode(&self) { unsafe { alsa::snd_midi_event_reset_encode(self.0) } } pub fn reset_decode(&self) { unsafe { alsa::snd_midi_event_reset_decode(self.0) } } pub fn decode(&self, buf: &mut [u8], ev: &mut Event) -> Result { ev.ensure_buf(); acheck!(snd_midi_event_decode(self.0, buf.as_mut_ptr() as *mut c_uchar, buf.len() as c_long, &ev.0)).map(|r| r as usize) } /// In case of success, returns a tuple of (bytes consumed from buf, found Event). pub fn encode<'a>(&'a mut self, buf: &[u8]) -> Result<(usize, Option>)> { // The ALSA documentation clearly states that the event will be valid as long as the Encoder // is not messed with (because the data pointer for sysex events may point into the Encoder's // buffer). We make this safe by taking self by unique reference and coupling it to // the event's lifetime. let mut ev = unsafe { mem::zeroed() }; let r = acheck!(snd_midi_event_encode(self.0, buf.as_ptr() as *const c_uchar, buf.len() as c_long, &mut ev))?; let e = if ev.type_ == alsa::SND_SEQ_EVENT_NONE as u8 { None } else { Some(unsafe { Event::extract(&mut ev, "snd_midi_event_encode") }?) }; Ok((r as usize, e)) } } #[test] fn print_seqs() { use std::ffi::CString; let s = super::Seq::open(None, None, false).unwrap(); s.set_client_name(&CString::new("rust_test_print_seqs").unwrap()).unwrap(); let clients: Vec<_> = ClientIter::new(&s).collect(); for a in &clients { let ports: Vec<_> = PortIter::new(&s, a.get_client()).collect(); println!("{:?}: {:?}", a, ports); } } #[test] fn seq_subscribe() { use std::ffi::CString; let s = super::Seq::open(None, None, false).unwrap(); s.set_client_name(&CString::new("rust_test_seq_subscribe").unwrap()).unwrap(); let timer_info = s.get_any_port_info(Addr { client: 0, port: 0 }).unwrap(); assert_eq!(timer_info.get_name().unwrap(), "Timer"); let info = PortInfo::empty().unwrap(); let _port = s.create_port(&info); let subs = PortSubscribe::empty().unwrap(); subs.set_sender(Addr { client: 0, port: 0 }); subs.set_dest(Addr { client: s.client_id().unwrap(), port: info.get_port() }); s.subscribe_port(&subs).unwrap(); } #[test] fn seq_loopback() { use std::ffi::CString; let s = super::Seq::open(Some(&CString::new("default").unwrap()), None, false).unwrap(); s.set_client_name(&CString::new("rust_test_seq_loopback").unwrap()).unwrap(); // Create ports let sinfo = PortInfo::empty().unwrap(); sinfo.set_capability(PortCap::READ | PortCap::SUBS_READ); sinfo.set_type(PortType::MIDI_GENERIC | PortType::APPLICATION); s.create_port(&sinfo).unwrap(); let sport = sinfo.get_port(); let dinfo = PortInfo::empty().unwrap(); dinfo.set_capability(PortCap::WRITE | PortCap::SUBS_WRITE); dinfo.set_type(PortType::MIDI_GENERIC | PortType::APPLICATION); s.create_port(&dinfo).unwrap(); let dport = dinfo.get_port(); // Connect them let subs = PortSubscribe::empty().unwrap(); subs.set_sender(Addr { client: s.client_id().unwrap(), port: sport }); subs.set_dest(Addr { client: s.client_id().unwrap(), port: dport }); s.subscribe_port(&subs).unwrap(); println!("Connected {:?} to {:?}", subs.get_sender(), subs.get_dest()); // Send a note! let note = EvNote { channel: 0, note: 64, duration: 100, velocity: 100, off_velocity: 64 }; let mut e = Event::new(EventType::Noteon, ¬e); e.set_subs(); e.set_direct(); e.set_source(sport); println!("Sending {:?}", e); s.event_output(&mut e).unwrap(); s.drain_output().unwrap(); // Receive the note! let mut input = s.input(); let e2 = input.event_input().unwrap(); println!("Receiving {:?}", e2); assert_eq!(e2.get_type(), EventType::Noteon); assert_eq!(e2.get_data(), Some(note)); } #[test] fn seq_encode_sysex() { let mut me = MidiEvent::new(16).unwrap(); let sysex = &[0xf0, 1, 2, 3, 4, 5, 6, 7, 0xf7]; let (s, ev) = me.encode(sysex).unwrap(); assert_eq!(s, 9); let ev = ev.unwrap(); let v = ev.get_ext().unwrap(); assert_eq!(&*v, sysex); } #[test] fn seq_decode_sysex() { let sysex = [0xf0, 1, 2, 3, 4, 5, 6, 7, 0xf7]; let mut ev = Event::new_ext(EventType::Sysex, &sysex[..]); let me = MidiEvent::new(0).unwrap(); let mut buffer = vec![0; sysex.len()]; assert_eq!(me.decode(&mut buffer[..], &mut ev).unwrap(), sysex.len()); assert_eq!(buffer, sysex); } #[test] #[should_panic] fn seq_get_input_twice() { use std::ffi::CString; let s = super::Seq::open(None, None, false).unwrap(); s.set_client_name(&CString::new("rust_test_seq_get_input_twice").unwrap()).unwrap(); let input1 = s.input(); let input2 = s.input(); // this should panic let _ = (input1, input2); } #[test] fn seq_has_data() { for v in EventType::all() { let v = *v; let mut i = 0; if <() as EventData>::has_data(v) { i += 1; } if <[u8; 12] as EventData>::has_data(v) { i += 1; } if Event::has_ext_data(v) { i += 1; } if EvNote::has_data(v) { i += 1; } if EvCtrl::has_data(v) { i += 1; } if Addr::has_data(v) { i += 1; } if Connect::has_data(v) { i += 1; } if EvResult::has_data(v) { i += 1; } if EvQueueControl::<()>::has_data(v) { i += 1; } if EvQueueControl::::has_data(v) { i += 1; } if EvQueueControl::::has_data(v) { i += 1; } if EvQueueControl::::has_data(v) { i += 1; } if i != 1 { panic!("{:?}: {} has_data", v, i) } } } #[test] fn seq_remove_events() -> std::result::Result<(), Box> { let info = RemoveEvents::new()?; info.set_condition(Remove::INPUT | Remove::DEST | Remove::TIME_BEFORE | Remove::TAG_MATCH); info.set_queue(123); info.set_time(time::Duration::new(456, 789)); info.set_dest(Addr { client: 212, port: 121 }); info.set_channel(15); info.set_event_type(EventType::Noteon); info.set_tag(213); assert_eq!(info.get_condition(), Remove::INPUT | Remove::DEST | Remove::TIME_BEFORE | Remove::TAG_MATCH); assert_eq!(info.get_queue(), 123); assert_eq!(info.get_time(), time::Duration::new(456, 789)); assert_eq!(info.get_dest(), Addr { client: 212, port: 121 }); assert_eq!(info.get_channel(), 15); assert_eq!(info.get_event_type()?, EventType::Noteon); assert_eq!(info.get_tag(), 213); Ok(()) } #[test] fn seq_portsubscribeiter() { let s = super::Seq::open(None, None, false).unwrap(); // Create ports let sinfo = PortInfo::empty().unwrap(); sinfo.set_capability(PortCap::READ | PortCap::SUBS_READ); sinfo.set_type(PortType::MIDI_GENERIC | PortType::APPLICATION); s.create_port(&sinfo).unwrap(); let sport = sinfo.get_port(); let dinfo = PortInfo::empty().unwrap(); dinfo.set_capability(PortCap::WRITE | PortCap::SUBS_WRITE); dinfo.set_type(PortType::MIDI_GENERIC | PortType::APPLICATION); s.create_port(&dinfo).unwrap(); let dport = dinfo.get_port(); // Connect them let subs = PortSubscribe::empty().unwrap(); subs.set_sender(Addr { client: s.client_id().unwrap(), port: sport }); subs.set_dest(Addr { client: s.client_id().unwrap(), port: dport }); s.subscribe_port(&subs).unwrap(); // Query READ subs from sport's point of view let read_subs: Vec = PortSubscribeIter::new(&s, Addr {client: s.client_id().unwrap(), port: sport }, QuerySubsType::READ).collect(); assert_eq!(read_subs.len(), 1); assert_eq!(read_subs[0].get_sender(), subs.get_sender()); assert_eq!(read_subs[0].get_dest(), subs.get_dest()); let write_subs: Vec = PortSubscribeIter::new(&s, Addr {client: s.client_id().unwrap(), port: sport }, QuerySubsType::WRITE).collect(); assert_eq!(write_subs.len(), 0); // Now query WRITE subs from dport's point of view let write_subs: Vec = PortSubscribeIter::new(&s, Addr {client: s.client_id().unwrap(), port: dport }, QuerySubsType::WRITE).collect(); assert_eq!(write_subs.len(), 1); assert_eq!(write_subs[0].get_sender(), subs.get_sender()); assert_eq!(write_subs[0].get_dest(), subs.get_dest()); }