def nowPlayingNotification(self, track, firstTry = True): """ The Now-Playing notification is a lightweight mechanism for notifying the Audioscrobbler server that a track has started playing """ if (self.session[SESSION_ID] is None and not self.handshake()) or not track.hasArtist() or not track.hasTitle(): return params = ( ( 's', self.session[SESSION_ID] ), ( 'a', tools.percentEncode(track.getSafeArtist()) ), ( 't', tools.percentEncode(track.getSafeTitle()) ), ( 'b', tools.percentEncode(track.getSafeAlbum()) ), ( 'l', track.getSafeLength() ), ( 'n', track.getSafeNumber() ), ( 'm', track.getSafeMBTrackId() ) ) try: data = '&'.join(['%s=%s' % (key, val) for (key, val) in params]) reply = urlopen(self.session[NOW_PLAYING_URL], data).read().strip().split('\n') if reply[0] == 'BADSESSION' and firstTry: self.session[:] = [None, None, None] self.nowPlayingNotification(track, False) except: logger.error('[%s] Unable to perform now-playing notification\n\n%s' % (MOD_NAME, traceback.format_exc()))
def addToCache(self): """ Add the current track to the cache, if any, and that all conditions are OK """ if self.currTrack is None: return else: track = self.currTrack[TRK_INFO] if not (track.hasArtist() and track.hasTitle() and track.hasLength()): return if not ( track.getLength() >= 30 and (self.currTrack[TRK_PLAY_TIME] >= 240 or self.currTrack[TRK_PLAY_TIME] >= track.getLength() / 2) ): return params = ( ("a[*]", tools.percentEncode(track.getSafeArtist())), ("t[*]", tools.percentEncode(track.getSafeTitle())), ("i[*]", str(self.currTrack[TRK_STARTED_TIMESTAMP])), ("o[*]", "P"), ("r[*]", ""), ("l[*]", track.getSafeLength()), ("b[*]", tools.percentEncode(track.getSafeAlbum())), ("n[*]", track.getSafeNumber()), ("m[*]", track.getSafeMBTrackId()), ) self.cache.append("&".join(["%s=%s" % (key, val) for (key, val) in params])) self.saveCache()
def nowPlayingNotification(self, track, firstTry=True): """ The Now-Playing notification is a lightweight mechanism for notifying the Audioscrobbler server that a track has started playing """ import urllib2 if (self.session[SESSION_ID] is None and not self.handshake()) or not track.hasArtist() or not track.hasTitle(): return params = ( ("s", self.session[SESSION_ID]), ("a", tools.percentEncode(track.getSafeArtist())), ("t", tools.percentEncode(track.getSafeTitle())), ("b", tools.percentEncode(track.getSafeAlbum())), ("l", track.getSafeLength()), ("n", track.getSafeNumber()), ("m", track.getSafeMBTrackId()), ) try: data = "&".join(["%s=%s" % (key, val) for (key, val) in params]) reply = urllib2.urlopen(self.session[NOW_PLAYING_URL], data).read().strip().split("\n") if reply[0] == "BADSESSION" and firstTry: self.session[:] = [None, None, None] self.nowPlayingNotification(track, False) except: logger.error("[%s] Unable to perform now-playing notification\n\n%s" % (MOD_NAME, traceback.format_exc()))
def __getFromInternet(self, artist, album): """ Try to download the cover from the Internet If successful, add it to the cache and return the path to it Otherwise, return None """ # Make sure to not be blocked by the request socket.setdefaulttimeout(consts.socketTimeout) # Request information to Last.fm # Beware of UTF-8 characters: we need to percent-encode all characters try: url = 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=%s&artist=%s&album=%s' % (AS_API_KEY, tools.percentEncode(artist), tools.percentEncode(album)) request = urllib2.Request(url, headers = {'User-Agent': USER_AGENT}) stream = urllib2.urlopen(request) data = stream.read() except urllib2.HTTPError, err: if err.code == 400: logger.error('[%s] No known cover for %s / %s' % (MOD_NAME, artist, album)) else: logger.error('[%s] Information request failed\n\n%s' % (MOD_NAME, traceback.format_exc())) return None
def addToCache(self): """ Add the current track to the cache, if any, and that all conditions are OK """ if self.currTrack is None: return else: track = self.currTrack[TRK_INFO] if not (track.hasArtist() and track.hasTitle() and track.hasLength()): return if not (track.getLength() >= 30 and (self.currTrack[TRK_PLAY_TIME] >= 240 or self.currTrack[TRK_PLAY_TIME] >= track.getLength()/2)): return params = ( ( 'a[*]', tools.percentEncode(track.getSafeArtist()) ), ( 't[*]', tools.percentEncode(track.getSafeTitle()) ), ( 'i[*]', str(self.currTrack[TRK_STARTED_TIMESTAMP]) ), ( 'o[*]', 'P' ), ( 'r[*]', '' ), ( 'l[*]', track.getSafeLength() ), ( 'b[*]', tools.percentEncode(track.getSafeAlbum()) ), ( 'n[*]', track.getSafeNumber() ), ( 'm[*]', track.getSafeMBTrackId() ) ) self.cache.append('&'.join(['%s=%s' % (key, val) for (key, val) in params]))
def __getFromInternet(self, artist, album): """ Try to download the cover from the Internet If successful, add it to the cache and return the path to it Otherwise, return None """ import socket, urllib.request, urllib.error, urllib.parse # Make sure to not be blocked by the request socket.setdefaulttimeout(consts.socketTimeout) # Request information to Last.fm # Beware of UTF-8 characters: we need to percent-encode all characters try: url = 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=%s&artist=%s&album=%s' % ( AS_API_KEY, tools.percentEncode(artist), tools.percentEncode(album)) request = urllib.request.Request( url, headers={'User-Agent': USER_AGENT}) stream = urllib.request.urlopen(request) data = stream.read().decode('utf-8') except urllib.error.HTTPError as err: if err.code == 400: logger.error('[%s] No known cover for %s / %s' % (MOD_NAME, artist, album)) else: logger.error('[%s] Information request failed\n\n%s' % (MOD_NAME, traceback.format_exc())) return None except urllib.error.URLError: logger.info('[%s] Could not fetch cover. No internet connection.' % MOD_NAME) return None except: logger.error('[%s] Information request failed\n\n%s' % (MOD_NAME, traceback.format_exc())) return None # Extract the URL to the cover image malformed = True startIdx = data.find(AS_TAG_START) endIdx = data.find(AS_TAG_END, startIdx) if startIdx != -1 and endIdx != -1: coverURL = data[startIdx + len(AS_TAG_START):endIdx] coverFormat = os.path.splitext(coverURL)[1].lower() if coverURL.startswith( ('http://', 'https://')) and coverFormat in ACCEPTED_FILE_FORMATS: malformed = False if malformed: ## Do not show the data in the log every time no cover is found if coverURL: logger.error('[%s] Received malformed data\n\n%s' % (MOD_NAME, data)) return None # Download the cover image try: request = urllib.request.Request( coverURL, headers={'User-Agent': USER_AGENT}) stream = urllib.request.urlopen(request) data = stream.read() if len(data) < 1024: raise Exception( 'The cover image seems incorrect (%u bytes is too small)' % len(data)) except: logger.error('[%s] Cover image request failed' % MOD_NAME) return None # So far, so good: let's cache the image cachePath = os.path.join(self.cacheRootPath, str(abs(hash(artist)))) cacheIdxPath = os.path.join(cachePath, 'INDEX') if not os.path.exists(cachePath): os.mkdir(cachePath) try: cacheIdx = tools.pickleLoad(cacheIdxPath) except: cacheIdx = {} nextInt = len(cacheIdx) + 1 filename = str(nextInt) + coverFormat coverPath = os.path.join(cachePath, filename) cacheIdx[artist + album] = filename tools.pickleSave(cacheIdxPath, cacheIdx) try: output = open(coverPath, 'wb') output.write(data) output.close() return coverPath except: logger.error('[%s] Could not save the downloaded cover\n\n%s' % (MOD_NAME, traceback.format_exc())) return None