Detecting screens

This commit is contained in:
Thomas Forgione 2018-09-26 13:46:46 +02:00
parent 8c74c39e4e
commit 11c399841f
No known key found for this signature in database
GPG Key ID: 203DAEA747F48F41
4 changed files with 129 additions and 3 deletions

View File

@ -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"

113
src/lib.rs Normal file
View File

@ -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)
}
}

View File

@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}

11
src/tv.rs Normal file
View File

@ -0,0 +1,11 @@
extern crate clap;
extern crate tvrs;
use tvrs::Screen;
fn main() {
let screens = Screen::find_screens()
.expect("An error happened while finding screens");
println!("{:?}", screens);
}