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(), name_c.as_ptr() as *const c_char, dir,
106 match device {
107 Some(ref d) => d.as_ptr() as *const c_char, None => null() },
110 desc_c.as_ptr() as *const c_char, &ss, null(), null(), null_mut(), )
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 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 let mut data = Vec::with_capacity(4800);
159 for _ in 0..4800 {
160 data.push([0.0, 0.0]);
161 }
162
163 p.write(&data[..]);
165}
166
167
168pub struct Record<C: ChannelCount> {
169 client: SimpleClient<C>
170}
171
172impl<C: ChannelCount> Record<C> {
173 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 let mut data = Vec::with_capacity(4800);
195 for _ in 0..4800 {
196 data.push([0]);
197 }
198
199 p.read(&mut data[..]);
201}