diff options
Diffstat (limited to 'src/pa_eq/mod.rs')
-rw-r--r-- | src/pa_eq/mod.rs | 112 |
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 @@ | |||
1 | mod dbus_api; | ||
2 | |||
3 | use Filter; | ||
4 | use cli::pa_eq::*; | ||
5 | use utils::*; | ||
6 | |||
7 | use self::dbus_api::equalizing_manager::OrgPulseAudioExtEqualizing1Manager; | ||
8 | use self::dbus_api::server_lookup::OrgPulseAudioServerLookup1; | ||
9 | use self::dbus_api::sink::OrgPulseAudioExtEqualizing1Equalizer; | ||
10 | |||
11 | use dbus::{BusType, ConnPath, Connection}; | ||
12 | |||
13 | use failure::{Error, ResultExt}; | ||
14 | |||
15 | #[derive(Fail, Debug)] | ||
16 | #[fail(display = "No equalized sink found")] | ||
17 | struct NoEqualizedSink; | ||
18 | |||
19 | pub 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 | |||
30 | pub 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 | |||
45 | pub 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 | |||
57 | fn 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 | |||
63 | fn 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 | |||
71 | fn 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 | |||
77 | fn 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 | |||
92 | fn 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 | |||
105 | fn 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 | } | ||