1mod cli;
8mod networking;
9mod fixture;
10
11use std::io::{self, Write};
12use std::{env, thread};
13use std::time::Duration;
14use common::{r_debug_log, r_log};
15use common::logging::{FileSink, Logger, TerminalSink};
16use common::logging::LogLevel::*;
17use interface::interfaces::dmx_output_loop;
18use crate::cli::run_command;
19
20fn main() -> io::Result<()> {
27
28 let port = get_arguments();
29
30 if cfg!(all(debug_assertions, not(test))) {
31 thread::sleep(Duration::from_millis(1000));
32 }
33
34 Logger::global().add_sink(Box::new(TerminalSink {cli_prompt: Some("> ".into())}));
35 Logger::global().add_sink(Box::new(FileSink::new("kernel.log")));
36
37 #[cfg(all(not(debug_assertions), not(test)))]
38 {
39 ctrlc::set_handler(move || {
40 r_log!(
41 Warning,
42 "Ctrl+C is disabled to prevent data loss. Please type 'exit' to shutdown safely."
43 );
44 })
45 .expect("Error setting Ctrl-C handler");
46 }
47
48
49 let interface_receiver = fixture::FixtureEngine::spawn().expect("Failed to spawn FixtureEngine");
50
51 let _artnet_handle = thread::spawn(|| {
52 dmx_output_loop(interface_receiver).expect("\x1b[31martnet loop failed\x1b[0m");
53 });
54
55
56 networking::activate_socket(port);
57
58
59 loop {
60 io::stdout().flush()?;
61
62 let mut input = String::new();
63 if let Err(e) = io::stdin().read_line(&mut input) {
64 r_log!(UserError, "Terminal input stream contained invalid UTF-8 (e.g. from deleting special characters).\
65 Discarding input. Error: {}", e);
66 continue;
67 }
68
69 let input = input.trim().to_string();
70
71 r_debug_log!(Info, "[Kernel Cli] User input: {}", input);
72
73
74 let response = run_command(true, input);
75
76 r_log!(response.0, "[Kernel Cli] {}", response.1);
77 }
78}
79
80fn get_arguments() -> u16 {
86 let mut port: u16 = 6767;
88
89 let args: Vec<String> = env::args().collect();
90 let mut iter = args.iter().skip(1);
91
92 while let Some(arg) = iter.next() {
93 match arg.as_ref() {
94 "--port" => {
95 if let Some(port_str) = iter.next() {
96 match port_str.parse::<u16>() {
97 Ok(p) => port = p,
98 Err(_) => {
99 println!("Invalid port number: {}", port_str);
100 thread::sleep(Duration::from_millis(50));
101 std::process::exit(1);
102 }
103 }
104 }
105 }
106
107 _ => {
108 println!("Invalid argument: {}", arg);
109 thread::sleep(Duration::from_millis(50));
110 std::process::exit(1);
111 },
112 }
113 }
114
115 port
116}