this repo has no description
1use crossbeam_channel::{bounded, Receiver};
2use std::{
3 collections::HashMap,
4 fs::File,
5 io::Read,
6 sync::{Arc, Mutex},
7};
8
9use flate2::read::GzDecoder;
10use serde_json::{Map, Value};
11use tauri::{App, Emitter, Listener, Manager, WindowEvent};
12
13use crate::{
14 osc::{self, OSCMessage}, runtime::{commands::RuntimeCommand, nodes::RuntimeNodeTree, recurse_runtime}, structs::parameter_types::ParameterType, utils::{setup_traymenu::setup_traymenu, vrchat_builtin_parameters}
15};
16
17pub fn setup(
18 app: &mut App,
19 addresses: &'static Mutex<Vec<OSCMessage>>,
20 runtime_command_receiver: Receiver<RuntimeCommand>,
21) {
22 let window = app.get_webview_window("main").unwrap();
23 window.hide().unwrap();
24
25 let win_handle = window.clone();
26
27 window.on_window_event(move |event| match event {
28 WindowEvent::CloseRequested { api, .. } => {
29 api.prevent_close();
30 win_handle.emit("prompt_to_close", ()).unwrap();
31 }
32 WindowEvent::Resized(_) => {
33 let minimised = win_handle.is_minimized().unwrap();
34 if minimised{
35 win_handle.hide().unwrap();
36 win_handle.emit("hide-window", ()).unwrap();
37 win_handle.unminimize().unwrap();
38 }
39 }
40 _ => {}
41 });
42
43 setup_traymenu(app.handle());
44
45 let handle = window.clone();
46 window.listen("tauri://drag-drop", move |ev| {
47 let path: Value = serde_json::from_str(ev.payload()).unwrap();
48 let path = path["paths"][0].as_str().unwrap();
49
50 let file = File::open(&path).unwrap();
51 let mut decoder = GzDecoder::new(file);
52 let mut string = String::new();
53
54 decoder.read_to_string(&mut string).unwrap();
55
56 let mut map = Map::new();
57
58 map.insert("path".to_owned(), Value::String(path.to_owned()));
59 map.insert("graph".to_owned(), Value::String(string));
60
61 handle.emit("load_new_tab", Value::Object(map)).unwrap();
62 });
63
64 let (sender, receiver) = bounded(1024);
65
66 tokio::spawn(async move {
67 osc::start_server(sender, "127.0.0.1:9001");
68 });
69
70 let (runtime_sender, runtime_receiver) = bounded(1024);
71
72 let runtime_sender_1 = runtime_sender.clone();
73 tokio::spawn(async move {
74 loop {
75 let cmd = runtime_command_receiver.recv().unwrap();
76 runtime_sender_1.send(cmd).unwrap();
77 }
78 });
79
80 tokio::spawn(async move {
81 loop {
82 let message = receiver.recv().unwrap();
83
84 window.emit("osc-message", &message).unwrap();
85
86 let msg = message.clone();
87 let mut addrs = addresses.lock().unwrap();
88 if !addrs.contains(&msg) {
89 addrs.push(msg);
90 }
91
92 if message.address == "/avatar/change".to_owned(){
93 *addrs = vrchat_builtin_parameters::get_read_addresses();
94
95 // TODO: Read avatar paramaters from file
96 }
97
98 runtime_sender
99 .send(RuntimeCommand::OSCMessage(message))
100 .unwrap();
101 }
102 });
103
104 // TODO: Run tabs in seperate threads (really not looking forward to this... thanks rust)
105
106 tokio::spawn(async move {
107 let mut tabs: HashMap<String, RuntimeNodeTree> = HashMap::new();
108
109 // #[cfg(target_os = "windows")]
110 let enigo = Arc::new(Mutex::new(enigo::Enigo::new(&enigo::Settings::default()).unwrap()));
111
112 loop {
113 let cmd = runtime_receiver.recv().unwrap();
114
115 match cmd {
116 RuntimeCommand::OSCMessage(msg) => {
117 for (_, mut tab) in &mut tabs {
118 let keys: Vec<String> = tab.nodes.keys().map(|x| x.clone()).collect();
119
120 for id in keys {
121 let entry = tab.nodes[&id].is_entrypoint();
122
123 if entry {
124 let mut args = vec![ ParameterType::String(msg.address.clone())];
125 let mut values = msg.values.clone();
126
127 args.append(&mut values);
128 let _ = recurse_runtime(id.clone(), &mut tab, args);
129 }
130 }
131 }
132 }
133
134 RuntimeCommand::AddTab(graph, id) => {
135 // #[cfg(target_os = "windows")]
136 tabs.insert(id, RuntimeNodeTree::from(graph, enigo.clone()));
137
138 // #[cfg(target_os = "linux")]
139 // tabs.insert(id, RuntimeNodeTree::from(graph));
140 }
141 RuntimeCommand::RemoveTab(id) => {
142 tabs.remove(&id);
143 }
144 }
145 }
146 });
147}