Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Last active November 21, 2016 07:02
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/63f2f0edbb4f429e003438a41caa0142 to your computer and use it in GitHub Desktop.
Save JoshCheek/63f2f0edbb4f429e003438a41caa0142 to your computer and use it in GitHub Desktop.
Command Line spotify remote-control (a working example for https://github.com/spotify/web-api/issues/15)
require 'io/console'
require 'open3'
require 'pp'
begin
require 'coderay'
rescue LoadError # might not already have syntax highlighting
end
class App
def initialize(stdout, stderr)
@stdout, @stderr = stdout, stderr
end
def tell(message)
full_message = %'tell application "Spotify"\n #{message}\nend tell'
stdout, stderr, status = Open3.capture3 'osascript', '-e', full_message
@stderr.print stderr unless stderr.empty?
raise unless status.success?
stdout
end
end
class Spotify
attr_reader :app
def initialize(app)
@app = app
end
def position(seconds)
app.tell "set player position to #{seconds}"
end
def position_current
app.tell("get player position").to_i
end
def position_relative(seconds)
position position_current+seconds
end
def track_relative(position)
if 0 < position
app.tell 'next track'
elsif position < 0
app.tell 'previous track'
end
end
def playpause
app.tell 'playpause'
end
def volume_relative(amount)
app.tell "set sound volume to #{volume+amount}"
end
def volume
app.tell('get sound volume').to_i
end
def info
track_attrs = ['artist', 'album', 'disc number', 'duration', 'played count', 'track number', 'popularity', 'id', 'name', 'artwork url', 'artwork', 'album artist', 'spotify url']
player_attrs = ['sound volume', 'player state', 'player position', 'repeating enabled', 'repeating', 'shuffling enabled', 'shuffling']
results = app.tell [
*track_attrs.map { |attr| "(get #{attr} of current track)" },
*player_attrs.map { |attr| "(get #{attr})" },
].join(' & "\n" & ')
lines = results.lines
{ current_track: {
artist: lines.shift.chomp,
album: lines.shift.chomp,
disc_number: lines.shift.to_i,
duration: lines.shift.to_i,
played_count: lines.shift.to_i,
track_number: lines.shift.to_i,
popularity: lines.shift.to_i,
id: lines.shift.chomp,
name: lines.shift.chomp,
artwork_url: lines.shift.chomp,
artwork: lines.shift.chomp,
album_artist: lines.shift.chomp,
spotify_url: lines.shift.chomp,
},
sound_volume: lines.shift.to_i,
player_state: lines.shift.chomp.intern,
player_position: lines.shift.to_f,
repeat_enabled: to_bool(lines.shift),
repeating: to_bool(lines.shift),
shuffling_enabled: to_bool(lines.shift),
shuffling: to_bool(lines.shift),
}
end
def to_bool(s)
s = s.chomp
s == 'true' ? true : s == 'false' ? false : s
end
end
spotify = Spotify.new(App.new($stdout, $stderr))
key = nil
loop do
case key
when 'q', 3.chr then break
when 'h' then spotify.position_relative -1
when 'H' then spotify.position_relative -15
when 'l' then spotify.position_relative 1
when 'L' then spotify.position_relative 15
when 'j' then spotify.track_relative 1
when 'k' then spotify.track_relative -1
when 'p' then spotify.playpause
when '+' then spotify.volume_relative 5
when '-' then spotify.volume_relative -5
end
inspected = spotify.info.pretty_inspect
inspected = CodeRay.encode(inspected, :ruby, :terminal) if defined? CodeRay
$stdout.puts "\e[H\e[2J#{inspected}"
key = $stdin.raw { $stdin.getc }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment