1use capi::sctypes::{UINT, LPCBYTE, LPCSTR};
9use capi::scom::som_passport_t;
10
11pub type Result<T> = ::std::result::Result<T, ()>;
13
14
15#[repr(C)]
17pub enum COLOR_SPACE {
18 Unknown,
19
20 Yv12,
21 Iyuv,
23 Nv12,
24 Yuy2,
25
26 Rgb24,
27 Rgb555,
28 Rgb565,
29 Rgb32,
30}
31
32macro_rules! cppcall {
33 ($this:ident . $func:ident ()) => {
35 unsafe {
36 ((*$this.vtbl).$func)($this as *mut _)
37 }
38 };
39 (const $this:ident . $func:ident ()) => {
40 unsafe {
41 ((*$this.vtbl).$func)($this as *const _)
42 }
43 };
44
45 ($this:ident . $func:ident ( $( $arg:expr ),* )) => {
47 unsafe {
48 ((*$this.vtbl).$func)($this as *mut _, $($arg),* )
49 }
50 };
51 (const $this:ident . $func:ident ( $( $arg:expr ),* )) => {
52 unsafe {
53 ((*$this.vtbl).$func)($this as *const _, $($arg),* )
54 }
55 };
56}
57
58macro_rules! cppresult {
59 ( $( $t:tt )* ) => {
60 if cppcall!( $($t)* ) {
61 Ok(())
62 } else {
63 Err(())
64 }
65 }
66}
67
68#[doc(hidden)]
69pub trait NamedInterface {
70 fn get_interface_name() -> &'static [u8];
71
72 fn query_interface(from: &mut iasset) -> Option<* mut iasset> {
73 let mut out: *mut iasset = ::std::ptr::null_mut();
74 from.get_interface(Self::get_interface_name().as_ptr() as LPCSTR, &mut out as *mut _);
75 if !out.is_null() {
76 Some(out)
77 } else {
78 None
79 }
80 }
81}
82
83impl NamedInterface for video_source {
84 fn get_interface_name() -> &'static [u8] {
85 b"source.video.sciter.com\0"
86 }
87}
88
89impl NamedInterface for video_destination {
90 fn get_interface_name() -> &'static [u8] {
91 b"destination.video.sciter.com\0"
92 }
93}
94
95impl NamedInterface for fragmented_video_destination {
96 fn get_interface_name() -> &'static [u8] {
97 b"fragmented.destination.video.sciter.com\0"
98 }
99}
100
101
102#[repr(C)]
104struct iasset_vtbl {
105 pub add_ref: extern "C" fn(this: *mut iasset) -> i32,
107
108 pub release: extern "C" fn(this: *mut iasset) -> i32,
110
111 pub get_interface: extern "C" fn(this: *mut iasset, name: LPCSTR, out: *mut *mut iasset) -> bool,
113
114 pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
116}
117
118#[repr(C)]
120pub struct iasset {
121 vtbl: *const iasset_vtbl,
122}
123
124impl iasset {
125 fn add_ref(&mut self) -> i32 {
127 cppcall!(self.add_ref())
128 }
129
130 fn release(&mut self) -> i32 {
132 cppcall!(self.release())
133 }
134
135 pub fn get_interface(&mut self, name: LPCSTR, out: *mut *mut iasset) -> bool {
137 cppcall!(self.get_interface(name, out))
138 }
139}
140
141
142#[repr(C)]
144struct video_source_vtbl {
145 pub add_ref: extern "C" fn(this: *mut video_source) -> i32,
148
149 pub release: extern "C" fn(this: *mut video_source) -> i32,
151
152 pub get_interface: extern "C" fn(this: *mut video_source, name: *const u8, out: *mut *mut iasset) -> bool,
154
155 pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
157 pub play: extern "C" fn(this: *mut video_source) -> bool,
161 pub pause: extern "C" fn(this: *mut video_source) -> bool,
162 pub stop: extern "C" fn(this: *mut video_source) -> bool,
163
164 pub get_is_ended: extern "C" fn(this: *const video_source, is_end: *mut bool) -> bool,
165
166 pub get_position: extern "C" fn(this: *const video_source, seconds: *mut f64) -> bool,
167 pub set_position: extern "C" fn(this: *mut video_source, seconds: f64) -> bool,
168
169 pub get_duration: extern "C" fn(this: *const video_source, seconds: *mut f64) -> bool,
170
171 pub get_volume: extern "C" fn(this: *const video_source, volume: *mut f64) -> bool,
172 pub set_volume: extern "C" fn(this: *mut video_source, volume: f64) -> bool,
173
174 pub get_balance: extern "C" fn(this: *const video_source, balance: *mut f64) -> bool,
175 pub set_balance: extern "C" fn(this: *mut video_source, balance: f64) -> bool,
176 }
178
179#[repr(C)]
181pub struct video_source {
182 vtbl: *const video_source_vtbl,
183}
184
185impl video_source {
186 pub fn play(&mut self) -> Result<()> {
188 cppresult!(self.play())
189 }
190
191 pub fn pause(&mut self) -> Result<()> {
193 cppresult!(self.pause())
194 }
195
196 pub fn stop(&mut self) -> Result<()> {
198 cppresult!(self.stop())
199 }
200
201 pub fn is_ended(&self) -> Result<bool> {
203 let mut r = false;
204 cppresult!(const self.get_is_ended(&mut r as *mut _)).map(|_| r)
205 }
206
207 pub fn get_position(&self) -> Result<f64> {
209 let mut r = 0f64;
210 cppresult!(const self.get_position(&mut r as *mut _)).map(|_| r)
211 }
212
213 pub fn set_position(&mut self, seconds: f64) -> Result<()> {
215 cppresult!(self.set_position(seconds))
216 }
217
218 pub fn get_duration(&self) -> Result<f64> {
222 let mut r = 0f64;
223 cppresult!(const self.get_duration(&mut r as *mut _)).map(|_| r)
224 }
225
226 pub fn get_volume(&self) -> Result<f64> {
230 let mut r = 0f64;
231 cppresult!(const self.get_volume(&mut r as *mut _)).map(|_| r)
232 }
233
234 pub fn set_volume(&mut self, volume: f64) -> Result<()> {
236 cppresult!(self.set_volume(volume))
237 }
238
239 pub fn get_balance(&self) -> Result<f64> {
241 let mut r = 0f64;
242 cppresult!(const self.get_balance(&mut r as *mut _)).map(|_| r)
243 }
244
245 pub fn set_balance(&mut self, balance: f64) -> Result<()> {
247 cppresult!(self.set_balance(balance))
248 }
249}
250
251
252#[repr(C)]
254struct video_destination_vtbl {
255 pub add_ref: extern "C" fn(this: *mut video_destination) -> i32,
258
259 pub release: extern "C" fn(this: *mut video_destination) -> i32,
261
262 pub get_interface: extern "C" fn(this: *mut video_destination, name: *const u8, out: *mut *mut iasset) -> bool,
264
265 pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
267 pub is_alive: extern "C" fn(this: *const video_destination) -> bool,
272
273 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,
275
276 pub stop_streaming: extern "C" fn(this: *mut video_destination) -> bool,
278
279 pub render_frame: extern "C" fn(this: *mut video_destination, data: LPCBYTE, size: UINT) -> bool,
281
282 pub render_frame_with_stride: extern "C" fn(this: *mut video_destination, data: LPCBYTE, size: UINT, stride: UINT) -> bool,
284 }
286
287#[repr(C)]
289pub struct video_destination {
290 vtbl: *const video_destination_vtbl,
291}
292
293impl video_destination {
294
295 pub fn is_alive(&self) -> bool {
297 cppcall!(const self.is_alive())
298 }
299
300 pub fn start_streaming(&mut self, frame_size: (i32, i32), color_space: COLOR_SPACE, src: Option<&video_source>) -> Result<()> {
306 let src_ptr = if let Some(ptr) = src { ptr as *const _ } else { ::std::ptr::null() };
307 cppresult!(self.start_streaming(frame_size.0, frame_size.1, color_space, src_ptr))
308 }
309
310 pub fn stop_streaming(&mut self) -> Result<()> {
312 cppresult!(self.stop_streaming())
313 }
314
315 pub fn render_frame(&mut self, data: &[u8]) -> Result<()> {
317 cppresult!(self.render_frame(data.as_ptr(), data.len() as UINT))
318 }
319
320 pub fn render_frame_with_stride(&mut self, data: &[u8], stride: u32) -> Result<()> {
322 cppresult!(self.render_frame_with_stride(data.as_ptr(), data.len() as UINT, stride))
323 }
324}
325
326
327#[repr(C)]
329struct fragmented_video_destination_vtbl {
330 pub add_ref: extern "C" fn(this: *mut fragmented_video_destination) -> i32,
333
334 pub release: extern "C" fn(this: *mut fragmented_video_destination) -> i32,
336
337 pub get_interface: extern "C" fn(this: *mut fragmented_video_destination, name: *const u8, out: *mut *mut iasset) -> bool,
339
340 pub get_passport: extern "C" fn(thing: *mut iasset) -> *const som_passport_t,
342 pub is_alive: extern "C" fn(this: *const fragmented_video_destination) -> bool,
347
348 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,
350
351 pub stop_streaming: extern "C" fn(this: *mut fragmented_video_destination) -> bool,
353
354 pub render_frame: extern "C" fn(this: *mut fragmented_video_destination, data: LPCBYTE, size: UINT) -> bool,
356
357 pub render_frame_with_stride: extern "C" fn(this: *mut fragmented_video_destination, data: LPCBYTE, size: UINT, stride: UINT) -> bool,
359 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,
364 }
366
367#[repr(C)]
369pub struct fragmented_video_destination {
370 vtbl: *const fragmented_video_destination_vtbl,
371}
372
373impl fragmented_video_destination {
374
375 pub fn is_alive(&self) -> bool {
377 cppcall!(const self.is_alive())
378 }
379
380 pub fn start_streaming(&mut self, frame_size: (i32, i32), color_space: COLOR_SPACE, src: Option<&video_source>) -> Result<()> {
386 let src_ptr = if let Some(ptr) = src { ptr as *const _ } else { ::std::ptr::null() };
387 cppresult!(self.start_streaming(frame_size.0, frame_size.1, color_space, src_ptr))
388 }
389
390 pub fn stop_streaming(&mut self) -> Result<()> {
392 cppresult!(self.stop_streaming())
393 }
394
395 pub fn render_frame(&mut self, data: &[u8]) -> Result<()> {
397 cppresult!(self.render_frame(data.as_ptr(), data.len() as UINT))
398 }
399
400 pub fn render_frame_with_stride(&mut self, data: &[u8], stride: u32) -> Result<()> {
402 cppresult!(self.render_frame_with_stride(data.as_ptr(), data.len() as UINT, stride))
403 }
404
405 pub fn render_frame_part(&mut self, data: &[u8], update_point: (i32, i32), update_size: (i32, i32)) -> Result<()> {
410 cppresult!(self.render_frame_part(data.as_ptr(), data.len() as UINT, update_point.0, update_point.1, update_size.0, update_size.1))
411 }
412}
413
414pub struct AssetPtr<T> {
416 ptr: *mut T,
417}
418
419unsafe impl<T> Send for AssetPtr<T> {}
421
422use ::std::ops::{Deref, DerefMut};
423
424impl Deref for AssetPtr<video_destination> {
425 type Target = video_destination;
426
427 fn deref(&self) -> &Self::Target {
428 unsafe { &*self.ptr }
429 }
430}
431
432impl DerefMut for AssetPtr<video_destination> {
433 fn deref_mut(&mut self) -> &mut Self::Target {
434 unsafe { &mut *self.ptr }
435 }
436}
437
438impl Deref for AssetPtr<fragmented_video_destination> {
439 type Target = fragmented_video_destination;
440
441 fn deref(&self) -> &Self::Target {
442 unsafe { &*self.ptr }
443 }
444}
445
446impl DerefMut for AssetPtr<fragmented_video_destination> {
447 fn deref_mut(&mut self) -> &mut Self::Target {
448 unsafe { &mut *self.ptr }
449 }
450}
451
452impl<T> Drop for AssetPtr<T> {
454 fn drop(&mut self) {
455 self.get().release();
456 }
457}
458
459impl<T> AssetPtr<T> {
460 fn attach(lp: *mut T) -> Self {
462 assert!(!lp.is_null());
463 Self {
464 ptr: lp
465 }
466 }
467
468 pub fn adopt(lp: *mut T) -> Self {
470 let mut me = Self::attach(lp);
471 me.get().add_ref();
472 me
473 }
474
475 fn get(&mut self) -> &mut iasset {
477 let ptr = self.ptr as *mut iasset;
478 unsafe { &mut *ptr }
479 }
480}
481
482
483impl<T> From<*mut T> for AssetPtr<T> {
485 fn from(lp: *mut T) -> Self {
487 AssetPtr::adopt(lp)
488 }
489}
490
491
492impl<T: NamedInterface> AssetPtr<T> {
494
495 pub fn try_from<U>(other: &mut AssetPtr<U>) -> Result<Self> {
507 let me = T::query_interface(other.get());
508 me.map(|p| AssetPtr::adopt(p as *mut T)).ok_or(())
509 }
510}