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/// [`get_language_text_strict`]と異なり、テキストにnull byteが含まれている場合は元のテキストを返却します。
92pub 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
99/// 現在の言語設定で定義されているテキストを取得する。
100///
101/// 任意のセクションから取得出来ます。
102///
103/// # Arguments
104///
105/// - `section`: 言語設定のセクション(.aul2ファイルのセクション名)
106/// - `text`: 元のテキスト(.aul2ファイルのキー名)
107pub 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
125/// 設定ファイルで定義されているフォント情報を取得する。
126///
127/// # Note
128///
129/// 取得出来ない場合はデフォルトのフォントが返却されます。
130///
131/// # Arguments
132///
133/// - `key`: 設定ファイル(style.conf)の`[Font]`のキー名
134pub 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
152/// 設定ファイルで定義されている色コードを取得する。
153///
154/// # Note
155///
156/// 複数の色が定義されている場合は最初の色が取得されます。
157///
158/// # Arguments
159///
160/// - `key`: 設定ファイル(style.conf)の`[Color]`のキー名
161///
162/// # See Also
163///
164/// - [`get_all_color_codes`]
165pub 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
169/// 設定ファイルで定義されている色コードを取得する。
170///
171/// # Arguments
172///
173/// - `key`: 設定ファイル(style.conf)の`[Color]`のキー名
174///
175/// # See Also
176///
177/// - [`get_color_code`]
178pub 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
208/// 設定ファイルで定義されているレイアウトサイズを取得する。
209///
210/// # Note
211///
212/// 取得出来ない場合は0が返却されます。
213///
214/// # Arguments
215///
216/// - `key`: 設定ファイル(style.conf)の`[Layout]`のキー名
217pub 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}