MythTV master
utils.py
Go to the documentation of this file.
1import chardet
2import os
3import re
4import sys
5import unicodedata
6import xbmc
7import xbmcaddon
8import xbmcgui
9import xbmcvfs
10
12ADDONNAME = ADDON.getAddonInfo('name')
13ADDONICON = ADDON.getAddonInfo('icon')
14ADDONVERSION = ADDON.getAddonInfo('version')
15ADDONID = ADDON.getAddonInfo('id')
16CWD = xbmcvfs.translatePath(ADDON.getAddonInfo('path'))
17PROFILE = xbmcvfs.translatePath(ADDON.getAddonInfo('profile'))
18LANGUAGE = ADDON.getLocalizedString
19
20CANCEL_DIALOG = (9, 10, 92, 216, 247, 257, 275, 61467, 61448,)
21ACTION_OSD = (107, 163,)
22ACTION_CODEC = (0, 27,)
23ACTION_UPDOWN = (3, 4, 105, 106, 111, 112, 603, 604)
24LYRIC_SCRAPER_DIR = os.path.join(CWD, 'lib', 'culrcscrapers')
25WIN = xbmcgui.Window(10000)
26
27def log(*args, **kwargs):
28 if kwargs['debug']:
29 message = '%s: %s' % (ADDONID, args[0])
30 xbmc.log(msg=message, level=xbmc.LOGDEBUG)
31
32def deAccent(str):
33 return unicodedata.normalize('NFKD', str).replace('"', '')
34
35def get_textfile(filepath):
36 try:
37 f = xbmcvfs.File(filepath)
38 data = f.readBytes()
39 f.close()
40 # Detect text encoding
41 enc = chardet.detect(data)
42 if enc['encoding']:
43 return data.decode(enc['encoding'])
44 else:
45 return data
46 except:
47 return None
48
49def get_artist_from_filename(*args, **kwargs):
50 filename = kwargs['filename']
51 SETTING_READ_FILENAME_FORMAT = kwargs['opt']['read_filename_format']
52 DEBUG = kwargs['opt']['debug']
53 try:
54 artist = ''
55 title = ''
56 basename = os.path.basename(filename)
57 # Artist - title.ext
58 if SETTING_READ_FILENAME_FORMAT == 0:
59 artist = basename.split('-', 1)[0].strip()
60 title = os.path.splitext(basename.split('-', 1)[1].strip())[0]
61 # Artist/Album/title.ext or Artist/Album/Track (-) title.ext
62 elif SETTING_READ_FILENAME_FORMAT in (1,2):
63 artist = os.path.basename(os.path.split(os.path.split(filename)[0])[0])
64 # Artist/Album/title.ext
65 if SETTING_READ_FILENAME_FORMAT == 1:
66 title = os.path.splitext(basename)[0]
67 # Artist/Album/Track (-) title.ext
68 elif SETTING_READ_FILENAME_FORMAT == 2:
69 title = os.path.splitext(basename)[0].split(' ', 1)[1].lstrip('-').strip()
70 # Track Artist - title.ext
71 elif SETTING_READ_FILENAME_FORMAT in (3,5):
72 at = basename.split(' ', 1)[1].strip()
73 artist = at.split('-', 1)[0].strip()
74 title = os.path.splitext(at.split('-', 1)[1].strip())[0]
75 # Track - Artist - title.ext
76 elif SETTING_READ_FILENAME_FORMAT == 4:
77 artist = basename.split('-', 2)[1].strip()
78 title = os.path.splitext(basename.split('-', 2)[2].strip())[0]
79 elif SETTING_READ_FILENAME_FORMAT == 6:
80 artist = basename.split('-', 1)[0].strip()
81 title = os.path.splitext(basename.split('-', 3)[3].strip())[0]
82 except:
83 # invalid format selected
84 log('failed to get artist and title from filename', debug=DEBUG)
85 return artist, title
86
87class Lyrics:
88 def __init__(self, *args, **kwargs):
89 settings = kwargs['settings']
90 self.song = Song(opt=settings)
91 self.lyrics = ''
92 self.source = ''
93 self.list = None
94 self.lrc = False
95
96class Song:
97 def __init__(self, *args, **kwargs):
98 self.artist = ''
99 self.title = ''
100 self.filepath = ''
101 self.embed = ''
102 self.source = ''
103 self.analyze_safe = True
104 self.SETTING_SAVE_FILENAME_FORMAT = kwargs['opt']['save_filename_format']
105 self.SETTING_SAVE_LYRICS_PATH = kwargs['opt']['save_lyrics_path']
106 self.SETTING_SAVE_SUBFOLDER = kwargs['opt']['save_subfolder']
107 self.SETTING_SAVE_SUBFOLDER_PATH = kwargs['opt']['save_subfolder_path']
108
109 def __str__(self):
110 return 'Artist: %s, Title: %s' % (self.artist, self.title)
111
112 def __eq__(self, song):
113 return (deAccent(self.artist) == deAccent(song.artist)) and (deAccent(self.title) == deAccent(song.title))
114
115 def path1(self, lrc):
116 if lrc:
117 ext = '.lrc'
118 else:
119 ext = '.txt'
120 # remove invalid filename characters
121 artist = "".join(i for i in self.artist if i not in "\/:*?<>|")
122 title = "".join(i for i in self.title if i not in "\/:*?<>|")
123 if self.SETTING_SAVE_FILENAME_FORMAT == 0:
124 return os.path.join(self.SETTING_SAVE_LYRICS_PATH, artist, title + ext)
125 else:
126 return os.path.join(self.SETTING_SAVE_LYRICS_PATH, artist + ' - ' + title + ext)
127
128 def path2(self, lrc):
129 if lrc:
130 ext = '.lrc'
131 else:
132 ext = '.txt'
133 dirname = os.path.dirname(self.filepath)
134 basename = os.path.basename(self.filepath)
135 filename = basename.rsplit('.', 1)[0]
137 return os.path.join(dirname, self.SETTING_SAVE_SUBFOLDER_PATH, filename + ext)
138 else:
139 return os.path.join(dirname, filename + ext)
140
141 @staticmethod
142 def current(*args, **kwargs):
143 kwargs = kwargs['opt']
144 song = Song.by_offset(offset=0, opt=kwargs)
145 return song
146
147 @staticmethod
148 def next(*args, **kwargs):
149 kwargs = kwargs['opt']
150 song = Song.by_offset(offset=1, opt=kwargs)
151 if song.artist != '' and song.title != '':
152 return song
153
154 @staticmethod
155 def by_offset(*args, **kwargs):
156 offset = kwargs['offset']
157 SETTING_READ_FILENAME = kwargs['opt']['read_filename']
158 SETTING_CLEAN_TITLE = kwargs['opt']['clean_title']
159 song = Song(opt=kwargs['opt'])
160 if offset > 0:
161 offset_str = '.offset(%i)' % offset
162 else:
163 offset_str = ''
164 song.filepath = xbmc.getInfoLabel('Player%s.Filenameandpath' % offset_str)
165 song.title = xbmc.getInfoLabel('MusicPlayer%s.Title' % offset_str).replace('\\', ' & ').replace('/', ' & ').replace(' ',' ').replace(':','-').strip('.')
166 song.artist = xbmc.getInfoLabel('MusicPlayer%s.Artist' % offset_str).replace('\\', ' & ').replace('/', ' & ').replace(' ',' ').replace(':','-').strip('.')
167 song.embed = xbmc.getInfoLabel('MusicPlayer%s.Lyrics' % offset_str)
168 song.source = xbmc.getInfoLabel('MusicPlayer%s.Property(culrc.source)' % offset_str)
169 # some third party addons may insert the tracknumber in the song title
170 regex = re.compile('\d\d\.\s')
171 match = regex.match(song.title)
172 if match:
173 song.title = song.title[4:]
174 if xbmc.getCondVisibility('Player.IsInternetStream') or xbmc.getCondVisibility('Pvr.IsPlayingRadio'):
175 # disable search for embedded lyrics for internet streams
176 song.analyze_safe = False
177 if not song.artist:
178 # We probably listen to online radio which usually sets the song title as 'Artist - Title' (via ICY StreamTitle)
179 sep = song.title.find('-')
180 if sep > 1:
181 song.artist = song.title[:sep - 1].strip()
182 song.title = song.title[sep + 1:].strip()
183 # The title can contains some additional info in brackets at the end, so we remove it
184 song.title = re.sub(r'\‍([^\‍)]*\‍)$', '', song.title)
185 if (song.filepath and ((not song.title) or (not song.artist) or (SETTING_READ_FILENAME))):
186 song.artist, song.title = get_artist_from_filename(filename=song.filepath, opt=kwargs['opt'])
187 if SETTING_CLEAN_TITLE:
188 song.title = re.sub(r'\‍([^\‍)]*\‍)$', '', song.title)
189 return song
def __init__(self, *args, **kwargs)
Definition: utils.py:88
def __str__(self)
Definition: utils.py:109
analyze_safe
Definition: utils.py:103
SETTING_SAVE_LYRICS_PATH
Definition: utils.py:105
def current(*args, **kwargs)
Definition: utils.py:142
def __eq__(self, song)
Definition: utils.py:112
SETTING_SAVE_FILENAME_FORMAT
Definition: utils.py:104
def next(*args, **kwargs)
Definition: utils.py:148
SETTING_SAVE_SUBFOLDER_PATH
Definition: utils.py:107
def by_offset(*args, **kwargs)
Definition: utils.py:155
def __init__(self, *args, **kwargs)
Definition: utils.py:97
def path2(self, lrc)
Definition: utils.py:128
SETTING_SAVE_SUBFOLDER
Definition: utils.py:106
def path1(self, lrc)
Definition: utils.py:115
def get_artist_from_filename(*args, **kwargs)
Definition: utils.py:49
def deAccent(str)
Definition: utils.py:32
def get_textfile(filepath)
Definition: utils.py:35
def log(*args, **kwargs)
Definition: utils.py:27
None log(str msg, int level=LOGDEBUG)
Definition: xbmc.py:9
str translatePath(str path)
Definition: xbmcvfs.py:55