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.
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
).