use capi::sctypes::{UINT, LPCBYTE, LPCSTR};
use capi::scom::som_passport_t;
pub type Result<T> = ::std::result::Result<T, ()>;
#[repr(C)]
pub enum COLOR_SPACE {
Unknown,
Yv12,
Iyuv,
Nv12,
Yuy2,
Rgb24,
Rgb555,
Rgb565,
Rgb32,
}
macro_rules! cppcall {
($this:ident . $func:ident ()) => {
unsafe {
((*$this.vtbl).$func)($this as *mut _)
}
};
(const $this:ident . $func:ident ()) => {
unsafe {
((*$this.vtbl).$func)($this as *const _)
}
};
($this:ident . $func:ident ( $( $arg:expr ),* )) => {
unsafe {
((*$this.vtbl).$func)($this as *mut _, $($arg),* )
}
};
(const $this:ident . $func:ident ( $( $arg:expr ),* )) => {
unsafe {
((*$this.vtbl).$func)($this as *const _, $($arg),* )
}
};
}
macro_rules! cppresult {
( $( $t:tt )* ) => {
if cppcall!( $($t)* ) {
Ok(())
} else {
Err(())
}
}
}
#[doc(hidden)]
pub trait NamedInterface {
fn get_interface_name() -> &'static [u8];
fn query_interface(from: &mut iasset) -> Option<* mut iasset> {
let mut out: *mut iasset = ::std::ptr::null_mut();
from.get_interface(Self::get_interface_name().as_ptr() as LPCSTR, &mut out as *mut _);
if !out.is_null() {
Some(out)
} else {
None
}
}
}
impl NamedInterface for video_source {
fn get_interface_name() -> &'static [u8] {
b"source.video.sciter.com\0"
}
}
impl NamedInterface for video_destination {
fn get_interface_name() -> &'static [u8] {
b"destination.video.sciter.com\0"
}
}
impl NamedInterface for fragmented_video_destination {
fn get_interface_name() -> &'static [u8] {
b"fragmented.destination.video.sciter.com\0"
}
}
#[repr(C)]
struct iasset_vtbl {
pub add_ref: extern "C" fn(this: *mut iasset) -> i32,
pub release: extern "C" fn(this: *mut iasset) -> i32,
pub get_interface: extern "C" fn(this: *mut iasset, name: LPCSTR, out: *mut *mut iasset) -> bool,
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
}
#[repr(C)]
pub struct iasset {
vtbl: *const iasset_vtbl,
}
impl iasset {
fn add_ref(&mut self) -> i32 {
cppcall!(self.add_ref())
}
fn release(&mut self) -> i32 {
cppcall!(self.release())
}
pub fn get_interface(&mut self, name: LPCSTR, out: *mut *mut iasset) -> bool {
cppcall!(self.get_interface(name, out))
}
}
#[repr(C)]
struct video_source_vtbl {
pub add_ref: extern "C" fn(this: *mut video_source) -> i32,
pub release: extern "C" fn(this: *mut video_source) -> i32,
pub get_interface: extern "C" fn(this: *mut video_source, name: *const u8, out: *mut *mut iasset) -> bool,
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
pub play: extern "C" fn(this: *mut video_source) -> bool,
pub pause: extern "C" fn(this: *mut video_source) -> bool,
pub stop: extern "C" fn(this: *mut video_source) -> bool,
pub get_is_ended: extern "C" fn(this: *const video_source, is_end: *mut bool) -> bool,
pub get_position: extern "C" fn(this: *const video_source, seconds: *mut f64) -> bool,
pub set_position: extern "C" fn(this: *mut video_source, seconds: f64) -> bool,
pub get_duration: extern "C" fn(this: *const video_source, seconds: *mut f64) -> bool,
pub get_volume: extern "C" fn(this: *const video_source, volume: *mut f64) -> bool,
pub set_volume: extern "C" fn(this: *mut video_source, volume: f64) -> bool,
pub get_balance: extern "C" fn(this: *const video_source, balance: *mut f64) -> bool,
pub set_balance: extern "C" fn(this: *mut video_source, balance: f64) -> bool,
}
#[repr(C)]
pub struct video_source {
vtbl: *const video_source_vtbl,
}
impl video_source {
pub fn play(&mut self) -> Result<()> {
cppresult!(self.play())
}
pub fn pause(&mut self) -> Result<()> {
cppresult!(self.pause())
}
pub fn stop(&mut self) -> Result<()> {
cppresult!(self.stop())
}
pub fn is_ended(&self) -> Result<bool> {
let mut r = false;
cppresult!(const self.get_is_ended(&mut r as *mut _)).map(|_| r)
}
pub fn get_position(&self) -> Result<f64> {
let mut r = 0f64;
cppresult!(const self.get_position(&mut r as *mut _)).map(|_| r)
}
pub fn set_position(&mut self, seconds: f64) -> Result<()> {
cppresult!(self.set_position(seconds))
}
pub fn get_duration(&self) -> Result<f64> {
let mut r = 0f64;
cppresult!(const self.get_duration(&mut r as *mut _)).map(|_| r)
}
pub fn get_volume(&self) -> Result<f64> {
let mut r = 0f64;
cppresult!(const self.get_volume(&mut r as *mut _)).map(|_| r)
}
pub fn set_volume(&mut self, volume: f64) -> Result<()> {
cppresult!(self.set_volume(volume))
}
pub fn get_balance(&self) -> Result<f64> {
let mut r = 0f64;
cppresult!(const self.get_balance(&mut r as *mut _)).map(|_| r)
}
pub fn set_balance(&mut self, balance: f64) -> Result<()> {
cppresult!(self.set_balance(balance))
}
}
#[repr(C)]
struct video_destination_vtbl {
pub add_ref: extern "C" fn(this: *mut video_destination) -> i32,
pub release: extern "C" fn(this: *mut video_destination) -> i32,
pub get_interface: extern "C" fn(this: *mut video_destination, name: *const u8, out: *mut *mut iasset) -> bool,
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
pub is_alive: extern "C" fn(this: *const video_destination) -> bool,
pub start_streaming: extern "C" fn(this: *mut video_destination, frame_width: i32, frame_height: i32, color_space: COLOR_SPACE, src: *const video_source) -> bool,
pub stop_streaming: extern "C" fn(this: *mut video_destination) -> bool,
pub render_frame: extern "C" fn(this: *mut video_destination, data: LPCBYTE, size: UINT) -> bool,
}
#[repr(C)]
pub struct video_destination {
vtbl: *const video_destination_vtbl,
}
impl video_destination {
pub fn is_alive(&self) -> bool {
cppcall!(const self.is_alive())
}
pub fn start_streaming(&mut self, frame_size: (i32, i32), color_space: COLOR_SPACE, src: Option<&video_source>) -> Result<()> {
let src_ptr = if let Some(ptr) = src { ptr as *const _ } else { ::std::ptr::null() };
cppresult!(self.start_streaming(frame_size.0, frame_size.1, color_space, src_ptr))
}
pub fn stop_streaming(&mut self) -> Result<()> {
cppresult!(self.stop_streaming())
}
pub fn render_frame(&mut self, data: &[u8]) -> Result<()> {
cppresult!(self.render_frame(data.as_ptr(), data.len() as UINT))
}
}
#[repr(C)]
struct fragmented_video_destination_vtbl {
pub add_ref: extern "C" fn(this: *mut fragmented_video_destination) -> i32,
pub release: extern "C" fn(this: *mut fragmented_video_destination) -> i32,
pub get_interface: extern "C" fn(this: *mut fragmented_video_destination, name: *const u8, out: *mut *mut iasset) -> bool,
pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
pub is_alive: extern "C" fn(this: *const fragmented_video_destination) -> bool,
pub start_streaming: extern "C" fn(this: *mut fragmented_video_destination, frame_width: i32, frame_height: i32, color_space: COLOR_SPACE, src: *const video_source) -> bool,
pub stop_streaming: extern "C" fn(this: *mut fragmented_video_destination) -> bool,
pub render_frame: extern "C" fn(this: *mut fragmented_video_destination, data: LPCBYTE, size: UINT) -> bool,
pub render_frame_part: extern "C" fn(this: *mut fragmented_video_destination, data: LPCBYTE, size: UINT, x: i32, y: i32, width: i32, height: i32) -> bool,
}
#[repr(C)]
pub struct fragmented_video_destination {
vtbl: *const fragmented_video_destination_vtbl,
}
impl fragmented_video_destination {
pub fn is_alive(&self) -> bool {
cppcall!(const self.is_alive())
}
pub fn start_streaming(&mut self, frame_size: (i32, i32), color_space: COLOR_SPACE, src: Option<&video_source>) -> Result<()> {
let src_ptr = if let Some(ptr) = src { ptr as *const _ } else { ::std::ptr::null() };
cppresult!(self.start_streaming(frame_size.0, frame_size.1, color_space, src_ptr))
}
pub fn stop_streaming(&mut self) -> Result<()> {
cppresult!(self.stop_streaming())
}
pub fn render_frame(&mut self, data: &[u8]) -> Result<()> {
cppresult!(self.render_frame(data.as_ptr(), data.len() as UINT))
}
pub fn render_frame_part(&mut self, data: &[u8], update_point: (i32, i32), update_size: (i32, i32)) -> Result<()> {
cppresult!(self.render_frame_part(data.as_ptr(), data.len() as UINT, update_point.0, update_point.1, update_size.0, update_size.1))
}
}
pub struct AssetPtr<T> {
ptr: *mut T,
}
unsafe impl<T> Send for AssetPtr<T> {}
use ::std::ops::{Deref, DerefMut};
impl Deref for AssetPtr<video_destination> {
type Target = video_destination;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr }
}
}
impl DerefMut for AssetPtr<video_destination> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.ptr }
}
}
impl Deref for AssetPtr<fragmented_video_destination> {
type Target = fragmented_video_destination;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr }
}
}
impl DerefMut for AssetPtr<fragmented_video_destination> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.ptr }
}
}
impl<T> Drop for AssetPtr<T> {
fn drop(&mut self) {
self.get().release();
}
}
impl<T> AssetPtr<T> {
fn attach(lp: *mut T) -> Self {
assert!(!lp.is_null());
Self {
ptr: lp
}
}
pub fn adopt(lp: *mut T) -> Self {
let mut me = Self::attach(lp);
me.get().add_ref();
me
}
fn get(&mut self) -> &mut iasset {
let ptr = self.ptr as *mut iasset;
unsafe { &mut *ptr }
}
}
impl<T> From<*mut T> for AssetPtr<T> {
fn from(lp: *mut T) -> Self {
AssetPtr::adopt(lp)
}
}
impl<T: NamedInterface> AssetPtr<T> {
pub fn try_from<U>(other: &mut AssetPtr<U>) -> Result<Self> {
let me = T::query_interface(other.get());
me.map(|p| AssetPtr::adopt(p as *mut T)).ok_or(())
}
}