use std;
use capi;
use std::os::raw::{c_char, c_void};
use std::ffi::{CStr, CString};
use std::ptr::{null, null_mut};
use ::util::unwrap_optional_callback;
pub use capi::pa_stream as StreamInternal;
pub use capi::pa_seek_mode_t as SeekMode;
pub use capi::pa_stream_direction_t as Direction;
pub struct Stream {
ptr: *mut StreamInternal,
weak: bool,
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum State {
Unconnected,
Creating,
Ready,
Failed,
Terminated,
}
impl From<State> for capi::pa_stream_state_t {
fn from(s: State) -> Self {
unsafe { std::mem::transmute(s) }
}
}
impl From<capi::pa_stream_state_t> for State {
fn from(s: capi::pa_stream_state_t) -> Self {
unsafe { std::mem::transmute(s) }
}
}
impl State {
pub fn is_good(self) -> bool {
self == State::Creating || self == State::Ready
}
}
pub type FlagSet = capi::pa_stream_flags_t;
pub mod flags {
use capi;
use super::FlagSet;
pub const NOFLAGS: FlagSet = capi::PA_STREAM_NOFLAGS;
pub const START_CORKED: FlagSet = capi::PA_STREAM_START_CORKED;
pub const INTERPOLATE_TIMING: FlagSet = capi::PA_STREAM_INTERPOLATE_TIMING;
pub const NOT_MONOTONIC: FlagSet = capi::PA_STREAM_NOT_MONOTONIC;
pub const AUTO_TIMING_UPDATE: FlagSet = capi::PA_STREAM_AUTO_TIMING_UPDATE;
pub const NO_REMAP_CHANNELS: FlagSet = capi::PA_STREAM_NO_REMAP_CHANNELS;
pub const NO_REMIX_CHANNELS: FlagSet = capi::PA_STREAM_NO_REMIX_CHANNELS;
pub const FIX_FORMAT: FlagSet = capi::PA_STREAM_FIX_FORMAT;
pub const FIX_RATE: FlagSet = capi::PA_STREAM_FIX_RATE;
pub const FIX_CHANNELS: FlagSet = capi::PA_STREAM_FIX_CHANNELS;
pub const DONT_MOVE: FlagSet = capi::PA_STREAM_DONT_MOVE;
pub const VARIABLE_RATE: FlagSet = capi::PA_STREAM_VARIABLE_RATE;
pub const PEAK_DETECT: FlagSet = capi::PA_STREAM_PEAK_DETECT;
pub const START_MUTED: FlagSet = capi::PA_STREAM_START_MUTED;
pub const ADJUST_LATENCY: FlagSet = capi::PA_STREAM_ADJUST_LATENCY;
pub const EARLY_REQUESTS: FlagSet = capi::PA_STREAM_EARLY_REQUESTS;
pub const DONT_INHIBIT_AUTO_SUSPEND: FlagSet = capi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND;
pub const START_UNMUTED: FlagSet = capi::PA_STREAM_START_UNMUTED;
pub const FAIL_ON_SUSPEND: FlagSet = capi::PA_STREAM_FAIL_ON_SUSPEND;
pub const RELATIVE_VOLUME: FlagSet = capi::PA_STREAM_RELATIVE_VOLUME;
pub const PASSTHROUGH: FlagSet = capi::PA_STREAM_PASSTHROUGH;
}
pub const EVENT_REQUEST_CORK: &str = capi::PA_STREAM_EVENT_REQUEST_CORK;
pub const EVENT_REQUEST_UNCORK: &str = capi::PA_STREAM_EVENT_REQUEST_UNCORK;
pub const EVENT_FORMAT_LOST: &str = capi::PA_STREAM_EVENT_FORMAT_LOST;
pub type SuccessCb = extern "C" fn(s: *mut StreamInternal, success: i32,
userdata: *mut c_void);
pub type RequestCb = extern "C" fn(p: *mut StreamInternal, nbytes: usize,
userdata: *mut c_void);
pub type NotifyCb = extern "C" fn(p: *mut StreamInternal, userdata: *mut c_void);
pub type EventCb = extern "C" fn(p: *mut StreamInternal, name: *const c_char,
pl: *mut ::proplist::ProplistInternal, userdata: *mut c_void);
pub enum PeekResult<'a> {
Empty,
Hole(usize),
Data(&'a [u8]),
}
pub enum BufferResult {
Null,
Buffer(*mut c_void, usize),
}
pub enum Latency {
None,
Positive(::sample::Usecs),
Negative(::sample::Usecs),
}
impl Stream {
pub fn new(ctx: &mut ::context::Context, name: &str, ss: &::sample::Spec,
map: Option<&::channelmap::Map>) -> Option<Self>
{
let c_name = CString::new(name.clone()).unwrap();
let p_map: *const capi::pa_channel_map = match map {
Some(map) => unsafe { std::mem::transmute(map) },
None => null::<capi::pa_channel_map>(),
};
let ptr = unsafe { capi::pa_stream_new(ctx.ptr, c_name.as_ptr(), std::mem::transmute(ss),
p_map) };
if ptr.is_null() {
return None;
}
Some(Self::from_raw(ptr))
}
pub fn new_with_proplist(ctx: &mut ::context::Context, name: &str, ss: &::sample::Spec,
map: Option<&::channelmap::Map>, plist: &mut ::proplist::Proplist) -> Option<Self>
{
let c_name = CString::new(name.clone()).unwrap();
let p_map: *const capi::pa_channel_map = match map {
Some(map) => unsafe { std::mem::transmute(map) },
None => null::<capi::pa_channel_map>(),
};
let ptr = unsafe { capi::pa_stream_new_with_proplist(ctx.ptr, c_name.as_ptr(),
std::mem::transmute(ss), p_map, plist.ptr) };
if ptr.is_null() {
return None;
}
Some(Self::from_raw(ptr))
}
pub fn new_extended(ctx: &mut ::context::Context, name: &str, formats: &[&::format::Info],
list: &mut ::proplist::Proplist) -> Option<Self>
{
let c_name = CString::new(name.clone()).unwrap();
let mut info_ptrs: Vec<*const capi::pa_format_info> = Vec::with_capacity(formats.len());
for format in formats {
info_ptrs.push(unsafe { std::mem::transmute(&format.ptr) });
}
let ptr = unsafe {
capi::pa_stream_new_extended(ctx.ptr, c_name.as_ptr(), info_ptrs.as_ptr(),
info_ptrs.len() as u32, list.ptr)
};
if ptr.is_null() {
return None;
}
Some(Self::from_raw(ptr))
}
pub fn from_raw(ptr: *mut StreamInternal) -> Self {
assert_eq!(false, ptr.is_null());
Self { ptr: ptr, weak: false }
}
pub fn from_raw_weak(ptr: *mut StreamInternal) -> Self {
assert_eq!(false, ptr.is_null());
Self { ptr: ptr, weak: true }
}
pub fn get_state(&self) -> State {
unsafe { capi::pa_stream_get_state(self.ptr).into() }
}
pub fn get_context(&self) -> ::context::Context {
::context::Context::from_raw(unsafe { capi::pa_stream_get_context(self.ptr) })
}
pub fn get_index(&self) -> Option<u32> {
match unsafe { capi::pa_stream_get_index(self.ptr) } {
::def::INVALID_INDEX => None,
r => Some(r),
}
}
pub fn get_device_index(&self) -> Option<u32> {
match unsafe { capi::pa_stream_get_device_index(self.ptr) } {
::def::INVALID_INDEX => None,
r => Some(r),
}
}
pub fn get_device_name(&self) -> Option<&'static CStr> {
let ptr: *const c_char = unsafe { capi::pa_stream_get_device_name(self.ptr) };
if ptr.is_null() {
return None;
}
Some(unsafe { CStr::from_ptr(ptr) })
}
pub fn is_suspended(&self) -> Result<bool, i32> {
match unsafe { capi::pa_stream_is_suspended(self.ptr) } {
0 => Ok(false),
1 => Ok(true),
r => Err(r),
}
}
pub fn is_corked(&self) -> Result<bool, i32> {
match unsafe { capi::pa_stream_is_corked(self.ptr) } {
0 => Ok(false),
1 => Ok(true),
r => Err(r),
}
}
pub fn connect_playback(&self, dev: Option<&str>, attr: Option<&::def::BufferAttr>,
flags: FlagSet, volume: Option<&::volume::CVolume>, sync_stream: Option<&mut Self>
) -> Result<(), i32>
{
let c_dev = match dev {
Some(dev) => CString::new(dev.clone()).unwrap(),
None => CString::new("").unwrap(),
};
let p_attr: *const capi::pa_buffer_attr = match attr {
Some(attr) => unsafe { std::mem::transmute(attr) },
None => null::<capi::pa_buffer_attr>(),
};
let p_vol: *const capi::pa_cvolume = match volume {
Some(volume) => unsafe { std::mem::transmute(volume) },
None => null::<capi::pa_cvolume>(),
};
let p_sync: *mut StreamInternal = match sync_stream {
Some(sync_stream) => sync_stream.ptr,
None => null_mut::<StreamInternal>(),
};
let p_dev: *const c_char = match dev {
Some(_) => c_dev.as_ptr(),
None => null::<c_char>(),
};
match unsafe { capi::pa_stream_connect_playback(self.ptr, p_dev, p_attr, flags, p_vol,
p_sync) }
{
0 => Ok(()),
e => Err(e),
}
}
pub fn connect_record(&self, dev: Option<&str>, attr: Option<&::def::BufferAttr>,
flags: FlagSet) -> Result<(), i32>
{
let c_dev = match dev {
Some(dev) => CString::new(dev.clone()).unwrap(),
None => CString::new("").unwrap(),
};
let p_attr: *const capi::pa_buffer_attr = match attr {
Some(attr) => unsafe { std::mem::transmute(attr) },
None => null::<capi::pa_buffer_attr>(),
};
let p_dev: *const c_char = match dev {
Some(_) => c_dev.as_ptr(),
None => null::<c_char>(),
};
match unsafe { capi::pa_stream_connect_record(self.ptr, p_dev, p_attr, flags) } {
0 => Ok(()),
e => Err(e),
}
}
pub fn connect_upload(&self, length: usize) -> Result<(), i32> {
match unsafe { capi::pa_stream_connect_upload(self.ptr, length) } {
0 => Ok(()),
e => Err(e),
}
}
pub fn finish_upload(&self) -> Result<(), i32> {
match unsafe { capi::pa_stream_finish_upload(self.ptr) } {
0 => Ok(()),
e => Err(e),
}
}
pub fn disconnect(&self) -> Result<(), i32> {
match unsafe { capi::pa_stream_disconnect(self.ptr) } {
0 => Ok(()),
e => Err(e),
}
}
pub fn begin_write(&self, nbytes: Option<usize>) -> Result<BufferResult, i32> {
let mut data_ptr = null_mut::<c_void>();
let mut nbytes_tmp: usize = match nbytes {
Some(nbytes) => nbytes,
None => std::usize::MAX,
};
match unsafe { capi::pa_stream_begin_write(self.ptr, &mut data_ptr, &mut nbytes_tmp) } {
0 if data_ptr.is_null() => Ok(BufferResult::Null),
0 => Ok(BufferResult::Buffer(data_ptr, nbytes_tmp)),
e => Err(e),
}
}
pub fn cancel_write(&self) -> Result<(), i32> {
match unsafe { capi::pa_stream_cancel_write(self.ptr) } {
0 => Ok(()),
e => Err(e),
}
}
pub fn write(&self, data: &[u8], free_cb: Option<::def::FreeCb>, offset: i64, seek: SeekMode
) -> Result<(), i32>
{
debug_assert_eq!(0, data.len().checked_rem(self.get_sample_spec().unwrap().frame_size())
.unwrap());
match unsafe { capi::pa_stream_write(self.ptr, data.as_ptr() as *const c_void, data.len(),
free_cb.unwrap_or_default(), offset, seek) }
{
0 => Ok(()),
e => Err(e),
}
}
pub fn write_ext_free(&self, data: &[u8], free_cb: Option<::def::FreeCb>,
free_cb_data: *mut c_void, offset: i64, seek: SeekMode) -> Result<(), i32>
{
debug_assert_eq!(0, data.len().checked_rem(self.get_sample_spec().unwrap().frame_size())
.unwrap());
match unsafe { capi::pa_stream_write_ext_free(self.ptr, data.as_ptr() as *const c_void,
data.len(), free_cb.unwrap_or_default(), free_cb_data, offset, seek.into()) }
{
0 => Ok(()),
e => Err(e),
}
}
pub fn peek(&self) -> Result<PeekResult, i32> {
let mut data_ptr = null::<c_void>();
let mut nbytes: usize = 0;
match unsafe { capi::pa_stream_peek(self.ptr, &mut data_ptr, &mut nbytes) } {
0 if data_ptr.is_null() && nbytes == 0 => Ok(PeekResult::Empty),
0 if data_ptr.is_null() => Ok(PeekResult::Hole(nbytes)),
0 => Ok(PeekResult::Data(unsafe { std::slice::from_raw_parts(data_ptr as *const u8,
nbytes) })),
e => Err(e),
}
}
pub fn discard(&self) -> Result<(), i32> {
match unsafe { capi::pa_stream_drop(self.ptr) } {
0 => Ok(()),
e => Err(e),
}
}
pub fn writable_size(&self) -> Option<usize> {
match unsafe { capi::pa_stream_writable_size(self.ptr) } {
std::usize::MAX => None,
r => Some(r),
}
}
pub fn readable_size(&self) -> Option<usize> {
match unsafe { capi::pa_stream_readable_size(self.ptr) } {
std::usize::MAX => None,
r => Some(r),
}
}
pub fn drain(&self, cb: Option<(SuccessCb, *mut c_void)>) -> Option<::operation::Operation> {
let (cb_f, cb_d) = unwrap_optional_callback::<SuccessCb>(cb);
let ptr = unsafe { capi::pa_stream_drain(self.ptr, cb_f, cb_d) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn update_timing_info(&self, cb: Option<(SuccessCb, *mut c_void)>
) -> Option<::operation::Operation>
{
let (cb_f, cb_d) = unwrap_optional_callback::<SuccessCb>(cb);
let ptr = unsafe { capi::pa_stream_update_timing_info(self.ptr, cb_f, cb_d) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn set_state_callback(&self, cb: Option<(NotifyCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<NotifyCb>(cb);
unsafe { capi::pa_stream_set_state_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_write_callback(&self, cb: Option<(RequestCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<RequestCb>(cb);
unsafe { capi::pa_stream_set_write_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_read_callback(&self, cb: Option<(RequestCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<RequestCb>(cb);
unsafe { capi::pa_stream_set_read_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_overflow_callback(&self, cb: Option<(NotifyCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<NotifyCb>(cb);
unsafe { capi::pa_stream_set_overflow_callback(self.ptr, cb_f, cb_d); }
}
pub fn get_underflow_index(&self) -> Option<i64> {
match unsafe { capi::pa_stream_get_underflow_index(self.ptr) } {
-1 => None,
r => Some(r),
}
}
pub fn set_underflow_callback(&self, cb: Option<(NotifyCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<NotifyCb>(cb);
unsafe { capi::pa_stream_set_underflow_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_started_callback(&self, cb: Option<(NotifyCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<NotifyCb>(cb);
unsafe { capi::pa_stream_set_started_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_latency_update_callback(&self, cb: Option<(NotifyCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<NotifyCb>(cb);
unsafe { capi::pa_stream_set_latency_update_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_moved_callback(&self, cb: Option<(NotifyCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<NotifyCb>(cb);
unsafe { capi::pa_stream_set_moved_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_suspended_callback(&self, cb: Option<(NotifyCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<NotifyCb>(cb);
unsafe { capi::pa_stream_set_suspended_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_event_callback(&self, cb: Option<(EventCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<EventCb>(cb);
unsafe { capi::pa_stream_set_event_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_buffer_attr_callback(&self, cb: Option<(NotifyCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<NotifyCb>(cb);
unsafe { capi::pa_stream_set_buffer_attr_callback(self.ptr, cb_f, cb_d); }
}
pub fn cork(&self, cb: Option<(SuccessCb, *mut c_void)>) -> Option<::operation::Operation> {
let (cb_f, cb_d) = unwrap_optional_callback::<SuccessCb>(cb);
let ptr = unsafe { capi::pa_stream_cork(self.ptr, true as i32, cb_f, cb_d) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn uncork(&self, cb: Option<(SuccessCb, *mut c_void)>) -> Option<::operation::Operation> {
let (cb_f, cb_d) = unwrap_optional_callback::<SuccessCb>(cb);
let ptr = unsafe { capi::pa_stream_cork(self.ptr, false as i32, cb_f, cb_d) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn flush(&self, cb: Option<(SuccessCb, *mut c_void)>) -> Option<::operation::Operation> {
let (cb_f, cb_d) = unwrap_optional_callback::<SuccessCb>(cb);
let ptr = unsafe { capi::pa_stream_flush(self.ptr, cb_f, cb_d) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn prebuf(&self, cb: Option<(SuccessCb, *mut c_void)>) -> Option<::operation::Operation> {
let (cb_f, cb_d) = unwrap_optional_callback::<SuccessCb>(cb);
let ptr = unsafe { capi::pa_stream_prebuf(self.ptr, cb_f, cb_d) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn trigger(&self, cb: Option<(SuccessCb, *mut c_void)>) -> Option<::operation::Operation> {
let (cb_f, cb_d) = unwrap_optional_callback::<SuccessCb>(cb);
let ptr = unsafe { capi::pa_stream_trigger(self.ptr, cb_f, cb_d) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn set_name(&self, name: &str, cb: Option<(SuccessCb, *mut c_void)>
) -> Option<::operation::Operation>
{
let (cb_f, cb_d) = unwrap_optional_callback::<SuccessCb>(cb);
let c_name = CString::new(name.clone()).unwrap();
let ptr = unsafe {
capi::pa_stream_set_name(self.ptr, c_name.as_ptr(), cb_f, cb_d)
};
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn get_time(&self) -> Result<Option<::sample::Usecs>, i32> {
let mut r_usecs: ::sample::Usecs = 0;
match unsafe { capi::pa_stream_get_time(self.ptr, &mut r_usecs) } {
0 => Ok(Some(r_usecs)),
e if e == -(::error::Code::NoData as i32) => Ok(None),
e => Err(e),
}
}
pub fn get_latency(&self) -> Result<Latency, i32> {
let mut r_usecs: ::sample::Usecs = 0;
let mut negative: i32 = 0;
match unsafe { capi::pa_stream_get_latency(self.ptr, &mut r_usecs, &mut negative) } {
0 => {
match negative {
1 => Ok(Latency::Negative(r_usecs)),
_ => Ok(Latency::Positive(r_usecs)),
}
},
e if e == -(::error::Code::NoData as i32) => Ok(Latency::None),
e => Err(e),
}
}
pub fn get_timing_info(&self) -> Option<&::def::TimingInfo> {
let ptr = unsafe { capi::pa_stream_get_timing_info(self.ptr) };
unsafe { std::mem::transmute(ptr) }
}
pub fn get_sample_spec(&self) -> Option<&::sample::Spec> {
let ptr = unsafe { capi::pa_stream_get_sample_spec(self.ptr) };
unsafe { std::mem::transmute(ptr) }
}
pub fn get_channel_map(&self) -> Option<&::channelmap::Map> {
let ptr = unsafe { capi::pa_stream_get_channel_map(self.ptr) };
unsafe { std::mem::transmute(ptr) }
}
pub fn get_format_info(&self) -> Option<::format::Info> {
let ptr = unsafe { capi::pa_stream_get_format_info(self.ptr) };
if ptr.is_null() {
return None;
}
Some(::format::Info::from_raw(unsafe { std::mem::transmute(ptr) }))
}
pub fn get_buffer_attr(&self) -> Option<&::def::BufferAttr> {
let ptr = unsafe { capi::pa_stream_get_buffer_attr(self.ptr) };
unsafe { std::mem::transmute(ptr) }
}
pub fn set_buffer_attr(&self, attr: &::def::BufferAttr, cb: (SuccessCb, *mut c_void)
) -> Option<::operation::Operation>
{
let ptr = unsafe { capi::pa_stream_set_buffer_attr(self.ptr, std::mem::transmute(attr),
Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn update_sample_rate(&self, rate: u32, cb: (SuccessCb, *mut c_void)
) -> Option<::operation::Operation>
{
let ptr = unsafe { capi::pa_stream_update_sample_rate(self.ptr, rate, Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn update_proplist(&self, mode: ::proplist::UpdateMode, plist: &mut ::proplist::Proplist,
cb: (SuccessCb, *mut c_void)) -> Option<::operation::Operation>
{
let ptr = unsafe { capi::pa_stream_proplist_update(self.ptr, mode, plist.ptr, Some(cb.0),
cb.1) };
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn proplist_remove(&self, keys: &[&str], cb: (SuccessCb, *mut c_void)
) -> Option<::operation::Operation>
{
let mut c_keys: Vec<CString> = Vec::with_capacity(keys.len());
for key in keys {
c_keys.push(CString::new(key.clone()).unwrap());
}
let mut c_key_ptrs: Vec<*const c_char> = Vec::with_capacity(c_keys.len()+1);
for c_key in c_keys {
c_key_ptrs.push(c_key.as_ptr());
}
c_key_ptrs.push(null());
let ptr = unsafe {
capi::pa_stream_proplist_remove(self.ptr, c_key_ptrs.as_ptr(), Some(cb.0), cb.1)
};
if ptr.is_null() {
return None;
}
Some(::operation::Operation::from_raw(ptr))
}
pub fn set_monitor_stream(&self, sink_input_idx: u32) -> Result<(), i32> {
match unsafe { capi::pa_stream_set_monitor_stream(self.ptr, sink_input_idx) } {
0 => Ok(()),
e => Err(e),
}
}
pub fn get_monitor_stream(&self) -> Option<u32> {
match unsafe { capi::pa_stream_get_monitor_stream(self.ptr) } {
::def::INVALID_INDEX => None,
r => Some(r),
}
}
}
impl Drop for Stream {
fn drop(&mut self) {
if !self.weak {
self.disconnect().unwrap();
unsafe { capi::pa_stream_unref(self.ptr) };
}
self.ptr = null_mut::<StreamInternal>();
}
}