Many years ago (October 2015, to be exact) I wrote a small plugin that allows you to add a note when updating a post, intended as a way to describe what was changed in that revision. For the developer set, it’s kind of like commit messages for your WordPress post/content updates. It was created to fill a need on various WordPress.org sites, such as the handbooks, but it seemed generally useful so I released it as a public plugin. After one more update in August 2016, it just sat there, usable and useful but without any attention. Until this week.
I stream my open source work semi-regularly, and decided that working through how to adapt an old plugin to the block editor (2 years late) would make for a useful exercise. So I did that, for almost 4 hours! But that’s not how long it takes to do this – the base work of this really took about 45 minutes, with the rest of the time spent chatting and chasing a bug related to revisions. So, for this post I’m going to explain the process of achieving the final code, first demonstrating what most people will need, then what I actually did because of some specific UX needs, and then dissect the revision bug and things I tried that didn’t work out.
Masterclasses are not unique to classical music, but they do form a central and critical component of music study. A masterclass is a format in which musicians perform a work for an established artist and the artist then gives them feedback rather like a lesson, except that all of this happens in front of an audience. You might also hear about “studio class” in music school settings, which are similar except that it is not an open audience but instead one made up of your peers who share the same primary professor. For big artists coming to a school or a region, you might have to audition (compete) for a spot to be criticized publicly on your performance. Put that way, it might not sound very appealing, but it is foundational in how to function and succeed as a musician and really in any profession, including as a part of a software team, which is what I do today.
Managing feedback in group settings
The first experience in managing professional feedback is typically how you receive it. Sometimes you might not immediately agree with what you’re being asked to do, and that’s okay. What’s important is to respect the time and effort of the person giving you the feedback and show them that you understand it, even if after synthesizing that information you decide it’s not the direction you want to go. In music, that means acknowledging what you’ve heard by demonstrating the requested change on the spot. This might be a specific request, like “play this section softer”, or something that requires more interpretation, like “don’t lose momentum by getting stuck before the high point of this phrase”. This kind of flexibility is itself a skill, and one that is of high value.
In software, your feedback sessions might not involve direct and immediate action in the same way, but it can be very helpful to show that you understand a concept. For instance, you might say “I hear you, and I need to think about it some more; I’ll start by trying out a different way of structuring this file”. Do be careful not to just repeat back verbatim all the time or come across as explaining back in a condescending way.
As you progress through your career, you will likely find yourself in the position of also giving feedback in a group setting. For many people who are just beginning this part of the journey, this can be quite intimidating because you have not previously had experience in doing this. You also may have had bad experiences in the past with feedback that was not delivered in a constructive way. This is where an early culture of group feedback comes in so handy, notably in the studio class setting: professors are asking your peers to also learn how to process, structure, and deliver feedback in real time. You hear from your professor every week; this is an opportunity for students to deliver a polished performance, receive feedback, and give feedback all at once.
That said, peer groups can also be intimidating. This is not unlike having to give a talk or demo some code in front of your coworkers – it can feel like more pressure than a large room of strangers because these are people whose opinions you are exposed to on a near-daily basis and hopefully care about. Remember that we are all learning all the time, and your peers may also need to work on their delivery! Some strategies you may have encountered are to use “yes, and” instead of “but”, or to begin feedback with related praise.
I highly recommend that teams actively solicit peer feedback at various stages throughout a project and also workshop methods of requesting and giving feedback, something that can be facilitated by an engineering manager. An EM might even want to structure some team meetings much like a studio class, where people present on something they’re working on so that not only do they have a chance to share about something they might not otherwise get to talk about, but the team also has a mechanism built-in for giving and receiving feedback. Soliciting feedback is also a skill in its own right – a culture of regular and expected feedback goes a long way toward building that in all levels of team members.
Another major difference between masterclasses and lessons is that you are expected to present a polished product at a masterclass, whereas lessons are to workshop that polish. In a masterclass setting, you and any collaborators enter the stage, bow, and perform to applause before proceeding with the feedback from the masterclass artist. Some professors, especially at the conservatory level, also require performance attire when performing in studio class (though perhaps not black tie).
Working on a software team typically does not involve building something in a vacuum until you’re ready to release it to the world – you hopefully have team checkpoints that are more equivalent to music lessons. But there is a lot to be said for knowing that even though you’re ready to share your work publicly and have met your deadline, there’s still more that can be done, rather like a software beta. And even for something you’ve been performing for a long time, a fresh perspective can change not only how you’re approaching that piece, but how you think about your craft in general. Always be prepared to show your best and recognize that true mastery is in knowing that there’s always another level to reach for.
While masterclasses are typically with an individual artist who specializes in an instrument, many works involve other musicians, such as a string quartet or a piano trio. These are things that are worth bringing to masterclasses too! Related, it’s also valuable to have lessons from people who might normally be considered outside of your discipline – one of the best lessons I’ve ever had was with a jazz professor who spent 2 hours pushing me to express myself more and more.
Not only do your collaborators need to be equally prepared, you need to work together to really achieve artistry. All too often you will see lower-level instrumental masterclasses where the pianist is an afterthought, plunking their way dutifully through concerto reductions, and it shows. Sometimes the masterclass artist will also dutifully ignore them, but more often they have to involve all collaborators in their feedback. No amount of telling a vocalist to evoke the dreamy sparkling of Debussy’s Nuit d’Etoiles is going to work if the pianist is heavy-handed on those rolled chords, or vice versa. (This is also why collaborative pianists have to study lyric diction and multiple languages and can specialize in vocal coaching, but I digress.)
Not only does feedback need to be inclusive of a group while also targeted to each individual, it needs to be clearly contextualized. In music, that means including music history and theory as well – the performance practices of the era, specific notational quirks of the composer, what harmonies are and how do they drive the piece, and limitations of instruments and how they interact together. So when giving feedback to a software team, be sure to continually frame things within broader feature or product goals, and tie the various disciplines together to create that cohesive whole.
In both giving and receiving that style of feedback, you will find that you need to have some amount of understanding of disciplines outside of your own. That doesn’t mean that you need to be an expert; in fact, you will probably be received poorly if you try to instruct somebody on how specifically to accomplish something you don’t normally work on. Instead, much like framing within broader goals, think about how you might inspire somebody to look at something a different way, or contextualize within your own discipline so that they can understand you better as well.
Bonus: watch a masterclass!
Here’s a 45 minute masterclass session with Benjamin Zander, the music director/conductor of the Boston Philharmonic Orchestra and the Boston Philharmonic Youth Orchestra, and Amanda Chi, the cello section lead of the youth orchestra. I promise you don’t need to be a musician to get something out of this – at one point, Maestro Zander acknowledges non-musicians in the audience and gives them a brief explanation of what he means by the direction and pull of harmonies. But even outside of that, you’ll see some real mastery of not only the musical material from both parties, but also how to address both audience and performer, contextualize the feedback, and deliver that feedback in a constructive and suggestive way rather than making it into a personal demand. I also really enjoy what he talks about at the end, differentiating between what you need to do as a performer of this solo piece versus what you need to do as the leader of your group.
You know how everybody hates on recipe blogs that start posts with stories even though a) it’s good for copyright and b) stories can tell you a lot of things about humans and the why and how of their food, well if that’s you then you’re going to hate this tech recipe! Or you’ve already scrolled past this.
So. Last year, I saw this tweet:
I have never done any hardware tinkering, but I immediately wanted to make one of these for my kids. The oldest is pretty good with making requests from voice assistants, but the little one isn’t there yet and we have some other problems anyway: preferring edited or specific alternate versions, difficulty requesting things that aren’t in English, and often a lot of people in the house making a lot of noise, which leads to yelling and garbled results. (See what I did there, I defined the problems I was trying to solve for, it’s like I’m good at my job or something.)
Since I have a few Raspberry Pis I’ve acquired as conference speaker gifts, I wanted to try to use as many existing parts as possible. My first thought was that I would like to play audio through an unused Google Home Mini, but it doesn’t have aux-in and honestly I just could not decipher the documentation around Google Assistant+Actions and those type of generic names and entangled services make things highly unsearchable. I decided to go with regular audio output and figure I can keep iterating with software and/or hardware over time.
The original maker doesn’t seem to have ended up doing a write up of what he did, so I took a look at other similar things people have built. I found this blog post, which took me to their code on GitHub. Availability and pricing as well as a love for the more tactile experience told me I still wanted to use swipe cards rather than RFID, and I don’t really know Python and wanted to make something with as little configuration or dependency management as possible so I figured I was on my own code-wise. That said, that blog post gave me a general direction for approach and led me to Pi MusicBox, which also serves as the base for my player.
I finally ordered the materials off Amazon mid-December for my spouse to bring back from his trip to the US, and got to work because I only had a week to get it all done. Here’s my planner page I worked on to get a head start while I waited:
First up was testing the card reader and setting up the writer, which was not a smooth process. I had to find the writer software online, because who has a CD drive anymore? The driver took forever to finish installation for some reason, but once it got there it seemed to work. Except that the card reader wasn’t returning anything. I tried a regular old bank card (I used one for a defunct account just to be extra safe) and only got numbers, no name, even though having done my time in retail I knew my name should show up in the magstripe data. I tried writing data to a fresh card in all 3 tracks and would only get tracks 2 and 3 from the reader, or sometimes even just track 3. Seems like a malfunctioning card reader (I’ve also occasionally noticed ghost input now that the jukebox has been running for a few days). Update in 2020: I got a second card reader and it works correctly.
Because tracks 2 and 3 can only contain numbers, I decided that the best route to go would be to just encode numbers sequentially and grab that line from a list of Spotify URIs for playback. My first few tests got nowhere – successful write, but wouldn’t read. I tried finding a new card reader in person but to no avail. I tried test data again and… it worked? That’s when I realized that my test data had three numbers, so I tried putting 001 and voilà, that fixed it. After thinking through it a bit, I actually realized that this was the best route anyway – if a Spotify URI stops working, I can swap it out, and the usual ISO encoding for cards is all-caps anyway, and the URIs are case-sensitive.
I decided to put the number on all 3 tracks since the reader seemed to unpredictably read either one or both of tracks 2 and 3 and I might replace it later. This was pretty easy in the card writer software, which allows you to create cards from a file, which I generated using a quick and dirty Bash script. I also made a card with 999 as a special case for toggling playback – there is also a local web server you can access for various functionality including shutdown/reboot, but a basic toggle seemed useful for the kids.
The script itself is extremely small – it does a little Bash magic (parameter expansion!) to extract the first number it comes across, strips off any leading zeroes, and then gets the indicated line from a list of song URIs if it’s not a special case card and plays said song. I stressed about it for a long time but in the end, my first working run was less than 10 lines of code.
For labels, the initial inspiration indicated that they made a React app that pulled in the data to make printables, which is super cool! I, however, am a weirdo who despite being a programmer is still often faster knocking stuff out in Photoshop/Illustrator as opposed to writing a whole app. I also wanted to use artwork besides album covers for many of the cards so that my 2 year-old can differentiate between tracks from a Mother Goose Club or El Reino Infantil album and pick what she wants – this has already proven successful 🙂
I did not hand-make a fancy box, though I might end up 3D printing something eventually, but I did discover that some of the drawer organizers I use were a great size and are good enough for now. Here’s what I ended up with for Christmas morning:
I enjoy posting about the process of building or learning things, and I’ve had a lot of people asking me about this, so I think it makes sense to blog about the process and the result. So now that you know why I decided to build a jukebox and how I arrived at the choices I made, let’s get into the step-by-step.
Magnetic stripe card reader that emulates keyboard input (mine, the first one I had so you can avoid that one because of the issues)
Spotify Premium account (protip if you have kids: use a family account and set up individual accounts for devices so you don’t run into playback limitations and you keep your recommendations somewhat more sane, I name them things like Alexa so if you ever see a reference to an Alexa Sandí associated with me please know that is not my actual child and somebody has sold or stolen my data)
A computer that can flash SD cards, run the card writer driver and software (I’m on a 12″ MacBook), and if you want to use my templates, access Adobe Illustrator
USB keyboard and HDMI monitor for initial setup (I used my Magic Keyboard with a cable and a TV)
Whatever you need to print 2×3″ labels (I had them printed onto adhesive sheets at Office Depot and cut them to size myself)
Set up Pi MusicBox. I found their documentation to be perfectly adequate, just note that when setting up Spotify you have to authorize and generate tokens that are copied into the config file.
Boot up the Raspberry Pi with the card reader plugged in and log in. Test Spotify playback by running mpc add spotify:track:7GhIk7Il098yCjg4BQjzvb && mpc play
Optional but recommended: fork my GitHub repo so you have your own copy and can keep your song list edits there. After forking, be sure to edit jukebox.sh to point to the songs.txt in your own repo.
Run curl https://raw.githubusercontent.com/helen/swipe-jukebox/master/jukebox.sh > jukebox.sh (substitute in your own username if you’ve forked the repo above).
Set root to auto-login on boot and /root/jukebox.sh to run after login so the setup can live headlessly going forward. These instructions work well, noting that the user for MusicBox is root, not pi.
Run bash jukebox.sh; this will download the song list referenced in the script as songs.txt. Enter a number like 1 at the prompt that says Swipe: to ensure the script is working as expected. If you want to quit the script, hit ctrl-c.
Edit songs.txt to your liking. I have found the easiest way to do this is to create a Spotify playlist and then select-all, right click, go to the Share menu item, select Copy Spotify URIs, and paste the result into the file. I also decided to paste the results into a Google Sheet along with the titles and artists extracted using a playlist converter tool so I have them conveniently numbered and saved separately.
Encode the cards. I found the easiest way to do this was to write them from a file, which just loads up each record sequentially and writes it to the next card you swipe. There’s both a sample file that goes up to 250 in the repo, as well as the Bash script I used to generate that file in case you want to go higher or if you get interrupted and need to make a subset. I wrote the number for each card on the back and also tested every card in the reader after writing, which at this point should trigger the appropriate playback.
Create the labels for the cards. I recommend you make them 2″ x 3″. There is an Illustrator template in the repo for those of you who are graphically-inclined. The intended artwork area is 1.5 inches square.
Print the labels for the cards and stick them on – I tested each individual one again before putting the label on because I am extremely particular, but if you make a mistake it’s fine, you can change the order of the URIs in the songs.txt file (and your playlist, if using one).
Shut down the Raspberry Pi – I find it easiest to do this by navigating to the web interface (typically at http://musicbox.local).
Box everything up and plug it in again to test the whole experience. When it’s headless, you’ll want to wait a minute or two for the green light to stop blinking so much for everything to be ready to go.
If you build one, please let me know! I’d also love to hear any tips or tricks or issues you come across if you try following along with this – I’m a software developer, as far as I’ve ever experienced there are always going to be bugs 🙂
Back with an update to my unapologetically-feminine tech-oriented “what’s in my bag” post. The laptop itself hasn’t changed, but the bag definitely has! All together, this weighs about 12 pounds. Previously, from May 2016.
Senreve Maestra bag in blush: Kicking it off with my most major upgrade from my last post is this gorgeous leather convertible satchel. What makes it convertible? Well, the straps can be pulled through the hardware loops to go from a shoulder/crossbody bag to a backpack. It’s pretty pricey (even pre-loved, which is how I got mine), I’m not gonna lie, but if you’re like me and you like your things to be both extremely functional and look a certain way, it’s one of the very few options we have. The materials are sturdy but luxe. I don’t really know what else compares to this bag out there – aesthetically it kinda makes me think of the Céline mini belt bag, although much more functional and not $2,500.
Rose gold MacBook 12″ with marble decal and color-matched rose gold keyboard cover: Some days I can feel this little 2.5 year old machine start to drag but the portability still has me hooked. I recently put on a marble decal to tone down the amount of rose gold/blush in my kit and also because I just like the way it looks. Meanwhile, the keyboard caps are starting to wear out and also the keyboard just kinda sucks anyway so I put a cover on it. It looks okay. I have to talk myself out of going to check out the new MacBook Air.
Laptop sleeve: This was a random Amazon find and I have yet to see a laptop sleeve I like better. I actually really like the feature to fold the flap and use it to prop up your laptop for ventilation and a better typing angle.
iPad Pro 10.5″: This is such a nice device. I don’t want to know if the new 11″ is better, I’m not upgrading 🙂 I can actually get away with doing a lot of my work on the iPad, like Slack-ing, writing docs, and doing code review. It’s also wonderful for sketching out thoughts and way easier to port around the house or take with me on day trips just in case something comes up.
Apple Pencil with magnetic sleeve and cap holder: I love this device and the accessories are super helpful IMO – the cap holder keeps that tiny little cap from getting lost, and the magnetic sleeve holds it in place on the edge of the case/iPad and further prevents the thing from rolling everywhere. I also find it more comfortable to write with.
Planner: This is the closest I’ve found to a layout that works for the way I work through things, short of making my own which I don’t want to do. I repurpose some of the sections as I need, although maybe it wouldn’t hurt for me to do some gratitude practice.
USB-A+C wall adapter: Why is it so hard to find a good high-speed USB-C and USB-A wall adapter without extra cords? I have no idea if this one is really made well or anything but my MacBook reports an very fast charge when using it and it’s nice and compact.
Presentation remote: Simple but it requires a USB dongle so I should probably upgrade this to Bluetooth at some point. I don’t really walk around when I present so it’s not critical for me. I’m pretty sure Nacin had it in his possession for two years and returned it to me by sneaking it onto my home desk.
Satechi USB-C hub: It’s rose gold! But also it works fine. I don’t use it very often. At my desk I have a USB-C monitor with USB ports on the back, and when I’m out and about I only really use this for presenting over HDMI.
USB-C cable: I am pretty sure this is the one that came with the battery pack. Don’t think it carries data.
Kindle Paperwhite with case: I love books and I love this case because it folds up so it can stand on its own, perfect for my favorite time to read: while eating alone. When you have small children, eating leisurely by yourself is a huge treat.
Chocolate: I always need chocolate when I’m traveling, which is what I’m usually doing when I actually carry this bag. Right now I am really enjoying these dark chocolate + hazelnut bars I picked up at the grocery store, but Ritter is typically my go-to. Or if I’m in the mood for extra sugar, 100 Grand bars.
Bag organizer: The last one I had was great and not all that dissimilar, but this one is definitely an upgrade. Most of the small items besides my wallets go in here (see picture at end of post), and it has a bottle holder. It also happens to match the inside of my bag very closely 🙂
Pouch: I change this up sometimes, pictured is something I got from a family member so if you’re looking at it wondering “is it really…?”, no it is probably not (if you know, you know). Anyway, this is bags-in-bags-in-bags level because being organized soothes me. I like this one because it’s just the right size for more pens, but sometimes there are also pouches holding makeup or other random objects I need for that particular outing.
Card cases: The black one is a slim one that I keep my main cards and a few bills in, and the orange one holds other cards that I don’t need to carry around with me for most daily activities.
USB to lightning/micro-USB mini cable: I picked this up randomly at a Container Store (my happy place). I have yet to actually try it but it seems handy!
AirPods with case: I know it’s been said a million times now but seriously, AirPods are a magical product. I keep mine in a case because a) my spouse also has a pair and b) it adds enough grip that it stops falling out of pockets inside my bags. This case happens to glow in the dark but I don’t think I’ve ever actually needed that part. Electrical tape also makes for a cool-looking DIY grip.
Regular EarPods with 3.5mm plug: For my computer, for calls or needing to listen to something in a noisy environment.
Screen cleaning cloth: I absolutely cannot stand having a dirty screen.
No-slip grip hair ties: Still the only hair ties that actually stay in my hair.
Bandaids: I haven’t had any shoe break in issues in a while (possibly because I spend more on them now…) but I’m a mom and I can be clumsy so they stay in my bag.
Lactaid: I am even less tolerant of lactose now so there are at least two stuck inside every single bag and wallet I own. I tried a generic lactase pill for a while and it didn’t work at all, so brand loyalty it is.
Compact mirror: Honestly I probably use my phone camera more for quick check ups myself but you never know when a mirror might come in handy.
Mints: This is usually whatever mints I picked up at an airport or grocery store recently. Right now it’s a tin of mints from the Café Britt shop.
Fresh Sugar lip balms: I carry minis of both the regular (clear) and a sheer rose tint which is very flattering. This links to a set of 6 different mini balms, which is my preferred size for my bag, but the full size ones are available alone.
Pens and pencil: Two years later, I am still obsessed with MUJI gel pens. I usually have a black one in 0.5m, a colored one in 0.38mm, and another black one in 0.38mm tucked into the spiral of my planner. The pencil is a typical 0.7mm BIC mechanical pencil, based on its translucent glitter body I think it’s from a bulk box I bought more than 10 years ago. I haven’t yet taken to a fancy pencil, but maybe someday.
9oz Swell water bottle: I like this size for my bag, although I also have a larger size (read: taller) 10up-branded one at my desk. This particular one is the Teal Wood color. I don’t remember how I acquired it, probably one of those fancy sample boxes.
A while back, GitHub added a setting for contributors to allow maintainers of a repo to push changes to a pull request branch of their fork. I've been doing a lot more work in GitHub recently and figured I'd document my Git process for handling pull requests where you just want to close up a couple small things in a given time frame and/or the originator isn't very responsive. IMO this makes it much easier to retain the commit history giving credit to the other person but still move existing PRs forward.
The essence of my process is to add their fork as a remote, switch to that branch, do stuff and commit, and then push to it. It's not really a whole lot, but I've found that very specific snippets come in very handy, even if they're short and straight-forward. I also don't like the instructions GitHub gives for making changes to a fork's branch. So, that gives us (using a real recent example):
If you use hub (I don't), I believe you can skip the first command as fetch will add the remote for you if it's not recognized. There's also the popular Git Extras, which has a pr command, but from what I've tested it doesn't use the actual remote branch the PR originates from even if you specify the remote, but rather the pulls/### branch GitHub makes for you. If you use (or decide to write) a Git helper that does the remote adding/fetching/checkout for you (e.g. git pr KZeni/patch-1 or even making it so that git pr ### could detect the remote fork and branch for that PR), let me know!