3
3
use crate :: avm2:: activation:: Activation ;
4
4
use crate :: avm2:: class:: { Class , ClassAttributes } ;
5
5
use crate :: avm2:: method:: { Method , NativeMethodImpl } ;
6
- use crate :: avm2:: object:: { sound_allocator, Object , SoundChannelObject , TObject } ;
6
+ use crate :: avm2:: object:: { sound_allocator, Object , QueuedPlay , SoundChannelObject , TObject } ;
7
7
use crate :: avm2:: value:: Value ;
8
8
use crate :: avm2:: Error ;
9
9
use crate :: avm2:: Multiname ;
@@ -12,20 +12,24 @@ use crate::avm2::QName;
12
12
use crate :: backend:: navigator:: Request ;
13
13
use crate :: character:: Character ;
14
14
use crate :: display_object:: SoundTransform ;
15
- use crate :: { avm2_stub_getter, avm2_stub_method} ;
15
+ use crate :: { avm2_stub_constructor , avm2_stub_getter, avm2_stub_method} ;
16
16
use gc_arena:: { GcCell , MutationContext } ;
17
17
use swf:: { SoundEvent , SoundInfo } ;
18
18
19
19
/// Implements `flash.media.Sound`'s instance constructor.
20
20
pub fn instance_init < ' gc > (
21
21
activation : & mut Activation < ' _ , ' gc > ,
22
22
this : Option < Object < ' gc > > ,
23
- _args : & [ Value < ' gc > ] ,
23
+ args : & [ Value < ' gc > ] ,
24
24
) -> Result < Value < ' gc > , Error < ' gc > > {
25
25
if let Some ( this) = this {
26
26
activation. super_init ( this, & [ ] ) ?;
27
27
28
- if this. as_sound ( ) . is_none ( ) {
28
+ if !args. is_empty ( ) {
29
+ avm2_stub_constructor ! ( activation, "flash.media.Sound" , "with arguments" ) ;
30
+ }
31
+
32
+ if let Some ( sound_object) = this. as_sound_object ( ) {
29
33
let class_object = this
30
34
. instance_of ( )
31
35
. ok_or ( "Attempted to construct Sound on a bare object." ) ?;
@@ -42,7 +46,8 @@ pub fn instance_init<'gc>(
42
46
. library_for_movie_mut ( movie)
43
47
. character_by_id ( symbol)
44
48
{
45
- this. set_sound ( activation. context . gc_context , * sound) ;
49
+ let sound = * sound;
50
+ sound_object. set_sound ( & mut activation. context , sound) ?;
46
51
} else {
47
52
tracing:: warn!( "Attempted to construct subclass of Sound, {}, which is associated with non-Sound character {}" , class_object. inner_class_definition( ) . read( ) . name( ) . local_name( ) , symbol) ;
48
53
}
@@ -68,10 +73,13 @@ pub fn bytes_total<'gc>(
68
73
this : Option < Object < ' gc > > ,
69
74
_args : & [ Value < ' gc > ] ,
70
75
) -> Result < Value < ' gc > , Error < ' gc > > {
71
- if let Some ( sound) = this. and_then ( |this| this. as_sound ( ) ) {
72
- if let Some ( length) = activation. context . audio . get_sound_size ( sound) {
73
- return Ok ( ( length) . into ( ) ) ;
76
+ if let Some ( sound) = this. and_then ( |this| this. as_sound_object ( ) ) {
77
+ if let Some ( sound_handle) = sound. sound_handle ( ) {
78
+ if let Some ( length) = activation. context . audio . get_sound_size ( sound_handle) {
79
+ return Ok ( ( length) . into ( ) ) ;
80
+ }
74
81
}
82
+ return Ok ( 0 . into ( ) ) ;
75
83
}
76
84
77
85
Ok ( Value :: Undefined )
@@ -105,10 +113,13 @@ pub fn length<'gc>(
105
113
this : Option < Object < ' gc > > ,
106
114
_args : & [ Value < ' gc > ] ,
107
115
) -> Result < Value < ' gc > , Error < ' gc > > {
108
- if let Some ( sound) = this. and_then ( |this| this. as_sound ( ) ) {
109
- if let Some ( duration) = activation. context . audio . get_sound_duration ( sound) {
110
- return Ok ( ( duration) . into ( ) ) ;
116
+ if let Some ( sound) = this. and_then ( |this| this. as_sound_object ( ) ) {
117
+ if let Some ( sound_handle) = sound. sound_handle ( ) {
118
+ if let Some ( duration) = activation. context . audio . get_sound_duration ( sound_handle) {
119
+ return Ok ( ( duration) . into ( ) ) ;
120
+ }
111
121
}
122
+ return Ok ( 0 . into ( ) ) ;
112
123
}
113
124
114
125
Ok ( Value :: Undefined )
@@ -120,7 +131,7 @@ pub fn play<'gc>(
120
131
this : Option < Object < ' gc > > ,
121
132
args : & [ Value < ' gc > ] ,
122
133
) -> Result < Value < ' gc > , Error < ' gc > > {
123
- if let Some ( sound ) = this. and_then ( |this| this. as_sound ( ) ) {
134
+ if let Some ( sound_object ) = this. and_then ( |this| this. as_sound_object ( ) ) {
124
135
let position = args
125
136
. get ( 0 )
126
137
. cloned ( )
@@ -133,12 +144,6 @@ pub fn play<'gc>(
133
144
. coerce_to_i32 ( activation) ?;
134
145
let sound_transform = args. get ( 2 ) . cloned ( ) . unwrap_or ( Value :: Null ) . as_object ( ) ;
135
146
136
- if let Some ( duration) = activation. context . audio . get_sound_duration ( sound) {
137
- if position > duration {
138
- return Ok ( Value :: Null ) ;
139
- }
140
- }
141
-
142
147
let in_sample = if position > 0.0 {
143
148
Some ( ( position / 1000.0 * 44100.0 ) as u32 )
144
149
} else {
@@ -153,23 +158,29 @@ pub fn play<'gc>(
153
158
envelope : None ,
154
159
} ;
155
160
156
- if let Some ( instance) = activation
157
- . context
158
- . start_sound ( sound, & sound_info, None , None )
159
- {
160
- if let Some ( sound_transform) = sound_transform {
161
- let st = SoundTransform :: from_avm2_object ( activation, sound_transform) ?;
162
- activation. context . set_local_sound_transform ( instance, st) ;
163
- }
164
-
165
- let sound_channel = SoundChannelObject :: from_sound_instance ( activation, instance) ?;
161
+ let sound_transform = if let Some ( sound_transform) = sound_transform {
162
+ Some ( SoundTransform :: from_avm2_object (
163
+ activation,
164
+ sound_transform,
165
+ ) ?)
166
+ } else {
167
+ None
168
+ } ;
166
169
167
- activation
168
- . context
169
- . attach_avm2_sound_channel ( instance, sound_channel) ;
170
+ let sound_channel = SoundChannelObject :: empty ( activation) ?;
170
171
172
+ let queued_play = QueuedPlay {
173
+ position,
174
+ sound_info,
175
+ sound_transform,
176
+ sound_channel,
177
+ } ;
178
+ if sound_object. play ( queued_play, activation) ? {
171
179
return Ok ( sound_channel. into ( ) ) ;
172
180
}
181
+ // If we start playing a loaded sound with an invalid position,
182
+ // this method returns `null`
183
+ return Ok ( Value :: Null ) ;
173
184
}
174
185
175
186
Ok ( Value :: Null )
@@ -202,6 +213,7 @@ pub fn load<'gc>(
202
213
args : & [ Value < ' gc > ] ,
203
214
) -> Result < Value < ' gc > , Error < ' gc > > {
204
215
if let Some ( this) = this {
216
+ // FIXME - don't allow replacing an existing sound
205
217
let url_request = match args. get ( 0 ) {
206
218
Some ( Value :: Object ( request) ) => request,
207
219
// This should never actually happen
0 commit comments