diff options
Diffstat (limited to 'third_party/rust/pulse/src/stream.rs')
-rw-r--r-- | third_party/rust/pulse/src/stream.rs | 456 |
1 files changed, 456 insertions, 0 deletions
diff --git a/third_party/rust/pulse/src/stream.rs b/third_party/rust/pulse/src/stream.rs new file mode 100644 index 0000000000..4548fb533a --- /dev/null +++ b/third_party/rust/pulse/src/stream.rs @@ -0,0 +1,456 @@ +// Copyright © 2017 Mozilla Foundation +// +// This program is made available under an ISC-style license. See the +// accompanying file LICENSE for details. + +use context; +use ffi; +use operation; +use std::ffi::CStr; +use std::mem::{self, forget, MaybeUninit}; +use std::os::raw::{c_int, c_void}; +use std::ptr; +use util::*; +use *; + +#[derive(Debug)] +pub struct Stream(*mut ffi::pa_stream); + +impl Stream { + pub fn new<'a, CM>( + c: &Context, + name: &::std::ffi::CStr, + ss: &SampleSpec, + map: CM, + ) -> Option<Self> + where + CM: Into<Option<&'a ChannelMap>>, + { + let ptr = unsafe { + ffi::pa_stream_new( + c.raw_mut(), + name.as_ptr(), + ss as *const _, + to_ptr(map.into()), + ) + }; + if ptr.is_null() { + None + } else { + Some(Stream(ptr)) + } + } + + #[doc(hidden)] + pub fn raw_mut(&self) -> &mut ffi::pa_stream { + unsafe { &mut *self.0 } + } + + pub fn unref(self) { + unsafe { + ffi::pa_stream_unref(self.raw_mut()); + } + } + + pub fn get_state(&self) -> StreamState { + StreamState::try_from(unsafe { ffi::pa_stream_get_state(self.raw_mut()) }) + .expect("pa_stream_get_state returned invalid StreamState") + } + + pub fn get_context(&self) -> Option<Context> { + let ptr = unsafe { ffi::pa_stream_get_context(self.raw_mut()) }; + if ptr.is_null() { + return None; + } + + let ctx = unsafe { context::from_raw_ptr(ptr) }; + Some(ctx) + } + + pub fn get_index(&self) -> u32 { + unsafe { ffi::pa_stream_get_index(self.raw_mut()) } + } + + pub fn get_device_name<'a>(&'a self) -> Result<&'a CStr> { + let r = unsafe { ffi::pa_stream_get_device_name(self.raw_mut()) }; + if r.is_null() { + let err = if let Some(c) = self.get_context() { + c.errno() + } else { + ffi::PA_ERR_UNKNOWN + }; + return Err(ErrorCode::from_error_code(err)); + } + Ok(unsafe { CStr::from_ptr(r) }) + } + + pub fn is_suspended(&self) -> Result<bool> { + let r = unsafe { ffi::pa_stream_is_suspended(self.raw_mut()) }; + error_result!(r != 0, r) + } + + pub fn is_corked(&self) -> Result<bool> { + let r = unsafe { ffi::pa_stream_is_corked(self.raw_mut()) }; + error_result!(r != 0, r) + } + + pub fn connect_playback<'a, D, A, V, S>( + &self, + dev: D, + attr: A, + flags: StreamFlags, + volume: V, + sync_stream: S, + ) -> Result<()> + where + D: Into<Option<&'a CStr>>, + A: Into<Option<&'a BufferAttr>>, + V: Into<Option<&'a CVolume>>, + S: Into<Option<&'a mut Stream>>, + { + let r = unsafe { + ffi::pa_stream_connect_playback( + self.raw_mut(), + str_to_ptr(dev.into()), + to_ptr(attr.into()), + flags.into(), + to_ptr(volume.into()), + map_to_mut_ptr(sync_stream.into(), |p| p.0), + ) + }; + error_result!((), r) + } + + pub fn connect_record<'a, D, A>(&self, dev: D, attr: A, flags: StreamFlags) -> Result<()> + where + D: Into<Option<&'a CStr>>, + A: Into<Option<&'a BufferAttr>>, + { + let r = unsafe { + ffi::pa_stream_connect_record( + self.raw_mut(), + str_to_ptr(dev.into()), + to_ptr(attr.into()), + flags.into(), + ) + }; + error_result!((), r) + } + + pub fn disconnect(&self) -> Result<()> { + let r = unsafe { ffi::pa_stream_disconnect(self.raw_mut()) }; + error_result!((), r) + } + + pub fn begin_write(&self, req_bytes: usize) -> Result<(*mut c_void, usize)> { + let mut data: *mut c_void = ptr::null_mut(); + let mut nbytes = req_bytes; + let r = unsafe { ffi::pa_stream_begin_write(self.raw_mut(), &mut data, &mut nbytes) }; + error_result!((data, nbytes), r) + } + + pub fn cancel_write(&self) -> Result<()> { + let r = unsafe { ffi::pa_stream_cancel_write(self.raw_mut()) }; + error_result!((), r) + } + + pub fn write( + &self, + data: *const c_void, + nbytes: usize, + offset: i64, + seek: SeekMode, + ) -> Result<()> { + let r = unsafe { + ffi::pa_stream_write(self.raw_mut(), data, nbytes, None, offset, seek.into()) + }; + error_result!((), r) + } + + pub unsafe fn peek(&self, data: *mut *const c_void, length: *mut usize) -> Result<()> { + let r = ffi::pa_stream_peek(self.raw_mut(), data, length); + error_result!((), r) + } + + pub fn drop(&self) -> Result<()> { + let r = unsafe { ffi::pa_stream_drop(self.raw_mut()) }; + error_result!((), r) + } + + pub fn writable_size(&self) -> Result<usize> { + let r = unsafe { ffi::pa_stream_writable_size(self.raw_mut()) }; + if r == ::std::usize::MAX { + let err = if let Some(c) = self.get_context() { + c.errno() + } else { + ffi::PA_ERR_UNKNOWN + }; + return Err(ErrorCode::from_error_code(err)); + } + Ok(r) + } + + pub fn readable_size(&self) -> Result<usize> { + let r = unsafe { ffi::pa_stream_readable_size(self.raw_mut()) }; + if r == ::std::usize::MAX { + let err = if let Some(c) = self.get_context() { + c.errno() + } else { + ffi::PA_ERR_UNKNOWN + }; + return Err(ErrorCode::from_error_code(err)); + } + Ok(r) + } + + pub fn update_timing_info<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation> + where + CB: Fn(&Stream, i32, *mut c_void), + { + assert_eq!(mem::size_of::<CB>(), 0); + + // See: A note about `wrapped` functions + unsafe extern "C" fn wrapped<F>( + s: *mut ffi::pa_stream, + success: c_int, + userdata: *mut c_void, + ) where + F: Fn(&Stream, i32, *mut c_void), + { + let mut stm = stream::from_raw_ptr(s); + let cb = MaybeUninit::<F>::uninit(); + let result = (*cb.as_ptr())(&mut stm, success, userdata); + forget(stm); + + result + } + + let r = unsafe { + ffi::pa_stream_update_timing_info(self.raw_mut(), Some(wrapped::<CB>), userdata) + }; + if r.is_null() { + let err = if let Some(c) = self.get_context() { + c.errno() + } else { + ffi::PA_ERR_UNKNOWN + }; + return Err(ErrorCode::from_error_code(err)); + } + Ok(unsafe { operation::from_raw_ptr(r) }) + } + + pub fn clear_state_callback(&self) { + unsafe { + ffi::pa_stream_set_state_callback(self.raw_mut(), None, ptr::null_mut()); + } + } + + pub fn set_state_callback<CB>(&self, _: CB, userdata: *mut c_void) + where + CB: Fn(&Stream, *mut c_void), + { + assert_eq!(mem::size_of::<CB>(), 0); + + // See: A note about `wrapped` functions + unsafe extern "C" fn wrapped<F>(s: *mut ffi::pa_stream, userdata: *mut c_void) + where + F: Fn(&Stream, *mut c_void), + { + let mut stm = stream::from_raw_ptr(s); + let cb = MaybeUninit::<F>::uninit(); + let result = (*cb.as_ptr())(&mut stm, userdata); + forget(stm); + + result + } + + unsafe { + ffi::pa_stream_set_state_callback(self.raw_mut(), Some(wrapped::<CB>), userdata); + } + } + + pub fn clear_write_callback(&self) { + unsafe { + ffi::pa_stream_set_write_callback(self.raw_mut(), None, ptr::null_mut()); + } + } + + pub fn set_write_callback<CB>(&self, _: CB, userdata: *mut c_void) + where + CB: Fn(&Stream, usize, *mut c_void), + { + assert_eq!(mem::size_of::<CB>(), 0); + + // See: A note about `wrapped` functions + unsafe extern "C" fn wrapped<F>( + s: *mut ffi::pa_stream, + nbytes: usize, + userdata: *mut c_void, + ) where + F: Fn(&Stream, usize, *mut c_void), + { + let mut stm = stream::from_raw_ptr(s); + let cb = MaybeUninit::<F>::uninit(); + let result = (*cb.as_ptr())(&mut stm, nbytes, userdata); + forget(stm); + + result + } + + unsafe { + ffi::pa_stream_set_write_callback(self.raw_mut(), Some(wrapped::<CB>), userdata); + } + } + + pub fn clear_read_callback(&self) { + unsafe { + ffi::pa_stream_set_read_callback(self.raw_mut(), None, ptr::null_mut()); + } + } + + pub fn set_read_callback<CB>(&self, _: CB, userdata: *mut c_void) + where + CB: Fn(&Stream, usize, *mut c_void), + { + assert_eq!(mem::size_of::<CB>(), 0); + + // See: A note about `wrapped` functions + unsafe extern "C" fn wrapped<F>( + s: *mut ffi::pa_stream, + nbytes: usize, + userdata: *mut c_void, + ) where + F: Fn(&Stream, usize, *mut c_void), + { + let mut stm = stream::from_raw_ptr(s); + let cb = MaybeUninit::<F>::uninit(); + let result = (*cb.as_ptr())(&mut stm, nbytes, userdata); + forget(stm); + + result + } + + unsafe { + ffi::pa_stream_set_read_callback(self.raw_mut(), Some(wrapped::<CB>), userdata); + } + } + + pub fn cork<CB>(&self, b: i32, _: CB, userdata: *mut c_void) -> Result<Operation> + where + CB: Fn(&Stream, i32, *mut c_void), + { + assert_eq!(mem::size_of::<CB>(), 0); + + // See: A note about `wrapped` functions + unsafe extern "C" fn wrapped<F>( + s: *mut ffi::pa_stream, + success: c_int, + userdata: *mut c_void, + ) where + F: Fn(&Stream, i32, *mut c_void), + { + let mut stm = stream::from_raw_ptr(s); + let cb = MaybeUninit::<F>::uninit(); + let result = (*cb.as_ptr())(&mut stm, success, userdata); + forget(stm); + + result + } + + let r = unsafe { ffi::pa_stream_cork(self.raw_mut(), b, Some(wrapped::<CB>), userdata) }; + if r.is_null() { + let err = if let Some(c) = self.get_context() { + c.errno() + } else { + ffi::PA_ERR_UNKNOWN + }; + return Err(ErrorCode::from_error_code(err)); + } + Ok(unsafe { operation::from_raw_ptr(r) }) + } + + pub fn get_time(&self) -> Result<USec> { + let mut usec: USec = 0; + let r = unsafe { ffi::pa_stream_get_time(self.raw_mut(), &mut usec) }; + error_result!(usec, r) + } + + pub fn get_latency(&self) -> Result<StreamLatency> { + let mut usec: u64 = 0; + let mut negative: i32 = 0; + let r = unsafe { ffi::pa_stream_get_latency(self.raw_mut(), &mut usec, &mut negative) }; + error_result!( + if negative == 0 { + StreamLatency::Positive(usec) + } else { + StreamLatency::Negative(usec) + }, + r + ) + } + + pub fn get_sample_spec(&self) -> &SampleSpec { + unsafe { + let ptr = ffi::pa_stream_get_sample_spec(self.raw_mut()); + debug_assert!(!ptr.is_null()); + &*ptr + } + } + + pub fn get_channel_map(&self) -> &ChannelMap { + unsafe { + let ptr = ffi::pa_stream_get_channel_map(self.raw_mut()); + debug_assert!(!ptr.is_null()); + &*ptr + } + } + + pub fn get_buffer_attr(&self) -> &BufferAttr { + unsafe { + let ptr = ffi::pa_stream_get_buffer_attr(self.raw_mut()); + debug_assert!(!ptr.is_null()); + &*ptr + } + } + + pub fn set_name<CB>(&self, name: &CStr, _: CB, userdata: *mut c_void) -> Result<Operation> + where + CB: Fn(&Stream, i32, *mut c_void), + { + assert_eq!(mem::size_of::<CB>(), 0); + + // See: A note about `wrapped` functions + unsafe extern "C" fn wrapped<F>( + s: *mut ffi::pa_stream, + success: c_int, + userdata: *mut c_void, + ) where + F: Fn(&Stream, i32, *mut c_void), + { + let mut stm = stream::from_raw_ptr(s); + let cb = MaybeUninit::<F>::uninit(); + let result = (*cb.as_ptr())(&mut stm, success, userdata); + forget(stm); + + result + } + + let r = unsafe { + ffi::pa_stream_set_name(self.raw_mut(), name.as_ptr(), Some(wrapped::<CB>), userdata) + }; + if r.is_null() { + let err = if let Some(c) = self.get_context() { + c.errno() + } else { + ffi::PA_ERR_UNKNOWN + }; + return Err(ErrorCode::from_error_code(err)); + } + Ok(unsafe { operation::from_raw_ptr(r) }) + } +} + +#[doc(hidden)] +pub unsafe fn from_raw_ptr(ptr: *mut ffi::pa_stream) -> Stream { + Stream(ptr) +} |