Skip to content

Commit 247b849

Browse files
author
Tomasz Cichocki
committed
Initial commit
0 parents  commit 247b849

3 files changed

Lines changed: 166 additions & 0 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target/
2+
**/*.rs.bk

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "wsnotify"
3+
version = "0.1.0"
4+
authors = ["Tomasz Cichocki <tomasz.cichocki@optiva.com>"]
5+
6+
[dependencies]
7+
notify = "4.0.0"
8+
app_dirs = "^1.1.1"

src/main.rs

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
extern crate notify;
2+
3+
use notify::{Watcher, RecursiveMode, RawEvent, raw_watcher};
4+
use notify::op::Op;
5+
use std::sync::mpsc::channel;
6+
7+
extern crate app_dirs;
8+
use app_dirs::*;
9+
10+
use std::fs::{File,OpenOptions};
11+
use std::path::Path;
12+
use std::io::Seek;
13+
use std::io::SeekFrom;
14+
use std::io::Read;
15+
//use std::io::Error;
16+
17+
fn read_file_length(path: &std::path::Path) -> Result<usize,std::io::Error> {
18+
match std::fs::metadata(path) {
19+
Ok(m) => Ok(m.len() as usize),
20+
Err(e) => Err(e),
21+
}
22+
}
23+
24+
trait CameraEventWatcher {
25+
// Data capture started.
26+
fn on_capture_start(&self, line: &str);
27+
28+
// Data capture stopped.
29+
fn on_capture_stop(&self, line: &str);
30+
31+
// Camera capture started.
32+
fn on_camera_start(&self, line: &str);
33+
34+
// Preparing to get Webcamshot.
35+
fn on_camera_prepare(&self, line: &str);
36+
37+
// Got picture from the webcam.
38+
fn on_camera_finish(&self, line: &str);
39+
40+
// Saved an image to
41+
fn on_image_save(&self, line: &str);
42+
}
43+
44+
struct EchoCameraWatcher {}
45+
impl CameraEventWatcher for EchoCameraWatcher {
46+
fn on_camera_start(&self, line: &str) {
47+
println!("{}", line);
48+
}
49+
fn on_camera_prepare(&self, line: &str) {
50+
println!("{}", line);
51+
}
52+
fn on_camera_finish(&self, line: &str) {
53+
println!("{}", line);
54+
}
55+
fn on_capture_start(&self, line: &str) {
56+
println!("{}", line);
57+
}
58+
59+
fn on_capture_stop(&self, line: &str) {
60+
println!("{}", line);
61+
}
62+
63+
fn on_image_save(&self, line: &str) {
64+
println!("{}", line);
65+
}
66+
}
67+
68+
pub struct FileScanner {
69+
file_name: Box<Path>,
70+
file: File,
71+
last_byte_read: usize,
72+
camera_watcher: Box<CameraEventWatcher>,
73+
}
74+
75+
impl FileScanner {
76+
fn create(file_name: &std::path::Path, camera_watcher: Box<CameraEventWatcher>) -> Result<FileScanner,String> {
77+
let file : File = OpenOptions::new().read(true).open(file_name)
78+
.map_err( |err| err.to_string())?;
79+
let len = read_file_length(file_name)
80+
.map_err( |err| err.to_string())?;
81+
82+
Ok(FileScanner {
83+
file_name: Box::from(file_name),
84+
file,
85+
last_byte_read: len,
86+
camera_watcher,
87+
})
88+
}
89+
90+
fn handle_event(&mut self, op: Op) -> Result<(), String> {
91+
92+
if op != notify::op::WRITE {
93+
// TODO support handling logfile rolling
94+
return Ok(());
95+
}
96+
97+
let len = read_file_length(&self.file_name).map_err( |err| err.to_string())?;
98+
// println!("{:?} {}", op, len);
99+
100+
let mut buffer = vec![0; len-self.last_byte_read].into_boxed_slice();
101+
self.file.seek(SeekFrom::Start(self.last_byte_read as u64))
102+
.map_err( |err| err.to_string())?;
103+
self.file.read_exact(&mut buffer).map_err( |err| err.to_string())?;
104+
105+
let buffer = String::from_utf8_lossy(&buffer);
106+
107+
for s in buffer.split('\n') {
108+
if String::from(s).contains("Camera capture started.") {
109+
self.camera_watcher.on_camera_start(s);
110+
} else if String::from(s).contains("Preparing to get Webcamshot.") {
111+
self.camera_watcher.on_camera_prepare(s);
112+
} else if String::from(s).contains("Got picture from the webcam.") {
113+
self.camera_watcher.on_camera_finish(s);
114+
} else if String::from(s).contains("Data capture started.") {
115+
self.camera_watcher.on_capture_start(s);
116+
} else if String::from(s).contains("Data capture stopped.") {
117+
self.camera_watcher.on_capture_stop(s);
118+
} else if String::from(s).contains("Saved an image to ") {
119+
self.camera_watcher.on_image_save(s);
120+
}
121+
}
122+
123+
self.last_byte_read = len;
124+
125+
Ok(())
126+
}
127+
128+
}
129+
130+
const APP_INFO: AppInfo = AppInfo{name: "Logs", author: "CrossoverWorkSmart"};
131+
132+
fn main() {
133+
let mut path = get_app_root(AppDataType::UserConfig, &APP_INFO).unwrap();
134+
path.push("deskapp.log");
135+
let path = path.as_path();
136+
137+
// Create a channel to receive the events.
138+
let (tx, rx) = channel();
139+
140+
// Create a watcher object, delivering raw events.
141+
// The notification back-end is selected based on the platform.
142+
let mut watcher = raw_watcher(tx).unwrap();
143+
let camera = Box::new(EchoCameraWatcher{});
144+
let mut scanner = FileScanner::create(path, camera).unwrap();
145+
146+
// Add a path to be watched. All files and directories at that path and
147+
// below will be monitored for changes.
148+
watcher.watch(path, RecursiveMode::NonRecursive).unwrap();
149+
loop {
150+
match rx.recv() {
151+
Ok(RawEvent{path: Some(_path), op: Ok(op), cookie: _cookie}) => scanner.handle_event(op).unwrap(),
152+
Ok(event) => println!("broken event: {:?}", event),
153+
Err(e) => println!("watch error: {:?}", e),
154+
}
155+
}
156+
}

0 commit comments

Comments
 (0)