commit
d1d7a3db07
|
@ -16,5 +16,13 @@ git = "https://github.com/tomaka/winapi-rs"
|
||||||
branch = "mmdeviceapi"
|
branch = "mmdeviceapi"
|
||||||
features = ["ole32"]
|
features = ["ole32"]
|
||||||
|
|
||||||
|
[target.i686-unknown-linux-gnu.dependencies.alsa-sys]
|
||||||
|
version = "*"
|
||||||
|
path = "alsa-sys"
|
||||||
|
|
||||||
|
[target.x86_64-unknown-linux-gnu.dependencies.alsa-sys]
|
||||||
|
version = "*"
|
||||||
|
path = "alsa-sys"
|
||||||
|
|
||||||
[dev-dependencies.vorbis]
|
[dev-dependencies.vorbis]
|
||||||
git = "https://github.com/tomaka/vorbis-rs"
|
git = "https://github.com/tomaka/vorbis-rs"
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
/target
|
||||||
|
/Cargo.lock
|
||||||
|
.cargo/
|
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
|
||||||
|
name = "alsa-sys"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"]
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
pkg-config = "*"
|
|
@ -0,0 +1,5 @@
|
||||||
|
extern crate "pkg-config" as pkg_config;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
pkg_config::find_library("alsa").unwrap();
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,107 @@
|
||||||
|
extern crate "alsa-sys" as alsa;
|
||||||
|
extern crate libc;
|
||||||
|
|
||||||
|
use std::{mem, ptr};
|
||||||
|
|
||||||
|
pub struct Channel {
|
||||||
|
channel: *mut alsa::snd_pcm_t,
|
||||||
|
num_channels: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Buffer<'a, T> {
|
||||||
|
channel: &'a mut Channel,
|
||||||
|
buffer: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Channel {
|
||||||
|
pub fn new() -> Channel {
|
||||||
|
unsafe {
|
||||||
|
let name = "default".to_c_str();
|
||||||
|
|
||||||
|
let mut playback_handle = mem::uninitialized();
|
||||||
|
check_errors(alsa::snd_pcm_open(&mut playback_handle, name.as_ptr(), alsa::SND_PCM_STREAM_PLAYBACK, alsa::SND_PCM_NONBLOCK)).unwrap();
|
||||||
|
|
||||||
|
let mut hw_params = mem::uninitialized();
|
||||||
|
check_errors(alsa::snd_pcm_hw_params_malloc(&mut hw_params)).unwrap();
|
||||||
|
check_errors(alsa::snd_pcm_hw_params_any(playback_handle, hw_params)).unwrap();
|
||||||
|
check_errors(alsa::snd_pcm_hw_params_set_access(playback_handle, hw_params, alsa::SND_PCM_ACCESS_RW_INTERLEAVED)).unwrap();
|
||||||
|
check_errors(alsa::snd_pcm_hw_params_set_format(playback_handle, hw_params, alsa::SND_PCM_FORMAT_S16_LE)).unwrap(); // TODO: check endianess
|
||||||
|
check_errors(alsa::snd_pcm_hw_params_set_rate(playback_handle, hw_params, 44100, 0)).unwrap();
|
||||||
|
check_errors(alsa::snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2)).unwrap();
|
||||||
|
check_errors(alsa::snd_pcm_hw_params(playback_handle, hw_params)).unwrap();
|
||||||
|
alsa::snd_pcm_hw_params_free(hw_params);
|
||||||
|
|
||||||
|
check_errors(alsa::snd_pcm_prepare(playback_handle)).unwrap();
|
||||||
|
|
||||||
|
Channel {
|
||||||
|
channel: playback_handle,
|
||||||
|
num_channels: 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_channels(&self) -> ::ChannelsCount {
|
||||||
|
self.num_channels
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_samples_rate(&self) -> ::SamplesRate {
|
||||||
|
::SamplesRate(44100)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_samples_format(&self) -> ::SampleFormat {
|
||||||
|
::SampleFormat::U16
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_data<'a, T>(&'a mut self, max_elements: uint) -> Buffer<'a, T> where T: Clone {
|
||||||
|
let available = unsafe { alsa::snd_pcm_avail(self.channel) };
|
||||||
|
let available = available * self.num_channels as alsa::snd_pcm_sframes_t;
|
||||||
|
|
||||||
|
let elements = ::std::cmp::min(available as uint, max_elements);
|
||||||
|
|
||||||
|
Buffer {
|
||||||
|
channel: self,
|
||||||
|
buffer: Vec::from_elem(elements, unsafe { mem::uninitialized() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Channel {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
alsa::snd_pcm_close(self.channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Buffer<'a, T> {
|
||||||
|
pub fn get_buffer<'b>(&'b mut self) -> &'b mut [T] {
|
||||||
|
self.buffer.as_mut_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(self) {
|
||||||
|
let written = (self.buffer.len() / self.channel.num_channels as uint) as alsa::snd_pcm_uframes_t;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let result = alsa::snd_pcm_writei(self.channel.channel,
|
||||||
|
self.buffer.as_ptr() as *const libc::c_void,
|
||||||
|
written);
|
||||||
|
|
||||||
|
if result < 0 {
|
||||||
|
check_errors(result as libc::c_int).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_errors(err: libc::c_int) -> Result<(), String> {
|
||||||
|
use std::c_str::CString;
|
||||||
|
|
||||||
|
if err < 0 {
|
||||||
|
unsafe {
|
||||||
|
let s = CString::new(alsa::snd_strerror(err), false);
|
||||||
|
return Err(s.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
#![feature(unsafe_destructor)]
|
#![feature(unsafe_destructor)]
|
||||||
|
|
||||||
#[cfg(all(not(windows)))]
|
#[cfg(all(not(windows), not(unix)))]
|
||||||
use this_platform_is_not_supported;
|
use this_platform_is_not_supported;
|
||||||
|
|
||||||
mod conversions;
|
mod conversions;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
#[path="alsa/mod.rs"]
|
||||||
|
pub mod cpal_impl;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
#[path="wasapi/mod.rs"]
|
#[path="wasapi/mod.rs"]
|
||||||
pub mod cpal_impl;
|
pub mod cpal_impl;
|
||||||
|
|
Loading…
Reference in New Issue