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

client: add MPV_EVENT_INITIALIZED #15089

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

kasper93
Copy link
Contributor

No description provided.

Copy link
Member

@avih avih left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks.

Copy link

github-actions bot commented Oct 14, 2024

Download the artifacts for this pull request:

Windows
macOS

@na-na-hi
Copy link
Contributor

Shouldn't this follow the suit of MPV_EVENT_IDLE and make it a property instead?

@avih
Copy link
Member

avih commented Oct 15, 2024

Shouldn't this follow the suit of MPV_EVENT_IDLE and make it a property instead?

What's the value in making it a property?

To me it "feels" more like an event than property, because it's one point in time in the lifetime of [lib]mpv (similar to shutdown, but sent only once), but on its own that shouldn't be considered a substantial argument.

Copy link
Member

@avih avih left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also update INTERNAL_EVENT_BASE.

This may be useful for waiting until all scripts have finished loading.
Use with caution, as scripts shouldn't perform too many tasks during
initialization or afterward. Instead, they should wait to be triggered
by property or event changes.
@kasper93
Copy link
Contributor Author

Shouldn't this follow the suit of MPV_EVENT_IDLE and make it a property instead?

It depends how such event would be used. I wanted to keep it internal, because I don't see clear use-cases.

Having this as property would allow script to check "initialized" state if it is loaded after actually initialization has taken place. On the other hand, unlike idle, we would never change initialized property during runtime. It is specifically one time trigger that happens on initial load. Though like I said, I have no idea, what to do if script is loaded later and missed the init event.

Copy link
Member

@avih avih left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix.

@avih
Copy link
Member

avih commented Oct 15, 2024

Though like I said, I have no idea, what to do if script is loaded later and missed the init event.

If a script is loaded later then this is irrelevant for them.

It's only relevant for clients/scripts which load/exist at startup - during the initialization phase, and which want to know when init is complete.

@sfan5
Copy link
Member

sfan5 commented Oct 15, 2024

what's the use case here?

@avih
Copy link
Member

avih commented Oct 15, 2024

what's the use case here?

Technically it's required for #15058 .

Making it public is to allow 3rd party scripts the same capabities which internal scripts have, because they can find it equally useful in various use cases related to sync between scripts which depends on knowing that all other scripts are loaded.

@avih
Copy link
Member

avih commented Oct 15, 2024

Technically it's required for #15058 .

Well, "required" - if we want to fix an existing bug where mpv --idle --script-opts=stats-bindlist=yes is supposed to wait for all scripts to finish init (where they typically add key bindings), but it doesn't actually wait correctly for all scripts to finish init.

It currently waits using a timeout of 0, but this method doesn't actually guarantee that all scripts have finished init, while this new initialized event allows to wait correctly.

Arguably this reason on its own might not be strong enough to add an mpv event, however, the functionality can be very useful to scripts which need init-sync with other scripts - in a similar way to how stats.lua can use of it to wait for all other scripts to finish their init.

@na-na-hi
Copy link
Contributor

Well, "required" - if we want to fix an existing bug where mpv --idle --script-opts=stats-bindlist=yes is supposed to wait for all scripts to finish init (where they typically add key bindings), but it doesn't actually wait correctly for all scripts to finish init.

It's only "required" because for input-bindings "change notification is not supported". Is the comment about "there is no mechanism to change key bindings at runtime" even true anymore now that load-input-conf exists? I think this should be fixed so that input-bindings works with change notification. This way the script can simply observe this property and doesn't need to know when the initialization is complete.

Arguably this reason on its own might not be strong enough to add an mpv event, however, the functionality can be very useful to scripts which need init-sync with other scripts - in a similar way to how stats.lua can use of it to wait for all other scripts to finish their init.

init-sync can be done by letting scripts writing their init status to user-data and then observe the property to determine whether other scripts have initialized instead. This is more useful than the MPV_EVENT_INITIALIZED event since it allows the script to complete a long initialization after the playback has started, such as waiting for network, as this avoids stalling playback from starting until the long init is complete.

@guidocella
Copy link
Contributor

Even if input-bindings is observable a script can't know how many times it will be changed.

@avih
Copy link
Member

avih commented Oct 15, 2024

It's only "required" because for input-bindings "change notification is not supported"

I don't think input-bindings notifications would allow for better bindlist behavior, because you don't know how long to wait, like in your example - where there's late initialization.

bindlist needs to cut it off at some stage. The original design was to wait till all scripts are loaded, so that the common case where script add bindings during init is covered.

Cases of bindings at a later stages can never be covered compoletely however you look at it.

However, the original design can be changed if someone has a better idea at which point in time to grab the input-bindings property in order to list them and exit - while still covering the common case of bindings which are added at the init phase.

init-sync can be done by letting scripts writing their init status to user-data and then observe the property to determine whether other scripts have initialized instead.

I don't think this covers the init-sync use case, for the same reason that observing input-bindings would not cover it - you don't know how long to wait and decide that "that's it, all scripts which should have changed user-data already changed it".

However, while I still think that this event can be very useful to scripts, and this event or something equivalent would be very nice to have, I don't have very strong opinion about adding this event.

My only take is that if we're adding this event, then there's a very good reason to also make it public, so that 3rd party clients/scripts can use it as well.

@kasper93
Copy link
Contributor Author

Even if input-bindings is observable a script can't know how many times it will be changed.

Exactly.

init-sync can be done by letting scripts writing their init status to user-data and then observe the property to determine whether other scripts have initialized instead. This is more useful than the MPV_EVENT_INITIALIZED event since it allows the script to complete a long initialization after the playback has started, such as waiting for network, as this avoids stalling playback from starting until the long init is complete.

Agreed. Having MPV_EVENT_INITIALIZED is limited in possible uses. I argue against making it public in the other PR #15058, but got out-voted by avih. The point here is that, we have this stats.lua function that prints keybind and quits the player, to do that it has to wait for all other scripts to add all bindings. Is waiting for "initialization enough? Probably not, because scripts may add binding at any time, but in practice most of them do it in main body of the script.

I will let you guys decide, I will adjust this PR accordingly to your guidance. I stated my position before.

@avih
Copy link
Member

avih commented Oct 16, 2024

@na-na-hi do you have a viable alternative to adding this event?

Do I understand correctly that you suggest to add observer notification to input-bindings, and use that somehow instead of this event? care to explain how?

If we don't want to add this event (I have no opinion about that, but I agree that fixing the 0-timeout for bindlist might not be a strong enough reason to add an mpv event), then my suggestion is to simply increase the timeout, for instance to 250ms, or maybe use some other trigger (instead of timeout) which would reasonably cover the common case of binding added by scripts/clients on init. It only has to be good enough, we don't need perfect coverage here IMO (which we can't get anyway - for instance with late init in scripts).

If we can't come up with an acceptable alternative to adding this event (bindings notifications and a good procedure to use them, bigger timeoue, whatever), then I think we should go ahead with adding this event.

@na-na-hi ? @sfan5 ?

My single take is that if we do add this event because we consider it useful to stats.lua, then we should make it public, because it would be snobbish of us to think that only we need it but 3rd party clients/scripts should not have use cases for it.

@sfan5
Copy link
Member

sfan5 commented Oct 16, 2024

I don't have a strong opinion, just wanted to know what this is for.

@na-na-hi
Copy link
Contributor

Do I understand correctly that you suggest to add observer notification to input-bindings, and use that somehow instead of this event? care to explain how?

Make the first change notification of input-bindings be sent only after the player is "initialized". Also is there any good reason for the scripts to receive notifications at the initialization stage? IMO this behavior makes it possible to result in different behavior depending on the order the scripts are initialized which is random. If there isn't, then the same principle can be applied to all properties.

@avih
Copy link
Member

avih commented Oct 16, 2024

Make the first change notification of input-bindings be sent only after the player is "initialized"

First of all, that's one step. When should the bindlist code stop listening for input-bindings notifications? after the first notification?

To me, that's just a roundabout method to do the same function as the initialized event, but in a limited way which works only if clients/scripts added bindings - and which doesn't guarantee the init-sync scenario (if no bindings were added during init). Personally I think the event is more elegant than this approach, and much more to the point (and also doesn't require first adding observer notification for input-bindings).

Why do you consider it better than adding the event?

Also is there any good reason for the scripts to receive notifications at the initialization stage?

I don't think so, but the notification arrives after the init of all scripts is complete - not during init. I.e. after the "main" code of each script was executed, and the event loop is entered, and the notification arrives as an event to the script's event loop.

It signals that all scripts are loaded, had a chance to register any listeners during their init, etc, and guarantees that any script-message sent after that event would be recieved by any other script which mpv loads on startup and registered the appropriate handler during init.

IMO this behavior makes it possible to result in different behavior depending on the order the scripts are initialized which is random.

I don't think so, but do correct me if I'm wrong.

This event is designed exactly to make the behavior consistent regardless of scripts load order by mpv. It doesn't matter whether script A or B were loaded first, because once that event is recieved, A knows that if B exists then it's already loaded, and B knows that if A exists then it's already loaded.

If there isn't, then the same principle can be applied to all properties.

Not sure what this means or implies. Care to elaborate?

@na-na-hi
Copy link
Contributor

When should the bindlist code stop listening for input-bindings notifications? after the first notification?

Yes, because the first notification happens after all scripts are initialized.

To me, that's just a roundabout method to do the same function as the initialized event, but in a limited way which works only if clients/scripts added bindings - and which doesn't guarantee the init-sync scenario (if no bindings were added during init).

I don't think it's more limited. It achieves the same result, plus the ability to receive the change notification if the bindings change afterwards. MPV_EVENT_INITIALIZED also doesn't guarantee the init-sync scenario which requires other sync methods.

It signals that all scripts are loaded, had a chance to register any listeners during their init, etc, and guarantees that any script-message sent after that event would be received by any other script which mpv loads on startup and registered the appropriate handler during init.

MPV_EVENT_INITIALIZED can only make sure that message handlers registered during init are ready this way, but not after init. Both can be achieved by the user-data approach I mentioned, so this event isn't needed.

Not sure what this means or implies. Care to elaborate?

It would achieve the same result for the script order issue, but without a new event and explicit handling by the scripts.

Overall my point is that this event has limited use cases which can be better served by changes elsewhere which don't introduce a new event which the scripts need to handle.

@avih
Copy link
Member

avih commented Oct 16, 2024

I wrote a lot of things but deleted them.

Let me put it simply: the event method is bullet-proof for the thing it guarantees (fire after all scripts are initialized), can have general init-sync value, covers our specific use case perfectly (bindlist) by ensuring we run after all scripts which add bindings at init have already added them.

And it's literally one line of clean code.

What arguments you have against merging it?

Do you think it's not worth adding an mpv event only to fix the bindlist scenario? I won't disagree with that.

If that's the reason, how about the 250ms method I suggested above? or maybe some other trigger you can think of which we can use today without additional infrastructure?

@avih
Copy link
Member

avih commented Oct 17, 2024

Well, I'm out of the discussion about which solution is best for the bindlist 0-timeout issue.

I didn't advocate to use this event, and I don't care which solution is used as long as it's reasonable (which I do consider both the event solution or a 250ms solution or something else which would cover our use case), or even not solve it at all if there's ongoing disagreement.

@kasper93 if you still want to use this event, please decide what to do with @na-na-hi arguments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants