Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

executable file 1395 lines (1296 sloc) 67.886 kB
# * Credits:
# *
# * original Artist Slideshow code by ronie
# * updates and additions since v1.3.0 by pkscout
# *
# * divingmule for script.image.lastfm.slideshow
# * grajen3 for script.ImageCacher
# * sfaxman for smartUnicode
# *
# * code from all scripts/examples are used in script.artistslideshow
# *
# * Musicbrainz python library by Kenneth Reitz
# * see resource/musicbrainzngs/copying for copyright and use restrictions
# *
# * Last.fm: http://www.last.fm/
# * fanart.tv: http://www.fanart.tv
# * theaudiodb: http://www.theaudiodb.com
# * htbackdrops: http://www.htbackdrops.org
import xbmc, xbmcaddon, xbmcgui, xbmcvfs
import itertools, os, random, re, sys, time
import xml.etree.ElementTree as _xmltree
if sys.version_info >= (2, 7):
import json as _json
else:
import simplejson as _json
from resources.dicttoxml.dicttoxml import dicttoxml
from resources.common.fix_utf8 import smartUTF8
from resources.common.fileops import checkPath, writeFile, readFile, deleteFile
from resources.common.url import URL
from resources.common.transforms import getImageType, itemHash, itemHashwithPath
from resources.common.xlogger import Logger
__addon__ = xbmcaddon.Addon()
__addonname__ = __addon__.getAddonInfo('id')
__addonversion__ = __addon__.getAddonInfo('version')
__addonpath__ = __addon__.getAddonInfo('path').decode('utf-8')
__addonicon__ = xbmc.translatePath('%s/icon.png' % __addonpath__ )
__language__ = __addon__.getLocalizedString
__preamble__ = '[Artist Slideshow]'
__logdebug__ = __addon__.getSetting( "logging" )
lw = Logger( preamble=__preamble__, logdebug=__logdebug__ )
mbURL = URL( 'json',{"User-Agent": __addonname__ + '/' + __addonversion__ + '( https://github.com/pkscout/artistslideshow )', "content-type":"text/html; charset=UTF-8"} )
JSONURL = URL( 'json' )
txtURL = URL( 'text' )
imgURL = URL( 'binary' )
LANGUAGES = (
# Full Language name[0] ISO 639-1[1] Script Language[2]
("Albanian" , "sq", "0" ),
("Arabic" , "ar", "1" ),
("Belarusian" , "hy", "2" ),
("Bosnian" , "bs", "3" ),
("Bulgarian" , "bg", "4" ),
("Catalan" , "ca", "5" ),
("Chinese" , "zh", "6" ),
("Croatian" , "hr", "7" ),
("Czech" , "cs", "8" ),
("Danish" , "da", "9" ),
("Dutch" , "nl", "10" ),
("English" , "en", "11" ),
("Estonian" , "et", "12" ),
("Persian" , "fa", "13" ),
("Finnish" , "fi", "14" ),
("French" , "fr", "15" ),
("German" , "de", "16" ),
("Greek" , "el", "17" ),
("Hebrew" , "he", "18" ),
("Hindi" , "hi", "19" ),
("Hungarian" , "hu", "20" ),
("Icelandic" , "is", "21" ),
("Indonesian" , "id", "22" ),
("Italian" , "it", "23" ),
("Japanese" , "ja", "24" ),
("Korean" , "ko", "25" ),
("Latvian" , "lv", "26" ),
("Lithuanian" , "lt", "27" ),
("Macedonian" , "mk", "28" ),
("Norwegian" , "no", "29" ),
("Polish" , "pl", "30" ),
("Portuguese" , "pt", "31" ),
("PortugueseBrazil" , "pb", "32" ),
("Romanian" , "ro", "33" ),
("Russian" , "ru", "34" ),
("Serbian" , "sr", "35" ),
("Slovak" , "sk", "36" ),
("Slovenian" , "sl", "37" ),
("Spanish" , "es", "38" ),
("Swedish" , "sv", "39" ),
("Thai" , "th", "40" ),
("Turkish" , "tr", "41" ),
("Ukrainian" , "uk", "42" ),
("Vietnamese" , "vi", "43" ),
("Farsi" , "fa", "13" ),
("Portuguese (Brazil)" , "pb", "32" ),
("Portuguese-BR" , "pb", "32" ),
("Brazilian" , "pb", "32" ) )
class Main:
def __init__( self ):
self._parse_argv()
self._init_window()
if self._get_infolabel( self.ARTISTSLIDESHOWRUNNING ) == "True":
lw.log( ['script already running'] )
else:
self._get_settings()
self._init_vars()
self._make_dirs()
self._upgrade()
self.LastCacheTrim = 0
self._set_property("ArtistSlideshowRunning", "True")
if( xbmc.Player().isPlayingAudio() == False and self._get_infolabel( self.EXTERNALCALL ) == '' ):
lw.log( ['no music playing'] )
if( self.DAEMON == "False" ):
self._set_property("ArtistSlideshowRunning")
else:
lw.log( ['first song started'] )
time.sleep(1) # it may take some time for xbmc to read tag info after playback started
self._use_correct_artwork()
self._trim_cache()
while (not xbmc.abortRequested):
time.sleep(1)
if self._get_infolabel( self.ARTISTSLIDESHOWRUNNING ) == "True":
if( xbmc.Player().isPlayingAudio() == True or self._get_infolabel( self.EXTERNALCALL ) != '' ):
if set( self.ALLARTISTS ) <> set( self._get_current_artists() ):
self._clear_properties()
self.UsingFallback = False
self._use_correct_artwork()
self._trim_cache()
elif(not (self.DownloadedAllImages or self.UsingFallback)):
if(not (self.LocalImagesFound and self.PRIORITY == '1')):
lw.log( ['same artist playing, continue download'] )
self._use_correct_artwork()
else:
time.sleep(2) # doublecheck if playback really stopped
if( xbmc.Player().isPlayingAudio() == False and self._get_infolabel( self.EXTERNALCALL ) == '' ):
if ( self.DAEMON == "False" ):
self._set_property( "ArtistSlideshowRunning" )
else:
self._clear_properties()
break
try:
self._set_property("ArtistSlideshow.CleanupComplete", "True")
except Exception, e:
lw.log( ['unexpected error while setting property.', e] )
def _clean_dir( self, dir_path ):
try:
dirs, old_files = xbmcvfs.listdir( dir_path )
except Exception, e:
lw.log( ['unexpected error while getting directory list', e] )
old_files = []
for old_file in old_files:
if not old_file.endswith( '.nfo' ):
success, loglines = deleteFile( os.path.join(dir_path, old_file.decode('utf-8')) )
def _clean_text( self, text ):
text = re.sub('<a [^>]*>|</a>|<span[^>]*>|</span>','',text)
text = re.sub('&quot;','"',text)
text = re.sub('&amp;','&',text)
text = re.sub('&gt;','>',text)
text = re.sub('&lt;','<',text)
text = re.sub('User-contributed text is available under the Creative Commons By-SA License and may also be available under the GNU FDL.','',text)
text = re.sub('Read more about .* on Last.fm.','',text)
return text.strip()
def _clear_properties( self ):
self.MBID = ''
self._set_property( "ArtistSlideshow", self.InitDir )
self._clean_dir( self.MergeDir )
self._clean_dir( self.TransitionDir )
self._set_property( "ArtistSlideshow.ArtistBiography" )
for count in range( 50 ):
self._set_property( "ArtistSlideshow.%d.SimilarName" % ( count + 1 ) )
self._set_property( "ArtistSlideshow.%d.SimilarThumb" % ( count + 1 ) )
self._set_property( "ArtistSlideshow.%d.AlbumName" % ( count + 1 ) )
self._set_property( "ArtistSlideshow.%d.AlbumThumb" % ( count + 1 ) )
def _download( self, src, dst, dst2 ):
if (not xbmc.abortRequested):
tmpname = xbmc.translatePath('special://profile/addon_data/%s/temp/%s' % ( __addonname__ , xbmc.getCacheThumbName(src) ))
lw.log( ['the tmpname is ' + tmpname] )
if not self._excluded( dst ):
if xbmcvfs.exists(tmpname):
success, loglines = deleteFile( tmpname )
lw.log( loglines )
success, loglines, urldata = imgURL.Get( src, params=self.params )
lw.log( loglines )
if success:
success, loglines = writeFile( urldata, tmpname )
lw.log( loglines )
if not success:
return False
if xbmcvfs.Stat( tmpname ).st_size() > 999:
image_ext = getImageType( tmpname )
if not xbmcvfs.exists ( dst + image_ext ):
lw.log( ['copying %s to %s' % (tmpname, dst2 + image_ext)] )
xbmcvfs.copy( tmpname, dst2 + image_ext )
lw.log( ['moving %s to %s' % (tmpname, dst + image_ext)] )
xbmcvfs.rename( tmpname, dst + image_ext )
return True
else:
lw.log( ['image already exists, deleting temporary file'] )
success, loglines = deleteFile( tmpname )
lw.log( loglines )
return False
else:
success, loglines = deleteFile( tmpname )
lw.log( loglines )
return False
else:
return False
def _excluded( self, item ):
path, filename = os.path.split( item )
exclusion_file = os.path.join( path, '_exclusions.nfo' )
if xbmcvfs.exists( exclusion_file ):
loglines, exclusions = readFile( exclusion_file )
loglines.append( 'checking %s against %s' % (filename, exclusions) )
lw.log( loglines )
if filename in exclusions:
lw.log( ['exclusion found'] )
return True
else:
return False
else:
success, loglines = writeFile( '', exclusion_file )
lw.log( loglines )
return False
def _get_artistinfo( self ):
lw.log( ['checking for local artist bio data'] )
bio = self._get_local_data( 'bio' )
if bio == []:
if self.MBID:
self.url = self.theaudiodbARTISTURL
self.params['i'] = self.MBID
lw.log( ['trying to get artist bio from ' + self.url] )
bio = self._get_data( 'theaudiodb', 'bio' )
if bio == []:
self.url = self.LastfmURL
additionalparams = {'lang':self.LANGUAGE, 'method':'artist.getInfo', 'artist':self.NAME}
self.params = dict( self.LastfmPARAMS.items() + additionalparams.items() )
lw.log( ['trying to get artist bio from ' + self.url] )
bio = self._get_data('lastfm', 'bio')
if bio == []:
self.biography = ''
else:
self.biography = self._clean_text(bio[0])
self.albums = self._get_local_data( 'albums' )
if self.albums == []:
loglines, theaudiodb_id = readFile( os.path.join(self.InfoDir, 'theaudiodbid.nfo') )
lw.log( loglines )
if theaudiodb_id:
self.url = self.theaudiodbALBUMURL
self.params['i'] = theaudiodb_id
lw.log( ['trying to get artist albumns from ' + self.url] )
self.albums = self._get_data('theaudiodb', 'albums')
if self.albums == []:
self.url = self.LastfmURL
additionalparams = {'method':'artist.getTopAlbums', 'artist':self.NAME}
self.params = dict( self.LastfmPARAMS.items() + additionalparams.items() )
lw.log( ['trying to get artist albums from ' + self.url] )
self.albums = self._get_data('lastfm', 'albums')
self.similar = self._get_local_data( 'similar' )
if self.similar == []:
self.url = self.LastfmURL
additionalparams = {'method':'artist.getSimilar', 'artist':self.NAME}
self.params = dict( self.LastfmPARAMS.items() + additionalparams.items() )
self.similar = self._get_data('lastfm', 'similar')
self._set_properties()
def _get_current_artists( self ):
current_artists = []
for artist, mbid in self._get_current_artists_info( 'withoutmbid'):
current_artists.append( artist )
return current_artists
def _get_current_artists_info( self, type ):
featured_artists = ''
artist_names = []
artists_info = []
mbids = []
if( xbmc.Player().isPlayingAudio() == True ):
try:
playing_file = xbmc.Player().getPlayingFile() + ' - ' + xbmc.Player().getMusicInfoTag().getArtist() + ' - ' + xbmc.Player().getMusicInfoTag().getTitle()
lw.log( ['playing file is ' + playing_file] )
except RuntimeError:
return artists_info
except Exception, e:
lw.log( ['unexpected error getting playing file back from XBMC', e] )
return artists_info
if playing_file != self.LASTPLAYINGFILE:
# if the same file is playing, use cached JSON response instead of doing a new query
response = xbmc.executeJSONRPC ( '{"jsonrpc":"2.0", "method":"Player.GetItem", "params":{"playerid":0, "properties":["artist", "musicbrainzartistid"]},"id":1}' )
self.LASTPLAYINGFILE = playing_file
self.LASTJSONRESPONSE = response
else:
response = self.LASTJSONRESPONSE
try:
artist_names = _json.loads(response)['result']['item']['artist']
except (IndexError, KeyError, ValueError):
artist_names = []
except Exception, e:
lw.log( ['unexpected error getting JSON back from XBMC', e] )
artist_names = []
try:
mbids = _json.loads(response)['result']['item']['muiscbrainzartistid']
except (IndexError, KeyError, ValueError):
mbids = []
except Exception, e:
lw.log( ['unexpected error getting JSON back from XBMC', e] )
mbids = []
try:
playing_song = xbmc.Player().getMusicInfoTag().getTitle()
except RuntimeError:
playing_song = ''
except Exception, e:
lw.log( ['unexpected error gettting playing song back from XBMC', e] )
playing_song = ''
if not artist_names:
lw.log( ['No artist names returned from JSON call, assuming this is an internet stream'] )
try:
playingartist = playing_song[0:(playing_song.find('-'))-1]
except RuntimeError:
playingartist = ''
playing_song = ''
except Exception, e:
lw.log( ['unexpected error gettting playing song back from XBMC', e] )
playingartist = ''
playing_song = ''
artist_names = self._split_artists( playingartist )
featured_artists = self._get_featured_artists( playing_song )
elif self._get_infolabel( self.SKININFO['artist'] ):
artist_names = self._split_artists( self._get_infolabel(self.SKININFO['artist']) )
mbids = self._get_infolabel( self.SKININFO['mbid'] ).split( ',' )
featured_artists = self._get_featured_artists( self._get_infolabel(self.SKININFO['title']) )
if featured_artists:
for one_artist in featured_artists:
artist_names.append( one_artist.strip(' ()') )
for artist_name, mbid in itertools.izip_longest( artist_names, mbids, fillvalue='' ):
if artist_name:
if not mbid and type == 'withmbid':
mbid = self._get_musicbrainz_id( artist_name )
else:
mbid = ''
artists_info.append( (artist_name, mbid) )
return artists_info
def _get_data( self, site, item ):
data = []
ForceUpdate = True
if item == "images":
if site == "fanarttv":
filename = os.path.join( self.InfoDir, 'fanarttvartistimages.nfo')
elif site == "theaudiodb":
filename = os.path.join( self.InfoDir, 'theaudiodbartistbio.nfo')
id_filename = os.path.join( self.InfoDir, 'theaudiodbid.nfo')
elif site == "htbackdrops":
filename = os.path.join( self.InfoDir, 'htbackdropsartistimages.nfo')
elif item == "bio":
if site == "theaudiodb":
filename = os.path.join( self.InfoDir, 'theaudiodbartistbio.nfo')
id_filename = os.path.join( self.InfoDir, 'theaudiodbid.nfo')
elif site == "lastfm":
filename = os.path.join( self.InfoDir, 'lastfmartistbio.nfo')
elif item == "similar":
filename = os.path.join( self.InfoDir, 'lastfmartistsimilar.nfo')
elif item == "albums":
if site == "theaudiodb":
filename = os.path.join( self.InfoDir, 'theaudiodbartistsalbums.nfo')
elif site == "lastfm":
filename = os.path.join( self.InfoDir, 'lastfmartistalbums.nfo')
if xbmcvfs.exists( filename ):
if time.time() - os.path.getmtime(filename) < 1209600:
lw.log( ['cached artist %s info found' % item] )
ForceUpdate = False
else:
lw.log( ['outdated cached info found for %s ' % item] )
if ForceUpdate:
lw.log( ['downloading artist %s info from %s' % (item, site)] )
if site == 'fanarttv' or site == 'theaudiodb':
#converts the JSON response to XML
success, loglines, json_data = JSONURL.Get( self.url, params=self.params )
self.params = {}
lw.log( loglines )
if success:
if site == 'fanarttv':
try:
images = json_data['artistbackground']
except Exception, e:
lw.log( ['error getting artist backgrounds from fanart.tv', e] )
images = []
if self.FANARTTVALLIMAGES == 'true':
try:
thumbs = json_data['artistthumb']
except Exception, e:
lw.log( ['error getting artist thumbs from fanart.tv', e] )
thumbs = []
images = images + thumbs
else:
images = json_data
success, loglines = writeFile( dicttoxml( images ).encode('utf-8'), filename )
lw.log( loglines )
json_data = ''
else:
return data
else:
success, loglines, urldata = txtURL.Get( self.url, params=self.params )
self.params = {}
lw.log( loglines )
if success:
success, loglines = writeFile( urldata, filename )
lw.log( loglines )
if not success:
return data
loglines, rawxml = readFile( filename )
lw.log( loglines )
if rawxml:
xmldata = _xmltree.fromstring( rawxml )
else:
deleteFile( filename )
return data
if item == "images":
if site == "fanarttv":
for element in xmldata.getiterator():
if element.tag == "url":
data.append(element.text)
elif site == "theaudiodb":
for element in xmldata.getiterator():
if element.tag.startswith( "strArtistFanart" ):
if element.text:
data.append(element.text)
if element.tag == 'idArtist' and not xbmcvfs.exists( id_filename ):
success, loglines = writeFile( element.text, id_filename )
lw.log( loglines )
elif site == "htbackdrops":
for element in xmldata.getiterator():
if element.tag == "id":
data.append(self.HtbackdropsDownloadURL + str( element.text ) + '/fullsize')
elif item == "bio":
if site == "theaudiodb":
for element in xmldata.getiterator():
if element.tag == "strBiography" + self.LANGUAGE.upper():
bio = element.text
if not bio:
bio = ''
data.append(bio)
if element.tag == 'idArtist' and not xbmcvfs.exists( id_filename ):
success, loglines = writeFile( element.text, id_filename )
lw.log( loglines )
if site == "lastfm":
for element in xmldata.getiterator():
if element.tag == "content":
bio = element.text
if not bio:
bio = ''
data.append(bio)
elif item == "similar":
if site == "lastfm":
for element in xmldata.getiterator():
if element.tag == "name":
name = element.text
name.encode('ascii', 'ignore')
elif element.tag == "image":
if element.attrib.get('size') == "mega":
image = element.text
if not image:
image = ''
data.append( ( name , image ) )
elif item == "albums":
if site == "theaudiodb":
match = False
for element in xmldata.getiterator():
if element.tag == "strAlbum":
name = element.text
name.encode('ascii', 'ignore')
match = True
elif element.tag == "strAlbumThumb" and match:
image = element.text
if not image:
image = ''
data.append( ( name , image ) )
match = False
if site == "lastfm":
match = False
for element in xmldata.getiterator():
if element.tag == "name":
if match:
match = False
else:
name = element.text
name.encode('ascii', 'ignore')
match = True
elif element.tag == "image":
if element.attrib.get('size') == "extralarge":
image = element.text
if not image:
image = ''
data.append( ( name , image ) )
if data == '':
lw.log( ['no %s found on %s' % (item, site)] )
return data
def _get_featured_artists( self, data ):
the_split = data.replace('ft.','feat.').split('feat.')
if len( the_split ) > 1:
return self._split_artists( the_split[-1] )
else:
return []
def _get_folder_size( self, start_path ):
total_size = 0
for dirpath, dirnames, filenames in os.walk( start_path ):
for f in filenames:
fp = os.path.join( dirpath, f )
total_size += os.path.getsize( fp )
return total_size
def _get_images( self, site ):
foundimages = False
if site == 'fanarttv':
if self.MBID:
self.url = self.fanarttvURL + self.MBID
self.params = self.fanarttvPARAMS
lw.log( ['asking for images from: %s' %self.url] )
else:
return []
elif site == 'theaudiodb':
if self.MBID:
self.url = self.theaudiodbARTISTURL
self.params['i'] = self.MBID
lw.log( ['asking for images from: %s' %self.url] )
else:
return []
elif site == "htbackdrops":
self.url = self.HtbackdropsQueryURL
if self.HTBACKDROPSALLIMAGES == 'true':
baseparams = {'cid':'5'}
else:
baseparams = {'aid':'1'}
if self.MBID:
additionalparams = {'mbid':self.MBID}
self.params = dict( baseparams.items() + additionalparams.items() )
lw.log( ['asking for images from: %s' %self.url] )
images = self._get_data(site, 'images')
if images:
foundimages = True
else:
success, loglines = deleteFile( os.path.join( self.InfoDir, 'htbackdropsartistimages.nfo') )
lw.log( loglines )
if not foundimages:
additionalparams = {'default_operator':'and', 'fields':'title', 'keywords':self.NAME.replace('&','%26')}
self.params = dict( baseparams.items() + additionalparams.items() )
lw.log( ['asking for images from: %s' %self.url] )
if not foundimages:
images = self._get_data(site, 'images')
return images
def _get_infolabel( self, item ):
try:
infolabel = xbmc.getInfoLabel( item )
except:
lw.log( ['problem reading information from %s, returning blank' % item] )
infolabel = ''
return infolabel
def _get_local_data( self, item ):
data = []
local_path = os.path.join( self.LOCALARTISTPATH, smartUTF8(self.NAME).decode('utf-8'), 'override' )
if item == "similar":
filename = os.path.join( local_path, 'artistsimilar.nfo' )
elif item == "albums":
filename = os.path.join( local_path, 'artistsalbums.nfo' )
elif item == "bio":
filename = os.path.join( local_path, 'artistbio.nfo' )
lw.log( ['checking filename ' + filename] )
loglines, rawxml = readFile( filename )
lw.log( loglines )
if rawxml:
xmldata = _xmltree.fromstring( rawxml )
else:
return []
if item == "bio":
for element in xmldata.getiterator():
if element.tag == "content":
bio = element.text
if not bio:
bio = ''
data.append(bio)
elif( item == "similar" or item == "albums" ):
for element in xmldata.getiterator():
if element.tag == "name":
name = element.text
name.encode('ascii', 'ignore')
elif element.tag == "image":
image_text = element.text
if not image_text:
image = ''
else:
image = os.path.join( local_path, item, image_text )
data.append( ( name , image ) )
if data == '':
lw.log( ['no %s found in local xml file' % item] )
return data
def _get_local_images( self ):
self.LocalImagesFound = False
if not self.NAME:
lw.log( ['no artist name provided'] )
return
self.CacheDir = os.path.join( self.LOCALARTISTPATH, smartUTF8(self.NAME).decode('utf-8'), self.FANARTFOLDER )
lw.log( ['cachedir = %s' % self.CacheDir] )
try:
dirs, files = xbmcvfs.listdir(self.CacheDir)
except OSError:
files = []
except Exception, e:
lw.log( ['unexpected error getting directory list', e] )
files = []
for file in files:
if file.lower().endswith('tbn') or file.lower().endswith('jpg') or file.lower().endswith('jpeg') or file.lower().endswith('gif') or file.lower().endswith('png'):
self.LocalImagesFound = True
if self.LocalImagesFound:
lw.log( ['local images found'] )
if self.ARTISTNUM == 1:
self._set_artwork_skininfo( self.CacheDir )
if self.ARTISTINFO == "true":
self._get_artistinfo()
if self.TOTALARTISTS > 1:
self._merge_images()
def _get_musicbrainz_id ( self, theartist ):
mbid = ''
lw.log( ['Looking for a musicbrainz ID for artist ' + theartist, 'Looking for musicbrainz ID in the musicbrainz.nfo file'] )
self._set_infodir( theartist )
filename = os.path.join( self.InfoDir, 'musicbrainz.nfo' )
if xbmcvfs.exists( filename ):
loglines, mbid = readFile( filename )
lw.log( loglines )
if not mbid:
if time.time() - os.path.getmtime(filename) < 1209600:
lw.log( ['no musicbrainz ID found in musicbrainz.nfo file'] )
return ''
else:
lw.log( ['no musicbrainz ID found in musicbrainz.nfo file, trying lookup again'] )
else:
lw.log( ['musicbrainz ID found in musicbrainz.nfo file'] )
return mbid
else:
lw.log( ['no musicbrainz.nfo file found'] )
if self._playback_stopped_or_changed():
success, loglines = writeFile( '', filename )
lw.log( loglines )
return ''
# this is here to account for songs or albums that have the artist 'Various Artists'
# because AS chokes when trying to find this artist on MusicBrainz
if theartist.lower() == 'various artists':
success, loglines = writeFile( self.VARIOUSARTISTSMBID, filename)
lw.log( loglines )
return self.VARIOUSARTISTSMBID
lw.log( ['querying musicbrainz.com for musicbrainz ID. This is about to get messy.'] )
badSubstrings = ["the ", "The ", "THE ", "a ", "A ", "an ", "An ", "AN "]
searchartist = theartist
for badSubstring in badSubstrings:
if theartist.startswith(badSubstring):
searchartist = theartist.replace(badSubstring, "")
mboptions = {"fmt":"json"}
mbsearch = 'artist:"%s"' % searchartist
query_times = {'last':0, 'current':time.time()}
lw.log( ['parsing musicbrainz response for muiscbrainz ID'] )
cached_mb_info = False
for artist in self._get_musicbrainz_info( mboptions, mbsearch, 'artist', 'artists', query_times ):
mbid = ''
if self._playback_stopped_or_changed():
return ''
try:
all_names = artist['aliases']
except KeyError:
all_names = []
except Exception, e:
lw.log( ['unexpected error getting JSON data from XBMC response', e] )
all_names = []
aliases = []
if all_names:
for one_name in all_names:
aliases.append( one_name['name'].lower() )
if artist['name'].lower() == theartist.lower() or theartist.lower() in aliases:
mbid = artist['id']
lw.log( ['found a potential musicbrainz ID of %s for %s' % (mbid, theartist)] )
playing_album = self._get_playing_item( 'album' )
if playing_album:
lw.log( ['checking album name against releases in musicbrainz'] )
query_times = {'last':query_times['current'], 'current':time.time()}
cached_mb_info = self._parse_musicbrainz_info( 'release', mbid, playing_album, query_times )
if not cached_mb_info:
playing_song = self._get_playing_item( 'title' )
if playing_song:
lw.log( ['checking song name against recordings in musicbrainz'] )
if smartUTF8( theartist ) == playing_song[0:(playing_song.find('-'))-1]:
playing_song = playing_song[(playing_song.find('-'))+2:]
query_times = {'last':query_times['current'], 'current':time.time()}
cached_mb_info = self._parse_musicbrainz_info( 'recording', mbid, playing_song, query_times )
if not cached_mb_info:
lw.log( ['checking song name against works in musicbrainz'] )
query_times = {'last':query_times['current'], 'current':time.time()}
cached_mb_info = self._parse_musicbrainz_info( 'work', mbid, playing_song, query_times )
if cached_mb_info:
break
else:
lw.log( ['No matching song/album found for %s. Trying the next artist.' % theartist] )
if cached_mb_info:
lw.log( ['Musicbrainz ID for %s is %s. writing out to cache file.' % (theartist, mbid)] )
else:
mbid = ''
lw.log( ['No musicbrainz ID found for %s. writing empty cache file.' % theartist] )
success, loglines = writeFile( mbid, filename )
lw.log( loglines )
return mbid
def _get_musicbrainz_info( self, mboptions, mbsearch, type, response_type, query_times ):
mbbase = 'http://www.musicbrainz.org/ws/2/'
theartist = self.NAME
mb_data = []
offset = 0
do_loop = True
elapsed_time = query_times['current'] - query_times['last']
if elapsed_time < 1:
self._wait( 1 - elapsed_time )
elif self._playback_stopped_or_changed():
return []
query_start = time.time()
while do_loop:
if mbsearch:
mbquery = mbbase + type
mboptions['query'] = mbsearch
else:
mbquery = mbbase + type[:-1]
mboptions['offset'] = str(offset)
lw.log( ['getting results from musicbrainz using: ' + mbquery] )
for x in range(1, 5):
success, loglines, json_data = mbURL.Get( mbquery, params=mboptions )
lw.log( loglines )
if self._playback_stopped_or_changed():
return []
if not success:
wait_time = random.randint(2,5)
lw.log( ['site unreachable, waiting %s seconds to try again.' % wait_time] )
self._wait( wait_time )
else:
try:
mb_data.extend( json_data[response_type] )
except KeyError:
lw.log( ['no valid value for %s found in JSON data' % type] )
offset = -100
except Exception, e:
lw.log( ['unexpected error while parsing JSON data', e] )
offset = -100
break
offset = offset + 100
try:
total_items = int(json_data[type[:-1] + '-count'])
except KeyError:
total_items = 0
except Exception, e:
lw.log( ['unexpected error getting JSON data from ' + mbquery, e] )
total_items = 0
if (not mbsearch) and (total_items - offset > 0):
lw.log( ['getting more data from musicbrainz'] )
query_elapsed = time.time() - query_start
if query_elapsed < 1:
self._wait(1 - query_elapsed)
elif self._playback_stopped_or_changed():
return []
else:
do_loop = False
return mb_data
def _get_playing_item( self, item ):
got_item = False
playing_item = ''
max_trys = 3
num_trys = 1
while not got_item:
try:
if item == 'album':
playing_item = xbmc.Player().getMusicInfoTag().getAlbum()
elif item == 'title':
playing_item = xbmc.Player().getMusicInfoTag().getTitle()
got_item = True
except RuntimeError:
got_title = False
except Exception, e:
got_title = False
lw.log( ['unexpected error getting %s from XBMC' % item, e] )
if num_trys > max_trys:
break
else:
num_trys = num_trys + 1
self._wait(1)
if self._playback_stopped_or_changed():
break
#if nothing is playing, assume the information was passed by another add-on
if not playing_item:
playing_item = self._get_infolabel( self.SKININFO[item] )
return playing_item
def _get_settings( self ):
self.FANARTTV = __addon__.getSetting( "fanarttv" )
self.FANARTTVALLIMAGES = __addon__.getSetting( "fanarttv_all" )
self.FANARTTVCLIENTAPIKEY = __addon__.getSetting( "fanarttv_clientapikey" )
self.THEAUDIODB = __addon__.getSetting( "theaudiodb" )
self.HTBACKDROPS = __addon__.getSetting( "htbackdrops" )
self.HTBACKDROPSALLIMAGES = __addon__.getSetting( "htbackdrops_all" )
self.ARTISTINFO = __addon__.getSetting( "artistinfo" )
self.LANGUAGE = __addon__.getSetting( "language" )
for language in LANGUAGES:
if self.LANGUAGE == language[2]:
self.LANGUAGE = language[1]
lw.log( ['language = %s' % self.LANGUAGE] )
break
self.LOCALARTISTPATH = __addon__.getSetting( "local_artist_path" ).decode('utf-8')
self.PRIORITY = __addon__.getSetting( "priority" )
self.USEFALLBACK = __addon__.getSetting( "fallback" )
self.FALLBACKPATH = __addon__.getSetting( "fallback_path" ).decode('utf-8')
self.USEOVERRIDE = __addon__.getSetting( "slideshow" )
self.OVERRIDEPATH = __addon__.getSetting( "slideshow_path" ).decode('utf-8')
self.RESTRICTCACHE = __addon__.getSetting( "restrict_cache" )
try:
self.maxcachesize = int(__addon__.getSetting( "max_cache_size" )) * 1000000
except ValueError:
self.maxcachesize = 1024 * 1000000
except Exception, e:
lw.log( ['unexpected error while parsing maxcachesize setting', e] )
self.maxcachesize = 1024 * 1000000
self.NOTIFICATIONTYPE = __addon__.getSetting( "show_progress" )
if self.NOTIFICATIONTYPE == "2":
self.PROGRESSPATH = __addon__.getSetting( "progress_path" ).decode('utf-8')
lw.log( ['set progress path to %s' % self.PROGRESSPATH] )
else:
self.PROGRESSPATH = ''
if __addon__.getSetting( "fanart_folder" ):
self.FANARTFOLDER = __addon__.getSetting( "fanart_folder" ).decode('utf-8')
lw.log( ['set fanart folder to %s' % self.FANARTFOLDER] )
else:
self.FANARTFOLDER = 'extrafanart'
def _init_vars( self ):
self.DATAROOT = xbmc.translatePath('special://profile/addon_data/%s' % __addonname__ ).decode('utf-8')
self.CHECKFILE = os.path.join( self.DATAROOT, 'migrationcheck.nfo' )
self._set_property( "ArtistSlideshow.CleanupComplete" )
self._set_property( "ArtistSlideshow.ArtworkReady" )
self.SKININFO = {}
for item in self.FIELDLIST:
if self.PASSEDFIELDS[item]:
self.SKININFO[item[0:-5]] = "Window(%s).Property(%s)" % ( self.WINDOWID, self.PASSEDFIELDS[item] )
else:
self.SKININFO[item[0:-5]] = ''
self.EXTERNALCALLSTATUS = self._get_infolabel( self.EXTERNALCALL )
lw.log( ['external call is set to ' + self._get_infolabel( self.EXTERNALCALL )] )
if __addon__.getSetting( "transparent" ) == 'true':
self._set_property("ArtistSlideshowTransparent", 'true')
self.InitDir = xbmc.translatePath('%s/resources/transparent' % __addonpath__ ).decode('utf-8')
else:
self._set_property("ArtistSlideshowTransparent", '')
self.InitDir = xbmc.translatePath('%s/resources/black' % __addonpath__ ).decode('utf-8')
self._set_property("ArtistSlideshow", self.InitDir)
self.NAME = ''
self.ALLARTISTS = []
self.MBID = ''
self.VARIOUSARTISTSMBID = '89ad4ac3-39f7-470e-963a-56509c546377'
self.LASTPLAYINGFILE = ''
self.LASTJSONRESPONSE = ''
self.LASTARTISTREFRESH = 0
self.LocalImagesFound = False
self.CachedImagesFound = False
self.ImageDownloaded = False
self.DownloadedAllImages = False
self.UsingFallback = False
self.MINREFRESH = 9.9
self.TransitionDir = xbmc.translatePath('special://profile/addon_data/%s/transition' % __addonname__ ).decode('utf-8')
self.MergeDir = xbmc.translatePath('special://profile/addon_data/%s/merge' % __addonname__ ).decode('utf-8')
LastfmApiKey = 'afe7e856e4f4089fc90f841980ea1ada'
fanarttvApiKey = '7a93c84fe1c9999e6f0fec206a66b0f5'
theaudiodbApiKey = '193621276b2d731671156g'
HtbackdropsApiKey = '96d681ea0dcb07ad9d27a347e64b652a'
self.params = {}
self.LastfmURL = 'http://ws.audioscrobbler.com/2.0/'
self.LastfmPARAMS = {'autocorrect':'1', 'api_key':LastfmApiKey}
self.fanarttvURL = 'https://webservice.fanart.tv/v3/music/'
self.fanarttvPARAMS = {'api_key': fanarttvApiKey}
if self.FANARTTVCLIENTAPIKEY:
self.fanarttvPARAMS.update( {'client_key': self.FANARTTVCLIENTAPIKEY} )
theaudiodbURL = 'http://www.theaudiodb.com/api/v1/json/%s/' % theaudiodbApiKey
self.theaudiodbARTISTURL = theaudiodbURL + 'artist-mb.php'
self.theaudiodbALBUMURL = theaudiodbURL + 'album.php'
self.HtbackdropsQueryURL = 'http://htbackdrops.org/api/%s/searchXML' % HtbackdropsApiKey
self.HtbackdropsDownloadURL = 'http://htbackdrops.org/api/' + HtbackdropsApiKey + '/download/'
def _init_window( self ):
self.WINDOW = xbmcgui.Window( int(self.WINDOWID) )
self.ARTISTSLIDESHOW = "Window(%s).Property(%s)" % ( self.WINDOWID, "ArtistSlideshow" )
self.ARTISTSLIDESHOWRUNNING = "Window(%s).Property(%s)" % ( self.WINDOWID, "ArtistSlideshowRunning" )
self.EXTERNALCALL = "Window(%s).Property(%s)" % ( self.WINDOWID, "ArtistSlideshow.ExternalCall" )
def _make_dirs( self ):
exists, loglines = checkPath( self.InitDir )
lw.log( loglines )
exists, loglines = checkPath( self.DATAROOT )
lw.log( loglines )
thedirs = ['temp', 'ArtistSlideshow', 'ArtistInformation', 'transition', 'merge']
for onedir in thedirs:
exists, loglines = checkPath( os.path.join( self.DATAROOT, onedir ) )
lw.log( loglines )
def _merge_images( self ):
lw.log( ['merging files from primary directory %s into merge directory %s' % (self.CacheDir, self.MergeDir)] )
self.MergedImagesFound = True
dirs, files = xbmcvfs.listdir(self.CacheDir)
for file in files:
if(file.lower().endswith('tbn') or file.lower().endswith('jpg') or file.lower().endswith('jpeg') or file.lower().endswith('gif') or file.lower().endswith('png')):
xbmcvfs.copy(os.path.join(self.CacheDir, smartUTF8(file).decode('utf-8')), os.path.join(self.MergeDir, smartUTF8(file).decode('utf-8')))
if self.ARTISTNUM == self.TOTALARTISTS:
wait_elapsed = time.time() - self.LASTARTISTREFRESH
if( wait_elapsed > self.MINREFRESH ):
self._wait( self.MINREFRESH - (wait_elapsed % self.MINREFRESH) )
else:
self._wait( self.MINREFRESH - (wait_elapsed + 2) ) #not sure why there needs to be a manual adjustment here
if not self._playback_stopped_or_changed():
lw.log( ['switching slideshow to merge directory'] )
self._set_artwork_skininfo( self.MergeDir )
def _migrate_info_files( self ):
#this is a one time process to move and rename all the .nfo files to the new location
new_loc = os.path.join( self.DATAROOT, 'ArtistInformation' )
self._move_info_files( os.path.join(self.DATAROOT, 'ArtistSlideshow'), new_loc, 'cache' )
if self.LOCALARTISTPATH:
self._move_info_files( self.LOCALARTISTPATH, new_loc, 'local' )
self._update_check_file( '1.5.4', 'migration of artist info files complete' )
def _migrate_tbn_files( self ):
#one time process to rename all the tbn files to the appropriate extensions based on image type
self._rename_tbn_files( os.path.join( self.DATAROOT, 'ArtistSlideshow' ), 'cache' )
if self.LOCALARTISTPATH:
self._rename_tbn_files( self.LOCALARTISTPATH, 'local' )
self._update_check_file( '1.6.0', 'renaming of tbn files compete' )
def _move_info_files( self, old_loc, new_loc, type ):
lw.log( ['attempting to move from %s to %s' % (old_loc, new_loc)] )
try:
folders, fls = xbmcvfs.listdir( old_loc )
except OSError:
lw.log( ['no directory found: ' + old_loc] )
return
except Exception, e:
lw.log( ['unexpected error while getting directory list', e] )
return
for folder in folders:
if type == 'cache':
old_folder = os.path.join( old_loc, folder )
new_folder = os.path.join( new_loc, folder )
elif type == 'local':
old_folder = os.path.join( old_loc, smartUTF8(folder).decode('utf-8'), self.FANARTFOLDER )
new_folder = os.path.join( new_loc, itemHash(folder) )
try:
dirs, old_files = xbmcvfs.listdir( old_folder )
except Exception, e:
lw.log( ['unexpected error while getting directory list', e] )
old_files = []
exclude_path = os.path.join( old_folder, '_exclusions.nfo' )
if old_files and type == 'cache' and not xbmcvfs.exists(exclude_path):
success, loglines = writeFile( '', exclude_path )
lw.log( loglines )
for old_file in old_files:
if old_file.endswith( '.nfo' ) and not old_file == '_exclusions.nfo':
exists, loglines = checkPath( new_folder )
lw.log( loglines )
new_file = old_file.strip('_')
if new_file == 'artistimagesfanarttv.nfo':
new_file = 'fanarttvartistimages.nfo'
elif new_file == 'artistimageshtbackdrops.nfo':
new_file = 'htbackdropsartistimages.nfo'
elif new_file == 'artistimageslastfm.nfo':
new_file = 'lastfmartistimages.nfo'
elif new_file == 'artistbio.nfo':
new_file = 'lastfmartistbio.nfo'
elif new_file == 'artistsalbums.nfo':
new_file = 'lastfmartistalbums.nfo'
elif new_file == 'artistsimilar.nfo':
new_file = 'lastfmartistsimilar.nfo'
xbmcvfs.rename( os.path.join(old_folder, old_file), os.path.join(new_folder, new_file) )
lw.log( ['moving %s to %s' % (old_file, os.path.join(new_folder, new_file))] )
def _parse_argv( self ):
try:
params = dict( arg.split( "=" ) for arg in sys.argv[ 1 ].split( "&" ) )
except IndexError:
params = {}
except Exception, e:
lw.log( ['unexpected error while parsing arguments', e] )
params = {}
self.WINDOWID = params.get( "windowid", "12006")
lw.log( ['window id is set to %s' % self.WINDOWID] )
self.PASSEDFIELDS = {}
self.FIELDLIST = ['artistfield', 'titlefield', 'albumfield', 'mbidfield']
for item in self.FIELDLIST:
self.PASSEDFIELDS[item] = params.get( item, '' )
lw.log( ['%s is set to %s' % (item, self.PASSEDFIELDS[item])] )
self.DAEMON = params.get( "daemon", "False" )
if self.DAEMON == "True":
lw.log( ['daemonizing'] )
def _parse_musicbrainz_info( self, type, mbid, playing_thing, query_times ):
if self._playback_stopped_or_changed():
return False
lw.log( ["checking this artist's " + type + "s against currently playing " + type] )
mboptions = {"artist":mbid, "limit":"100", "fmt":"json"}
for thing in self._get_musicbrainz_info( mboptions, '', type + 's', type + 's', query_times ):
title = smartUTF8( thing['title'] )
if playing_thing.rfind('(') > 0:
playing_title = smartUTF8( playing_thing[:playing_thing.rfind('(')-2] )
else:
playing_title = smartUTF8( playing_thing )
lw.log( ['comparing musicbrainz %s: %s with local %s: %s' % (type, title, type, playing_title)] )
if title.lower().startswith( playing_title.lower() ) or playing_title.lower().startswith( title.lower() ):
lw.log( ['found matching %s, this should be the right artist' % type] )
return True
return False
def _playback_stopped_or_changed( self ):
if set( self.ALLARTISTS ) <> set( self._get_current_artists() ) or self.EXTERNALCALLSTATUS != self._get_infolabel( self.EXTERNALCALL ):
self._clear_properties()
return True
else:
return False
def _refresh_image_directory( self ):
if( self._get_infolabel( self.ARTISTSLIDESHOW ).decode('utf-8') == self.TransitionDir):
self._set_artwork_skininfo( self.CacheDir )
lw.log( ['switching slideshow to ' + self.CacheDir] )
else:
self._set_artwork_skininfo( self.TransitionDir )
lw.log( ['switching slideshow to ' + self.TransitionDir] )
self.LASTARTISTREFRESH = time.time()
lw.log( ['Last slideshow refresh time is ' + str(self.LASTARTISTREFRESH)] )
def _rename_tbn_files( self, loc, type ):
lw.log( ['attempting to rename .tbn files with correct extension', 'from location: ' + loc] )
try:
folders, fls = xbmcvfs.listdir( loc )
except OSError:
lw.log( ['no directory found: ' + loc] )
return
except Exception, e:
lw.log( ['unexpected error while getting directory list', e] )
return
for folder in folders:
lw.log( ['checking ' + folder] )
if type == 'cache':
thepath = os.path.join( loc, smartUTF8(folder).decode('utf-8') )
elif type == 'local':
thepath = os.path.join( loc, smartUTF8(folder).decode('utf-8'), self.FANARTFOLDER )
try:
dirs, files = xbmcvfs.listdir( thepath )
except Exception, e:
lw.log( ['unexpected error while getting file list', e] )
files = []
for file in files:
if file.endswith( '.tbn' ):
old_path = os.path.join( thepath, file )
new_file = file.replace( '.tbn', getImageType( old_path ) )
new_path = os.path.join( thepath, new_file )
xbmcvfs.rename( old_path, new_path )
lw.log( ['renaming %s to %s' % (old_path, new_path)] )
lw.log( ['finished renaming .tbn files with correct extension'] )
def _set_artwork_skininfo( self, dir ):
self._set_property("ArtistSlideshow", dir)
self._set_property("ArtistSlideshow.ArtworkReady", "true")
def _set_cachedir( self, theartist ):
self.CacheDir = self._set_thedir( theartist, "ArtistSlideshow" )
def _set_infodir( self, theartist ):
self.InfoDir = self._set_thedir( theartist, "ArtistInformation" )
def _set_properties( self ):
self._set_property("ArtistSlideshow.ArtistBiography", self.biography)
for count, item in enumerate( self.similar ):
self._set_property("ArtistSlideshow.%d.SimilarName" % ( count + 1 ), item[0])
self._set_property("ArtistSlideshow.%d.SimilarThumb" % ( count + 1 ), item[1])
for count, item in enumerate( self.albums ):
self._set_property("ArtistSlideshow.%d.AlbumName" % ( count + 1 ), item[0])
self._set_property("ArtistSlideshow.%d.AlbumThumb" % ( count + 1 ), item[1])
def _set_property( self, property_name, value=""):
#sets a property (or clears it if no value is supplied)
#does not crash if e.g. the window no longer exists.
try:
self.WINDOW.setProperty(property_name, value)
lw.log( ['%s set to %s' % (property_name, value)] )
except Exception, e:
lw.log( ["Exception: Couldn't set propery " + property_name + " value " + value , e])
def _set_thedir(self, theartist, dirtype):
CacheName = itemHash(theartist)
thedir = xbmc.translatePath('special://profile/addon_data/%s/%s/%s/' % ( __addonname__ , dirtype, CacheName, )).decode('utf-8')
exists, loglines = checkPath( thedir )
lw.log( loglines )
return thedir
def _split_artists( self, response):
return response.replace('ft.',' / ').replace('feat.',' / ').split(' / ')
def _start_download( self ):
self.CachedImagesFound = False
self.DownloadedFirstImage = False
self.DownloadedAllImages = False
self.ImageDownloaded = False
self.FirstImage = True
cached_image_info = False
if not self.NAME:
lw.log( ['no artist name provided'] )
return
if self.PRIORITY == '2' and self.LocalImagesFound:
pass
#self.CacheDir was successfully set in _get_local_images
else:
self._set_cachedir( self.NAME )
lw.log( ['cachedir = %s' % self.CacheDir] )
dirs, files = xbmcvfs.listdir(self.CacheDir)
for file in files:
if (file.lower().endswith('tbn') or file.lower().endswith('jpg') or file.lower().endswith('jpeg') or file.lower().endswith('gif') or file.lower().endswith('png')) or (self.PRIORITY == '2' and self.LocalImagesFound):
self.CachedImagesFound = True
if self.CachedImagesFound:
lw.log( ['cached images found'] )
cached_image_info = True
self.LASTARTISTREFRESH = time.time()
if self.ARTISTNUM == 1:
self._set_artwork_skininfo( self.CacheDir )
if self.ARTISTINFO == "true":
self._get_artistinfo()
else:
self.LASTARTISTREFRESH = 0
if self.ARTISTNUM == 1:
for cache_file in ['fanarttvartistimages.nfo', 'theaudiodbartistbio.nfo', 'htbackdropsartistimages.nfo']:
filename = os.path.join( self.InfoDir, cache_file.decode('utf-8') )
if xbmcvfs.exists( filename ):
if time.time() - os.path.getmtime(filename) < 1209600:
lw.log( ['cached %s found' % filename] )
cached_image_info = True
else:
lw.log( ['outdated %s found' % filename] )
cached_image_info = False
if self.NOTIFICATIONTYPE == "1":
self._set_property("ArtistSlideshow", self.InitDir)
if not cached_image_info:
command = 'XBMC.Notification(%s, %s, %s, %s)' % (smartUTF8(__language__(30300)), smartUTF8(__language__(30301)), 5000, smartUTF8(__addonicon__))
xbmc.executebuiltin(command)
elif self.NOTIFICATIONTYPE == "2":
if not cached_image_info:
self._set_property("ArtistSlideshow", self.PROGRESSPATH)
else:
self._set_property("ArtistSlideshow", self.InitDir)
else:
self._set_property("ArtistSlideshow", self.InitDir)
sourcelist = []
sourcelist.append( ['fanarttv', self.FANARTTV] )
sourcelist.append( ['theaudiodb', self.THEAUDIODB] )
sourcelist.append( ['htbackdrops', self.HTBACKDROPS] )
imagelist = []
for source in sourcelist:
lw.log( ['checking the source %s with a value of %s.' % (source[0], source[1])] )
if source[1] == "true":
imagelist.extend( self._get_images(source[0]) )
lw.log( ['downloading images'] )
folders, cachelist = xbmcvfs.listdir( self.CacheDir )
cachelist_str = ''.join(str(e) for e in cachelist)
for url in imagelist:
if( self._playback_stopped_or_changed() ):
return
path = itemHashwithPath( url, self.CacheDir )
path2 = itemHashwithPath( url, self.TransitionDir )
checkpath, checkfilename = os.path.split( path )
if not (checkfilename in cachelist_str):
if self._download(url, path, path2):
lw.log( ['downloaded %s to %s' % (url, path)] )
self.ImageDownloaded = True
elif self._excluded( path ):
indicies = [i for i, elem in enumerate(cachelist) if checkfilename in elem]
success, loglines = deleteFile( os.path.join( checkpath, cachelist[indicies[0]] ) )
lw.log( loglines )
if self.ImageDownloaded:
if( self._playback_stopped_or_changed() and self.ARTISTNUM == 1 ):
self._set_artwork_skininfo( self.CacheDir )
self.LASTARTISTREFRESH = time.time()
self._clean_dir( self.TransitionDir )
return
if not self.CachedImagesFound:
self.CachedImagesFound = True
if self.ARTISTINFO == "true" and self.ARTISTNUM == 1:
self._get_artistinfo()
wait_elapsed = time.time() - self.LASTARTISTREFRESH
if( wait_elapsed > self.MINREFRESH ):
if( not (self.FirstImage and not self.CachedImagesFound) ):
self._wait( self.MINREFRESH - (wait_elapsed % self.MINREFRESH) )
if( not self._playback_stopped_or_changed() and self.ARTISTNUM == 1 ):
self._refresh_image_directory()
self.FirstImage = False
if self.ImageDownloaded:
lw.log( ['finished downloading images'] )
self.DownloadedAllImages = True
if( self._playback_stopped_or_changed() ):
self._set_artwork_skininfo( self.CacheDir )
self.LASTARTISTREFRESH = time.time()
self._clean_dir( self.TransitionDir )
return
lw.log( ['cleaning up from refreshing slideshow'] )
wait_elapsed = time.time() - self.LASTARTISTREFRESH
if( wait_elapsed < self.MINREFRESH ):
self._wait( self.MINREFRESH - wait_elapsed )
if( not self._playback_stopped_or_changed() ):
if self.ARTISTNUM == 1:
self._refresh_image_directory()
if self.NOTIFICATIONTYPE == "1" and not cached_image_info:
command = 'XBMC.Notification(%s, %s, %s, %s)' % (smartUTF8(__language__(30304)), smartUTF8(__language__(30305)), 5000, smartUTF8(__addonicon__))
xbmc.executebuiltin(command)
if self.TOTALARTISTS > 1:
self._merge_images()
if( self._get_infolabel( self.ARTISTSLIDESHOW ).decode('utf-8') == self.TransitionDir and self.ARTISTNUM == 1):
self._wait( self.MINREFRESH )
if( not self._playback_stopped_or_changed() ):
self._refresh_image_directory()
self._clean_dir( self.TransitionDir )
if not self.ImageDownloaded:
lw.log( ['no images downloaded'] )
self.DownloadedAllImages = True
if not self.CachedImagesFound:
if self.ARTISTNUM == 1:
lw.log( ['setting slideshow directory to blank directory'] )
self._set_property("ArtistSlideshow", self.InitDir)
if self.NOTIFICATIONTYPE == "1" and not cached_image_info:
command = 'XBMC.Notification(%s, %s, %s, %s)' % (smartUTF8(__language__(30302)), smartUTF8(__language__(30303)), 10000, smartUTF8(__addonicon__))
xbmc.executebuiltin(command)
if( self.ARTISTINFO == "true" and not self._playback_stopped_or_changed() ):
self._get_artistinfo()
elif self.TOTALARTISTS > 1:
self._merge_images()
def _trim_cache( self ):
if( self.RESTRICTCACHE == 'true' and not self.PRIORITY == '2' ):
now = time.time()
cache_trim_delay = 0 #delay time is in seconds
if( now - self.LastCacheTrim > cache_trim_delay ):
lw.log( ['trimming the cache down to %s bytes' % self.maxcachesize] )
cache_root = xbmc.translatePath( 'special://profile/addon_data/%s/ArtistSlideshow/' % __addonname__ ).decode('utf-8')
folders, fls = xbmcvfs.listdir( cache_root )
folders.sort( key=lambda x: os.path.getmtime( os.path.join ( cache_root, x ) ), reverse=True )
cache_size = 0
first_folder = True
for folder in folders:
if( self._playback_stopped_or_changed() ):
break
cache_size = cache_size + self._get_folder_size( os.path.join (cache_root, folder ) )
lw.log( ['looking at folder %s cache size is now %s' % (folder, cache_size)] )
if( cache_size > self.maxcachesize and not first_folder ):
self._clean_dir( os.path.join(cache_root, folder) )
lw.log( ['deleted files in folder %s' % folder] )
first_folder = False
self.LastCacheTrim = now
def _use_correct_artwork( self ):
self.ALLARTISTS = self._get_current_artists()
self.ARTISTNUM = 0
self.TOTALARTISTS = len( self.ALLARTISTS )
self.MergedImagesFound = False
for artist, mbid in self._get_current_artists_info( 'withmbid' ):
lw.log( ['current artist is %s with a mbid of %s' % (artist, mbid)] )
self.ARTISTNUM += 1
self.NAME = artist
self.MBID = mbid
self._set_infodir( self.NAME )
if self.USEOVERRIDE == 'true':
lw.log( ['using override directory for images'] )
self._set_property("ArtistSlideshow", self.OVERRIDEPATH)
self._set_artwork_skininfo( self.OVERRIDEPATH )
if(self.ARTISTNUM == 1):
self._get_artistinfo()
elif self.PRIORITY == '1' and self.LOCALARTISTPATH:
lw.log( ['looking for local artwork'] )
self._get_local_images()
if not self.LocalImagesFound:
lw.log( ['no local artist artwork found, start download'] )
self._start_download()
elif self.PRIORITY == '2' and self.LOCALARTISTPATH:
lw.log( ['looking for local artwork'] )
self._get_local_images()
lw.log( ['start download'] )
self._start_download()
else:
lw.log( ['start download'] )
self._start_download()
if not (self.CachedImagesFound or self.ImageDownloaded):
lw.log( ['no remote artist artwork found, looking for local artwork'] )
self._get_local_images()
if not (self.LocalImagesFound or self.CachedImagesFound or self.ImageDownloaded or self.MergedImagesFound):
if (self.USEFALLBACK == 'true'):
lw.log( ['no images found for artist, using fallback slideshow'] )
lw.log( ['fallbackdir = ' + self.FALLBACKPATH] )
self.UsingFallback = True
self._set_property("ArtistSlideshow", self.FALLBACKPATH)
self._set_artwork_skininfo( self.FALLBACKPATH )
def _update_check_file( self, version, message ):
success, loglines = writeFile( version, self.CHECKFILE )
lw.log( loglines )
if success:
lw.log( [message] )
def _upgrade( self ):
#this is where any code goes for one time upgrade routines
loglines, data = readFile( self.CHECKFILE )
lw.log( loglines )
if not data:
self._migrate_info_files()
loglines, data = readFile( self.CHECKFILE )
if data == '1.5.4':
self._migrate_tbn_files()
def _wait( self, wait_time ):
waited = 0
while( waited < wait_time ):
time.sleep(0.1)
waited = waited + 0.1
if self._playback_stopped_or_changed():
self._set_property( "ArtistSlideshow", self.InitDir )
self._set_property( "ArtistSlideshow.ArtworkReady" )
self.Abort = True
return
if ( __name__ == "__main__" ):
lw.log( ['script version %s started' % __addonversion__], xbmc.LOGNOTICE )
lw.log( ['debug logging set to %s' % __logdebug__], xbmc.LOGNOTICE )
slideshow = Main()
lw.log( ['script stopped'], xbmc.LOGNOTICE )
Jump to Line
Something went wrong with that request. Please try again.