control centre: menus for Wi-Fi, Bluetooth, VPN and Sound in their own window
The tile or block grows into its menu; the panel fades its content and takes the menu's size underneath. Wi-Fi lists networks (join saved/open, disconnect, stop iwd), Bluetooth lists devices, VPN has a switch per openvpn service, Sound has every output with its own slider and a default picker. A second Sound slider for the output named by extra_output in shell.conf (NR515). Screen and keyboard light are written to sysfs directly: logind refuses a shell without a seat.
This commit is contained in:
@@ -37,6 +37,10 @@ pub struct Sink {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub bluetooth: bool,
|
||||
|
||||
// first channel, in percent
|
||||
pub volume: u8,
|
||||
pub muted: bool,
|
||||
}
|
||||
|
||||
pub fn sink_inputs(text: &str) -> Vec<Stream> {
|
||||
@@ -97,6 +101,10 @@ pub fn sinks(text: &str) -> Vec<Sink> {
|
||||
sink.name = name.to_string();
|
||||
} else if let Some(description) = line.strip_prefix("Description: ") {
|
||||
sink.description = description.to_string();
|
||||
} else if let Some(mute) = line.strip_prefix("Mute: ") {
|
||||
sink.muted = mute == "yes";
|
||||
} else if let Some(volume) = line.strip_prefix("Volume: ") {
|
||||
sink.volume = first_percent(volume);
|
||||
} else if line == "device.api = \"bluez5\"" {
|
||||
sink.bluetooth = true;
|
||||
}
|
||||
@@ -105,6 +113,17 @@ pub fn sinks(text: &str) -> Vec<Sink> {
|
||||
sinks
|
||||
}
|
||||
|
||||
/*
|
||||
* what a person calls an output: the monitor or receiver an hdmi port names in brackets,
|
||||
* "... DisplayPort 1 Output [TX-NR515] (Stereo)" gives "TX-NR515", else the description
|
||||
*/
|
||||
pub fn short_sink_name(description: &str) -> &str {
|
||||
match (description.find('['), description.find(']')) {
|
||||
(Some(open), Some(close)) if open < close => &description[open + 1..close],
|
||||
_ => description,
|
||||
}
|
||||
}
|
||||
|
||||
// "front-left: 52429 / 80% / -5.81 dB, front-right: ..." gives 80
|
||||
fn first_percent(volume: &str) -> u8 {
|
||||
let percent = volume.split('/').nth(1).map(|part| part.trim().trim_end_matches('%'));
|
||||
@@ -462,6 +481,9 @@ Sink Input #57
|
||||
\tState: RUNNING
|
||||
\tName: alsa_output.usb-Yamaha_AG03MK2-00.analog-stereo
|
||||
\tDescription: Yamaha AG03MK2 Analog Stereo
|
||||
\tMute: no
|
||||
\tVolume: front-left: 52428 / 80% / -5.81 dB, front-right: 52428 / 80% / -5.81 dB
|
||||
\tBase Volume: 65536 / 100% / 0.00 dB
|
||||
\tProperties:
|
||||
\t\tdevice.api = \"alsa\"
|
||||
\tPorts:
|
||||
@@ -470,6 +492,7 @@ Sink Input #57
|
||||
Sink #80
|
||||
\tName: bluez_output.00_1B_66_AA_BB_CC.1
|
||||
\tDescription: JBL Tune 720BT
|
||||
\tMute: yes
|
||||
\tProperties:
|
||||
\t\tdevice.api = \"bluez5\"
|
||||
";
|
||||
@@ -492,7 +515,11 @@ Sink #80
|
||||
assert_eq!(sinks.len(), 2);
|
||||
assert_eq!((sinks[0].index, sinks[0].bluetooth), (65, false));
|
||||
assert_eq!(sinks[0].description, "Yamaha AG03MK2 Analog Stereo");
|
||||
assert_eq!((sinks[0].volume, sinks[0].muted, sinks[1].muted), (80, false, true));
|
||||
assert_eq!((sinks[1].name.as_str(), sinks[1].description.as_str(), sinks[1].bluetooth), ("bluez_output.00_1B_66_AA_BB_CC.1", "JBL Tune 720BT", true));
|
||||
|
||||
assert_eq!(short_sink_name("700 Series Chipset Family HD Audio HDMI / DisplayPort 1 Output [TX-NR515] (Stereo)"), "TX-NR515");
|
||||
assert_eq!(short_sink_name("Yamaha AG03MK2 Analog Stereo"), "Yamaha AG03MK2 Analog Stereo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user