Detecting screens
This commit is contained in:
parent
8c74c39e4e
commit
11c399841f
|
@ -4,3 +4,8 @@ version = "0.1.0"
|
|||
authors = ["Thomas Forgione <thomas@forgione.fr>"]
|
||||
|
||||
[dependencies]
|
||||
clap = "2.32.0"
|
||||
|
||||
[[bin]]
|
||||
name = "tvrs"
|
||||
path = "src/tv.rs"
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
use std::io;
|
||||
use std::process::Command;
|
||||
use std::num::ParseIntError;
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
/// The different kinds of errors that can happen.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
|
||||
/// An io::Error happened while running the xrandr command.
|
||||
IoError(io::Error),
|
||||
|
||||
/// An error happened while parsing the xrandr output to a string
|
||||
Utf8Error(FromUtf8Error),
|
||||
|
||||
/// An error happened while parsing the resolution of a xrandr screen.
|
||||
ParseIntError(ParseIntError),
|
||||
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(e: io::Error) -> Error {
|
||||
Error::IoError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FromUtf8Error> for Error {
|
||||
fn from(e: FromUtf8Error) -> Error {
|
||||
Error::Utf8Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for Error {
|
||||
fn from(e: ParseIntError) -> Error {
|
||||
Error::ParseIntError(e)
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct that represents a screen and its supported resolutions.
|
||||
#[derive(Debug)]
|
||||
pub struct Screen {
|
||||
/// The name of the screen received from xrandr.
|
||||
name: String,
|
||||
|
||||
/// The available resolutions of the screen.
|
||||
resolutions: Vec<(u32, u32)>,
|
||||
|
||||
/// Whether the screen is primary or not
|
||||
primary: bool,
|
||||
|
||||
/// Whether the screen is connected or not.
|
||||
connected: bool,
|
||||
}
|
||||
|
||||
impl Screen {
|
||||
|
||||
/// Creates a screen from the first line in the xrandr command.
|
||||
pub fn from_line(line: &str) -> Screen {
|
||||
let split = line.split_whitespace().collect::<Vec<_>>();
|
||||
Screen {
|
||||
name: split[0].to_string(),
|
||||
resolutions: vec![],
|
||||
primary: line.contains("primary"),
|
||||
connected: line.contains(" connected"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds all the screens by spawning and parsing the output of xrandr.
|
||||
pub fn find_screens() -> Result<Vec<Screen>, Error> {
|
||||
let mut screens = vec![];
|
||||
|
||||
let xrandr = Command::new("xrandr")
|
||||
.output()?;
|
||||
|
||||
let output = String::from_utf8(xrandr.stdout)?;
|
||||
let output = output.split('\n').skip(1);
|
||||
|
||||
for line in output {
|
||||
|
||||
if line.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if line.contains("connected") {
|
||||
|
||||
screens.push(Screen::from_line(line));
|
||||
|
||||
} else if let Some(mut last) = screens.last_mut() {
|
||||
|
||||
// Get the first thing
|
||||
let split = line.split_whitespace().collect::<Vec<_>>();
|
||||
|
||||
// Remove the _ with the frequency
|
||||
let resolution = split[0]
|
||||
.split("_").collect::<Vec<_>>()[0]
|
||||
.split("x").collect::<Vec<_>>();
|
||||
|
||||
last.resolutions.push((
|
||||
resolution[0].parse::<u32>()?,
|
||||
resolution[1].parse::<u32>()?,
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for screen in &mut screens {
|
||||
screen.resolutions.sort();
|
||||
}
|
||||
|
||||
Ok(screens)
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
Loading…
Reference in New Issue