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

Launched streams and ToastNotifications created by Twitch GUI create unusual windows wait cursor behaviour. #952

Open
4 tasks done
Sneakpeakcss opened this issue Jan 20, 2023 · 4 comments

Comments

@Sneakpeakcss
Copy link

Sneakpeakcss commented Jan 20, 2023

Checklist

Streamlink Twitch GUI version

v2.2.0

Streamlink version

5.1.2

Operating system, environment and configuration details

Windows 10 21H2

Description

This started happening after one of the updates few years ago, i've mentioned it last year on gitter and at that point i just blamed my old bloated system, but lately after doing a clean Windows10 installation and straight up installing only Streamlink + Streamlink Twitch GUI the problem still persists.

1)

When Twitch GUI creates a Toast Notification, windows wait cursor instantly activates and only dissapears after the notification either dissapears or is hidden manually.
This behaviour only happens with Twitch GUI, any other software that sends notifications doesn't show any loading.

Twitch GUI v2.2.0:

GUI.v2.2.0.mp4

Debug Log ToastNotification GUI v2.2.0.log

The last version that doesn't act this way for me is v1.11.0
Since this version is so old it's impossible to test it on an automatically activated notification, however the test button still manages to show the proper behaviour.

Twitch GUI v1.11.0:

GUI.v1.11.0.Last.Working.Version.mp4

Debug Log ToastNotification GUI v1.11.0.log

And every single release starting from v1.12.0 that Upgraded snoretoast (Windows notification provider) to 0.7.0 presents the same problem.

Twitch GUI v1.12.0:

GUI.v1.12.0.First.Bugged.Version.mp4

Debug Log ToastNotification GUI v1.12.0.log

 
 
2)

Similar behaviour happens when the player is launched by Twitch GUI, but in this case it sometimes creates an endless loop that never stops unless i manually 'unstuck' it, for example by opening a random text file.

I mainly use MPC-HC, but the same happens in default VLC installation,
though i wasn't able to catch it being stuck in an endless loop, the prolonged loading on mouse cursor is still present:

Twitch GUI v2.2.0 + MPC-HC:

GUI.v.2.2.0.MPC-HC.mp4

GUI v2.2.0 MPC-HC test.log

Twitch GUI v2.2.0 + VLC:

GUI.v.2.2.0.VLC.mp4

GUI v2.2.0 VLC test.log

While the loading might rarely stop very quickly by itself it usually takes a lot of time (as shown on the video examples), VLC seems to have less delay on that, but it still happens with it, it also stops the moment Twitch GUI window pops-out after closing the player manually.
And once again this only happens when streams are launched by Twtich GUI, doing it either manually with streamlink or even opening them through Chatty doesn't even show it for a second, for example:

Launching streams manually using Streamlink + MPC-HC / VLC:

Streamlink.Launch.Example.mp4

I couln't find any logs for MPC-HC, but i've managed to take two from VLC while launching a stream with Twitch GUI and PowerShell, however it doesn't seem to be there anything that would point at why this happens at all.
TwitchGUI Test VLC Log.txt
Streamlink Test VLC Log.txt

 

I've tried using both installer and portable versions of Twitch GUI, installing them on different SSDs / HDD or opening the application as administrator, different setting configurations in GUI or launching it with --disable-gpu… And nothing helped.

Nothing unusual shows in task manager, different streamlink versions never had any influence on this. I very vaguely remember long ago using Process Monitor to see if there's any difference in how snoretoast.exe behaved between v1.11.0 - v1.12.0, and there being something about how the older version cached something locally(?), but i'm not sure if any of that would be connected to either (player / toast) problems, and at the same time it's impossible to check if the v1.11.0 version has the same problem while launching streams.

At this point i'm wondering if this is specific to my hardware configuration since i can only assume that someone else at this point would be insanely bothered by random loading cursor (or maybe notifications are turned off by default(?) and not many people use that option?)
I'm left with joking to myself that if it wasn't for Twitch GUI i wouldn't even know about wait cursor since i barely notice it outside of this scenario, so at least it has been somewhat (not)amusingly educational at my expense.

Debug log

No response

@bastimeyer
Copy link
Member

First off, on WIndows, Streamlink Twitch GUI needs a helper utility called SnoreToast in order to display native notifications. Chromium still doesn't have support for native notifications, unlike on Linux (freedesktop notifications via DBUS) or macOS. This means that whenever a notification needs to be shown, snoretoast has to be executed and an action is performed according to its exit code. This isn't a perfect solution. There's also a named pipe which can be read from for other callbacks, but that's not being used or even relevant.

The last version that doesn't act this way for me is v1.11.0

The v1.12.0 release of Streamlink Twitch GUI bumped NW.js from 0.45.5 to 0.52.2. This included a bump of Chromium from 81.x to 89.x and NodeJS from v14.0.0 to v15.12.0. The change of the bundled snoretoast version in that release is irrelevant.

I don't use Windows, but the reason for the spinning/loading/hourglass cursor is how Windows handles process startups and GUI initializations. Windows basically waits until there is something for the user to see and it does that by showing a different cursor during that time.

The cursor replacement (called feedback mode) can be disabled via the low level Windows APIs (STARTUPINFO / STARTF_FORCEOFFFEEDBACK), but this stuff is managed by NW.js / NodeJS, and I don't have access to any of this from the application code and the public NodeJS JS APIs that are being used by the application code, namely child_process.spawn(cmd, args, options).

There was an issue in an old NW.js release in 2016 where the application itself was showing a spinning mouse cursor, but it's unrelated to this issue.

I don't know much about the NW.js and NodeJS internals, but something must've changed in regards to how child process spawning is implemented and how CreateProcess in the win32 API is called. The STARTF_FORCEOFFFEEDBACK bitmask needs to be applied to the dwFlags parameter value.

Spawning the child processes in detached mode unfortunately doesn't help, I just tested that in my Win10 VM.

This issue needs to be reported upstream on the NW.js issue tracker and an NW.js reproduction/demonstration app needs to be created.


As a small workaround, I could enable "Chromium Rich Notifications" on all versions of Windows, not just 7 (which btw will be dropped soon), which are notifications that are rendered by Chromium itself, so no helper process is needed. That wouldn't be ideal though, not just because those notifications don't follow the system theme, but also because of how the notification type selection and its order is implemented. If the order doesn't get changed, then rich notifications would need to be selected explitly, and if the order gets changed, then people who have chosen the automatic selection will use the non-native notifications by default.

@bastimeyer
Copy link
Member

Apparently, setting shell: true on the spawn options prevents the spinning cursor, and most likely any wrapper script would work as well, but both solutions are very problematic on Windows due to how shell tokenization works, which is insanely stupid. Since notifications contain user-generated content, I don't feel confident at all with this.

@bastimeyer
Copy link
Member

NodeJS's I/O is done via libuv, and here's the Windows implementation of the uv_spawn function and the git-blame of its dwFlags, which indicates no changes:
https://github.com/libuv/libuv/blame/v1.44.2/src/win/process.c#L1060
STARTF_FORCEOFFFEEDBACK was never set here, so I'm not sure what changed.

Here's some of the call stack:
https://github.com/nwjs/node/blob/nw71/lib/internal/child_process.js#L395
https://github.com/nwjs/node/blob/nw71/lib/internal/child_process.js#L266
https://github.com/nwjs/node/blob/nw71/lib/internal/child_process.js#L44
https://github.com/nwjs/node/blob/nw71/src/process_wrap.cc#L144
https://github.com/nwjs/node/blob/nw71/src/process_wrap.cc#L264

@bastimeyer
Copy link
Member

I'm currently having a look at refactoring the providers of the NotificationService. There's a solution for the mouse cursor problem by using Windows native notifications via the Chromium API directly, so that executing snoretoast is not necessary.

Chromium has added support for native "ActionCenter" notifications several years ago, but similar to notifications via snoretoast, only applications that have a shortcut installed in the system's start menu with an attached AppID are allowed to send ActionCenter notifications. If such a shortcut does not exist, then a "rich" notification gets shown by Chromium, which is rendered by the browser itself.

The snoretoast provider has a setup step implemented which installs the shortcut upon first execution via snoretoast.exe -install "name" "path-to-app.exe" "app-id". Another solution is creating the shortcut in the Twitch GUI's Windows installer, but that would only be a one-time action, and that could lead to the user not being able to see ActionCenter notifications once the shortcut got removed or replaced. And users which don't use the installer would also not be able to see ActionCenter notifications. Those shortcuts unfortunately can't be created via regular methods, as those don't support setting the AppID property. This is only possible by using certain Windows APIs.

Chrome on Windows faces same problem. Its own installer (and/or internal update mechanism - not sure) creates a shortcut at %ProgramData%\Microsoft\Windows\Start Menu\Programs\Google Chrome.lnk with its embedded AppID. Without this shortcut, ActionCenter notifications can't be sent. Quick DOM API example:

await window.Notification.requestPermission();
new window.Notification("title");

Streamlink Twitch GUI already implements notifications via the Chromium API, but this is only enabled for macOS and Linux as the native provider, and for Windows 7 as the rich provider.

If the shortcut could be created with the correct AppID, then the rich provider could be removed in favor of a single native provider (or something similar). Unfortunately, NW.js doesn't register the right AppID that is defined in the app's package.json manifest, which is streamlink-twitch-gui (or Streamlink Twitch GUI). The shortcut could still be created by running snoretoast.exe -install ... if the right AppID could be figured out. Then ActionCenter notifications can be shown via the Chromium or DOM APIs.

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

No branches or pull requests

2 participants