GSoC 2021: Pin Recordings and CritiqueBrainz Integration in ListenBrainz

Hi! I am Jason Dao, aka jasondk on IRC. I’m a third year undergrad at University of California, Davis. This past summer, I’ve been working with the MetaBrainz team to add some neat features to the project ListenBrainz.

The Proposal

For those unfamiliar, ListenBrainz is one of the many projects under the MetaBrainz umbrella: it’s an open source music website that allows users to import their listen history. Users can create playlists, get recommendations, or find other users with similar music tastes.

My GSoC proposal consisted of two distinct features to ListenBrainz: a social feature that would allow users to “pin” their favorite Listens to their profiles with some text, and another feature that aimed to integrate CritiqueBrainz with ListenBrainz by allowing users to submit reviews for their Listens straight from the ListenBrainz site.

Community Bonding

In January 2021 I had my first encounter with the MetaBrainz community when I submitted my first PR, LB-519, which added a little timestamp to indicate the date of the last imported listen to ListenBrainz’ LastFM importer. I became attached to this importer and submitted a couple more PR’s to improve it, correcting some of the logic, improving error handling, and adding a progress bar to the UI.

Before the coding period started, I also shot a PR to change the way we displayed older timestamps across the website.

The Coding Period Begins

All PRs are viewable here.

(The only tasks remaining are to remove some feature flags, add timeline event for reviews, and add user following pins view)

After fleshing out the plans and sorting out some finer details, it was time to get to work on the first feature, the pinned recordings.

To store the data for the pins, I added a table to our database, created some database methods (SQL queries) to allow us to interact with the table, and added the the API endpoint and routes that would allow for retrieving and interacting with the pins.

At this point that we decided we should include optional MBID’s in addition to MSID’s to the pins, as part of ListenBrainz’ migration to MBID’s. This allows us to easily drop the MSID’s in the future, so I opened a PR for this.

When all the backend stuff was finished, I moved on to creating the frontend components in React, including the ‘submit pin’ popup modal and the pinned recording card. Here is a photo of the modal:

Lastly, PR’s were opened to make these pins playable on the embedded BrainzPlayer, and to add a tab to profiles that would display the entire pin history of the user.

Switching Gears

At last it was time to start on the CritiqueBrainz integration project. And just in time!

Over the summer, the team made some remarkable progress on the MBID mapper, which now links ~80% of Listens to a unique identifier in the MusicBrainz database. These MBID’s can be used to link Listens to recordings, recordings to releases, releases to release groups, and so on. This opens up possibilities for integration across projects as well.

The CritiqueBrainz API uses MBID’s to identify reviewable entities, including recordings, but also artists and release groups.

The first step in this project was to allow not just the recording of a Listen to be reviewable, but also the associated album and artist as well. API functions were added that would perform lookups with the MusicBrainz database to fetch potentially missing MBID’s so more entities could be reviewable per Listen.

At the center of this feature is the React component for the review popup modal. It was important to get it to look pretty and feel intuitive. Here is a photo:

The Lessons I’ve Learned

My experience coding with the MetaBrainz team this summer has been invaluable to me.

One of the challenges I faced was getting used to such a large codebase. It was overwhelming in the beginning, but as I continued to make changes to the code and examined how the files and modules interacted with each other I started to be able to put the pieces together.

Diving into a such a huge codebase for the first time and having to figure out how everything works really helped me internalize the importance of code quality and style. ListenBrainz’ codebase has dozens of contributors but it looks like it was written by a single person for the most part. I got to learn how to write code that was highly standardized, reusable, and readable.

I also internalized that, very often, tasks will take longer than expected to complete. At many points throughout the coding period I found myself revisiting old code that I had already submitted because I realized it should be improved and refactored or it wasn’t working anymore. In the future I’ll be prioritizing more detailed and through planning to hopefully avoid these situations, and staying focused on the bigger picture of what the tasks are meant to accomplish together rather than individually.

The End

It was a blast to be able to interact with other developers, learn from them, and get exposed to so many tools and libraries and frameworks. As a noob, this summer was filled with many ‘firsts’ for me, with each new merged PR, each commit, I felt myself growing more comfortable and confident as a developer..

I am immensely grateful to everyone in the MetaBrainz community, who helped get me through to the end! I would like to especially thank

  • my mentor Robert Kaye (ruaok), for guiding through the summer and whose cleverness I hope rubbed off on me!
  • Kartik Ohri (lucifer), for the labor he poured into CritiqueBrainz and for fixing many of my little mistakes
  • Param Singh (param), for his generosity in reviewing all my React PR’s
  • The MetaBrainz Foundation & Google for this opportunity and introducing me to open source development ^_*

(As soon as they’re deployed), please visit, import some listens, and give these features a try!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.