def h_method_call(self, _, mdic, cdic): """ Listens for "method_call" messages and adds the "user parameters" to a new message """ dic=self._getParams() Bus.publish(self, "umethod_call", (mdic, cdic, dic))
def h_auth_gettoken(self, status, response_headers, cdic, udic, response): """ Authentication flow Success: ["ok", url] Failure: ["error", error_code, error_msg] """ Bus.publish(self, "log", "h_auth_gettoken, status: %s" % status) if status!="200": cdic["e"](["error", "method_failed", "Cannot retrieve 'auth token' from Last.fm"]) return if not response: cdic["e"](["error", "invalid_response", "Invalid response received from Last.fm"]) return match=re.search("\<token\>(.*)\<\/token\>", response) if match is None: cdic["e"](["error", "token_missing", "Missing 'auth token' from Last.fm response"]) return auth_token=match.group(1) Bus.publish(self, "user_params", {"auth_token":auth_token, "token":""}) api_key=udic.get("api_key", "") ## Return URL that must be used by the user for authentication ## =========================================================== url=self.auth_url % (api_key, auth_token) cdic["c"](["ok", url])
def playing_song_changed (self, sp, entry): """ Just grab the current playing entry The rest of the work will be done through the event "playing_changed" """ if entry: self.current_entry = sp.get_playing_entry() ed = EntryHelper.track_details(self.shell, entry) Bus.publish(self, "entry-playing", entry, ed)
def _process(self): dic=self.mdic if self.method=="auth.getSession": dic["token"]=self.udic.get("auth_token", "MISSING_AUTH_TOKEN") else: if self.srequired: dic["sk"]=self.udic.get("token", "MISSING_SESSION_TOKEN") dic["api_key"]=self.udic.get("api_key","") ## Signing tsign="" if self.srequired or self.method=="auth.getSession": secret=self.udic.get("secret_key", "") keys=sorted(dic.keys()) for key in keys: value=self.mdic[key] if type(value)==dbus.Array: liste="" for item in value: liste=item+"," value=liste.strip(",") tsign += key+value tsign+=secret.strip() m=md5() m.update(tsign) api_sig=m.hexdigest() Bus.publish(self, "log", "tosign(%s)" % tsign) ## URL formatting / POST body formatting fragment="" for key in dic: value=dic[key] if type(value) == dbus.Array: liste="" for item in value: liste=str(item)+"," value=liste.strip(",") fragment+=key+"="+urllib.quote(value)+"&" if self.srequired or self.method=="auth.getSession": fragment+="api_sig="+str(api_sig) fragment=fragment.strip("&") ## We do not want to update 'dic' with 'api_sig' ## Do not add keys which would pollute unneccessarily ## -------------------------------------------------- if self.wmethod: self.url=self.API self.body=fragment else: self.url=self.API+"?"+fragment self.body=None
def entry_changed(self, db, entry, changes): """ Gets triggered on every entry change Unfortunately, this includes every entry during the "startup phase" which consists in scanning all the sources of the library Allow sending 'None' for entry """ ed = EntryHelper.track_details(self.shell, entry) Bus.publish(self, "entry-changed", entry, ed)
def activate (self, shell): self.shell = shell self.db=shell.props.db Bus.publish(self, "db", self.db) sp = shell.get_player () self.spcb = ( sp.connect ('playing-song-changed', self.playing_song_changed) , ) self.dbcb = ( self.db.connect('entry-changed', self.entry_changed) ,#self.db.connect('load-complete', self.load_complete) )
def _session_required_flow(self, mdic, cdic, udic): """ A session must be authenticated before calling the method We need to have a "token" as starting point """ #Bus.publish(self, "log", "_session_required_flow: mdic(%s)" % mdic) auth_token=udic.get("auth_token", "") if not auth_token: cdic["e"](["error", "session_required"]) return cdic.update({"original_mdic":mdic}) Bus.publish(self, "method_call", {"method":"auth.getSession"}, cdic)
def h_auth_getsession(self, status, response_headers, cdic, udic, response): """ Return from "getsession" - part of authentication flow """ Bus.publish(self, "log", "h_auth_getsession, status: %s" % status) if status!="200": cdic["e"](["error", "method_failed", "Cannot retrieve 'session token' from Last.fm"]) return if not response: cdic["e"](["error", "invalid_response", "Invalid response received from Last.fm"]) return match=re.search("\<key\>(.*)\<\/key\>", response) if match is None: cdic["e"](["error", "token_missing", "Missing 'session token' from Last.fm response"]) return ## We've got a "session token" ... ## Now we need to complete the original method call token=match.group(1) Bus.publish(self, "user_params", {"token":token}) orig_mdic=cdic["original_mdic"] # get rid of original_mdic in cdic del cdic["original_mdic"] Bus.publish(self, "method_call", orig_mdic, cdic)
def q_user_params(self, _=None): """ Responder for the question "user_params?" """ dic=self._getParams() Bus.publish(self, "user_params", dic)
self.db.set(entry, rhythmdb.PROP_RATING, fvalue) except: print "setRating: expecting a float for 'rating', got: %s" % rating def setRatings(self, entries, rating): """ """ def _rate(model, _path, iter): entry=model.get(iter, 0)[0] self.db.set(entry, rhythmdb.PROP_RATING, rating) entries.foreach(_rate) th=TrackHelper() Bus.subscribe("db", th.hDb) class TrackHandler(object): def __init__(self, trackHelper): self.th=trackHelper self.currentEntry=None def hEntryPlaying(self, _, entry): """ Intercepts the current playing entry """ self.currentEntry=entry
""" Performs 'dependency checks' of the received parameters against the 'root parameters' """ for key in iparams: if key in self.rootParams: self._updateParams({"auth_token":"", "token":""}) self.q_user_params() break ## ========================================================== Bus Interfacing user=User() Bus.subscribe("user_params?", user.q_user_params) Bus.subscribe("user_params", user.h_user_params) Bus.subscribe("method_call", user.h_method_call) ## ========================================================== TESTS if __name__ == '__main__': class Logger(object): def __call__(self, msgType, e): print "Logger: Error: msgType(%s) Exception(%s)" % (msgType, str(e)) class Test(object): def handler(self, msgType, params): print params Bus.logger=Logger()
def sRateCurrentPlaying(self, rating): """ DBus signal handler - /Player/RateCurrentPlaying """ Bus.publish(self, "rate-current", rating)
def hEntryPlaying(self, _, entry, ed): """ Message Bus handler """ self.TrackChange(ed) def sRateCurrentPlaying(self, rating): """ DBus signal handler - /Player/RateCurrentPlaying """ Bus.publish(self, "rate-current", rating) player=hPlayer() Bus.subscribe("entry-playing", player.hEntryPlaying) dbus.Bus().add_signal_receiver(player.sRateCurrentPlaying, signal_name="RateCurrentPlaying", dbus_interface="org.freedesktop.MediaPlayer", bus_name=None, path="/Player") class hTrack(dbus.service.Object): """ DBus signals for the /Track path """ PATH="/Track" def __init__(self): dbus.service.Object.__init__(self, dbus.SessionBus(), self.PATH)
print "setRating: exception(%s)" % str(e) def setRatings(self, entries, rating): """ Set the rating of a batch of entries """ def _rate(model, _path, iter): entry = model.get(iter, 0)[0] self.db.set(entry, rhythmdb.PROP_RATING, rating) entries.foreach(_rate) th = TrackHelper() Bus.subscribe("db", th.hDb) class TrackHandler(object): def __init__(self, trackHelper): self.th = trackHelper self.currentEntry = None def hEntryPlaying(self, _, entry, _entryDic): """ Intercepts the current playing entry """ self.currentEntry = entry def hRateCurrent(self, _, rating): """
if ws_method.is_error(): cdic["e"](["error", ws_method.get_error()]) return ctx=(ws_method.method, cdic, udic) make_ws_request(ctx, ws_method.url, http_method=ws_method.http_method, postdata=ws_method.body) def _session_required_flow(self, mdic, cdic, udic): """ A session must be authenticated before calling the method We need to have a "token" as starting point """ #Bus.publish(self, "log", "_session_required_flow: mdic(%s)" % mdic) auth_token=udic.get("auth_token", "") if not auth_token: cdic["e"](["error", "session_required"]) return cdic.update({"original_mdic":mdic}) Bus.publish(self, "method_call", {"method":"auth.getSession"}, cdic) wsh=WsMethodHandler() Bus.subscribe("umethod_call", wsh.h_umethod_call) ## Test string for 'track.getTags' #"depeche mode", "little 15"
def page(self, response): if self.finished: return self.finished=True Bus.publish(self, "ws_response", (self.status, self.response_headers, self._ctx, response))
""" @author: jldupont Created on 2010-02-01 """ from twisted.python import log from mbus import Bus class Logger(object): """ Simple Logger """ def _log(self, _, _msg): log.msg(_msg) logger=Logger() Bus.subscribe("log", logger._log)
def clientConnectionFailed(self, _, reason): self.eback(["error", "conn_error", "connection to Last.fm API failed"]) Bus.publish(self, "error", ["conn_error", {"reason":reason, "status":self.status}])
Bus.publish(self, "log", "h_auth_gettoken, status: %s" % status) if status!="200": cdic["e"](["error", "method_failed", "Cannot retrieve 'auth token' from Last.fm"]) return if not response: cdic["e"](["error", "invalid_response", "Invalid response received from Last.fm"]) return match=re.search("\<token\>(.*)\<\/token\>", response) if match is None: cdic["e"](["error", "token_missing", "Missing 'auth token' from Last.fm response"]) return auth_token=match.group(1) Bus.publish(self, "user_params", {"auth_token":auth_token, "token":""}) api_key=udic.get("api_key", "") ## Return URL that must be used by the user for authentication ## =========================================================== url=self.auth_url % (api_key, auth_token) cdic["c"](["ok", url]) wsrh=WsResponseHandler() Bus.subscribe("ws_response", wsrh.h_ws_response)