From aa98fad1263765708b89d93bb8b31a18c0743bca Mon Sep 17 00:00:00 2001 From: David Wendt Date: Mon, 4 Jan 2021 21:57:06 -0500 Subject: [PATCH] avm1: Stub impl the `Video` class. --- core/src/avm1/globals.rs | 13 ++++++++++++ core/src/avm1/globals/video.rs | 30 +++++++++++++++++++++++++++ core/src/display_object/video.rs | 35 ++++++++++++++++++++++++++------ 3 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 core/src/avm1/globals/video.rs diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index 12f3b77b7..6a5ea9212 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -55,6 +55,7 @@ pub(crate) mod system_security; pub(crate) mod text_field; mod text_format; mod transform; +mod video; mod xml; pub fn random<'gc>( @@ -506,6 +507,8 @@ pub struct SystemPrototypes<'gc> { pub date: Object<'gc>, pub bitmap_data: Object<'gc>, pub bitmap_data_constructor: Object<'gc>, + pub video: Object<'gc>, + pub video_constructor: Object<'gc>, } /// Initialize default global scope and builtins for an AVM1 instance. @@ -582,6 +585,8 @@ pub fn create_globals<'gc>( ); let date_proto: Object<'gc> = date::create_proto(gc_context, object_proto, function_proto); + let video_proto: Object<'gc> = video::create_proto(gc_context, object_proto, function_proto); + //TODO: These need to be constructors and should also set `.prototype` on each one let object = object::create_object_object(gc_context, object_proto, function_proto); @@ -697,6 +702,12 @@ pub fn create_globals<'gc>( Some(function_proto), transform_proto, ); + let video = FunctionObject::constructor( + gc_context, + Executable::Native(video::constructor), + Some(function_proto), + video_proto, + ); flash.define_value(gc_context, "geom", geom.into(), Attribute::empty()); flash.define_value(gc_context, "filters", filters.into(), Attribute::empty()); @@ -1255,6 +1266,8 @@ pub fn create_globals<'gc>( date: date_proto, bitmap_data: bitmap_data_proto, bitmap_data_constructor: bitmap_data, + video: video_proto, + video_constructor: video, }, globals.into(), broadcaster_functions, diff --git a/core/src/avm1/globals/video.rs b/core/src/avm1/globals/video.rs new file mode 100644 index 000000000..b0724e84d --- /dev/null +++ b/core/src/avm1/globals/video.rs @@ -0,0 +1,30 @@ +//! Video class + +use crate::avm1::activation::Activation; +use crate::avm1::error::Error; +use crate::avm1::globals::display_object; +use crate::avm1::object::Object; +use crate::avm1::value::Value; +use crate::avm1::ScriptObject; +use gc_arena::MutationContext; + +/// Implements `Video` +pub fn constructor<'gc>( + _activation: &mut Activation<'_, 'gc, '_>, + _this: Object<'gc>, + _args: &[Value<'gc>], +) -> Result, Error<'gc>> { + Ok(Value::Undefined) +} + +pub fn create_proto<'gc>( + gc_context: MutationContext<'gc, '_>, + proto: Object<'gc>, + fn_proto: Object<'gc>, +) -> Object<'gc> { + let object = ScriptObject::object(gc_context, Some(proto)); + + display_object::define_display_object_proto(gc_context, object, fn_proto); + + object.into() +} diff --git a/core/src/display_object/video.rs b/core/src/display_object/video.rs index 9c7bc4adb..b6348a4a3 100644 --- a/core/src/display_object/video.rs +++ b/core/src/display_object/video.rs @@ -1,6 +1,6 @@ //! Video player display object -use crate::avm1::Object as Avm1Object; +use crate::avm1::{Object as Avm1Object, StageObject as Avm1StageObject}; use crate::backend::render::BitmapHandle; use crate::backend::video::{EncodedFrame, VideoStreamHandle}; use crate::bounding_box::BoundingBox; @@ -10,7 +10,7 @@ use crate::display_object::{DisplayObjectBase, TDisplayObject}; use crate::prelude::*; use crate::tag_utils::{SwfMovie, SwfSlice}; use crate::types::{Degrees, Percent}; -use crate::vminterface::Instantiator; +use crate::vminterface::{AvmObject, AvmType, Instantiator}; use gc_arena::{Collect, GcCell, MutationContext}; use std::borrow::{Borrow, BorrowMut}; use std::collections::BTreeMap; @@ -40,6 +40,9 @@ pub struct VideoData<'gc> { /// The last decoded frame in the video stream. decoded_frame: Option>, + + /// AVM representation of this video player. + object: Option>, } #[derive(Clone, Debug, Collect)] @@ -83,6 +86,7 @@ impl<'gc> Video<'gc> { source, stream: None, decoded_frame: None, + object: None, }, )) } @@ -176,15 +180,17 @@ impl<'gc> TDisplayObject<'gc> for Video<'gc> { fn post_instantiation( &self, context: &mut UpdateContext<'_, 'gc, '_>, - _display_object: DisplayObject<'gc>, + display_object: DisplayObject<'gc>, _init_object: Option>, _instantiated_by: Instantiator, run_frame: bool, ) { let mut write = self.0.write(context.gc_context); - let stream = match &*write.source.read() { - VideoSource::SWF { streamdef, .. } => { + let (stream, movie) = match &*write.source.read() { + VideoSource::SWF { + streamdef, movie, .. + } => { let stream = context.video.register_video_stream( streamdef.num_frames.into(), (streamdef.width, streamdef.height), @@ -199,11 +205,28 @@ impl<'gc> TDisplayObject<'gc> for Video<'gc> { return; } - Some(CollectWrapper(stream.unwrap())) + (Some(CollectWrapper(stream.unwrap())), movie.clone()) } }; write.stream = stream; + + if write.object.is_none() { + let library = context.library.library_for_movie_mut(movie); + let vm_type = library.avm_type(); + if vm_type == AvmType::Avm2 { + //TODO: AVM2 me, cap'n. + } else if vm_type == AvmType::Avm1 { + let object: Avm1Object<'_> = Avm1StageObject::for_display_object( + context.gc_context, + display_object, + Some(context.avm1.prototypes().video), + ) + .into(); + write.object = Some(object.into()); + } + } + drop(write); self.seek(context, 0);