Source code

Revision control

Copy as Markdown

Other Tools

// Copyright © 2017 Mozilla Foundation
//
// This program is made available under an ISC-style license. See the
// accompanying file LICENSE for details.
#[macro_use]
extern crate bitflags;
extern crate pulse_ffi as ffi;
#[macro_use]
mod error;
mod context;
mod mainloop_api;
mod operation;
mod proplist;
mod stream;
mod threaded_mainloop;
mod util;
pub use context::Context;
pub use error::ErrorCode;
pub use ffi::pa_buffer_attr as BufferAttr;
pub use ffi::pa_channel_map as ChannelMap;
pub use ffi::pa_cvolume as CVolume;
pub use ffi::pa_sample_spec as SampleSpec;
pub use ffi::pa_server_info as ServerInfo;
pub use ffi::pa_sink_info as SinkInfo;
pub use ffi::pa_sink_input_info as SinkInputInfo;
pub use ffi::pa_source_info as SourceInfo;
pub use ffi::pa_usec_t as USec;
pub use ffi::pa_volume_t as Volume;
pub use ffi::timeval as TimeVal;
pub use mainloop_api::MainloopApi;
pub use operation::Operation;
pub use proplist::Proplist;
use std::os::raw::{c_char, c_uint};
pub use stream::Stream;
pub use threaded_mainloop::ThreadedMainloop;
#[allow(non_camel_case_types)]
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SampleFormat {
Invalid = ffi::PA_SAMPLE_INVALID,
U8 = ffi::PA_SAMPLE_U8,
Alaw = ffi::PA_SAMPLE_ALAW,
Ulaw = ffi::PA_SAMPLE_ULAW,
Signed16LE = ffi::PA_SAMPLE_S16LE,
Signed16BE = ffi::PA_SAMPLE_S16BE,
Float32LE = ffi::PA_SAMPLE_FLOAT32LE,
Float32BE = ffi::PA_SAMPLE_FLOAT32BE,
Signed32LE = ffi::PA_SAMPLE_S32LE,
Signed32BE = ffi::PA_SAMPLE_S32BE,
Signed24LE = ffi::PA_SAMPLE_S24LE,
Signed24BE = ffi::PA_SAMPLE_S24BE,
Signed24_32LE = ffi::PA_SAMPLE_S24_32LE,
Signed23_32BE = ffi::PA_SAMPLE_S24_32BE,
}
impl Default for SampleFormat {
fn default() -> Self {
SampleFormat::Invalid
}
}
impl Into<ffi::pa_sample_format_t> for SampleFormat {
fn into(self) -> ffi::pa_sample_format_t {
self as ffi::pa_sample_format_t
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ContextState {
Unconnected = ffi::PA_CONTEXT_UNCONNECTED,
Connecting = ffi::PA_CONTEXT_CONNECTING,
Authorizing = ffi::PA_CONTEXT_AUTHORIZING,
SettingName = ffi::PA_CONTEXT_SETTING_NAME,
Ready = ffi::PA_CONTEXT_READY,
Failed = ffi::PA_CONTEXT_FAILED,
Terminated = ffi::PA_CONTEXT_TERMINATED,
}
impl ContextState {
// This function implements the PA_CONTENT_IS_GOOD macro from pulse/def.h
// It must match the version from PA headers.
pub fn is_good(self) -> bool {
match self {
ContextState::Connecting
| ContextState::Authorizing
| ContextState::SettingName
| ContextState::Ready => true,
_ => false,
}
}
pub fn try_from(x: ffi::pa_context_state_t) -> Option<Self> {
if x >= ffi::PA_CONTEXT_UNCONNECTED && x <= ffi::PA_CONTEXT_TERMINATED {
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Default for ContextState {
fn default() -> Self {
ContextState::Unconnected
}
}
impl Into<ffi::pa_context_state_t> for ContextState {
fn into(self) -> ffi::pa_context_state_t {
self as ffi::pa_context_state_t
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StreamState {
Unconnected = ffi::PA_STREAM_UNCONNECTED,
Creating = ffi::PA_STREAM_CREATING,
Ready = ffi::PA_STREAM_READY,
Failed = ffi::PA_STREAM_FAILED,
Terminated = ffi::PA_STREAM_TERMINATED,
}
impl StreamState {
// This function implements the PA_STREAM_IS_GOOD macro from pulse/def.h
// It must match the version from PA headers.
pub fn is_good(self) -> bool {
match self {
StreamState::Creating | StreamState::Ready => true,
_ => false,
}
}
pub fn try_from(x: ffi::pa_stream_state_t) -> Option<Self> {
if x >= ffi::PA_STREAM_UNCONNECTED && x <= ffi::PA_STREAM_TERMINATED {
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Default for StreamState {
fn default() -> Self {
StreamState::Unconnected
}
}
impl Into<ffi::pa_stream_state_t> for StreamState {
fn into(self) -> ffi::pa_stream_state_t {
self as ffi::pa_stream_state_t
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum OperationState {
Running = ffi::PA_OPERATION_RUNNING,
Done = ffi::PA_OPERATION_DONE,
Cancelled = ffi::PA_OPERATION_CANCELLED,
}
impl OperationState {
pub fn try_from(x: ffi::pa_operation_state_t) -> Option<Self> {
if x >= ffi::PA_OPERATION_RUNNING && x <= ffi::PA_OPERATION_CANCELLED {
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Into<ffi::pa_operation_state_t> for OperationState {
fn into(self) -> ffi::pa_operation_state_t {
self as ffi::pa_operation_state_t
}
}
bitflags! {
pub struct ContextFlags: u32 {
const NOAUTOSPAWN = ffi::PA_CONTEXT_NOAUTOSPAWN;
const NOFAIL = ffi::PA_CONTEXT_NOFAIL;
}
}
impl Into<ffi::pa_context_flags_t> for ContextFlags {
fn into(self) -> ffi::pa_context_flags_t {
self.bits() as ffi::pa_context_flags_t
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DeviceType {
Sink = ffi::PA_DEVICE_TYPE_SINK,
Source = ffi::PA_DEVICE_TYPE_SOURCE,
}
impl DeviceType {
pub fn try_from(x: ffi::pa_device_type_t) -> Option<Self> {
if x >= ffi::PA_DEVICE_TYPE_SINK && x <= ffi::PA_DEVICE_TYPE_SOURCE {
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Into<ffi::pa_device_type_t> for DeviceType {
fn into(self) -> ffi::pa_device_type_t {
self as ffi::pa_device_type_t
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StreamDirection {
NoDirection = ffi::PA_STREAM_NODIRECTION,
Playback = ffi::PA_STREAM_PLAYBACK,
Record = ffi::PA_STREAM_RECORD,
StreamUpload = ffi::PA_STREAM_UPLOAD,
}
impl StreamDirection {
pub fn try_from(x: ffi::pa_stream_direction_t) -> Option<Self> {
if x >= ffi::PA_STREAM_NODIRECTION && x <= ffi::PA_STREAM_UPLOAD {
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Into<ffi::pa_stream_direction_t> for StreamDirection {
fn into(self) -> ffi::pa_stream_direction_t {
self as ffi::pa_stream_direction_t
}
}
bitflags! {
pub struct StreamFlags : u32 {
const START_CORKED = ffi::PA_STREAM_START_CORKED;
const INTERPOLATE_TIMING = ffi::PA_STREAM_INTERPOLATE_TIMING;
const NOT_MONOTONIC = ffi::PA_STREAM_NOT_MONOTONIC;
const AUTO_TIMING_UPDATE = ffi::PA_STREAM_AUTO_TIMING_UPDATE;
const NO_REMAP_CHANNELS = ffi::PA_STREAM_NO_REMAP_CHANNELS;
const NO_REMIX_CHANNELS = ffi::PA_STREAM_NO_REMIX_CHANNELS;
const FIX_FORMAT = ffi::PA_STREAM_FIX_FORMAT;
const FIX_RATE = ffi::PA_STREAM_FIX_RATE;
const FIX_CHANNELS = ffi::PA_STREAM_FIX_CHANNELS;
const DONT_MOVE = ffi::PA_STREAM_DONT_MOVE;
const VARIABLE_RATE = ffi::PA_STREAM_VARIABLE_RATE;
const PEAK_DETECT = ffi::PA_STREAM_PEAK_DETECT;
const START_MUTED = ffi::PA_STREAM_START_MUTED;
const ADJUST_LATENCY = ffi::PA_STREAM_ADJUST_LATENCY;
const EARLY_REQUESTS = ffi::PA_STREAM_EARLY_REQUESTS;
const DONT_INHIBIT_AUTO_SUSPEND = ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND;
const START_UNMUTED = ffi::PA_STREAM_START_UNMUTED;
const FAIL_ON_SUSPEND = ffi::PA_STREAM_FAIL_ON_SUSPEND;
const RELATIVE_VOLUME = ffi::PA_STREAM_RELATIVE_VOLUME;
const PASSTHROUGH = ffi::PA_STREAM_PASSTHROUGH;
}
}
impl StreamFlags {
pub fn try_from(x: ffi::pa_stream_flags_t) -> Option<Self> {
if (x & !(ffi::PA_STREAM_NOFLAGS
| ffi::PA_STREAM_START_CORKED
| ffi::PA_STREAM_INTERPOLATE_TIMING
| ffi::PA_STREAM_NOT_MONOTONIC
| ffi::PA_STREAM_AUTO_TIMING_UPDATE
| ffi::PA_STREAM_NO_REMAP_CHANNELS
| ffi::PA_STREAM_NO_REMIX_CHANNELS
| ffi::PA_STREAM_FIX_FORMAT
| ffi::PA_STREAM_FIX_RATE
| ffi::PA_STREAM_FIX_CHANNELS
| ffi::PA_STREAM_DONT_MOVE
| ffi::PA_STREAM_VARIABLE_RATE
| ffi::PA_STREAM_PEAK_DETECT
| ffi::PA_STREAM_START_MUTED
| ffi::PA_STREAM_ADJUST_LATENCY
| ffi::PA_STREAM_EARLY_REQUESTS
| ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
| ffi::PA_STREAM_START_UNMUTED
| ffi::PA_STREAM_FAIL_ON_SUSPEND
| ffi::PA_STREAM_RELATIVE_VOLUME
| ffi::PA_STREAM_PASSTHROUGH))
== 0
{
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Into<ffi::pa_stream_flags_t> for StreamFlags {
fn into(self) -> ffi::pa_stream_flags_t {
self.bits() as ffi::pa_stream_flags_t
}
}
pub enum StreamLatency {
Positive(u64),
Negative(u64),
}
bitflags! {
pub struct SubscriptionMask : u32 {
const SINK = ffi::PA_SUBSCRIPTION_MASK_SINK;
const SOURCE = ffi::PA_SUBSCRIPTION_MASK_SOURCE;
const SINK_INPUT = ffi::PA_SUBSCRIPTION_MASK_SINK_INPUT;
const SOURCE_OUTPUT = ffi::PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT;
const MODULE = ffi::PA_SUBSCRIPTION_MASK_MODULE;
const CLIENT = ffi::PA_SUBSCRIPTION_MASK_CLIENT;
const SAMPLE_CACHE = ffi::PA_SUBSCRIPTION_MASK_SAMPLE_CACHE;
const SERVER = ffi::PA_SUBSCRIPTION_MASK_SERVER;
const AUTOLOAD = ffi::PA_SUBSCRIPTION_MASK_AUTOLOAD;
const CARD = ffi::PA_SUBSCRIPTION_MASK_CARD;
}
}
impl SubscriptionMask {
pub fn try_from(x: ffi::pa_subscription_mask_t) -> Option<Self> {
if (x & !ffi::PA_SUBSCRIPTION_MASK_ALL) == 0 {
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Into<ffi::pa_subscription_mask_t> for SubscriptionMask {
fn into(self) -> ffi::pa_subscription_mask_t {
self.bits() as ffi::pa_subscription_mask_t
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SubscriptionEventFacility {
Sink = ffi::PA_SUBSCRIPTION_EVENT_SINK,
Source = ffi::PA_SUBSCRIPTION_EVENT_SOURCE,
SinkInput = ffi::PA_SUBSCRIPTION_EVENT_SINK_INPUT,
SourceOutput = ffi::PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT,
Module = ffi::PA_SUBSCRIPTION_EVENT_MODULE,
Client = ffi::PA_SUBSCRIPTION_EVENT_CLIENT,
SampleCache = ffi::PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE,
Server = ffi::PA_SUBSCRIPTION_EVENT_SERVER,
Autoload = ffi::PA_SUBSCRIPTION_EVENT_AUTOLOAD,
Card = ffi::PA_SUBSCRIPTION_EVENT_CARD,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SubscriptionEventType {
New,
Change,
Remove,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct SubscriptionEvent(ffi::pa_subscription_event_type_t);
impl SubscriptionEvent {
pub fn try_from(x: ffi::pa_subscription_event_type_t) -> Option<Self> {
if (x & !(ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK | ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK))
== 0
{
Some(SubscriptionEvent(x))
} else {
None
}
}
pub fn event_facility(self) -> SubscriptionEventFacility {
unsafe { ::std::mem::transmute(self.0 & ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK) }
}
pub fn event_type(self) -> SubscriptionEventType {
unsafe { ::std::mem::transmute((self.0 & ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK) >> 4) }
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SeekMode {
Relative = ffi::PA_SEEK_RELATIVE,
Absolute = ffi::PA_SEEK_ABSOLUTE,
RelativeOnRead = ffi::PA_SEEK_RELATIVE_ON_READ,
RelativeEnd = ffi::PA_SEEK_RELATIVE_END,
}
impl SeekMode {
pub fn try_from(x: ffi::pa_seek_mode_t) -> Option<Self> {
if x >= ffi::PA_SEEK_RELATIVE && x <= ffi::PA_SEEK_RELATIVE_END {
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Into<ffi::pa_seek_mode_t> for SeekMode {
fn into(self) -> ffi::pa_seek_mode_t {
self as ffi::pa_seek_mode_t
}
}
bitflags! {
#[derive(Debug, Clone, Copy)]
pub struct SinkFlags: u32 {
const HW_VOLUME_CTRL = ffi::PA_SINK_HW_VOLUME_CTRL;
const LATENCY = ffi::PA_SINK_LATENCY;
const HARDWARE = ffi::PA_SINK_HARDWARE;
const NETWORK = ffi::PA_SINK_NETWORK;
const HW_MUTE_CTRL = ffi::PA_SINK_HW_MUTE_CTRL;
const DECIBEL_VOLUME = ffi::PA_SINK_DECIBEL_VOLUME;
const FLAT_VOLUME = ffi::PA_SINK_FLAT_VOLUME;
const DYNAMIC_LATENCY = ffi::PA_SINK_DYNAMIC_LATENCY;
const SET_FORMATS = ffi::PA_SINK_SET_FORMATS;
}
}
impl SinkFlags {
pub fn try_from(x: ffi::pa_sink_flags_t) -> Option<SinkFlags> {
if (x & !(ffi::PA_SINK_NOFLAGS
| ffi::PA_SINK_HW_VOLUME_CTRL
| ffi::PA_SINK_LATENCY
| ffi::PA_SINK_HARDWARE
| ffi::PA_SINK_NETWORK
| ffi::PA_SINK_HW_MUTE_CTRL
| ffi::PA_SINK_DECIBEL_VOLUME
| ffi::PA_SINK_DYNAMIC_LATENCY
| ffi::PA_SINK_FLAT_VOLUME
| ffi::PA_SINK_SET_FORMATS))
== 0
{
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SinkState {
InvalidState = ffi::PA_SINK_INVALID_STATE,
Running = ffi::PA_SINK_RUNNING,
Idle = ffi::PA_SINK_IDLE,
Suspended = ffi::PA_SINK_SUSPENDED,
Init = ffi::PA_SINK_INIT,
Unlinked = ffi::PA_SINK_UNLINKED,
}
bitflags! {
pub struct SourceFlags: u32 {
const HW_VOLUME_CTRL = ffi::PA_SOURCE_HW_VOLUME_CTRL;
const LATENCY = ffi::PA_SOURCE_LATENCY;
const HARDWARE = ffi::PA_SOURCE_HARDWARE;
const NETWORK = ffi::PA_SOURCE_NETWORK;
const HW_MUTE_CTRL = ffi::PA_SOURCE_HW_MUTE_CTRL;
const DECIBEL_VOLUME = ffi::PA_SOURCE_DECIBEL_VOLUME;
const DYNAMIC_LATENCY = ffi::PA_SOURCE_DYNAMIC_LATENCY;
const FLAT_VOLUME = ffi::PA_SOURCE_FLAT_VOLUME;
}
}
impl Into<ffi::pa_source_flags_t> for SourceFlags {
fn into(self) -> ffi::pa_source_flags_t {
self.bits() as ffi::pa_source_flags_t
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SourceState {
InvalidState = ffi::PA_SOURCE_INVALID_STATE,
Running = ffi::PA_SOURCE_RUNNING,
Idle = ffi::PA_SOURCE_IDLE,
Suspended = ffi::PA_SOURCE_SUSPENDED,
Init = ffi::PA_SOURCE_INIT,
Unlinked = ffi::PA_SOURCE_UNLINKED,
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PortAvailable {
Unknown = ffi::PA_PORT_AVAILABLE_UNKNOWN,
No = ffi::PA_PORT_AVAILABLE_NO,
Yes = ffi::PA_PORT_AVAILABLE_YES,
}
impl PortAvailable {
pub fn try_from(x: ffi::pa_port_available_t) -> Option<Self> {
if x >= ffi::PA_PORT_AVAILABLE_UNKNOWN && x <= ffi::PA_PORT_AVAILABLE_YES {
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Into<ffi::pa_port_available_t> for PortAvailable {
fn into(self) -> ffi::pa_port_available_t {
self as ffi::pa_port_available_t
}
}
#[repr(i32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ChannelPosition {
Invalid = ffi::PA_CHANNEL_POSITION_INVALID,
Mono = ffi::PA_CHANNEL_POSITION_MONO,
FrontLeft = ffi::PA_CHANNEL_POSITION_FRONT_LEFT,
FrontRight = ffi::PA_CHANNEL_POSITION_FRONT_RIGHT,
FrontCenter = ffi::PA_CHANNEL_POSITION_FRONT_CENTER,
RearCenter = ffi::PA_CHANNEL_POSITION_REAR_CENTER,
RearLeft = ffi::PA_CHANNEL_POSITION_REAR_LEFT,
RearRight = ffi::PA_CHANNEL_POSITION_REAR_RIGHT,
LowFreqEffects = ffi::PA_CHANNEL_POSITION_LFE,
FrontLeftOfCenter = ffi::PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
FrontRightOfCenter = ffi::PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
SideLeft = ffi::PA_CHANNEL_POSITION_SIDE_LEFT,
SideRight = ffi::PA_CHANNEL_POSITION_SIDE_RIGHT,
Aux0 = ffi::PA_CHANNEL_POSITION_AUX0,
Aux1 = ffi::PA_CHANNEL_POSITION_AUX1,
Aux2 = ffi::PA_CHANNEL_POSITION_AUX2,
Aux3 = ffi::PA_CHANNEL_POSITION_AUX3,
Aux4 = ffi::PA_CHANNEL_POSITION_AUX4,
Aux5 = ffi::PA_CHANNEL_POSITION_AUX5,
Aux6 = ffi::PA_CHANNEL_POSITION_AUX6,
Aux7 = ffi::PA_CHANNEL_POSITION_AUX7,
Aux8 = ffi::PA_CHANNEL_POSITION_AUX8,
Aux9 = ffi::PA_CHANNEL_POSITION_AUX9,
Aux10 = ffi::PA_CHANNEL_POSITION_AUX10,
Aux11 = ffi::PA_CHANNEL_POSITION_AUX11,
Aux12 = ffi::PA_CHANNEL_POSITION_AUX12,
Aux13 = ffi::PA_CHANNEL_POSITION_AUX13,
Aux14 = ffi::PA_CHANNEL_POSITION_AUX14,
Aux15 = ffi::PA_CHANNEL_POSITION_AUX15,
Aux16 = ffi::PA_CHANNEL_POSITION_AUX16,
Aux17 = ffi::PA_CHANNEL_POSITION_AUX17,
Aux18 = ffi::PA_CHANNEL_POSITION_AUX18,
Aux19 = ffi::PA_CHANNEL_POSITION_AUX19,
Aux20 = ffi::PA_CHANNEL_POSITION_AUX20,
Aux21 = ffi::PA_CHANNEL_POSITION_AUX21,
Aux22 = ffi::PA_CHANNEL_POSITION_AUX22,
Aux23 = ffi::PA_CHANNEL_POSITION_AUX23,
Aux24 = ffi::PA_CHANNEL_POSITION_AUX24,
Aux25 = ffi::PA_CHANNEL_POSITION_AUX25,
Aux26 = ffi::PA_CHANNEL_POSITION_AUX26,
Aux27 = ffi::PA_CHANNEL_POSITION_AUX27,
Aux28 = ffi::PA_CHANNEL_POSITION_AUX28,
Aux29 = ffi::PA_CHANNEL_POSITION_AUX29,
Aux30 = ffi::PA_CHANNEL_POSITION_AUX30,
Aux31 = ffi::PA_CHANNEL_POSITION_AUX31,
TopCenter = ffi::PA_CHANNEL_POSITION_TOP_CENTER,
TopFrontLeft = ffi::PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
TopFrontRight = ffi::PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
TopFrontCenter = ffi::PA_CHANNEL_POSITION_TOP_FRONT_CENTER,
TopRearLeft = ffi::PA_CHANNEL_POSITION_TOP_REAR_LEFT,
TopRearRight = ffi::PA_CHANNEL_POSITION_TOP_REAR_RIGHT,
TopRearCenter = ffi::PA_CHANNEL_POSITION_TOP_REAR_CENTER,
}
impl ChannelPosition {
pub fn try_from(x: ffi::pa_channel_position_t) -> Option<Self> {
if x >= ffi::PA_CHANNEL_POSITION_INVALID && x < ffi::PA_CHANNEL_POSITION_MAX {
Some(unsafe { ::std::mem::transmute(x) })
} else {
None
}
}
}
impl Default for ChannelPosition {
fn default() -> Self {
ChannelPosition::Invalid
}
}
impl Into<ffi::pa_channel_position_t> for ChannelPosition {
fn into(self) -> ffi::pa_channel_position_t {
self as ffi::pa_channel_position_t
}
}
pub type Result<T> = ::std::result::Result<T, error::ErrorCode>;
pub trait CVolumeExt {
fn set(&mut self, channels: c_uint, v: Volume);
fn set_balance(&mut self, map: &ChannelMap, new_balance: f32);
}
impl CVolumeExt for CVolume {
fn set(&mut self, channels: c_uint, v: Volume) {
unsafe {
ffi::pa_cvolume_set(self, channels, v);
}
}
fn set_balance(&mut self, map: &ChannelMap, new_balance: f32) {
unsafe {
ffi::pa_cvolume_set_balance(self, map, new_balance);
}
}
}
pub trait ChannelMapExt {
fn init() -> ChannelMap;
fn init_auto(ch: u32, def: ffi::pa_channel_map_def_t) -> Option<ChannelMap>;
fn can_balance(&self) -> bool;
}
impl ChannelMapExt for ChannelMap {
fn init() -> ChannelMap {
let mut cm = ChannelMap::default();
unsafe {
ffi::pa_channel_map_init(&mut cm);
}
cm
}
fn init_auto(ch: u32, def: ffi::pa_channel_map_def_t) -> Option<ChannelMap> {
let mut cm = ChannelMap::default();
let r: *mut ffi::pa_channel_map =
unsafe { ffi::pa_channel_map_init_auto(&mut cm, ch, def) };
if r.is_null() {
None
} else {
Some(cm)
}
}
fn can_balance(&self) -> bool {
unsafe { ffi::pa_channel_map_can_balance(self) > 0 }
}
}
pub trait ProplistExt {
fn proplist(&self) -> Proplist;
}
impl ProplistExt for SinkInfo {
fn proplist(&self) -> Proplist {
unsafe { proplist::from_raw_ptr(self.proplist) }
}
}
impl ProplistExt for SourceInfo {
fn proplist(&self) -> Proplist {
unsafe { proplist::from_raw_ptr(self.proplist) }
}
}
pub trait SampleSpecExt {
fn frame_size(&self) -> usize;
fn sample_size(&self) -> usize;
}
impl SampleSpecExt for SampleSpec {
fn frame_size(&self) -> usize {
unsafe { ffi::pa_frame_size(self) }
}
fn sample_size(&self) -> usize {
unsafe { ffi::pa_sample_size(self) }
}
}
pub trait USecExt {
fn to_bytes(self, spec: &SampleSpec) -> usize;
}
impl USecExt for USec {
fn to_bytes(self, spec: &SampleSpec) -> usize {
unsafe { ffi::pa_usec_to_bytes(self, spec) }
}
}
pub fn library_version() -> *const c_char {
unsafe { ffi::pa_get_library_version() }
}
pub fn sw_volume_from_linear(vol: f64) -> Volume {
unsafe { ffi::pa_sw_volume_from_linear(vol) }
}
pub fn rtclock_now() -> USec {
unsafe { ffi::pa_rtclock_now() }
}