From d35f0c9ee105f8c789827d6f5c740154f7b9b1bc Mon Sep 17 00:00:00 2001 From: Minijackson Date: Mon, 8 Oct 2018 15:41:46 +0200 Subject: Use features to separate pa_eq and pa_effects + slightly better logging --- src/pa_eq/mod.rs | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/pa_eq/mod.rs (limited to 'src/pa_eq/mod.rs') diff --git a/src/pa_eq/mod.rs b/src/pa_eq/mod.rs new file mode 100644 index 0000000..f7f1875 --- /dev/null +++ b/src/pa_eq/mod.rs @@ -0,0 +1,112 @@ +mod dbus_api; + +use Filter; +use cli::pa_eq::*; +use utils::*; + +use self::dbus_api::equalizing_manager::OrgPulseAudioExtEqualizing1Manager; +use self::dbus_api::server_lookup::OrgPulseAudioServerLookup1; +use self::dbus_api::sink::OrgPulseAudioExtEqualizing1Equalizer; + +use dbus::{BusType, ConnPath, Connection}; + +use failure::{Error, ResultExt}; + +#[derive(Fail, Debug)] +#[fail(display = "No equalized sink found")] +struct NoEqualizedSink; + +pub fn main(cmd: Command) -> Result<(), Error> { + use cli::pa_eq::Command::*; + + warn!("The PulseAudio equalizer has been deprecated for a while, and is known to sometimes cause crashes, latency or audible artifacts"); + + match cmd { + Load(args) => load(args), + Reset(args) => reset(args), + } +} + +pub fn reset(_args: ResetCli) -> Result<(), Error> { + let conn = connect()?; + let conn_sink = get_equalized_sink(&conn)?; + let filter_rate = conn_sink.get_filter_sample_rate()?; + let filter = Filter { + preamp: 1f64, + frequencies: vec![], + coefficients: vec![], + }.pad(filter_rate); + + send_filter(&conn_sink, filter)?; + + Ok(()) +} + +pub fn load(args: LoadCli) -> Result<(), Error> { + let conn = connect()?; + let conn_sink = get_equalized_sink(&conn)?; + + let filter = read_filter_from_arg(&args.file)?; + + let filter_rate = conn_sink.get_filter_sample_rate()?; + send_filter(&conn_sink, filter.pad(filter_rate))?; + + Ok(()) +} + +fn connect() -> Result { + Ok(connect_impl().context( + "Could not connect to PulseAudio's D-Bus socket. Have you loaded the 'module-dbus-protocol' module?" + )?) +} + +fn connect_impl() -> Result { + let pulse_sock_path = get_pulse_dbus_sock()?; + info!("PulseAudio's D-Bus socket path is: {}", pulse_sock_path); + + trace!("Connecting to PulseAudio's D-Bus socket"); + Ok(Connection::open_private(&pulse_sock_path)?) +} + +fn get_equalized_sink<'a>(conn: &'a Connection) -> Result, Error> { + Ok(get_equalized_sink_impl(conn).context( + "Could not find an equalized sink. Have you loaded the 'module-equalizer-sink' module?", + )?) +} + +fn get_equalized_sink_impl<'a>( + conn: &'a Connection, +) -> Result, Error> { + let conn_manager = conn.with_path("org.PulseAudio.Core1", "/org/pulseaudio/equalizing1", 2000); + + // TODO: make that a command-line option + trace!("Getting (one of) the equalized sink(s)"); + let mut sinks = conn_manager.get_equalized_sinks()?; + let sink_path = sinks.pop().ok_or(NoEqualizedSink {})?; + info!("Using equalized sink: {:?}", sink_path.as_cstr()); + + trace!("Connecting to equalized sink"); + Ok(conn.with_path("org.PulseAudio.Core1", sink_path, 2000)) +} + +fn send_filter(conn_sink: &ConnPath<&Connection>, filter: Filter) -> Result<(), Error> { + let channel = conn_sink.get_nchannels()?; + info!("Using channel: {}", channel); + trace!("Sending filter: {:?}", filter); + conn_sink.seed_filter( + channel, + filter.frequencies, + filter.coefficients.into_iter().map(decibel_to_ratio).collect(), + decibel_to_ratio(filter.preamp), + )?; + Ok(()) +} + +fn get_pulse_dbus_sock() -> Result { + trace!("Connecting to the D-Bus' session bus"); + let conn = Connection::get_private(BusType::Session)?; + let conn = conn.with_path("org.PulseAudio1", "/org/pulseaudio/server_lookup1", 2000); + + trace!("Checking PulseAudio's D-Bus socket path"); + Ok(conn.get_address()?) +} -- cgit v1.2.3