Skip to content

Instantly share code, notes, and snippets.

@koyachi
Created March 28, 2009 11:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save koyachi/87086 to your computer and use it in GitHub Desktop.
Save koyachi/87086 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
require 'rubygems'
require 'uri'
require 'net/http'
require 'digest/md5'
require 'rexml/document'
require 'extlib'
require 'yaml'
class WebService; end
class WebService::EchoNest
def initialize(apikey)
@api_key = apikey
@base_url = 'http://developer.echonest.com'
@host = 'developer.echonest.com'
end
def upload(file)
file_data = File.read(file)
boundary = '----BOUNDARYBOUNDARY----'
data = <<EOF
--#{boundary}\r
Content-Disposition: form-data; name="api_key"\r
\r
#{@api_key}\r
--#{boundary}\r
Content-Disposition: form-data; name="version"\r
\r
3\r
--#{boundary}\r
Content-Disposition: form-data; name="wait"\r
\r
Y\r
--#{boundary}\r
Content-Disposition: form-data; name="file"; filename="#{file}"\r
Content-Type: application/octet-stream\r
\r
#{file_data}\r
--#{boundary}--\r
EOF
header ={
'Content-Length' => data.length.to_s,
'Content-Type' => "multipart/form-data; boundary=#{boundary}"
}
url = @base_url + '/api/upload'
uri = URI.parse(url)
response = Net::HTTP.start(uri.host, 80) {|http|
http.post(uri.path, data, header)
}
doc = REXML::Document.new response.body
result = {
'status' => {},
'query' => {},
'track' => {},
}
%w[code message].each do |m|
result['status'][m] = doc.elements['response'].elements['status'].elements[m].text
end
%w[api_key url file wait].each do |m|
elm = REXML::XPath.first(doc, "//parameter[@name=\"#{m}\"]")
result['query'][m] = elm.text if elm
end
%w[id md5].each do |m|
result['track'][m] = doc.elements['response'].elements['track'].attributes[m]
end
result
end
def get_beats(args)
p args
url = @base_url + '/api/get_beats?' +
['api_key=' + @api_key,
'version=3'].join('&')
if args[:id]
url += "&id=#{args[:id]}"
else
if args[:file]
md5 = Digest::MD5.hexdigest(File.open(args[:file], 'rb').read)
else
md5 = args[:md5]
end
url += "&md5=#{md5}"
end
response = Net::HTTP::get_response(URI.parse(url));
doc = REXML::Document.new response.body
result = Mash.new({
:status => Mash.new({}),
:query => Mash.new({}),
:beats => [],
})
%w[code message].each do |m|
result[:status][m] = doc.elements['response'].elements['status'].elements[m].text
end
# unknown md5
if result[:status][:code] == '5'
puts "unknown md5. uploading..."
upload args[:file]
get_beats :md5 => md5
else
%w[api_key id md5].each do |m|
elm = REXML::XPath.first(doc, "//parameter[@name=\"#{m}\"]")
result[:query][m] = elm.text if elm
end
doc.elements.each('response/analysis/beat') {|elm|
result[:beats].push(Mash.new({
:confidence => elm.attributes['confidence'],
:value => elm.text
}))
}
result
end
end
def get_tatums(args)
end
def get_bars(args)
end
def get_sections(args)
url = @base_url + '/api/get_sections?' +
['api_key=' + @api_key,
'version=3'].join('&')
if args[:id]
url += "&id=#{args[:id]}"
else
if args[:file]
md5 = Digest::MD5.hexdigest(File.open(args[:file], 'rb').read)
else
md5 = args[:md5]
end
url += "&md5=#{md5}"
end
response = Net::HTTP::get_response(URI.parse(url));
doc = REXML::Document.new response.body
result = Mash.new({
:status => Mash.new({}),
:query => Mash.new({}),
:sections => [],
})
%w[code message].each do |m|
result[:status][m] = doc.elements['response'].elements['status'].elements[m].text
end
# unknown md5
if result[:status][:code] == '5'
puts "unknown md5. uploading..."
upload args[:file]
get_sections :md5 => md5
else
%w[api_key id md5].each do |m|
elm = REXML::XPath.first(doc, "//parameter[@name=\"#{m}\"]")
result[:query][m] = elm.text if elm
end
doc.elements.each('response/analysis/section') {|elm|
result[:sections].push(Mash.new({
:start => elm.attributes['start'],
:duration => elm.attributes['duration'],
}))
}
result
end
end
def get_segments(args)
url = @base_url + '/api/get_segments?' +
['api_key=' + @api_key,
'version=3'].join('&')
if args[:id]
url += "&id=#{args[:id]}"
else
if args[:file]
md5 = Digest::MD5.hexdigest(File.open(args[:file], 'rb').read)
else
md5 = args[:md5]
end
url += "&md5=#{md5}"
end
response = Net::HTTP::get_response(URI.parse(url));
doc = REXML::Document.new response.body
result = Mash.new({
:status => Mash.new({}),
:query => Mash.new({}),
:segments => [],
})
%w[code message].each do |m|
result[:status][m] = doc.elements['response'].elements['status'].elements[m].text
end
# unknown md5
if result[:status][:code] == '5'
puts "unknown md5. uploading..."
upload args[:file]
get_segments :md5 => md5
else
%w[api_key id md5].each do |m|
elm = REXML::XPath.first(doc, "//parameter[@name=\"#{m}\"]")
result[:query][m] = elm.text if elm
end
doc.elements.each('response/analysis/segment') {|elm|
loudness = []
elm.elements.each('loudness/dB') {|e|
loudness.push({
:time => e.attributes['time'] || 0,
:value => e.text
})
}
pitches = []
elm.elements.each('pitches/pitch') {|e|
pitches.push e.text
}
timbre = []
elm.elements.each('timbre/coeff') {|e|
timbre.push e.text
}
result[:segments].push(Mash.new({
:start => elm.attributes['start'],
:duration => elm.attributes['duration'],
:loudness => {
:min => {
:time => loudness[0][:time],
:value => loudness[0][:value],
},
:max => {
:time => loudness[1][:time],
:value => loudness[1][:value],
},
},
:pitches => pitches,
:timbre => timbre,
}))
}
result
end
end
def search_tracks(query)
p 'search_tracks'
query = query.gsub(' ', '+')
url = @base_url + '/api/search_tracks?' +
['api_key=' + @api_key,
'version=3',
'query=' + query].join('&')
response = Net::HTTP::get_response(URI.parse(url));
REXML::Document.new response.body
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment