metadata.py: Use arbitrary variables from existing tags or database in renamer.

This commit adds the possiblity to use variables from tags already present in
the downloaded media files in file, folder and album art renaming routines. The
variable names translate directly to MediaFile field names, so it is now
possible to use variables like $mb_albumid, $genre, $bitrate, $samplerate, etc.
The full list can be read from MediaFile.readable_fields().
This commit is contained in:
Andrzej Ciarkowski
2016-02-27 00:37:49 +01:00
parent 7e9bd432ce
commit 97e405ee8c
3 changed files with 534 additions and 151 deletions
+34 -151
View File
@@ -30,6 +30,7 @@ from beetsplug import lyrics as beetslyrics
from headphones import notifiers, utorrent, transmission, deluge
from headphones import db, albumart, librarysync
from headphones import logger, helpers, request, mb, music_encoder
from headphones import metadata
postprocessor_lock = threading.Lock()
@@ -339,14 +340,13 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
if any(files.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS):
downloaded_track_list.append(os.path.join(r, files))
builder = metadata.AlbumMetadataBuilder()
# Check if files are valid media files and are writable, before the steps
# below are executed. This simplifies errors and prevents unfinished steps.
for downloaded_track in downloaded_track_list:
try:
f = MediaFile(downloaded_track)
if f is None:
# this test is just to keep pyflakes from complaining about an unused variable
return
builder.add_media_file(f)
except (FileTypeError, UnreadableFileError):
logger.error("Track file is not a valid media file: %s. Not " \
"continuing.", downloaded_track.decode(
@@ -378,6 +378,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
shutil.rmtree(new_folder)
return
metadata_dict = builder.build()
# start encoding
if headphones.CONFIG.MUSIC_ENCODER:
downloaded_track_list = music_encoder.encode(albumpath)
@@ -413,7 +414,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
renameNFO(albumpath)
if headphones.CONFIG.ADD_ALBUM_ART and artwork:
addAlbumArt(artwork, albumpath, release)
addAlbumArt(artwork, albumpath, release, metadata_dict)
if headphones.CONFIG.CORRECT_METADATA:
correctedMetadata = correctMetadata(albumid, release, downloaded_track_list)
@@ -433,7 +434,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
'No DESTINATION_DIR has been set. Set "Destination Directory" to the parent directory you want to move the files to')
albumpaths = [albumpath]
elif headphones.CONFIG.MOVE_FILES and headphones.CONFIG.DESTINATION_DIR:
albumpaths = moveFiles(albumpath, release, tracks)
albumpaths = moveFiles(albumpath, release, metadata_dict)
else:
albumpaths = [albumpath]
@@ -606,34 +607,20 @@ def embedAlbumArt(artwork, downloaded_track_list):
continue
def addAlbumArt(artwork, albumpath, release):
def addAlbumArt(artwork, albumpath, release, metadata_dict):
logger.info('Adding album art to folder')
md = metadata.album_metadata(albumpath, release, metadata_dict)
try:
date = release['ReleaseDate']
except TypeError:
date = u''
ext = ".jpg"
# PNGs are possibe here too
if artwork[:4] == '\x89PNG':
ext = ".png"
if date is not None:
year = date[:4]
else:
year = u''
album_art_name = helpers.replace_all(
headphones.CONFIG.ALBUM_ART_FORMAT.strip(), md) + ext
values = {'$Artist': release['ArtistName'],
'$Album': release['AlbumTitle'],
'$Year': year,
'$Date': date,
'$artist': release['ArtistName'].lower(),
'$album': release['AlbumTitle'].lower(),
'$year': year,
'$date': date
}
album_art_name = helpers.replace_all(headphones.CONFIG.ALBUM_ART_FORMAT.strip(),
values) + ".jpg"
album_art_name = helpers.replace_illegal_chars(album_art_name).encode(headphones.SYS_ENCODING,
'replace')
album_art_name = helpers.replace_illegal_chars(album_art_name).encode(
headphones.SYS_ENCODING, 'replace')
if headphones.CONFIG.FILE_UNDERSCORES:
album_art_name = album_art_name.replace(' ', '_')
@@ -680,62 +667,15 @@ def renameNFO(albumpath):
os.path.join(r, file).decode(headphones.SYS_ENCODING, 'replace'), e))
def moveFiles(albumpath, release, tracks):
def moveFiles(albumpath, release, metadata_dict):
logger.info("Moving files: %s" % albumpath)
try:
date = release['ReleaseDate']
except TypeError:
date = u''
if date is not None:
year = date[:4]
else:
year = u''
md = metadata.album_metadata(albumpath, release, metadata_dict)
folder = helpers.replace_all(
headphones.CONFIG.FOLDER_FORMAT.strip(), md, normalize=True)
artist = release['ArtistName'].replace('/', '_')
album = release['AlbumTitle'].replace('/', '_')
if headphones.CONFIG.FILE_UNDERSCORES:
artist = artist.replace(' ', '_')
album = album.replace(' ', '_')
releasetype = release['Type'].replace('/', '_')
if release['ArtistName'].startswith('The '):
sortname = release['ArtistName'][4:] + ", The"
else:
sortname = release['ArtistName']
if sortname[0].isdigit():
firstchar = u'0-9'
else:
firstchar = sortname[0]
for r, d, f in os.walk(albumpath):
try:
origfolder = os.path.basename(
os.path.normpath(r).decode(headphones.SYS_ENCODING, 'replace'))
except:
origfolder = u''
values = {'$Artist': artist,
'$SortArtist': sortname,
'$Album': album,
'$Year': year,
'$Date': date,
'$Type': releasetype,
'$OriginalFolder': origfolder,
'$First': firstchar.upper(),
'$artist': artist.lower(),
'$sortartist': sortname.lower(),
'$album': album.lower(),
'$year': year,
'$date': date,
'$type': releasetype.lower(),
'$first': firstchar.lower(),
'$originalfolder': origfolder.lower()
}
folder = helpers.replace_all(headphones.CONFIG.FOLDER_FORMAT.strip(), values, normalize=True)
folder = folder.replace(' ', '_')
folder = helpers.replace_illegal_chars(folder, type="folder")
folder = folder.replace('./', '_/').replace('/.', '/_')
@@ -1080,82 +1020,25 @@ def embedLyrics(downloaded_track_list):
def renameFiles(albumpath, downloaded_track_list, release):
logger.info('Renaming files')
try:
date = release['ReleaseDate']
except TypeError:
date = u''
if date is not None:
year = date[:4]
else:
year = u''
# Until tagging works better I'm going to rely on the already provided metadata
for downloaded_track in downloaded_track_list:
try:
f = MediaFile(downloaded_track)
except:
logger.info("MediaFile couldn't parse: %s",
downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
md, from_metadata = metadata.file_metadata(downloaded_track, release)
if md is None:
# unable to parse media file, skip file
continue
if not f.disc:
discnumber = ''
else:
discnumber = '%d' % f.disc
if not f.track:
tracknumber = ''
else:
tracknumber = '%02d' % f.track
if not f.title:
basename = os.path.basename(downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
title = os.path.splitext(basename)[0]
ext = os.path.splitext(basename)[1]
ext = md[metadata.Vars.EXTENSION]
if not from_metadata:
title = md[metadata.Vars.TITLE]
new_file_name = helpers.cleanTitle(title) + ext
else:
title = f.title
new_file_name = helpers.replace_all(
headphones.CONFIG.FILE_FORMAT.strip(), md
).replace('/', '_') + ext
if release['ArtistName'] == "Various Artists" and f.artist:
artistname = f.artist
else:
artistname = release['ArtistName']
if artistname.startswith('The '):
sortname = artistname[4:] + ", The"
else:
sortname = artistname
values = {'$Disc': discnumber,
'$Track': tracknumber,
'$Title': title,
'$Artist': artistname,
'$SortArtist': sortname,
'$Album': release['AlbumTitle'],
'$Year': year,
'$Date': date,
'$disc': discnumber,
'$track': tracknumber,
'$title': title.lower(),
'$artist': artistname.lower(),
'$sortartist': sortname.lower(),
'$album': release['AlbumTitle'].lower(),
'$year': year,
'$date': date
}
ext = os.path.splitext(downloaded_track)[1]
new_file_name = helpers.replace_all(headphones.CONFIG.FILE_FORMAT.strip(),
values).replace('/', '_') + ext
new_file_name = helpers.replace_illegal_chars(new_file_name).encode(headphones.SYS_ENCODING,
'replace')
new_file_name = helpers.replace_illegal_chars(new_file_name).encode(
headphones.SYS_ENCODING, 'replace')
if headphones.CONFIG.FILE_UNDERSCORES:
new_file_name = new_file_name.replace(' ', '_')
@@ -1166,8 +1049,8 @@ def renameFiles(albumpath, downloaded_track_list, release):
new_file = os.path.join(albumpath, new_file_name)
if downloaded_track == new_file_name:
logger.debug("Renaming for: " + downloaded_track.decode(headphones.SYS_ENCODING,
'replace') + " is not neccessary")
logger.debug("Renaming for: " + downloaded_track.decode(
headphones.SYS_ENCODING, 'replace') + " is not neccessary")
continue
logger.debug('Renaming %s ---> %s',