Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Associate sounds with instance ID #1445

Closed
wants to merge 11 commits into from
Closed

Conversation

relrelb
Copy link
Contributor

@relrelb relrelb commented Oct 31, 2020

Fixes #1441
Fixes #1319

@Herschel
Copy link
Member

Herschel commented Nov 1, 2020

Thanks! I wouldn't want to merge this without the sound instances cleaning up after themselves; currently the instance list would "leak" unless sounds are explicitly stopped. Event sounds from the timeline should be stopped as well.

@relrelb relrelb changed the title core: Sound.start and Sound.stop improvements core: Improve Sound.{start,stop} Nov 1, 2020
core/src/display_object.rs Outdated Show resolved Hide resolved
@relrelb
Copy link
Contributor Author

relrelb commented Nov 7, 2020

I came up with a better solution that doesn't leak the sound instances, so this is not a prototype anymore and ready for CR.

@Herschel
Copy link
Member

Herschel commented Nov 8, 2020

Using Character ID is troublesome because:

One possibility is to add an unique increasing instance_id to DisplayObject. There is already UpdateContext.instance_counter that is used for generating default instance names, we can store this ID in DisplayObject as well.

@relrelb relrelb changed the title core: Improve Sound.{start,stop} Associate sounds with instance ID Nov 20, 2020
@relrelb
Copy link
Contributor Author

relrelb commented Nov 20, 2020

Now sounds are stopped per an instance ID, which is the UpdateContext.instance_counter that gets incremented on each DisplayObject instantiation.

However, there are some Rust borrowing issues left, which you might assist me to solve. In short, I made instantiate_display_object in library.rs receive an UpdateContext as parameter rather than a MutationContext. So I changed all instantiate_display_object (directly or indirectly) to pass context rather than context.gc_context. This causes 5 similar errors, for example in movie_clip.rs:

if let Ok(child) = context // 1st borrow
    .library
    library_for_movie_mut(self.movie().unwrap())
    instantiate_by_id(id, context) // 2nd borrow, context used to be context.gc_context
{
    ...

The problem is that context is now mutably borrowed twice. Do you have any idea how to solve it?

@kmeisthax
Copy link
Member

kmeisthax commented Nov 21, 2020

You can't chain methods on context variables that also need the context. This is the same reason why Avm1 and Avm2 don't take &self. For libraries, however, the library itself is owned so you can just move it out of the temporary:

let library = context.library.library_for_movie_mut(self.movie().unwrap());
if let Ok(child) = library.instantiate_by_id(id, context) {
   //context and library should both have zero borrows within this block
}

Rust's borrow checker is a little weird with how it accounts for lifetimes and borrows accrued in temporaries; any borrow that's part of an if let statement lasts for the entire block, even if it makes no semantic sense to do so. This even applies when RefCell semantics are at work; you can totally get spurious BorrowMutError panics simply because you accidentally held a temporary in an if let.

@relrelb
Copy link
Contributor Author

relrelb commented Nov 21, 2020

@kmeisthax Thanks for your help, but unfortunately the compiler still complains for the same reason. Can you please try to compile the code yourself and confirm it's working?
After looking for similar code that takes context.library and then uses context, I haven't found any code that uses both library and context in the same statement, as my code does. I suspect this is the difference that makes it difficult to compile.

@Herschel
Copy link
Member

You could do it in post_instantiation alongside set_default_instance_name -- I think that's the least invasive change for now.

@relrelb
Copy link
Contributor Author

relrelb commented Nov 26, 2020

@Herschel Thanks for your suggestion! Despite I think it's not the ideal way, I did it in set_default_instance_name (which I renamed to set_instance_id_and_default_instance_name), and it seems to work well.

One thing that still remained - few methods currently accept an optional instance_id (e.g. start_sound), and few places pass None to them. I'm pretty sure all sounds should be associated with some instance_id, but I'm not familiar enough with the Flash Player behavior. I would be thankful if you review my changes and pay extra attention to the TODOs I placed near such cases.

Previously, Sound.stop stopped only the last played sound.

This commit is a prototype and needs some follow-ups:
* Remove inactive sound instances from the list.
* Fix and uncomment the code in Sound.position, but anyway it wasn't
fully functional before.
Instead of maintaining a Vec of active sound instances in each
DisplayObject, this commit reuses the already-existing sound
tracking mechanism of each backend.
This is both much more simple, and doesn't leak the instances list.

TODO: Consider to require all sound instances to be associated with
a MovieClip. Currently some are not associated with any (i.e. have
None in their clip_id). This would allow to convert clip_id to be
non-Option.
As a preparation for associating active sounds to an unique
instance ID instead of a possibly shared clip ID.

The code currently does not compile because of 5 similar errors
related to Rust borrowing.
This commit uses the instance IDs added in the previous commit for
tracking the active sounds.

The code still doesn't compile as the borrowing issues haven't been
fixed yet.
It always should be non-negative.

Maybe it's worth to define a type alias for it:
pub type InstanceId = u32;
But I'm not sure where to place it.
For now, we're going to initialize instance_id in
post_instantiation alongside set_default_instance_name.
The previous commit removed its initialization because it led to
compile errors.
On second thought it's still useful.
@ousia
Copy link
Contributor

ousia commented Jan 13, 2021

Was this request abandoned? Sorry for asking that, but it seems to be no activity for over a month.

Maybe I’m just being impatient. (I must confess that I’m extremely interested in an improvement for #340, reported almost a year ago).

Many thanks for your excellent work.

@Herschel Herschel self-assigned this Jan 23, 2021
@relrelb
Copy link
Contributor Author

relrelb commented Jan 25, 2021

Mostly superseded by #2825, but still needed for #1319?

@relrelb
Copy link
Contributor Author

relrelb commented Jan 27, 2021

Completely superseded by #2825.

@relrelb relrelb closed this Jan 27, 2021
@relrelb relrelb deleted the sound branch January 28, 2021 07:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants