1use crate::{CWString, NullByteError, load_wide_string};
4
5#[derive(Debug, Clone, PartialEq)]
7pub struct FontInfo {
8 pub name: String,
10 pub size: f32,
12}
13impl FontInfo {
14 unsafe fn from_raw(font_info_ptr: *mut aviutl2_sys::config2::FONT_INFO) -> Self {
20 let font_info = unsafe { &*font_info_ptr };
21 let name = unsafe { load_wide_string(font_info.name) };
22 Self {
23 name,
24 size: font_info.size,
25 }
26 }
27}
28
29struct InternalConfigHandle {
30 raw: *mut aviutl2_sys::config2::CONFIG_HANDLE,
31}
32unsafe impl Send for InternalConfigHandle {}
33
34static CONFIG_HANDLE: std::sync::OnceLock<std::sync::Mutex<InternalConfigHandle>> =
35 std::sync::OnceLock::new();
36
37pub fn app_data_path() -> std::path::PathBuf {
39 let path = unsafe {
40 load_wide_string(
41 CONFIG_HANDLE
42 .get()
43 .expect("Config handle not initialized")
44 .lock()
45 .unwrap()
46 .raw
47 .as_ref()
48 .expect("Config handle raw pointer is null")
49 .app_data_path,
50 )
51 };
52 std::path::PathBuf::from(path)
53}
54
55pub fn translate(text: &str) -> String {
60 match translate_strict(text) {
61 Ok(translated) => translated,
62 Err(_) => text.to_string(),
63 }
64}
65
66pub fn translate_strict(text: &str) -> Result<String, NullByteError> {
74 let wide_text = CWString::new(text)?;
75 let translated = unsafe {
76 let handle = CONFIG_HANDLE
77 .get()
78 .expect("Config handle not initialized")
79 .lock()
80 .unwrap();
81 (handle
82 .raw
83 .as_ref()
84 .expect("Config handle raw pointer is null")
85 .translate)(handle.raw, wide_text.as_ptr())
86 };
87 Ok(unsafe { load_wide_string(translated) })
88}
89
90pub fn get_language_text(section: &str, text: &str) -> String {
93 match get_language_text_strict(section, text) {
94 Ok(translated) => translated,
95 Err(_) => text.to_string(),
96 }
97}
98
99pub fn get_language_text_strict(section: &str, text: &str) -> Result<String, NullByteError> {
108 let wide_section = CWString::new(section)?;
109 let wide_text = CWString::new(text)?;
110 let translated = unsafe {
111 let handle = CONFIG_HANDLE
112 .get()
113 .expect("Config handle not initialized")
114 .lock()
115 .unwrap();
116 (handle
117 .raw
118 .as_ref()
119 .expect("Config handle raw pointer is null")
120 .get_language_text)(handle.raw, wide_section.as_ptr(), wide_text.as_ptr())
121 };
122 Ok(unsafe { load_wide_string(translated) })
123}
124
125pub fn get_font_info(key: &str) -> Result<FontInfo, std::ffi::NulError> {
135 let c_key = std::ffi::CString::new(key)?;
136 let font_info = unsafe {
137 let handle = CONFIG_HANDLE
138 .get()
139 .expect("Config handle not initialized")
140 .lock()
141 .unwrap();
142 let font_info_ptr = (handle
143 .raw
144 .as_ref()
145 .expect("Config handle raw pointer is null")
146 .get_font_info)(handle.raw, c_key.as_ptr());
147 FontInfo::from_raw(font_info_ptr)
148 };
149 Ok(font_info)
150}
151
152pub fn get_color_code(key: &str) -> Result<Option<(u8, u8, u8)>, std::ffi::NulError> {
166 get_all_color_codes(key).map(|codes| codes.into_iter().next())
167}
168
169pub fn get_all_color_codes(key: &str) -> Result<Vec<(u8, u8, u8)>, std::ffi::NulError> {
179 let c_key = std::ffi::CString::new(key)?;
180 let color_codes = unsafe {
181 let handle = CONFIG_HANDLE
182 .get()
183 .expect("Config handle not initialized")
184 .lock()
185 .unwrap();
186 let count = (handle
187 .raw
188 .as_ref()
189 .expect("Config handle raw pointer is null")
190 .get_color_code_index)(handle.raw, c_key.as_ptr(), -1);
191 let mut codes = Vec::with_capacity(count as usize);
192 for i in 0..count {
193 let color_code = (handle
194 .raw
195 .as_ref()
196 .expect("Config handle raw pointer is null")
197 .get_color_code_index)(handle.raw, c_key.as_ptr(), i);
198 let r = ((color_code >> 16) & 0xFF) as u8;
199 let g = ((color_code >> 8) & 0xFF) as u8;
200 let b = (color_code & 0xFF) as u8;
201 codes.push((r, g, b));
202 }
203 codes
204 };
205 Ok(color_codes)
206}
207
208pub fn get_layout_size(key: &str) -> Result<i32, std::ffi::NulError> {
218 let c_key = std::ffi::CString::new(key)?;
219 let layout_size = unsafe {
220 let handle = CONFIG_HANDLE
221 .get()
222 .expect("Config handle not initialized")
223 .lock()
224 .unwrap();
225 (handle
226 .raw
227 .as_ref()
228 .expect("Config handle raw pointer is null")
229 .get_layout_size)(handle.raw, c_key.as_ptr())
230 };
231 Ok(layout_size)
232}
233
234#[doc(hidden)]
235pub fn __initialize_config_handle(raw: *mut aviutl2_sys::config2::CONFIG_HANDLE) {
236 CONFIG_HANDLE
237 .set(std::sync::Mutex::new(InternalConfigHandle { raw }))
238 .unwrap_or_else(|_| {
239 panic!("Config handle is already initialized");
240 });
241}
242
243#[doc(hidden)]
244pub fn __initialize_config_handle_unwind(raw: *mut aviutl2_sys::config2::CONFIG_HANDLE) {
245 if let Err(panic_info) =
246 crate::__catch_unwind_with_panic_info(|| __initialize_config_handle(raw))
247 {
248 tracing::error!("Panic occurred during InitializeConfig: {}", panic_info);
249 let _ = crate::logger::write_error_log(&panic_info);
250 }
251}