pulse_simple/
lib.rs

1extern crate libpulse_sys;
2extern crate libpulse_simple_sys;
3extern crate libc;
4
5use libc::c_char;
6use libpulse_sys::*;
7use libpulse_simple_sys::*;
8use std::ptr::{null, null_mut};
9use std::mem::{transmute, size_of};
10use std::marker::PhantomData;
11use std::ffi::CString;
12
13
14pub trait Sampleable {
15    fn format() -> pa_sample_format_t;
16}
17
18impl Sampleable for u8 {
19    fn format() -> pa_sample_format_t {
20        PA_SAMPLE_U8
21    }
22}
23
24impl Sampleable for i16 {
25    fn format() -> pa_sample_format_t {
26        if cfg!(target_endian = "little") {
27            PA_SAMPLE_S16LE
28        } else {
29            PA_SAMPLE_S16BE
30        }
31    }
32}
33
34impl Sampleable for f32 {
35    fn format() -> pa_sample_format_t {
36        if cfg!(target_endian = "little") {
37            PA_SAMPLE_FLOAT32LE
38        } else {
39            PA_SAMPLE_FLOAT32BE
40        }
41    }
42}
43
44impl Sampleable for i32 {
45    fn format() -> pa_sample_format_t {
46        if cfg!(target_endian = "little") {
47            PA_SAMPLE_S32LE
48        } else {
49            PA_SAMPLE_S32BE
50        }
51    }
52}
53
54pub trait ChannelCount {
55    fn count() -> u8;
56
57    type S: Sampleable;
58    fn format() -> pa_sample_format_t {
59        Self::S::format()
60    }
61    fn sample_size() -> usize {
62        Self::count() as usize * size_of::<Self::S>()
63    }
64}
65
66macro_rules! define_channel_count {
67    ($n: expr) => (
68        impl<S> ChannelCount for [S; $n] where S: Sampleable {
69            type S = S;
70            fn count() -> u8 {
71                $n
72            }
73        }
74    )
75}
76
77define_channel_count!(1);
78define_channel_count!(2);
79define_channel_count!(3);
80define_channel_count!(4);
81define_channel_count!(5);
82define_channel_count!(6);
83define_channel_count!(7);
84define_channel_count!(8);
85define_channel_count!(9);
86
87
88struct SimpleClient<C: ChannelCount> {
89    simple: *mut pa_simple,
90    phantom: PhantomData<C>,
91}
92
93impl<C: ChannelCount> SimpleClient<C> {
94    fn new(name: &str, desc: &str, dir: pa_stream_direction_t, device: Option<&str>, rate: u32) -> Self {
95        let ss = pa_sample_spec {
96            format: C::format(),
97            channels: C::count(),
98            rate: rate
99        };
100        let name_c = CString::new(name).unwrap();
101        let desc_c = CString::new(desc).unwrap();
102        let s = unsafe {
103            pa_simple_new(null(),             // Use the default server.
104                          name_c.as_ptr() as *const c_char,  // Our application's name.
105                          dir,
106                          match device {
107                              Some(ref d) => d.as_ptr() as *const c_char, // Device name to use
108                              None => null() // Use the default device
109                          },
110                          desc_c.as_ptr() as *const c_char,  // Description of our stream.
111                          &ss,                // Our sample format.
112                          null(),             // Use default channel map
113                          null(),             // Use default buffering attributes.
114                          null_mut(),         // Ignore error code.
115                         )
116        };
117        assert!(s != null_mut());
118        SimpleClient {
119            simple: s,
120            phantom: PhantomData
121        }
122    }
123}
124
125impl<C: ChannelCount> Drop for SimpleClient<C> {
126    fn drop(&mut self) {
127        unsafe { pa_simple_free(self.simple) };
128    }
129}
130
131
132pub struct Playback<C: ChannelCount> {
133    client: SimpleClient<C>
134}
135
136impl<C: ChannelCount> Playback<C> {
137    /// Arguments: name, description, optional device (None uses the default device), and rate
138    pub fn new(name: &str, desc: &str, device: Option<&str>, rate: u32) -> Self {
139        Playback {
140            client: SimpleClient::new(name, desc, PA_STREAM_PLAYBACK, device, rate)
141        }
142    }
143
144    pub fn write(&self, data: &[C]) {
145        let res = unsafe {
146            let ptr = transmute(data.as_ptr());
147            pa_simple_write(self.client.simple, ptr, data.len() * C::sample_size(), null_mut())
148        };
149        assert!(res == 0);
150    }
151}
152
153#[test]
154fn test_playback() {
155    let p = Playback::new("Test", "Playback", None, 48000);
156
157    // Generate sound
158    let mut data = Vec::with_capacity(4800);
159    for _ in 0..4800 {
160        data.push([0.0, 0.0]);
161    }
162
163    // Play
164    p.write(&data[..]);
165}
166
167
168pub struct Record<C: ChannelCount> {
169    client: SimpleClient<C>
170}
171
172impl<C: ChannelCount> Record<C> {
173    /// Arguments: name, description, optional device (None uses the default device), and rate
174    pub fn new(name: &str, desc: &str, device: Option<&str>, rate: u32) -> Self {
175        Record {
176            client: SimpleClient::new(name, desc, PA_STREAM_RECORD, device, rate)
177        }
178    }
179
180    pub fn read(&self, data: &mut [C]) {
181        let res = unsafe {
182            let ptr = transmute(data.as_mut_ptr());
183            pa_simple_read(self.client.simple, ptr, data.len() * C::sample_size(), null_mut())
184        };
185        assert!(res >= 0);
186    }
187}
188
189#[test]
190fn test_record() {
191    let p = Record::new("Test", "Record", None, 48000);
192
193    // Fill:
194    let mut data = Vec::with_capacity(4800);
195    for _ in 0..4800 {
196        data.push([0]);
197    }
198
199    // Record
200    p.read(&mut data[..]);
201}