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