Show cmus and ncspot status in Sway
last updated 2023-01-15 14:57:45 by Simon Vandevelde
To play music on my pc, I use two different applications:
Both are minimalistic applications that work right out of your terminal. It would be cool, I thought, to show their status on my Sway status bar. So, I spent some time figuring out how to best do so. If you read this post, you can do so too!
It's actually fairly simple: I have a status.sh
script which is called by swaybar to update the text every second (see Pomodoro timer in Sway).
You can do this by adding the following line to the bar
section of your sway config:
status_command while ~/.config/sway/status.sh; do sleep 1; doneAll we need to do is add some code to this script to also display cmus and ncspot. If you don't want to read, you can also view the script directly.
cmus
Collecting the current information from cmus is luckily very easy, thanks to cmus's built-in controller.
$ cmus-remote -C # Returns 1 if cmus is running $ cmus-remote -Q status playing file /home/saltfactory/Music/Mort Garson/Music from Patch Cord Productions/10 Music For Advertising #4.mp3 duration 66 position 4 tag artist Mort Garson tag album Music From Patch Cord Productions tag title Music For Advertising #4 tag date 2020 tag originaldate 2020 tag genre Electronic tag discnumber 1 tag tracknumber 10 tag albumartist Mort Garson tag artistsort Garson, Mort tag albumartistsort Garson, Mort tag albumsort Music from Patch Cord Productions tag label Sacred Bones Records tag publisher Sacred Bones Records tag musicbrainz_trackid 18e0097a-ca9f-4128-b205-ae6d7889a328 tag media CD set aaa_mode all set continue true set play_library true set play_sorted true set replaygain disabled set replaygain_limit true set replaygain_preamp 0.000000 set repeat false set repeat_current false set shuffle tracks set softvol false set vol_left 100 set vol_right 100As you can see, this command allows us to see all revelant information (and more!).
All we then need to do is collect the information we want to display whenever cmus is running.
In my case, I want to know the artist and title of the current number, as well as if cmus is playing or paused.
In our status.sh
script, this is done as follows.
if cmus-remote -C ; then # If cmus is active, get the information and display it. # cmus information current_artist=$(cmus-remote -Q | grep "\sartist\s" | cut -d " " -f 3-) current_title=$(cmus-remote -Q | grep "\stitle\s" | cut -d " " -f 3-) cmus_playing=$(cmus-remote -Q | grep "status\s" | cut -d " " -f 2-) fi
This makes it very easy to add this information to our status output, but only whenever cmus is actually open. For example:
if [ $ cmus_playing = 'playing' ]; then # Show a play or pause symbol. playing='▶'; else playing='⏸'; fi if [ "$ current_artist" = "" ]; then # If cmus isn't open, only show date. echo $ date_formatted; else echo $ playing $ current_artist - $ current_title ♫ '|' $ date_formatted; fi(take care to remove the whitespace after each dollar!)
ncspot
ncspot is a bit more tricky to set up, as it does not have a cmus-remote
-equivalent.
It does, however, have a UNIX socket which you can connect to with, e.g., netcat
.
The downside of this approach is that the connection through netcat
stays open -- it keeps listening for changes, and outputs them to the stdout.
This is annoying, as we are only interested in the currently playing information, and thus want to close the connection right after we have received our first bit of data.
As it turns out, there are multiple netcat
implementations, each with their own features.
Luckily for use, the OpenBSD variant of netcat supports a -W
flag, which closes the connection after x amount of bytes have been transfered.
We can use this as follows:
$ nc -W 1 -U ~/.cache/ncspot/ncspot.sock {"mode":{"Playing":{"secs_since_epoch":1673790531,"nanos_since_epoch":558149619}},"playable":{"type":"Track","id":"2fqnivbjstZvlCcXjpu3Tw","uri":"spotify:track:2fqnivbjstZvlCcXjpu3Tw","title":"Tu pu du cu - Bonus Track","track_number":16,"disc_number":1,"duration":172872,"artists":["Odezenne"],"artist_ids":["1FiWBzw15KbR9amOb1Xnxp"],"album":"OVNI (Orchestre virtuose national incompétent) [Edition bonus Louis XIV]","album_id":"5Hl4kW2racfsaeBKtod3pz","album_artists":["Odezenne"],"cover_url":"https://i.scdn.co/image/ab67616d0000b2733a0b4a45a983e0166b998bcc","url":"https://open.spotify.com/track/2fqnivbjstZvlCcXjpu3Tw","added_at":"2021-12-07T19:03:50Z","list_index":0}}This outputs all known information on the currently playing track in a json format. Using the json parser
jq
, we can structure this a bit more neatly.
$ nc -W 1 -U ~/.cache/ncspot/ncspot.sock | jq { "mode": { "Playing": { "secs_since_epoch": 1673790531, "nanos_since_epoch": 558149619 } }, "playable": { "type": "Track", "id": "2fqnivbjstZvlCcXjpu3Tw", "uri": "spotify:track:2fqnivbjstZvlCcXjpu3Tw", "title": "Tu pu du cu - Bonus Track", "track_number": 16, "disc_number": 1, "duration": 172872, "artists": [ "Odezenne" ], "artist_ids": [ "1FiWBzw15KbR9amOb1Xnxp" ], "album": "OVNI (Orchestre virtuose national incompétent) [Edition bonus Louis XIV]", "album_id": "5Hl4kW2racfsaeBKtod3pz", "album_artists": [ "Odezenne" ], "cover_url": "https://i.scdn.co/image/ab67616d0000b2733a0b4a45a983e0166b998bcc", "url": "https://open.spotify.com/track/2fqnivbjstZvlCcXjpu3Tw", "added_at": "2021-12-07T19:03:50Z", "list_index": 0 } }
Alright, so just like with cmus
, it's now pretty easy to add this to our status.sh
.
if nc -W 1 -U ~/.cache/ncspot/ncspot.sock > /dev/null; then # ncspot outputs json through the socket -- use jq to grab the first # artist and the title of the current song. # We use `eval` to strip the quotation marks around the output. ncspot_info=$(nc -W 1 -U ~/.cache/ncspot/ncspot.sock); eval current_artist=$(echo | jq '.playable.artists[0]') eval current_title=$(echo | jq '.playable.title') eval ncspot_playing=$(echo | jq '.mode.Playing.secs_since_epoch'); fiWe can combine this together with the previous
cmus
code as follows:
if [ != null ] || [ = 'playing' ]; then playing='▶'; else playing='⏸'; fiAnd that's it! Now everything should work.
You can view the full status.sh
code here.