1
0
mirror of https://github.com/emersion/kanshi synced 2024-11-23 00:02:16 +01:00

Add Store trait

This commit is contained in:
emersion 2017-08-05 21:16:26 +02:00
parent b942582ec4
commit 7c7a69e182
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
2 changed files with 114 additions and 88 deletions

@ -1,37 +1,27 @@
extern crate edid;
extern crate getopts;
extern crate xmltree;
mod backend;
mod store;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::env;
use getopts::Options;
use xmltree::Element;
use backend::{ConnectedOutput, Backend, SysFsBackend};
use store::{SavedOutput, Store, GnomeStore};
#[derive(Debug, Default)]
struct SavedOutput {
name: String,
vendor: String,
product: String,
serial: String,
fn connector_type(name: &str) -> Option<String> {
let name = name.to_lowercase();
width: i32,
height: i32,
rate: f32,
x: i32,
y: i32,
//rotation: Rotation,
//reflect_x: bool,
//reflect_y: bool,
primary: bool,
//presentation: bool,
//underscanning: bool,
[
"VGA", "Unknown", "DVI", "Composite", "SVIDEO", "LVDS", "Component", "DIN", "DP", "HDMI",
"TV", "eDP", "Virtual", "DSI",
]
.iter()
.find(|t| name.starts_with(t.to_lowercase().as_str()))
.map(|s| s.to_string())
}
impl PartialEq<SavedOutput> for ConnectedOutput {
@ -90,22 +80,6 @@ impl PartialEq<SavedOutput> for ConnectedOutput {
}
}
fn parse_bool(s: &str) -> bool {
s == "yes"
}
fn connector_type(name: &str) -> Option<String> {
let name = name.to_lowercase();
[
"VGA", "Unknown", "DVI", "Composite", "SVIDEO", "LVDS", "Component", "DIN", "DP", "HDMI",
"TV", "eDP", "Virtual", "DSI",
]
.iter()
.find(|t| name.starts_with(t.to_lowercase().as_str()))
.map(|s| s.to_string())
}
fn print_usage(program: &str, opts: Options) {
let brief = format!("Usage: {} [options]", program);
print!("{}", opts.usage(&brief));
@ -130,62 +104,27 @@ fn main() {
let mut stderr = std::io::stdout();
let be = SysFsBackend{};
let connected_outputs = be.list_outputs().unwrap();
let backend = SysFsBackend{};
let connected_outputs = match backend.list_outputs() {
Ok(c) => c,
Err(err) => {
writeln!(&mut stderr, "Error: cannot list connected monitors: {}", err).unwrap();
std::process::exit(1);
},
};
writeln!(&mut stderr, "Connected outputs: {:?}", connected_outputs).unwrap();
let user_config_path = env::var("XDG_CONFIG_HOME")
.map(PathBuf::from)
.unwrap_or(env::home_dir().unwrap().join(".config"));
let monitors_path = user_config_path.join("monitors.xml");
let f = match File::open(&monitors_path) {
Ok(f) => f,
let store = GnomeStore{};
let configurations = match store.list_configurations() {
Ok(c) => c,
Err(err) => {
writeln!(&mut stderr, "Error: cannot open config file {:?}: {}", &monitors_path, err).unwrap();
writeln!(&mut stderr, "Error: cannot list saved monitor configurations: {}", err).unwrap();
std::process::exit(1);
}
},
};
let monitors = Element::parse(f).unwrap();
let configuration = monitors.children.iter()
.filter(|e| e.name == "configuration")
.map(|e| {
e.children.iter()
.filter(|e| e.name == "output")
.map(|e| {
let mut o = SavedOutput{
name: e.attributes.get("name").unwrap().to_owned(),
vendor: e.get_child("vendor").unwrap().text.as_ref().unwrap().to_owned(),
product: e.get_child("product").unwrap().text.as_ref().unwrap().to_owned(),
serial: e.get_child("serial").unwrap().text.as_ref().unwrap().to_owned(),
..SavedOutput::default()
};
if let Some(c) = e.get_child("width") {
o.width = c.text.as_ref().unwrap().parse::<i32>().unwrap()
}
if let Some(c) = e.get_child("height") {
o.height = c.text.as_ref().unwrap().parse::<i32>().unwrap()
}
if let Some(c) = e.get_child("rate") {
o.rate = c.text.as_ref().unwrap().parse::<f32>().unwrap()
}
if let Some(c) = e.get_child("x") {
o.x = c.text.as_ref().unwrap().parse::<i32>().unwrap()
}
if let Some(c) = e.get_child("y") {
o.y = c.text.as_ref().unwrap().parse::<i32>().unwrap()
}
if let Some(c) = e.get_child("primary") {
o.primary = parse_bool(c.text.as_ref().unwrap())
}
o
})
.collect::<Vec<_>>()
})
let configuration = configurations.iter()
.filter_map(|config| {
let n_saved = config.len();
if n_saved != connected_outputs.len() {
@ -195,7 +134,7 @@ fn main() {
let matched = config.into_iter()
.filter_map(|saved| {
connected_outputs.iter()
.find(|connected| **connected == saved)
.find(|connected| **connected == *saved)
.map(|connected| (connected.name.clone(), saved))
})
.collect::<Vec<_>>();

87
src/store.rs Normal file

@ -0,0 +1,87 @@
extern crate xmltree;
use std::error::Error;
use std::env;
use std::path::PathBuf;
use std::fs::File;
#[derive(Debug, Default)]
pub struct SavedOutput {
pub name: String,
pub vendor: String,
pub product: String,
pub serial: String,
pub width: i32,
pub height: i32,
pub rate: f32,
pub x: i32,
pub y: i32,
//pub rotation: Rotation,
//pub reflect_x: bool,
//pub reflect_y: bool,
pub primary: bool,
//pub presentation: bool,
//pub underscanning: bool,
}
pub trait Store {
fn list_configurations(&self) -> Result<Vec<Vec<SavedOutput>>, Box<Error>>;
}
fn parse_bool(s: &str) -> bool {
s == "yes"
}
pub struct GnomeStore;
impl Store for GnomeStore {
fn list_configurations(&self) -> Result<Vec<Vec<SavedOutput>>, Box<Error>> {
let user_config_path = env::var("XDG_CONFIG_HOME")
.map(PathBuf::from)
.unwrap_or(env::home_dir().unwrap().join(".config"));
let monitors_path = user_config_path.join("monitors.xml");
let monitors = xmltree::Element::parse(File::open(&monitors_path)?).unwrap();
let configurations = monitors.children.iter()
.filter(|e| e.name == "configuration")
.map(|e| {
e.children.iter()
.filter(|e| e.name == "output")
.map(|e| {
let mut o = SavedOutput{
name: e.attributes.get("name").unwrap().to_owned(),
vendor: e.get_child("vendor").unwrap().text.as_ref().unwrap().to_owned(),
product: e.get_child("product").unwrap().text.as_ref().unwrap().to_owned(),
serial: e.get_child("serial").unwrap().text.as_ref().unwrap().to_owned(),
..SavedOutput::default()
};
if let Some(c) = e.get_child("width") {
o.width = c.text.as_ref().unwrap().parse::<i32>().unwrap()
}
if let Some(c) = e.get_child("height") {
o.height = c.text.as_ref().unwrap().parse::<i32>().unwrap()
}
if let Some(c) = e.get_child("rate") {
o.rate = c.text.as_ref().unwrap().parse::<f32>().unwrap()
}
if let Some(c) = e.get_child("x") {
o.x = c.text.as_ref().unwrap().parse::<i32>().unwrap()
}
if let Some(c) = e.get_child("y") {
o.y = c.text.as_ref().unwrap().parse::<i32>().unwrap()
}
if let Some(c) = e.get_child("primary") {
o.primary = parse_bool(c.text.as_ref().unwrap())
}
o
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
Ok(configurations)
}
}