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

Interface with macOS's media controls and now playing info in Control Center #4809

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

fwcd
Copy link
Member

@fwcd fwcd commented Jun 18, 2022

This branch exposes Mixxx's playback state to macOS through the Media Player framework, making it externally controllable (e.g. via control center, media keys etc.):

Screen Shot 2022-06-18 at 05 53 16

Some notes on the implementation:

  • The implementation of MacOSMediaPlayerService is written in Objective-C++. This should not be an issue, given that Clang handles ObjC++ natively pretty well, but something to be aware of (I needed to tweak the clang-format config, since it would otherwise fail when trying to format some ObjC constructs)
  • The API of the MacOSMediaPlayerService closely follows the ScrobblingService from expose current track metadata to external APIs #3483, to make integration with the more general abstractions from the other PR for exposing playback metadata easy (in the future).
    • Ideally, all of the general challenges surrounding exposing playback metadata should be handled abstractly (e.g. figuring out which decks to play/pause etc.), so the service implementations can focus on the platform-specifics (e.g. macOS in this case or MPRIS, ...)

To do

  • Set up basic infrastructure (MacOSMediaPlayerService, Objective-C++, linking the Media Player framework)
  • Expose basic track metadata (title, artist, album, ...)
  • Expose cover art
  • Expose track playback info
    • Duration
    • Elapsed time
  • Implement remote command callbacks
    • Play
    • Pause
    • Seek
    • Skipping via auto-DJ
  • Figure out whether we need to manually manage memory on ObjC objects and blocks
    • We've enabled Automatic Reference Counting (ARC) via -fobjc-arc that takes care of this

Future Directions

  • Compute correct rate from bpm adjustment in slotBroadcastCurrentTrack. This isn't that urgent though since the playback position corrects itself ~every second in slotPlayPositionChanged and might just be nice to have a smoother slider.
  • Implement ScrobblingService interface from expose current track metadata to external APIs #3483 (once ready)

@github-actions github-actions bot added the build label Jun 18, 2022
Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

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

Nice!1 Thank you very much for picking this up.

@github-actions
Copy link

This PR is marked as stale because it has been open 90 days with no activity.

@github-actions github-actions bot added the stale Stale issues that haven't been updated for a long time. label Sep 18, 2022
@fwcd fwcd force-pushed the macos-media-player-service branch from 9670686 to 1a303bd Compare October 3, 2022 14:27
@ronso0 ronso0 added macos and removed stale Stale issues that haven't been updated for a long time. labels Oct 3, 2022
@fwcd fwcd force-pushed the macos-media-player-service branch 3 times, most recently from 328b63f to 8f5ccb8 Compare March 18, 2023 01:46
Comment on lines 108 to 137
MacOSMediaPlayerService::~MacOSMediaPlayerService() {
for (DeckAttributes* attributes : qAsConst(m_deckAttributes)) {
delete attributes;
}
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Implementation note: This approach of managing memory manually is based on

MprisPlayer::~MprisPlayer() {
for (DeckAttributes* attrib : qAsConst(m_deckAttributes)) {
delete attrib;
}
}
from #3483, I haven't found a better way to do this though since DeckAttributes doesn't seem to provide an easy way to hook itself into the QObject graph.

@fwcd fwcd marked this pull request as ready for review March 18, 2023 02:18
@Swiftb0y
Copy link
Member

Since this involves Obj-C code again, I'd step up to review this, but I have a little too much on my plate right now. Feel free to ping me sometimes so I don't forget about this and can address it when I have my time. Thank you.

@fwcd fwcd force-pushed the macos-media-player-service branch from fb7b792 to dd58d98 Compare March 30, 2023 00:10
@Swiftb0y
Copy link
Member

There are still unaddressed comments from previous reviews. Also IMO, we should really introduce an abstraction for these external player concepts first. Otherwise we end up duplicating lots of code. I think #3483 contains that but its quite big for review. It would be nice if that abstraction could be factored out first...

@fwcd
Copy link
Member Author

fwcd commented Apr 19, 2023

There are still unaddressed comments from previous reviews.

Do you mean #4809 (comment)?

It would be nice if that abstraction could be factored out first...

I agree, would be really cool to have the more general abstraction for this first.

@Swiftb0y
Copy link
Member

There are still unaddressed comments from previous reviews.

Do you mean #4809 (comment)?

Yes.

It would be nice if that abstraction could be factored out first...

I agree, would be really cool to have the more general abstraction for this first.

Do you have interest in working on that?

@fwcd
Copy link
Member Author

fwcd commented Apr 19, 2023

Do you have interest in working on that?

I am afraid I don't really have the time to dig into that and I'm not really familiar with the relevant design and implementation choices there.

Yes.

As mentioned, I think the current solution should work fine, since we create a new dictionary per track. The isNull case can occur

emit coverFound(pRequestor, coverInfo, QPixmap(), requestedCacheKey, false);
An assert wouldn't work therefore. So if there's anything to do there, I'd appreciate some more feedback.

@daschuer
Copy link
Member

What is the sate here? Is that still working?
Can you resolve the conflict?

@fwcd
Copy link
Member Author

fwcd commented Oct 16, 2023

Sure! My hope was that we could get the interface from #3483 merged first, but otherwise the PR should be pretty much ready (though it could of course use some battle-testing).

} // anonymous namespace

MacOSMediaPlayerService::MacOSMediaPlayerService(
PlayerManagerInterface& pPlayerManager) {
Copy link
Member Author

Choose a reason for hiding this comment

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

There are a few design questions that might be interesting though, especially for the "interface PR": Given that this service also handles control in both directions (play/pause, seeking), the question would be if the scrobbling service interface should support that too. Currently the MacOSMediaPlayerService simply takes a play manager and then wires itself up to that, but perhaps we'd want to take the opportunity and abstract over that too.

@fwcd fwcd force-pushed the macos-media-player-service branch from a30cf7a to 915dfcf Compare October 27, 2023 12:03
@github-actions github-actions bot added the broadcast Bugs pertaining to streaming radio broadcaster use-case label Oct 27, 2023
@fwcd fwcd mentioned this pull request Nov 6, 2023
@fwcd fwcd force-pushed the macos-media-player-service branch from e7502ca to e4029b8 Compare July 23, 2024 00:03
fwcd and others added 11 commits July 23, 2024 02:50
- Stub out MacOSMediaPlayerService
- Broadcast now playing info to MPNowPlayingInfoCenter
- Wire up MacOSMediaPlayerService
- Remove unused dependency
- Set now playing playback state
- Define __MACOS_MEDIAPLAYER__ publicly
- Set asset URL and media type for now playing
- Set some dummy values for playback rate and time
- Set MPNowPlayingInfoPropertyIsLiveStream
- Register play command in MPRemoteCommandCenter
- Successfully load cover art asynchronously to macOS media player
- Handle case where broadcasted track is null
- Add moc include
- Use new CoverArtCache API
Copy link
Member

@acolombier acolombier left a comment

Choose a reason for hiding this comment

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

This is a great feature! Just a small suggestion, but happy to approve and merge otherwise!

Comment on lines +277 to +279
const CoverInfo& coverInfo,
const QPixmap& pixmap) {
Q_UNUSED(coverInfo);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
const CoverInfo& coverInfo,
const QPixmap& pixmap) {
Q_UNUSED(coverInfo);
const CoverInfo&,
const QPixmap& pixmap) {

Copy link
Member

Choose a reason for hiding this comment

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

As per our new guideline on this, introduced a few hours ago ;)

Comment on lines +383 to +385
#ifdef __MACOS_MEDIAPLAYER__
m_pMacOSMediaPlayerService = std::make_shared<MacOSMediaPlayerService>(*m_pPlayerManager);
#endif
Copy link
Member

Choose a reason for hiding this comment

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

This means that this feature will always be enabled for user (since I assume we will probably ship a Mixxx release with MACOS_MEDIAPLAYER=on), however I can imagine some user not wanting this integration to be on, so would you consider adding a user setting for this? Note that I'm not a Mac user, so happy to ignore that one!

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea, I'm not sure where to put that though. Ideally, this should probably go into DlgPrefMetadata as proposed in https://github.com/mixxxdj/mixxx/pull/3483/files#diff-25906de66775af0b1495dd1a528cc4256dd1de4778a23a494db27fbb4c164a76

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I think it sounds sensible to unify it with #3483 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
broadcast Bugs pertaining to streaming radio broadcaster use-case build code quality macos needs review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants