1 //! Thin but safe wrappers for [ALSA](http://http://alsa-project.org).
2 //!
3 //! [Github repo](https://github.com/diwic/alsa-rs)
4 //!
5 //! [Crates.io](https://crates.io/crates/alsa)
6 //!
7 //! This ALSA API wrapper/binding is WIP - the ALSA API is huge, and new
8 //! functions and structs might be added as requested.
9 //!
10 //! Most functions map 1-to-1 to alsa-lib functions, e g, `ctl::CardInfo::get_id()` is a wrapper around
11 //! `snd_ctl_card_info_get_id` and the [alsa-lib documentation](http://www.alsa-project.org/alsa-doc/alsa-lib/)
12 //! can be consulted for additional information.
13 //!
14 //! Enjoy!
15 
16 extern crate alsa_sys as alsa;
17 extern crate libc;
18 #[macro_use]
19 extern crate bitflags;
20 #[macro_use]
21 extern crate nix;
22 
23 macro_rules! alsa_enum {
24  ($(#[$attr:meta])+ $name:ident, $static_name:ident [$count:expr], $( $a:ident = $b:ident),* ,) =>
25 {
26 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
27 $(#[$attr])*
28 pub enum $name {
29 $(
30     $a = alsa::$b as isize,
31 )*
32 }
33 
34 static $static_name: [$name; $count] =
35   [ $( $name::$a, )* ];
36 
37 impl $name {
38     /// Returns a slice of all possible values; useful for iteration
39     pub fn all() -> &'static [$name] { &$static_name[..] }
40 
41     #[allow(dead_code)]
42     fn from_c_int(c: ::libc::c_int, s: &'static str) -> Result<$name> {
43         Self::all().iter().find(|&&x| c == x as ::libc::c_int).map(|&x| x)
44             .ok_or_else(|| Error::unsupported(s))
45     }
46 }
47 
48 }
49 }
50 
51 /// Replaces constants ending with PLAYBACK/CAPTURE as well as
52 /// INPUT/OUTPUT
53 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
54 pub enum Direction {
55     Playback,
56     Capture
57 }
58 impl Direction {
59     #[inline]
60     pub fn input() -> Direction { Direction::Capture }
61     #[inline]
62     pub fn output() -> Direction { Direction::Playback }
63 }
64 
65 /// Used to restrict hw parameters. In case the submitted
66 /// value is unavailable, in which direction should one search
67 /// for available values?
68 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
69 pub enum ValueOr {
70     /// The value set is the submitted value, or less
71     Less = -1,
72     /// The value set is the submitted value, or the nearest
73     Nearest = 0,
74     /// The value set is the submitted value, or greater
75     Greater = 1,
76 }
77 
78 /// Rounding mode (used in some mixer related calls)
79 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
80 pub enum Round {
81     /// Round down (towards negative infinity)
82     Floor = 0,
83     /// Round up (towards positive infinity)
84     Ceil = 1,
85 }
86 
87 mod error;
88 pub use error::{Error, Result};
89 
90 pub mod card;
91 pub use card::Card as Card;
92 
93 mod ctl_int;
94 pub mod ctl {
95     //! Control device API
96     pub use super::ctl_int::{Ctl, CardInfo, ElemIface, ElemId, ElemType, ElemValue, ElemInfo};
97 }
98 
99 pub use ctl::Ctl as Ctl;
100 
101 pub mod hctl;
102 pub use hctl::HCtl as HCtl;
103 
104 pub mod pcm;
105 pub use pcm::PCM as PCM;
106 
107 pub mod rawmidi;
108 pub use rawmidi::Rawmidi as Rawmidi;
109 
110 pub mod device_name;
111 
112 pub mod poll;
113 pub use poll::PollDescriptors as PollDescriptors;
114 
115 pub mod mixer;
116 pub use mixer::Mixer as Mixer;
117 
118 pub mod seq;
119 pub use seq::Seq as Seq;
120 
121 mod io;
122 pub use io::Output;
123 
124 // Reexported inside PCM module
125 mod chmap;
126 
127 mod pcm_direct;
128 
129 /// Functions that bypass alsa-lib and talk directly to the kernel.
130 pub mod direct {
131     /// This module bypasses alsa-lib and directly read and write into memory mapped kernel memory.
132     ///
133     /// In case of the sample memory, this is in many cases the DMA buffers that is transferred to the sound card.
134     ///
135     /// The reasons for doing this are:
136     ///
137     ///  * Minimum overhead where it matters most: let alsa-lib do the code heavy setup -
138     ///    then steal its file descriptor and deal with sample streaming from Rust.
139     ///  * RT-safety to the maximum extent possible. Creating/dropping any of these structs causes syscalls,
140     ///    but function calls on these are just read and write from memory. No syscalls, no memory allocations,
141     ///    not even loops (with the exception of `MmapPlayback::write` that loops over samples to write).
142     ///  * Possibility to allow Send + Sync for structs
143     ///  * It's a fun experiment and an interesting deep dive into how alsa-lib does things.
144     ///
145     /// Note: Not all sound card drivers support this direct method of communication; although almost all
146     /// modern/common ones do. It only works with hardware devices though (such as "hw:xxx" device strings),
147     /// don't expect it to work with, e g, the PulseAudio plugin or so.
148     ///
149     /// For an example of how to use this mode, look in the "synth-example" directory.
150     pub mod pcm {
151         pub use pcm_direct::{SyncPtrStatus, Status, Control, MmapCapture, MmapPlayback, MmapIO, RawSamples};
152 
153     }
154 }
155