diff --git a/Cargo.lock b/Cargo.lock index 36c8c9f..3e976b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,9 @@ version = 3 [[package]] name = "alsa" -version = "0.7.0" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2562ad8dcf0f789f65c6fdaad8a8a9708ed6b488e649da28c01656ad66b8b47" dependencies = [ "alsa-sys", "bitflags", diff --git a/Cargo.toml b/Cargo.toml index c6f8bc5..1f89ade 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] half = "^2.1.0" -alsa = { path = "./alsa" } +alsa = "^0.7.1" configparser = { version = "^3.0.2", features=["indexmap"] } clap = { version = "4.1.6", features=["derive"] } log = "0.4.17" diff --git a/README.md b/README.md index 11375f8..89c7458 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,6 @@ or enabling speaker output on your machine. An announcement will be made when sp support is ready for use. ## Requirements -* We currently rely on a local version of the `alsa` crate, as a release has not yet been - pushed to crates.io with the required bindings. * A patched eleven secret herbs and spices kernel ## Todo list @@ -25,7 +23,3 @@ support is ready for use. - [ ] Daemonise correctly - [ ] Kernel driver interlock - [ ] Packaging/distro-agnosticism - -## Sundry -The `alsa` crate is Copyright (c) 2015-2021 David Henningsson, and other -contributors. Redistributed under the MIT license. diff --git a/alsa/Cargo.lock b/alsa/Cargo.lock deleted file mode 100644 index abc0fd5..0000000 --- a/alsa/Cargo.lock +++ /dev/null @@ -1,58 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "alsa" -version = "0.7.0" -dependencies = [ - "alsa-sys", - "bitflags", - "libc", - "nix", -] - -[[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 = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[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.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" - -[[package]] -name = "nix" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] - -[[package]] -name = "pkg-config" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" diff --git a/alsa/Cargo.toml b/alsa/Cargo.toml deleted file mode 100644 index 0dab4c6..0000000 --- a/alsa/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "alsa" -version = "0.7.0" -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 = "1.3.2" -nix = { version = "^0.24", default-features = false, features = ["ioctl"] } - -[badges] -is-it-maintained-issue-resolution = { repository = "diwic/alsa-rs" } -is-it-maintained-open-issues = { repository = "diwic/alsa-rs" } diff --git a/alsa/LICENSE-APACHE b/alsa/LICENSE-APACHE deleted file mode 100644 index f433b1a..0000000 --- a/alsa/LICENSE-APACHE +++ /dev/null @@ -1,177 +0,0 @@ - - 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 diff --git a/alsa/LICENSE-MIT b/alsa/LICENSE-MIT deleted file mode 100644 index 993d2f9..0000000 --- a/alsa/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -MIT 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. diff --git a/alsa/README.md b/alsa/README.md deleted file mode 100644 index 74e801c..0000000 --- a/alsa/README.md +++ /dev/null @@ -1,62 +0,0 @@ -ALSA 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 poll or mio. - 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. - diff --git a/alsa/examples/record.rs b/alsa/examples/record.rs deleted file mode 100644 index d91fd15..0000000 --- a/alsa/examples/record.rs +++ /dev/null @@ -1,50 +0,0 @@ -//! Example that continously reads data and displays its RMS volume. - -use alsa::pcm::*; -use alsa::{Direction, ValueOr, Error}; - -fn start_capture(device: &str) -> Result { - let pcm = PCM::new(device, Direction::Capture, false)?; - { - // For this example, we assume 44100Hz, one channel, 16 bit audio. - let hwp = HwParams::any(&pcm)?; - hwp.set_channels(1)?; - hwp.set_rate(44100, ValueOr::Nearest)?; - hwp.set_format(Format::s16())?; - hwp.set_access(Access::RWInterleaved)?; - pcm.hw_params(&hwp)?; - } - pcm.start()?; - Ok(pcm) -} - -// Calculates RMS (root mean square) as a way to determine volume -fn rms(buf: &[i16]) -> f64 { - if buf.len() == 0 { return 0f64; } - let mut sum = 0f64; - for &x in buf { - sum += (x as f64) * (x as f64); - } - let r = (sum / (buf.len() as f64)).sqrt(); - // Convert value to decibels - 20.0 * (r / (i16::MAX as f64)).log10() -} - - -fn read_loop(pcm: &PCM) -> Result<(), Error> { - let io = pcm.io_i16()?; - let mut buf = [0i16; 8192]; - loop { - // Block while waiting for 8192 samples to be read from the device. - assert_eq!(io.readi(&mut buf)?, buf.len()); - let r = rms(&buf); - println!("RMS: {:.1} dB", r); - } -} - -fn main() { - // The "default" device is usually directed to the sound server process, - // e g PulseAudio or PipeWire. - let capture = start_capture("default").unwrap(); - read_loop(&capture).unwrap(); -} \ No newline at end of file diff --git a/alsa/src/card.rs b/alsa/src/card.rs deleted file mode 100644 index 93345f4..0000000 --- a/alsa/src/card.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! 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()) - } -} diff --git a/alsa/src/chmap.rs b/alsa/src/chmap.rs deleted file mode 100644 index b2c7592..0000000 --- a/alsa/src/chmap.rs +++ /dev/null @@ -1,148 +0,0 @@ -use 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 - } - } -} diff --git a/alsa/src/ctl_int.rs b/alsa/src/ctl_int.rs deleted file mode 100644 index aa81dc0..0000000 --- a/alsa/src/ctl_int.rs +++ /dev/null @@ -1,455 +0,0 @@ - -use crate::alsa; -use std::ffi::{CStr, CString}; -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_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(|_| ()) - } - - /// 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 }) - } -} - -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); -} diff --git a/alsa/src/device_name.rs b/alsa/src/device_name.rs deleted file mode 100644 index 965231e..0000000 --- a/alsa/src/device_name.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! 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) } - } -} diff --git a/alsa/src/direct.rs b/alsa/src/direct.rs deleted file mode 100644 index 239b5bd..0000000 --- a/alsa/src/direct.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Functions that bypass alsa-lib and talk directly to the kernel. - -pub mod pcm; - -mod ffi; diff --git a/alsa/src/direct/asound_ioctl.rs b/alsa/src/direct/asound_ioctl.rs deleted file mode 100644 index c145582..0000000 --- a/alsa/src/direct/asound_ioctl.rs +++ /dev/null @@ -1,6713 +0,0 @@ -/* 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) - ) - ); -} diff --git a/alsa/src/direct/ffi.rs b/alsa/src/direct/ffi.rs deleted file mode 100644 index 5e9738c..0000000 --- a/alsa/src/direct/ffi.rs +++ /dev/null @@ -1,79 +0,0 @@ - -// Some definitions from the kernel headers - -// 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, -} - -ioctl_read!(sndrv_pcm_ioctl_channel_info, b'A', 0x32, snd_pcm_channel_info); -ioctl_readwrite!(sndrv_pcm_ioctl_sync_ptr, b'A', 0x23, snd_pcm_sync_ptr); - -pub fn pagesize() -> usize { - unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } -} diff --git a/alsa/src/direct/pcm.rs b/alsa/src/direct/pcm.rs deleted file mode 100644 index ccea666..0000000 --- a/alsa/src/direct/pcm.rs +++ /dev/null @@ -1,630 +0,0 @@ -/*! -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).map_err(|_| - Error::new("SNDRV_PCM_IOCTL_SYNC_PTR", nix::errno::Errno::last() as i32))?; - - 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::new("mmap (of driver memory)", nix::errno::Errno::last() as i32)) - } 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).map_err(|_| - Error::new("SNDRV_PCM_IOCTL_CHANNEL_INFO", nix::errno::Errno::last() as i32))?; - 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()); -} diff --git a/alsa/src/error.rs b/alsa/src/error.rs deleted file mode 100644 index 02debb8..0000000 --- a/alsa/src/error.rs +++ /dev/null @@ -1,100 +0,0 @@ -#![macro_use] - -use libc::{c_void, c_int, c_char, free}; -use std::{fmt, str}; -use std::ffi::CStr; -use std::error::Error as StdError; - -/// 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(Debug, Clone, PartialEq, Copy)] -pub struct Error(&'static str, nix::Error); - -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 { - let errno = nix::errno::Errno::from_i32(res as i32); - Error(func, errno) - } - - pub fn unsupported(func: &'static str) -> Error { - Error(func, nix::Error::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) -> nix::Error { self.1 } - - /// 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 nix_error(&self) -> nix::Error { self.1 } -} - -pub fn invalid_str(func: &'static str) -> Error { Error(func, nix::Error::EILSEQ) } - -impl StdError for Error { - fn source(&self) -> Option<&(dyn StdError + 'static)> { Some(&self.1) } - fn description(&self) -> &str { "ALSA error" } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "ALSA function '{}' failed with error '{}'", self.0, self.1) - } -} - -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(), nix::errno::Errno::ENOENT); -} diff --git a/alsa/src/hctl.rs b/alsa/src/hctl.rs deleted file mode 100644 index b6f5aad..0000000 --- a/alsa/src/hctl.rs +++ /dev/null @@ -1,162 +0,0 @@ -//! 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; -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)) - } - - 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" }) - } - } - } -} diff --git a/alsa/src/io.rs b/alsa/src/io.rs deleted file mode 100644 index f6c3739..0000000 --- a/alsa/src/io.rs +++ /dev/null @@ -1,49 +0,0 @@ -use 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 } diff --git a/alsa/src/lib.rs b/alsa/src/lib.rs deleted file mode 100644 index ce83ec4..0000000 --- a/alsa/src/lib.rs +++ /dev/null @@ -1,140 +0,0 @@ -//! 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_use] -extern crate nix as nix_the_crate; - -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)) - } -} - -} -} - -/// 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, 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; - -/// Re-exports from the nix crate. -/// -/// Use these re-exports instead of also depending on the nix crate. There -/// is no guarantee that these will match a specific nix version, it may -/// change between minor updates of the library. -pub mod nix { - pub use nix_the_crate::Error; - pub use nix_the_crate::errno; -} diff --git a/alsa/src/mixer.rs b/alsa/src/mixer.rs deleted file mode 100644 index d925f09..0000000 --- a/alsa/src/mixer.rs +++ /dev/null @@ -1,639 +0,0 @@ -//! 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(|i| i == 1) } -} - -/// 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_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)) - } - - 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)) - } - - 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_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: "); - 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); -} diff --git a/alsa/src/pcm.rs b/alsa/src/pcm.rs deleted file mode 100644 index b25a1d9..0000000 --- a/alsa/src/pcm.rs +++ /dev/null @@ -1,1151 +0,0 @@ -//! 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::marker::PhantomData; -use std::mem::size_of; -use std::ffi::{CStr, CString}; -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; - -pub struct Info(*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), - } - } -} - -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)) - } - - #[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) - } - - 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 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 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); -} diff --git a/alsa/src/poll.rs b/alsa/src/poll.rs deleted file mode 100644 index 3e91911..0000000 --- a/alsa/src/poll.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! 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! { - 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) -} diff --git a/alsa/src/rawmidi.rs b/alsa/src/rawmidi.rs deleted file mode 100644 index 50ef9cc..0000000 --- a/alsa/src/rawmidi.rs +++ /dev/null @@ -1,211 +0,0 @@ -//! 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()) - } - } -} diff --git a/alsa/src/seq.rs b/alsa/src/seq.rs deleted file mode 100644 index bb1e46d..0000000 --- a/alsa/src/seq.rs +++ /dev/null @@ -1,1567 +0,0 @@ -//! 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! { - /// [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! { - /// [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! { - /// [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() - } -} - -/// Low level methods to set/get data on an Event. Don't use these directly, use generic methods on Event instead. -pub trait EventData { - fn get_data(ev: &Event) -> Self; - fn has_data(e: EventType) -> bool; - 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 mut 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()); -} diff --git a/alsa/synth-example/Cargo.toml b/alsa/synth-example/Cargo.toml deleted file mode 100644 index 0390f2a..0000000 --- a/alsa/synth-example/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "synth-example" -version = "0.1.0" -authors = ["David Henningsson "] -edition = "2018" - -[dependencies] -dasp = { version = "0.11", features = ["signal"] } -alsa = { path = "..", version = "0.6" } diff --git a/alsa/synth-example/src/main.rs b/alsa/synth-example/src/main.rs deleted file mode 100644 index 5ef98e4..0000000 --- a/alsa/synth-example/src/main.rs +++ /dev/null @@ -1,311 +0,0 @@ -// A quickly made Hammond organ. - -use std::{iter, error}; -use alsa::{seq, pcm}; -use std::ffi::CString; -use dasp::signal; - -type Res = Result>; - -fn connect_midi_source_ports(s: &alsa::Seq, our_port: i32) -> Res<()> { - // Iterate over clients and clients' ports - let our_id = s.client_id()?; - let ci = seq::ClientIter::new(&s); - for client in ci { - if client.get_client() == our_id { continue; } // Skip ourselves - let pi = seq::PortIter::new(&s, client.get_client()); - for port in pi { - let caps = port.get_capability(); - - // Check that it's a normal input port - if !caps.contains(seq::PortCap::READ) || !caps.contains(seq::PortCap::SUBS_READ) { continue; } - if !port.get_type().contains(seq::PortType::MIDI_GENERIC) { continue; } - - // Connect source and dest ports - let subs = seq::PortSubscribe::empty()?; - subs.set_sender(seq::Addr { client: port.get_client(), port: port.get_port() }); - subs.set_dest(seq::Addr { client: our_id, port: our_port }); - println!("Reading from midi input {:?}", port); - s.subscribe_port(&subs)?; - } - } - - Ok(()) -} - -fn open_midi_dev() -> Res { - // Open the sequencer. - let s = alsa::Seq::open(None, Some(alsa::Direction::Capture), true)?; - let cstr = CString::new("rust_synth_example").unwrap(); - s.set_client_name(&cstr)?; - - // Create a destination port we can read from - let mut dinfo = seq::PortInfo::empty().unwrap(); - dinfo.set_capability(seq::PortCap::WRITE | seq::PortCap::SUBS_WRITE); - dinfo.set_type(seq::PortType::MIDI_GENERIC | seq::PortType::APPLICATION); - dinfo.set_name(&cstr); - s.create_port(&dinfo).unwrap(); - let dport = dinfo.get_port(); - - // source ports should ideally be configurable, but right now we're just reading them all. - connect_midi_source_ports(&s, dport)?; - - Ok(s) -} - -fn open_audio_dev() -> Res<(alsa::PCM, u32)> { - let args: Vec<_> = std::env::args().collect(); - if args.len() < 2 { - println!("Usage: 'cargo run --release CARD_NAME SAMPLE_RATE BUF_SIZE'"); - Err("No card name specified")? - } - let req_devname = format!("hw:{}", args[1]); - let req_samplerate = args.get(2).map(|x| x.parse()).unwrap_or(Ok(48000))?; - let req_bufsize = args.get(3).map(|x| x.parse()).unwrap_or(Ok(256))?; // A few ms latency by default, that should be nice - - // Open the device - let p = alsa::PCM::new(&req_devname, alsa::Direction::Playback, false)?; - - // Set hardware parameters - { - let hwp = pcm::HwParams::any(&p)?; - hwp.set_channels(2)?; - hwp.set_rate(req_samplerate, alsa::ValueOr::Nearest)?; - hwp.set_format(pcm::Format::s16())?; - hwp.set_access(pcm::Access::MMapInterleaved)?; - hwp.set_buffer_size(req_bufsize)?; - hwp.set_period_size(req_bufsize / 4, alsa::ValueOr::Nearest)?; - p.hw_params(&hwp)?; - } - - // Set software parameters - let rate = { - let hwp = p.hw_params_current()?; - let swp = p.sw_params_current()?; - let (bufsize, periodsize) = (hwp.get_buffer_size()?, hwp.get_period_size()?); - swp.set_start_threshold(bufsize - periodsize)?; - swp.set_avail_min(periodsize)?; - p.sw_params(&swp)?; - println!("Opened audio output {:?} with parameters: {:?}, {:?}", req_devname, hwp, swp); - hwp.get_rate()? - }; - - Ok((p, rate)) -} - -// Sample format -type SF = i16; - -type SigGen = signal::Sine; - -// Standard Hammond drawbar. -const BAR_FREQS: [f64; 9] = [16., 5.+1./3., 8., 4., 2.+2./3., 2., 1.+3./5., 1.+1./3., 1.]; - -#[derive(Clone)] -struct Sig { - note: u8, - sig: SigGen, - targetvol: f64, - curvol: f64, - baridx: usize, -} - - -struct Synth { - sigs: Vec>, - sample_rate: signal::Rate, - stored_sample: Option, - bar_values: [f64; 9], -} - -impl Synth { - fn add_note(&mut self, note: u8, vol: f64) { - let hz = 440. * 2_f64.powf((note as f64 - 69.)/12.); - - for (baridx, barfreq) in BAR_FREQS.iter().enumerate() { - let idx = self.sigs.iter().position(|s| s.is_none()); - let idx = if let Some(idx) = idx { idx } else { - println!("Voice overflow!"); return; - }; - let hz = self.sample_rate.const_hz(hz * 8. / barfreq); - let s = Sig { sig: hz.sine(), note, targetvol: vol, curvol: 0., baridx }; - self.sigs[idx] = Some(s); - } - } - fn remove_note(&mut self, note: u8) { - for i in self.sigs.iter_mut() { - if let &mut Some(ref mut i) = i { - if i.note == note { i.targetvol = 0. } - } - } - } - fn cc(&mut self, ctrl: u32, value: i32) { - let idx = match ctrl { - // Standard knobs on UMA25S, modify to your liking - 1 => 0, - 74 => 1, - 71 => 2, - 73 => 3, - 75 => 4, - 72 => 5, - 91 => 6, - 93 => 7, - 10 => 8, - _ => return, - }; - self.bar_values[idx] = f64::from(value) / 255.; - } -} - -impl Iterator for Synth { - type Item = SF; - fn next(&mut self) -> Option { - use dasp::{signal::Signal, Sample}; - - // Mono -> Stereo - if let Some(s) = self.stored_sample.take() { return Some(s) }; - - let mut z = 0f64; - for sig in &mut self.sigs { - let mut remove = false; - if let &mut Some(ref mut i) = sig { - let barvalue = self.bar_values[i.baridx]; - if barvalue > 0.0 { - let s = i.sig.next(); - z += s.mul_amp(i.curvol * barvalue); - } - - // Quick and dirty volume envelope to avoid clicks. - if i.curvol != i.targetvol { - if i.targetvol == 0. { - i.curvol -= 0.002; - if i.curvol <= 0. { remove = true; } - } else { - i.curvol += 0.002; - if i.curvol >= i.targetvol { i.curvol = i.targetvol; } - } - } - } - if remove { *sig = None }; - } - let z = z.min(0.999).max(-0.999); - let z: Option = Some(SF::from_sample(z)); - self.stored_sample = z; - z - } -} - -fn write_samples_direct(p: &alsa::PCM, mmap: &mut alsa::direct::pcm::MmapPlayback, synth: &mut Synth) - -> Res { - - if mmap.avail() > 0 { - // Write samples to DMA area from iterator - mmap.write(synth); - } - use alsa::pcm::State; - match mmap.status().state() { - State::Running => { return Ok(false); }, // All fine - State::Prepared => { println!("Starting audio output stream"); p.start()? }, - State::XRun => { println!("Underrun in audio output stream!"); p.prepare()? }, - State::Suspended => { println!("Resuming audio output stream"); p.resume()? }, - n @ _ => Err(format!("Unexpected pcm state {:?}", n))?, - } - Ok(true) // Call us again, please, there might be more data to write -} - -fn write_samples_io(p: &alsa::PCM, io: &mut alsa::pcm::IO, synth: &mut Synth) -> Res { - let avail = match p.avail_update() { - Ok(n) => n, - Err(e) => { - println!("Recovering from {}", e); - p.recover(e.errno() as std::os::raw::c_int, true)?; - p.avail_update()? - } - } as usize; - - if avail > 0 { - io.mmap(avail, |buf| { - for sample in buf.iter_mut() { - *sample = synth.next().unwrap() - }; - buf.len() / 2 - })?; - } - use alsa::pcm::State; - match p.state() { - State::Running => Ok(false), // All fine - State::Prepared => { println!("Starting audio output stream"); p.start()?; Ok(true) }, - State::Suspended | State::XRun => Ok(true), // Recover from this in next round - n @ _ => Err(format!("Unexpected pcm state {:?}", n))?, - } -} - -fn read_midi_event(input: &mut seq::Input, synth: &mut Synth) -> Res { - if input.event_input_pending(true)? == 0 { return Ok(false); } - let ev = input.event_input()?; - // println!("Received: {:?}", ev); - match ev.get_type() { - seq::EventType::Noteon => { - let data: seq::EvNote = ev.get_data().unwrap(); - if data.velocity == 0 { - synth.remove_note(data.note); - } else { - synth.add_note(data.note, f64::from(data.velocity + 64) / 2048.); - } - }, - seq::EventType::Noteoff => { - let data: seq::EvNote = ev.get_data().unwrap(); - synth.remove_note(data.note); - }, - seq::EventType::Controller => { - let data: seq::EvCtrl = ev.get_data().unwrap(); - synth.cc(data.param, data.value); - } - _ => {}, - } - Ok(true) -} - - -fn run() -> Res<()> { - let (audio_dev, rate) = open_audio_dev()?; - let midi_dev = open_midi_dev()?; - - let mut midi_input = midi_dev.input(); - - // 256 Voices synth - let mut synth = Synth { - sigs: iter::repeat(None).take(256).collect(), - sample_rate: signal::rate(f64::from(rate)), - stored_sample: None, - bar_values: [1., 0.75, 1., 0.75, 0., 0., 0., 0., 0.75], // Some Gospel-ish default. - }; - - // Create an array of fds to poll. - use alsa::PollDescriptors; - let mut fds = audio_dev.get()?; - fds.append(&mut (&midi_dev, Some(alsa::Direction::Capture)).get()?); - - // Let's use the fancy new "direct mode" for minimum overhead! - let mut mmap = audio_dev.direct_mmap_playback::(); - - // Direct mode unavailable, use alsa-lib's mmap emulation instead - let mut io = if mmap.is_err() { - Some(audio_dev.io_i16()?) - } else { None }; - - loop { - if let Ok(ref mut mmap) = mmap { - if write_samples_direct(&audio_dev, mmap, &mut synth)? { continue; } - } else if let Some(ref mut io) = io { - if write_samples_io(&audio_dev, io, &mut synth)? { continue; } - } - if read_midi_event(&mut midi_input, &mut synth)? { continue; } - // Nothing to do, let's sleep until woken up by the kernel. - alsa::poll::poll(&mut fds, 100)?; - } -} - -fn main() { - if let Err(e) = run() { println!("Error: {}", e); } -}