Merge remote-tracking branch 'AdeHub/master' into develop

This commit is contained in:
rembo10
2012-10-30 15:40:33 -04:00
3 changed files with 314 additions and 9 deletions

181
headphones/getXldProfile.py Executable file
View File

@@ -0,0 +1,181 @@
import os.path
import plistlib
import sys
import xml.parsers.expat as expat
import commands
from headphones import logger
def getXldProfile(xldProfile):
xldProfileNotFound = xldProfile
expandedPath = os.path.expanduser('~/Library/Preferences/jp.tmkk.XLD.plist')
try:
preferences = plistlib.Plist.fromFile(expandedPath)
except (expat.ExpatError):
os.system("/usr/bin/plutil -convert xml1 %s" % expandedPath )
try:
preferences = plistlib.Plist.fromFile(expandedPath)
except (ImportError):
os.system("/usr/bin/plutil -convert binary1 %s" % expandedPath )
logger.info('The plist at "%s" has a date in it, and therefore is not useable.' % expandedPath)
return(xldProfileNotFound, None, None)
except (ImportError):
logger.info('The plist at "%s" has a date in it, and therefore is not useable.' % expandedPath)
except:
logger.info('Unexpected error:', sys.exc_info()[0])
return(xldProfileNotFound, None, None)
xldProfile = xldProfile.lower()
profiles = preferences.get('Profiles')
for profile in profiles:
profilename = profile.get('XLDProfileManager_ProfileName')
xldProfileForCmd = profilename
profilename = profilename.lower()
xldFormat = None
xldBitrate = None
if profilename == xldProfile:
OutputFormatName = profile.get('OutputFormatName')
ShortDesc = profile.get('ShortDesc')
# Determine format and bitrate
if OutputFormatName == 'WAV':
xldFormat = 'wav'
elif OutputFormatName == 'AIFF':
xldFormat = 'aiff'
elif 'PCM' in OutputFormatName:
xldFormat = 'pcm'
elif OutputFormatName == 'Wave64':
xldFormat = 'w64'
elif OutputFormatName == 'MPEG-4 AAC':
xldFormat = 'm4a'
if 'CBR' in ShortDesc or 'ABR' in ShortDesc or 'CVBR' in ShortDesc:
xldBitrate = int(profile.get('XLDAacOutput2_Bitrate'))
elif 'TVBR' in ShortDesc:
XLDAacOutput2_VBRQuality = int(profile.get('XLDAacOutput2_VBRQuality'))
if XLDAacOutput2_VBRQuality > 122:
xldBitrate = 320
elif XLDAacOutput2_VBRQuality > 113 and XLDAacOutput2_VBRQuality <= 122:
xldBitrate = 285
elif XLDAacOutput2_VBRQuality > 104 and XLDAacOutput2_VBRQuality <= 113:
xldBitrate = 255
elif XLDAacOutput2_VBRQuality > 95 and XLDAacOutput2_VBRQuality <= 104:
xldBitrate = 225
elif XLDAacOutput2_VBRQuality > 86 and XLDAacOutput2_VBRQuality <= 95:
xldBitrate = 195
elif XLDAacOutput2_VBRQuality > 77 and XLDAacOutput2_VBRQuality <= 86:
xldBitrate = 165
elif XLDAacOutput2_VBRQuality > 68 and XLDAacOutput2_VBRQuality <= 77:
xldBitrate = 150
elif XLDAacOutput2_VBRQuality > 58 and XLDAacOutput2_VBRQuality <= 68:
xldBitrate = 135
elif XLDAacOutput2_VBRQuality > 49 and XLDAacOutput2_VBRQuality <= 58:
xldBitrate = 115
elif XLDAacOutput2_VBRQuality > 40 and XLDAacOutput2_VBRQuality <= 49:
xldBitrate = 105
elif XLDAacOutput2_VBRQuality > 31 and XLDAacOutput2_VBRQuality <= 40:
xldBitrate = 95
elif XLDAacOutput2_VBRQuality > 22 and XLDAacOutput2_VBRQuality <= 31:
xldBitrate = 80
elif XLDAacOutput2_VBRQuality > 13 and XLDAacOutput2_VBRQuality <= 22:
xldBitrate = 75
elif XLDAacOutput2_VBRQuality > 4 and XLDAacOutput2_VBRQuality <= 13:
xldBitrate = 45
elif XLDAacOutput2_VBRQuality >= 0 and XLDAacOutput2_VBRQuality <= 4:
xldBitrate = 40
elif OutputFormatName == 'Apple Lossless':
xldFormat = 'm4a'
elif OutputFormatName == 'FLAC':
if 'ogg' in ShortDesc:
xldFormat = 'oga'
else:
xldFormat = 'flac'
elif OutputFormatName == 'MPEG-4 HE-AAC':
xldFormat = 'm4a'
xldBitrate = int(profile.get('Bitrate'))
elif OutputFormatName == 'LAME MP3':
xldFormat = 'mp3'
if 'VBR' in ShortDesc:
VbrQuality = float(profile.get('VbrQuality'))
if VbrQuality < 1:
xldBitrate = 260
elif VbrQuality >= 1 and VbrQuality < 2:
xldBitrate = 250
elif VbrQuality >= 2 and VbrQuality < 3:
xldBitrate = 210
elif VbrQuality >= 3 and VbrQuality < 4:
xldBitrate = 195
elif VbrQuality >= 4 and VbrQuality < 5:
xldBitrate = 185
elif VbrQuality >= 5 and VbrQuality < 6:
xldBitrate = 150
elif VbrQuality >= 6 and VbrQuality < 7:
xldBitrate = 130
elif VbrQuality >= 7 and VbrQuality < 8:
xldBitrate = 120
elif VbrQuality >= 8 and VbrQuality < 9:
xldBitrate = 105
elif VbrQuality >= 9:
xldBitrate = 85
elif 'CBR' in ShortDesc:
xldBitrate = int(profile.get('Bitrate'))
elif 'ABR' in ShortDesc:
xldBitrate = int(profile.get('AbrBitrate'))
elif OutputFormatName == 'Opus':
xldFormat = 'opus'
xldBitrate = int(profile.get('XLDOpusOutput_Bitrate'))
elif OutputFormatName == 'Ogg Vorbis':
xldFormat = 'ogg'
XLDVorbisOutput_Quality = float(profile.get('XLDVorbisOutput_Quality'))
if XLDVorbisOutput_Quality <= -2:
xldBitrate = 32
elif XLDVorbisOutput_Quality > -2 and XLDVorbisOutput_Quality <= -1:
xldBitrate = 48
elif XLDVorbisOutput_Quality > -1 and XLDVorbisOutput_Quality <= 0:
xldBitrate = 64
elif XLDVorbisOutput_Quality > 0 and XLDVorbisOutput_Quality <= 1:
xldBitrate = 80
elif XLDVorbisOutput_Quality > 1 and XLDVorbisOutput_Quality <= 2:
xldBitrate = 96
elif XLDVorbisOutput_Quality > 2 and XLDVorbisOutput_Quality <= 3:
xldBitrate = 112
elif XLDVorbisOutput_Quality > 3 and XLDVorbisOutput_Quality <= 4:
xldBitrate = 128
elif XLDVorbisOutput_Quality > 4 and XLDVorbisOutput_Quality <= 5:
xldBitrate = 160
elif XLDVorbisOutput_Quality > 5 and XLDVorbisOutput_Quality <= 6:
xldBitrate = 192
elif XLDVorbisOutput_Quality > 6 and XLDVorbisOutput_Quality <= 7:
xldBitrate = 224
elif XLDVorbisOutput_Quality > 7 and XLDVorbisOutput_Quality <= 8:
xldBitrate = 256
elif XLDVorbisOutput_Quality > 8 and XLDVorbisOutput_Quality <= 9:
xldBitrate = 320
elif XLDVorbisOutput_Quality > 9:
xldBitrate = 500
elif OutputFormatName == 'WavPack':
xldFormat = 'wv'
if ShortDesc != 'normal':
xldBitrate = int(profile.get('XLDWavpackOutput_BitRate'))
# Lossless
if xldFormat and not xldBitrate:
xldBitrate = 500
return(xldProfileForCmd, xldFormat, xldBitrate)
return(xldProfileNotFound, None, None)

View File

@@ -27,7 +27,26 @@ try:
except ImportError:
import lib.argparse as argparse
# xld
if headphones.ADVANCEDENCODER.lower().startswith('xld'):
XLDPROFILE = headphones.ADVANCEDENCODER[4:]
import getXldProfile
XLD = True
else:
XLD = False
def encode(albumPath):
# Return if xld details not found
if XLD:
global xldProfile
(xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(XLDPROFILE)
if not xldFormat:
logger.error(u'Details for xld profile "%s" not found, will not be reencoded' % (xldProfile))
return None
tempDirEncode=os.path.join(albumPath,"temp")
musicFiles=[]
musicFinalFiles=[]
@@ -46,26 +65,48 @@ def encode(albumPath):
for r,d,f in os.walk(albumPath):
for music in f:
if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS):
if not XLD:
encoderFormat = headphones.ENCODEROUTPUTFORMAT.encode(headphones.SYS_ENCODING)
else:
xldMusicFile = os.path.join(r, music)
xldInfoMusic = MediaFile(xldMusicFile)
encoderFormat = xldFormat
if (headphones.ENCODERLOSSLESS):
if (music.lower().endswith('.flac')):
ext = os.path.normpath(os.path.splitext(music)[1].lstrip(".")).lower()
if not XLD and ext == 'flac' or XLD and (ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 500)):
musicFiles.append(os.path.join(r, music))
musicTemp = os.path.normpath(os.path.splitext(music)[0]+'.'+headphones.ENCODEROUTPUTFORMAT.encode(headphones.SYS_ENCODING))
musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat)
musicTempFiles.append(os.path.join(tempDirEncode, musicTemp))
else:
logger.debug('Music "%s" is already encoded' % (music))
else:
musicFiles.append(os.path.join(r, music))
musicTemp = os.path.normpath(os.path.splitext(music)[0]+'.'+headphones.ENCODEROUTPUTFORMAT.encode(headphones.SYS_ENCODING))
musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat)
musicTempFiles.append(os.path.join(tempDirEncode, musicTemp))
if headphones.ENCODER=='lame':
if XLD:
if headphones.ENCODERFOLDER:
encoder = os.path.join(headphones.ENCODERFOLDER.encode(headphones.SYS_ENCODING), 'xld')
else:
encoder = os.path.join('/Applications', 'xld')
elif headphones.ENCODER=='lame':
encoder=os.path.join(headphones.ENCODERFOLDER.encode(headphones.SYS_ENCODING),'lame')
elif headphones.ENCODER=='ffmpeg':
encoder=os.path.join(headphones.ENCODERFOLDER.encode(headphones.SYS_ENCODING),'ffmpeg')
i=0
for music in musicFiles:
infoMusic=MediaFile(music)
if headphones.ENCODER == 'lame':
if XLD:
if xldBitrate and (infoMusic.bitrate / 1000 <= xldBitrate):
logger.info('Music "%s" has bitrate <= "%skbit", will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate))
else:
command(encoder,music,musicTempFiles[i],albumPath)
ifencoded=1
elif headphones.ENCODER == 'lame':
if not any(music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + x) for x in ["mp3", "wav"]):
logger.warn(u'Lame cant encode "%s" format for "%s", use ffmpeg' % (os.path.splitext(music)[1].decode(headphones.SYS_ENCODING, 'replace'),music.decode(headphones.SYS_ENCODING, 'replace')))
else:
@@ -106,7 +147,17 @@ def command(encoder,musicSource,musicDest,albumPath):
return_code=1
cmd=''
startMusicTime=time.time()
if headphones.ENCODER == 'lame':
if XLD:
xldDestDir = os.path.split(musicDest)[0]
cmd = encoder
cmd = cmd + ' "' + musicSource + '"'
cmd = cmd + ' --profile'
cmd = cmd + ' "' + xldProfile + '"'
cmd = cmd + ' -o'
cmd = cmd + ' "' + xldDestDir + '"'
elif headphones.ENCODER == 'lame':
if headphones.ADVANCEDENCODER =='':
cmd=encoder + ' -h'
if headphones.ENCODERVBRCBR=='cbr':

View File

@@ -28,6 +28,15 @@ from lib.beets.mediafile import MediaFile
import headphones
from headphones import db, albumart, librarysync, lyrics, logger, helpers
# xld
if headphones.ADVANCEDENCODER.lower().startswith('xld'):
XLDPROFILE = headphones.ADVANCEDENCODER[4:]
import getXldProfile
XLD = True
else:
XLD = False
postprocessor_lock = threading.Lock()
def checkFolder():
@@ -147,12 +156,73 @@ def verify(albumid, albumpath):
tracks = myDB.select('SELECT * from tracks WHERE AlbumID=?', [albumid])
downloaded_track_list = []
downloaded_cuecount = 0
for r,d,f in os.walk(albumpath):
for files in f:
if any(files.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS):
downloaded_track_list.append(os.path.join(r, files))
elif files.lower().endswith('.cue'):
downloaded_cuecount += 1
# use xld to split cue
if XLD and headphones.MUSIC_ENCODER and downloaded_cuecount and downloaded_cuecount >= len(downloaded_track_list):
(xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(XLDPROFILE)
if not xldFormat:
logger.info(u'Details for xld profile "%s" not found, cannot split cue' % (xldProfile))
else:
if headphones.ENCODERFOLDER:
xldencoder = os.path.join(headphones.ENCODERFOLDER, 'xld')
else:
xldencoder = os.path.join('/Applications','xld')
for r,d,f in os.walk(albumpath):
xldfolder = r
xldfile = ''
xldcue = ''
for file in f:
if any(file.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS) and not xldfile:
xldfile = os.path.join(r, file)
elif file.lower().endswith('.cue') and not xldcue:
xldcue = os.path.join(r, file)
if xldfile and xldcue and xldfolder:
xldcmd = xldencoder
xldcmd = xldcmd + ' "' + xldfile + '"'
xldcmd = xldcmd + ' -c'
xldcmd = xldcmd + ' "' + xldcue + '"'
xldcmd = xldcmd + ' --profile'
xldcmd = xldcmd + ' "' + xldProfile + '"'
xldcmd = xldcmd + ' -o'
xldcmd = xldcmd + ' "' + xldfolder + '"'
logger.info(u"Cue found, splitting file " + xldfile.decode(headphones.SYS_ENCODING, 'replace'))
logger.debug(xldcmd)
os.system(xldcmd)
# count files, should now be more than original if xld successfully split
new_downloaded_track_list_count = 0
for r,d,f in os.walk(albumpath):
for file in f:
if any(file.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS):
new_downloaded_track_list_count += 1
if new_downloaded_track_list_count > len(downloaded_track_list):
# rename original unsplit files
for downloaded_track in downloaded_track_list:
os.rename(downloaded_track, downloaded_track + '.original')
#reload
downloaded_track_list = []
for r,d,f in os.walk(albumpath):
for file in f:
if any(file.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS):
downloaded_track_list.append(os.path.join(r, file))
# test #1: metadata - usually works
logger.debug('Verifying metadata...')
@@ -233,9 +303,12 @@ def verify(albumid, albumpath):
def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list):
logger.info('Starting post-processing for: %s - %s' % (release['ArtistName'], release['AlbumTitle']))
#start enconding
#start encoding
if headphones.MUSIC_ENCODER:
downloaded_track_list=music_encoder.encode(albumpath)
if not downloaded_track_list:
return
album_art_path = albumart.getAlbumArt(albumid)