diff options
Diffstat (limited to 'src/pa_eq.rs')
-rw-r--r-- | src/pa_eq.rs | 110 |
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 @@ | |||
1 | use Filter; | ||
2 | use cli::pa_eq::*; | ||
3 | use utils::*; | ||
4 | |||
5 | use dbus_api::equalizing_manager::OrgPulseAudioExtEqualizing1Manager; | ||
6 | use dbus_api::server_lookup::OrgPulseAudioServerLookup1; | ||
7 | use dbus_api::sink::OrgPulseAudioExtEqualizing1Equalizer; | ||
8 | |||
9 | use dbus::{BusType, ConnPath, Connection}; | ||
10 | |||
11 | use failure::{Error, ResultExt}; | ||
12 | |||
13 | #[derive(Fail, Debug)] | ||
14 | #[fail(display = "No equalized sink found")] | ||
15 | struct NoEqualizedSink; | ||
16 | |||
17 | pub 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 | |||
28 | pub 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 | |||
43 | pub 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 | |||
55 | fn 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 | |||
61 | fn 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 | |||
69 | fn 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 | |||
75 | fn 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 | |||
90 | fn 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 | |||
103 | fn 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 | } | ||