use std;
use capi;
use std::ffi::CStr;
use std::ptr::null;
pub const VOLUME_NORM: Volume = Volume(capi::PA_VOLUME_NORM);
pub const VOLUME_MUTED: Volume = Volume(capi::PA_VOLUME_MUTED);
pub const VOLUME_MAX: Volume = Volume(capi::PA_VOLUME_MAX);
pub const VOLUME_INVALID: Volume = Volume(capi::PA_VOLUME_INVALID);
pub const DECIBEL_MINUS_INFINITY: VolumeDB = VolumeDB(capi::PA_DECIBEL_MININFTY);
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Volume(pub capi::pa_volume_t);
impl Default for Volume {
fn default() -> Self { VOLUME_NORM }
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct VolumeDB(pub f64);
impl Default for VolumeDB {
fn default() -> Self { VolumeDB(0.0) }
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct VolumeLinear(pub f64);
impl Default for VolumeLinear {
fn default() -> Self { VolumeLinear(0.0) }
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct ChannelVolumes {
pub channels: u8,
pub values: [Volume; ::sample::CHANNELS_MAX],
}
impl PartialEq for ChannelVolumes {
fn eq(&self, other: &Self) -> bool {
match self.channels == other.channels {
true => self.values[..self.channels as usize] == other.values[..other.channels as usize],
false => false,
}
}
}
impl From<VolumeDB> for Volume {
fn from(v: VolumeDB) -> Self {
Volume(unsafe { capi::pa_sw_volume_from_dB(v.0) })
}
}
impl From<Volume> for VolumeDB {
fn from(v: Volume) -> Self {
VolumeDB(unsafe { capi::pa_sw_volume_to_dB(v.0) })
}
}
impl From<VolumeLinear> for Volume {
fn from(v: VolumeLinear) -> Self {
Volume(unsafe { capi::pa_sw_volume_from_linear(v.0) })
}
}
impl From<Volume> for VolumeLinear {
fn from(v: Volume) -> Self {
VolumeLinear(unsafe { capi::pa_sw_volume_to_linear(v.0) })
}
}
impl From<VolumeLinear> for VolumeDB {
fn from(v: VolumeLinear) -> Self {
VolumeDB::from(Volume::from(v))
}
}
impl From<VolumeDB> for VolumeLinear {
fn from(v: VolumeDB) -> Self {
VolumeLinear::from(Volume::from(v))
}
}
impl VolumeLinear {
pub fn is_muted(&self) -> bool {
self.0 <= 0.0
}
pub fn is_normal(&self) -> bool {
self.0 == 1.0
}
}
impl Volume {
pub fn is_muted(&self) -> bool {
*self == VOLUME_MUTED
}
pub fn is_normal(&self) -> bool {
*self == VOLUME_NORM
}
pub fn is_max(&self) -> bool {
*self == VOLUME_MAX
}
pub fn ui_max() -> Self {
Volume(capi::pa_volume_ui_max())
}
pub fn is_valid(&self) -> bool {
capi::pa_volume_is_valid(self.0)
}
pub fn clamp(&mut self) {
self.0 = capi::pa_clamp_volume(self.0)
}
pub fn multiply(a: Self, b: Self) -> Self {
Volume(unsafe { capi::pa_sw_volume_multiply(a.0, b.0) })
}
pub fn divide(a: Self, b: Self) -> Self {
Volume(unsafe { capi::pa_sw_volume_divide(a.0, b.0) })
}
pub fn print(&self) -> String {
const PRINT_MAX: usize = capi::PA_VOLUME_SNPRINT_MAX;
let mut tmp = Vec::with_capacity(PRINT_MAX);
unsafe {
capi::pa_volume_snprint(tmp.as_mut_ptr(), PRINT_MAX, self.0);
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
pub fn print_db(&self) -> String {
const PRINT_DB_MAX: usize = capi::PA_SW_VOLUME_SNPRINT_DB_MAX;
let mut tmp = Vec::with_capacity(PRINT_DB_MAX);
unsafe {
capi::pa_sw_volume_snprint_dB(tmp.as_mut_ptr(), PRINT_DB_MAX, self.0);
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
pub fn print_verbose(&self, print_db: bool) -> String {
const PRINT_VERBOSE_MAX: usize = capi::PA_VOLUME_SNPRINT_VERBOSE_MAX;
let mut tmp = Vec::with_capacity(PRINT_VERBOSE_MAX);
unsafe {
capi::pa_volume_snprint_verbose(tmp.as_mut_ptr(), PRINT_VERBOSE_MAX, self.0,
print_db as i32);
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
}
impl std::fmt::Display for Volume {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", &self.print())
}
}
impl ChannelVolumes {
pub fn init(&mut self) -> &Self {
unsafe { capi::pa_cvolume_init(std::mem::transmute(&self)) };
self
}
pub fn set(&mut self, channels: u32, v: Volume) -> &Self {
unsafe { capi::pa_cvolume_set(std::mem::transmute(&self), channels, v.0) };
self
}
pub fn reset(&mut self, channels: u32) -> &Self {
self.set(channels, VOLUME_NORM)
}
pub fn mute(&mut self, channels: u32) -> &Self {
self.set(channels, VOLUME_MUTED)
}
pub fn equal_to(&self, to: &Self) -> bool {
unsafe { capi::pa_cvolume_equal(std::mem::transmute(self), std::mem::transmute(to)) != 0 }
}
pub fn is_muted(&self) -> bool {
self.channels_equal_to(VOLUME_MUTED)
}
pub fn is_norm(&self) -> bool {
self.channels_equal_to(VOLUME_NORM)
}
pub fn avg(&self) -> Volume {
Volume(unsafe { capi::pa_cvolume_avg(std::mem::transmute(self)) })
}
pub fn avg_mask(&self, cm: &::channelmap::Map, mask: Option<::channelmap::PositionMask>
) -> Volume
{
let mask_actual = mask.unwrap_or(::channelmap::POSITION_MASK_ALL);
Volume(unsafe { capi::pa_cvolume_avg_mask(std::mem::transmute(self),
std::mem::transmute(cm), mask_actual) })
}
pub fn max(&self) -> Volume {
Volume(unsafe { capi::pa_cvolume_max(std::mem::transmute(self)) })
}
pub fn max_mask(&self, cm: &::channelmap::Map, mask: Option<::channelmap::PositionMask>
) -> Volume
{
let mask_actual = mask.unwrap_or(::channelmap::POSITION_MASK_ALL);
Volume(unsafe { capi::pa_cvolume_max_mask(std::mem::transmute(self),
std::mem::transmute(cm), mask_actual) })
}
pub fn min(&self) -> Volume {
Volume(unsafe { capi::pa_cvolume_min(std::mem::transmute(self)) })
}
pub fn min_mask(&self, cm: &::channelmap::Map, mask: Option<::channelmap::PositionMask>
) -> Volume
{
let mask_actual = mask.unwrap_or(::channelmap::POSITION_MASK_ALL);
Volume(unsafe { capi::pa_cvolume_min_mask(std::mem::transmute(self),
std::mem::transmute(cm), mask_actual) })
}
pub fn is_valid(&self) -> bool {
unsafe { capi::pa_cvolume_valid(std::mem::transmute(self)) != 0 }
}
pub fn channels_equal_to(&self, v: Volume) -> bool {
unsafe { capi::pa_cvolume_channels_equal_to(std::mem::transmute(self), v.0) != 0 }
}
pub fn sw_multiply(&mut self, with: Option<&Self>) -> &mut Self {
match with {
Some(with) => unsafe {
capi::pa_sw_cvolume_multiply(std::mem::transmute(&self), std::mem::transmute(&self),
std::mem::transmute(with))
},
None => unsafe {
capi::pa_sw_cvolume_multiply(std::mem::transmute(&self), std::mem::transmute(&self),
std::mem::transmute(&self))
},
};
self
}
pub fn sw_multiply_scalar(&mut self, with: Volume) -> &mut Self {
unsafe { capi::pa_sw_cvolume_multiply_scalar(std::mem::transmute(&self),
std::mem::transmute(&self), with.0) };
self
}
pub fn sw_divide(&mut self, with: Option<&Self>) -> &mut Self {
match with {
Some(with) => unsafe {
capi::pa_sw_cvolume_divide(std::mem::transmute(&self), std::mem::transmute(&self),
std::mem::transmute(with))
},
None => unsafe {
capi::pa_sw_cvolume_divide(std::mem::transmute(&self), std::mem::transmute(&self),
std::mem::transmute(&self))
},
};
self
}
pub fn sw_divide_scalar(&mut self, with: Volume) -> &mut Self {
unsafe { capi::pa_sw_cvolume_divide_scalar(std::mem::transmute(&self),
std::mem::transmute(&self), with.0) };
self
}
pub fn remap(&mut self, from: &::channelmap::Map, to: &::channelmap::Map) -> &mut Self {
unsafe { capi::pa_cvolume_remap(std::mem::transmute(&self),
std::mem::transmute(from), std::mem::transmute(to)) };
self
}
pub fn is_compatible_with_ss(&self, ss: &::sample::Spec) -> bool {
unsafe { capi::pa_cvolume_compatible(std::mem::transmute(self),
std::mem::transmute(ss)) != 0 }
}
pub fn is_compatible_with_cm(&self, cm: &::channelmap::Map) -> bool {
unsafe { capi::pa_cvolume_compatible_with_channel_map(std::mem::transmute(self),
std::mem::transmute(cm)) != 0 }
}
pub fn get_balance(&self, map: &::channelmap::Map) -> f32 {
unsafe { capi::pa_cvolume_get_balance(std::mem::transmute(self), std::mem::transmute(map)) }
}
pub fn set_balance(&mut self, map: &::channelmap::Map, new_balance: f32) -> Option<&mut Self> {
let ptr = unsafe { capi::pa_cvolume_set_balance(std::mem::transmute(&self),
std::mem::transmute(map), new_balance) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn get_fade(&self, map: &::channelmap::Map) -> f32 {
unsafe { capi::pa_cvolume_get_fade(std::mem::transmute(self), std::mem::transmute(map)) }
}
pub fn set_fade(&mut self, map: &::channelmap::Map, new_fade: f32) -> Option<&mut Self>{
let ptr = unsafe { capi::pa_cvolume_set_fade(std::mem::transmute(&self),
std::mem::transmute(map), new_fade) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn get_lfe_balance(&self, map: &::channelmap::Map) -> f32 {
unsafe { capi::pa_cvolume_get_lfe_balance(std::mem::transmute(self),
std::mem::transmute(map)) }
}
pub fn set_lfe_balance(&mut self, map: &::channelmap::Map, new_balance: f32
) -> Option<&mut Self>
{
let ptr = unsafe { capi::pa_cvolume_set_lfe_balance(std::mem::transmute(&self),
std::mem::transmute(map), new_balance) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn scale(&mut self, max: Volume) -> Option<&mut Self> {
let ptr = unsafe { capi::pa_cvolume_scale(std::mem::transmute(&self), max.0) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn scale_mask(&mut self, max: Volume, cm: &mut ::channelmap::Map,
mask: Option<::channelmap::PositionMask>) -> Option<&mut Self>
{
let mask_actual = mask.unwrap_or(::channelmap::POSITION_MASK_ALL);
let ptr = unsafe { capi::pa_cvolume_scale_mask(std::mem::transmute(&self), max.0,
std::mem::transmute(cm), mask_actual) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn set_position(&mut self, map: &::channelmap::Map, t: ::channelmap::Position, v: Volume
) -> Option<&mut Self>
{
let ptr = unsafe { capi::pa_cvolume_set_position(std::mem::transmute(&self),
std::mem::transmute(map), t.into(), v.0) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn get_position(&self, map: &::channelmap::Map, t: ::channelmap::Position) -> Volume {
Volume(unsafe { capi::pa_cvolume_get_position(std::mem::transmute(self),
std::mem::transmute(map), t.into()) })
}
pub fn merge(&mut self, with: &Self) -> Option<&mut Self> {
let ptr = unsafe { capi::pa_cvolume_merge(std::mem::transmute(&self),
std::mem::transmute(&self), std::mem::transmute(with)) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn inc_clamp(&mut self, inc: Volume, limit: Volume) -> Option<&mut Self> {
let ptr = unsafe { capi::pa_cvolume_inc_clamp(std::mem::transmute(&self), inc.0, limit.0) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn increase(&mut self, inc: Volume) -> Option<&mut Self> {
let ptr = unsafe { capi::pa_cvolume_inc(std::mem::transmute(&self), inc.0) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn decrease(&mut self, dec: Volume) -> Option<&mut Self> {
let ptr = unsafe { capi::pa_cvolume_dec(std::mem::transmute(&self), dec.0) };
if ptr.is_null() {
return None;
}
Some(self)
}
pub fn print(&self) -> String {
const PRINT_MAX: usize = capi::PA_CVOLUME_SNPRINT_MAX;
let mut tmp = Vec::with_capacity(PRINT_MAX);
unsafe {
capi::pa_cvolume_snprint(tmp.as_mut_ptr(), PRINT_MAX, std::mem::transmute(self));
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
pub fn print_db(&self) -> String {
const PRINT_DB_MAX: usize = capi::PA_SW_CVOLUME_SNPRINT_DB_MAX;
let mut tmp = Vec::with_capacity(PRINT_DB_MAX);
unsafe {
capi::pa_sw_cvolume_snprint_dB(tmp.as_mut_ptr(), PRINT_DB_MAX,
std::mem::transmute(self));
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
pub fn print_verbose(&self, map: Option<&::channelmap::Map>, print_db: bool) -> String {
const PRINT_VERBOSE_MAX: usize = capi::PA_CVOLUME_SNPRINT_VERBOSE_MAX;
let p_map: *const capi::pa_channel_map = match map {
Some(map) => unsafe { std::mem::transmute(map) },
None => null::<capi::pa_channel_map>(),
};
let mut tmp = Vec::with_capacity(PRINT_VERBOSE_MAX);
unsafe {
capi::pa_cvolume_snprint_verbose(tmp.as_mut_ptr(), PRINT_VERBOSE_MAX,
std::mem::transmute(self), p_map, print_db as i32);
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
}
impl std::fmt::Display for ChannelVolumes {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", &self.print())
}
}