# This file is part of Headphones. # # Headphones 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 3 of the License, or # (at your option) any later version. # # Headphones 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. # # You should have received a copy of the GNU General Public License # along with Headphones. If not, see . import os import headphones import shutil import time from subprocess import call from headphones import logger from lib.beets.mediafile import MediaFile try: import argparse except ImportError: import lib.argparse as argparse # xld if headphones.ENCODER == 'xld': 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(headphones.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=[] musicTempFiles=[] encoder ="" startAlbumTime=time.time() ifencoded=0 if not os.path.exists(tempDirEncode): os.mkdir(tempDirEncode) else: shutil.rmtree(tempDirEncode) time.sleep(1) os.mkdir(tempDirEncode) 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): 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] + '.' + 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] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) if headphones.ENCODER_PATH: encoder = headphones.ENCODER_PATH.encode(headphones.SYS_ENCODING) else: if XLD: encoder = os.path.join('/Applications', 'xld') elif headphones.ENCODER =='lame': if headphones.SYS_PLATFORM == "win32": ## NEED THE DEFAULT LAME INSTALL ON WIN! encoder = "C:/Program Files/lame/lame.exe" else: encoder="lame" elif headphones.ENCODER =='ffmpeg': if headphones.SYS_PLATFORM == "win32": encoder = "C:/Program Files/ffmpeg/ffmpeg.exe" else: encoder="ffmpeg" i=0 for music in musicFiles: infoMusic=MediaFile(music) 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: if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate/1000)<=headphones.BITRATE)): logger.info('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE)) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 else: if headphones.ENCODEROUTPUTFORMAT=='ogg': if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.ogg'): logger.warn('Can not reencode .ogg music "%s"' % (music.decode(headphones.SYS_ENCODING, 'replace'))) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 elif (headphones.ENCODEROUTPUTFORMAT=='mp3' or headphones.ENCODEROUTPUTFORMAT=='m4a'): if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.'+headphones.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate/1000)<=headphones.BITRATE)): logger.info('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE)) else: command(encoder,music,musicTempFiles[i],albumPath) ifencoded=1 i=i+1 shutil.rmtree(tempDirEncode) time.sleep(1) 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): musicFinalFiles.append(os.path.join(r, music)) if ifencoded==0: logger.info('Encoding for folder "%s" is not needed' % (albumPath.decode(headphones.SYS_ENCODING, 'replace'))) return musicFinalFiles def command(encoder,musicSource,musicDest,albumPath): return_code=1 cmd='' startMusicTime=time.time() 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': cmd=cmd+ ' --resample ' + str(headphones.SAMPLINGFREQUENCY) + ' -b ' + str(headphones.BITRATE) elif headphones.ENCODERVBRCBR=='vbr': cmd=cmd+' -V'+str(headphones.ENCODERQUALITY) cmd=cmd+ ' ' + headphones.ADVANCEDENCODER else: cmd=cmd+' '+ headphones.ADVANCEDENCODER cmd=cmd+ ' "' + musicSource + '"' cmd=cmd+ ' "' + musicDest +'"' elif headphones.ENCODER == 'ffmpeg': cmd=encoder+ ' -i' cmd=cmd+ ' "' + musicSource + '"' if headphones.ADVANCEDENCODER =='': if headphones.ENCODEROUTPUTFORMAT=='ogg': cmd=cmd+ ' -acodec libvorbis' if headphones.ENCODEROUTPUTFORMAT=='m4a': cmd=cmd+ ' -strict experimental' if headphones.ENCODERVBRCBR=='cbr': cmd=cmd+ ' -ar ' + str(headphones.SAMPLINGFREQUENCY) + ' -ab ' + str(headphones.BITRATE) + 'k' elif headphones.ENCODERVBRCBR=='vbr': cmd=cmd+' -aq ' + str(headphones.ENCODERQUALITY) cmd=cmd+ ' -y -ac 2 -vn' else: cmd=cmd+' '+ headphones.ADVANCEDENCODER cmd=cmd+ ' "' + musicDest + '"' logger.debug(cmd) try: return_code = call(cmd, shell=True) if (return_code==0) and (os.path.exists(musicDest)): if headphones.DELETE_LOSSLESS_FILES: os.remove(musicSource) shutil.move(musicDest,albumPath) logger.info('Music "%s" encoded in %s' % (musicSource,getTimeEncode(startMusicTime))) except subprocess.CalledProcessError, e: logger.warn('Music "%s" encoding error : %s' % (musicSource, e.output)) def getTimeEncode(start): seconds =int(time.time()-start) hours = seconds / 3600 seconds -= 3600*hours minutes = seconds / 60 seconds -= 60*minutes return "%02d:%02d:%02d" % (hours, minutes, seconds)