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

Integrate Apple Music playback into ListenBrainz #2509

Merged
merged 45 commits into from Apr 18, 2024

Conversation

vardansaini
Copy link
Contributor

@vardansaini vardansaini commented Jun 26, 2023

Problem

ListenBrainz currently supports integration with Spotify, but there is a growing demand for integration with other music services. Apple Music is a popular music streaming service, and integrating it into ListenBrainz will provide more options for users to access personalized recommendations.

Solution

Integrating Apple Music into ListenBrainz involves several steps, starting with OAuth configuration on the frontend. The OAuth process facilitates user authentication and access to their Apple Music account. This integration aims to enhance the ListenBrainz experience by allowing users to play music seamlessly from Apple Music through the BrainzPlayer.

  1. OAuth Integration Frontend: To initiate the integration of Apple Music into ListenBrainz, the first step is configuring OAuth on the frontend. This is accomplished using the MusicKit JavaScript library, which offers authentication through the OAuth protocol. To begin, include the MusicKit library in the webpage with the following script:
    htmlCopy code
<script src="https://js-cdn.music.apple.com/musickit/v3/musickit.js" data-web-components async></script>
  1. Developer Token and MusicKit Configuration: To configure MusicKit on the frontend, a developer token needs to be generated on the backend and sent to the frontend. After including the MusicKit library, you can configure the MusicKit instance using the generated developer token:
    javascriptCopy code
    document.addEventListener('musickitloaded', async function () { try { await MusicKit.configure({ developerToken: 'DEVELOPER-TOKEN', app: { name: 'ListenBrainz', build: 'GIT-COMMIT-SHA', } }); const music = MusicKit.getInstance(); } catch (err) { // Handle configuration error } });

  2. User Authentication and Token Submission: The authorize method provided by MusicKit can be utilized to authenticate the user and gain access to their Apple Music account. Upon successful authorization, the obtained Music-User-Token is sent to the server's callback URL. However, it's important to note that Apple Music does not require a client secret for OAuth; instead, the process is carried out client-side using MusicKit.

  3. Backend Processing: The callback URL endpoint for music services receives the authorization code for other services. In the case of Apple Music, the OAuth process is slightly different due to the absence of a client secret. MusicKit is used to handle authorization client-side, and once the user grants access, the music.authorize().then(musicUserToken => {...}) block is executed. The retrieved Music-User-Token is then submitted to the server at the callback URL.

  4. Storing Token and Storefront: To ensure a seamless experience, the obtained token and the user's storefront (region) should be stored in the database for future use. This data will be crucial for accessing and customizing the user's Apple Music content.

  5. Integrate Apple Music in BrainzPlayer: The BrainzPlayer, which is a web-based music player used in ListenBrainz, can be extended to support Apple Music playback. MusicKit is integrated into the player in a manner similar to its inclusion in the OAuth frontend setup.

  6. Player Controls and Event Handling: Once the BrainzPlayer is loaded with MusicKit, various playback controls like play, pause, etc., can be accessed using the MusicKitInstance. Event callbacks can also be added to respond to changes in playback state through the playbackStateWillChange and playbackStateDidChange events.

  7. User Authorization Check: Before implementing event callbacks, it's essential to verify whether the user has authorized Apple Music. This step ensures that only authorized users can interact with the Apple Music integration in the player.

  8. Track Enqueue and Playback: To play tracks from Apple Music, the MusicKit player allows tracks to be enqueued using the setQueue or playNext method. The Apple Music Identifier of the desired track is used to facilitate playback.

  9. Search and Playback: In cases where a specific track lacks an Apple Music Identifier in the ListenBrainz database, the search API can be employed to retrieve relevant tracks. Subsequently, tracks can be enqueued from the search results into the player for seamless playback within the BrainzPlayer interface.

Action

BEFORE MIDTEM EVAL

Video of integration so far :-
https://github.com/metabrainz/listenbrainz-server/assets/61253200/0851bc57-b9f3-4fda-84e2-7a496376fa9d

@MonkeyDo MonkeyDo changed the title apple music player initial Integrate Apple Music playback into ListenBrainz Jun 29, 2023
frontend/js/src/user/Listens.tsx Outdated Show resolved Hide resolved
frontend/js/src/brainzplayer/BrainzPlayer.tsx Outdated Show resolved Hide resolved
frontend/js/src/brainzplayer/BrainzPlayer.tsx Outdated Show resolved Hide resolved
frontend/js/src/brainzplayer/AppleMusicPlayer.tsx Outdated Show resolved Hide resolved
frontend/js/src/brainzplayer/AppleMusicPlayer.tsx Outdated Show resolved Hide resolved
frontend/js/src/brainzplayer/AppleMusicPlayer.tsx Outdated Show resolved Hide resolved
frontend/js/src/brainzplayer/AppleMusicPlayer.tsx Outdated Show resolved Hide resolved
vardansaini and others added 10 commits July 3, 2023 10:46
@amCap1712
Copy link
Member

While testing on test.lb I found a couple of issues:

  1. Apple Music Player asks for authorization as soon as the page loads, this seems rather annoying. We should not try to authenticate until the user is actually trying to play with apple music's player.
  2. The buttons in the screenshot work correctly but the current selection is not highlighted. This is confusing for the user and needs to be fixed.
    image

@amCap1712 amCap1712 marked this pull request as ready for review August 16, 2023 09:51
@amCap1712
Copy link
Member

amCap1712 commented Aug 16, 2023

Hi! Please update the PR description with the workflow describing how this works, what are the blockers and what parts are pending. @MonkeyDo is reworking the test suite of frontend tests so it might be fine to merge this as is and then the tests could come in a separate PR.

Copy link
Contributor

@MonkeyDo MonkeyDo left a comment

Choose a reason for hiding this comment

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

I can't test the music playing because I'm not a premium user, but I have some findings as a non-premium user :p

frontend/js/src/brainzplayer/AppleMusicPlayer.tsx Outdated Show resolved Hide resolved
frontend/js/src/brainzplayer/AppleMusicPlayer.tsx Outdated Show resolved Hide resolved
frontend/js/src/brainzplayer/AppleMusicPlayer.tsx Outdated Show resolved Hide resolved
frontend/js/src/brainzplayer/AppleMusicPlayer.tsx Outdated Show resolved Hide resolved
@MonkeyDo
Copy link
Contributor

Hello @vardansaini , what is the status on this PR?

@vardansaini
Copy link
Contributor Author

Hello @vardansaini , what is the status on this PR?

Hi @MonkeyDo I got super busy with University and some family stuff, I will be back on it as soon as possible. My apologies for the delay!

@pep8speaks
Copy link

pep8speaks commented Mar 25, 2024

Hello @vardansaini! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2024-04-18 12:12:28 UTC

The HTML page we previously had was refactored and now in JS comnponent instead
MonkeyDo and others added 9 commits March 26, 2024 18:17
in the settings/music-services page, requiring a custom method since apple uses a non-standard auth workflow (see previous commits)
+small formatting issues
Note sure why this was added, but it's making the entire test suite fail.
@MonkeyDo MonkeyDo dismissed their stale review April 2, 2024 11:25

My own review from previous code, now outdated. I adressed all issues from my review

@MonkeyDo
Copy link
Contributor

Resolved merge conflicts, deploying to test.LB to ensure I didn't break anything

MonkeyDo and others added 6 commits April 12, 2024 13:26
Allows enabling/disabling the apple music player
On the music services page, it was showing  apple music as connected at all times regardless of the connection status, because it was using the wrong value to determine the connection status
Mais que diable ?1
Copy link
Member

@anshg1214 anshg1214 left a comment

Choose a reason for hiding this comment

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

I have tested this PR on test.lb, and have found a couple of issues as discussed on chat. LMK if I can help with anything.

listenbrainz/config.py.sample Outdated Show resolved Hide resolved
listenbrainz/domain/apple.py Outdated Show resolved Hide resolved
frontend/js/src/common/brainzplayer/AppleMusicPlayer.tsx Outdated Show resolved Hide resolved
listenbrainz/webserver/views/settings.py Outdated Show resolved Hide resolved
Co-authored-by: Ansh Goyal <anshg1214@gmail.com>
MonkeyDo and others added 4 commits April 15, 2024 19:44
The Apple Music authorization is not an OAuth flow, and we don't use that variable anywhere in the codebase
SOMEHOW adding this perfectly valid bitrate configuration option completely break the MusicKit player in our application, and I have no idea why.
Tried in a minimal repro and the option is valid and does not break anything.
Don't ask me why, I already lost a day on this trying to figure out why music wasn't playing anymore even though it was working previously.
Otherwise, currently it just skips to the next one automatically
@MonkeyDo MonkeyDo requested a review from anshg1214 April 18, 2024 12:13
Copy link
Member

@anshg1214 anshg1214 left a comment

Choose a reason for hiding this comment

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

LGTM 🚀

@MonkeyDo MonkeyDo merged commit e583396 into metabrainz:master Apr 18, 2024
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants