vapoursynth/vsscript/
mod.rs

1//! VapourSynth script-related things.
2
3use std::ptr::{self, NonNull};
4use std::sync::atomic::{AtomicPtr, Ordering};
5use vapoursynth_sys as ffi;
6
7/// A wrapper for the VSScript API.
8#[derive(Debug, Clone, Copy)]
9pub(crate) struct VSScriptAPI {
10    handle: NonNull<ffi::VSSCRIPTAPI>,
11}
12
13unsafe impl Send for VSScriptAPI {}
14unsafe impl Sync for VSScriptAPI {}
15
16/// A cached VSScript API pointer.
17static RAW_VSSCRIPT_API: AtomicPtr<ffi::VSSCRIPTAPI> = AtomicPtr::new(ptr::null_mut());
18
19impl VSScriptAPI {
20    /// Retrieves the VSScript API.
21    ///
22    /// Returns `None` on error, for example if the requested API version is not supported.
23    #[inline]
24    pub(crate) fn get() -> Option<Self> {
25        // Check if we already have the API.
26        let handle = RAW_VSSCRIPT_API.load(Ordering::Relaxed);
27
28        let handle = if handle.is_null() {
29            // Attempt retrieving it otherwise.
30            let version = ffi::VSSCRIPT_API_MAJOR << 16 | ffi::VSSCRIPT_API_MINOR;
31            let handle = unsafe { ffi::getVSScriptAPI(version as i32) } as *mut ffi::VSSCRIPTAPI;
32
33            if !handle.is_null() {
34                // Verify the VSScript API version.
35                let api_version = unsafe { ((*handle).getAPIVersion.unwrap())() };
36                let major = api_version >> 16;
37                let minor = api_version & 0xFFFF;
38
39                if major as u32 != ffi::VSSCRIPT_API_MAJOR {
40                    panic!(
41                        "Invalid VSScript major API version (expected: {}, got: {})",
42                        ffi::VSSCRIPT_API_MAJOR,
43                        major
44                    );
45                } else if (minor as u32) < ffi::VSSCRIPT_API_MINOR {
46                    panic!(
47                        "Invalid VSScript minor API version (expected: >= {}, got: {})",
48                        ffi::VSSCRIPT_API_MINOR,
49                        minor
50                    );
51                }
52
53                // If we successfully retrieved the API, cache it.
54                RAW_VSSCRIPT_API.store(handle, Ordering::Relaxed);
55            }
56            handle
57        } else {
58            handle
59        };
60
61        if handle.is_null() {
62            None
63        } else {
64            Some(Self {
65                handle: unsafe { NonNull::new_unchecked(handle) },
66            })
67        }
68    }
69
70    #[inline]
71    pub(crate) fn handle(&self) -> &ffi::VSSCRIPTAPI {
72        unsafe { self.handle.as_ref() }
73    }
74}
75
76mod errors;
77pub use self::errors::{Error, VSScriptError};
78
79mod environment;
80pub use self::environment::{Environment, EvalFlags};