# -*- coding: utf-8 -*-
#######################################################################
#
#    YAMP - Yet Another Music Player - Lyrics
#    Version 3.2.2 2021-05-10
#    Coded by  by AlfredENeumann (c)2016-2021
#    Support: www.vuplus-support.org, board.newnigma2.to
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of the GNU General Public License
#    as published by the Free Software Foundation; either version 2
#    of the License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#######################################################################

from YampGlobals import *

from Components.ConfigList import ConfigListScreen
from Components.FileList import FileList
#from Components.Sources.StaticText import StaticText   #!!!!!neu

from Components.Pixmap import Pixmap, MultiPixmap
from Components.ScrollLabel import ScrollLabel

#from Screens.InfoBarGenerics import InfoBarSeek #, InfoBarNotifications
from Screens.HelpMenu import HelpableScreen
#from Screens.VirtualKeyBoard import VirtualKeyBoard

from twisted.web.client import downloadPage, getPage

from urllib import quote, quote_plus, unquote
from xml.etree.cElementTree import fromstring as xml_fromstring

#Lyricslist

from Components.GUIComponent import GUIComponent
from Components.MultiContent import MultiContentEntryText

from enigma import eListboxPythonMultiContent, eListbox, gFont, RT_VALIGN_CENTER, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_HALIGN_CENTER

from skin import parseFont, parsePosition, parseSize
from enigma import fontRenderClass

import mutagen
from mutagen.apev2 import APEv2
from mutagen.easyid3 import EasyID3
from mutagen.easymp4 import EasyMP4
from mutagen.flac import Picture, FLAC, StreamInfo
from mutagen.id3 import ID3
from mutagen.mp3 import MP3
from mutagen.oggvorbis import OggVorbis

# our own modules
from __init__ import _
from YampConfig import YampConfigScreenV31
from YampPixmaps import YampCoverArtPixmap, YampScreenSaver
from YampBoxDisplay import *

GETLYRICSTIMEOUT = 10

#class YampLyricsScreenV32(Screen, InfoBarSeek):
class YampLyricsScreenV32(Screen):
	def __init__(self, session, parent):
		Screen.__init__(self, session)
		with open(os.path.join(yampDir, "skins", config.plugins.yampmusicplayer.yampSkin.value, "YampLyrics.xml"), 'r') as f:
			self.skin = f.read()

		self.parent = parent
		self.oldskin = config.plugins.yampmusicplayer.yampSkin.value == 'default265' or config.plugins.yampmusicplayer.yampSkin.value == 'transparent'

		self["title"] = Label(_("YAMP Music Player Lyrics"))
		self.lyricslist = YampLyricsList()
		self.lyrics=''
		if self.oldskin: self["lyrics"] = ScrollLabel(self.lyrics)
		else: self["lyrics"] = self.lyricslist
		
		self["songtitle"] = Label ("")
		self["artist"] = Label ("")
		self["album"] = Label ("")
		self["Length"] = Label(_("length"))
		self["length"] = Label("")
		self["Tracknr"] = Label(_("Track-No"))
		self["tracknr"] = Label("")
		self["bitrate"] = Label("")

		self["providedby"] = Label (_("songtext provided by:"))
		self["provider"] = MultiPixmap()
		self["coverArt"] = YampCoverArtPixmap()
		self["cprovidedby"] = Label (_("Cover provided by:"))
		self["cprovider"] = MultiPixmap()
		
		self["key_red"] = Label (_("Exit"))
		self["key_green"] = Label ("")
		self["key_yellow"] = Label ("")
		self["key_blue"] = Label ("")

		if self.oldskin:
			self["actions"] = ActionMap(["YampActions", "YampOtherActions"], 
			{
				"exit": self.keyExit,
				"red": self.keyExit,
				"up": self["lyrics"].pageUp,
				"down": self["lyrics"].pageDown,
				"green": self.keyGreen,
			}, -1)
		else:
			self["actions"] = ActionMap(["YampActions", "YampOtherActions"], 
			{
				"exit": self.keyExit,
				"red": self.keyExit,
				"ok": self.ok,
				"play": self.play,
				"pause": self.pause,
				"prevTitle": self.previousEntry,
				"nextTitle": self.nextEntry,
				"up": self.moveup,
				"down": self.movedown,
				"green": self.keyGreen,
				"yellow": self.keyYellow,
				"blue": self.keyBlue,
			}, -1)
			self["seekactions"] = ActionMap(["YampSeekSubActions"], 
			{
				"key1": self.key1,
				"key3": self.key3,
				"key4": self.key4,
				"key6": self.key6,
				"key7": self.key7,
				"key9": self.key9,
			}, -2)

#		InfoBarSeek.__init__(self, actionmap = "YampSeekActions")
		
#		if config.plugins.yampmusicplayer.yampRemote.value == 'default':
		
#				"right" : (self.pagedown, _("Next page, Screensaver: next slide")),
#				"left" : (self.pageup, _("Previous page, Screensaver: previous slide")),

#				"prevBouquet": (self.pagedownspecial, _("Next page")),
#				"nextBouquet" : (self.pageupspecial, _("Previous page")),
		
		self.onLayoutFinish.append(self.layoutFinished)
		self.onClose.append(self.cleanup)

		self.isDreamOS = os.path.exists("/var/lib/dpkg/status")
		self.triggerTimer = eTimer()
		if self.isDreamOS: self.triggerTimer_conn=self.triggerTimer.timeout.connect(self.triggerStartActions)
		else: self.triggerTimer.callback.append(self.triggerStartActions)
		self.updateTimer = eTimer()
		if self.isDreamOS: self.updateTimer_conn=self.updateTimer.timeout.connect(self.updateInfoCyclic)
		else: self.updateTimer.callback.append(self.updateInfoCyclic)
		self.updateCoverTimer = eTimer()
		if self.isDreamOS: self.updateCoverTimer_conn=self.updateCoverTimer.timeout.connect(self.updateCoverCyclic)
		else: self.updateCoverTimer.callback.append(self.updateCoverCyclic)
		self.lyricsAutoSaveTimer = eTimer()
		if self.isDreamOS: self.lyricsAutoSaveTimer_conn=self.lyricsAutoSaveTimer.timeout.connect(self.autoSaveLyrics)
		else: self.lyricsAutoSaveTimer.callback.append(self.autoSaveLyrics)
##		self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
##			{
##				iPlayableService.evEnd : self.serviceStopped,
#				iPlayableService.evUpdatedInfo : self.updateInfoCyclic,
##			})
		self.LcdText=''
		self.offsetJump = 0
		self.autoMoveOn = True
		self.allowTimeEdit = False
		self.songPos = 0
		self.scrollMinLines = config.plugins.yampmusicplayer.lyricsMinLinesScroll.value
		self.scrollLine = config.plugins.yampmusicplayer.lyricsScrollLine.value - 1
		self.timeStampOffset = config.plugins.yampmusicplayer.lyricsOffsetTime.value  #milliseconds offset
		self.timeStampChanged = False
		self.lyricsFileName=''
		self.pixNumCover = COVERS_NO
		self.coverArtFile = ''
		self.pixNumCoverOld = COVERS_NO
		self.coverArtFileOld = ''
		self.pixNumLyrics = LYRICSS_NO
		self.coverTestMode = config.plugins.yampmusicplayer.yampCoverLyricsTestMode.value
		self.lyricsFoundPrio = LYRICSS_NO

		self.lastAutosaveFilename = ''
		self.lastAutosaveTime = 0.0
		self.lastAutosavePrio = LYRICSS_NO
		self.savedMessageType = MessageBox.TYPE_INFO

		self.replaceText = self.parent.infoBarNaReplace
		self.waitForSaveAnswer = False
		
	def layoutFinished(self):
		try:
			self.setSongInfo()
		except:
			LOG('YampLyricsScreen: layoutFinished: currTitle: EXCEPT', 'err') 
		
		self.setTextGreenKey()
		self.setTextYellowKey()
		self.setTextBlueKey()

		self.triggerTimer.start(50,True)
		self.updateTimer.start(200,False)		#for autoMove
		self.updateCoverTimer.start(618,False)		#for update Covers - Test 2
		
#		LOG('YampLyricsScreen: layoutFinished: before getLyrics: self.lyrics: *%s*' %(self.lyrics), 'all')
#		LOG('YampLyricsScreen: layoutFinished: before getLyrics', 'all')
		try:
			self.getLyrics()
		except:
			LOG('YampLyricsScreen: layoutFinished: self.getLyrics: EXCEPT', 'err')
		try:
			self.buildNewLyrics()
#			LOG('YampLyricsScreen: layoutFinished: self.txtLines: %s' %(self.txtLines), 'err') ###Test
		except:
			LOG('YampLyricsScreen: layoutFinished: buildNewLyrics: EXCEPT', 'err') 
		try:
			self.lyricslist.selectionEnabled(1)
		except:
			LOG('YampLyricsScreen: layoutFinished: selectionEnabled: EXCEPT', 'err') 
		try:
			if not self.oldskin: self.lyricslist.moveToIndex(0)
		except:
			LOG('YampLyricsScreen: layoutFinished: moveToIndex: EXCEPT', 'err') 

	def key1(self):
		self.parent.seekOwn(1)

	def key3(self):
		self.parent.seekOwn(3)

	def key4(self):
		self.parent.seekOwn(4)

	def key6(self):
		self.parent.seekOwn(6)

	def key7(self):
		self.parent.seekOwn(7)

	def key9(self):
		self.parent.seekOwn(9)

	def keyPrevious(self):
		self.parent.seekOwn(11)

	def keyNext(self):
		self.parent.seekOwn(12)
			
			
	def lyricsChanged(self):
		LOG('\nYampLyricsScreen: lyricsChanged: Start: pixNumLyrics: %d' %(self.pixNumLyrics), 'all')
		try:
			if not self.oldskin: self["provider"].setPixmapNum(self.pixNumLyrics % LYRICSS_NO)
		except:
			LOG('YampLyricsScreen: lyricsChanged: setPixmapNum: EXCEPT', 'err')
		try:
			self.buildNewLyrics()
		except:
			LOG('YampLyricsScreen: lyricsChanged: buildNewLyrics: EXCEPT', 'err')
		self.setTextGreenKey()
			
#
# Show Lyrics methods
#
# 1. Look for lyrics in ID3 tag (for mp3s, flac), 2. Look for lyrics in lyrics directory, 3. Search lyrics with chartlyrics.com

	def getLyrics(self):
		LOG('YampLyricsScreen: getLyrics: Start', 'all')
		self.pixNumLyrics = LYRICSS_NO
		self.lyricsFoundPrio = LYRICSS_NO
		self.lyrics = _("Sorry, (still) no lyrics found")
		try:
			songFilename = self.parent.playlist.getServiceRefList()[self.parent.playlist.getCurrentIndex()].getPath()
			if config.plugins.yampmusicplayer.useSingleLyricsPath.value:
				self.lyricsFileName = os.path.join(config.plugins.yampmusicplayer.lyricsPath.value, os.path.basename(os.path.splitext(songFilename)[0] + ".txt"))
				self.lyricsFileNameLrc = os.path.join(config.plugins.yampmusicplayer.lyricsPath.value, os.path.basename(os.path.splitext(songFilename)[0] + ".lrc"))
			else:
				self.lyricsFileName = os.path.splitext(songFilename)[0] + ".txt"
				self.lyricsFileNameLrc = os.path.splitext(songFilename)[0] + ".lrc"
			LOG('YampLyricsScreen: getLyrics: songFilename: %s lyricsFileName: %s' %(songFilename,self.lyricsFileName), 'all')
			LOG('YampLyricsScreen: getLyrics: songFilename: %s lyricsFileName: %s' %(songFilename,self.lyricsFileNameLrc), 'all')
#			LOG('YampLyricsScreen: getLyrics: songFilename: %s lyricsFileName: %s' %(songFilename,self.lyricsFileName), 'err')
#			LOG('YampLyricsScreen: getLyrics: songFilename: %s lyricsFileName: %s' %(songFilename,self.lyricsFileNameLrc), 'err')
		except:
			LOG('YampLyricsScreen: getLyrics: Start: EXCEPT', 'err')
		
		prio1 = config.plugins.yampmusicplayer.prioLyrics1.value
		prio2 = config.plugins.yampmusicplayer.prioLyrics2.value
		prio3 = config.plugins.yampmusicplayer.prioLyrics3.value
		prio4 = config.plugins.yampmusicplayer.prioLyrics4.value
		LOG('YampLyricsScreen: getLyrics: prio: %s %s %s %s' %(prio1,prio2,prio3,prio4), 'all')
#		LOG('YampLyricsScreen: getLyrics: prio: %s %s %s %s' %(prio1,prio2,prio3,prio4), 'spe2')

		self.searchId3(songFilename, prio1, prio2, prio3, prio4)
		LOG('YampLyricsScreen: getLyrics: before searchfile', 'all')
		self.searchFile(prio1, prio2, prio3, prio4)
		LOG('YampLyricsScreen: getLyrics: before lyricsChanged', 'all')
		self.lyricsChanged()
		LOG('YampLyricsScreen: getLyrics: before searchChartlyrics', 'all')
#		LOG('YampLyricsScreen: getLyrics: before searchChartlyrics', 'spe2')
		self.searchChartlyrics(prio1, prio2, prio3, prio4)
		LOG('YampLyricsScreen: getLyrics: before searchGeniuslyrics', 'all')
#		LOG('YampLyricsScreen: getLyrics: before searchGeniuslyrics', 'spe2')
		self.searchGeniuslyrics(prio1, prio2, prio3, prio4)

	#Lyrics search genius.com
	def searchGeniuslyrics(self,prio1,prio2,prio3,prio4):
		if prio1 == 'lyricsGenius': prio = 1
		elif prio2 == 'lyricsGenius': prio = 2
		elif prio3 == 'lyricsGenius': prio = 3
		elif prio4 == 'lyricsGenius': prio = 4
		else: return

		LOG('YampLyricsScreen: searchGeniuslyrics: prio: %d  lyricsFoundPrio: %d' %(prio,self.lyricsFoundPrio), 'all')
		if self.lyricsFoundPrio < prio: return		#already found with higher priority

		artist_name = self.artist.replace("'","*abc*abc*").lower()			
		try:
			artist_name = re.sub('\([^)]*\)','', artist_name) 	#remove everything between brackets
		except:
			LOG('YampLyricsScreen: searchGeniuslyrics: artist name remove brackets: EXCEPT', 'err')
##		artist_name = self.artist.replace("'","#*#*").lower()			
##		artist_name = artist_name.replace("p!nk","pink")			
		song_title = self.songtitle.replace("'","")
		try:
			song_title = re.sub('\([^)]*\)','', song_title) 	#remove everything between brackets
		except:
			LOG('YampLyricsScreen: searchGeniuslyrics: song_title remove brackets: EXCEPT', 'err')

#		if artist_name == 'pink': song_title = song_title.replace('!','i')
		if song_title == '' or artist_name == '': return
		LOG('YampLyricsScreen: searchGeniuslyrics: title: %s artist: %s' %(song_title,artist_name), 'spe2')
##		LOG('YampLyricsScreen: searchGeniuslyrics: title: %s artist: %s' %(song_title,artist_name), 'all')

		base_url = "http://api.genius.com"
		headers = {'Authorization': 'Bearer 8FiOPP2Mt2KVhS6maP4XoLH4w5MaBScK3Y0Aa5eYqZ_5itjA3iOunlbBHxV6wh1o'}

##		search_url = base_url + "/search?q=" + quote_plus(artist_name.replace("#*#*","'") + ' ' + song_title)
		search_url = base_url + "/search?q=" + quote_plus(artist_name.replace("*abc*abc*","'") + ' ' + song_title)
#		LOG('YampLyricsScreen: searchGeniuslyrics: search_url: %s' %(search_url), 'all')
		LOG('YampLyricsScreen: searchGeniuslyrics: search_url: %s' %(search_url), 'spe2')
		try:
			getPage(search_url, headers=headers, timeout=GETLYRICSTIMEOUT).addCallback(self.getGenius1,prio).addErrback(self.getGeniusFailed)
		except:
			LOG('YampLyricsScreen: searchGeniuslyrics: getPage: EXCEPT', 'err')

	def getGeniusFailed(self,result):
		LOG('YampScreen: getGeniusFailed: result: %s:' %(result), 'err')
		self.lyrics = _("Access to genius.com failed.") + "\n\n%s" % str(result.getErrorMessage())
		if self.lyricsFoundPrio == LYRICSS_NO: self.lyricsChanged()
	
	
	def getGenius1(self, response, prio):
		if self.lyricsFoundPrio < prio: return		#already found with higher priority
		try:
			import json
		except:
			LOG('YampLyricsScreen: getGenius1: import: EXCEPT', 'err')
		try:
			LOG('YampLyricsScreen: getGenius1: response: type: %s: %s' %(type(response),response), 'all')
		except:
			LOG('YampLyricsScreen: getGenius1: response: EXCEPT', 'err')

		base_url = "http://api.genius.com"
		headers = {'Authorization': 'Bearer 8FiOPP2Mt2KVhS6maP4XoLH4w5MaBScK3Y0Aa5eYqZ_5itjA3iOunlbBHxV6wh1o'}

#		artist_name = self.artist.replace("'","").lower()
		try:
			artist_name = re.sub('\([^)]*\)','', self.artist).lower() 	#remove everything between brackets
		except:
			LOG('YampLyricsScreen: getGenius1: artist name remove brackets: EXCEPT', 'err')
##		artist_name = self.artist.lower()			
#		artist_name = artist_name.replace("p!nk","pink")			
		LOG('YampLyricsScreen: getGenius1: artist_name: %s' %(artist_name), 'spe2')

		try:
			jsonx = json.loads(response)
			LOG('YampLyricsScreen: getGenius1: jsonx: %s' %(jsonx), 'spe2')
		except:
			LOG('YampLyricsScreen: getGenius1: json: EXCEPT', 'err')
		try:
			song_info = None
			for hit in jsonx["response"]["hits"]:
				if hit["result"]["primary_artist"]["name"].lower() == artist_name:
					song_info = hit
					break
			if song_info == None:
				for hit in jsonx["response"]["hits"]:
					if hit["result"]["primary_artist"]["name"].lower().startswith(artist_name):
						song_info = hit
						break
			LOG('YampLyricsScreen: getGenius1: song_info: %s' %(song_info), 'all')
		except:
			LOG('YampLyricsScreen: getGenius1: part 1: EXCEPT', 'err')
			
		if song_info:
			song_api_path = song_info["result"]["api_path"]

			song_url = str(base_url + song_api_path)
			LOG('YampLyricsScreen: getGenius1: song_url: %s' %(song_url), 'all')
			getPage(song_url, headers=headers, timeout=GETLYRICSTIMEOUT).addCallback(self.getGenius2,prio).addErrback(self.getGeniusFailed)

			
	def getGenius2(self, response, prio):
		LOG('YampLyricsScreen: getGenius2: response: type: %s\n%s' %(type(response),response), 'all')
		if self.lyricsFoundPrio < prio: return		#already found with higher priority
		try:
			import json
		except:
			LOG('YampLyricsScreen: getGenius2: import: EXCEPT', 'err')
		try:
			jsonx = json.loads(response)
		except:
			LOG('YampLyricsScreen: getGenius2: Songinfo json: EXCEPT', 'err')
		try:
			path = jsonx["response"]["song"]["path"]
			#gotta go regular html scraping... come on Genius
			page_url = str("http://genius.com" + path)
			LOG('YampLyricsScreen: getGenius2: page_url: %s' %(page_url), 'all')
			getPage(page_url, timeout=GETLYRICSTIMEOUT).addCallback(self.getGenius3,prio).addErrback(self.getGeniusFailed)
		except:
			LOG('YampLyricsScreen: getGenius2: Songinfo page: EXCEPT', 'err')

	def getGenius3(self, response, prio):
		LOG('YampLyricsScreen: getGenius3: response: type: %s\n%s' %(type(response),response), 'all')
		if self.lyricsFoundPrio < prio: return		#already found with higher priority
		try:
			from bs4 import BeautifulSoup
		except:
			self.session.open(MessageBox, _("python-beautifulsoup4 not installed\nLyrics Search at genius.com not possible"), type = MessageBox.TYPE_INFO,timeout = 10 )
#			LOG('YampLyricsScreen: getGenius3: import: EXCEPT', 'err')
			return

		lyrics=''
		try:
			newStart = """<html><head><title>lyrics/title></head><body>"""
			
			startHead = response.find('<div class="lyrics">')
			LOG('YampLyricsScreen: getGenius3: len response; %d' %(len(response)), 'spe2')
			
			if startHead >0: 
				response = response[startHead:]		
				LOG('YampLyricsScreen: getGenius3: len response; %d' %(len(response)), 'spe2')
				endHead = response.find('</div>')
				if endHead >0: 
					endHead +=6
					response = response[:endHead]
					LOG('YampLyricsScreen: getGenius3: end found: %d' %(endHead), 'spe2')
				LOG('YampLyricsScreen: getGenius3: len response; %d' %(len(response)), 'spe2')
				response = newStart + response
				LOG('YampLyricsScreen: getGenius3: len response; %d' %(len(response)), 'spe2')
		except:
			LOG('YampLyricsScreen: getGenius3: remove build new response: EXCEPT', 'err')
		try:
#			LOG('YampLyricsScreen: getGenius3: Time1', 'all')
			html = BeautifulSoup(response)
#			LOG('YampLyricsScreen: getGenius3: Time2', 'all')
#			LOG('YampLyricsScreen: getGenius3: html: type: %s\n%s' %(type(html),html), 'all')
			LOG('YampLyricsScreen: getGenius3: html: type: %s\n%s' %(type(html),html), 'spe2')
		except:
			LOG('YampLyricsScreen: getGenius3: html: EXCEPT', 'err')
		try:
			#remove script tags that they put in the middle of the lyrics
			[h.extract() for h in html('script')]
			#at least Genius is nice and has a tag called 'lyrics'!
#			lyrics = html.find("lyrics").get_text()
			lyrics = html.find("div").get_text()
			LOG('YampLyricsScreen: getGenius3: lyrics: %s' %(lyrics), 'spe2')
		except:
			LOG('YampLyricsScreen: getGenius3: Songinfo: EXCEPT', 'err')
		if self.lyricsFoundPrio < prio: return		#already found with higher priority
		if lyrics:
			self.lyrics = str(lyrics)
#			LOG('YampLyricsScreen: getGenius3: lyrics: %s:' %(self.lyrics), 'all')
			self.pixNumLyrics = LYRICSS_GENIUS
			self.lyricsFoundPrio = prio
			self.lyricsChanged()

	#Lyrics search chartlyrics.com
	def searchChartlyrics(self,prio1,prio2,prio3,prio4):
		LOG('YampLyricsScreen: getLyrics: Start chartlyrics: Start', 'all')
#		LOG('YampLyricsScreen: getLyrics: Start chartlyrics: Start', 'spe2')
		if prio1 == 'lyricsChart': prio = 1
		elif prio2 == 'lyricsChart': prio = 2
		elif prio3 == 'lyricsChart': prio = 3
		elif prio4 == 'lyricsChart': prio = 4
		else: return

		LOG('YampLyricsScreen: searchChartlyrics: prio: %d  lyricsFoundPrio: %d' %(prio,self.lyricsFoundPrio), 'all')
		if self.lyricsFoundPrio < prio: return		#already found with higher priority

		artist = self.artist.replace("'","")
#		artist = artist.replace('!', 'i')
		title = self.songtitle.replace("'","")
		LOG('YampLyricsScreen: searchChartlyrics: artist: %s  title: %s' %(artist,title), 'all')
#		LOG('YampLyricsScreen: searchChartlyrics: artist: %s  title: %s' %(artist,title), 'spe2')
		if artist and title:
			url = "http://api.chartlyrics.com/apiv1.asmx/SearchLyricDirect?artist=%%22%s%%22&song=%%22%s%%22" % (quote(artist), quote(title))
			LOG('YampLyricsScreen: searchChartlyrics: url: %s' %(url), 'all')
#			LOG('YampLyricsScreen: searchChartlyrics: url: %s' %(url), 'spe2')
			try:
#				getPage(url, timeout=20).addCallback(self.getLyricsParseXML,prio).addErrback(self.getChartyricsFailed,prio)
				getPage(url, timeout=GETLYRICSTIMEOUT).addCallback(self.getLyricsParseXML,prio).addErrback(self.getChartlyricsFailed)
			except:
				LOG('YampLyricsScreen: searchChartlyrics: getPage: EXCEPT', 'err')
				
	def getLyricsParseXML(self, xmlstring, prio):
		if self.lyricsFoundPrio < prio: return		#already found with higher priority
		LOG('YampLyricsScreen: getLyricsParseXML: Start: xmlstring: %s' %(xmlstring), 'all')
#		LOG('YampLyricsScreen: getLyricsParseXML: Start: xmlstring: %s' %(xmlstring), 'spe2')
#		LOG('YampLyricsScreen: getLyricsParseXML: Start: xmlstring: %s' %(xmlstring), 'err')
		xmlElement = xml_fromstring(xmlstring)
		LOG('YampLyricsScreen: getLyricsParseXML: xmlElement: %s' %(xmlElement), 'all')
#		LOG('YampLyricsScreen: getLyricsParseXML: xmlElement: %s' %(xmlElement), 'err')
		lyrics = htmlUnescape(unquote(xmlElement.findtext("{http://api.chartlyrics.com/}Lyric").encode("utf-8", 'ignore')))
		LOG('YampLyricsScreen: getLyricsParseXML: lyrics: %s' %(lyrics), 'all')
#		LOG('YampLyricsScreen: getLyricsParseXML: lyrics: %s' %(lyrics), 'err')
		title = htmlUnescape(unquote(xmlElement.findtext("{http://api.chartlyrics.com/}LyricSong").encode("utf-8", 'ignore')))
		artist = htmlUnescape(unquote(xmlElement.findtext("{http://api.chartlyrics.com/}LyricArtist").encode("utf-8", 'ignore')))
		if self.lyricsFoundPrio < prio: return		#already found with higher priority
		if lyrics:
			try:
				self.lyrics = lyrics
				LOG('YampLyricsScreen: getLyricsParseXML: lyrics: %s:' %(self.lyrics), 'all')
#				LOG('YampLyricsScreen: getLyricsParseXML: lyrics: %s:' %(self.lyrics), 'err')
				self.pixNumLyrics = LYRICSS_CHARTL
				self.lyricsFoundPrio = prio
				self.lyricsChanged()
			except:
				LOG('YampLyricsScreen: getLyricsParseXML: self.lyrics: EXCEPT', 'err')
		
	def getChartlyricsFailed(self,result):
		LOG('YampLyricsScreen: getChartlyricsFailed: result: %s:' %(result), 'all')
		self.lyrics = _("Access to chartlyrics.com failed.") + "\n\n%s" % str(result.getErrorMessage())
		if self.lyricsFoundPrio == LYRICSS_NO: self.lyricsChanged()
		
	#Lyrics search ID3 (mp3, flac)
	def searchId3(self,songFilename,prio1,prio2,prio3,prio4):
		if prio1 == 'lyricsID3': prio = 1
		elif prio2 == 'lyricsID3': prio = 2
		elif prio3 == 'lyricsID3': prio = 3
		elif prio4 == 'lyricsID3': prio = 4
		else: return

#		LOG('YampLyricsScreen: searchId3: prio: %d  lyricsFoundPrio: %d' %(prio,self.lyricsFoundPrio), 'err')
		if self.lyricsFoundPrio < prio: return	#already found with higher priority

		if songFilename.lower().endswith(".mp3"):
			#Lyrics search mp3
			LOG('YampLyricsScreen: searchId3: mp3', 'all')
			try:
				audio = ID3(songFilename)
			except:
				audio = None
			if audio:
				for frame in audio.values():
					if frame.FrameID == "USLT":
						self.lyrics = getEncodedString(frame.text).replace("\r\n","\n").replace("\r","\n")
						self.pixNumLyrics = LYRICSS_MP3
						self.lyricsFoundPrio = prio
						break
						
		elif songFilename.lower().endswith(".flac"):
			#Lyrics search flac
			LOG('YampLyricsScreen: searchId3: flac', 'all')
			try:
				flacInfo = FLAC(songFilename)
#				LOG('YampLyricsScreen: searchId3: FLAC: songFilename: %s:' %(songFilename), 'err')
			except:
				flacInfo = None
			try:
				if flacInfo:
#					LOG('YampLyricsScreen: searchId3: FLAC: has flacinfo: flacInfo: %s:' %(flacInfo), 'err')
#					try:
#						LOG('YampLyricsScreen: searchId3: FLAC: flacInfo[''lyrics'']: %s' %(flacInfo['lyrics']), 'err')
#					except:
#						LOG('YampLyricsScreen: searchId3: FLAC: flacInfo[''lyrics'']: EXCEPT', 'err')
					if not 'lyrics' in flacInfo:
						LOG('YampLyricsScreen: searchId3: lyrics in flacInfo: NO', 'all')
					else:
						LOG('YampLyricsScreen: searchId3: lyrics in flacInfo: YES', 'all')
						try:
							text = flacInfo['lyrics']
#							LOG('YampLyricsScreen: searchId3: FLAC: text: %s:' %(text), 'err')
						except:
							LOG('YampLyricsScreen: searchId3: FLAC: text: EXCEPT', 'err')

						try:	
							self.lyrics = text[0]
#							LOG('YampLyricsScreen: searchId3: FLAC: self.lyrics 1: %s' %(self.lyrics), 'err')
						except:
							LOG('YampLyricsScreen: searchId3: FLAC: self.lyrics 1: EXCEPT', 'err')

						try:
#							LOG('YampLyricsScreen: searchId3: FLAC: self.lyrics before encode: %s' %(self.lyrics), 'err')
							self.lyrics = getEncodedString(self.lyrics).replace("\r\n","\n").replace("\r","\n")
#							LOG('YampLyricsScreen: searchId3: FLAC: self.lyrics after encode: %s' %(self.lyrics), 'err')
						except:
							LOG('YampLyricsScreen: searchId3: FLAC: self.lyrics: encode: EXCEPT' , 'err')
						try:
#							self.lyrics = "%s: %s\n\n%s" % (self.currArtist, self.currTitle, self.lyrics)
#							LOG('YampLyricsScreen: searchId3: FLAC: self.lyrics 5: %s' %(self.lyrics), 'err')
							self.pixNumLyrics = LYRICSS_FLAC
							self.lyricsFoundPrio = prio
						except:
							LOG('YampLyricsScreen: searchId3: FLAC: self.lyrics 5: EXCEPT', 'err')
			except:
				LOG('YampLyricsScreen: searchId3: FLAC: FlacInfo EXCEPT:', 'err')
		return
		
	#Lyrics search file
	def searchFile(self,prio1,prio2,prio3,prio4):
		if prio1 == 'lyricsFile': prio = 1
		elif prio2 == 'lyricsFile': prio = 2
		elif prio3 == 'lyricsFile': prio = 3
		elif prio4 == 'lyricsFile': prio = 4
		else: return

		LOG('YampLyricsScreen: searchFile: prio: %d  lyricsFoundPrio: %d' %(prio,self.lyricsFoundPrio), 'all')
		if self.lyricsFoundPrio < prio: return	#already found with higher priority

		fileFound = False
		try:
			LOG('YampLyricsScreen: searchFile: lyricsFileName: %s' %(self.lyricsFileName), 'all')
			file = open(self.lyricsFileName, "r")
			self.lyrics = file.read()
			file.close()
			self.pixNumLyrics = LYRICSS_FILE
			self.lyricsFoundPrio = prio
		except:
			try:
				LOG('YampLyricsScreen: searchFile: lyricsFileNameLrc: %s' %(self.lyricsFileNameLrc), 'all')
				file = open(self.lyricsFileNameLrc, "r")
				self.lyrics = file.read()
				file.close()
				self.pixNumLyrics = LYRICSS_FILE
				self.lyricsFoundPrio = prio
			except:
				pass
		return 
		
	def setTimestamp(self):
		if not self.allowTimeEdit: return
#		LOG('YampLyricsScreen: setTimestamp: Start: ', 'err')
		try:
			selIndex = self["lyrics"].getSelectionIndex()
			index = selIndex + self.startIndex
#			LOG('YampLyricsScreen: setTimestamp: selIndex: %d startindex: %d  index: %d  text: %s' %(selIndex,self.startIndex,index,self.txtLines[index]), 'err') ###Test
		except:
			LOG('YampLyricsScreen: setTimestamp: set index: EXCEPT ', 'err')
		try:
			milliseconds = (self.songPos / 90) - self.timeStampOffset
			if milliseconds < 0: milliseconds = 0
			minutes = milliseconds / 60000
			seconds = (milliseconds % 60000) / 1000.0
#			LOG('YampLyricsScreen: setTimestamp: milliseconds: %d minutes: %d  seconds: %f' %(milliseconds,minutes,seconds), 'err') ###Test
		except:
			LOG('YampLyricsScreen: setTimestamp: calculate time: EXCEPT ', 'err')
		try:
			self.tiStamp[index]='[%02d:%05.2f]' %(minutes,seconds)
			self.timeStampChanged = True
#			LOG('YampLyricsScreen: setTimestamp: tiStamp: %s:' %(self.tiStamp[index]), 'err')
#			self.tiStamp[index]='[(0:02d):(1:02.2f)]'.format(minutes,seconds)
		except:
			LOG('YampLyricsScreen: setTimestamp: tiStamp: EXCEPT ', 'err')
		try:
			self.buildLyricsMenuList(self.txtLines[self.startIndex:],self.tiStamp[self.startIndex:])
		except:
			LOG('YampLyricsScreen: setTimestamp: buildLyricsMenuList: EXCEPT ', 'err')
		self.movedown()

	def autoMove(self):
		if not self.autoMoveOn or self.oldskin: return
		try:
			for index in range(len(self.tiStampMsec90)-1, -1, -1):
#				LOG('YampLyricsScreen: autoMove: index: %d' %(index), 'err')
				if self.songPos >= self.tiStampMsec90[index] and self.tiStampMsec90[index] != 0:
#					LOG('YampLyricsScreen: autoMove: indexfound: idx: %d  stamp: %d songPos: %d' %(index,self.tiStampMsec90[index], self.songPos), 'err') ###Test

					#new textline has to be displayed
					try:	
						if index < self.startIndex:			#list has been manually scrolled down -> scroll back
#							LOG('YampLyricsScreen: autoMove: index < self.startIndex: idx: %d  startIndex: %d' %(index, self.startIndex), 'err') ###Test
							self.startIndex = index
							if self.allowTimeEdit: self.buildLyricsMenuList(self.txtLines[self.startIndex:],self.tiStamp[self.startIndex:])
							else: self.buildLyricsMenuList(self.txtLines[self.startIndex:])
					except:
						LOG('YampLyricsScreen: autoMove: index < self.startIndex: EXCEPT', 'err') ###Test
					
					self.lyricslist.moveToIndex(index-self.startIndex)
#					LOG('YampLyricsScreen: autoMove: self.txtLines[index]: %s' %(self.txtLines[index]), 'err') ###Test
					if self.txtLines[index].strip() == '': self.movedown()
					
					#check scrolling
					if self.lenLyricslist > self.scrollMinLines:		#only scroll when more lines than page  
						while self["lyrics"].getSelectionIndex() > self.scrollLine:
							self.startIndex += 1   
							if self.allowTimeEdit: self.buildLyricsMenuList(self.txtLines[self.startIndex:],self.tiStamp[self.startIndex:])
							else: self.buildLyricsMenuList(self.txtLines[self.startIndex:])
					break
		except:
			LOG('YampLyricsScreen: autoMove: index: EXCEPT', 'err')
		
			
	def moveup(self):
		if self.oldskin: return
		self["lyrics"].up()
		try:
			sel = self["lyrics"].getSelection().text.strip()
#			LOG('YampLyricsScreen: moveup: getSelection: %s' %(sel), 'err') 
		except:
			LOG('YampLyricsScreen: moveup: getSelection: EXCEPT', 'err') 
		try:
			selIndex =self["lyrics"].getSelectionIndex()
#			LOG('YampLyricsScreen: moveup: getSelectionIndex: %d' %(selIndex), 'err') 
		except:
			LOG('YampLyricsScreen: moveup: getSelectionIndex: EXCEPT', 'err') 
		try:	
#			if sel == '' and selIndex < LYRICS_SCROLL_LINE and self.startIndex == 0: 
			if sel == '' and selIndex < self.scrollLine and self.startIndex == 0: 
				self.moveup()
		except:
			LOG('YampLyricsScreen: moveup: while: EXCEPT', 'err') 

		#check scrolling
		try:	
			if selIndex > 0: 
				try:
					selIndex = self["lyrics"].getSelectionIndex()
				except:
					LOG('YampLyricsScreen: moveup: selIndex: EXCEPT', 'err') 
#				if selIndex <= LYRICS_SCROLL_LINE and self.startIndex > 0:
				if selIndex <= self.scrollLine and self.startIndex > 0:
					try:
#						LOG('YampLyricsScreen: moveup: startIndex before: %d  offsetJump: %d' %(self.startIndex, self.offsetJump), 'err') 
						self.startIndex -= 1 
						if self.startIndex < 0: self.startIndex = 0 
#						LOG('YampLyricsScreen: moveup: startIndex after: %d' %(self.startIndex), 'err') 
						if self.allowTimeEdit: self.buildLyricsMenuList(self.txtLines[self.startIndex:],self.tiStamp[self.startIndex:])
						else: self.buildLyricsMenuList(self.txtLines[self.startIndex:])
					except:
						LOG('YampLyricsScreen: moveup: buildLyricsMenuList: EXCEPT', 'err') 
					try:
#						self.lyricslist.moveToIndex(LYRICS_SCROLL_LINE)
						self.lyricslist.moveToIndex(self.scrollLine)
					except:
						LOG('YampLyricsScreen: moveup: moveToIndex: EXCEPT', 'err') 
					try:
						sel = self["lyrics"].getSelection().text.strip()
						if sel == '':	self.moveup()
					except:
						LOG('YampLyricsScreen: moveup: moveup end: EXCEPT', 'err') 
		except:
			LOG('YampLyricsScreen: moveup: buildnew komplett: EXCEPT', 'err') 

			
	def movedown(self):
#		LOG('YampLyricsScreen: movedown: getSelection: Start', 'err') 
		if self.oldskin: return
		self["lyrics"].down()
		try:
			sel =self["lyrics"].getSelection().text.strip()
#			LOG('YampLyricsScreen: movedown: getSelection: %s' %(sel), 'err') 
		except:
			LOG('YampLyricsScreen: movedown: getSelection: EXCEPT', 'err') 
		try:
			selIndex = self["lyrics"].getSelectionIndex()
#		LOG('YampLyricsScreen: movedown: getSelectionIndex: %d' %(selIndex), 'err') 
		except:
			LOG('YampLyricsScreen: movedown: getSelectionIndex: EXCEPT', 'err') 
		try:	
#			LOG('YampLyricsScreen: movedown: sel: *%s* selIndex: %d scrollLine: %d startIndex: %d' %(sel,selIndex,self.scrollLine,self.startIndex), 'err') 
#			LOG('YampLyricsScreen: movedown: lenLyricslist: %d scrollMinLines: %d' %(self.lenLyricslist,self.scrollMinLines), 'err') 
			if sel == '' and ((selIndex <= self.scrollLine and self.startIndex == 0) or self.lenLyricslist <= self.scrollMinLines): 
#				LOG('YampLyricsScreen: movedown: extra movedown', 'err') 
				self.movedown()
		except:
			LOG('YampLyricsScreen: movedown: EXCEPT', 'err') 

		#check scrolling
		try:	
			if self.lenLyricslist > self.scrollMinLines:		#only scroll when more lines than page 
				try:
					selIndex = self["lyrics"].getSelectionIndex()
#					LOG('YampLyricsScreen: movedown: before scroll 2xxx: selIndex: %d %s' %(selIndex,sel), 'err') 
				except:
					LOG('YampLyricsScreen: movedown: selIndex: EXCEPT', 'err') 
				if selIndex > self.scrollLine:   # and selIndex + self.startIndex <= len(self.txtLines)
					try:
#						LOG('YampLyricsScreen: movedown: startIndex before: %d' %(self.startIndex), 'err') 
						self.startIndex += 1
#						LOG('YampLyricsScreen: movedown: startIndex after: %d' %(self.startIndex), 'err') 
						if self.allowTimeEdit: self.buildLyricsMenuList(self.txtLines[self.startIndex:],self.tiStamp[self.startIndex:])
						else: self.buildLyricsMenuList(self.txtLines[self.startIndex:])
					except:
						LOG('YampLyricsScreen: movedown: buildLyricsMenuList: EXCEPT', 'err') 
					try:
						self.lyricslist.moveToIndex(self.scrollLine)
					except:
						LOG('YampLyricsScreen: movedown: moveToIndex: EXCEPT', 'err') 
					try:
						sel = self["lyrics"].getSelection().text.strip()
						if sel == '':	self.movedown()
					except:
						LOG('YampLyricsScreen: movedown: movedown end: EXCEPT', 'err') 
		except:
			LOG('YampLyricsScreen: movedown: buildnew komplett: EXCEPT', 'err') 


	def pause(self):
		try:
#			LOG('YampLyricsScreen: pause: Start', 'err') 
			self.parent.pause()
		except:
			LOG('YampLyricsScreen: pause: EXCEPT', 'err') 

	def play(self):
		try:
#			LOG('YampLyricsScreen: play: Start', 'err')
			self.parent.play()
		except:
			LOG('YampLyricsScreen: play: EXCEPT', 'err') 

	def previousEntry(self):
		try:
#			LOG('YampLyricsScreen: previousEntry: Start', 'err') 
			self.parent.previousEntry()
		except:
			LOG('YampLyricsScreen: previousEntry: EXCEPT', 'err') 

	def nextEntry(self):
		try:
#			LOG('YampLyricsScreen: nextEntry: Start', 'err') 
			self.parent.nextEntry()
		except:
			LOG('YampLyricsScreen: nextEntry: EXCEPT', 'err') 
			
	def ok(self):
		try:
			if self.allowTimeEdit: self.setTimestamp()
		except:
			LOG('YampLyricsScreen: ok: EXCEPT', 'err') 

	def autoSaveLyrics(self):	
		LOG('YampLyricsScreen: autoSaveLyrics start: autoSaveLyrics: %d' %(config.plugins.yampmusicplayer.autoSaveLyrics.value), 'all')
		try:
			import os
		except:	LOG('YampLyricsScreen: autoSaveLyrics: import: EXCEPT', 'err') 

		if not config.plugins.yampmusicplayer.autoSaveLyrics.value: return
		if not self.pixNumLyrics == LYRICSS_CHARTL and not self.pixNumLyrics == LYRICSS_GENIUS: return
		if (os.path.exists(self.lyricsFileName) or os.path.exists(self.lyricsFileNameLrc)) and (os.path.isfile(self.lyricsFileName) or os.path.isfile(self.lyricsFileName)): return
		self.saveLyrics()

	def saveLyrics(self):	
		try:
			index = 0
			text = ''
			for line in self.txtLines:
				text=text + self.tiStamp[index] + line + '\n'
				index +=1
			file = open(self.lyricsFileName, "w")
			file.write(text)
			file.close()
			self.timeStampChanged = False
			self.session.open(MessageBox, _("Lyrics saved to %s") %(self.lyricsFileName), type = MessageBox.TYPE_INFO,timeout = 5 )
		except:
			self.session.open(MessageBox, _("Saving lyrics %s failed") %(self.lyricsFileName), type = MessageBox.TYPE_WARNING,timeout = 10 )
			
	def keyGreen(self):
		try:
			if self.pixNumLyrics == LYRICSS_NO: return
			if self.pixNumLyrics == LYRICSS_FILE and not self.allowTimeEdit and not self.timeStampChanged:
				self.session.openWithCallback(self.deleteConfirmed, MessageBox, _("Do yo want to delete the lyrics file\n%s ?") %(self.lyricsFileName), default = True)
			else: self.saveLyrics()
		except:
			LOG('YampLyricsScreen: keyGreen: EXCEPT', 'err') 

	def deleteConfirmed(self,answer):
#		LOG('YampLyricsScreen: deleteConfirmed: answer; %d' %(answer), 'all')
		try:
			if answer:
				os.remove(self.lyricsFileName)
#				self.session.open(MessageBox, _("Lyrics file\n%s\n deleted") %(self.lyricsFileName), type = MessageBox.TYPE_INFO,timeout = 5 )
				try:
					self.getLyrics()
				except:
					LOG('YampLyricsScreen: deleteConfirmed: getlyrics: EXCEPT', 'err') 
		except:
			LOG('YampLyricsScreen: deleteConfirmed: EXCEPT', 'err') 
		
	def keyYellow(self):
		if self.oldskin: return
		try:
			self.autoMoveOn = not self.autoMoveOn
			self.setTextYellowKey()
		except:
			LOG('YampLyricsScreen: key_yellow: EXCEPT', 'err') 

	def keyBlue(self):
		if self.oldskin: return
		try:
			self.allowTimeEdit = not self.allowTimeEdit
			self.setTextBlueKey()
			if self.allowTimeEdit: 
				self.buildLyricsMenuList(self.txtLines[self.startIndex:],self.tiStamp[self.startIndex:])
				self.autoMoveOn = False
			else: 
				self.buildLyricsMenuList(self.txtLines[self.startIndex:])
			self.setTextYellowKey()
			self.setTextGreenKey()
		except:
			LOG('YampLyricsScreen: keyBlue: EXCEPT', 'err') 

	def setTextGreenKey(self):	
		if self.oldskin: return
		if self.pixNumLyrics == LYRICSS_FILE and not self.allowTimeEdit and not self.timeStampChanged: self["key_green"].setText(_("Delete"))
		elif self.pixNumLyrics == LYRICSS_NO: self["key_green"].setText("")
		else: self["key_green"].setText(_("Save"))

	def setTextYellowKey(self):	
		if self.oldskin: return
		if self.autoMoveOn: self["key_yellow"].setText(_("Auto move Off"))
		else: self["key_yellow"].setText(_("Auto move On"))

	def setTextBlueKey(self):		
		if self.oldskin: return
		if self.allowTimeEdit: self["key_blue"].setText(_("Disallow time edit"))
		else:	self["key_blue"].setText(_("Allow time edit"))

	def triggerStartActions(self):
#		try:
#			LOG('YampLyricsScreen: triggerStartActions ok' , 'err') 
#		except:
#			LOG('YampLyricsScreen: triggerStartActions: EXCEPT', 'err')  ###Test 
###		LOG('YampLyricsScreen: triggerStartActions: setCover', 'spe') 
		self.setCover()
		self.setLcdText()
		
	def setLcdText(self):
		if config.plugins.yampmusicplayer.yampLCD.value == 'off': return
		if config.plugins.yampmusicplayer.yampLCD.value == 'rolling':
			self.updateLCDText(self.songtitle + ' - ' + self.artist + ' - ' + self.album,1)
		else:	
			self.updateLCDText(self.songtitle, 1)
			self.updateLCDText(self.artist, 2)
			self.updateLCDText(self.album, 3)
			
	def setSongInfo(self):
		try:
			self.songtitle = self.parent.currTitle
			self.artist = self.parent.currArtist
			self.album = self.parent.currAlbum
			self.tracknr = self.parent.currTracknr
			self.bitrate = self.parent.currBitRate
			if self.oldskin: return

			self["songtitle"].setText(self.songtitle.replace('n/a',self.replaceText))
			self["artist"].setText(self.artist.replace('n/a',self.replaceText))
			self["album"].setText(self.album.replace('n/a',self.replaceText))
			if self.tracknr > 0: self["tracknr"].setText(str(self.tracknr))
			else: self["tracknr"].setText('')
			self["length"].setText(self.parent.currLength.replace('n/a',self.replaceText))
			self["bitrate"].setText(self.bitrate.replace('n/a',self.replaceText))
#			LOG('YampLyricsScreen: setSongInfo: currLength: %s' %(self.parent.currLength), 'err') 
##			self["provider"].setPixmapNum(self.pixNumLyrics)
		except:
			LOG('YampLyricsScreen: setSongInfo: EXCEPT', 'err') 

	def setCover(self):
		lcdMode = config.plugins.yampmusicplayer.yampLCD.value
		if lcdMode != 'off' and lcdMode != 'rolling':
			self.summaries.setCover()
		if self.oldskin: return

		try: 
			newCoverArtFile, newPixNumCover = self.parent.getCoverArtFile()
###			LOG('YampLyricsScreen: setCover: newPixNumCover: %d newCoverArtFile: *%s*' %(newPixNumCover,newCoverArtFile), 'spe') ###Test

			actCoverArtFile = self["coverArt"].getFileName()
###			LOG('YampLyricsScreen: setCover: actCoverArtFile: *%s*' %(actCoverArtFile), 'spe') ###Test
			if newCoverArtFile.strip().lower() != actCoverArtFile.strip().lower():
				self["coverArt"].showCoverArt(newCoverArtFile)
				self["cprovider"].setPixmapNum(newPixNumCover)
###				LOG('YampLyricsScreen: setCover: setNewCover: coverArtFile: *%s*' %(newCoverArtFile), 'spe') ###Test
				LOG('YampLyricsScreen: setCover: setNewCover: coverArtFile: *%s*' %(newCoverArtFile), 'all')
#				LOG('YampLyricsScreen: setCover: coverArtFile: *%s*' %(self.coverArtFile), 'all') ###Test
		except:
			LOG('YampLyricsScreen: setCover: EXCEPT', 'err') 
			
	def cleanup(self):
#		LOG('YampLyricsScreen: cleanup', 'err')  ###Test
		self.triggerTimer.stop()
		self.updateTimer.stop()
		self.updateCoverTimer.stop()
		del self.triggerTimer
		del self.updateTimer
		del self.updateCoverTimer
		del self.lyricsAutoSaveTimer
		
	def updateLCDText(self, text, line):
		if config.plugins.yampmusicplayer.yampLCD.value == 'rolling':
			try:
				self.LcdText = text
#				LOG('YampLyricsScreen: updateLCDText: RollingLCD: LcdText: %s' %(self.LcdText), 'err') 
			except:
				pass
		else:	
#			LOG('YampLyricsScreen: updateLCDText: normalLCD: LcdText: %s' %(text), 'err') 
			self.summaries.setText(text,line)
		
	def getLcdText(self):	#for LCD Running Text
#		LOG('YampLyricsScreen: getLcdText: LcdText: %s' %(self.LcdText), 'all')
		return(self.LcdText)
		
	def createSummary(self):
		confLcd = config.plugins.yampmusicplayer.yampLCD.value
		if confLcd == 'off': return
		elif confLcd == 'rolling':
			return YampLCDRunningScreenV31
		else:
			return YampLCDScreenV31

	def lockShow(self):
		pass

	def unlockShow(self):
		pass


	def updateCoverCyclic(self):
		if self.coverTestMode == 2:
###			LOG('YampLyricsScreen: updateCoverCyclic: setCover', 'spe') 
			self.setCover() 
		
	def updateInfoCyclic(self):
#		coverUpdate = False
#		newCoverArtFile, newPixNumCover = self.parent.getCoverArtFile()
#		LOG('YampLyricsScreen: setCover: newPixNumCover: %d newCoverArtFile: *%s*' %(newPixNumCover,newCoverArtFile), 'spe') ###Test

		try:
			len, self.songPos = self.parent.getSeekData()
#			LOG('YampLyricsScreen: updateInfoCyclic: len: %d  pos: %d' %(len,self.songPos), 'err')
		except:
			LOG('YampLyricsScreen: updateInfoCyclic EXCEPT', 'err')
		self.autoMove()
		if self.coverTestMode == 1 or self.coverTestMode == 3:
			if self.parent.coverChangedLyrics:
				self.parent.coverChangedLyrics = False
###				LOG('YampLyricsScreen: updateInfoCyclic: coverChangedLyrics: setCover', 'spe') 
#				coverUpdate = True
				self.setCover() 
			if self.parent.coverChangedGoogleLyrics:
				self.parent.coverChangedGoogleLyrics = False
###				LOG('YampLyricsScreen: updateInfoCyclic: coverChangedGoogleLyrics: setCover', 'spe') 
#				coverUpdate = True
				self.setCover() 
		if self.songtitle != self.parent.currTitle:		#new Song
			LOG('YampLyricsScreen: updateInfoCyclic: new song: songtitle: %s  parentsongtitle: %s' %(self.songtitle,self.parent.currTitle), 'all')
			if self.parent.currentIsVideo and not config.plugins.yampmusicplayer.showLyricsOnVideo.value:
				self.close()
				return
			self.allowTimeEdit = False
			self.setTextBlueKey()
	#		LOG('YampLyricsScreen: updateInfoCyclic: timeStampChanged: %d ' %(self.timeStampChanged), 'err')
			if self.timeStampChanged:
				self.waitForSaveAnswer = True
	#			LOG('YampLyricsScreen: updateInfoCyclic: in timeStampChanged: Messagebox', 'err')
				self.timeStampChanged = False
				self.setTextGreenKey()
				self.session.openWithCallback(self.saveConfirmed, MessageBox, _("TimeStamp has been changed\nDo yo want to save the lyrics file?"), default = True)
				return
			if self.waitForSaveAnswer: 
	#			LOG('YampLyricsScreen: updateInfoCyclic: waitForSaveAnswer: getLyrics', 'err')
				return
	#		LOG('YampLyricsScreen: updateInfoCyclic: updateNext: getLyrics', 'err')
			self.setSongInfo()
			self.setLcdText()
			self.getLyrics()
			self.autoMoveOn = True
			self.setTextYellowKey()
##			self.allowTimeEdit = False
			self.setTextBlueKey()
##			if not self.timeStampChanged: 
##				self.getLyrics()
##			else:
##				self.session.openWithCallback(self.saveConfirmed, MessageBox, _("TimeStamp has been changed\nDo yo want to save the lyrics file?"), default = True)
#				self.session.openWithCallback(self.saveConfirmed, MessageBox, _("TimeStamp has been changed\nDo yo want to save the lyrics file?"), default = True, title = _('Lyrics time stamp changed'))

	def saveConfirmed(self,answer):
#		LOG('YampLyricsScreen: saveConfirmed: answer; %d' %(answer), 'err')
		if answer: 
			self.saveLyrics()
		self.waitForSaveAnswer = False
#		else: 
#			self.timeStampChanged = False
#			self.getLyrics()

			
	def buildNewLyrics(self):
		LOG('YampLyricsScreen: buildNewLyrics: Start', 'all')
#		LOG('YampLyricsScreen: buildNewLyrics: Start', 'err')
		self.lyrics = self.lyricsClean(self.lyrics)

		try:
			if self.oldskin: 
#				LOG('YampLyricsScreen: buildNewLyrics: self.oldskin', 'err')
				LOG('YampLyricsScreen: buildNewLyrics: self.oldskin: self.lyrics: %s ' %(self.lyrics), 'all')
				self["lyrics"].setText(self.lyrics)
		except:
			LOG('YampLyricsScreen: buildNewLyrics: oldskin: EXCEPT', 'err')
		try:
			self.tiStamp, self.tiStampMsec90, self.txtLines = self.textToList(self.lyrics)
#			LOG('YampLyricsScreen: buildNewLyrics: self.tiStamp: %s' %(self.tiStamp), 'err') ###Test
#			LOG('YampLyricsScreen: buildNewLyrics: self.tiStampMsec90: %s' %(self.tiStampMsec90), 'err') ###Test
#			LOG('YampLyricsScreen: buildNewLyrics: self.txtLines: %s' %(self.txtLines), 'err') ###Test
		except:
			LOG('YampLyricsScreen: buildNewLyrics: self.textToList: EXCEPT', 'err')
		try:
			self.buildLyricsMenuList(self.txtLines)
		except:
			LOG('YampLyricsScreen: buildNewLyrics: buildLyricsMenuList: EXCEPT', 'err')
		try:
			self.startIndex = 0	
			self.lenLyricslist = len(self.lyricslist)
			self.lyricslist.moveToIndex(0)		
		except:
			LOG('YampLyricsScreen: buildNewLyrics: setparameters: EXCEPT', 'err')
		try:
#			self.autoSaveLyrics()
			if self.lyricsAutoSaveTimer.isActive(): self.lyricsAutoSaveTimer.stop() 
			self.lyricsAutoSaveTimer.start((GETLYRICSTIMEOUT + 10)*1000,True)
		except:
			LOG('YampLyricsScreen: buildNewLyrics: autosavelyrics: EXCEPT', 'err')

		
#	def getSeekData(self):
#		try:
#			LOG('YampLyricsScreen: getSeekData', 'err')	###Test
#			service = self.session.nav.getCurrentService()
#			seek = service and service.seek()
#			if seek is None:
#				return (0, 0)
#			len = seek.getLength()
#			pos = seek.getPlayPosition()
#			if len[0] or pos[0]:
#				return (0, 0)
#			return (len[1], pos[1])
#		except:
#			LOG('YampLyricsScreen: getSeekData EXCEPT', 'err')
		
		
	def keyExit(self):
		if self.timeStampChanged:
			self.session.openWithCallback(self.exitConfirmed, MessageBox, _("TimeStamp has been changed\nDo yo want to save before exit?"), default = True)
#			self.session.openWithCallback(self.exitConfirmed, MessageBox, _("TimeStamp has been changed\nDo yo want to save before exit?"), default = True, title = _('Lyrics time stamp changed'))
		else:
			self.close()
			
	def exitConfirmed(self,answer):
		if answer:
			self.saveLyrics()
		self.close()
		
	def buildLyricsMenuList(self, text, timeStamp=None):
#		try:
#			LOG('YampLyricsScreen: buildLyricsMenuList Start: text: %s' %(text), 'err')
#			LOG('YampLyricsScreen: buildLyricsMenuList Start: timeStamp: %s' %(timeStamp), 'err')
#		except:
#			LOG('YampLyricsScreen: buildLyricsMenuList Start: EXCEPT', 'err')
			
		self.lyricslist.list = []
		if timeStamp is None:
			try:
				self.lyricslist.setWithTimeStamp(False)
				for line in text:
					self.lyricslist.append(LyricslistEntryComponent(text = line))
			except:
				pass
		else:
			try:
				self.lyricslist.setWithTimeStamp(True)
				index = 0
				for line in text:
					self.lyricslist.append(LyricslistEntryComponent(text = line, tiStamp = timeStamp[index]))
#					LOG('YampLyricsScreen: buildLyricsMenuList: for line in text: text: %s tiStamp:%s ' %(line,timeStamp[index]), 'err')
					index += 1
			except:
				LOG('YampLyricsScreen: buildLyricsMenuList: for line in text:  EXCEPT' , 'err')
		self.lyricslist.updateList()
		if len(self.lyricslist) > 1:
			self.autoMove()
			
	def lyricsClean(self,text):
		try:
			import re
			text = re.sub(r'\[ar:.*\]','',text)									#remove artist string [ar:xxx]
			text = re.sub(r'\[ti:.*\]','',text)									#remove title string [ti:xxx]
			text = re.sub(r'\[offset:.*\]','',text)							#remove offset string [ofset:xxx]
			text = re.sub(r'\[Offset:.*\]','',text)							#remove offset string [ofset:xxx]
			text = re.sub(r'\[ap:.*\]','',text)									#remove ap string [ap:xxx]
			text = re.sub(r'\[al:.*\]','',text)									#remove al string [al:xxx]
			text = re.sub(r'\[by:.*\]','',text)									#remove a string [by:xxx]
#			try:
#				text = re.sub(r'\[[0-9]+:[0-9]+.?[0-9]*\]\[[0-9]+:[0-9]+.?[0-9]*\]',r'\[[0-9]+:[0-9]+.?[0-9]*\]',text)	#remove leading timecode [00:00.00]
#				text = re.sub(r'\[[0-9]+:[0-9]+.?[0-9]*\]\[[0-9]+:[0-9]+.?[0-9]*\]',r'\[[0-9]+:[0-9]+.?[0-9]*\]\[[0-9]+:[0-9]+.?[0-9]*\]',text)	#remove leading timecode [00:00.00]
#			except:
#				pass
#			text = re.sub(r'\[[0-9]+:[0-9]+.?[0-9]*\]','',text)	#remove leading timecode [00:00.00]
			text = re.sub(r'<!--.*-->','',text)									#remove xml comment
			text = re.sub(r'<script.*/script>','',text)					#remove xml script
			text = re.sub(r'</em>','',text)											#remove xml em class end
			text = re.sub(r'<em class=.*>','',text)							#remove xml em class
			
			text = text.strip()																	#remove empty lines at beginning / end
#			LOG('YampScreen: flacLyricsClean: text: %s' %(text), 'err')
		except:
			LOG('YampScreen: flacLyricsClean: text: EXCEPT', 'err')
		return text
			
	def textToList(self, text):
		import re
#		LOG('YampLyricsScreen: textToList Start: text: %s' %(text), 'err') 
		textLines=[]
		tStamp=[]
		tStampmsecs90=[]
		import string, re
		try:
			textLines=string.split(text,'\n')
		except:
			LOG('YampLyricsScreen: textToList: text.split: EXCEPT', 'err') 
		try:
			for line in textLines:
#				LOG('YampLyricsScreen: textToList: line: %s' %(line), 'err') 
				tx=''
				timeStamp = re.findall(r'\[[0-9]+:[0-9]+.?[0-9]*\]',line)
#				LOG('YampLyricsScreen: textToList: timeStamp: %s' %(timeStamp), 'err') 
				if len(timeStamp): tx=timeStamp[len(timeStamp)-1]
				else: tx='[00:00.00]'
				if len(tx) == 7 and tx[6] == ']': #assuming milliseconds missing: [xx:yy]
					tx = tx[:6] + '.00]'
				tStamp.append(tx)
#				LOG('YampLyricsScreen: textToList: tx: %s' %(tx), 'err') 
				minutes = int(tx[1:3])
				seconds = float(tx[4:9]) 
				posMsec90 = int( ( (minutes * 60.0 + seconds) * 1000.0 ) * 90.0 ) 
				tStampmsecs90.append(posMsec90)
#				LOG('YampLyricsScreen: textToList: minutes: %d seconds: %f  posMsecs90: %d' %(minutes,seconds,posMsec90), 'err') 
				
#				LOG('YampLyricsScreen: textToList: tStamp: %s' %(tStamp), 'err') 
#				LOG('YampLyricsScreen: textToList: timeStamp: %s  line: %s' %(tStamp[line], line), 'err') 
#				LOG('YampLyricsScreen: textToList: line: %s  type: %s' %(line, type(line)), 'err') 
#				textLines[line] = re.sub(r'\[[0-9]+:[0-9]+.?[0-9]*\]','',line)	#remove leading timecode [00:00.00]
		except:
			LOG('YampLyricsScreen: textToList: timeStamp: EXCEPT', 'err') 
#		try:
#			textLines = re.sub(r'\[[0-9]+:[0-9]+.?[0-9]*\]','',textLines)	#remove leading timecode [00:00.00]
#		except:
#			LOG('YampLyricsScreen: textToList: re.sub: EXCEPT', 'err') 
		try:
			textLines = re.sub(r'\[[0-9]+:[0-9]+.?[0-9]*\]','',text)	#remove leading timecode [00:00.00]
			textLines=string.split(textLines,'\n')
		except:
			LOG('YampLyricsScreen: textToList: re.sub: EXCEPT', 'err') 

		return tStamp, tStampmsecs90, textLines
			

class YampLyricsList(GUIComponent):
	def __init__(self, enableWrapAround=False):   #!!!!
		GUIComponent.__init__(self)

		try:   #!!!noch andere Vorgaben fuer FHD
			self.itemFont = parseFont("Regular;18", ((1,1),(1,1)))
			self.myItemHeight = 23
#			LOG('YampLyricsList: init: setDefaults: ok', 'err') 
		except:
#			pass
			LOG('YampLyricsList: init: setDefaults:  EXCEPT', 'err') 
			
		self.isDreamOS = os.path.exists("/var/lib/dpkg/status")

		self.list = []
		self.withTimeStamp = False
		self.title = ""
		self.onSelectionChanged = [ ]
		self.enableWrapAround = enableWrapAround
		self.l = eListboxPythonMultiContent()
		try:
			self.l.setBuildFunc(self.buildEntry)
#			LOG('YampLyricsList:__init__:set self.l.setBuildFunc: ok', 'err') ###Test
		except:
			LOG('YampLyricsList:__init__:set self.l.setBuildFunc:   EXCEPT', 'err') 
		
	GUI_WIDGET = eListbox

	def buildEntry(self, item):
#		LOG('YampLyricsList: buildEntry: Start' , 'err')
#		try:
#			LOG('YampLyricsList: buildEntry: Start: item.text: %s' %(item.text) , 'err')
#		except:
#			LOG('YampLyricsList: buildEntry: Start: item.text: EXCEPT', 'err')
#		try:
#			LOG('YampLyricsList: buildEntry: Start: item.tiStamp: %s' %(item.tiStamp) , 'err')
#		except:
#			LOG('YampLyricsList: buildEntry: Start: item.tiStamp: EXCEPT', 'err')

		self.w = self.l.getItemSize().width()
		self.h = self.myItemHeight
#		LOG('YampLyricsList: buildEntry: list: self.w: %d self.h: %d' %(self.w, self.h) , 'err')
		res = [ None ]

		liney = int(self.fonth * 0.01) + 1
		lineh = int(self.fonth * 1.05)
#		LOG('YampLyricsList: buildEntry: liney: %d  lineh: %d'  %(liney, lineh) , 'err')

		if self.withTimeStamp:
			if len(item.text.strip()) == 0: item.tiStamp = ''
			widthTiStamp = int(lineh * 4.5)
			res.append (MultiContentEntryText(pos=(0, liney), size=(widthTiStamp, lineh), font = 0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = "%s" % item.tiStamp))
			res.append (MultiContentEntryText(pos=(widthTiStamp, liney), size=(self.w-widthTiStamp, lineh), font = 0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = "%s" % item.text))
		else:
			res.append (MultiContentEntryText(pos=(0, liney), size=(self.w, lineh), font = 0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = "%s" % item.text))
		return res

	def applySkin(self, desktop, parent):
		attribs = []
		if self.skinAttributes is not None:
			for (attrib, value) in self.skinAttributes:
#				try:
#					LOG('YampLyricsList: applySkin: attrib *%s*  value: *%s*'  %(attrib, value), 'err') 
#				except:
#					pass
				if attrib == "itemFont":
					self.itemFont = parseFont(value, ((1,1),(1,1)))
				else:
					attribs.append((attrib, value))

		self.fonth = int(fontRenderClass.getInstance().getLineHeight(self.itemFont))
		self.myItemHeight = int(self.fonth * 1.15)
		self.l.setItemHeight(self.myItemHeight)

		try:
			self.l.setFont(0, self.itemFont)
		except:
			LOG('YampLyricsList: applySkin: setFont0   EXCEPT', 'err') 
#		try:
#			self.l.setFont(1, self.itemFont1)
#		except:
#			LOG('YampLyricsList: applySkin: setFont1   EXCEPT', 'err') 
		try:
			self.skinAttributes = attribs
		except:
			LOG('YampLyricsList: applySkin: SetskinAttributes   EXCEPT', 'err') 
		return GUIComponent.applySkin(self, desktop, parent)


	def postWidgetCreate(self, instance):
		try:
			pass
#			LOG('YampLyricsList: postWidgetCreate: Start: ok', 'err')
		except:
			LOG('YampLyricsList: postWidgetCreate: Start:  EXCEPT', 'err')
		instance.setContent(self.l)
		if self.isDreamOS: instance.selectionChanged_conn=instance.selectionChanged.connect(self.selectionChanged)
		else: instance.selectionChanged.get().append(self.selectionChanged)
		if self.enableWrapAround:
			self.instance.setWrapAround(True)
		try:
			pass
#			LOG('YampLyricsList: postWidgetCreate: End: ok', 'err')
		except:
			LOG('YampLyricsList: postWidgetCreate: End:  EXCEPT', 'err')

	def preWidgetRemove(self, instance):
		instance.setContent(None)
		if self.isDreamOS: instance.selectionChanged_conn = None
		else: instance.selectionChanged.get().remove(self.selectionChanged)
		
	def selectionChanged(self):
		for f in self.onSelectionChanged:
			f()

	def updateList(self):
		self.l.setList(self.list)

	def moveToIndex(self, index):
		self.instance.moveSelectionTo(index)
		
	def append(self, item):
		self.list.append((item,))

	def selectionEnabled(self, enabled):
		if self.instance is not None:
			self.instance.setSelectionEnable(enabled)

	def pageUp(self):
		if self.instance is not None:
			self.instance.moveSelection(self.instance.pageUp)

	def pageDown(self):
		if self.instance is not None:
			self.instance.moveSelection(self.instance.pageDown)

	def up(self):
		if self.instance is not None:
			self.instance.moveSelection(self.instance.moveUp)

	def down(self):
		if self.instance is not None:
			self.instance.moveSelection(self.instance.moveDown)

	def getSelection(self):
		return self.l.getCurrentSelection() and self.l.getCurrentSelection()[0]

	def getSelectionIndex(self):
		return self.l.getCurrentSelectionIndex()

	def getLyricsList(self):
		return self.list

	def setWithTimeStamp(self, withTimeStamp):
		self.withTimeStamp = withTimeStamp

	def setTitle(self, title):
		self.title = title

	def __len__(self):
		return len(self.list)


class LyricslistEntryComponent:
	def __init__(self, text = "", tiStamp=""):
		self.text = text
		self.tiStamp = tiStamp

def getEncodedString(value):
	returnValue = ""
	try:
		returnValue = value.encode("utf-8", 'ignore')
	except UnicodeDecodeError:
		try:
			returnValue = value.encode("iso8859-1", 'ignore')
		except UnicodeDecodeError:
			try:
				returnValue = value.decode("cp1252").encode("utf-8")
			except UnicodeDecodeError:
				returnValue = "n/a"
	return returnValue
		
		
		
def htmlUnescape(text):
		text = text.replace('&amp;', '&')
		text = text.replace('&quot;', '"')
		text = text.replace('&gt;', ">")
		text = text.replace('&lt;', "<")
		return text
