#!/usr/bin/env bash | |
# | |
# This is sp, the command-line Spotify controller. It talks to a running | |
# instance of the Spotify Linux client over dbus, providing an interface not | |
# unlike mpc. | |
# | |
# Put differently, it allows you to control Spotify without leaving the comfort | |
# of your command line, and without a custom client or Premium subscription. | |
# | |
# As an added bonus, it also works with ssh, at and cron. | |
# | |
# Example: | |
# $ sp weather girls raining men | |
# $ sp current | |
# Album 100 Hits Of The '80s | |
# Artist The Weather Girls | |
# Title It's Raining Men | |
# $ sp pause | |
# | |
# Alarm clock example: | |
# $ at 7:45 <<< 'sp bangarang' | |
# | |
# Remote example: | |
# $ ssh vader@prod02.nomoon.ta 'sp imperial march' | |
# | |
# | |
# Copyright (C) 2013 Wander Nauta | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining a copy | |
# of this software, to deal in the Software without restriction, including | |
# without limitation the rights to use, copy, modify, merge, publish, | |
# distribute, sublicense, and/or sell copies of the Software, and to permit | |
# persons to whom the Software is furnished to do so, subject to the following | |
# conditions: | |
# | |
# The above copyright notice and this permission notice shall be included in | |
# all copies or substantial portions of the Software. | |
# | |
# The software is provided "as is", without warranty of any kind, express or | |
# implied, including but not limited to the warranties of merchantability, | |
# fitness for a particular purpose and noninfringement. In no event shall the | |
# authors or copyright holders be liable for any claim, damages or other | |
# liability, whether in an action of contract, tort or otherwise, arising from, | |
# out of or in connection with the software or the use or other dealings in the | |
# software. | |
# | |
# CONSTANTS | |
SP_VERSION="0.1" | |
SP_DEST="org.mpris.MediaPlayer2.spotify" | |
SP_PATH="/org/mpris/MediaPlayer2" | |
SP_MEMB="org.mpris.MediaPlayer2.Player" | |
# SHELL OPTIONS | |
shopt -s expand_aliases | |
# UTILITY FUNCTIONS | |
function require { | |
hash $1 2>/dev/null || { | |
echo >&2 "Error: '$1' is required, but was not found."; exit 1; | |
} | |
} | |
# COMMON REQUIRED BINARIES | |
# We need dbus-send to talk to Spotify. | |
require dbus-send | |
# Assert standard Unix utilities are available. | |
require grep | |
require sed | |
require cut | |
require tr | |
# 'SPECIAL' (NON-DBUS-ALIAS) COMMANDS | |
function sp-dbus { | |
# Sends the given method to Spotify over dbus. | |
dbus-send --print-reply --dest=$SP_DEST $SP_PATH $SP_MEMB.$1 ${*:2} > /dev/null | |
} | |
function sp-open { | |
# Opens the given spotify: URI in Spotify. | |
sp-dbus OpenUri string:$1 | |
} | |
function sp-metadata { | |
# Prints the currently playing track in a parseable format. | |
dbus-send \ | |
--print-reply `# We need the reply.` \ | |
--dest=$SP_DEST \ | |
$SP_PATH \ | |
org.freedesktop.DBus.Properties.Get \ | |
string:"$SP_MEMB" string:'Metadata' \ | |
| grep -Ev "^method" `# Ignore the first line.` \ | |
| grep -Eo '("(.*)")|(\b[0-9][a-zA-Z0-9.]*\b)' `# Filter interesting fiels.`\ | |
| sed -E '2~2 a|' `# Mark odd fields.` \ | |
| tr -d '\n' `# Remove all newlines.` \ | |
| sed -E 's/\|/\n/g' `# Restore newlines.` \ | |
| sed -E 's/(xesam:)|(mpris:)//' `# Remove ns prefixes.` \ | |
| sed -E 's/^"//' `# Strip leading...` \ | |
| sed -E 's/"$//' `# ...and trailing quotes.` \ | |
| sed -E 's/"+/|/' `# Regard "" as seperator.` \ | |
| sed -E 's/ +/ /g' `# Merge consecutive spaces.` | |
} | |
function sp-current { | |
# Prints the currently playing track in a friendly format. | |
require column | |
sp-metadata \ | |
| grep --color=never -E "(title)|(album)|(artist)" \ | |
| sed 's/^\(.\)/\U\1/' \ | |
| column -t -s'|' | |
} | |
function sp-eval { | |
# Prints the currently playing track as shell variables, ready to be eval'ed | |
require sort | |
sp-metadata \ | |
| grep --color=never -E "(title)|(album)|(artist)|(trackid)|(trackNumber)" \ | |
| sort -r \ | |
| sed 's/^\([^|]*\)\|/\U\1/' \ | |
| sed -E 's/\|/="/' \ | |
| sed -E 's/$/"/' \ | |
| sed -E 's/^/SPOTIFY_/' | |
} | |
function sp-art { | |
# Prints the artUrl. | |
sp-metadata | grep "artUrl" | cut -d'|' -f2 | |
} | |
function sp-display { | |
# Calls display on the artUrl. | |
require display | |
display $(sp-art) | |
} | |
function sp-feh { | |
# Calls feh on the artURl. | |
require feh | |
feh $(sp-art) | |
} | |
function sp-url { | |
# Prints the HTTP url. | |
TRACK=$(sp-metadata | grep "url" | cut -d'|' -f2 | cut -d':' -f3) | |
echo "http://open.spotify.com/track/$TRACK" | |
} | |
function sp-clip { | |
# Copies the HTTP url. | |
require xclip | |
sp-url | xclip | |
} | |
function sp-http { | |
# xdg-opens the HTTP url. | |
require xdg-open | |
xdg-open $(sp-url) | |
} | |
function sp-help { | |
# Prints usage information. | |
echo "Usage: sp [command]" | |
echo "Control a running Spotify instance from the command line." | |
echo "" | |
echo " sp play - Play/pause Spotify" | |
echo " sp pause - Pause Spotify" | |
echo " sp next - Go to next track" | |
echo " sp prev - Go to previous track" | |
echo "" | |
echo " sp current - Format the currently playing track" | |
echo " sp metadata - Dump the current track's metadata" | |
echo " sp eval - Return the metadata as a shell script" | |
echo "" | |
echo " sp art - Print the URL to the current track's album artwork" | |
echo " sp display - Display the current album artwork with \`display\`" | |
echo " sp feh - Display the current album artwork with \`feh\`" | |
echo "" | |
echo " sp url - Print the HTTP URL for the currently playing track" | |
echo " sp clip - Copy the HTTP URL to the X clipboard" | |
echo " sp http - Open the HTTP URL in a web browser" | |
echo "" | |
echo " sp open <uri> - Open a spotify: uri" | |
echo " sp search <q> - Start playing the best search result for the given query" | |
echo "" | |
echo " sp version - Show version information" | |
echo " sp help - Show this information" | |
echo "" | |
echo "Any other argument will start a search (i.e. 'sp foo' will search for foo)." | |
} | |
function sp-search { | |
# Searches for tracks, plays the first result. | |
require curl | |
Q="$@" | |
SPTFY_URI=$( \ | |
curl -s -G --data-urlencode "q=$Q" https://api.spotify.com/v1/search\?type=track \ | |
| grep -E -o "spotify:track:[a-zA-Z0-9]+" -m 1 \ | |
) | |
sp-open $SPTFY_URI | |
} | |
function sp-version { | |
# Prints version information. | |
echo "sp $SP_VERSION" | |
echo "Copyright (C) 2013 Wander Nauta" | |
echo "License MIT" | |
} | |
# 'SIMPLE' (DBUS-ALIAS) COMMANDS | |
alias sp-play=" sp-dbus PlayPause" | |
alias sp-pause=" sp-dbus Pause" | |
alias sp-next=" sp-dbus Next" | |
alias sp-prev=" sp-dbus Previous" | |
# DISPATCHER | |
# First, we connect to the dbus session spotify is on. This isn't really needed | |
# when running locally, but is crucial when we don't have an X display handy | |
# (for instance, when running sp over ssh.) | |
SPOTIFY_PID="$(pidof -s spotify || pidof -s .spotify-wrapped)" | |
if [[ -z "$SPOTIFY_PID" ]]; then | |
echo "Error: Spotify is not running." | |
exit 1 | |
fi | |
QUERY_ENVIRON="$(cat /proc/${SPOTIFY_PID}/environ | tr '\0' '\n' | grep "DBUS_SESSION_BUS_ADDRESS" | cut -d "=" -f 2-)" | |
if [[ "${QUERY_ENVIRON}" != "" ]]; then | |
export DBUS_SESSION_BUS_ADDRESS="${QUERY_ENVIRON}" | |
fi | |
# Then we dispatch the command. | |
subcommand="$1" | |
if [[ -z "$subcommand" ]]; then | |
# No arguments given, print help. | |
sp-help | |
else | |
# Arguments given, check if it's a command. | |
if $(type sp-$subcommand > /dev/null 2> /dev/null); then | |
# It is. Run it. | |
shift | |
eval "sp-$subcommand $@" | |
else | |
# It's not. Try a search. | |
eval "sp-search $@" | |
fi | |
fi |
This comment has been minimized.
This comment has been minimized.
finally got my xfce4 pause/next/play key bindings to work with spotify. |
This comment has been minimized.
This comment has been minimized.
Works great! Would there by an easy way to integrate login and logout into this script? |
This comment has been minimized.
This comment has been minimized.
I've created an AUR package for Arch Linux users: https://aur.archlinux.org/packages/sp/ |
This comment has been minimized.
This comment has been minimized.
Nice script thank you for that ! |
This comment has been minimized.
This comment has been minimized.
How do I install this? |
This comment has been minimized.
This comment has been minimized.
Thank!! |
This comment has been minimized.
This comment has been minimized.
Fantastic script |
This comment has been minimized.
This comment has been minimized.
@wandernauta Thanks so much for this script! I've been using it to debug DBus support in the 1.x Spotify Linux client, it's been a real lifesaver. ;) |
This comment has been minimized.
This comment has been minimized.
This is great, thank you so much! |
This comment has been minimized.
This comment has been minimized.
Great script! Created another script that pauses spotify and then locks my (enlightenment) screen (which is also done over DBus). :D |
This comment has been minimized.
This comment has been minimized.
thanks a bunch - this works great! |
This comment has been minimized.
This comment has been minimized.
still works! thanks! |
This comment has been minimized.
This comment has been minimized.
Excellent script to control Spotify from command line, to make shorcuts con media keys, and even automatize or integrate with Conky. Thank you so much :D |
This comment has been minimized.
This comment has been minimized.
Thanks for the script! I found the search functionality broken due to Spotify deprecating their API, so I forked and fixed it: https://gist.github.com/duncan-bayne/3f7ef98a15b02b693bf47a03fda79b3a |
This comment has been minimized.
This comment has been minimized.
Excellent stuff! Works like a boss with xbindkeys to replace the media keys on my work keyboard. Thanks so much. |
This comment has been minimized.
This comment has been minimized.
Thanks! :) |
This comment has been minimized.
This comment has been minimized.
Hi, any idea how to find out if spotify is currently playing or in pause state? Metatada does always return the currently active song. |
This comment has been minimized.
This comment has been minimized.
search does not work for me, it takes a moment and does/says nothing. open does work, though. |
This comment has been minimized.
This comment has been minimized.
In order for the search to work, you'll have to update line 215 to the new API url @wandernauta.
Thanks for this awesome utility! |
This comment has been minimized.
This comment has been minimized.
Thank you, @leothelocust! That works like a charm. I've updated the gist. |
This comment has been minimized.
This comment has been minimized.
Brilliant! |
This comment has been minimized.
This comment has been minimized.
I'm usually on linux, but at my current job I have to use windows (.NET) and I was wondering if anyone knew of a way that I could do this same thing on windows? |
This comment has been minimized.
This comment has been minimized.
Still works! |
This comment has been minimized.
This comment has been minimized.
is there a way to save the current song to the library? |
This comment has been minimized.
This comment has been minimized.
Great tool, but I ran into problems with "sp eval" when the title(or any other information) contained double quotes.
|
This comment has been minimized.
This comment has been minimized.
You can extend the search via these functions.
|
This comment has been minimized.
This comment has been minimized.
Hello! What about volume control? Does spotify ignore it? |
This comment has been minimized.
This comment has been minimized.
@ivanmilov I am sure the d-bus mpris support is not complete in the spotify client. Most of the methods and variables do not work. I think volume control must be one of them They also made the authentication mandatory for the api now so all the search functions do not work. It needs a token with authorisation code or client credentials :( Will definitely try and fix this as I figure them out. |
This comment has been minimized.
This comment has been minimized.
@sbmkvp I had a go at the authentication and came up with a working fix. Might not be the greatest one but I just wanted it to get working again. I used the information from here which also links to the site to register your application for your own Client ID and Client Secret. Edit: Actually if you have a look at my fork of sp, I added your search functions and you just have to fill in the variables at the top with your own ID and Secret and it should work fine.
|
This comment has been minimized.
This comment has been minimized.
Thank you @wandernauta for the cli and @vorbeiei for the search alterations! I've further revisioned @vorbeiei's verison on my fork of sp to make curl silent when performing searches. function sp-search {
# Searches for tracks, plays the first result.
require curl
#send request for token with ID and SecretID encoded to base64->grep take only token from reply->trim reply down to token-> modified request to include token in header
Q="$@"
ST=$(curl -H "Authorization: Basic $SP_B64ID" -d grant_type=client_credentials https://accounts.spotify.com/api/token --silent\
| grep -E -o "access_token\":\"[a-zA-Z0-9_-]+\"" -m 1 )
ST2=${ST:15:86}}
SPTFY_URI=$( \
curl -H "Authorization: Bearer $ST2" -s -G --data-urlencode "q=$Q" https://api.spotify.com/v1/search\?type=track \
| grep -E -o "spotify:track:[a-zA-Z0-9]+" -m 1 \
)
sp-open $SPTFY_URI
} |
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
@rarrais' version isn't working for me still - it's not returning any sort of error, and after a brief pause, it seems to do nothing. |
This comment has been minimized.
This comment has been minimized.
@boardfish You have to create an app here: https://beta.developer.spotify.com/dashboard/applications and insert your ID and Secret in the file where indicated. (I updated my fork to include the link because it's really not obvious) |
This comment has been minimized.
This comment has been minimized.
The image 'sp display' displays is quite low-res and comes with a Spotify logo down in the corner. This can quite easily be fixed by changing the sp-art function to
The images at "i.scdn.co" have a resolution of 300x300 (as opposed to the 180x180 that "open.spotify.com" gives) and doesn't have the logo. :) |
This comment has been minimized.
This comment has been minimized.
This script doesn't work for me, it gives me an error: |
This comment has been minimized.
This comment has been minimized.
Hey @wandernauta I have fixed this in my fork by adding an additional line to the eval function that changes the output of eval to use single quotes instead of double quotes. You can merge to fix this for other people. Thank you for creating the original! |
This comment has been minimized.
This comment has been minimized.
@wandernauta thanks for this script |
This comment has been minimized.
This comment has been minimized.
Sorry for the bother, but how would I go about getting the Album, Artist, and Title separately? |
This comment has been minimized.
This comment has been minimized.
@John-AZ1 If you are only after certain fields, use sp eval. it creates shell variables of the metadata, so you can easily access it. |
This comment has been minimized.
This comment has been minimized.
I found that using single quotes instead of double quotes yields to problems with songs using a ' in the title, and I think that's more common than songs with a $ |
This comment has been minimized.
This comment has been minimized.
Hi, open has stopped working for me. Not sure how long ago, as haven't used this for quite a while, but looking to get it working again. Basically, when I run The metadata is showing the right info (see below), but play, next, pause etc do nothing until I manually click the play button in the UI (next to the track, the main play button isn't enabled). Then the sp play/pause etc start working again. I've just updated the spotify client, so maybe that has something to do with it? Running
|
This comment has been minimized.
This comment has been minimized.
@rarrais Did the same |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Thanks for this great script! Any chance we could get the current song playing progress (either in percent, seconds from beginning or so)? |
This comment has been minimized.
This comment has been minimized.
This worked great with Ubuntu 14, but doesn't work with Ubuntu 18. Anyone else get sp to work with Ubuntu 18.04? Thanks. |
This comment has been minimized.
This comment has been minimized.
how use it with https://bitbucket.org/geertvandeweyer/spotify_recorder ? |
This comment has been minimized.
This comment has been minimized.
As @o1354921 mentioned before, you can get in trouble when using sp-eval and some title contains double quotes. |
This comment has been minimized.
This comment has been minimized.
Playerctl works good as well and has extra functionality |
This comment has been minimized.
This comment has been minimized.
I got this on nixos; seems the nixpkg spotify does not register itself with dbus. |
This comment has been minimized.
This comment has been minimized.
Is there any chance to have a "like" option to star a song? |
This comment has been minimized.
This comment has been minimized.
Prevent Advertisement from playing https://gist.github.com/neerajvashistha/a22045093b0d431e903e64e3a98cba5e has anybody got any success on stream record it? @EsmailELBoBDev2 ? |
This comment has been minimized.
This comment has been minimized.
If anyone is in need of a Debian/Ubuntu Package, I got bored and built a |
This comment has been minimized.
This comment has been minimized.
@neerajvashistha im sorry dude i really not have idea what i mean there xD |
This comment has been minimized.
This comment has been minimized.
Would also love that. |
This comment has been minimized.
This comment has been minimized.
@EsmailELBoBDev2 @neerajvashistha Maybe the question would have fit better in the issues of the spotify stream recorder. But here are some things you should do in order to use it:
You can then use In my case, my About “staring” songs: @cpazaras @AfroMonkey I used d-feet to inspect the dbus methods of the spotify process. There seem to be no methods for leaving a star/like. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Spotify have changed the way their query API works and so now it requires an authentication token to lookup songs. |
This comment has been minimized.
This comment has been minimized.
Here's a working solution I made for searching songs |
This comment has been minimized.
This comment has been minimized.
@dedeibel There is a much easier solution, instead of getting the dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:"org.mpris.MediaPlayer2.Player" string:'PlaybackStatus' | grep -Ev "^method" | grep -Eo '("(.*)")|(\b[0-9][a-zA-Z0-9.]*\b)' | cut -f2 -d'"' |
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This works perfectly. Super handy. Thanks!