summaryrefslogtreecommitdiffstats
path: root/src/pa_eq/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/pa_eq/mod.rs')
-rw-r--r--src/pa_eq/mod.rs112
1 files changed, 112 insertions, 0 deletions
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 @@
1mod dbus_api;
2
3use Filter;
4use cli::pa_eq::*;
5use utils::*;
6
7use self::dbus_api::equalizing_manager::OrgPulseAudioExtEqualizing1Manager;
8use self::dbus_api::server_lookup::OrgPulseAudioServerLookup1;
9use self::dbus_api::sink::OrgPulseAudioExtEqualizing1Equalizer;
10
11use dbus::{BusType, ConnPath, Connection};
12
13use failure::{Error, ResultExt};
14
15#[derive(Fail, Debug)]
16#[fail(display = "No equalized sink found")]
17struct NoEqualizedSink;
18
19pub fn main(cmd: Command) -> Result<(), Error> {
20 use cli::pa_eq::Command::*;
21
22 warn!("The PulseAudio equalizer has been deprecated for a while, and is known to sometimes cause crashes, latency or audible artifacts");
23
24 match cmd {
25 Load(args) => load(args),
26 Reset(args) => reset(args),
27 }
28}
29
30pub fn reset(_args: ResetCli) -> Result<(), Error> {
31 let conn = connect()?;
32 let conn_sink = get_equalized_sink(&conn)?;
33 let filter_rate = conn_sink.get_filter_sample_rate()?;
34 let filter = Filter {
35 preamp: 1f64,
36 frequencies: vec![],
37 coefficients: vec![],
38 }.pad(filter_rate);
39
40 send_filter(&conn_sink, filter)?;
41
42 Ok(())
43}
44
45pub fn load(args: LoadCli) -> Result<(), Error> {
46 let conn = connect()?;
47 let conn_sink = get_equalized_sink(&conn)?;
48
49 let filter = read_filter_from_arg(&args.file)?;
50
51 let filter_rate = conn_sink.get_filter_sample_rate()?;
52 send_filter(&conn_sink, filter.pad(filter_rate))?;
53
54 Ok(())
55}
56
57fn connect() -> Result<Connection, Error> {
58 Ok(connect_impl().context(
59 "Could not connect to PulseAudio's D-Bus socket. Have you loaded the 'module-dbus-protocol' module?"
60 )?)
61}
62
63fn connect_impl() -> Result<Connection, Error> {
64 let pulse_sock_path = get_pulse_dbus_sock()?;
65 info!("PulseAudio's D-Bus socket path is: {}", pulse_sock_path);
66
67 trace!("Connecting to PulseAudio's D-Bus socket");
68 Ok(Connection::open_private(&pulse_sock_path)?)
69}
70
71fn get_equalized_sink<'a>(conn: &'a Connection) -> Result<ConnPath<'a, &'a Connection>, Error> {
72 Ok(get_equalized_sink_impl(conn).context(
73 "Could not find an equalized sink. Have you loaded the 'module-equalizer-sink' module?",
74 )?)
75}
76
77fn get_equalized_sink_impl<'a>(
78 conn: &'a Connection,
79) -> Result<ConnPath<'a, &'a Connection>, Error> {
80 let conn_manager = conn.with_path("org.PulseAudio.Core1", "/org/pulseaudio/equalizing1", 2000);
81
82 // TODO: make that a command-line option
83 trace!("Getting (one of) the equalized sink(s)");
84 let mut sinks = conn_manager.get_equalized_sinks()?;
85 let sink_path = sinks.pop().ok_or(NoEqualizedSink {})?;
86 info!("Using equalized sink: {:?}", sink_path.as_cstr());
87
88 trace!("Connecting to equalized sink");
89 Ok(conn.with_path("org.PulseAudio.Core1", sink_path, 2000))
90}
91
92fn send_filter(conn_sink: &ConnPath<&Connection>, filter: Filter) -> Result<(), Error> {
93 let channel = conn_sink.get_nchannels()?;
94 info!("Using channel: {}", channel);
95 trace!("Sending filter: {:?}", filter);
96 conn_sink.seed_filter(
97 channel,
98 filter.frequencies,
99 filter.coefficients.into_iter().map(decibel_to_ratio).collect(),
100 decibel_to_ratio(filter.preamp),
101 )?;
102 Ok(())
103}
104
105fn get_pulse_dbus_sock() -> Result<String, Error> {
106 trace!("Connecting to the D-Bus' session bus");
107 let conn = Connection::get_private(BusType::Session)?;
108 let conn = conn.with_path("org.PulseAudio1", "/org/pulseaudio/server_lookup1", 2000);
109
110 trace!("Checking PulseAudio's D-Bus socket path");
111 Ok(conn.get_address()?)
112}