Added option to embed lyrics - modified config page, added lyrics variables where needed

This commit is contained in:
Remy
2011-08-21 00:51:59 -07:00
parent 9ac74bafdf
commit 13663c0bfa
6 changed files with 127 additions and 62 deletions

View File

@@ -205,6 +205,7 @@
<h4><input type="checkbox" name="cleanup_files" value="1" ${config['cleanup_files']} /> Delete leftover files (.m3u, .nfo, .sfv, .nzb, etc.)</h4>
<h4><input type="checkbox" name="add_album_art" value="1" ${config['add_album_art']}> Add album art as 'folder.jpg' to album folder</h4>
<h4><input type="checkbox" name="embed_album_art" value="1" ${config['embed_album_art']}> Embed album art in each file</h4>
<h4><input type="checkbox" name="embed_lyrics" value="1" ${config['embed_lyrics']}> Embed lyrics</h4>
</td>
</tr>

View File

@@ -205,6 +205,7 @@
<h4><input type="checkbox" name="cleanup_files" value="1" ${config['cleanup_files']} /> Delete leftover files (.m3u, .nfo, .sfv, .nzb, etc.)</h4>
<h4><input type="checkbox" name="add_album_art" value="1" ${config['add_album_art']}> Add album art as 'folder.jpg' to album folder</h4>
<h4><input type="checkbox" name="embed_album_art" value="1" ${config['embed_album_art']}> Embed album art in each file</h4>
<h4><input type="checkbox" name="embed_lyrics" value="1" ${config['embed_lyrics']}> Embed lyrics</h4>
</td>
</tr>
@@ -260,7 +261,7 @@
<td>
<h2>Re-Encoding Options:</h2>
<br>
<h3><input type="checkbox" name="encode" value="1" ${config['encode']}/>Re-encode Postprocessed Albuns</h3>
<h3><input type="checkbox" name="encode" value="1" ${config['encode']}/> Re-encode downloads during postprocessing</h3>
<i class="smalltext">Note: this option requires the lame or ffmpeg encoder</i>
<br><br>
<%
@@ -275,66 +276,30 @@
<option value="lame" ${lameselect}>lame</option>
<option value="ffmpeg" ${ffmpegselect}>ffmpeg</option>
</select>
<%
if config['encoderoutputformat'] == 'ogg':
oggselect = 'selected="selected"'
mp3select = ''
m4aselect = ''
elif config['encoderoutputformat'] == 'm4a':
oggselect = ''
m4aselect = 'selected="selected"'
mp3select = ''
else:
oggselect = ''
m4aselect = ''
mp3select = 'selected="selected"'
%>
Format: <select name="encoderoutputformat">
<option value="mp3" ${mp3select}>mp3</option>
<option value="ogg" ${oggselect}>ogg</option>
<option value="m4a" ${m4aselect}>m4a</option>
%for x in ['mp3', 'ogg', 'm4a']:
<%
if config['encoderoutputformat'] == x:
outputselect = 'selected'
else:
outputselect = ''
%>
<option value=${x} ${outputselect}>${x}</option>
%endfor
</select></h4>
<br>
<%
if config["bitrate"] == 64:
bitrate64select = 'selected="selected"'
bitrate128select = ''
bitrate192select = ''
bitrate256select = ''
bitrate320select = ''
elif config["bitrate"] == 128:
bitrate64select = ''
bitrate128select = 'selected="selected"'
bitrate192select = ''
bitrate256select = ''
bitrate320select = ''
elif config["bitrate"] == 192:
bitrate64select = ''
bitrate128select = ''
bitrate192select = 'selected="selected"'
bitrate256select = ''
bitrate320select = ''
elif config["bitrate"] == 256:
bitrate64select = ''
bitrate128select = ''
bitrate192select = ''
bitrate256select = 'selected="selected"'
bitrate320select = ''
else:
bitrate64select = ''
bitrate128select = ''
bitrate192select = ''
bitrate256select = ''
bitrate320select = 'selected="selected"'
%>
<h4>Bitrate: <select name="bitrate">
<option value=64 ${bitrate64select}> 64 kbps</option>
<option value=128 ${bitrate128select}>128 kbps</option>
<option value=192 ${bitrate192select}>192 kbps</option>
<option value=256 ${bitrate256select}>256 kbps</option>
<option value=320 ${bitrate320select}>320 kbps</option>
%for x in [64, 128, 192, 256, 320]:
<%
if config["bitrate"] == x:
bitrateselected = "selected"
else:
bitrateselected = ''
%>
<option value=${x} ${bitrateselected}> ${x} kbps</option>
%endfor
</select>
<%
@@ -361,5 +326,5 @@
<p class="center"><input type="submit" value="Save Changes"><br>
(Web Interface changes require a restart to take effect)</h3>
</form>
</%def>
</form>
</%def>

View File

@@ -73,6 +73,7 @@ RENAME_FILES = False
CLEANUP_FILES = False
ADD_ALBUM_ART = False
EMBED_ALBUM_ART = False
EMBED_LYRICS = False
DOWNLOAD_DIR = None
BLACKHOLE = None
BLACKHOLE_DIR = None
@@ -175,7 +176,7 @@ def initialize():
HTTP_PORT, HTTP_HOST, HTTP_USERNAME, HTTP_PASSWORD, HTTP_ROOT, LAUNCH_BROWSER, GIT_PATH, \
CURRENT_VERSION, LATEST_VERSION, MUSIC_DIR, DESTINATION_DIR, PREFERRED_QUALITY, PREFERRED_BITRATE, DETECT_BITRATE, \
ADD_ARTISTS, CORRECT_METADATA, MOVE_FILES, RENAME_FILES, FOLDER_FORMAT, FILE_FORMAT, CLEANUP_FILES, INCLUDE_EXTRAS, \
ADD_ALBUM_ART, EMBED_ALBUM_ART, DOWNLOAD_DIR, BLACKHOLE, BLACKHOLE_DIR, USENET_RETENTION, NZB_SEARCH_INTERVAL, \
ADD_ALBUM_ART, EMBED_ALBUM_ART, EMBED_LYRICS, DOWNLOAD_DIR, BLACKHOLE, BLACKHOLE_DIR, USENET_RETENTION, NZB_SEARCH_INTERVAL, \
LIBRARYSCAN_INTERVAL, DOWNLOAD_SCAN_INTERVAL, SAB_HOST, SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, \
NZBMATRIX, NZBMATRIX_USERNAME, NZBMATRIX_APIKEY, NEWZNAB, NEWZNAB_HOST, NEWZNAB_APIKEY, \
NZBSORG, NZBSORG_UID, NZBSORG_HASH, NEWZBIN, NEWZBIN_UID, NEWZBIN_PASSWORD, LASTFM_USERNAME, INTERFACE, FOLDER_PERMISSIONS, \
@@ -223,6 +224,7 @@ def initialize():
CLEANUP_FILES = bool(check_setting_int(CFG, 'General', 'cleanup_files', 0))
ADD_ALBUM_ART = bool(check_setting_int(CFG, 'General', 'add_album_art', 0))
EMBED_ALBUM_ART = bool(check_setting_int(CFG, 'General', 'embed_album_art', 0))
EMBED_LYRICS = bool(check_setting_int(CFG, 'General', 'embed_lyrics', 0))
DOWNLOAD_DIR = check_setting_str(CFG, 'General', 'download_dir', '')
BLACKHOLE = bool(check_setting_int(CFG, 'General', 'blackhole', 0))
BLACKHOLE_DIR = check_setting_str(CFG, 'General', 'blackhole_dir', '')
@@ -404,6 +406,7 @@ def config_write():
new_config['General']['cleanup_files'] = int(CLEANUP_FILES)
new_config['General']['add_album_art'] = int(ADD_ALBUM_ART)
new_config['General']['embed_album_art'] = int(EMBED_ALBUM_ART)
new_config['General']['embed_lyrics'] = int(EMBED_LYRICS)
new_config['General']['download_dir'] = DOWNLOAD_DIR
new_config['General']['blackhole'] = int(BLACKHOLE)
new_config['General']['blackhole_dir'] = BLACKHOLE_DIR

67
headphones/lyrics.py Normal file
View File

@@ -0,0 +1,67 @@
import re
import urllib
from xml.dom import minidom
import htmlentitydefs
from headphones import logger
def getLyrics(artist, song):
params = { "artist": artist,
"song": song,
"fmt": 'xml'
}
searchURL = 'http://lyrics.wikia.com/api.php?' + urllib.urlencode(params)
try:
data = urllib.urlopen(searchURL).read()
except Exception, e:
logger.warn('Error opening: %s. Error: %s' % (searchURL, e))
return
parseddata = minidom.parseString(data)
url = parseddata.getElementsByTagName("url")
if url:
lyricsurl = url[0].firstChild.nodeValue
else:
logger.info('No lyrics found for %s - %s' % (artist, song))
return
try:
lyricspage = urllib.urlopen(lyricsurl).read()
except Exception, e:
logger.warn('Error fetching lyrics from: %s. Error: %s' % (lyricsurl, e))
return
m = re.compile('''<div class='lyricbox'><div class='rtMatcher'>.*?</div>(.*?)<!--''').search(lyricspage)
lyrics = convert_html_entities(m.group(1)).replace('<br />', '\n')
return lyrics
def convert_html_entities(s):
matches = re.findall("&#\d+;", s)
if len(matches) > 0:
hits = set(matches)
for hit in hits:
name = hit[2:-1]
try:
entnum = int(name)
s = s.replace(hit, unichr(entnum))
except ValueError:
pass
matches = re.findall("&\w+;", s)
hits = set(matches)
amp = "&amp;"
if amp in hits:
hits.remove(amp)
for hit in hits:
name = hit[1:-1]
if htmlentitydefs.name2codepoint.has_key(name):
s = s.replace(hit, unichr(htmlentitydefs.name2codepoint[name]))
s = s.replace(amp, "&")
return s

View File

@@ -7,7 +7,7 @@ from lib.beets import autotag
from lib.beets.mediafile import MediaFile
import headphones
from headphones import db, albumart, logger, helpers
from headphones import db, albumart, lyrics, logger, helpers
def checkFolder():
@@ -219,6 +219,9 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list)
if headphones.CORRECT_METADATA:
correctMetadata(albumid, release, downloaded_track_list)
if headphones.EMBED_LYRICS:
embedLyrics(downloaded_track_list)
if headphones.RENAME_FILES:
renameFiles(albumpath, downloaded_track_list, release)
@@ -255,7 +258,8 @@ def embedAlbumArt(artwork, downloaded_track_list):
f = MediaFile(downloaded_track)
except:
logger.error('Could not read %s. Not adding album art' % downloaded_track)
continue
logger.debug('Adding album art to: %s' % downloaded_track)
f.art = artwork
f.save()
@@ -380,6 +384,29 @@ def correctMetadata(albumid, release, downloaded_track_list):
for item in items:
item.write()
def embedLyrics(downloaded_track_list):
logger.info('Adding lyrics')
for downloaded_track in downloaded_track_list:
try:
f = MediaFile(downloaded_track)
except:
logger.error('Could not read %s. Not checking lyrics' % downloaded_track)
if f.albumartist and f.title:
metalyrics = lyrics.getLyrics(f.albumartist, f.title)
elif f.artist and f.title:
metalyrics = lyrics.getLyrics(f.artist, f.title)
else:
logger.info('No artist/track metadata found for track: %s. Not fetching lyrics' % downloaded_track)
metalyrics = None
if lyrics:
logger.debug('Adding lyrics to: %s' % downloaded_track)
f.lyrics = metalyrics
f.save()
def renameFiles(albumpath, downloaded_track_list, release):
logger.info('Renaming files')

View File

@@ -344,6 +344,7 @@ class WebInterface(object):
"cleanup_files" : checked(headphones.CLEANUP_FILES),
"add_album_art" : checked(headphones.ADD_ALBUM_ART),
"embed_album_art" : checked(headphones.EMBED_ALBUM_ART),
"embed_lyrics" : checked(headphones.EMBED_LYRICS),
"dest_dir" : headphones.DESTINATION_DIR,
"folder_format" : headphones.FOLDER_FORMAT,
"file_format" : headphones.FILE_FORMAT,
@@ -366,7 +367,7 @@ class WebInterface(object):
sab_host=None, sab_username=None, sab_apikey=None, sab_password=None, sab_category=None, download_dir=None, blackhole=0, blackhole_dir=None,
usenet_retention=None, nzbmatrix=0, nzbmatrix_username=None, nzbmatrix_apikey=None, newznab=0, newznab_host=None, newznab_apikey=None,
nzbsorg=0, nzbsorg_uid=None, nzbsorg_hash=None, newzbin=0, newzbin_uid=None, newzbin_password=None, preferred_quality=0, preferred_bitrate=None, detect_bitrate=0, move_files=0,
rename_files=0, correct_metadata=0, cleanup_files=0, add_album_art=0, embed_album_art=0, destination_dir=None, folder_format=None, file_format=None, include_extras=0, interface=None, log_dir=None,
rename_files=0, correct_metadata=0, cleanup_files=0, add_album_art=0, embed_album_art=0, embed_lyrics=0, destination_dir=None, folder_format=None, file_format=None, include_extras=0, interface=None, log_dir=None,
encode=0, encoder=None, bitrate=None, samplingfrequency=None, encoderfolder=None, advancedencoder=None, encoderoutputformat=None):
headphones.HTTP_HOST = http_host
@@ -404,6 +405,7 @@ class WebInterface(object):
headphones.CLEANUP_FILES = cleanup_files
headphones.ADD_ALBUM_ART = add_album_art
headphones.EMBED_ALBUM_ART = embed_album_art
headphones.EMBED_LYRICS = embed_lyrics
headphones.DESTINATION_DIR = destination_dir
headphones.FOLDER_FORMAT = folder_format
headphones.FILE_FORMAT = file_format