Skip to content

Instantly share code, notes, and snippets.

@pachacamac
Last active March 31, 2020 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pachacamac/d0d71c64a14dc5bae0d943a432a84f6b to your computer and use it in GitHub Desktop.
Save pachacamac/d0d71c64a14dc5bae0d943a432a84f6b to your computer and use it in GitHub Desktop.
soma
#!/usr/bin/env ruby
require 'json'
require 'open-uri'
#require 'byebug'
def load_json(url)
#JSON.parse(`wget -q -O- #{url}`, symbolize_names: true)
JSON.parse(open(url).read, symbolize_names: true)
end
class String
#extend: http://misc.flogisoft.com/bash/tip_colors_and_formatting
def black; "\e[30m#{self}\e[0m" end
def red; "\e[31m#{self}\e[0m" end
def green; "\e[32m#{self}\e[0m" end
def brown; "\e[33m#{self}\e[0m" end
def blue; "\e[34m#{self}\e[0m" end
def magenta; "\e[35m#{self}\e[0m" end
def cyan; "\e[36m#{self}\e[0m" end
def gray; "\e[37m#{self}\e[0m" end
def bg_black; "\e[40m#{self}\e[0m" end
def bg_red; "\e[41m#{self}\e[0m" end
def bg_green; "\e[42m#{self}\e[0m" end
def bg_brown; "\e[43m#{self}\e[0m" end
def bg_blue; "\e[44m#{self}\e[0m" end
def bg_magenta; "\e[45m#{self}\e[0m" end
def bg_cyan; "\e[46m#{self}\e[0m" end
def bg_gray; "\e[47m#{self}\e[0m" end
def bold; "\e[1m#{self}\e[22m" end
def italic; "\e[3m#{self}\e[23m" end
def underline; "\e[4m#{self}\e[24m" end
def blink; "\e[5m#{self}\e[25m" end
def reverse_color; "\e[7m#{self}\e[27m" end
end
channels = load_json('http://somafm.com/channels.json')[:channels]
channels += [
{
id: 'pink_noise',
title: 'pink noise',
description: 'Random noise having equal energy per octave, and so having more low-frequency components than white noise.',
stream_url: 'http://uk1.internet-radio.com:8004/;stream'
},
{
id: 'white_noise',
title: 'white noise',
description: 'Noise containing many frequencies with equal intensities.',
stream_url: 'http://uk1.internet-radio.com:8267/;stream'
},
{
id: 'brown_noise',
title: 'brown noise',
description: 'Similar to pink noise, but with different spectral content and different relationships.',
stream_url: 'http://uk1.internet-radio.com:8280/;stream'
},
{
id: 'rbb24',
title: 'rbb24',
description: 'rbb|24 ist das multimediale Nachrichtenportal für Berlin und Brandenburg',
stream_url: 'https://rbb-radioberlin-live.sslcast.addradio.de/rbb/radioberlin/live/mp3/128/stream.mp3'
},
{
id: 'psyradio-progressive',
title: 'psyradio-progressive',
description: 'psyradio * fm - progressive - http://html.psyradio.fm/',
stream_url: 'http://streamer.psyradio.org:8010/;listen.mp3'
},
{
id: 'psyradio-chillout',
title: 'psyradio-chillout',
description: 'psyradio * fm - chillout - http://html.psyradio.fm/',
stream_url: 'http://streamer.psyradio.org:8020/;listen.mp3'
},
{
id: 'psyradio-psytrance',
title: 'psyradio-psytrance',
description: 'psyradio * fm - psytrance - http://html.psyradio.fm/',
stream_url: 'http://streamer.psyradio.org:8030/;listen.mp3'
},
{
id: 'psyradio-alternative',
title: 'psyradio-alternative',
description: 'psyradio * fm - alternative - http://html.psyradio.fm/',
stream_url: 'http://streamer.psyradio.org:8040/;listen.mp3'
}
]
#puts JSON.pretty_generate(channels.map{|e| e[:stream_url] || e[:playlists].first[:url]})
# curl 'http://html.psyradio.fm/songData.php?ajax=1' --data 'channel=psy'
# {"songInformation":{"songID":"7520","song_title":"American Bar","artist_name":"Drip Drop & YaNn","song_duration":"435069","song_last_played":"2018-07-19 02:09:44"},"voteInformation":{"voteID":"19593","voteBlocked":0,"votePercent":"73"}}%
# curl 'http://html.psyradio.fm/songData.php?ajax=1' --data 'channel=alt'
# {"songInformation":{"songID":"3470","song_title":"Subsequent Connection (Atmos Remix)","artist_name":"Human Element","song_duration":"464039","song_last_played":"2018-07-19 02:10:47"},"voteInformation":{"voteID":"20001","voteBlocked":0,"votePercent":"82"}}%
# curl 'http://html.psyradio.fm/songData.php?ajax=1' --data 'channel=prog'
# {"songInformation":{"songID":"15621","song_title":"Wookie Beats (Ft. Moses)","artist_name":"Sensient","song_duration":"594834","song_last_played":"2018-07-19 02:12:37"},"voteInformation":{"voteID":"2328","voteBlocked":0,"votePercent":"65"}}%
# curl 'http://html.psyradio.fm/songData.php?ajax=1' --data 'channel=chill'
# {"songInformation":{"songID":"4207","song_title":"Cavok No Sig (feat. Georgina Brett)","artist_name":"Eat Static","song_duration":"587598","song_last_played":"2018-07-19 02:09:25"},"voteInformation":{"voteID":"19725","voteBlocked":0,"votePercent":"90"}}%
$player_pid = nil
$randomize_mode = nil
$chan = nil
def play_channel(channel)
Process.kill(9, $player_pid) if process_alive?($player_pid)
stream_url = channel[:stream_url] || "http://ice.somafm.com/#{channel[:id]}"
puts stream_url
commands = [
"cvlc -q #{stream_url}",
"mplayer -really-quiet #{stream_url}"
]
player_command = commands.find{|pc| `which #{pc.split(' ').first}` != ''}
if player_command
$player_pid = spawn(player_command)
else
STDERR.puts "No suitable player installed. Try installing one of #{commands.map{|e|e.split(' ').first}.join(', ')}"
exit
end
#Process.wait $player_pid
end
def process_alive?(pid)
return false unless pid
Process.kill(0, pid)
true
rescue Errno::ESRCH
false
end
if !ARGV[0]
sizes = channels.reduce(Hash.new(0)) { |s, e| e.each { |k, v| s[k] = s[k] < v.to_s.size ? v.to_s.size : s[k] }; s }
channels.each_with_index do |c, i|
id = i.to_s.ljust(5)
print c[:stream_url] ? id.brown.bold : id.red.bold
print c[:id].ljust(sizes[:id] + 2).magenta
print c[:title].ljust(sizes[:title] + 2).green
puts c[:description].cyan
end
print "\nWhich channel nr would you like to hear? > "
nr = gets.chomp.to_i
$chan = channels[nr]
puts "\nTuning into #{$chan[:title]}...\n\n"
else
q = ARGV[0].chomp.downcase
if q == 'random'
puts "randomizer on"
$chan = channels.sample
$randomize_mode = true
elsif q.match(/\d+/) && channels.each_index.include?(q.to_i)
$chan = channels[q.to_i]
else
$chan = channels.find { |e| e[:id].downcase.include?(q) || e[:title].downcase.include?(q) }
end
abort "Sorry couldn't find channel that matches '#{q}'..." unless $chan
puts "Tuning into #{$chan[:id]}...\n\n"
end
Thread.abort_on_exception = true
updater = Thread.new do
current_song = ''
loop do
sleep 1
next if $chan[:stream_url] # don't update for non-soma channels
song = nil
begin
#puts "http://somafm.com/songs/#{$chan[:id]}.json"
song = load_json("http://somafm.com/songs/#{$chan[:id]}.json")[:songs].first
rescue => e
STDERR.puts e
next
end
if song != current_song
if current_song != '' && $randomize_mode
current_song = ''
$chan = channels.sample
play_channel($chan)
else
print "\n#{Time.now.strftime('%R')}: ".blue
print song[:artist].bold.brown
print ' - '.bold.red
print song[:title].bold.brown
if song[:album] != ''
print ' - '.bold.red
print "[#{song[:album]}]".green
end
puts "\n"
current_song = song
end
end
sleep 9
end
end
if ARGV[1] == 'sonos'
# TODO: doesn't work?
# TODO: make work with mpdash?
puts 'trying to play on sonos'
require 'sonos'
sonos = Sonos::System.new
speaker = sonos.speakers.first
speaker.volume = 40
speaker.play stream_url
speaker.play
else
play_channel($chan)
end
updater.join
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment