🔍
Showing the current Google Music song in conky

So here’s a trivial-seeming task that required a bit more digging that I anticipated. I’m increasingly using Google Music streaming over my local music collection these days, but I’d like to get the same general experience as I’d have with a local music player. This includes being able to play and pause with one of the extra buttons on my mouse and seeing what song’s playing in the conky-powered i3bar at the top of my screen.

If you’re using i3wm with the default i3status powering the output on your i3bar, I really recommend swapping it out for conky. Conky’s configuration files are much more powerful: not only do you get far more built-in variables, but you can literally place the output of arbitrary terminal commands on your i3bar. Here’s a tutorial describing how to set it up.

With my previous music setup, mpd, this was quite easy – conky actually has a whole lot of mpd stuff built in. Trying to replicate the effect with Google Music was a bit of a different story.

The first thing we’ll need to do this is MarshallOfSound’s excellent unofficial desktop player for Google Music. This is an Electron wrapper for the Google Music site, packaged with some nice extras such as native support for multimedia buttons and Last.fm scrobbling. If you use Google Music, you should really be using this already.

Now that we’ve got a native app playing Google Music, we’re one step closer to getting that conky output. GPMDP stores a bunch of info about the currently playing song in a file at this location:

.config/Google Play Music Desktop Player/json_store/playback.json

It looks something like this:

{
    "playing": true,
    "song": {
        "title": "Paper Thin Walls",
        "artist": "Modest Mouse",
        "album": "The Moon & Antarctica",
        "albumArt": "https://lh6.ggpht.com/DAyuCTyQaQk0H7K7JfzBa4Nt9Q6AuekSUAy7tKCkBAcdEl-qGMzOTnwq3Km9MbzqItQBbXrJrA=s90-c-e100"
    },
    "rating": {
        "liked": false,
        "disliked": false
    },
    "time": {
        "current": 155744,
        "total": 182000
    },
    "songLyrics": "These walls are paper thin [snip] be a fool for everyone that I don't know\n",
    "shuffle": "NO_SHUFFLE",
    "repeat": "NO_REPEAT"
}

For our conky output, we want something like this:

Modest Mouse - Paper Thin Walls

Now, it’s probably possible to accomplish this with a lot of cut, sed and awk wizardry, but the cleaner option is to actually parse the JSON in our terminal. jq is a useful little program that does just that, so let’s install it.

sudo apt-get install jq

jq takes in JSON-formatted text and can extract individual values from it with syntax like this:

jq '.song.artist'

which gets us this:

"Modest Mouse"

You can extract multiple values by comma-separating them:

$ jq '.song.artist, .song.title'
"Modest Mouse"
"Paper Thin Walls"

and remove quotes with -r (raw) flag:

$ jq -r '.song.artist, .song.title'
Modest Mouse
Paper Thin Walls

So our command thus far looks like this:

cat "$HOME/.config/Google Play Music Desktop Player/json_store/playback.json" | jq -r '.song.artist, .song.title'

and gets us this:

Modest Mouse
Paper Thin Walls

Close, but we want Artist - Title all on the same line. We can almost accomplish this with tr.

$ cat "$HOME/.config/Google Play Music Desktop Player/json_store/playback.json" | jq -r '.song.artist, .song.title' | tr '\n' '-'
Modest Mouse-Paper Thin Walls

But tr only substitutes individual characters for other individual characters, so we can only substitute the \n newline with '-', and not ' - '. Almost there, but not quite.

sed lets us perform far more powerful substitutions, but it’s line-based, so quite poor at replacing newline characters. Still, we can achieve our desired effect with a little help from StackOverflow:

sed ':a;N;$!ba;s/\n/ \- /'

The :a;N;$!ba; basically makes sed transform this:

Modest Mouse
Paper Thin Walls

into this:

Modest Mouse\nPaper Thin Walls

without losing the trailing newline that makes it display nicely in the terminal.

The s/\n/ \- / makes our desired substitution (- is escaped with a backslash because it’s part of regular expression syntax).

So at last we have our command:

$ cat "$HOME/.config/Google Play Music Desktop Player/json_store/playback.json" | jq -r '.song.artist, .song.title' | sed ':a;N;$!ba;s/\n/ \- /'
Modest Mouse - Paper Thin Walls

For the final step, we toss this behind an exec command in our conkyrc, add some nice unicode and a symbol of our choice, and voilà!

Depending on how you use conky, you could to extend this by including the album name, lyrics and even album art. Another useful extension would be displaying something else when the player is closed (this just displays null - null).