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