-
Notifications
You must be signed in to change notification settings - Fork 3k
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
stats.lua: don't use io.write from builtin script #15058
Conversation
Download the artifacts for this pull request: |
I don't think it's worth the additional code and new mpv command just to avoid Yes, it's not very nice, but it does work, and it's simple, and there are no known issues with If we keep this approach, then while Also, it incorrectly clears the last output page, e.g. if the screen is 80x25, then the last 25 lines dissappear from the output. Also, because it clears the screen and moves the cursor to the top (or so it seems), after running
the screen ends up empty. One has to scroll up to see the remaining bindings list which was not cleared - which is really not nice. Unrelated, it seems that the terminal-width argument is ignored, e.g. in
and instead it always adjusts to the actual terminal width. This is definitely an improvement for the default width ( I think the best course of action with regards to this is to update the docs about the default being actual screen-width rather than 79, and restore the override functionality (which might require restoring the ellipsis function). Also unrelated, when printed to the terminal and quitting, the title is |
This just doesn't leave any output? The whole keybinding list is cleared is for me. Anyway the point of not using |
@guidocella: I fixed initialization race condition and console.lua, should be fine now. |
It's not hacky, it works exactly as intended, and it's intentional. mpv waits for all scripts to finish their init phase before it starts calling all the scripts' respective event loop functions - which then starts calling registered callbacks - such as timers. Scripts typically set bindings on their init phase, which should be quick, because otherwise it would stall mpv's init. But even if it does stall mpv, the bindings list should still wait for all scripts to init and register their key bindings, so that they can be listed by stats.lua . Also, it's still definitely not worth adding all this code, and a new mpv event, only to avoid "not nice" is simply not a good enough reason for this PR. If you have better reasons, do mention them. |
It still randomly clears the whole list sometimes. |
Thank you @guidocella for testing, I see there is still a way to race it. |
It doesn't work. We go to idle, we feed scripts, nothing is waiting for all of them, not sure where you get this idea. |
Should be fixed now, I had local change in other place, sorry for that. |
I can confirm it's fixed. |
It indeed doesn't work, but it used to, and now the docs on "script initialization and lifecycle" are incorrect. The docs clearly states that mpv waits for all scripts to finish init before continuing. "continuing" refers to calling the event loop of all scripts, starting playback, etc. Scripts could rely on this documented behavior in order to sync with other scripts etc, but now it seems that this doesn't work anymore, so at some stage this got broken. Either way, the bindlist output should wait for all script to finish init, even if it takes more than few ms, in order to allow them to register key bindings on their init so that stats.lua can list them. Also, please do mention at the commit message a reason better than "not nice" to justify all this new code and new mpv event, otherwise, if it's good enough, then it's just not worth it. |
mpv enters idle state on wait since 5fb0594, scripts waiting were further refined in 11c573f there is no reason for scripts to block each other. mpv waits for all of them before starting playback, scripts are run asynchronously.
Citation needed. I've read https://mpv.io/manual/master/#details-on-the-script-initialization-and-lifecycle and it clearly states what happens and at no point it tells that your script will be blocked by other scripts. It explicitly states
And this is how mpv currently works.
Works as expected.
Yes, that's clear. Hence the fix in this PR.
"not nice" and broken initialization wait is good enough for me. As for the rest, @guidocella explained why those changes were prompted in #15058 (comment) |
they don't block eachother. Scripts run in parallel, and so is their init phase. It's just that mpv should wait for all scripts to finish init before continuing, i.e. mpv and scripts should be blocked after their init is complete and before all scripts finish init - and then the first event should be sent from mpv. |
The commit message should explain what's broken. Not some random comment at the PR page on github. Also, which part specifically? the ellipsis function is not used already anyway, and the output does fit the terminal width also without this PR by default. Don't answer me. Add it to the commit message. |
I can expose initialization event publicly. Though I don't know if there is really an use-case where this is needed. Scripts will not be driven by any events, because mpv core is dead. Only events can be triggered by other scripts or add_timeout, because it is just called on every tick. |
Ok. |
I think this could be useful to expose it publicly. There's a value in the fact that a script can know that all other scripts have finished their init - just like it has value for stats.lua. There can also be value in scripts which need to sync with other scripts, for instance sending a script-message only after all other scripts are loaded, etc.
Not sure what this means, but if this works and has value for stats.lua, then it should work and can have value for 3rd party scripts too. |
This looks better. Thanks. Some comments: At the commit message of "stats.lua: wait for all other scripts to finish init correctly", there's a big block of text explaining why scripts shouldn't block, etc, with this in it:
and
I don't think it's relevant. Obviously it's true that scripts shouldn't block, etc, but no script was blocking before this commit, and making this event public won't encourage blocking behavior, because it's not intended to address blocking and/or slow-loading scripts at all. It's intended to ensure all other scripts have finished their init phase. Consider these two scripts:
script b
Script a definitely does everything by the book. It's not blocking more than necessary and it initializes blazingly fast. And yet it's not guaranteed that script b will see the binding which script a added, because the script load/init order in mpv is arbitrary, and it's entirely possibe that script b init will run before script a bound the key. In fact, without this new event, script b has no way to know where to try and grab the bindings which script a sets. It certainly shouldn't use the hacky 0-timeout method, right? And this is what this new event allows to synchronize. There are also other use cases where it can be useful, like with scripts which synchronize with eachother. Imagine a server script which broadcasts a message of "i'm ready to recieve messages", and it wants to do that after all other scripts are loaded, to guarantee that any client scripts will recieve this message, etc. Or, with similar synchronized scripts scenario, a client wants to test whether there's a server script. When should it send a message to ensure that the server script is already loaded and will accept it if it exists? It can't use timeout of 0, because that doesn't guarantee to wait for other scripts. It can use timeout of 10s which will likely work, but is super ugly. Or it could use the new event which would guarantee the correct behavior possible without arbitrary timeouts which don't guarantee anything and would likely wait more than necessary. It's a synchronization method completely unrelated to scripts init blocking behavior (though obviously it would address such cases also). So I don't think this whole block reasoning is relevant at all. All the stratements there are true, but theyre irrelevant as a reason to not make this public. FWIW, I do think it would be useful to make it public still, exactly because this commit itself demonstrates how it can be useful to scripts, and it can be equally useful to 3rd party scripts. It's a great event, which is much nicer than the timeout hack, and would be really nice if 3rd party scripts would be able to use it. The general approach was and should be to not use internal things which only internal scripts can do but 3rd party scripts can't. It's not nice at all, and it prevents one from writing their own stats.lua replacement for instance, etc. Much work was done explicitly to ensure 3rd party clients/scripts can do as much as possible which internal clients/scripts can do (e.g. mouse position, and others), and it would be nice to keep this trend and not introduce useful features which are undocumented and unaccessible to 3rd party clients/scripts, especially when they're not hacky or fiddly. At the last commit "stats.lua: don't use io.write from builtin script", the commit message mentions these:
Mind giving an example of "processing the input"? I don't want to guess what it means. The other two reasons are areguably not entirely relevant to the current commit, and specifically it makes it sound as if log levels should be respected here, and that it prevents terminal-truncation. "filtering log levels" indeed doesn't happen with "truncating the output" is interesting. I agree it's useful, but it already truncates currently anyway, using the internal In fact, originally only the bindlist output had terminal truncation in mpv. Then it was extended to all stats.lua terminal output, as well as improved to use the actual terminal width. Then, very recently, a central facility was added to all allow it in all mpv terminal output by adding this functionality to the logging (with the respective So what you're really doing is (rightly) wanting to remove the custom in-script truncation, now that there's new central log truncation, and And the proper course of action is to follow by removing |
Script B shouldn't do anything like that on initialization. Nor should it run any code after initialization of all scripts. This is exactly what I want to avoid by not providing a way to do that. Sure, we can theoretise scenario where this is needed, but unless you have actual use-case where this is required I won't add it. mpv as first-party takes the opportunity to listen to all scripts, 3rd-party scripts shouldn't do that. Ideally all clients should be sandboxes and don't have any access to other scripts, initialization or timing of it.
And they can all do that, when they need to, not during/after init. Scripts are driven by mpv events, not the other way around.
Any and all processing. This is general comment about bad practice. Using
The future is not relevant, this PR removes
This is the plan. |
I'm not going to review it when you object to every single comment I make. You know best, you do best. |
Can I remove bindlist in this case? I'm going out of my way to make you happy. This PR is not really worth my time, arguing about irrelevant script option. Blocked by: #15089 |
I think it's useful to users, but I don't care where or how it's implemented. Currently it's only implemented in stats.lua, so until similar functionality is implemented elsewhere, I think it should stay. I'm curious, don't you think it's useful to print all the bindings, including those from scripts and input.conf, from CLI, similar to how other lists are printed from CLI? (functionality only - ignoring the awkward invocation). |
Here's another idea for this changeset. To recap, two main subjects are addressed here:
And as a result of using the log, some additional changes were added to ensure that it can print to the output without clearing the screen on exit, such as the flush command, and some use of timeouts to workaround internal log output timing (or some such - I didn't get that part fully). Now, this is a suggestion to make this patchset much smaller:
And in the future, we can still replace Or maybe take just one of those suggestions, e.g. maybe just the timeout to avoid the event bikeshed. I also don't think this PR is bad. The only issue is the fiddly timing of the output/flush wgich I don't really understand, but I trust that it works well, so I don't have anything against it. I'm just trying to move it forward with maybe something simpler. |
Note that this still is not perfect, because if osd message is changed, console cannot know about it and would still clear it, but this change make it at least not do it to every message even if console is not used.
Scripts and especially internal scripts shouln't bypass msg.c logging code for various resons, ranging from processing the input, filtering the log levels, truncating the output and so on. io.write() is lazy way of outputing to stdout without respecting mpv's logging module. Uses osd message, because this has no prefixes. Added internal flush-status-line command to flush current output without clearing before exiting. This commit will allow us to remove duplicated terminal handling code from stats.lua, mpv core already handles all that and does it in better way, without taking shortcuts.
I removed initialization thing, it is not important for this change. I will merge later today if there is no NACK. |
There's a problem with this on windows, piping the bindlist to "less":
("less" for windows is available here) "less" doesn't get any keypresses - like "q" to quit, or arrows to navigate, etc. This didn't happen with Adding at the CLI: However, (attempt to) doing that programatically at stats.lua by adding So this is a problem. |
I can reproduce on c201c48 in cmd. Doesn't happen in pwsh or any other implementation of less. Is not related to any changes in this PR. Feel free to report issue, if you feel it is mpv fault. I will look at this closer when I have time, but likely something is conflicting with our input handling. |
No description provided.