main.rs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. // Use these to incrementally fix warnings with cargo fix
  19. #![allow(warnings, unused)]
  20. //#![deny(unused_imports)]
  21. use async_lock::{Mutex as AsyncMutex, RwLock as AsyncRwLock};
  22. use darkfi::system::CondVar;
  23. use file_rotate::{compression::Compression, suffix::AppendCount, ContentLimit, FileRotate};
  24. use std::sync::{mpsc, Arc};
  25. #[macro_use]
  26. extern crate log;
  27. #[allow(unused_imports)]
  28. use log::LevelFilter;
  29. #[derive(Debug)]
  30. pub enum AndroidSuggestEvent {
  31. Init,
  32. CreateInputConnect,
  33. Compose { text: String, cursor_pos: i32, is_commit: bool },
  34. ComposeRegion { start: usize, end: usize },
  35. FinishCompose,
  36. DeleteSurroundingText { left: usize, right: usize },
  37. }
  38. #[cfg(target_os = "android")]
  39. mod android;
  40. mod app;
  41. mod build_info;
  42. mod error;
  43. mod expr;
  44. mod gfx;
  45. mod logger;
  46. mod mesh;
  47. mod net;
  48. mod plugin;
  49. mod prop;
  50. mod pubsub;
  51. //mod py;
  52. mod ringbuf;
  53. mod scene;
  54. mod shape;
  55. use scene::SceneNode as SceneNode3;
  56. mod text;
  57. mod text2;
  58. mod ui;
  59. mod util;
  60. use crate::{net::ZeroMQAdapter, text::TextShaper};
  61. // Hides the cmd.exe terminal on Windows.
  62. // Enable this when making release builds.
  63. //#![windows_subsystem = "windows"]
  64. pub type ExecutorPtr = Arc<smol::Executor<'static>>;
  65. fn panic_hook(panic_info: &std::panic::PanicHookInfo) {
  66. error!("panic occurred: {panic_info}");
  67. error!("{}", std::backtrace::Backtrace::force_capture().to_string());
  68. std::process::abort()
  69. }
  70. fn main() {
  71. // Abort the application on panic right away
  72. std::panic::set_hook(Box::new(panic_hook));
  73. text2::init_txt_ctx();
  74. logger::setup_logging();
  75. #[cfg(target_os = "android")]
  76. {
  77. use crate::android::{get_appdata_path, get_external_storage_path};
  78. info!("App internal data path: {:?}", get_appdata_path());
  79. info!("App external storage path: {:?}", get_external_storage_path());
  80. // Workaround for this bug
  81. // https://gitlab.torproject.org/tpo/core/arti/-/issues/999
  82. unsafe {
  83. std::env::set_var("HOME", get_appdata_path().as_os_str());
  84. }
  85. //let paths = std::fs::read_dir("/data/data/darkfi.darkfi/").unwrap();
  86. //for path in paths {
  87. // debug!("{}", path.unwrap().path().display())
  88. //}
  89. }
  90. let exe_path = std::env::current_exe().unwrap();
  91. let basename = exe_path.parent().unwrap();
  92. std::env::set_current_dir(basename);
  93. info!("Target OS: {}", build_info::TARGET_OS);
  94. info!("Target arch: {}", build_info::TARGET_ARCH);
  95. let cwd = std::env::current_dir().unwrap();
  96. info!("Current dir: {}", cwd.display());
  97. let ex = Arc::new(smol::Executor::new());
  98. let sg_root = SceneNode3::root();
  99. let async_runtime = app::AsyncRuntime::new(ex.clone());
  100. async_runtime.start();
  101. #[cfg(feature = "enable-netdebug")]
  102. {
  103. let sg_root2 = sg_root.clone();
  104. let ex2 = ex.clone();
  105. let zmq_task = ex.spawn(async {
  106. let zmq_rpc = ZeroMQAdapter::new(sg_root2, ex2).await;
  107. zmq_rpc.run().await;
  108. });
  109. async_runtime.push_task(zmq_task);
  110. }
  111. let (method_req, method_rep) = mpsc::channel();
  112. // The UI actually needs to be running for this to reply back.
  113. // Otherwise calls will just hang.
  114. let render_api = gfx::RenderApi::new(method_req);
  115. let event_pub = gfx::GraphicsEventPublisher::new();
  116. let text_shaper = TextShaper::new();
  117. let cv_gfxwin_started = Arc::new(CondVar::new());
  118. let cv_gfxwin_started2 = cv_gfxwin_started.clone();
  119. let cv_app_started = Arc::new(CondVar::new());
  120. let cv_app_started2 = cv_app_started.clone();
  121. let app = app::App::new(sg_root, render_api, event_pub.clone(), text_shaper, ex.clone());
  122. let app2 = app.clone();
  123. let app_task = ex.spawn(async move {
  124. app2.setup().await;
  125. // Needed because accessing screen_size() is not allowed until window init
  126. cv_gfxwin_started2.wait().await;
  127. app2.start().await;
  128. cv_app_started2.notify();
  129. });
  130. async_runtime.push_task(app_task);
  131. /*
  132. // Nice to see which events exist
  133. let ev_sub = event_pub.subscribe_key_down();
  134. let ev_relay_task = ex.spawn(async move {
  135. debug!(target: "main", "event relayer started");
  136. loop {
  137. let Ok((key, mods, repeat)) = ev_sub.receive().await else {
  138. debug!(target: "main", "Event relayer closed");
  139. break
  140. };
  141. // Ignore keys which get stuck repeating when switching windows
  142. match key {
  143. miniquad::KeyCode::LeftShift | miniquad::KeyCode::LeftSuper => continue,
  144. _ => {}
  145. }
  146. if !repeat {
  147. debug!(target: "main", "key_down event: {:?} {:?} {}", key, mods, repeat);
  148. }
  149. }
  150. });
  151. async_runtime.push_task(ev_relay_task);
  152. let ev_sub = event_pub.subscribe_key_up();
  153. let ev_relay_task = ex.spawn(async move {
  154. debug!(target: "main", "event relayer started");
  155. loop {
  156. let Ok((key, mods)) = ev_sub.receive().await else {
  157. debug!(target: "main", "Event relayer closed");
  158. break
  159. };
  160. // Ignore keys which get stuck repeating when switching windows
  161. match key {
  162. miniquad::KeyCode::LeftShift | miniquad::KeyCode::LeftSuper => continue,
  163. _ => {}
  164. }
  165. debug!(target: "main", "key_up event: {:?} {:?}", key, mods);
  166. }
  167. });
  168. async_runtime.push_task(ev_relay_task);
  169. let ev_sub = event_pub.subscribe_char();
  170. let ev_relay_task = ex.spawn(async move {
  171. debug!(target: "main", "event relayer started");
  172. loop {
  173. let Ok((key, mods, repeat)) = ev_sub.receive().await else {
  174. debug!(target: "main", "Event relayer closed");
  175. break
  176. };
  177. debug!(target: "main", "char event: {:?} {:?} {}", key, mods, repeat);
  178. }
  179. });
  180. async_runtime.push_task(ev_relay_task);
  181. */
  182. //let stage = gfx::Stage::new(method_rep, event_pub);
  183. gfx::run_gui(app, async_runtime, method_rep, event_pub, cv_gfxwin_started);
  184. debug!(target: "main", "Started GFX backend");
  185. }
  186. /*
  187. use rustpython_vm::{self as pyvm, convert::ToPyObject};
  188. fn main() {
  189. let module = pyvm::Interpreter::without_stdlib(Default::default()).enter(|vm| {
  190. let source = r#"
  191. def foo():
  192. open("hihi", "w")
  193. return 110
  194. #max(1 + lw/3, 4*10) + foo(2, True)
  195. "#;
  196. //let code_obj = vm
  197. // .compile(source, pyvm::compiler::Mode::Exec, "<embedded>".to_owned())
  198. // .map_err(|err| vm.new_syntax_error(&err, Some(source))).unwrap();
  199. //code_obj
  200. pyvm::import::import_source(vm, "lain", source).unwrap()
  201. });
  202. fn foo(x: u32, y: bool) -> u32 {
  203. if y {
  204. 2 * x
  205. } else {
  206. x
  207. }
  208. }
  209. let res = pyvm::Interpreter::without_stdlib(Default::default()).enter(|vm| {
  210. let globals = vm.ctx.new_dict();
  211. globals.set_item("lw", vm.ctx.new_int(110).to_pyobject(vm), vm).unwrap();
  212. globals.set_item("lh", vm.ctx.new_int(4).to_pyobject(vm), vm).unwrap();
  213. globals.set_item("foo", vm.new_function("foo", foo).into(), vm).unwrap();
  214. let scope = pyvm::scope::Scope::new(None, globals);
  215. let foo_fn = module.get_attr("foo", vm).unwrap();
  216. foo_fn.call((), vm).unwrap()
  217. //vm.run_code_obj(code_obj, scope).unwrap()
  218. });
  219. println!("{:?}", res);
  220. }
  221. */