Skip to content

Commit fe54ad1

Browse files
committed
Add the ability to query the daemon to retrieve information about the current status
1 parent 19b4f9a commit fe54ad1

File tree

6 files changed

+108
-31
lines changed

6 files changed

+108
-31
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backlight_ipc/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,21 @@ pub enum BacklightMode {
1313
Manual,
1414
}
1515

16+
#[derive(Serialize, Deserialize, Debug)]
17+
pub struct BacklightInfo {
18+
pub brightness_percent: u8,
19+
}
20+
1621
#[derive(Serialize, Deserialize, Debug)]
1722
pub enum BacklightCommand {
1823
SetBrightness(u8),
1924
IncreaseBrightness(u8),
2025
DecreaseBrightness(u8),
2126
Refresh,
2227
SetMode(BacklightMode),
28+
GetInfo,
29+
GetInfoResponse(BacklightInfo),
30+
NotifyShutdown,
2331
}
2432

2533
// The following abstraction allow us to easily change the protocol if need be.

backlightctl/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ edition = "2021"
66
[dependencies]
77
clap = { version = "4.5.21", features = ["derive"] }
88
backlight_ipc = { path = "../backlight_ipc" }
9+
serde_json = "1.0"

backlightctl/src/main.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ struct BacklightctlCli {
2222
/// UNIX socket path (for test purposes)
2323
#[clap(short, long, default_value = DEFAULT_UNIX_SOCKET_PATH)]
2424
unix_socket_path: PathBuf,
25+
26+
/// Output will be JSON
27+
#[clap(long, default_value_t = false)]
28+
json: bool,
2529
}
2630

2731
fn main() {
@@ -167,4 +171,40 @@ fn main() {
167171
exit(1);
168172
}
169173
}
174+
175+
if let Err(err) = BacklightCommand::GetInfo.serialize_into(&stream) {
176+
eprintln!("{err}");
177+
exit(1);
178+
}
179+
180+
let backlight_info = match BacklightCommand::deserialize_from(&stream) {
181+
Ok(BacklightCommand::GetInfoResponse(info)) => info,
182+
Ok(cmd) => {
183+
eprintln!("Unexpected response: {cmd:?}");
184+
exit(1);
185+
}
186+
Err(err) => {
187+
eprintln!("{err}");
188+
exit(1);
189+
}
190+
};
191+
192+
if cli.json {
193+
match serde_json::to_string(&backlight_info) {
194+
Ok(backlight_info_json) => {
195+
println!("{backlight_info_json}");
196+
}
197+
Err(err) => {
198+
eprintln!("Cannot serialize GetInfoResponse to json: {err}");
199+
exit(1);
200+
}
201+
}
202+
} else {
203+
println!("Current brightness: {}%", backlight_info.brightness_percent);
204+
}
205+
206+
if let Err(err) = BacklightCommand::NotifyShutdown.serialize_into(&stream) {
207+
eprintln!("{err}");
208+
exit(1);
209+
}
170210
}

backlightd/src/main.rs

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
use std::{
22
env,
3-
fs::remove_file,
3+
fs::{self, remove_file},
44
io,
5-
os::unix::net::UnixListener,
5+
os::unix::{
6+
fs::PermissionsExt,
7+
net::{UnixListener, UnixStream},
8+
},
69
process::exit,
7-
sync::mpsc::{channel, Receiver, Sender},
10+
sync::mpsc::{channel, Sender},
811
thread,
912
};
1013

14+
use anyhow::bail;
1115
use auto::auto_adjust;
12-
use backlight_ipc::{BacklightCommand, BacklightMode, DEFAULT_UNIX_SOCKET_PATH};
13-
use log::error;
16+
use backlight_ipc::{BacklightCommand, BacklightInfo, BacklightMode, DEFAULT_UNIX_SOCKET_PATH};
1417
use monitors::auto_refresh_monitors_list;
1518

1619
mod acpi;
@@ -19,14 +22,16 @@ mod ddc;
1922
mod location;
2023
mod monitors;
2124

22-
fn handle_commands(
23-
cmd_receiver: Receiver<BacklightCommand>,
25+
fn handle_client(
26+
client: UnixStream,
2427
auto_adjust_sender: Sender<BacklightMode>,
25-
) -> ! {
28+
) -> anyhow::Result<()> {
2629
loop {
27-
let command = cmd_receiver
28-
.recv()
29-
.expect("Failed to receive command from cmd channel");
30+
let command = match BacklightCommand::deserialize_from(&client) {
31+
Ok(cmd) => cmd,
32+
Err(err) => bail!("Unable to deserialize command: {err}"),
33+
};
34+
3035
let result = match command {
3136
BacklightCommand::SetBrightness(percent) => {
3237
auto_adjust_sender
@@ -54,22 +59,38 @@ fn handle_commands(
5459
auto_adjust_sender
5560
.send(backlight_mode)
5661
.unwrap_or_else(|err| {
57-
error!("Failed to send mode to auto adjust channel: {err}")
62+
log::error!("Failed to send mode to auto adjust channel: {err}")
5863
});
5964
Ok(())
6065
}
66+
BacklightCommand::GetInfo => {
67+
BacklightCommand::GetInfoResponse(BacklightInfo {
68+
brightness_percent: monitors::get_average_brightness(),
69+
})
70+
.serialize_into(&client)
71+
.unwrap_or_else(|err| log::error!("Unable to serialize GetInfoResponse: {err}"));
72+
Ok(())
73+
}
74+
BacklightCommand::GetInfoResponse(_) => {
75+
log::warn!("Got GetInfoResponse from client, API misuse ?");
76+
Ok(())
77+
}
78+
BacklightCommand::NotifyShutdown => break,
6179
};
6280

6381
if let Err(err) = result {
64-
error!("Command handling failed: {err}");
82+
log::error!("Command handling failed: {err}");
6583
}
6684
}
85+
86+
Ok(())
6787
}
6888

6989
fn main() {
7090
pretty_env_logger::formatted_builder()
7191
.filter_level(log::LevelFilter::Info)
7292
.parse_env("BACKLIGHTD_LOG_LEVEL")
93+
.filter_module("ureq", log::LevelFilter::Warn)
7394
.init();
7495

7596
let args: Vec<String> = env::args().collect();
@@ -90,54 +111,49 @@ fn main() {
90111

91112
if let Err(err) = remove_file(unix_socket_path) {
92113
if !matches!(err.kind(), io::ErrorKind::NotFound) {
93-
error!("{unix_socket_path}: {err}");
114+
log::error!("{unix_socket_path}: {err}");
94115
exit(1);
95116
}
96117
}
97118

98119
let listener = match UnixListener::bind(unix_socket_path) {
99120
Ok(listener) => listener,
100121
Err(err) => {
101-
error!("{unix_socket_path}: {err}");
122+
log::error!("{unix_socket_path}: {err}");
102123
exit(1);
103124
}
104125
};
105126

106-
let (cmd_sender, cmd_receiver) = channel();
127+
if let Err(err) = fs::set_permissions(unix_socket_path, fs::Permissions::from_mode(0o777)) {
128+
log::error!("{unix_socket_path}: {err}");
129+
exit(1);
130+
}
131+
107132
let (auto_sender, auto_receiver) = channel();
108133

109134
let auto_refresh_monitors_thread = thread::spawn(move || auto_refresh_monitors_list());
110-
let command_handler_thread = thread::spawn(move || handle_commands(cmd_receiver, auto_sender));
111135
let auto_adjust_thread = thread::spawn(move || auto_adjust(auto_receiver));
112136

113137
for stream in listener.incoming() {
114138
if auto_refresh_monitors_thread.is_finished() {
115139
panic!("auto refresh monitors thread is gone");
116140
}
117141

118-
if command_handler_thread.is_finished() {
119-
panic!("command handler thread is gone");
120-
}
121-
122142
if auto_adjust_thread.is_finished() {
123143
panic!("auto adjust thread is gone");
124144
}
125145

126-
let stream = match stream {
127-
Ok(stream) => stream,
146+
let client = match stream {
147+
Ok(client) => client,
128148
Err(err) => {
129-
error!("A client tried to connect but something wrong happened: {err}");
149+
log::error!("Failed to accept incoming client: {err}");
130150
continue;
131151
}
132152
};
133153

134-
match BacklightCommand::deserialize_from(&stream) {
135-
Ok(command) => {
136-
cmd_sender.send(command).unwrap();
137-
}
138-
Err(err) => {
139-
error!("Unable to deserialize command: {err}");
140-
}
154+
if let Err(err) = handle_client(client, auto_sender.clone()) {
155+
log::error!("{err}");
156+
continue;
141157
}
142158
}
143159

backlightd/src/monitors.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,14 @@ pub(crate) fn decrease_brightness_percent(percent: u8) -> anyhow::Result<()> {
165165
Ok(())
166166
}
167167
}
168+
169+
pub(crate) fn get_average_brightness() -> u8 {
170+
let monitors = MONITORS.lock().unwrap();
171+
let mut sum: usize = 0;
172+
173+
for monitor in &*monitors {
174+
sum += monitor.get_brightness() as usize;
175+
}
176+
177+
(sum / monitors.len()) as u8
178+
}

0 commit comments

Comments
 (0)