Add ALSA widget (#18)
Add initial ALSA widget, and put both ALSA and PulseAudio behind feature flags.
This commit is contained in:
committed by
Kenny Levinsen
parent
4e9f0e566f
commit
1ae11bab29
Generated
+29
@@ -1,5 +1,25 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "alsa"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alsa-sys"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "andrew"
|
||||
version = "0.2.1"
|
||||
@@ -34,6 +54,11 @@ name = "autocfg"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.1.0"
|
||||
@@ -680,6 +705,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "wldash"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"alsa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -720,10 +746,13 @@ dependencies = [
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum alsa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe6a5e4eb4879d7cb8d19161927fbf825f0d89761776359c9cf4f9c9c2f35c52"
|
||||
"checksum alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0edcbbf9ef68f15ae1b620f722180b82a98b6f0628d30baa6b8d2a5abc87d58"
|
||||
"checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e"
|
||||
"checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
|
||||
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
|
||||
"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
|
||||
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
||||
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
||||
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||
"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
|
||||
|
||||
+7
-1
@@ -8,7 +8,11 @@ edition = "2018"
|
||||
lto = "fat"
|
||||
|
||||
[features]
|
||||
default = ["alsa-widget", "pulseaudio-widget"]
|
||||
damage_debug = []
|
||||
alsa-widget = ["alsa"]
|
||||
pulseaudio-widget = ["libpulse-binding"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
smithay-client-toolkit = "0.6.4"
|
||||
@@ -20,7 +24,6 @@ memmap = "0.7"
|
||||
os_pipe = "0.8"
|
||||
wayland-client = { version = "0.23", features = ["dlopen"] }
|
||||
wayland-protocols = { version = "0.23", features = ["client", "unstable_protocols"] }
|
||||
libpulse-binding = { version = "2.11"}
|
||||
dbus = "0.6"
|
||||
fuzzy-matcher = "0.2"
|
||||
lazy_static = "1.4"
|
||||
@@ -30,3 +33,6 @@ shlex = "0.1"
|
||||
serde_json = "1.0"
|
||||
serde_yaml = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
libpulse-binding = { version = "2.11", optional = true }
|
||||
alsa = { version = "0.3.0", optional = true }
|
||||
|
||||
+16
-1
@@ -48,10 +48,16 @@ pub enum Widget {
|
||||
font_size: f32,
|
||||
length: u32,
|
||||
},
|
||||
#[cfg(feature="pulseaudio-widget")]
|
||||
PulseAudio {
|
||||
font_size: f32,
|
||||
length: u32,
|
||||
},
|
||||
#[cfg(feature="alsa-widget")]
|
||||
AlsaSound {
|
||||
font_size: f32,
|
||||
length: u32
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget {
|
||||
@@ -121,8 +127,16 @@ impl Widget {
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
#[cfg(feature="pulseaudio-widget")]
|
||||
Widget::PulseAudio { font_size, length } => {
|
||||
match widgets::sound::PulseAudio::new(font_size, length, tx.clone()) {
|
||||
match widgets::audio::PulseAudio::new(font_size, length, tx.clone()) {
|
||||
Ok(w) => Some(w),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
#[cfg(feature="alsa-widget")]
|
||||
Widget::AlsaSound { font_size, length } => {
|
||||
match widgets::audio::Alsa::new(font_size, length) {
|
||||
Ok(w) => Some(w),
|
||||
Err(_) => None,
|
||||
}
|
||||
@@ -182,6 +196,7 @@ impl Default for Config {
|
||||
length: 600,
|
||||
}),
|
||||
}),
|
||||
#[cfg(feature="pulseaudio-widget")]
|
||||
Box::new(Widget::Margin {
|
||||
margins: (0, 0, 0, 8),
|
||||
widget: Box::new(Widget::PulseAudio {
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
|
||||
use crate::color::Color;
|
||||
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
||||
|
||||
use alsa::mixer::{ Mixer, Selem, SelemChannelId, SelemId };
|
||||
|
||||
const CARD_NAME: &'static str = "default";
|
||||
const SELEM_NAME: &'static str = "Master";
|
||||
const SELEM_ID: u32 = 0u32;
|
||||
|
||||
#[inline]
|
||||
fn alsa_error_to_io_error(fail: &'static str, err: &alsa::Error) -> ::std::io::Error {
|
||||
let kind = ::std::io::ErrorKind::Other;
|
||||
let func = err.func();
|
||||
let errno = err.errno().map(|errno| format!("; errno = {}", errno)).unwrap_or(String::new());
|
||||
return ::std::io::Error::new(kind, format!("{}: {}{}", fail, func, errno));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn alsa_volume_to_f32(volume: i64, min: i64, max: i64) -> f32 {
|
||||
(volume - min) as f32 / (max - min) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn f32_to_alsa_volume(volume: f32, min: i64, max: i64) -> i64 {
|
||||
min + ((max - min) as f32 * volume) as i64
|
||||
}
|
||||
|
||||
pub struct Alsa {
|
||||
pub mixer: Mixer,
|
||||
}
|
||||
|
||||
impl Alsa {
|
||||
pub fn new(font_size: f32, length: u32) -> ::std::io::Result<Box<BarWidget>> {
|
||||
let mixer = Mixer::new(CARD_NAME, true)
|
||||
.map_err(|err| alsa_error_to_io_error("Failed to create ALSA mixer", &err))?;
|
||||
let mixer = Self { mixer };
|
||||
mixer.get_master_volume()?; // probing
|
||||
Ok(BarWidget::new_simple(font_size, length, Box::new(mixer)))
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_master<'a>(&'a self) -> ::std::io::Result<Selem<'a>> {
|
||||
let master_id = SelemId::new(SELEM_NAME, SELEM_ID);
|
||||
match self.mixer.find_selem(&master_id) {
|
||||
Some(master) => Ok(master),
|
||||
None => {
|
||||
let kind = ::std::io::ErrorKind::NotFound;
|
||||
let desc = "`Master` not found";
|
||||
Err(::std::io::Error::new(kind, desc))
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn get_master_volume(&self) -> ::std::io::Result<f32> {
|
||||
self.get_master()
|
||||
.and_then(|master| {
|
||||
let (min, max) = master.get_playback_volume_range();
|
||||
master.get_playback_volume(SelemChannelId::mono())
|
||||
.map(|volume| alsa_volume_to_f32(volume, min, max))
|
||||
.map_err(|e| alsa_error_to_io_error("Failed to get `Master` volume", &e))
|
||||
})
|
||||
}
|
||||
pub fn set_master_volume(&self, volume: f32) -> ::std::io::Result<()> {
|
||||
self.get_master()
|
||||
.and_then(|master| {
|
||||
let (min, max) = master.get_playback_volume_range();
|
||||
let volume = f32_to_alsa_volume(volume, min, max);
|
||||
master.set_playback_volume_all(volume)
|
||||
.map_err(|e| alsa_error_to_io_error("Failed to set `Master` volume", &e))
|
||||
})
|
||||
}
|
||||
pub fn inc_master_volume(&self, diff: f32) -> ::std::io::Result<()> {
|
||||
self.get_master()
|
||||
.and_then(|master| {
|
||||
let (min, max) = master.get_playback_volume_range();
|
||||
master.get_playback_volume(SelemChannelId::mono())
|
||||
.and_then(|volume| {
|
||||
let volume = alsa_volume_to_f32(volume, min, max);
|
||||
let volume = f32_to_alsa_volume(volume + diff, min, max);
|
||||
master.set_playback_volume_all(volume)
|
||||
})
|
||||
.map_err(|e| alsa_error_to_io_error("Failed to inc/dec `Master` volume", &e))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl BarWidgetImpl for Alsa {
|
||||
fn name(&self) -> &str {
|
||||
"volume"
|
||||
}
|
||||
fn value(&self) -> f32 {
|
||||
match self.get_master_volume() {
|
||||
Ok(v) => v,
|
||||
Err(e) => panic!(e)
|
||||
}
|
||||
}
|
||||
fn color(&self) -> Color {
|
||||
Color::new(1.0, 1.0, 1.0, 1.0)
|
||||
}
|
||||
fn inc(&mut self, diff: f32) {
|
||||
if let Err(e) = self.inc_master_volume(diff) {
|
||||
panic!(e)
|
||||
}
|
||||
}
|
||||
fn set(&mut self, abs: f32) {
|
||||
if let Err(e) = self.set_master_volume(abs) {
|
||||
panic!(e)
|
||||
}
|
||||
}
|
||||
fn toggle(&mut self) {}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
#[cfg(feature="alsa-widget")]
|
||||
mod alsa_sound;
|
||||
#[cfg(feature="alsa-widget")]
|
||||
pub use alsa_sound::Alsa;
|
||||
|
||||
#[cfg(feature="pulseaudio-widget")]
|
||||
mod pulse_sound;
|
||||
#[cfg(feature="pulseaudio-widget")]
|
||||
pub use pulse_sound::PulseAudio;
|
||||
|
||||
+3
-1
@@ -5,4 +5,6 @@ pub mod calendar;
|
||||
pub mod clock;
|
||||
pub mod date;
|
||||
pub mod launcher;
|
||||
pub mod sound;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub mod audio;
|
||||
|
||||
Reference in New Issue
Block a user