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

Media keys support (MPRIS, etc) #24

Closed
Sinono3 opened this issue Jan 20, 2021 · 7 comments
Closed

Media keys support (MPRIS, etc) #24

Sinono3 opened this issue Jan 20, 2021 · 7 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@Sinono3
Copy link
Contributor

Sinono3 commented Jan 20, 2021

Hi. I really like this client and I want to have a go at implementing media keys support. I've been doing some research and doing this seems straightforward. Please forgive me if my issue format or style isn't correct, it's my first time posting an issue on an open-source project, besides English isn't my first language 😅

Implementation details

I need some orientation as to in what part of the project this has to be implemented. In terms of in which crate, I assume psst-gui since it's the highest level one of them all. I've looked at the code a bit and got a general idea of it. Still, I don't know how and where the media key receiver should modify the app's state, maybe this could be done via polling the receiver for events on every frame and then applying the changes to the state. I hope multithreading isn't necessary (I haven't done anything with it except for a few experiments).

Cross-platform support

Surprisingly, I haven't found an all-in-one solution for cross-platform media keys support in Rust. Maybe because each platform's implementation slightly varies in capability, or maybe I haven't looked good enough. I was thinking we could maybe create a MediaKeys trait with some basic functionality functions:

trait MediaKeys {
	fn process_event(&mut self, state: &mut AppState, event: MediaKeyEvent);
	fn emit_metadata(&mut self, state: &AppState);
}

And then, derive that trait for each platform implementation: LinuxMediaKeys, MacOSMediaKeys, etc. Then maybe use Cargo features or other cfg! stuff to actually compile each of them only in their respective platforms.

Personally, I can try to implement it on Linux first, and then Windows but I am not quite sure about macOS since I don't own an Apple desktop or laptop.

My sources for most of this actually come from this blogpost.

Linux

Using D-Bus MPRIS messages and maybe the mpris-player crate, I think it'll be quite simple. This crate is a bit old and it uses function callbacks for things so I might have to do it in a different way.

Windows

It seems System Media Transport Controls is the way to go. Haven't quite looked into it yet.

macOS

Haven't looked into it yet, but here's what the blogpost says:

My experience as a user of macOS is very limited, and as a developer non-existent, but it seems that the macOS equivalent of MPRIS is MPRemoteCommandCenter in the Media Player framework.

@seeplusplus
Copy link

Hi! I also thought about tackling this issue. I'm also in pretty unfamiliar territory, but it looks like druid supports key events. I'm not sure if this captures KeyEvents that occur globally or just within the context of when the application is currently focused.

Surprisingly, I haven't found an all-in-one solution for cross-platform media keys support in Rust. Maybe because each platform's implementation slightly varies in capability, or maybe I haven't looked good enough.

I also ran into this same issue, so I'm guessing this just hasn't been really solved for, unless this is something that "just works" in Druid. I don't know if media keys are captured by key events (I'll be spinning up a dummy druid application tonight to play around with this, as I've never worked with druid before).

@jpochyla
Copy link
Owner

Thank you @Sinono3 for the research! With the exception of Windows, I've looked into possible ways for media keys control and ended up with the same results, MPRIS on Linux, and Now Playing on MacOS. This is definitely wanted. I also think this would deserve a separate crate, so others can use it as well, providing an interface to all three APIs behind future gates, and additionally unifying them behind a common trait.

@seeplusplus I'm not sure this would be in scope for Druid, as a correct media control support would also need things like reporting the information of current playback, not just key presses.

@jpochyla jpochyla added enhancement New feature or request help wanted Extra attention is needed labels Jan 22, 2021
@seeplusplus
Copy link

seeplusplus commented Jan 22, 2021

From a purely separation of concerns standpoint I think I'd see value in putting the "key presses" portion of media control support in Druid. We (Psst) should not (in terms of design) have to be concerned with platform specific implementations of listening for media key input (IMO). That should be Druid's job. What we do with those events (i.e., media control support) should be up to the application (e.g., Psst). I could be wrong though, I'm interested to see what the folks over at Druid think. Worst case, we write platform specific code for listening for media keys and find a way to package that separately from Psst, since it doesn't seem like there exists anything already in the ecosystem for doing this.

@Sinono3
Copy link
Contributor Author

Sinono3 commented Jan 27, 2021

Heya. I just want to say I've been working on a basic implementation of this library. Once I finish the main structure and check that it works, I'll upload a git repository. It works a bit like I explained in my original post, with slight variations.

In terms of platforms, I'm getting close to getting the Windows version working, it was a pain doing interop with WinRT. I had to use the Chromium source code as reference. Next I'll try MPRIS in Linux, if that's okay.

From a purely separation of concerns standpoint I think I'd see value in putting the "key presses" portion of media control support in Druid.

The thing is, media controls are never (in all cases I've seen, at least) handled directly with a global keypress handler, instead, each OS creates an abstraction layer to also allow metadata, album cover art, and other functionality. Besides, it also allows for things such as having multiple media players without there being any collision: if programs directly listened for global keypresses, you could not play/pause one of them without doing so for the other, because there would be no differentation.

@Sinono3
Copy link
Contributor Author

Sinono3 commented Jan 28, 2021

I got a veeery rudimentary version of the crate working on Windows. Here's the link to the repo if anyone's interested in contributing or maybe a few months down the road getting it to work with Psst.

@jpochyla
Copy link
Owner

jpochyla commented Feb 2, 2021

Looks cool! I can contribute and test the Mac support.

@jpochyla
Copy link
Owner

Souvlaki is integrated now, closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants