Skip to main content

aviutl2/
config.rs

1//! AviUtl2の設定関連機能へのインターフェースを提供します。
2
3use crate::{CWString, NullByteError, load_wide_string};
4
5/// フォント情報
6#[derive(Debug, Clone, PartialEq)]
7pub struct FontInfo {
8    /// フォント名
9    pub name: String,
10    /// フォントサイズ
11    pub size: f32,
12}
13impl FontInfo {
14    /// 内部のFONT_INFOからFontInfoを作成する。
15    ///
16    /// # Safety
17    ///
18    /// `font_info_ptr`は有効なポインタである必要があります。
19    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
37/// アプリケーションデータフォルダへのパスを取得する。
38pub 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
55/// 現在の言語設定で定義されているテキストを取得する。
56///
57/// 参照する言語設定のセクションはビルドしたプラグインのファイル名になります。
58/// [`translate_strict`]と異なり、テキストにnull byteが含まれている場合は元のテキストを返却します。
59pub fn translate(text: &str) -> String {
60    match translate_strict(text) {
61        Ok(translated) => translated,
62        Err(_) => text.to_string(),
63    }
64}
65
66/// 現在の言語設定で定義されているテキストを取得する。
67///
68/// 参照する言語設定のセクションはビルドしたプラグインのファイル名になります。
69///
70/// # Arguments
71///
72/// - `text`: 元のテキスト(.aul2ファイルのキー名)
73pub 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
90/// 現在の言語設定で定義されているテキストを取得する。
91///
92/// 任意のセクションから取得出来ます。
93///
94/// # Arguments
95///
96/// - `section`: 言語設定のセクション(.aul2ファイルのセクション名)
97/// - `text`: 元のテキスト(.aul2ファイルのキー名)
98pub fn get_language_text(section: &str, text: &str) -> Result<String, NullByteError> {
99    let wide_section = CWString::new(section)?;
100    let wide_text = CWString::new(text)?;
101    let translated = unsafe {
102        let handle = CONFIG_HANDLE
103            .get()
104            .expect("Config handle not initialized")
105            .lock()
106            .unwrap();
107        (handle
108            .raw
109            .as_ref()
110            .expect("Config handle raw pointer is null")
111            .get_language_text)(handle.raw, wide_section.as_ptr(), wide_text.as_ptr())
112    };
113    Ok(unsafe { load_wide_string(translated) })
114}
115
116/// 設定ファイルで定義されているフォント情報を取得する。
117///
118/// # Note
119///
120/// 取得出来ない場合はデフォルトのフォントが返却されます。
121///
122/// # Arguments
123///
124/// - `key`: 設定ファイル(style.conf)の`[Font]`のキー名
125pub fn get_font_info(key: &str) -> Result<FontInfo, std::ffi::NulError> {
126    let c_key = std::ffi::CString::new(key)?;
127    let font_info = unsafe {
128        let handle = CONFIG_HANDLE
129            .get()
130            .expect("Config handle not initialized")
131            .lock()
132            .unwrap();
133        let font_info_ptr = (handle
134            .raw
135            .as_ref()
136            .expect("Config handle raw pointer is null")
137            .get_font_info)(handle.raw, c_key.as_ptr());
138        FontInfo::from_raw(font_info_ptr)
139    };
140    Ok(font_info)
141}
142
143/// 設定ファイルで定義されている色コードを取得する。
144///
145/// # Note
146///
147/// 複数の色が定義されている場合は最初の色が取得されます。
148///
149/// # Arguments
150///
151/// - `key`: 設定ファイル(style.conf)の`[Color]`のキー名
152///
153/// # See Also
154///
155/// - [`get_all_color_codes`]
156pub fn get_color_code(key: &str) -> Result<Option<(u8, u8, u8)>, std::ffi::NulError> {
157    get_all_color_codes(key).map(|codes| codes.into_iter().next())
158}
159
160/// 設定ファイルで定義されている色コードを取得する。
161///
162/// # Arguments
163///
164/// - `key`: 設定ファイル(style.conf)の`[Color]`のキー名
165///
166/// # See Also
167///
168/// - [`get_color_code`]
169pub fn get_all_color_codes(key: &str) -> Result<Vec<(u8, u8, u8)>, std::ffi::NulError> {
170    let c_key = std::ffi::CString::new(key)?;
171    let color_codes = unsafe {
172        let handle = CONFIG_HANDLE
173            .get()
174            .expect("Config handle not initialized")
175            .lock()
176            .unwrap();
177        let count = (handle
178            .raw
179            .as_ref()
180            .expect("Config handle raw pointer is null")
181            .get_color_code_index)(handle.raw, c_key.as_ptr(), -1);
182        let mut codes = Vec::with_capacity(count as usize);
183        for i in 0..count {
184            let color_code = (handle
185                .raw
186                .as_ref()
187                .expect("Config handle raw pointer is null")
188                .get_color_code_index)(handle.raw, c_key.as_ptr(), i);
189            let r = ((color_code >> 16) & 0xFF) as u8;
190            let g = ((color_code >> 8) & 0xFF) as u8;
191            let b = (color_code & 0xFF) as u8;
192            codes.push((r, g, b));
193        }
194        codes
195    };
196    Ok(color_codes)
197}
198
199/// 設定ファイルで定義されているレイアウトサイズを取得する。
200///
201/// # Note
202///
203/// 取得出来ない場合は0が返却されます。
204///
205/// # Arguments
206///
207/// - `key`: 設定ファイル(style.conf)の`[Layout]`のキー名
208pub fn get_layout_size(key: &str) -> Result<i32, std::ffi::NulError> {
209    let c_key = std::ffi::CString::new(key)?;
210    let layout_size = unsafe {
211        let handle = CONFIG_HANDLE
212            .get()
213            .expect("Config handle not initialized")
214            .lock()
215            .unwrap();
216        (handle
217            .raw
218            .as_ref()
219            .expect("Config handle raw pointer is null")
220            .get_layout_size)(handle.raw, c_key.as_ptr())
221    };
222    Ok(layout_size)
223}
224
225#[doc(hidden)]
226pub fn __initialize_config_handle(raw: *mut aviutl2_sys::config2::CONFIG_HANDLE) {
227    CONFIG_HANDLE
228        .set(std::sync::Mutex::new(InternalConfigHandle { raw }))
229        .unwrap_or_else(|_| {
230            panic!("Config handle is already initialized");
231        });
232}
233
234#[doc(hidden)]
235pub fn __initialize_config_handle_unwind(raw: *mut aviutl2_sys::config2::CONFIG_HANDLE) {
236    if let Err(panic_info) =
237        crate::__catch_unwind_with_panic_info(|| __initialize_config_handle(raw))
238    {
239        tracing::error!("Panic occurred during InitializeConfig: {}", panic_info);
240        let _ = crate::logger::write_error_log(&panic_info);
241    }
242}