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()))
Пример #4
0
    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]))
Пример #6
0
    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