mirror of
https://github.com/rembo10/headphones.git
synced 2026-04-05 04:29:25 +01:00
Merge remote-tracking branch 'basilfx/bugfixes' into develop
This commit is contained in:
@@ -254,6 +254,13 @@ table.display tr.even.gradeU {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
table.display tr.odd.gradeW {
|
||||
background-color: #ffffaa;
|
||||
}
|
||||
|
||||
table.display tr.even.gradeW {
|
||||
background-color: #ffffaa;
|
||||
}
|
||||
|
||||
table.display tr.odd.gradeZ {
|
||||
background-color: #FAFAFA;
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
lossless<%inherit file="base.html"/>
|
||||
<%inherit file="base.html"/>
|
||||
<%!
|
||||
from headphones import helpers
|
||||
%>
|
||||
|
||||
<%def name="headerIncludes()">
|
||||
<div id="subhead_container">
|
||||
<div id="subhead_menu">
|
||||
<a class="menu_link_edit" href="clearLogs"><i class="fa fa-trash-o"></i> Clear log</a>
|
||||
</div>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
<%def name="body()">
|
||||
<div class="title">
|
||||
<div id="paddingheader">
|
||||
<h1 class="clearfix"><i class="fa fa-flag"></i> Logs</h1>
|
||||
</div>
|
||||
<table class="display" id="log_table">
|
||||
@@ -40,6 +48,8 @@ lossless<%inherit file="base.html"/>
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
initActions();
|
||||
|
||||
$('#log_table').dataTable( {
|
||||
"bProcessing": true,
|
||||
"bServerSide": true,
|
||||
@@ -49,23 +59,26 @@ $(document).ready(function() {
|
||||
"iDisplayLength": 25,
|
||||
"bStateSave": true,
|
||||
"oLanguage": {
|
||||
"sSearch":"",
|
||||
"sSearch":"Filter:",
|
||||
"sLengthMenu":"Show _MENU_ lines per page",
|
||||
"sEmptyTable": "No log information available",
|
||||
"sInfo":"Showing _START_ to _END_ of _TOTAL_ lines",
|
||||
"sInfoEmpty":"Showing 0 to 0 of 0 lines",
|
||||
"sInfoFiltered":"(filtered from _MAX_ total lines)"},
|
||||
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
|
||||
if (aData[1] === "WARNING" || aData[1] === "ERROR")
|
||||
if (aData[1] === "ERROR")
|
||||
{
|
||||
$('td', nRow).closest('tr').addClass("gradeX");
|
||||
}
|
||||
else if (aData[1] === "WARNING")
|
||||
{
|
||||
$('td', nRow).closest('tr').addClass("gradeW");
|
||||
}
|
||||
else
|
||||
{
|
||||
$('td', nRow).closest('tr').addClass("gradeZ");
|
||||
}
|
||||
|
||||
|
||||
|
||||
return nRow;
|
||||
},
|
||||
"fnServerData": function ( sSource, aoData, fnCallback ) {
|
||||
|
||||
@@ -15,20 +15,17 @@
|
||||
|
||||
# NZBGet support added by CurlyMo <curlymoo1@gmail.com> as a part of XBian - XBMC on the Raspberry Pi
|
||||
|
||||
from __future__ import with_statement
|
||||
|
||||
import os, sys, subprocess
|
||||
|
||||
import threading
|
||||
import webbrowser
|
||||
import sqlite3
|
||||
import itertools
|
||||
import cherrypy
|
||||
|
||||
from lib.apscheduler.scheduler import Scheduler
|
||||
from lib.configobj import ConfigObj
|
||||
|
||||
import cherrypy
|
||||
|
||||
from headphones import versioncheck, logger, version
|
||||
from headphones.common import *
|
||||
|
||||
@@ -1093,7 +1090,7 @@ def start():
|
||||
started = True
|
||||
|
||||
def sig_handler(signum=None, frame=None):
|
||||
if type(signum) != type(None):
|
||||
if signum is not None:
|
||||
logger.info("Signal %i caught, saving and exiting...", signum)
|
||||
shutdown()
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ def expand_subfolders(f):
|
||||
difference = max(path_depths) - min(path_depths)
|
||||
|
||||
if difference > 0:
|
||||
logger.info("Found %d media folders, but depth difference between lowest and deepest media folder is %d (expected zero). If this is a discography or a collection of albums, make sure albums are per folder" % (len(media_folders), difference))
|
||||
logger.info("Found %d media folders, but depth difference between lowest and deepest media folder is %d (expected zero). If this is a discography or a collection of albums, make sure albums are per folder.", len(media_folders), difference)
|
||||
|
||||
# While already failed, advice the user what he could try. We assume the
|
||||
# directory may contain separate CD's and maybe some extra's. The
|
||||
@@ -283,7 +283,7 @@ def expand_subfolders(f):
|
||||
extra_media_folders = [ media_folder[:min(path_depths)] for media_folder in media_folders if len(media_folder) > min(path_depths) ]
|
||||
extra_media_folders = list(set([ os.path.join(*media_folder) for media_folder in extra_media_folders ]))
|
||||
|
||||
logger.info("Please look at the following folder(s), since they cause the depth difference: %s" % extra_media_folders)
|
||||
logger.info("Please look at the following folder(s), since they cause the depth difference: %s", extra_media_folders)
|
||||
return
|
||||
|
||||
# Convert back to paths and remove duplicates, which may be there after
|
||||
@@ -297,7 +297,7 @@ def expand_subfolders(f):
|
||||
logger.debug("Did not expand subfolder, as it resulted in one folder.")
|
||||
return
|
||||
|
||||
logger.debug("Expanded subfolders in folder: " % media_folders)
|
||||
logger.debug("Expanded subfolders in folder: %s", media_folders)
|
||||
return media_folders
|
||||
|
||||
def extract_data(s):
|
||||
@@ -374,14 +374,14 @@ def extract_metadata(f):
|
||||
|
||||
# Verify results
|
||||
if len(results) == 0:
|
||||
logger.info("No metadata in media files found, ignoring")
|
||||
logger.info("No metadata in media files found, ignoring.")
|
||||
return (None, None, None)
|
||||
|
||||
# Require that some percentage of files have tags
|
||||
count_ratio = 0.75
|
||||
|
||||
if count < (count_ratio * len(results)):
|
||||
logger.info("Counted %d media files, but only %d have tags, ignoring" % (count, len(results)))
|
||||
logger.info("Counted %d media files, but only %d have tags, ignoring.", count, len(results))
|
||||
return (None, None, None)
|
||||
|
||||
# Count distinct values
|
||||
@@ -399,7 +399,7 @@ def extract_metadata(f):
|
||||
old_album = new_albums[index]
|
||||
new_albums[index] = RE_CD_ALBUM.sub("", album).strip()
|
||||
|
||||
logger.debug("Stripped albumd number identifier: %s -> %s" % (old_album, new_albums[index]))
|
||||
logger.debug("Stripped albumd number identifier: %s -> %s", old_album, new_albums[index])
|
||||
|
||||
# Remove duplicates
|
||||
new_albums = list(set(new_albums))
|
||||
@@ -417,7 +417,7 @@ def extract_metadata(f):
|
||||
if len(artists) > 1 and len(albums) == 1:
|
||||
split_artists = [ RE_FEATURING.split(artist) for artist in artists ]
|
||||
featurings = [ len(split_artist) - 1 for split_artist in split_artists ]
|
||||
logger.info("Album seem to feature %d different artists" % sum(featurings))
|
||||
logger.info("Album seem to feature %d different artists", sum(featurings))
|
||||
|
||||
if sum(featurings) > 0:
|
||||
# Find the artist of which the least splits have been generated.
|
||||
@@ -429,8 +429,8 @@ def extract_metadata(f):
|
||||
return (artist, albums[0], years[0])
|
||||
|
||||
# Not sure what to do here.
|
||||
logger.info("Found %d artists, %d albums and %d years in metadata, so ignoring" % (len(artists), len(albums), len(years)))
|
||||
logger.debug("Artists: %s, Albums: %s, Years: %s" % (artists, albums, years))
|
||||
logger.info("Found %d artists, %d albums and %d years in metadata, so ignoring", len(artists), len(albums), len(years))
|
||||
logger.debug("Artists: %s, Albums: %s, Years: %s", artists, albums, years)
|
||||
|
||||
return (None, None, None)
|
||||
|
||||
@@ -486,7 +486,7 @@ def smartMove(src, dest, delete=True):
|
||||
filename = os.path.basename(src)
|
||||
|
||||
if os.path.isfile(os.path.join(dest, filename)):
|
||||
logger.info('Destination file exists: %s', os.path.join(dest, filename).decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.info('Destination file exists: %s', os.path.join(dest, filename))
|
||||
title = os.path.splitext(filename)[0]
|
||||
ext = os.path.splitext(filename)[1]
|
||||
i = 1
|
||||
|
||||
@@ -55,7 +55,7 @@ def initLogger(verbose=1):
|
||||
|
||||
# Configure the logger to accept all messages
|
||||
logger.propagate = False
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.setLevel(logging.DEBUG if verbose == 2 else logging.INFO)
|
||||
|
||||
# Setup file logger
|
||||
filename = os.path.join(headphones.LOG_DIR, FILENAME)
|
||||
@@ -69,7 +69,7 @@ def initLogger(verbose=1):
|
||||
|
||||
# Add list logger
|
||||
loglist_handler = LogListHandler()
|
||||
loglist_handler.setLevel(logging.INFO)
|
||||
loglist_handler.setLevel(logging.DEBUG)
|
||||
|
||||
logger.addHandler(loglist_handler)
|
||||
|
||||
@@ -78,11 +78,7 @@ def initLogger(verbose=1):
|
||||
console_formatter = logging.Formatter('%(asctime)s - %(levelname)s :: %(threadName)s : %(message)s', '%d-%b-%Y %H:%M:%S')
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setFormatter(console_formatter)
|
||||
|
||||
if verbose == 1:
|
||||
console_handler.setLevel(logging.INFO)
|
||||
elif verbose == 2:
|
||||
console_handler.setLevel(logging.DEBUG)
|
||||
console_handler.setLevel(logging.DEBUG)
|
||||
|
||||
logger.addHandler(console_handler)
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Headphones. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import with_statement
|
||||
|
||||
import time
|
||||
import threading
|
||||
|
||||
|
||||
@@ -13,22 +13,20 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Headphones. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import with_statement
|
||||
|
||||
import os
|
||||
import time
|
||||
import threading
|
||||
import music_encoder
|
||||
import shutil, re
|
||||
import re
|
||||
import shutil
|
||||
import uuid
|
||||
from headphones import notifiers
|
||||
import beets
|
||||
import threading
|
||||
import headphones
|
||||
|
||||
from beets import autotag
|
||||
from beets.mediafile import MediaFile
|
||||
|
||||
import headphones
|
||||
from headphones import db, albumart, librarysync, lyrics, logger, helpers, request
|
||||
from headphones.helpers import sab_replace_dots, sab_replace_spaces
|
||||
from headphones import notifiers
|
||||
from headphones import db, albumart, librarysync, lyrics
|
||||
from headphones import logger, helpers, request, mb, music_encoder
|
||||
|
||||
postprocessor_lock = threading.Lock()
|
||||
|
||||
@@ -48,9 +46,9 @@ def checkFolder():
|
||||
# iterations in just in case we can't read the config for some reason
|
||||
|
||||
nzb_album_possibilities = [ album['FolderName'],
|
||||
sab_replace_dots(album['FolderName']),
|
||||
sab_replace_spaces(album['FolderName']),
|
||||
sab_replace_spaces(sab_replace_dots(album['FolderName']))
|
||||
helpers.sab_replace_dots(album['FolderName']),
|
||||
helpers.sab_replace_spaces(album['FolderName']),
|
||||
helpers.sab_replace_spaces(sab_replace_dots(album['FolderName']))
|
||||
]
|
||||
|
||||
for nzb_folder_name in nzb_album_possibilities:
|
||||
@@ -80,8 +78,6 @@ def verify(albumid, albumpath, Kind=None, forced=False):
|
||||
#from an RSS feed or etc
|
||||
#TODO: This should be a call to a class method.. copied it out of importer with only minor changes
|
||||
#TODO: odd things can happen when there are diacritic characters in the folder name, need to translate them?
|
||||
import mb
|
||||
|
||||
release_list = None
|
||||
|
||||
try:
|
||||
@@ -746,13 +742,13 @@ def moveFiles(albumpath, release, tracks):
|
||||
try:
|
||||
os.chmod(os.path.normpath(temp_f).encode(headphones.SYS_ENCODING, 'replace'), int(headphones.FOLDER_PERMISSIONS, 8))
|
||||
except Exception, e:
|
||||
logger.error("Error trying to change permissions on folder: %s" % temp_f.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.error("Error trying to change permissions on folder: %s. %s", temp_f.decode(headphones.SYS_ENCODING, 'replace'), e)
|
||||
|
||||
# If we failed to move all the files out of the directory, this will fail too
|
||||
try:
|
||||
shutil.rmtree(albumpath)
|
||||
except Exception, e:
|
||||
logger.error('Could not remove directory: %s. %s' % (albumpath.decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
logger.error('Could not remove directory: %s. %s', albumpath.decode(headphones.SYS_ENCODING, 'replace'), e)
|
||||
|
||||
destination_paths = []
|
||||
|
||||
@@ -779,10 +775,10 @@ def correctMetadata(albumid, release, downloaded_track_list):
|
||||
elif any(downloaded_track.lower().endswith('.' + x.lower()) for x in headphones.LOSSY_MEDIA_FORMATS):
|
||||
lossy_items.append(beets.library.Item.from_path(downloaded_track))
|
||||
else:
|
||||
logger.warn("Skipping: " + downloaded_track.decode(headphones.SYS_ENCODING, 'replace') + " because it is not a mutagen friendly file format")
|
||||
logger.warn("Skipping: %s because it is not a mutagen friendly file format", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
except Exception, e:
|
||||
|
||||
logger.error("Beets couldn't create an Item from: " + downloaded_track.decode(headphones.SYS_ENCODING, 'replace') + " - not a media file?" + str(e))
|
||||
logger.error("Beets couldn't create an Item from: %s - not a media file? %s", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e))
|
||||
|
||||
for items in [lossy_items, lossless_items]:
|
||||
|
||||
@@ -792,16 +788,16 @@ def correctMetadata(albumid, release, downloaded_track_list):
|
||||
try:
|
||||
cur_artist, cur_album, candidates, rec = autotag.tag_album(items, search_artist=helpers.latinToAscii(release['ArtistName']), search_album=helpers.latinToAscii(release['AlbumTitle']))
|
||||
except Exception, e:
|
||||
logger.error('Error getting recommendation: %s. Not writing metadata' % e)
|
||||
logger.error('Error getting recommendation: %s. Not writing metadata', e)
|
||||
return
|
||||
if str(rec) == 'recommendation.none':
|
||||
logger.warn('No accurate album match found for %s, %s - not writing metadata' % (release['ArtistName'], release['AlbumTitle']))
|
||||
logger.warn('No accurate album match found for %s, %s - not writing metadata', release['ArtistName'], release['AlbumTitle'])
|
||||
return
|
||||
|
||||
if candidates:
|
||||
dist, info, mapping, extra_items, extra_tracks = candidates[0]
|
||||
else:
|
||||
logger.warn('No accurate album match found for %s, %s - not writing metadata' % (release['ArtistName'], release['AlbumTitle']))
|
||||
logger.warn('No accurate album match found for %s, %s - not writing metadata', release['ArtistName'], release['AlbumTitle'])
|
||||
return
|
||||
|
||||
logger.info('Beets recommendation for tagging items: %s' % rec)
|
||||
@@ -813,9 +809,9 @@ def correctMetadata(albumid, release, downloaded_track_list):
|
||||
for item in items:
|
||||
try:
|
||||
item.write()
|
||||
logger.info("Successfully applied metadata to: " + item.path.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.info("Successfully applied metadata to: %s", item.path.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
except Exception, e:
|
||||
logger.warn("Error writing metadata to " + item.path.decode(headphones.SYS_ENCODING, 'replace') + ": " + str(e))
|
||||
logger.warn("Error writing metadata to '%s': %s", item.path.decode(headphones.SYS_ENCODING, 'replace'), str(e))
|
||||
|
||||
def embedLyrics(downloaded_track_list):
|
||||
logger.info('Adding lyrics')
|
||||
@@ -827,7 +823,7 @@ def embedLyrics(downloaded_track_list):
|
||||
try:
|
||||
f = MediaFile(downloaded_track)
|
||||
except:
|
||||
logger.error('Could not read %s. Not checking lyrics' % downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.error('Could not read %s. Not checking lyrics', downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
continue
|
||||
|
||||
if f.albumartist and f.title:
|
||||
@@ -835,16 +831,16 @@ def embedLyrics(downloaded_track_list):
|
||||
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.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.info('No artist/track metadata found for track: %s. Not fetching lyrics', downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
metalyrics = None
|
||||
|
||||
if lyrics:
|
||||
logger.debug('Adding lyrics to: %s' % downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.debug('Adding lyrics to: %s', downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
f.lyrics = metalyrics
|
||||
try:
|
||||
f.save()
|
||||
except:
|
||||
logger.error('Cannot save lyrics to: %s. Skipping' % downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.error('Cannot save lyrics to: %s. Skipping', downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
continue
|
||||
|
||||
def renameFiles(albumpath, downloaded_track_list, release):
|
||||
@@ -859,7 +855,7 @@ def renameFiles(albumpath, downloaded_track_list, release):
|
||||
try:
|
||||
f = MediaFile(downloaded_track)
|
||||
except:
|
||||
logger.info("MediaFile couldn't parse: " + downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.info("MediaFile couldn't parse: %s", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
continue
|
||||
|
||||
if not f.disc:
|
||||
@@ -928,11 +924,11 @@ def renameFiles(albumpath, downloaded_track_list, release):
|
||||
logger.debug("Renaming for: " + downloaded_track.decode(headphones.SYS_ENCODING, 'replace') + " is not neccessary")
|
||||
continue
|
||||
|
||||
logger.debug('Renaming %s ---> %s' % (downloaded_track.decode(headphones.SYS_ENCODING,'replace'), new_file_name.decode(headphones.SYS_ENCODING,'replace')))
|
||||
logger.debug('Renaming %s ---> %s', downloaded_track.decode(headphones.SYS_ENCODING,'replace'), new_file_name.decode(headphones.SYS_ENCODING,'replace'))
|
||||
try:
|
||||
os.rename(downloaded_track, new_file)
|
||||
except Exception, e:
|
||||
logger.error('Error renaming file: %s. Error: %s' % (downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
logger.error('Error renaming file: %s. Error: %s', downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), e)
|
||||
continue
|
||||
|
||||
def updateFilePermissions(albumpaths):
|
||||
@@ -1044,7 +1040,6 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None):
|
||||
continue
|
||||
else:
|
||||
logger.info('Querying MusicBrainz for the release group id for: %s - %s', name, album)
|
||||
from headphones import mb
|
||||
try:
|
||||
rgid = mb.findAlbumID(helpers.latinToAscii(name), helpers.latinToAscii(album))
|
||||
except:
|
||||
@@ -1072,7 +1067,6 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None):
|
||||
continue
|
||||
else:
|
||||
logger.info('Querying MusicBrainz for the release group id for: %s - %s', name, album)
|
||||
from headphones import mb
|
||||
try:
|
||||
rgid = mb.findAlbumID(helpers.latinToAscii(name), helpers.latinToAscii(album))
|
||||
except:
|
||||
@@ -1116,7 +1110,6 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None):
|
||||
continue
|
||||
else:
|
||||
logger.info('Querying MusicBrainz for the release group id for: %s', folder)
|
||||
from headphones import mb
|
||||
try:
|
||||
rgid = mb.findAlbumID(album=helpers.latinToAscii(folder))
|
||||
except:
|
||||
@@ -1129,3 +1122,4 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None):
|
||||
else:
|
||||
logger.info('No match found on MusicBrainz for: %s - %s', name, album)
|
||||
|
||||
| ||||