mpv icon indicating copy to clipboard operation
mpv copied to clipboard

win32: add Media Control support

Open kasper93 opened this issue 1 year ago • 42 comments

Add support for SystemMediaTransportControls interface. This allows to control mpv from Windows media control ui.

Fixes: #9336 Fixes: #13813 Fixes: #14007

kasper93 avatar Jun 11 '24 00:06 kasper93

TO fix https://github.com/mpv-player/mpv/issues/14007 ?

hooke007 avatar Jun 11 '24 02:06 hooke007

Side note, it is possible to make it work in C using only COM interfaces, but it results in significantly more boilerplate code and is completely not worth the effort. As always patches welcome, if someone wants to rewrite it.

kasper93 avatar Jun 11 '24 09:06 kasper93

Since this implementation is just a libmpv client, can you consider making it a C plugin instead? This would avoid adding any dependency to mpv core.

na-na-hi avatar Jun 11 '24 10:06 na-na-hi

Since this implementation is just a libmpv client, can you consider making it a C plugin instead? This would avoid adding any dependency to mpv core.

I've considered it, but since it is pretty core player functionality to integrate into system and macOS does the same. I decided to integrate it inside.

kasper93 avatar Jun 11 '24 10:06 kasper93

but since it is pretty core player functionality to integrate into system and macOS does the same

In this case I would expect proper integration. At least the thumbnail needs to work, which doesn't seem to be the case for now. If this is not possible from a libmpv client, a different approach is needed.

na-na-hi avatar Jun 11 '24 11:06 na-na-hi

In this case I would expect proper integration. At least the thumbnail needs to work, which doesn't seem to be the case for now. If this is not possible from a libmpv client, a different approach is needed.

Thumbnails are not supported on macOS either, I don't think this is a blocker. Generally thumbnail support in mpv is another big topic and out of the scope of this PR. Note that we don't support thumbnails on OSC timeline either.

Either way, thumbnail or more likely periodic screenshot of current frame is possible in the future. (and not that difficult)

kasper93 avatar Jun 11 '24 11:06 kasper93

This also fixes #13813 and #9336.

na-na-hi avatar Jun 11 '24 12:06 na-na-hi

Currently the SMTC interface in Windows 11 doesn't display the mpv icon and program name. The built-in Windows media player does that, and once the Windows media player is run and closed, mpv is stuck with the wrong program icon and name.

na-na-hi avatar Jun 11 '24 16:06 na-na-hi

Currently the SMTC interface in Windows 11 doesn't display the mpv icon and program name. The built-in Windows media player does that, and once the Windows media player is run and closed, mpv is stuck with the wrong program icon and name.

It works the same way with Firefox, if you have ideas how Windows expects this information to be given, let me know. It clearly doesn't get that information from hwnd.

EDIT: It is possible that it works only for installed application that have app id defined.

kasper93 avatar Jun 11 '24 17:06 kasper93

At least the thumbnail needs to work, which doesn't seem to be the case for now.

I have experimented a little and it works pretty good now. I need to glue everything together, because there are multiple cases, local files, external files, embedded files, etc. I will finish it when I get time, but you can expect proper support.'

EDIT: To be honest, I find thumbnail itself not that useful. Compared to other features of this PR, so not sure why this is required, but it will work.

kasper93 avatar Jun 12 '24 00:06 kasper93

It is possible that it works only for installed application that have app id defined.

From a look at the API this seems to be the case.

To be honest, I find thumbnail itself not that useful.

Personally I expect this feature to behave in a similar way as on mobile platforms. So I at least expect album arts to work. For videos, I find most apps don't attempt to do this, or only show a random frame, so missing thumbnail isn't too bad.

The above problem of icon and program name might also be alleviated with the "thumbnail" by displaying the mpv icon when no thumbnail is applicable.

na-na-hi avatar Jun 12 '24 02:06 na-na-hi

Perhaps related, would it be possible to add thumbnail-toolbars(prev,play/pause,next) to the taskbar? https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#thumbnail-toolbars

image

zhongfly avatar Jun 12 '24 15:06 zhongfly

The above problem of icon and program name might also be alleviated with the "thumbnail" by displaying the mpv icon when no thumbnail is applicable.

I found it "cheap", if you get what I mean. Like pushing logo in the place where it shouldn't have been.

From a look at the API this seems to be the case.

I've taken a look and I'm almost certain they are getting app info for installed packages. Something like

// id for mpv is `mpv.exe`
using winrt::Windows::ApplicationModel::AppInfo;
using winrt::Windows::Foundation::Size;
auto app = AppInfo::GetFromAppUserModelId(id);
auto di = app.DisplayInfo();
auto name = di.DisplayName();
auto logo = di.GetLogo(Size(96, 96));

There is no app registered for mpv. There are possibilities like https://blogs.windows.com/windowsdeveloper/2019/10/29/identity-registration-and-activation-of-non-packaged-win32-apps/ but it still would need to be installed and have dedicated package. I don't think it is feasible for mpv in any way.

Perhaps related, would it be possible to add thumbnail-toolbars(prev,play/pause,next) to the taskbar?

No, this is completely not related. This is completely different interface, with basically custom buttons that you can put there. I'm not interested in supporting this. Maybe one day, this taskbar stuff could be merged into one place, but this is out of the scope of this PR.

kasper93 avatar Jun 12 '24 16:06 kasper93

There is no app registered for mpv. There are possibilities like https://blogs.windows.com/windowsdeveloper/2019/10/29/identity-registration-and-activation-of-non-packaged-win32-apps/ but it still would need to be installed and have dedicated package. I don't think it is feasible for mpv in any way.

But this is feasible for libmpv. In addition, it is possible to use Add-AppxPackage -Register to register mpv in-place without signature, and mpv-packaging can do this for end-users.

Andarwinux avatar Jun 12 '24 16:06 Andarwinux

In this case it will possibly work or not. I don't know.

kasper93 avatar Jun 12 '24 16:06 kasper93

Added thumbnail support per @na-na-hi request. It tries to use external file/url directly if available (track marked as image or albumart), if not found it tries to use Windows thumbnail for the file and finally uses screenshot-raw if needed.

kasper93 avatar Jun 14 '24 23:06 kasper93

Thanks for the thumbnail support. Here are some problems I found during testing:

  • Embedded album art doesn't work, even when it shows up in Explorer thumbnail.
  • If I click the info/thumbnail area (which brings the Windows built-in media player to the foreground, but does nothing to mpv) and then click the play/pause button a few times, the SMTC interface won't be updated anymore, and I can't close the mpv window with the X button afterwards. This might be related to HWND or app id.

na-na-hi avatar Jun 15 '24 02:06 na-na-hi

Embedded album art doesn't work, even when it shows up in Explorer thumbnail.

I will double check that.

If I click the info/thumbnail area (which brings the Windows built-in media player to the foreground, but does nothing to mpv)

I didn't even know it does that. Unfortunately since they cannot recognize mpv as an application it doesn't work.

and then click the play/pause button a few times, the SMTC interface won't be updated anymore, and I can't close the mpv window with the X button afterwards. This might be related to HWND or app id.

This sounds like we crashed one of the event threads and no longer can close / join them cleanly. I need to review the code if all error paths would behave correctly. But if you can give more info, it can help too, I cannot reproduce this one.

Side note about this (Windows 11) media control thingy, it is really buggy. It can leave phantom statuses, from various apps, it can just stop working, etc. It is not very robust.

EDIT:

I might disable screenshot-raw fallback, it is not fast enough and with higher resolution videos can produce small hitch at start when screenshot is taken. Our screenshots are taken with all the processing, which can be really slow. Maybe doing it is possible to query last swapchain image instead, but not sure.

kasper93 avatar Jun 15 '24 03:06 kasper93

Embedded album art doesn't work, even when it shows up in Explorer thumbnail.

@na-na-hi could you show example of a file like that?

kasper93 avatar Jun 15 '24 04:06 kasper93

But if you can give more info, it can help too, I cannot reproduce this one.

I reproduced with the following: cap4 log.txt

could you show example of a file like that?

None of the mp3 files with embedded album art works for me. Example: 01_Shuwa_Shuwa Parfait_ななひら.zip

Thumbnail works for external album arts.

na-na-hi avatar Jun 15 '24 05:06 na-na-hi

I reproduced with the following:

Can you check the verbose log? It should print errors.

EDIT:

I can see exception, after clicking on title thingy.

SystemMediaTransportControls: update_thumbnail: 0x8001010d - An outgoing call cannot be made since the application is dispatching an input-synchronous call.

Maybe it is dispatched after all and we could do bring to front on our window. But I didn't see this before.

Looking into it, what is going on.

EDIT2:

Also seems to fail after opening directory, because of mixed forward slashes.

update_thumbnail: 0x800700a1 - The specified path (...) contains one or more invalid characters.

None of the mp3 files with embedded album art works for me.

Works for me, but I changed few things, try latest version.

kasper93 avatar Jun 15 '24 05:06 kasper93

Works for me, but I changed few things, try latest version.

The latest version works now.

na-na-hi avatar Jun 15 '24 05:06 na-na-hi

@na-na-hi: I've added path normalization, which helps with exceptions. Also fixed window focusing. Do you see any other issues?

kasper93 avatar Jun 15 '24 06:06 kasper93

A few more suggestions:

  • The stray app icon/name problem is because mpv isn't installed, but third-party builds can integrate their own installers. I think it's better for mpv to define and use an appid here so that third-party installers can properly integrate and solve this problem.
  • Add an option to disable SMTC. For example, Firefox and Spotify have options to disable this so that they won't hook and steal media key inputs.

na-na-hi avatar Jun 15 '24 16:06 na-na-hi

Changed thumbnail get to do it asynchronous, because it was introducing lag on the buttons for me.

The stray app icon/name problem is because mpv isn't installed, but third-party builds can integrate their own installers. I think it's better for mpv to define and use an appid here so that third-party installers can properly integrate and solve this problem.

I don't know what is required to make it work. So I would rather wait for someone to test and add needed changes.

For example, to even use mpv.exe from installed package, you have to add, something like the following to manifest.

    <msix xmlns="urn:schemas-microsoft-com:msix.v1"
        publisher="CN=mpv"
        packageName="mpv.exe"
        applicationId="mpv.exe"
    />

For libmpv, the story is different and appid, would be of parent app anyway.

I would imagine, we would need smtc-appid property that users can set and it would be set as appid in our code. But I'm not sure it is even needed, so I would like to defer to upstream integrators for those changes.

Add an option to disable SMTC. For example, Firefox and Spotify have options to disable this so that they won't hook and steal media key inputs.

Added --media-controls, so other platforms can connect to it too.

kasper93 avatar Jun 15 '24 17:06 kasper93

I don't know what is required to make it work. So I would rather wait for someone to test and add needed changes.

I think this is OK for now. We can wait for the third-party who cares to submit a PR for that.

na-na-hi avatar Jun 15 '24 17:06 na-na-hi

Honestly given the need to pull in C++ and some winrt stuff I do agree with @na-na-hi's suggestion of keeping this as an external plugin. It doesn't even use anything other than the client API.

Note that this must not mean that we can't have it in the mpv repo. It could even be built and installed by default, just keep it in a separate folder and somewhat separate from the main meson.build.

I've considered it, but since it is pretty core player functionality to integrate into system and macOS does the same. I decided to integrate it inside.

On Linux mpris is the de-facto standard and does not have integration in mpv either (unless you install a plugin). If you wanted to import it into mpv it would be a similar level of annoying because it builds on D-Bus.

At least the thumbnail needs to work, which doesn't seem to be the case for now. If this is not possible from a libmpv client, a different approach is needed.

Thumbnails are absolutely doable from the client API. I do it on mpv-android. I think it's also generally useful to add features to the client API whenever possible (e.g. if we introduce a way to get a nearly live view of the rendered video).

sfan5 avatar Jun 15 '24 20:06 sfan5

Honestly given the need to pull in C++ and some winrt stuff I do agree with @na-na-hi's suggestion of keeping this as an external plugin. It doesn't even use anything other than the client API.

The same can be said for our macOS integration, and yet it is included here.

Note that this must not mean that we can't have it in the mpv repo. It could even be built and installed by default, just keep it in a separate folder and somewhat separate from the main meson.build.

I don't see the real benefit of this approach. Wouldn't this only increase the complexity of the solution from both a development and user perspective? I might be missing something, so please let me know what issues or problems this solution would resolve.

keep it in a separate folder and somewhat separate from the main meson.build.

EDIT: It is in separate meson.build in osdep/win32. And only if it is enabled C++ language is added. Just in case, it wasn't clear. Because it is literally separated as much as possibly can if we would like to link into mpv.exe still.

On Linux mpris is the de-facto standard and does not have integration in mpv either (unless you install a plugin). If you wanted to import it into mpv it would be a similar level of annoying because it builds on D-Bus.

I don't understand the inconvenience you are referring to. Focusing on this PR, it only adds an optional dependency on a few headers, which greatly simplifies the code. As for C++, we already have all the necessary components; it's not like we're adding Rust or Swift.

Thumbnails are absolutely doable from the client API. I do it on mpv-android.

Thumbnails are implemented in this PR. Since you have it integrated within mpv-android too, it seems you agree that it's a feature deserving of integration in the media player frontend. I assume you don't require users to install an external application to handle this basic feature.

I think the main question is, what is mpv.exe? Is it a media player or just a toolkit to DIY one?

Regarding modularizing things, it would indeed be nice to have a clean separation of core mpv code, libmpv API, scripting engines, video outputs, and so on. However, it has never been done that way. We even embed lua source into the mpv binary. Why isn't youtube-dl an external feature? I'm not sure where this modularization requirement is coming from. Not to mention the entire macOS integration, but that's another topic.

tl;dr: I believe media controls (and thumbnails) are fundamental media player features and should be integrated into the media player (mpv). Users should not have to DIY these features. It is prohibitively difficult to know how to enable these media controls. How are users supposed to know that? They just want to download a player and have it work. I love that mpv is customizable, but customizability should extend beyond basic features and target people who like to tinker.

kasper93 avatar Jun 15 '24 23:06 kasper93

The same can be said for our macOS integration, and yet it is included here.

just some additional info, back when i added support for some of the macOS components that are application wide the conclusion was to use libmpv/the client API even for internal usage.

if we are comparing the pulling of c++ in with the objective-c usage in the macOS parts, the latter is a hard requirement since there is no basic c api for a lot of the needed things.

anyway don't misunderstand me, i am not trying to argue against the inclusion, i am more on the side of including such features.

Akemi avatar Jun 16 '24 00:06 Akemi