Daniel@0: /* Part of DML (Digital Music Laboratory) Daniel@0: Copyright 2014-2015 Samer Abdallah, University of London Daniel@0: Daniel@0: This program is free software; you can redistribute it and/or Daniel@0: modify it under the terms of the GNU General Public License Daniel@0: as published by the Free Software Foundation; either version 2 Daniel@0: of the License, or (at your option) any later version. Daniel@0: Daniel@0: This program is distributed in the hope that it will be useful, Daniel@0: but WITHOUT ANY WARRANTY; without even the implied warranty of Daniel@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Daniel@0: GNU General Public License for more details. Daniel@0: Daniel@0: You should have received a copy of the GNU General Public Daniel@0: License along with this library; if not, write to the Free Software Daniel@0: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Daniel@0: */ Daniel@0: Daniel@0: :- module(echonest, Daniel@0: [ echocall/4 Daniel@0: ]). Daniel@0: Daniel@0: /** Interface to echonest Web API Daniel@0: */ Daniel@0: Daniel@0: :- use_module(library(fileutils)). Daniel@0: :- use_module(library(http/json)). Daniel@0: :- use_module(library(jpath)). Daniel@0: :- use_module(library(webby)). Daniel@0: :- use_module(library(state)). Daniel@0: Daniel@0: :- set_prolog_flag(double_quotes,string). Daniel@0: Daniel@0: :- setting(min_wait,number,3,"Minimum time between echonest requests"). Daniel@0: :- initialization set_state(next_request_time,0). Daniel@0: Daniel@0: wait_respectfully :- Daniel@0: get_time(Now), Daniel@0: setting(min_wait,TMin), Daniel@0: get_state(next_request_time,T0), T1 is max(Now,T0) + TMin, Daniel@0: set_state(next_request_time,T1), Daniel@0: ( Now>=T0 -> true Daniel@0: ; DT is T0-Now, Daniel@0: debug(echonest,"Sleeping for ~f seconds to respect rate limit",[DT]), Daniel@0: sleep(DT) Daniel@0: ). Daniel@0: Daniel@0: echocall(Key,PathParts,Params,Response) :- Daniel@0: debug(echonest,"Echonest call: ~q, ~q...",[PathParts,Params]), Daniel@0: parts_path([api,v4|PathParts],Path), Daniel@0: wait_respectfully, Daniel@0: catch( restcall(get([api_key=Key, format=json | Params]), json(Response), Daniel@0: [protocol(http), host('developer.echonest.com'), path(Path)], []), Daniel@0: Ex, handle(Ex)). Daniel@0: Daniel@0: handle(http_bad_status(SC,codes(Doc))) :- !, Daniel@0: with_input_from(codes(Doc),json_read_dict(current_input,Dict)), Daniel@0: jpath(response:status:(code:Code,message:Msg),Dict), Daniel@0: throw(echonest_error(SC,Code,Msg)). Daniel@0: handle(Ex) :- throw(Ex). Daniel@0: Daniel@0: Daniel@0: prolog:message(echonest_error(SC,Code,Msg)) --> Daniel@0: {http_status(SC,Meaning)}, Daniel@0: ["(HTTP ~w: ~w) Echonest error ~w: '~s'."-[SC,Meaning,Code,Msg]].