MusicBrainz Android App: Adding BrainzPlayer in Android App

Greetings, Everyone!

I am Ashutosh Aswal (IRC nick yellowhatpro), pursuing my bachelor’s from Punjab Engineering College Chandigarh, India. As a Google Summer of Code’22 contributor, I worked for MetaBrainz, on the MusicBrainz Android app and added a music playback feature to the app, which we call BrainzPlayer.

During the GSoC period, I was mentored by Akshat Tiwari (akshaaatt). Through this post, I will be summarizing my journey throughout the summer with MetaBrainz.

Let’s begin!! ( •̀ ω •́ )✧

Project Description

The project’s target was to introduce BrainzPlayer, a local music playback feature, into the MusicBrainz Android app. After this feature integration, users can play locally saved music directly from the app.

My pull requests.

My commits.

Coding Journey

We started with setting up the Music Service, Exoplayer, and the related Media APIs, which allow playback to be possible on the device, even when the app is in the background.

After this, we defined the Media Source, which accesses our local storage to search the media items and make them accessible within the app.

After accomplishing this, we worked on the notifications feature, which shows the metadata of the currently playing media item, and lets us control the playback, like seek, play, pause, etc., directly from the notification panel without opening the app.

Notification Panel

Now we worked on a service connector class that contains the functions to deal with the playback commands within the app.

After this, our app was ready to play songs. Now was the time to add some cool UI.

The UI is written in Jetpack Compose, Android’s latest toolkit for building awesome UI. Using Compose we worked on the Player Screen, which contains the playback features.

Now that we have the music playback feature, we worked on different entities: song, album, artist, and playlist.

To achieve this, we introduced a local database within the app. We introduced the various entities, including the required data and logic layer.

We wrote multiple database queries and added repositories for the entities in the data layer. Then we worked on the logic part and created functions that took in account the data layer and would show the result in the UI.

After working on the data and logic layer, we focused on creating the UI for the different entities. Each entity has its screen, from where the user can play songs. For this, we coordinated with aerozol, and I would thank him for coming up with beautiful designs and our BrainzPlayer logo. Then finally, with the designs in hand, we could execute them in compose.

By the end of the program, we were able to add some animations, and find out bugs and fix them.

Finally, the BrainzPlayer feature is merged with the master branch, so we can expect it to go into production soon. \^o^/

Preview of the upcoming feature:

Acknowledgement:

I want to thank my mentor, akshaaatt, for his immense support and guidance. Under his mentorship, I could learn, experiment, and improve my code quality over the time.

I am also indebted to the MetaBrainz team for their kind and supportive behavior, which made the journey incredible and unforgettable, and makes me motivated to work with them even beyond.

That’s it from my side.
Thank you for having me !! ヾ(≧▽≦*)o

GSoC’22: Personal Recommendation of a track

Hi Everyone!

I am Shatabarto Bhattacharya (also known as riksucks on IRC and hrik2001 on Github). I am an undergraduate student pursuing Information Technology from UIET, Panjab University, Chandigarh, India. This year I participated in Google Summer of Code under MetaBrainz and worked on implementing a feature to send personal recommendation of a track to multiple followers, along with a write up. My mentors for this project were Kartik Ohri (lucifer on IRC) and Nicolas Pelletier (monkey on IRC)

Proposal

For readers, who are not acquainted with ListenBrainz, it is a website where you can integrate multiple listening services and view and manage all your listens at a unified platform. One can not only peruse their own listening habits, but also find other interesting listeners and interact with them. Moreover, one can even interact with their followers (by sending recommendations or pinning recordings). My GSoC proposal pertained to creating one more such interaction with your followers, sending personalized recommendations to your followers.

Community Bonding Period

During the community bonding period, I was finishing up working on implementing feature to hide events in the feed of the user and correcting the response of missing MusicBrainz data API. I had also worked on ListenBrainz earlier (before GSoC), and had worked on small tickets and also had implemented deletion of events from feed and displaying missing MusicBrainz data in ListenBrainz.

Coding Period (Before midterm)

While coding, I realized that the schema and the paradigm of storing data in the user_timeline_event that I had suggested in the proposal won’t be feasible. Hence after discussion with lucifer in the IRC, we decided to store recommendations as JSONB metadata with an array of user IDs representing the recommendees. I had to scratch my brain a bit to polish my SQL skills to craft queries, with help and supervision from lucifer. There was also a time where the codebase for the backend that accepted requests from client had a very poorly written validation system, and pydantic wouldn’t work properly when it came to assignment after a pydantic data-structure had been declared. But after planning the whole thing out, the backend and the SQL code came out eloquent and efficient. The PR for that is here.

{
     "metadata": {
        "track_name": "Natkhat",
        "artist_name": "Seedhe Maut",
        "release_name": "न",
        "recording_mbid": "681a8006-d912-4867-9077-ca29921f5f7f",
        "recording_msid": "124a8006-d904-4823-9355-ca235235537e",
        "users": ["lilriksucks", "lilhrik2001", "hrik2001"],
        "blurb_content": "Try out these new people in Indian Hip-Hop! Yay!"
    }
 }

Example POST request to the server, for personal recommendation.

Coding Period (After midterm)

After the midterm, I started working on creating the modal. At first my aim was to create a dropdown menu for search bar using Bootstrap (as most of the code had bootstrap rather than being coded from scratch). But after a while I consulted with lucifer and monkey and went for coding it from scratch. I had also planned to implement traversing search results using arrow keys, but the feature couldn’t be implemented in due time. Here are screenshots of what was created in this PR.

Accessing menu button for personal recommendation

A modal will appear with a dropdown of usernames to choose for personal recommendation

Modal with usernames chosen and a small note written for recommendation

If one has grokked my proposal, they might already notice that the UI/UX of the coded modal is different from the one proposed. This is because while coding it, I realized that the modal needs to not only look pretty but also go well with the design system. Hence the pills were made blue in color (proposed color was green). While I was finishing up coding the view for seeing recommendations in the feed, I realized that the recommender might want to see the people they had recommended. So, I asked lucifer and monkey, if they would like such feature, and both agreed, hence this UI/UX was born:

Peek into the feed page of recommender

What a recommendee sees

Special thanks to CatQuest and aerozol for their feedbacks over the IRC regarding the UI/UX!

Experience

I am really glad that I got mentorship from lucifer and monkey. Both are people whom I look up to, as they both are people who are not only good at their crafts but are also very good mentors. I really enjoy contributing to ListenBrainz because almost every discussion is a round table discussion. Anyone can chime in and suggest and have very interesting discussions on the IRC. I am very glad that my open source journey started with MetaBrainz and its wholesome community. It is almost every programmer’s dream to work on projects that actually matter. I am so glad that I had the good luck to work on a project that is actually being used by a lot of people and also had the opportunity to work on a large codebase where a lot of people have already contributed. It really made me push my boundaries and made me more confident about being good at open source!

My Google Summer of Code 2022 summary

What and for whom

Organization: MetaBrainz Foundation
Project: MusicBrainz Picard
Mentors: Laurent Monin (zas) & Philipp Wolfer (phw)
Main focus: Introducing single-instance mode in Picard 3.0
GSoC website: Link

What has been done: TL;DR edition

  • Picard works in single-instance mode by default, allowing to force-spawn a new instance
  • Picard accepts not just file paths but also URLs, MBIDs and commands as command-line arguments
  • The command-line arguments are sent to the existing instance (and processed by it) if possible
  • Picard can execute commands passed by the command-line interface; e.g. save all files, show the Picard window or close the app
  • Picard can also load the commands from a text file

List of pull requests

Single-instance mode

  • Picard#2116: A big commit where the whole single-instance mode for Picard was designed and introduced (only for file paths though)
  • Picard#2135: Fixed problems with exiting the app, caused by Picard#2116
  • Picard#2130: Supported URLs (with MBIDs) and mbid:// links (documented there) can be passed with file paths via CLI to an existing (or to a new one) instance
  • Picard#2137: Supported commands (like QUIT or SHOW) can be passed via CLI to an existing instance

Picard remote commands enhancements

  • Picard#2141: REMOVE_EMPTY & REMOVE_UNCLUSTERED commands added
  • Picard#2142: LOAD command, extending the positional arguments’ functionality, added
  • Picard#2143: FROM_FILE command, executing a command pipeline from a given file, added
  • Picard#2144: CLEAR_LOGS command added
  • Picard#2145: Fixed errors with the FROM_FILE command
  • Picard#2146: WRITE_LOGS command, allowing to save Picard logs into a file, added

Code refactoring

  • Picard#2080: Code explicitly marked as deprecated got removed, my initial commit to get to know the Picard’s codebase and workflow
  • Picard#2127: Minor patch, unparsed args are now ignored as they were not used anywhere
  • Picard#2139: Refactored the whole process of passing arguments to Picard, replaced ‘%’-formatted strings with f-strings, more than one arguments can be passed correctly to a command

Other

What have I learnt during GSoC 2022

  • How to work with other people on GitHub
  • How to improve my git experience (e.g. hooks)
  • How one can handle inter-process communication, basically I have researched:
    • pipes
    • named pipes
    • sockets
    • dbus
  • How to use Windows API with Python
  • Differences between Windows and Unix pipes
  • \0 is the only character that is prohibited on both Windows & Unix in path names
  • /tmp is not the recommended way to store non-persistent app data on *nix
  • os._exit might be useful when pythonic threads get broken
  • Importing a tuple in Python is underrated. git diff gets cleaner, as one sees only the additions

Some personal thoughts

  • Python is a really decent language that helps with starting one’s programming journey but the deeper I went, the more annoyances I have encountered (that is why I ended up starting to work as a C++ dev)
  • Ultra-safety is a double-edged sword: good luck terminating Pythonic futures/threads with file operations
  • CI/CD and testing in general is as important as decent codebase
  • If one can plan their time well, flexible work hours make their work both more effective and more enjoyable
  • Python sometimes change for worse or breaks the code without any reason (e.g. they have switched from using a mode into w on pipes, ref: LINK)
  • I will not start any new personal project in Python (especially one using multi-threading, multiple processes etc.), unless forced to do so. Nu for scripting, filling the niche & exploring the functional programming, some statically-typed languages for bigger projects, games, research, etc.
  • Impostor syndrome is just an another excuse to procrastinate. Do not be scared to learn & do new things but also ask smart questions. Everyone makes mistakes but if you made it to this org, you are a good fit and have enough qualifications

Special thanks

The whole MetaBrainz community is awesome and I am glad I have become a part of it, but I would like to express my special gratitude to the people I have directly worked with in any way 🙂 (alphabetical order by github username)

GSoC’22: CritiqueBrainz reviews for BookBrainz entities

Greetings, Everyone!

I am Ansh Goyal (ansh on IRC), an undergraduate student from the Birla Institute of Technology and Science (BITS), Pilani, India. This summer, I participated in Google Summer of Code and introduced a new feature, CritiqueBrainz reviews for BookBrainz entities.

I was mentored by Alastair Porter (alastairp on IRC) and Nicolas Pelletier (monkey on IRC) during this period. This post summarizes my contributions made for this project and my experiences throughout the journey.

Proposal

Book reviews are a glimpse into a world you may or may not choose to enter. Reviews give books greater visibility and a greater chance of getting found by more readers. BookBrainz and CritiqueBrainz should enable users to rate and write reviews directly through the website using the CritiqueBrainz API.

For GSoC ’22, I made a proposal that aimed at adding CritiqueBrainz reviews for BookBrainz entities.

Community Bonding

During the community bonding period, my mentors, Alastair Porter and Nicolas Pelletier, helped me create a streamlined pathway to move along with the project. We also worked on various tickets like CB-433, CB-434, and CB-410 and added multiple features.

So we decided first to complete reviewing BookBrainz edition groups thoroughly from CritiqueBrainz as well as BookBrainz, and then extend the project for all other entities like literary work, author, and Series.

We discussed the various database and structural changes involved in the project, like adding BookBrainz Database in CritiqueBrainz, adding tables in BookBrainz DB, etc., the page designs and overall improvements.

Coding Period

The coding period starts with importing the BB database in CB to fetch the required information and perform tests. 

Now that the database was set up and ready for us to work on, it was time to write SQL queries for fetching the edition groups and all the other associated information, like identifiers and relationships. I made the code reusable to prevent duplication while fetching data for different entity types. So I opened a PR for it.

So now it was the time to allow users to review an edition group in CritiqueBrainz. For this, I made a few changes in the database, allowed BB entity types, and then added pages for their reviews in this PR. Then I worked on showing the information fetched from the BookBrainz database to the users on their entity pages.

Then to allow users to search edition groups, I worked on adding an option to search BB entities with the help of the search API already present in BB. This feature was implemented in this PR.

After adding support for Edition Groups, it was time to add support for other entity types. This expansion was very smooth because of the reusable components created by then. So I added support for Literary Works, Authors and Series. Later we discovered that the series items were not being ordered correctly, so this was fixed in #460.

During this process, my mentors and I discovered some improvements and refactoring, which were done in #445#451 and #456.

After adding support for all the entities, I added support for showing the relationships between the entities on the respective entity pages. These included showing Author-Work, Work-Edition Group, and Work-Work relationships.

CritiqueBrainz Author’s Page

While enabling CritiqueBrainz to review entities, I was also working on BookBrainz to allow users to view reviews and ratings and post them from  the entity’s page. 

So I started adding support to fetch and display reviews and ratings for edition groups which involved creating a route which would handle getting and pushing reviews to CritiqueBrainz. 

After this step, it was time to connect BookBrainz with CritiqueBrainz. This involved authentication using OAuth login. To add this feature, I first added a table ‘external_service_oauth’ in the database and then in the ORM.

Then I added routes to allow user login to CritiqueBrainz, handled the callback, and saved the tokens in the database. After that, the next thing was to allow users to post reviews from the entity page. For that, I create a modal similar to the one in ListenBrainz (to maintain consistency).

BookBrainz

After completing my project, I began working on my stretch goals and starting with unifying reviews for entities common in both BookBrainz and MusicBrainz databases. We decided that if an entity exists in both databases, we show the reviews for all the entities on the entity page (PR).

Overall Experience

I am incredibly grateful to my mentors for their constant guidance and support throughout my project. I learned a lot of technical concepts and improved the quality of my code during this journey. I had a wonderful time interacting with the amazing folks at MetaBrainz and exchanging valuable thoughts during our weekly meetings.

I would love to thank Google and the MetaBrainz Foundation for providing me with this great opportunity!

GSoC 2022: Unified Form Editor for BookBrainz

Hi, I am Shubham gupta (IRC Shubh) pursuing my bachelor’s from the National Institute of Technology, Kurushetra. This year I participated in Google Summer of Code and implemented a new editor in Bookbrainz.

In this project, I was mentored by Nicolas Pelletier (IRC monkey). The purpose of this blog is to summarize my contribution made for this project and share my experiences along the way.

Before GSoC

I joined metabrainz at the end of November’21, due to my affection for novels I instantly fell in love with BookBrainz project. I initially started working on small bug fixes and typo corrections but later shifted to work on more challenging features.

My first challenging work was to pre-fill the current entity editor with POST requests which was required for user scripts to work and also created some user scripts to help simplify the creation process.

Later I worked on to upgrade react-select and completing notification feature on BB.

Proposal

For GSoC’22, I made a proposal to work on implementing a unified form on BookBrainz.

My main motivation behind this project was to make the entity creation process more intuitive and simpler for new users. The purpose of this project is to unify all the workflows of entity creation into a simpler book interface, this abstracts away the BookBrainz specifics for users and provides them an easy interface to work with.

Though a lot has changed since the proposal, from design to implementation details, the main idea behind the project remained unchanged.

Community Bonding

During this period, I worked with my mentor to finalize the design for the editor. This included a lot of back & forth discussion but finally, we ended up picking a base design that was similar to how we choose a book: we first go through the book’s cover and back cover, then its details and inner contents.

I also discussed a new timeline with my mentor which incorporated my university classes and exams. Following this I started implementing the editor from this period itself.

Coding Period

First Phase

By this phase, I completed all the mockups and made relevant changes in design as suggested by community members.

We ended up with the following design, also later we added a summary section as a new tab to make reviewing new entities easier.

unified-form mock

I started working on the new editor routes which can support multiple entity submissions for the creation and later added support for editing as well.

Pull requests: #847#858

Since a lot of implementation was similar to existing entity routes, the main thing that was missing was to unify them into one api and make it support temporary BBIDs for new entities.

The main idea behind keeping temporary BBIDs was to allow late submission of entities, meaning new entities would only be created when the user submits the whole form. This allowed a user to undo their actions and gave them more granular control over entity creation/modification. But following this approach resulted in a lot of duplicate code which was hard to generalize due to temporary ids; this was later fixed in the second phase.

I completed working on the routes part with suitable tests and started working on the React front-end. I started by setting up a Redux store to handle multiple entity states, after some discussion with my mentor we ended up going with the state design that segregates each entity into their own states.

At the end of this phase, the editor looked something like this

First Phase Screenshot

Second Phase

During this period I continued working on the editor interface since that is the meat of the project it took most of the time of this project.

Frontend PR:#850

The challenging part of managing a large store like we had was to minimize the state updates as much as possible, since this was so crucial for performance I spent about a week reading redux articles and profiling editor state. All this paid off and resulted in blazingly fast editors (entity/unified-form) with minimal state update calls, which also benefited the existing editing pages.

The solution was to reduce the scope of a redux state by memoizing the components as much as possible and caching the results of expensive calculations which reduced component load time drastically.

After implementing all entity creation workflows, I moved to linking them, either through relationship or by some other attributes.

This linking process needs to be automatic and users don’t have to know the relationships, they should also be able to opt-out of linking specific entities with respective checkboxes.

An example of linking entities is Series-Work, where selecting a Work already adds it to a Series item.

Unified Form Series Editor

We also introduce a major change in the way we submit the entities: we now submit new entities directly to the server. This reduced the duplicate code by half as compared to before since now we don’t have to manage those temporary ids anymore. This also resulted in reducing the amount of work potentially lost when an error occurs during filling the form.

I also wrote mocha/enzyme tests for required React components. This is all for the frontend PR.

I made the follow-up PRs to improve UI and introduced bug fixes: #872#871#874

Overall Experience

I enjoyed working together with my mentor on such a large project. I learned a lot during my journey and understood the importance of different phases of software development. I realized the importance of carefully designing the application and discussing the ideas with other team members. I also got to know a lot about testing and why it is so important for large projects like this, overall the best learning experience I could ask for.

Also, the members of the MetaBrainz foundation are very supportive and help each other to resolve issues. Lastly special thanks to my mentor Nicolas Pelletier who helped me a lot during my GSoC journey. He always supported me and encouraged me even when things weren’t looking good. He is truly one of the most amazing people I’ve ever met!

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.

Continue reading “GSoC 2021: Pin Recordings and CritiqueBrainz Integration in ListenBrainz”

GSoC’21: MusicBrainz Android App: Dawn of Showdown

Greetings, Everyone!

I am Akshat Tiwari (akshaaatt on IRC), an undergraduate student from Delhi Technological University, India.

It has been an exhilarating experience for me, right from submitting a proposal for GSoC to becoming a part of a fantastic community.

The Google Summer of Code 2021 Edition finally comes to an end after the 3-Month long journey. I will be detailing the journey of working towards my summer of code project today. This blog is a summary of all the work done.

Continue reading “GSoC’21: MusicBrainz Android App: Dawn of Showdown”

GSoC 2021: Complete Rust binding for the MusicBrainz API

Hi Everyone! I am Ritiek Malhotra (ritiek on IRC) and recently completed my undergraduate degree in Computer Science and Engineering. I participated in Google Summer of Code ’21 and worked on musicbrainz_rs – a library wrapper on the MusicBrainz Web API written for the Rust programming language.

Continue reading “GSoC 2021: Complete Rust binding for the MusicBrainz API”

GSoC 2021: Push the URL relationship editor to the next level

Hello everyone, I’m Yang Yang (aka yyoung), an undergraduate student from Shanghai Jiao Tong University, China. I am honored to be accepted as a student of Google Summer of Code 2021 in MetaBrainz Foundation to work on the improvements of external links editor. I had a good time with the MusicBrainz dev team this summer, and it was a valuable experience for me. This is a final report and overview of my work.

Continue reading “GSoC 2021: Push the URL relationship editor to the next level”

GSoC 2021: Series Entity for BookBrainz

Hi everyone, I am Akash Gupta, currently pursuing my undergraduate from Kalinga Institute of Industrial Technology. This summer, I participated in Google Summer of Code and developed a new feature — Series Entity— for the project BookBrainz.

I was mentored by Nicolas Pelletier (monkey on IRC) during this period. This post summarizes my contributions to the project and the experiences that I had throughout the summer.

Continue reading “GSoC 2021: Series Entity for BookBrainz”