summaryrefslogtreecommitdiffstats
path: root/third_party/rust/alsa
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/alsa')
-rw-r--r--third_party/rust/alsa/.cargo-checksum.json1
-rw-r--r--third_party/rust/alsa/Cargo.toml57
-rw-r--r--third_party/rust/alsa/LICENSE-APACHE177
-rw-r--r--third_party/rust/alsa/LICENSE-MIT21
-rw-r--r--third_party/rust/alsa/README.md62
-rw-r--r--third_party/rust/alsa/src/card.rs54
-rw-r--r--third_party/rust/alsa/src/chmap.rs148
-rw-r--r--third_party/rust/alsa/src/ctl_int.rs443
-rw-r--r--third_party/rust/alsa/src/device_name.rs90
-rw-r--r--third_party/rust/alsa/src/direct.rs5
-rw-r--r--third_party/rust/alsa/src/direct/asound_ioctl.rs6713
-rw-r--r--third_party/rust/alsa/src/direct/ffi.rs79
-rw-r--r--third_party/rust/alsa/src/direct/pcm.rs630
-rw-r--r--third_party/rust/alsa/src/error.rs100
-rw-r--r--third_party/rust/alsa/src/hctl.rs162
-rw-r--r--third_party/rust/alsa/src/io.rs49
-rw-r--r--third_party/rust/alsa/src/lib.rs140
-rw-r--r--third_party/rust/alsa/src/mixer.rs639
-rw-r--r--third_party/rust/alsa/src/pcm.rs1151
-rw-r--r--third_party/rust/alsa/src/poll.rs68
-rw-r--r--third_party/rust/alsa/src/rawmidi.rs211
-rw-r--r--third_party/rust/alsa/src/seq.rs1567
22 files changed, 12567 insertions, 0 deletions
diff --git a/third_party/rust/alsa/.cargo-checksum.json b/third_party/rust/alsa/.cargo-checksum.json
new file mode 100644
index 0000000000..6c1275da33
--- /dev/null
+++ b/third_party/rust/alsa/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"ebf9ca424a7b1dcebc54249f6c58d4668c1adb200fa8cc6aca2af50175f89355","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"3cc33f8e76680b9cba2e2a5bc94de5a92420045863ab2fadbef290a55b4d8530","README.md":"36dd58bf914ea508c409133b1ce908ab9a12d766cc23a48eb990ba4a4dba6ed8","src/card.rs":"874675475f6f9287831eb8d74df2acc5bafea2f9ef40aeb887f547571e55c613","src/chmap.rs":"171779996a2ba6465f37ee7854eb7630c2a28da47f977a11bf82af075c0c3e8f","src/ctl_int.rs":"4a007295952413a3ea7f4629cb4808e6654cd2bd00f53d5c616c72ea2b400aef","src/device_name.rs":"5a0e9502dfb829bc005838bc7e9419c817fbbb6d56c8ad97dee56d53fddf1b64","src/direct.rs":"fbd40addd2458bb0b3e856e5b0225fd24dc0ad46ce3662aef12635cf34ef7f55","src/direct/asound_ioctl.rs":"27c8935a0e7bd6e1925d947411c37ca81befba60468a6f2206da9fb08805be89","src/direct/ffi.rs":"aeb0871bd764198558557b5af1a1f6038efe8c8a400d77b4ddfc91143029ac90","src/direct/pcm.rs":"017b5f9e0bb85730e12cef7de97dcbb641690a42cc706367aa30c87f2d8b28b1","src/error.rs":"32ecdbef500e75a65390d7757e2e8bcd17cc97326653eb49b8e59031aa001702","src/hctl.rs":"7f7b2a62f94b296b6e0e5e7dc87ab3b16d5f657ae86cc8a547d6d821a702960b","src/io.rs":"a6e21b94a265b7de56388e035b104877c8b6a0f5d10002c5931dacc90dd577fd","src/lib.rs":"a380f903951ee5706578702076e85751de5c62451623fde2b45be632a2be2e97","src/mixer.rs":"925bf2bf64180c1314311ed284e03ae806d020b0e93aa2bf8f617040e9fbc881","src/pcm.rs":"de347ce845eb00f549e48b9c1f7be3b53f99c2f16b94ce98a5958ef414c5bdef","src/poll.rs":"04065e299c065a8f0127ff951e242052d6ebfaf8f111d452833f0454bf5b209f","src/rawmidi.rs":"7fe501699290706d010db187f6f81ef0c597d6c3820c0df04b24ac835f1cb6ca","src/seq.rs":"ef730132dc45499063e0d0daf3f68ab8a91fb5aa2f987b064c307dfd126801b8"},"package":"8512c9117059663fb5606788fbca3619e2a91dac0e3fe516242eab1fa6be5e44"} \ No newline at end of file
diff --git a/third_party/rust/alsa/Cargo.toml b/third_party/rust/alsa/Cargo.toml
new file mode 100644
index 0000000000..15f45319b1
--- /dev/null
+++ b/third_party/rust/alsa/Cargo.toml
@@ -0,0 +1,57 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+name = "alsa"
+version = "0.7.0"
+authors = ["David Henningsson <coding@diwic.se>"]
+include = [
+ "README.md",
+ "LICENSE-*",
+ "Cargo.toml",
+ "src/",
+]
+description = "Thin but safe wrappers for ALSA (Linux sound API)"
+documentation = "http://docs.rs/alsa"
+readme = "README.md"
+keywords = [
+ "ALSA",
+ "audio",
+ "sound",
+]
+categories = [
+ "multimedia::audio",
+ "api-bindings",
+]
+license = "Apache-2.0/MIT"
+repository = "https://github.com/diwic/alsa-rs"
+resolver = "2"
+
+[dependencies.alsa-sys]
+version = "0.3.1"
+
+[dependencies.bitflags]
+version = "1.3.2"
+
+[dependencies.libc]
+version = "0.2"
+
+[dependencies.nix]
+version = "^0.24"
+features = ["ioctl"]
+default-features = false
+
+[badges.is-it-maintained-issue-resolution]
+repository = "diwic/alsa-rs"
+
+[badges.is-it-maintained-open-issues]
+repository = "diwic/alsa-rs"
diff --git a/third_party/rust/alsa/LICENSE-APACHE b/third_party/rust/alsa/LICENSE-APACHE
new file mode 100644
index 0000000000..f433b1a53f
--- /dev/null
+++ b/third_party/rust/alsa/LICENSE-APACHE
@@ -0,0 +1,177 @@
+
+ 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/third_party/rust/alsa/LICENSE-MIT b/third_party/rust/alsa/LICENSE-MIT
new file mode 100644
index 0000000000..993d2f9b24
--- /dev/null
+++ b/third_party/rust/alsa/LICENSE-MIT
@@ -0,0 +1,21 @@
+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/third_party/rust/alsa/README.md b/third_party/rust/alsa/README.md
new file mode 100644
index 0000000000..74e801c944
--- /dev/null
+++ b/third_party/rust/alsa/README.md
@@ -0,0 +1,62 @@
+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/third_party/rust/alsa/src/card.rs b/third_party/rust/alsa/src/card.rs
new file mode 100644
index 0000000000..93345f4bb7
--- /dev/null
+++ b/third_party/rust/alsa/src/card.rs
@@ -0,0 +1,54 @@
+//! 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<Card>;
+
+ fn next(&mut self) -> Option<Result<Card>> {
+ 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<Card> {
+ acheck!(snd_card_get_index(s.as_ptr())).map(Card)
+ }
+ pub fn get_name(&self) -> Result<String> {
+ 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<String> {
+ 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/third_party/rust/alsa/src/chmap.rs b/third_party/rust/alsa/src/chmap.rs
new file mode 100644
index 0000000000..b2c75921b3
--- /dev/null
+++ b/third_party/rust/alsa/src/chmap.rs
@@ -0,0 +1,148 @@
+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<libc::c_char> = 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::<alsa::snd_pcm_chmap_t>() + mem::size_of::<libc::c_uint>() * 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<ChmapPosition> {
+ fn from(a: &'a Chmap) -> Vec<ChmapPosition> {
+ 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<Self::Item> {
+ 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/third_party/rust/alsa/src/ctl_int.rs b/third_party/rust/alsa/src/ctl_int.rs
new file mode 100644
index 0000000000..1be29dbdc3
--- /dev/null
+++ b/third_party/rust/alsa/src/ctl_int.rs
@@ -0,0 +1,443 @@
+
+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> {
+ 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<Ctl> {
+ 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<Ctl> {
+ let s = format!("hw:{}", c.get_index());
+ Ctl::open(&CString::new(s).unwrap(), nonblock)
+ }
+
+ pub fn card_info(&self) -> Result<CardInfo> { CardInfo::new().and_then(|c|
+ acheck!(snd_ctl_card_info(self.0, c.0)).map(|_| c)) }
+
+ pub fn wait(&self, timeout_ms: Option<u32>) -> Result<bool> {
+ 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<MilliBel> {
+ 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<i64> {
+ 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)
+ }
+
+ /// 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<Option<Event>> {
+ 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<usize> {
+ 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<poll::Flags> {
+ 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<CardInfo> {
+ 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<ElemValue> {
+ let mut p = ptr::null_mut();
+ acheck!(snd_ctl_elem_value_malloc(&mut p))
+ .map(|_| ElemValue { ptr: p, etype: t, count })
+}
+
+impl ElemValue {
+
+ // 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<bool> {
+ 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<i32> {
+ 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<i64> {
+ 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<u32> {
+ 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<u8> {
+ 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<ElemValue> {
+ // 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<ElemInfo> {
+ 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<ElemId> {
+ 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<ElemId> {
+ 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<Event> {
+ 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/third_party/rust/alsa/src/device_name.rs b/third_party/rust/alsa/src/device_name.rs
new file mode 100644
index 0000000000..965231e1a0
--- /dev/null
+++ b/third_party/rust/alsa/src/device_name.rs
@@ -0,0 +1,90 @@
+//! 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<HintIter> {
+ 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> {
+ HintIter::new(card, &CString::new(iface).unwrap())
+ }
+}
+
+impl Iterator for HintIter {
+ type Item = Hint;
+ fn next(&mut self) -> Option<Hint> {
+ 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<String>,
+ pub desc: Option<String>,
+ pub direction: Option<Direction>,
+}
+
+impl Hint {
+ fn get_str(p: *const c_void, name: &str) -> Option<String> {
+ 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/third_party/rust/alsa/src/direct.rs b/third_party/rust/alsa/src/direct.rs
new file mode 100644
index 0000000000..239b5bd158
--- /dev/null
+++ b/third_party/rust/alsa/src/direct.rs
@@ -0,0 +1,5 @@
+//! Functions that bypass alsa-lib and talk directly to the kernel.
+
+pub mod pcm;
+
+mod ffi;
diff --git a/third_party/rust/alsa/src/direct/asound_ioctl.rs b/third_party/rust/alsa/src/direct/asound_ioctl.rs
new file mode 100644
index 0000000000..c1455827b7
--- /dev/null
+++ b/third_party/rust/alsa/src/direct/asound_ioctl.rs
@@ -0,0 +1,6713 @@
+/* automatically generated by rust-bindgen */
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub struct __BindgenBitfieldUnit<Storage, Align>
+where
+ Storage: AsRef<[u8]> + AsMut<[u8]>,
+{
+ storage: Storage,
+ align: [Align; 0],
+}
+
+impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
+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<T>(::std::marker::PhantomData<T>);
+impl<T> __IncompleteArrayField<T> {
+ #[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<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
+ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+ fmt.write_str("__IncompleteArrayField")
+ }
+}
+impl<T> ::std::clone::Clone for __IncompleteArrayField<T> {
+ #[inline]
+ fn clone(&self) -> Self {
+ Self::new()
+ }
+}
+impl<T> ::std::marker::Copy for __IncompleteArrayField<T> {}
+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<unsafe extern "C" fn(arg1: ::std::os::raw::c_int)>;
+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::<wait__bindgen_ty_1>(),
+ 4usize,
+ concat!("Size of: ", stringify!(wait__bindgen_ty_1))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<wait__bindgen_ty_1>(),
+ 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::<wait__bindgen_ty_2>(),
+ 4usize,
+ concat!("Size of: ", stringify!(wait__bindgen_ty_2))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<wait__bindgen_ty_2>(),
+ 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::<wait>(),
+ 4usize,
+ concat!("Size of: ", stringify!(wait))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<wait>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(wait))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<wait>())).w_status as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(wait),
+ "::",
+ stringify!(w_status)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<wait>())).__wait_terminated as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(wait),
+ "::",
+ stringify!(__wait_terminated)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<wait>())).__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::<div_t>(),
+ 8usize,
+ concat!("Size of: ", stringify!(div_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<div_t>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(div_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<div_t>())).quot as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(div_t),
+ "::",
+ stringify!(quot)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<div_t>())).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::<ldiv_t>(),
+ 16usize,
+ concat!("Size of: ", stringify!(ldiv_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<ldiv_t>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(ldiv_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<ldiv_t>())).quot as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(ldiv_t),
+ "::",
+ stringify!(quot)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<ldiv_t>())).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::<lldiv_t>(),
+ 16usize,
+ concat!("Size of: ", stringify!(lldiv_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<lldiv_t>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(lldiv_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<lldiv_t>())).quot as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(lldiv_t),
+ "::",
+ stringify!(quot)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<lldiv_t>())).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::<timespec>(),
+ 16usize,
+ concat!("Size of: ", stringify!(timespec))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<timespec>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(timespec))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<timespec>())).tv_sec as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(timespec),
+ "::",
+ stringify!(tv_sec)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<timespec>())).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::<timeval>(),
+ 16usize,
+ concat!("Size of: ", stringify!(timeval))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<timeval>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(timeval))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<timeval>())).tv_sec as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(timeval),
+ "::",
+ stringify!(tv_sec)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<timeval>())).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::<fd_set>(),
+ 128usize,
+ concat!("Size of: ", stringify!(fd_set))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<fd_set>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(fd_set))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<fd_set>())).__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::<pthread_attr_t>(),
+ 56usize,
+ concat!("Size of: ", stringify!(pthread_attr_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_attr_t>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(pthread_attr_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_attr_t>())).__size as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_attr_t),
+ "::",
+ stringify!(__size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_attr_t>())).__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::<pthread_mutex_t___pthread_mutex_s>(),
+ 40usize,
+ concat!("Size of: ", stringify!(pthread_mutex_t___pthread_mutex_s))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_mutex_t___pthread_mutex_s>(),
+ 8usize,
+ concat!(
+ "Alignment of ",
+ stringify!(pthread_mutex_t___pthread_mutex_s)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<pthread_mutex_t___pthread_mutex_s>())).__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::<pthread_mutex_t___pthread_mutex_s>())).__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::<pthread_mutex_t___pthread_mutex_s>())).__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::<pthread_mutex_t___pthread_mutex_s>())).__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::<pthread_mutex_t___pthread_mutex_s>())).__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::<pthread_mutex_t___pthread_mutex_s>())).__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::<pthread_mutex_t___pthread_mutex_s>())).__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::<pthread_mutex_t___pthread_mutex_s>())).__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::<pthread_mutex_t>(),
+ 40usize,
+ concat!("Size of: ", stringify!(pthread_mutex_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_mutex_t>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(pthread_mutex_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_mutex_t>())).__data as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_mutex_t),
+ "::",
+ stringify!(__data)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_mutex_t>())).__size as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_mutex_t),
+ "::",
+ stringify!(__size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_mutex_t>())).__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::<pthread_mutexattr_t>(),
+ 4usize,
+ concat!("Size of: ", stringify!(pthread_mutexattr_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_mutexattr_t>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(pthread_mutexattr_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_mutexattr_t>())).__size as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_mutexattr_t),
+ "::",
+ stringify!(__size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_mutexattr_t>())).__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::<pthread_cond_t__bindgen_ty_1>(),
+ 48usize,
+ concat!("Size of: ", stringify!(pthread_cond_t__bindgen_ty_1))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_cond_t__bindgen_ty_1>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(pthread_cond_t__bindgen_ty_1))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<pthread_cond_t__bindgen_ty_1>())).__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::<pthread_cond_t__bindgen_ty_1>())).__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::<pthread_cond_t__bindgen_ty_1>())).__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::<pthread_cond_t__bindgen_ty_1>())).__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::<pthread_cond_t__bindgen_ty_1>())).__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::<pthread_cond_t__bindgen_ty_1>())).__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::<pthread_cond_t__bindgen_ty_1>())).__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::<pthread_cond_t__bindgen_ty_1>())).__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::<pthread_cond_t>(),
+ 48usize,
+ concat!("Size of: ", stringify!(pthread_cond_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_cond_t>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(pthread_cond_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_cond_t>())).__data as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_cond_t),
+ "::",
+ stringify!(__data)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_cond_t>())).__size as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_cond_t),
+ "::",
+ stringify!(__size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_cond_t>())).__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::<pthread_condattr_t>(),
+ 4usize,
+ concat!("Size of: ", stringify!(pthread_condattr_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_condattr_t>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(pthread_condattr_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_condattr_t>())).__size as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_condattr_t),
+ "::",
+ stringify!(__size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_condattr_t>())).__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::<pthread_rwlock_t__bindgen_ty_1>(),
+ 56usize,
+ concat!("Size of: ", stringify!(pthread_rwlock_t__bindgen_ty_1))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_rwlock_t__bindgen_ty_1>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(pthread_rwlock_t__bindgen_ty_1))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t__bindgen_ty_1>())).__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::<pthread_rwlock_t>(),
+ 56usize,
+ concat!("Size of: ", stringify!(pthread_rwlock_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_rwlock_t>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(pthread_rwlock_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_rwlock_t>())).__data as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_rwlock_t),
+ "::",
+ stringify!(__data)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_rwlock_t>())).__size as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_rwlock_t),
+ "::",
+ stringify!(__size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_rwlock_t>())).__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::<pthread_rwlockattr_t>(),
+ 8usize,
+ concat!("Size of: ", stringify!(pthread_rwlockattr_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_rwlockattr_t>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(pthread_rwlockattr_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_rwlockattr_t>())).__size as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_rwlockattr_t),
+ "::",
+ stringify!(__size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_rwlockattr_t>())).__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::<pthread_barrier_t>(),
+ 32usize,
+ concat!("Size of: ", stringify!(pthread_barrier_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_barrier_t>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(pthread_barrier_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_barrier_t>())).__size as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_barrier_t),
+ "::",
+ stringify!(__size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_barrier_t>())).__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::<pthread_barrierattr_t>(),
+ 4usize,
+ concat!("Size of: ", stringify!(pthread_barrierattr_t))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<pthread_barrierattr_t>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(pthread_barrierattr_t))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_barrierattr_t>())).__size as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(pthread_barrierattr_t),
+ "::",
+ stringify!(__size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<pthread_barrierattr_t>())).__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::<random_data>(),
+ 48usize,
+ concat!("Size of: ", stringify!(random_data))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<random_data>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(random_data))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<random_data>())).fptr as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(random_data),
+ "::",
+ stringify!(fptr)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<random_data>())).rptr as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(random_data),
+ "::",
+ stringify!(rptr)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<random_data>())).state as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(random_data),
+ "::",
+ stringify!(state)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<random_data>())).rand_type as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(random_data),
+ "::",
+ stringify!(rand_type)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<random_data>())).rand_deg as *const _ as usize },
+ 28usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(random_data),
+ "::",
+ stringify!(rand_deg)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<random_data>())).rand_sep as *const _ as usize },
+ 32usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(random_data),
+ "::",
+ stringify!(rand_sep)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<random_data>())).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::<drand48_data>(),
+ 24usize,
+ concat!("Size of: ", stringify!(drand48_data))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<drand48_data>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(drand48_data))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<drand48_data>())).__x as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(drand48_data),
+ "::",
+ stringify!(__x)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<drand48_data>())).__old_x as *const _ as usize },
+ 6usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(drand48_data),
+ "::",
+ stringify!(__old_x)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<drand48_data>())).__c as *const _ as usize },
+ 12usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(drand48_data),
+ "::",
+ stringify!(__c)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<drand48_data>())).__init as *const _ as usize },
+ 14usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(drand48_data),
+ "::",
+ stringify!(__init)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<drand48_data>())).__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<unsafe extern "C" fn()>) -> ::std::os::raw::c_int;
+}
+extern "C" {
+ pub fn at_quick_exit(
+ __func: ::std::option::Option<unsafe extern "C" fn()>,
+ ) -> ::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::<snd_aes_iec958>(),
+ 176usize,
+ concat!("Size of: ", stringify!(snd_aes_iec958))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_aes_iec958>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(snd_aes_iec958))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_aes_iec958>())).status as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_aes_iec958),
+ "::",
+ stringify!(status)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_aes_iec958>())).subcode as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_aes_iec958),
+ "::",
+ stringify!(subcode)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_aes_iec958>())).pad as *const _ as usize },
+ 171usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_aes_iec958),
+ "::",
+ stringify!(pad)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_aes_iec958>())).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::<snd_cea_861_aud_if>(),
+ 5usize,
+ concat!("Size of: ", stringify!(snd_cea_861_aud_if))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_cea_861_aud_if>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(snd_cea_861_aud_if))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_cea_861_aud_if>())).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::<snd_cea_861_aud_if>())).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::<snd_cea_861_aud_if>())).db3 as *const _ as usize },
+ 2usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_cea_861_aud_if),
+ "::",
+ stringify!(db3)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_cea_861_aud_if>())).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::<snd_cea_861_aud_if>())).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::<snd_hwdep_info>(),
+ 220usize,
+ concat!("Size of: ", stringify!(snd_hwdep_info))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_hwdep_info>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_hwdep_info))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_info>())).device as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_info),
+ "::",
+ stringify!(device)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_info>())).card as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_info),
+ "::",
+ stringify!(card)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_info>())).id as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_info),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_info>())).name as *const _ as usize },
+ 72usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_info),
+ "::",
+ stringify!(name)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_info>())).iface as *const _ as usize },
+ 152usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_info),
+ "::",
+ stringify!(iface)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_info>())).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::<snd_hwdep_dsp_status>(),
+ 64usize,
+ concat!("Size of: ", stringify!(snd_hwdep_dsp_status))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_hwdep_dsp_status>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_hwdep_dsp_status))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_dsp_status>())).version as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_dsp_status),
+ "::",
+ stringify!(version)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_dsp_status>())).id as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_dsp_status),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_dsp_status>())).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::<snd_hwdep_dsp_status>())).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::<snd_hwdep_dsp_status>())).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::<snd_hwdep_dsp_status>())).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::<snd_hwdep_dsp_image>(),
+ 96usize,
+ concat!("Size of: ", stringify!(snd_hwdep_dsp_image))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_hwdep_dsp_image>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_hwdep_dsp_image))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_dsp_image>())).index as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_dsp_image),
+ "::",
+ stringify!(index)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_dsp_image>())).name as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_dsp_image),
+ "::",
+ stringify!(name)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_dsp_image>())).image as *const _ as usize },
+ 72usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_dsp_image),
+ "::",
+ stringify!(image)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_dsp_image>())).length as *const _ as usize },
+ 80usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_hwdep_dsp_image),
+ "::",
+ stringify!(length)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_hwdep_dsp_image>())).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::<snd_pcm_sync_id>(),
+ 16usize,
+ concat!("Size of: ", stringify!(snd_pcm_sync_id))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_sync_id>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_pcm_sync_id))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_sync_id>())).id as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_sync_id),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_sync_id>())).id16 as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_sync_id),
+ "::",
+ stringify!(id16)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_sync_id>())).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::<snd_pcm_info>(),
+ 288usize,
+ concat!("Size of: ", stringify!(snd_pcm_info))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_info>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_pcm_info))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).device as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(device)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).subdevice as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(subdevice)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).stream as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(stream)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).card as *const _ as usize },
+ 12usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(card)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).id as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).name as *const _ as usize },
+ 80usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(name)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).subname as *const _ as usize },
+ 160usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(subname)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).dev_class as *const _ as usize },
+ 192usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(dev_class)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).dev_subclass as *const _ as usize },
+ 196usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(dev_subclass)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).subdevices_count as *const _ as usize },
+ 200usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(subdevices_count)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).subdevices_avail as *const _ as usize },
+ 204usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(subdevices_avail)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).sync as *const _ as usize },
+ 208usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_info),
+ "::",
+ stringify!(sync)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_info>())).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::<snd_interval>(),
+ 12usize,
+ concat!("Size of: ", stringify!(snd_interval))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_interval>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_interval))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_interval>())).min as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_interval),
+ "::",
+ stringify!(min)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_interval>())).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::<snd_mask>(),
+ 32usize,
+ concat!("Size of: ", stringify!(snd_mask))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_mask>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_mask))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_mask>())).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::<snd_pcm_hw_params>(),
+ 608usize,
+ concat!("Size of: ", stringify!(snd_pcm_hw_params))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_hw_params>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_pcm_hw_params))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).flags as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_hw_params),
+ "::",
+ stringify!(flags)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).masks as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_hw_params),
+ "::",
+ stringify!(masks)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).mres as *const _ as usize },
+ 100usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_hw_params),
+ "::",
+ stringify!(mres)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).intervals as *const _ as usize },
+ 260usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_hw_params),
+ "::",
+ stringify!(intervals)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).ires as *const _ as usize },
+ 404usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_hw_params),
+ "::",
+ stringify!(ires)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).rmask as *const _ as usize },
+ 512usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_hw_params),
+ "::",
+ stringify!(rmask)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).cmask as *const _ as usize },
+ 516usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_hw_params),
+ "::",
+ stringify!(cmask)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).info as *const _ as usize },
+ 520usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_hw_params),
+ "::",
+ stringify!(info)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).msbits as *const _ as usize },
+ 524usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_hw_params),
+ "::",
+ stringify!(msbits)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_hw_params>())).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::<snd_pcm_hw_params>())).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::<snd_pcm_hw_params>())).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::<snd_pcm_hw_params>())).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::<snd_pcm_sw_params>(),
+ 136usize,
+ concat!("Size of: ", stringify!(snd_pcm_sw_params))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_sw_params>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_pcm_sw_params))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).boundary as *const _ as usize },
+ 64usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_sw_params),
+ "::",
+ stringify!(boundary)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_sw_params>())).proto as *const _ as usize },
+ 72usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_sw_params),
+ "::",
+ stringify!(proto)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_sw_params>())).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::<snd_pcm_sw_params>())).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::<snd_pcm_channel_info>(),
+ 24usize,
+ concat!("Size of: ", stringify!(snd_pcm_channel_info))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_channel_info>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_pcm_channel_info))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_channel_info>())).channel as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_channel_info),
+ "::",
+ stringify!(channel)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_channel_info>())).offset as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_channel_info),
+ "::",
+ stringify!(offset)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_channel_info>())).first as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_channel_info),
+ "::",
+ stringify!(first)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_channel_info>())).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::<snd_pcm_status>(),
+ 152usize,
+ concat!("Size of: ", stringify!(snd_pcm_status))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_status>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_pcm_status))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).state as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(state)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).trigger_tstamp as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(trigger_tstamp)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).tstamp as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(tstamp)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).appl_ptr as *const _ as usize },
+ 40usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(appl_ptr)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).hw_ptr as *const _ as usize },
+ 48usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(hw_ptr)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).delay as *const _ as usize },
+ 56usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(delay)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).avail as *const _ as usize },
+ 64usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(avail)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).avail_max as *const _ as usize },
+ 72usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(avail_max)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).overrange as *const _ as usize },
+ 80usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(overrange)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).suspended_state as *const _ as usize },
+ 88usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(suspended_state)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_pcm_status>())).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::<snd_pcm_status>())).audio_tstamp as *const _ as usize },
+ 96usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(audio_tstamp)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_status>())).driver_tstamp as *const _ as usize },
+ 112usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_status),
+ "::",
+ stringify!(driver_tstamp)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_pcm_status>())).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::<snd_pcm_status>())).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::<snd_pcm_mmap_status>(),
+ 56usize,
+ concat!("Size of: ", stringify!(snd_pcm_mmap_status))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_mmap_status>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_pcm_mmap_status))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_mmap_status>())).state as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_mmap_status),
+ "::",
+ stringify!(state)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_mmap_status>())).pad1 as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_mmap_status),
+ "::",
+ stringify!(pad1)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_mmap_status>())).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::<snd_pcm_mmap_status>())).tstamp as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_mmap_status),
+ "::",
+ stringify!(tstamp)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_pcm_mmap_status>())).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::<snd_pcm_mmap_status>())).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::<snd_pcm_mmap_control>(),
+ 16usize,
+ concat!("Size of: ", stringify!(snd_pcm_mmap_control))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_mmap_control>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_pcm_mmap_control))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_mmap_control>())).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::<snd_pcm_mmap_control>())).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::<snd_pcm_sync_ptr__bindgen_ty_1>(),
+ 64usize,
+ concat!("Size of: ", stringify!(snd_pcm_sync_ptr__bindgen_ty_1))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_sync_ptr__bindgen_ty_1>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_pcm_sync_ptr__bindgen_ty_1))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_pcm_sync_ptr__bindgen_ty_1>())).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::<snd_pcm_sync_ptr__bindgen_ty_1>())).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::<snd_pcm_sync_ptr__bindgen_ty_2>(),
+ 64usize,
+ concat!("Size of: ", stringify!(snd_pcm_sync_ptr__bindgen_ty_2))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_sync_ptr__bindgen_ty_2>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_pcm_sync_ptr__bindgen_ty_2))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_pcm_sync_ptr__bindgen_ty_2>())).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::<snd_pcm_sync_ptr__bindgen_ty_2>())).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::<snd_pcm_sync_ptr>(),
+ 136usize,
+ concat!("Size of: ", stringify!(snd_pcm_sync_ptr))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_pcm_sync_ptr>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_pcm_sync_ptr))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_sync_ptr>())).flags as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_sync_ptr),
+ "::",
+ stringify!(flags)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_sync_ptr>())).s as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_pcm_sync_ptr),
+ "::",
+ stringify!(s)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_pcm_sync_ptr>())).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::<snd_xferi>(),
+ 24usize,
+ concat!("Size of: ", stringify!(snd_xferi))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_xferi>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_xferi))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_xferi>())).result as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_xferi),
+ "::",
+ stringify!(result)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_xferi>())).buf as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_xferi),
+ "::",
+ stringify!(buf)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_xferi>())).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::<snd_xfern>(),
+ 24usize,
+ concat!("Size of: ", stringify!(snd_xfern))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_xfern>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_xfern))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_xfern>())).result as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_xfern),
+ "::",
+ stringify!(result)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_xfern>())).bufs as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_xfern),
+ "::",
+ stringify!(bufs)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_xfern>())).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::<snd_rawmidi_info>(),
+ 268usize,
+ concat!("Size of: ", stringify!(snd_rawmidi_info))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_rawmidi_info>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_rawmidi_info))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_info>())).device as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(device)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_info>())).subdevice as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(subdevice)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_info>())).stream as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(stream)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_info>())).card as *const _ as usize },
+ 12usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(card)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_info>())).flags as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(flags)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_info>())).id as *const _ as usize },
+ 20usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_info>())).name as *const _ as usize },
+ 84usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(name)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_info>())).subname as *const _ as usize },
+ 164usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(subname)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_rawmidi_info>())).subdevices_count as *const _ as usize
+ },
+ 196usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(subdevices_count)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_rawmidi_info>())).subdevices_avail as *const _ as usize
+ },
+ 200usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_info),
+ "::",
+ stringify!(subdevices_avail)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_info>())).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::<snd_rawmidi_params>(),
+ 48usize,
+ concat!("Size of: ", stringify!(snd_rawmidi_params))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_rawmidi_params>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_rawmidi_params))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_params>())).stream as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_params),
+ "::",
+ stringify!(stream)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_params>())).buffer_size as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_params),
+ "::",
+ stringify!(buffer_size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_params>())).avail_min as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_params),
+ "::",
+ stringify!(avail_min)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_params>())).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::<snd_rawmidi_status>(),
+ 56usize,
+ concat!("Size of: ", stringify!(snd_rawmidi_status))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_rawmidi_status>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_rawmidi_status))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_status>())).stream as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_status),
+ "::",
+ stringify!(stream)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_status>())).tstamp as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_status),
+ "::",
+ stringify!(tstamp)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_status>())).avail as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_status),
+ "::",
+ stringify!(avail)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_status>())).xruns as *const _ as usize },
+ 32usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_rawmidi_status),
+ "::",
+ stringify!(xruns)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_rawmidi_status>())).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::<snd_timer_id>(),
+ 20usize,
+ concat!("Size of: ", stringify!(snd_timer_id))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_id>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_timer_id))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_id>())).dev_class as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_id),
+ "::",
+ stringify!(dev_class)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_id>())).dev_sclass as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_id),
+ "::",
+ stringify!(dev_sclass)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_id>())).card as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_id),
+ "::",
+ stringify!(card)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_id>())).device as *const _ as usize },
+ 12usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_id),
+ "::",
+ stringify!(device)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_id>())).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::<snd_timer_ginfo>(),
+ 248usize,
+ concat!("Size of: ", stringify!(snd_timer_ginfo))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_ginfo>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_timer_ginfo))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).tid as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(tid)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).flags as *const _ as usize },
+ 20usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(flags)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).card as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(card)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).id as *const _ as usize },
+ 28usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).name as *const _ as usize },
+ 92usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(name)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).reserved0 as *const _ as usize },
+ 176usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(reserved0)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).resolution as *const _ as usize },
+ 184usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(resolution)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).resolution_min as *const _ as usize },
+ 192usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(resolution_min)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).resolution_max as *const _ as usize },
+ 200usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(resolution_max)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).clients as *const _ as usize },
+ 208usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_ginfo),
+ "::",
+ stringify!(clients)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_ginfo>())).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::<snd_timer_gparams>(),
+ 72usize,
+ concat!("Size of: ", stringify!(snd_timer_gparams))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_gparams>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_timer_gparams))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_gparams>())).tid as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_gparams),
+ "::",
+ stringify!(tid)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_gparams>())).period_num as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_gparams),
+ "::",
+ stringify!(period_num)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_gparams>())).period_den as *const _ as usize },
+ 32usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_gparams),
+ "::",
+ stringify!(period_den)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_gparams>())).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::<snd_timer_gstatus>(),
+ 80usize,
+ concat!("Size of: ", stringify!(snd_timer_gstatus))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_gstatus>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_timer_gstatus))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_gstatus>())).tid as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_gstatus),
+ "::",
+ stringify!(tid)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_gstatus>())).resolution as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_gstatus),
+ "::",
+ stringify!(resolution)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_timer_gstatus>())).resolution_num as *const _ as usize
+ },
+ 32usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_gstatus),
+ "::",
+ stringify!(resolution_num)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_timer_gstatus>())).resolution_den as *const _ as usize
+ },
+ 40usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_gstatus),
+ "::",
+ stringify!(resolution_den)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_gstatus>())).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::<snd_timer_select>(),
+ 52usize,
+ concat!("Size of: ", stringify!(snd_timer_select))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_select>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_timer_select))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_select>())).id as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_select),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_select>())).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::<snd_timer_info>(),
+ 232usize,
+ concat!("Size of: ", stringify!(snd_timer_info))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_info>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_timer_info))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_info>())).flags as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_info),
+ "::",
+ stringify!(flags)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_info>())).card as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_info),
+ "::",
+ stringify!(card)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_info>())).id as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_info),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_info>())).name as *const _ as usize },
+ 72usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_info),
+ "::",
+ stringify!(name)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_info>())).reserved0 as *const _ as usize },
+ 152usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_info),
+ "::",
+ stringify!(reserved0)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_info>())).resolution as *const _ as usize },
+ 160usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_info),
+ "::",
+ stringify!(resolution)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_info>())).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::<snd_timer_params>(),
+ 80usize,
+ concat!("Size of: ", stringify!(snd_timer_params))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_params>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_timer_params))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_params>())).flags as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_params),
+ "::",
+ stringify!(flags)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_params>())).ticks as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_params),
+ "::",
+ stringify!(ticks)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_params>())).queue_size as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_params),
+ "::",
+ stringify!(queue_size)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_params>())).reserved0 as *const _ as usize },
+ 12usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_params),
+ "::",
+ stringify!(reserved0)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_params>())).filter as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_params),
+ "::",
+ stringify!(filter)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_params>())).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::<snd_timer_status>(),
+ 96usize,
+ concat!("Size of: ", stringify!(snd_timer_status))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_status>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_timer_status))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_status>())).tstamp as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_status),
+ "::",
+ stringify!(tstamp)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_status>())).resolution as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_status),
+ "::",
+ stringify!(resolution)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_status>())).lost as *const _ as usize },
+ 20usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_status),
+ "::",
+ stringify!(lost)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_status>())).overrun as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_status),
+ "::",
+ stringify!(overrun)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_status>())).queue as *const _ as usize },
+ 28usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_status),
+ "::",
+ stringify!(queue)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_status>())).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::<snd_timer_read>(),
+ 8usize,
+ concat!("Size of: ", stringify!(snd_timer_read))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_read>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_timer_read))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_read>())).resolution as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_read),
+ "::",
+ stringify!(resolution)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_read>())).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::<snd_timer_tread>(),
+ 32usize,
+ concat!("Size of: ", stringify!(snd_timer_tread))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_timer_tread>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_timer_tread))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_tread>())).event as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_tread),
+ "::",
+ stringify!(event)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_tread>())).tstamp as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_timer_tread),
+ "::",
+ stringify!(tstamp)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_timer_tread>())).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::<snd_ctl_card_info>(),
+ 376usize,
+ concat!("Size of: ", stringify!(snd_ctl_card_info))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_card_info>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_ctl_card_info))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_card_info>())).card as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_card_info),
+ "::",
+ stringify!(card)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_card_info>())).pad as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_card_info),
+ "::",
+ stringify!(pad)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_card_info>())).id as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_card_info),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_card_info>())).driver as *const _ as usize },
+ 24usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_card_info),
+ "::",
+ stringify!(driver)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_card_info>())).name as *const _ as usize },
+ 40usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_card_info),
+ "::",
+ stringify!(name)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_card_info>())).longname as *const _ as usize },
+ 72usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_card_info),
+ "::",
+ stringify!(longname)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_card_info>())).reserved_ as *const _ as usize },
+ 152usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_card_info),
+ "::",
+ stringify!(reserved_)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_card_info>())).mixername as *const _ as usize },
+ 168usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_card_info),
+ "::",
+ stringify!(mixername)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_card_info>())).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::<snd_ctl_elem_id>(),
+ 64usize,
+ concat!("Size of: ", stringify!(snd_ctl_elem_id))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_id>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_ctl_elem_id))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_id>())).numid as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_id),
+ "::",
+ stringify!(numid)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_id>())).iface as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_id),
+ "::",
+ stringify!(iface)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_id>())).device as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_id),
+ "::",
+ stringify!(device)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_id>())).subdevice as *const _ as usize },
+ 12usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_id),
+ "::",
+ stringify!(subdevice)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_id>())).name as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_id),
+ "::",
+ stringify!(name)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_id>())).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::<snd_ctl_elem_list>(),
+ 80usize,
+ concat!("Size of: ", stringify!(snd_ctl_elem_list))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_list>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_ctl_elem_list))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_list>())).offset as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_list),
+ "::",
+ stringify!(offset)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_list>())).space as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_list),
+ "::",
+ stringify!(space)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_list>())).used as *const _ as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_list),
+ "::",
+ stringify!(used)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_list>())).count as *const _ as usize },
+ 12usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_list),
+ "::",
+ stringify!(count)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_list>())).pids as *const _ as usize },
+ 16usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_list),
+ "::",
+ stringify!(pids)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_list>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1>(),
+ 24usize,
+ concat!(
+ "Size of: ",
+ stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1)
+ )
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1>(),
+ 8usize,
+ concat!(
+ "Alignment of ",
+ stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_1>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2>(),
+ 24usize,
+ concat!(
+ "Size of: ",
+ stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2)
+ )
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2>(),
+ 8usize,
+ concat!(
+ "Alignment of ",
+ stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_2>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3>(),
+ 88usize,
+ concat!(
+ "Size of: ",
+ stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3)
+ )
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3>(),
+ 8usize,
+ concat!(
+ "Alignment of ",
+ stringify!(snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3>())).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::<snd_ctl_elem_info__bindgen_ty_1__bindgen_ty_3>())).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::<snd_ctl_elem_info__bindgen_ty_1>(),
+ 128usize,
+ concat!("Size of: ", stringify!(snd_ctl_elem_info__bindgen_ty_1))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_info__bindgen_ty_1>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_ctl_elem_info__bindgen_ty_1))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_info__bindgen_ty_1>())).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::<snd_ctl_elem_info__bindgen_ty_1>())).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::<snd_ctl_elem_info__bindgen_ty_1>())).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::<snd_ctl_elem_info__bindgen_ty_1>())).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::<snd_ctl_elem_info__bindgen_ty_2>(),
+ 8usize,
+ concat!("Size of: ", stringify!(snd_ctl_elem_info__bindgen_ty_2))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_info__bindgen_ty_2>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_ctl_elem_info__bindgen_ty_2))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_info__bindgen_ty_2>())).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::<snd_ctl_elem_info__bindgen_ty_2>())).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::<snd_ctl_elem_info>(),
+ 272usize,
+ concat!("Size of: ", stringify!(snd_ctl_elem_info))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_info>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_ctl_elem_info))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_info>())).id as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_info),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_info>())).type_ as *const _ as usize },
+ 64usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_info),
+ "::",
+ stringify!(type_)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_info>())).access as *const _ as usize },
+ 68usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_info),
+ "::",
+ stringify!(access)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_info>())).count as *const _ as usize },
+ 72usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_info),
+ "::",
+ stringify!(count)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_info>())).owner as *const _ as usize },
+ 76usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_info),
+ "::",
+ stringify!(owner)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_info>())).value as *const _ as usize },
+ 80usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_info),
+ "::",
+ stringify!(value)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_info>())).dimen as *const _ as usize },
+ 208usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_info),
+ "::",
+ stringify!(dimen)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_info>())).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::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1>(),
+ 1024usize,
+ concat!(
+ "Size of: ",
+ stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1)
+ )
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1>(),
+ 8usize,
+ concat!(
+ "Alignment of ",
+ stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1>())).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::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_1>())).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::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2>(),
+ 512usize,
+ concat!(
+ "Size of: ",
+ stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2)
+ )
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2>(),
+ 8usize,
+ concat!(
+ "Alignment of ",
+ stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2>())).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::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_2>())).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::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3>(),
+ 512usize,
+ concat!(
+ "Size of: ",
+ stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3)
+ )
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3>(),
+ 8usize,
+ concat!(
+ "Alignment of ",
+ stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3>())).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::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_3>())).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::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4>(),
+ 512usize,
+ concat!(
+ "Size of: ",
+ stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4)
+ )
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4>(),
+ 8usize,
+ concat!(
+ "Alignment of ",
+ stringify!(snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4>())).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::<snd_ctl_elem_value__bindgen_ty_1__bindgen_ty_4>())).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::<snd_ctl_elem_value__bindgen_ty_1>(),
+ 1024usize,
+ concat!("Size of: ", stringify!(snd_ctl_elem_value__bindgen_ty_1))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_value__bindgen_ty_1>(),
+ 8usize,
+ concat!(
+ "Alignment of ",
+ stringify!(snd_ctl_elem_value__bindgen_ty_1)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_elem_value__bindgen_ty_1>())).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::<snd_ctl_elem_value__bindgen_ty_1>())).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::<snd_ctl_elem_value__bindgen_ty_1>())).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::<snd_ctl_elem_value__bindgen_ty_1>())).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::<snd_ctl_elem_value__bindgen_ty_1>())).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::<snd_ctl_elem_value>(),
+ 1224usize,
+ concat!("Size of: ", stringify!(snd_ctl_elem_value))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_elem_value>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(snd_ctl_elem_value))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_value>())).id as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_value),
+ "::",
+ stringify!(id)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_value>())).value as *const _ as usize },
+ 72usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_value),
+ "::",
+ stringify!(value)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_value>())).tstamp as *const _ as usize },
+ 1096usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_elem_value),
+ "::",
+ stringify!(tstamp)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_elem_value>())).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::<snd_ctl_tlv>(),
+ 8usize,
+ concat!("Size of: ", stringify!(snd_ctl_tlv))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_tlv>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_ctl_tlv))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_tlv>())).numid as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_tlv),
+ "::",
+ stringify!(numid)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_tlv>())).length as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_tlv),
+ "::",
+ stringify!(length)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_tlv>())).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::<snd_ctl_event__bindgen_ty_1__bindgen_ty_1>(),
+ 68usize,
+ concat!(
+ "Size of: ",
+ stringify!(snd_ctl_event__bindgen_ty_1__bindgen_ty_1)
+ )
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_event__bindgen_ty_1__bindgen_ty_1>(),
+ 4usize,
+ concat!(
+ "Alignment of ",
+ stringify!(snd_ctl_event__bindgen_ty_1__bindgen_ty_1)
+ )
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_event__bindgen_ty_1__bindgen_ty_1>())).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::<snd_ctl_event__bindgen_ty_1__bindgen_ty_1>())).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::<snd_ctl_event__bindgen_ty_1>(),
+ 68usize,
+ concat!("Size of: ", stringify!(snd_ctl_event__bindgen_ty_1))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_event__bindgen_ty_1>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_ctl_event__bindgen_ty_1))
+ );
+ assert_eq!(
+ unsafe {
+ &(*(::std::ptr::null::<snd_ctl_event__bindgen_ty_1>())).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::<snd_ctl_event__bindgen_ty_1>())).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::<snd_ctl_event>(),
+ 72usize,
+ concat!("Size of: ", stringify!(snd_ctl_event))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<snd_ctl_event>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(snd_ctl_event))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_event>())).type_ as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_event),
+ "::",
+ stringify!(type_)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<snd_ctl_event>())).data as *const _ as usize },
+ 4usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(snd_ctl_event),
+ "::",
+ stringify!(data)
+ )
+ );
+}
diff --git a/third_party/rust/alsa/src/direct/ffi.rs b/third_party/rust/alsa/src/direct/ffi.rs
new file mode 100644
index 0000000000..5e9738c68e
--- /dev/null
+++ b/third_party/rust/alsa/src/direct/ffi.rs
@@ -0,0 +1,79 @@
+
+// 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/third_party/rust/alsa/src/direct/pcm.rs b/third_party/rust/alsa/src/direct/pcm.rs
new file mode 100644
index 0000000000..ccea666145
--- /dev/null
+++ b/third_party/rust/alsa/src/direct/pcm.rs
@@ -0,0 +1,630 @@
+/*!
+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<pcm::Frames>, avail_min: Option<pcm::Frames>) -> Result<Self> {
+ 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<snd_pcm_mmap_status>);
+
+fn pcm_to_fd(p: &pcm::PCM) -> Result<RawFd> {
+ 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<Self> { Status::from_fd(pcm_to_fd(p)?) }
+
+ pub fn from_fd(fd: RawFd) -> Result<Self> {
+ 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<snd_pcm_mmap_control>);
+
+impl Control {
+ pub fn new(p: &pcm::PCM) -> Result<Self> { Self::from_fd(pcm_to_fd(p)?) }
+
+ pub fn from_fd(fd: RawFd) -> Result<Self> {
+ 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<S> {
+ ptr: *mut S,
+ size: libc::size_t,
+}
+
+impl<S> fmt::Debug for DriverMemory<S> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "DriverMemory({:?})", self.ptr) }
+}
+
+impl<S> DriverMemory<S> {
+ fn new(fd: RawFd, count: usize, offs: libc::off_t, writable: bool) -> Result<Self> {
+ let mut total = count * mem::size_of::<S>();
+ 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<S> Send for DriverMemory<S> {}
+unsafe impl<S> Sync for DriverMemory<S> {}
+
+impl<S> Drop for DriverMemory<S> {
+ fn drop(&mut self) {
+ unsafe {{ libc::munmap(self.ptr as *mut libc::c_void, self.size); } }
+ }
+}
+
+#[derive(Debug)]
+struct SampleData<S> {
+ mem: DriverMemory<S>,
+ frames: pcm::Frames,
+ channels: u32,
+}
+
+impl<S> SampleData<S> {
+ pub fn new(p: &pcm::PCM) -> Result<Self> {
+ 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::<S>() 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<S> = MmapIO<S, Playback>;
+
+pub type MmapCapture<S> = MmapIO<S, Capture>;
+
+#[derive(Debug)]
+/// Struct containing direct I/O functions shared between playback and capture.
+pub struct MmapIO<S, D> {
+ data: SampleData<S>,
+ 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<S> {
+ pub ptr: *mut S,
+ pub frames: Frames,
+ pub channels: u32,
+}
+
+impl<S> RawSamples<S> {
+ #[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<I: Iterator<Item=S>>(&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<S, D: MmapDir> MmapIO<S, D> {
+ fn new(p: &pcm::PCM) -> Result<Self> {
+ 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<S, D: MmapDir>(p: &pcm::PCM) -> Result<MmapIO<S, D>> { MmapIO::new(p) }
+
+impl<S, D: MmapDir> MmapIO<S, D> {
+ /// 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<S>, Option<RawSamples<S>>) {
+ 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<S> MmapPlayback<S> {
+ /// Write samples to the kernel ringbuffer.
+ pub fn write<I: Iterator<Item=S>>(&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<S> MmapCapture<S> {
+ /// 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<S> {
+ 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<S>,
+ samples: RawSamples<S>,
+ p_offs: isize,
+ read_samples: isize,
+ next_p: Option<RawSamples<S>>,
+}
+
+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<Self::Item> {
+ 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::<i16>().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<i16> = 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::<i16>().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/third_party/rust/alsa/src/error.rs b/third_party/rust/alsa/src/error.rs
new file mode 100644
index 0000000000..02debb8a52
--- /dev/null
+++ b/third_party/rust/alsa/src/error.rs
@@ -0,0 +1,100 @@
+#![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<T> = ::std::result::Result<T, Error>;
+
+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<String> {
+ 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<c_int> {
+ 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<Error> 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/third_party/rust/alsa/src/hctl.rs b/third_party/rust/alsa/src/hctl.rs
new file mode 100644
index 0000000000..b6f5aad2ef
--- /dev/null
+++ b/third_party/rust/alsa/src/hctl.rs
@@ -0,0 +1,162 @@
+//! 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<HCtl> {
+ 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<HCtl> {
+ 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<Elem> {
+ 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<u32> {
+ acheck!(snd_hctl_handle_events(self.0)).map(|x| x as u32)
+ }
+
+ pub fn wait(&self, timeout_ms: Option<u32>) -> Result<bool> {
+ 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<usize> {
+ 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<poll::Flags> {
+ 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<Elem<'a>> {
+ 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<ctl_int::ElemId> {
+ 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<ctl_int::ElemInfo> {
+ 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<ctl_int::ElemValue> {
+ 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<bool> {
+ 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/third_party/rust/alsa/src/io.rs b/third_party/rust/alsa/src/io.rs
new file mode 100644
index 0000000000..f6c3739ec2
--- /dev/null
+++ b/third_party/rust/alsa/src/io.rs
@@ -0,0 +1,49 @@
+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<Output> {
+ let mut q = ptr::null_mut();
+ acheck!(snd_output_buffer_open(&mut q)).map(|_| Output(q))
+ }
+
+ pub fn buffer_string<T, F: FnOnce(&[u8]) -> 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/third_party/rust/alsa/src/lib.rs b/third_party/rust/alsa/src/lib.rs
new file mode 100644
index 0000000000..ce83ec4b11
--- /dev/null
+++ b/third_party/rust/alsa/src/lib.rs
@@ -0,0 +1,140 @@
+//! 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/third_party/rust/alsa/src/mixer.rs b/third_party/rust/alsa/src/mixer.rs
new file mode 100644
index 0000000000..d925f09d36
--- /dev/null
+++ b/third_party/rust/alsa/src/mixer.rs
@@ -0,0 +1,639 @@
+//! 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<Mixer> {
+ 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<Selem> {
+ 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<Mixer> {
+ 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<u32> {
+ acheck!(snd_mixer_handle_events(self.0)).map(|x| x as u32)
+ }
+
+ pub fn wait(&self, timeout_ms: Option<u32>) -> Result<bool> {
+ 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<usize> {
+ 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<poll::Flags> {
+ 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<Elem<'a>> {
+ 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<Selem<'a>> {
+ 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<i64> {
+ 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<MilliBel> {
+ 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<MilliBel> {
+ 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<i64> {
+ 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<MilliBel> {
+ 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<MilliBel> {
+ 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<i32> {
+ 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<i32> {
+ 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<u32> {
+ acheck!(snd_mixer_selem_get_enum_items(self.handle)).map(|v| v as u32)
+ }
+
+ pub fn get_enum_item_name(&self, idx: u32) -> Result<String> {
+ 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<IterEnum> {
+ Ok(IterEnum(self, 0, self.get_enum_items()?))
+ }
+
+ pub fn get_enum_item(&self, channel: SelemChannelId) -> Result<u32> {
+ 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<String>;
+ fn next(&mut self) -> Option<Self::Item> {
+ 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/third_party/rust/alsa/src/pcm.rs b/third_party/rust/alsa/src/pcm.rs
new file mode 100644
index 0000000000..b25a1d9b4d
--- /dev/null
+++ b/third_party/rust/alsa/src/pcm.rs
@@ -0,0 +1,1151 @@
+//! 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<Info> {
+ 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<bool>);
+
+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<PCM> {
+ 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<PCM> {
+ 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<u32>) -> Result<bool> {
+ 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<Frames> { acheck!(snd_pcm_avail_update(self.0)) }
+ pub fn avail(&self) -> Result<Frames> { 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<Frames> {
+ let mut d = 0;
+ acheck!(snd_pcm_delay(self.0, &mut d)).map(|_| d)
+ }
+
+ pub fn status(&self) -> Result<Status> {
+ 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<IO<i8>> { self.io_checked() }
+ pub fn io_u8(&self) -> Result<IO<u8>> { self.io_checked() }
+ pub fn io_i16(&self) -> Result<IO<i16>> { self.io_checked() }
+ pub fn io_u16(&self) -> Result<IO<u16>> { self.io_checked() }
+ pub fn io_i32(&self) -> Result<IO<i32>> { self.io_checked() }
+ pub fn io_u32(&self) -> Result<IO<u32>> { self.io_checked() }
+ pub fn io_f32(&self) -> Result<IO<f32>> { self.io_checked() }
+ pub fn io_f64(&self) -> Result<IO<f64>> { self.io_checked() }
+
+ pub fn io_checked<S: IoFormat>(&self) -> Result<IO<S>> {
+ self.verify_format(S::FORMAT).map(|_| IO::new(self))
+ }
+
+ #[deprecated(note = "renamed to io_bytes")]
+ pub fn io(&self) -> IO<u8> { IO::new(self) }
+ pub fn io_bytes(&self) -> IO<u8> { IO::new(self) }
+
+ /// Read buffers by talking to the kernel directly, bypassing alsa-lib.
+ pub fn direct_mmap_capture<S>(&self) -> Result<crate::direct::pcm::MmapCapture<S>> {
+ 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<S>(&self) -> Result<crate::direct::pcm::MmapPlayback<S>> {
+ 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> {
+ 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> {
+ 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> {
+ 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<Chmap> {
+ 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<usize> {
+ 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<poll::Flags> {
+ 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<S>);
+
+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::<S>()) 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::<S>()
+ }
+
+ /// 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<usize> {
+ 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<usize> {
+ 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<F: FnOnce(&mut [S]) -> usize>(&self, frames: usize, func: F) -> Result<usize> {
+ 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<usize> {
+ 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<usize> {
+ 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 { <i16 as IoFormat>::FORMAT }
+ pub const fn u16() -> Format { <u16 as IoFormat>::FORMAT }
+ pub const fn s32() -> Format { <i32 as IoFormat>::FORMAT }
+ pub const fn u32() -> Format { <u32 as IoFormat>::FORMAT }
+ pub const fn float() -> Format { <f32 as IoFormat>::FORMAT }
+ pub const fn float64() -> Format { <f64 as IoFormat>::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<HwParams<'a>> {
+ 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<'a>> { 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<bool> {
+ 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<u32> {
+ 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<u32> {
+ 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<u32> {
+ 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<u32> {
+ 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<u32> {
+ 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<u32> {
+ 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<u32> {
+ 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<u32> {
+ 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<Format> {
+ 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<Access> {
+ 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<Frames> {
+ 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<u32> {
+ 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<Frames> {
+ 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<Frames> {
+ 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<Frames> {
+ 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<u32> {
+ 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<Frames> {
+ 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<Frames> {
+ 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<Frames> {
+ 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<u32> {
+ 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<Frames> {
+ 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<Frames> {
+ 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<Frames> {
+ 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<u32> {
+ 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<u32> {
+ 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<SwParams<'a>> {
+ 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<Frames> {
+ 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<Frames> {
+ 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<Frames> {
+ 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<Frames> {
+ 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<bool> {
+ 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<TstampType> {
+ 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<Status> {
+ 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/third_party/rust/alsa/src/poll.rs b/third_party/rust/alsa/src/poll.rs
new file mode 100644
index 0000000000..3e9191164e
--- /dev/null
+++ b/third_party/rust/alsa/src/poll.rs
@@ -0,0 +1,68 @@
+//! 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<usize>;
+ fn revents(&self, _: &[pollfd]) -> Result<Flags>;
+
+ /// Wrapper around count and fill - returns an array of pollfds
+ fn get(&self) -> Result<Vec<pollfd>> {
+ 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<usize> { a[0] = *self; Ok(1) }
+ fn revents(&self, a: &[pollfd]) -> Result<Flags> { Ok(Flags::from_bits_truncate(a[0].revents)) }
+}
+
+/// Wrapper around the libc poll call.
+pub fn poll(fds: &mut[pollfd], timeout: i32) -> Result<usize> {
+ 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<Vec<(&'a dyn Descriptors, Flags)>> {
+
+ let mut pollfds: Vec<pollfd> = 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/third_party/rust/alsa/src/rawmidi.rs b/third_party/rust/alsa/src/rawmidi.rs
new file mode 100644
index 0000000000..50ef9ccb3b
--- /dev/null
+++ b/third_party/rust/alsa/src/rawmidi.rs
@@ -0,0 +1,211 @@
+//! 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<Info> {
+ 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<Info> {
+ 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<String> {
+ 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<String> {
+ 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<Self> {
+ 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<Info>;
+ fn next(&mut self) -> Option<Result<Info>> {
+ 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> {
+ Self::open(&CString::new(name).unwrap(), dir, nonblock)
+ }
+
+ pub fn open(name: &CStr, dir: Direction, nonblock: bool) -> Result<Rawmidi> {
+ 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> {
+ Info::new().and_then(|i| acheck!(snd_rawmidi_info(self.0, i.0)).map(|_| i))
+ }
+
+ pub fn status(&self) -> Result<Status> {
+ 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<String> {
+ 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<usize> {
+ 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<poll::Flags> {
+ 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<usize> {
+ 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<usize> {
+ 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/third_party/rust/alsa/src/seq.rs b/third_party/rust/alsa/src/seq.rs
new file mode 100644
index 0000000000..bb1e46dfa5
--- /dev/null
+++ b/third_party/rust/alsa/src/seq.rs
@@ -0,0 +1,1567 @@
+//! 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<bool>);
+
+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<Direction>, nonblock: bool) -> Result<Seq> {
+ 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<i32> {
+ acheck!(snd_seq_client_id(self.0)).map(|q| q as i32)
+ }
+
+ pub fn drain_output(&self) -> Result<i32> {
+ acheck!(snd_seq_drain_output(self.0)).map(|q| q as i32)
+ }
+
+ pub fn get_any_client_info(&self, client: i32) -> Result<ClientInfo> {
+ 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<PortInfo> {
+ 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<i32> {
+ 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::<i32>::has_data(t) || EvQueueControl::<u32>::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<u32> {
+ 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<u32> {
+ 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<u32> {
+ 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<QueueTempo> {
+ 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<QueueStatus> {
+ 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<i32> { acheck!(snd_seq_alloc_queue(self.0)).map(|q| q as i32) }
+ pub fn alloc_named_queue(&self, n: &CStr) -> Result<i32> {
+ 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<Event> {
+ // 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<u32> {
+ 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<Direction>) -> 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<Direction>) {
+
+ 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<usize> {
+ 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<poll::Flags> {
+ 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<Self> {
+ 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<Self::Item> {
+ 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<Self> {
+ 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<Self> {
+ 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<Self::Item> {
+ 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<dyn std::error::Error>;
+
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
+ let mut split: Split<'_, char> = s.trim().split(':');
+ let client = split.next()
+ .ok_or("no client provided")?
+ .parse::<i32>()?;
+ let port = split.next()
+ .ok_or("no port provided")?
+ .parse::<i32>()?;
+ 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<Self> {
+ 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<Self> {
+ 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<Self> {
+ 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<Self::Item> {
+ 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<Cow<'a, [u8]>>);
+
+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<D: EventData>(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<D: Into<Cow<'a, [u8]>>>(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<Event<'any>> {
+ 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<D: EventData>(&self) -> Option<D> { 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<time::Duration> {
+ 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<u32> {
+ 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::<EvNote>() { x.field(&z); }
+ if let Some(z) = self.get_data::<EvCtrl>() { x.field(&z); }
+ if let Some(z) = self.get_data::<Addr>() { x.field(&z); }
+ if let Some(z) = self.get_data::<Connect>() { x.field(&z); }
+ if let Some(z) = self.get_data::<EvQueueControl<()>>() { x.field(&z); }
+ if let Some(z) = self.get_data::<EvQueueControl<i32>>() { x.field(&z); }
+ if let Some(z) = self.get_data::<EvQueueControl<u32>>() { x.field(&z); }
+ if let Some(z) = self.get_data::<EvQueueControl<time::Duration>>() { x.field(&z); }
+ if let Some(z) = self.get_data::<EvResult>() { 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<T> {
+ 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<i32> {
+ 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<u32> {
+ 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<time::Duration> {
+ 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<Self> {
+ 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<Self> {
+ 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<Self> {
+ 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<Self> {
+ 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<Self> {
+ 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<EventType> { 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<MidiEvent> {
+ 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<usize> {
+ 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<Event<'a>>)> {
+ // 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, &note);
+ 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::<u32>::has_data(v) { i += 1; }
+ if EvQueueControl::<i32>::has_data(v) { i += 1; }
+ if EvQueueControl::<time::Duration>::has_data(v) { i += 1; }
+ if i != 1 { panic!("{:?}: {} has_data", v, i) }
+ }
+}
+
+#[test]
+fn seq_remove_events() -> std::result::Result<(), Box<dyn std::error::Error>> {
+ 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<PortSubscribe> = 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<PortSubscribe> = 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<PortSubscribe> = 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());
+}