diff --git a/data/interfaces/default/artist.html b/data/interfaces/default/artist.html index 7c82f4fc..fced33c4 100644 --- a/data/interfaces/default/artist.html +++ b/data/interfaces/default/artist.html @@ -25,6 +25,9 @@ <%def name="body()">

${artist['ArtistName']}

+ %if artist['Status'] == 'Loading': +

(Album information for this artist is currently being loaded)

+ %endif

Mark selected albums as diff --git a/data/interfaces/remix/artist.html b/data/interfaces/remix/artist.html index 7c82f4fc..fced33c4 100644 --- a/data/interfaces/remix/artist.html +++ b/data/interfaces/remix/artist.html @@ -25,6 +25,9 @@ <%def name="body()">

${artist['ArtistName']}

+ %if artist['Status'] == 'Loading': +

(Album information for this artist is currently being loaded)

+ %endif

Mark selected albums as diff --git a/headphones/__init__.py b/headphones/__init__.py index 533b067d..60637241 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -120,7 +120,8 @@ BITRATE = None SAMPLINGFREQUENCY = None ADVANCEDENCODER = None ENCODEROUTPUTFORMAT = None -VORBISQUALITY = None +ENCODERQUALITY = None +ENCODERVBRCBR = None def CheckSection(sec): """ Check if INI section exists, if not create it """ @@ -180,7 +181,7 @@ def initialize(): 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, \ - ENCODERFOLDER, ENCODER, BITRATE, SAMPLINGFREQUENCY, ENCODE, ADVANCEDENCODER, ENCODEROUTPUTFORMAT, VORBISQUALITY + ENCODERFOLDER, ENCODER, BITRATE, SAMPLINGFREQUENCY, ENCODE, ADVANCEDENCODER, ENCODEROUTPUTFORMAT, ENCODERQUALITY, ENCODERVBRVBR if __INITIALIZED__: return False @@ -269,7 +270,8 @@ def initialize(): ENCODE = bool(check_setting_int(CFG, 'General', 'encode', 0)) ADVANCEDENCODER = check_setting_str(CFG, 'General', 'advancedencoder', '') ENCODEROUTPUTFORMAT = check_setting_str(CFG, 'General', 'encoderoutputformat', 'mp3') - VORBISQUALITY = check_setting_int(CFG, 'General', 'vorbisquality', 60) + ENCODERQUALITY = check_setting_int(CFG, 'General', 'vorbisquality', 60) + ENCODERVBRCBR = check_setting_str(CFG, 'General', 'encodervbrcbr', 'cbr') if not LOG_DIR: LOG_DIR = os.path.join(DATA_DIR, 'logs') @@ -455,8 +457,9 @@ def config_write(): new_config['General']['encoderfolder'] = ENCODERFOLDER new_config['General']['advancedencoder'] = ADVANCEDENCODER new_config['General']['encoderoutputformat'] = ENCODEROUTPUTFORMAT - new_config['General']['vorbisquality'] = VORBISQUALITY - + new_config['General']['encoderquality'] = ENCODERQUALITY + new_config['General']['encodervbrcbr'] = ENCODERVBRCBR + new_config.write() diff --git a/headphones/encode.py b/headphones/encode.py index 27ec44b3..6211663f 100644 --- a/headphones/encode.py +++ b/headphones/encode.py @@ -13,12 +13,14 @@ except ImportError: import lib.argparse as argparse def encode(albumPath): - tempDirEncode=os.path.join(albumPath,"temp") musicFiles=[] musicFinalFiles=[] musicTempFiles=[] encoder ="" + startAlbumTime=time.clock() + ifencoded=0 + if not os.path.exists(tempDirEncode): os.mkdir(tempDirEncode) else: @@ -30,7 +32,7 @@ def encode(albumPath): for music in f: if any(music.endswith('.' + x) for x in headphones.MEDIA_FORMATS): musicFiles.append(os.path.join(r, music)) - musicTemp = os.path.splitext(music)[0]+'.'+headphones.ENCODEROUTPUTFORMAT + musicTemp = os.path.normpath(os.path.splitext(music)[0]+'.'+headphones.ENCODEROUTPUTFORMAT).encode(headphones.SYS_ENCODING) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) if headphones.ENCODER=='lame': @@ -49,33 +51,46 @@ def encode(albumPath): logger.warn('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music,headphones.BITRATE)) else: command(encoder,music,musicTempFiles[i],albumPath) + ifencoded=1 else: if headphones.ENCODEROUTPUTFORMAT=='ogg': if music.endswith('.ogg'): logger.warn('Can not reencode .ogg music "%s"' % (music)) else: command(encoder,music,musicTempFiles[i],albumPath) + ifencoded=1 elif (headphones.ENCODEROUTPUTFORMAT=='mp3' or headphones.ENCODEROUTPUTFORMAT=='m4a'): if (music.endswith('.'+headphones.ENCODEROUTPUTFORMAT) and (infoMusic.bitrate/1000<=headphones.BITRATE)): logger.warn('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music,headphones.BITRATE)) else: command(encoder,music,musicTempFiles[i],albumPath) + ifencoded=1 i=i+1 shutil.rmtree(tempDirEncode) - time.sleep(1) - logger.info('Encoding for folder "%s" is completed' % (albumPath)) + time.sleep(1) for r,d,f in os.walk(albumPath): for music in f: if any(music.endswith('.' + x) 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)) + else: + logger.info('Encoding for folder "%s" is completed in %s' % (albumPath,getTimeEncode(startAlbumTime))) + return musicFinalFiles def command(encoder,musicSource,musicDest,albumPath): return_code=1 cmd='' + startMusicTime=time.clock() if headphones.ENCODER == 'lame': - cmd=encoder + ' -h --resample ' + str(headphones.SAMPLINGFREQUENCY) + ' -b ' + str(headphones.BITRATE) + cmd=encoder + ' -h' + if headphones.ENCODERVBRCBR=='cbr': + cmd=cmd+ ' --resample ' + str(headphones.SAMPLINGFREQUENCY) + ' -b ' + str(headphones.BITRATE) + elif headphones.ENCODERVBRCBR=='vbr': + cmd=cmd+'' cmd=cmd+ ' ' + headphones.ADVANCEDENCODER cmd=cmd+ ' "' + musicSource + '"' cmd=cmd+ ' "' + musicDest +'"' @@ -86,10 +101,23 @@ def command(encoder,musicSource,musicDest,albumPath): cmd=cmd+ ' -acodec libvorbis' if headphones.ENCODEROUTPUTFORMAT=='m4a': cmd=cmd+ ' -strict experimental' - cmd=cmd+ ' -y -ac 2 -map_metadata 0:0,s0 -vn -ar ' + str(headphones.SAMPLINGFREQUENCY) + ' -ab ' + str(headphones.BITRATE) + 'k' + if headphones.ENCODERVBRCBR=='cbr': + cmd=cmd+ ' -ar ' + str(headphones.SAMPLINGFREQUENCY) + ' -ab ' + str(headphones.BITRATE) + 'k' + elif headphones.ENCODERVBRCBR=='vbr': + cmd=cmd+'' + cmd=cmd+ ' -y -ac 2 -map_metadata 0:0,s0 -vn' cmd=cmd+ ' ' + headphones.ADVANCEDENCODER cmd=cmd+ ' "' + musicDest + '"' return_code = call(cmd, shell=True) if (return_code==0) and (os.path.exists(musicDest)): os.remove(musicSource) - shutil.move(musicDest,albumPath) \ No newline at end of file + shutil.move(musicDest,albumPath) + logger.info('Music "%s" encoded in %s' % (musicSource,getTimeEncode(startMusicTime))) + +def getTimeEncode(start): + seconds =int(time.clock()-start) + hours = seconds / 3600 + seconds -= 3600*hours + minutes = seconds / 60 + seconds -= 60*minutes + return "%02d:%02d:%02d" % (hours, minutes, seconds) \ No newline at end of file diff --git a/headphones/helpers.py b/headphones/helpers.py index 9428f319..73054bdb 100644 --- a/headphones/helpers.py +++ b/headphones/helpers.py @@ -121,6 +121,17 @@ def cleanName(string): return out_string +def cleanTitle(title): + + title = re.sub('[\.\-\/\_]', ' ', title).lower() + + # Strip out extra whitespace + title = ' '.join(title.split()) + + title = title.title() + + return title + def extract_data(s): from headphones import logger diff --git a/headphones/librarysync.py b/headphones/librarysync.py index 208d2b26..81a7da4d 100644 --- a/headphones/librarysync.py +++ b/headphones/librarysync.py @@ -8,15 +8,6 @@ from headphones import db, logger, helpers, importer def libraryScan(dir=None): - myDB = db.DBConnection() - - # Clean up bad filepaths - tracks = myDB.select('SELECT Location, TrackID from tracks WHERE Location IS NOT NULL') - - for track in tracks: - if not os.path.isfile(track['Location'].encode(headphones.SYS_ENCODING)): - myDB.action('UPDATE tracks SET Location=? WHERE TrackID=?', [None, track['TrackID']]) - if not dir: dir = headphones.MUSIC_DIR @@ -24,6 +15,19 @@ def libraryScan(dir=None): dir = str(dir) except UnicodeEncodeError: dir = unicode(dir).encode('unicode_escape') + + if not os.path.isdir(dir): + logger.warn('Cannot find directory: %s. Not scanning' % dir) + return + + myDB = db.DBConnection() + + # Clean up bad filepaths + tracks = myDB.select('SELECT Location, TrackID from tracks WHERE Location IS NOT NULL') + + for track in tracks: + if not os.path.isfile(track['Location'].encode(headphones.SYS_ENCODING)): + myDB.action('UPDATE tracks SET Location=?, BitRate=? WHERE TrackID=?', [None, None, track['TrackID']]) logger.info('Scanning music directory: %s' % dir) @@ -114,12 +118,14 @@ def libraryScan(dir=None): firstchar = '0-9' else: firstchar = sortname[0] + + lowerfirst = firstchar.lower() - albumvalues = { 'artist': artist, 'album': album, 'year': year, 'first': firstchar, + 'lowerfirst': lowerfirst } @@ -145,16 +151,18 @@ def libraryScan(dir=None): new_file_name = new_file_name.replace('?','_').replace(':', '_') - full_path_to_file = os.path.normpath(os.path.join(headphones.MUSIC_DIR, folder, new_file_name)) + full_path_to_file = os.path.normpath(os.path.join(headphones.MUSIC_DIR, folder, new_file_name)).encode(headphones.SYS_ENCODING, 'replace') match = glob.glob(full_path_to_file) if match: logger.info('Found a match: %s. Writing MBID to metadata' % match[0]) + + unipath = unicode(match[0], headphones.SYS_ENCODING, errors='replace') - myDB.action('UPDATE tracks SET Location=? WHERE TrackID=?', [match[0], track['TrackID']]) - myDB.action('DELETE from have WHERE Location=?', [match[0]]) + myDB.action('UPDATE tracks SET Location=? WHERE TrackID=?', [unipath, track['TrackID']]) + myDB.action('DELETE from have WHERE Location=?', [unipath]) # Try to insert the appropriate track id so we don't have to keep doing this try: diff --git a/headphones/lyrics.py b/headphones/lyrics.py index a3e89352..3c95676e 100644 --- a/headphones/lyrics.py +++ b/headphones/lyrics.py @@ -7,8 +7,8 @@ from headphones import logger def getLyrics(artist, song): - params = { "artist": artist, - "song": song, + params = { "artist": artist.encode('utf-8'), + "song": song.encode('utf-8'), "fmt": 'xml' } @@ -43,7 +43,12 @@ def getLyrics(artist, song): m = re.compile('''

.*?
(.*?)