screenruster_saver/
lib.rs

1//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2//                    Version 2, December 2004
3//
4// Copyleft (ↄ) meh. <meh@schizofreni.co> | http://meh.schizofreni.co
5//
6// Everyone is permitted to copy and distribute verbatim or modified
7// copies of this license document, and changing it is allowed as long
8// as the name is changed.
9//
10//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12//
13//  0. You just DO WHAT THE FUCK YOU WANT TO.
14
15#![feature(type_ascription)]
16
17use std::io;
18use std::env;
19
20#[cfg(feature = "renderer")]
21pub use gl;
22#[cfg(feature = "renderer")]
23pub use picto;
24
25pub use json;
26pub use log::{debug, error, info, log, log_enabled, trace, warn};
27
28#[macro_use]
29mod util;
30
31mod error;
32pub use error::{Result, Error};
33
34mod state;
35pub use state::State;
36
37mod safety;
38pub use safety::Safety;
39
40mod password;
41pub use password::Password;
42
43pub mod pointer;
44pub use pointer::Pointer;
45
46mod channel;
47pub use channel::{Request, Response, Channel};
48
49#[cfg(feature = "renderer")]
50mod saver;
51#[cfg(feature = "renderer")]
52pub use saver::Saver;
53
54#[cfg(feature = "renderer")]
55mod renderer;
56#[cfg(feature = "renderer")]
57pub use renderer::Renderer;
58
59#[cfg(feature = "renderer")]
60mod display;
61#[cfg(feature = "renderer")]
62pub use display::Display;
63
64
65/// Initialize the saver.
66pub fn init() -> Result<Channel> {
67	use std::io::Write;
68
69	// Initialize logger.
70	{
71		let mut builder = env_logger::Builder::new();
72		let     pid     = unsafe { libc::getpid() };
73
74		builder.format(move |buf, record| {
75			writeln!(buf, "{}:{}:{}: {}", record.level(), pid, record.module_path().unwrap_or("unknown"), record.args())
76		});
77
78		if let Ok(log) = env::var("RUST_LOG") {
79			builder.parse_filters(&log);
80		}
81
82		builder.init();
83	}
84
85	Channel::open(io::stdin(), io::stdout())
86}
87
88/// Run the saver.
89#[cfg(feature = "renderer")]
90pub fn run<S: Saver + Send + 'static>(mut saver: S) -> Result<()> {
91	macro_rules! exit {
92		($body:expr) => (
93			if let Ok(value) = $body {
94				value
95			}
96			else {
97				break;
98			}
99		);
100	}
101
102	use crossbeam_channel::select;
103
104	let channel = init()?;
105
106	if let Ok(Request::Config(config)) = channel.recv() {
107		saver.config(config);
108	}
109	else {
110		return Err(Error::Protocol);
111	}
112
113	let renderer = if let Ok(Request::Target { display, screen, window }) = channel.recv() {
114		Renderer::new(display, screen, window, saver)
115	}
116	else {
117		return Err(Error::Protocol);
118	};
119
120	'main: loop {
121		select! {
122			recv(channel.as_ref()) -> message => {
123				match exit!(message) {
124					channel::Request::Target { .. } | channel::Request::Config(..) => {
125						unreachable!();
126					}
127
128					channel::Request::Resize { width, height } => {
129						renderer.resize(width, height).unwrap();
130					}
131
132					channel::Request::Throttle(value) => {
133						renderer.throttle(value).unwrap();
134					}
135
136					channel::Request::Blank(value) => {
137						renderer.blank(value).unwrap();
138					}
139
140					channel::Request::Safety(value) => {
141						renderer.safety(value).unwrap();
142					}
143
144					channel::Request::Pointer(pointer) => {
145						renderer.pointer(pointer).unwrap();
146					}
147
148					channel::Request::Password(password) => {
149						renderer.password(password).unwrap();
150					}
151
152					channel::Request::Start => {
153						renderer.start().unwrap();
154					}
155
156					channel::Request::Lock => {
157						renderer.lock().unwrap();
158					}
159
160					channel::Request::Stop => {
161						renderer.stop().unwrap();
162					}
163				}
164			},
165
166			recv(renderer.as_ref()) -> message => {
167				match exit!(message) {
168					renderer::Response::Initialized => {
169						channel.send(channel::Response::Initialized).unwrap();
170					}
171
172					renderer::Response::Started => {
173						channel.send(channel::Response::Started).unwrap();
174					}
175
176					renderer::Response::Stopped => {
177						break 'main;
178					}
179				}
180			}
181		}
182	}
183
184	channel.send(channel::Response::Stopped).unwrap();
185
186	Ok(())
187}