mirror of
https://github.com/rembo10/headphones.git
synced 2026-05-16 00:25:31 +01:00
Merge branch 'develop'
This commit is contained in:
@@ -153,7 +153,7 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Blackhole</legend>
|
||||
<legend>Usenet</legend>
|
||||
<div class="row checkbox">
|
||||
<input id="useblackhole" type="checkbox" name="blackhole" value=1 ${config['use_blackhole']} /><label>Use Black Hole</label>
|
||||
</div>
|
||||
|
||||
@@ -866,7 +866,8 @@ div#artistheader h2 a {
|
||||
text-align: left;
|
||||
}
|
||||
#artist_table th#status,
|
||||
#artist_table th#albumart {
|
||||
#artist_table th#albumart,
|
||||
#artist_table th#lastupdated {
|
||||
min-width: 50px;
|
||||
text-align: left;
|
||||
}
|
||||
@@ -878,7 +879,8 @@ div#artistheader h2 a {
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#artist_table td#status {
|
||||
#artist_table td#status,
|
||||
#artist_table td#lastupdated {
|
||||
min-width: 50px;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
@@ -1295,6 +1297,7 @@ div#artistheader h2 a {
|
||||
clear: both;
|
||||
}
|
||||
#album_table th#albumname,
|
||||
#album_table th#artistname,
|
||||
#upcoming_table th#artistname,
|
||||
#wanted_table th#artistname {
|
||||
min-width: 150px;
|
||||
@@ -1317,6 +1320,7 @@ div#artistheader h2 a {
|
||||
vertical-align: middle;
|
||||
}
|
||||
#album_table td#albumname,
|
||||
#album_table td#artistname,
|
||||
#album_table td#reldate,
|
||||
#album_table td#type,
|
||||
#track_table td#duration,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<%def name="headerIncludes()">
|
||||
<div id="subhead_container">
|
||||
<div id="subhead_menu">
|
||||
<a id="menu_link_edit" href="manageAlbums">Manage Albums</a>
|
||||
<a id="menu_link_edit" href="manageArtists">Manage Artists</a>
|
||||
%if not headphones.ADD_ARTISTS:
|
||||
<a id="menu_link_edit" href="manageNew">Manage New Artists</a>
|
||||
@@ -101,4 +102,4 @@
|
||||
initThisPage();
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
</%def>
|
||||
|
||||
148
data/interfaces/default/managealbums.html
Normal file
148
data/interfaces/default/managealbums.html
Normal file
@@ -0,0 +1,148 @@
|
||||
<%inherit file="base.html" />
|
||||
<%!
|
||||
from headphones import db
|
||||
import headphones
|
||||
%>
|
||||
|
||||
<%def name="headerIncludes()">
|
||||
<div id="subhead_container">
|
||||
|
||||
</div>
|
||||
<a href="manage" class="back">« Back to manage overview</a>
|
||||
</%def>
|
||||
|
||||
|
||||
<%def name="body()">
|
||||
<div class="table_wrapper">
|
||||
<div id="manageheader" class="title">
|
||||
<h1 class="clearfix"><img src="interfaces/default/images/icon_manage.png" alt="manage"/>Manage Albums</h1>
|
||||
</div>
|
||||
<form action="markAlbums" method="get" id="markAlbums">
|
||||
<div id="markalbum">Mark selected albums as
|
||||
<select name="action" onChange="doAjaxCall('markAlbums',$(this),'table',true);" data-error="You didn't select any albums">
|
||||
<option disabled="disabled" selected="selected">Choose...</option>
|
||||
<option value="Wanted">Wanted</option>
|
||||
<option value="WantedNew">Wanted (new only)</option>
|
||||
<option value="WantedLossless">Wanted (lossless)</option>
|
||||
<option value="Skipped">Skipped</option>
|
||||
<option value="Downloaded">Downloaded</option>
|
||||
</select>
|
||||
<input type="hidden" value="Go">
|
||||
</div>
|
||||
<table class="display" id="album_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="select"><input type="checkbox" onClick="toggle(this)" /></th>
|
||||
<th id="albumname">Album</th>
|
||||
<th id="artistname">Artist</th>
|
||||
<th id="reldate">Date</th>
|
||||
<th id="type">Type</th>
|
||||
<th id="status">Status</th>
|
||||
<th id="have">Have</th>
|
||||
<th id="bitrate">Bitrate</th>
|
||||
<th id="albumformat">Format</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
%for album in albums:
|
||||
<%
|
||||
if album['Status'] == 'Skipped':
|
||||
grade = 'Z'
|
||||
elif album['Status'] == 'Wanted':
|
||||
grade = 'X'
|
||||
elif album['Status'] == 'Snatched':
|
||||
grade = 'C'
|
||||
else:
|
||||
grade = 'A'
|
||||
|
||||
myDB = db.DBConnection()
|
||||
totaltracks = len(myDB.select('SELECT TrackTitle from tracks WHERE AlbumID=?', [album['AlbumID']]))
|
||||
havetracks = len(myDB.select('SELECT TrackTitle from tracks WHERE AlbumID=? AND Location IS NOT NULL', [album['AlbumID']])) + len(myDB.select('SELECT TrackTitle from have WHERE ArtistName like ? AND AlbumTitle LIKE ?', [album['ArtistName'], album['AlbumTitle']]))
|
||||
|
||||
try:
|
||||
percent = (havetracks*100.0)/totaltracks
|
||||
if percent > 100:
|
||||
percent = 100
|
||||
except (ZeroDivisionError, TypeError):
|
||||
percent = 0
|
||||
totaltracks = '?'
|
||||
|
||||
avgbitrate = myDB.action("SELECT AVG(BitRate) FROM tracks WHERE AlbumID=?", [album['AlbumID']]).fetchone()[0]
|
||||
if avgbitrate:
|
||||
bitrate = str(int(avgbitrate)/1000) + ' kbps'
|
||||
else:
|
||||
bitrate = ''
|
||||
|
||||
albumformatcount = myDB.action("SELECT COUNT(DISTINCT Format) FROM tracks WHERE AlbumID=?", [album['AlbumID']]).fetchone()[0]
|
||||
if albumformatcount == 1:
|
||||
albumformat = myDB.action("SELECT DISTINCT Format FROM tracks WHERE AlbumID=?", [album['AlbumID']]).fetchone()[0]
|
||||
elif albumformatcount > 1:
|
||||
albumformat = 'Mixed'
|
||||
else:
|
||||
albumformat = ''
|
||||
|
||||
lossy_formats = [str.upper(fmt) for fmt in headphones.LOSSY_MEDIA_FORMATS]
|
||||
|
||||
%>
|
||||
<tr class="grade${grade}">
|
||||
<td id="select"><input type="checkbox" name="${album['AlbumID']}" class="checkbox" /></td>
|
||||
<td id="albumname"><a href="albumPage?AlbumID=${album['AlbumID']}">${album['AlbumTitle']}</a></td>
|
||||
<td id="artistname"><a href="artistPage?ArtistID=${album['ArtistID']}">${album['ArtistName']}</a></td>
|
||||
<td id="reldate">${album['ReleaseDate']}</td>
|
||||
<td id="type">${album['Type']}</td>
|
||||
<td id="status">${album['Status']}</td>
|
||||
<td id="have"><span title="${percent}"><span><div class="progress-container"><div style="width:${percent}%"><div class="havetracks">${havetracks}/${totaltracks}</div></div></div></td>
|
||||
<td id="bitrate">${bitrate}</td>
|
||||
<td id="albumformat">${albumformat}</td>
|
||||
</tr>
|
||||
%endfor
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
<%def name="headIncludes()">
|
||||
<link rel="stylesheet" href="interfaces/default/css/data_table.css">
|
||||
</%def>
|
||||
|
||||
<%def name="javascriptIncludes()">
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
<script>
|
||||
|
||||
function initThisPage() {
|
||||
$('#album_table').dataTable({
|
||||
"bDestroy": true,
|
||||
"aoColumns": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{ "sType": "title-numeric"},
|
||||
null,
|
||||
null
|
||||
],
|
||||
"aoColumnDefs": [
|
||||
{ 'bSortable': false, 'aTargets': [ 0 ] }
|
||||
],
|
||||
"oLanguage": {
|
||||
"sLengthMenu":"Show _MENU_ albums per page",
|
||||
"sEmptyTable": "No album information available",
|
||||
"sInfo":"Showing _TOTAL_ albums",
|
||||
"sInfoEmpty":"Showing 0 to 0 of 0 albums",
|
||||
"sInfoFiltered":"(filtered from _MAX_ total albums)",
|
||||
"sSearch": ""},
|
||||
"bPaginate": false,
|
||||
"aaSorting": [[5, 'desc']]
|
||||
|
||||
});
|
||||
resetFilters("albums");
|
||||
}
|
||||
$(document).ready(function() {
|
||||
initThisPage();
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
<th id="name">Artist Name</th>
|
||||
<th id="status">Status</th>
|
||||
<th id="album">Latest Album</th>
|
||||
<th id="lastupdated">Last Updated</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -56,13 +57,20 @@
|
||||
else:
|
||||
releasedate = ''
|
||||
albumdisplay = '<i>None</i>'
|
||||
|
||||
if not artist['LastUpdated']:
|
||||
lastupdated = "Never"
|
||||
else:
|
||||
lastupdated = artist['LastUpdated']
|
||||
|
||||
%>
|
||||
<tr class="grade${grade}">
|
||||
<td id="select"><input type="checkbox" name="${artist['ArtistID']}" class="checkbox" /></td>
|
||||
<td id="albumart"><div id="artistImg"><img class="albumArt" height="50" width="50"></div></td>
|
||||
<td id="name"><span title="${artist['ArtistSortName']}"></span><a href="artistPage?ArtistID=${artist['ArtistID']}" title="${artist['ArtistID']}">${artist['ArtistName']}</a></td>
|
||||
<td id="albumart"><div id="artistImg"><img class="albumArt" id="${artist['ArtistID']}" height="50" width="50"></div></td>
|
||||
<td id="name"><span title="${artist['ArtistSortName']}"></span><a href="artistPage?ArtistID=${artist['ArtistID']}">${artist['ArtistName']}</a></td>
|
||||
<td id="status">${artist['Status']}</td>
|
||||
<td id="album"><span title="${releasedate}"></span><a href="albumPage?AlbumID=${artist['AlbumID']}">${albumdisplay}</a></td>
|
||||
<td id="lastupdated">${lastupdated}</td>
|
||||
</tr>
|
||||
%endfor
|
||||
</tbody>
|
||||
@@ -79,9 +87,9 @@
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
<script>
|
||||
function getArtistArt() {
|
||||
$("table#artist_table tr td#name").each(function(){
|
||||
var id = $(this).children('a').attr('title');
|
||||
var image = $(this).parent().find("td#albumart img");
|
||||
$("table#artist_table tr td#albumart #artistImg").each(function(){
|
||||
var id = $(this).children('img').attr('id');
|
||||
var image = $(this).children('img');
|
||||
if ( !image.hasClass('done') ) {
|
||||
image.addClass('done');
|
||||
getThumb(image,id,'artist');
|
||||
@@ -98,7 +106,8 @@
|
||||
null,
|
||||
{ "sType": "title-string"},
|
||||
null,
|
||||
{ "sType": "title-string"}
|
||||
{ "sType": "title-string"},
|
||||
null
|
||||
],
|
||||
"oLanguage": {
|
||||
"sSearch" : ""},
|
||||
|
||||
@@ -298,7 +298,7 @@ def initialize():
|
||||
DOWNLOAD_DIR = check_setting_str(CFG, 'General', 'download_dir', '')
|
||||
BLACKHOLE = bool(check_setting_int(CFG, 'General', 'blackhole', 0))
|
||||
BLACKHOLE_DIR = check_setting_str(CFG, 'General', 'blackhole_dir', '')
|
||||
USENET_RETENTION = check_setting_int(CFG, 'General', 'usenet_retention', '')
|
||||
USENET_RETENTION = check_setting_int(CFG, 'General', 'usenet_retention', '1500')
|
||||
INCLUDE_EXTRAS = bool(check_setting_int(CFG, 'General', 'include_extras', 0))
|
||||
AUTOWANT_UPCOMING = bool(check_setting_int(CFG, 'General', 'autowant_upcoming', 1))
|
||||
AUTOWANT_ALL = bool(check_setting_int(CFG, 'General', 'autowant_all', 0))
|
||||
@@ -679,6 +679,7 @@ def dbcheck():
|
||||
c.execute('CREATE TABLE IF NOT EXISTS have (ArtistName TEXT, AlbumTitle TEXT, TrackNumber TEXT, TrackTitle TEXT, TrackLength TEXT, BitRate TEXT, Genre TEXT, Date TEXT, TrackID TEXT, Location TEXT, CleanName TEXT, Format TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS lastfmcloud (ArtistName TEXT, ArtistID TEXT, Count INTEGER)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS descriptions (ArtistID TEXT, ReleaseGroupID TEXT, ReleaseID TEXT, Summary TEXT, Content TEXT, LastUpdated TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS blacklist (ArtistID TEXT UNIQUE)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS releases (ReleaseID TEXT, ReleaseGroupID TEXT, UNIQUE(ReleaseID, ReleaseGroupID))')
|
||||
c.execute('CREATE INDEX IF NOT EXISTS tracks_albumid ON tracks(AlbumID ASC)')
|
||||
c.execute('CREATE INDEX IF NOT EXISTS album_artistid_reldate ON albums(ArtistID ASC, ReleaseDate DESC)')
|
||||
|
||||
@@ -56,14 +56,20 @@ def artistlist_to_mbids(artistlist, forced=False):
|
||||
except IndexError:
|
||||
logger.info('MusicBrainz query turned up no matches for: %s' % artist)
|
||||
continue
|
||||
|
||||
# Check if it's blacklisted/various artists
|
||||
myDB = db.DBConnection()
|
||||
bl_artist = myDB.action('SELECT * FROM blacklist WHERE ArtistID=?', [artistid]).fetchone()
|
||||
if bl_artist or artistid == various_artists_mbid:
|
||||
logger.info("Artist ID for '%s' is either blacklisted or Various Artists. To add artist, you must do it manually (Artist ID: %s)" % (artist, artistid))
|
||||
continue
|
||||
|
||||
# Add to database if it doesn't exist
|
||||
if artistid != various_artists_mbid and not is_exists(artistid):
|
||||
if not is_exists(artistid):
|
||||
addArtisttoDB(artistid)
|
||||
|
||||
# Just update the tracks if it does
|
||||
else:
|
||||
myDB = db.DBConnection()
|
||||
havetracks = len(myDB.select('SELECT TrackTitle from tracks WHERE ArtistID=?', [artistid])) + len(myDB.select('SELECT TrackTitle from have WHERE ArtistName like ?', [artist]))
|
||||
myDB.action('UPDATE artists SET HaveTracks=? WHERE ArtistID=?', [havetracks, artistid])
|
||||
|
||||
@@ -82,7 +88,7 @@ def addArtistIDListToDB(artistidlist):
|
||||
|
||||
def addArtisttoDB(artistid, extrasonly=False):
|
||||
|
||||
# Putting this here to get around the circular import
|
||||
# Putting this here to get around the circular import. We're using this to update thumbnails for artist/albums
|
||||
from headphones import cache
|
||||
|
||||
# Can't add various artists - throws an error from MB
|
||||
@@ -91,6 +97,9 @@ def addArtisttoDB(artistid, extrasonly=False):
|
||||
return
|
||||
|
||||
myDB = db.DBConnection()
|
||||
|
||||
# Delete from blacklist if it's on there
|
||||
myDB.action('DELETE from blacklist WHERE ArtistID=?', [artistid])
|
||||
|
||||
# We need the current minimal info in the database instantly
|
||||
# so we don't throw a 500 error when we redirect to the artistPage
|
||||
|
||||
@@ -26,13 +26,10 @@ def libraryScan(dir=None):
|
||||
if not dir:
|
||||
dir = headphones.MUSIC_DIR
|
||||
|
||||
try:
|
||||
dir = str(dir)
|
||||
except UnicodeEncodeError:
|
||||
dir = unicode(dir).encode('unicode_escape')
|
||||
dir = dir.encode(headphones.SYS_ENCODING)
|
||||
|
||||
if not os.path.isdir(dir):
|
||||
logger.warn('Cannot find directory: %s. Not scanning' % dir)
|
||||
logger.warn('Cannot find directory: %s. Not scanning' % dir.decode(headphones.SYS_ENCODING))
|
||||
return
|
||||
|
||||
myDB = db.DBConnection()
|
||||
@@ -57,14 +54,13 @@ def libraryScan(dir=None):
|
||||
if any(files.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS):
|
||||
|
||||
song = os.path.join(r, files)
|
||||
file = unicode(os.path.join(r, files), headphones.SYS_ENCODING, errors='replace')
|
||||
|
||||
# Try to read the metadata
|
||||
try:
|
||||
f = MediaFile(song)
|
||||
|
||||
except:
|
||||
logger.error('Cannot read file: ' + file)
|
||||
logger.error('Cannot read file: ' + song.decode(headphones.SYS_ENCODING))
|
||||
continue
|
||||
|
||||
# Grab the bitrates for the auto detect bit rate option
|
||||
@@ -87,7 +83,7 @@ def libraryScan(dir=None):
|
||||
track = myDB.action('SELECT TrackID from tracks WHERE ArtistName LIKE ? AND AlbumTitle LIKE ? AND TrackTitle LIKE ?', [f_artist, f.album, f.title]).fetchone()
|
||||
|
||||
if track:
|
||||
myDB.action('UPDATE tracks SET Location=?, BitRate=?, Format=? WHERE TrackID=?', [file, f.bitrate, f.format, track['TrackID']])
|
||||
myDB.action('UPDATE tracks SET Location=?, BitRate=?, Format=? WHERE TrackID=?', [song.decode(headphones.SYS_ENCODING), f.bitrate, f.format, track['TrackID']])
|
||||
continue
|
||||
|
||||
# Try to match on mbid if available and we couldn't find a match based on metadata
|
||||
@@ -98,114 +94,16 @@ def libraryScan(dir=None):
|
||||
track = myDB.action('SELECT TrackID from tracks WHERE TrackID=?', [f.mb_trackid]).fetchone()
|
||||
|
||||
if track:
|
||||
myDB.action('UPDATE tracks SET Location=?, BitRate=?, Format=? WHERE TrackID=?', [file, f.bitrate, f.format, track['TrackID']])
|
||||
myDB.action('UPDATE tracks SET Location=?, BitRate=?, Format=? WHERE TrackID=?', [song.decode(headphones.SYS_ENCODING), f.bitrate, f.format, track['TrackID']])
|
||||
continue
|
||||
|
||||
# if we can't find a match in the database on a track level, it might be a new artist or it might be on a non-mb release
|
||||
new_artists.append(f_artist)
|
||||
|
||||
# The have table will become the new database for unmatched tracks (i.e. tracks with no associated links in the database
|
||||
myDB.action('INSERT INTO have (ArtistName, AlbumTitle, TrackNumber, TrackTitle, TrackLength, BitRate, Genre, Date, TrackID, Location, CleanName, Format) VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [f_artist, f.album, f.track, f.title, f.length, f.bitrate, f.genre, f.date, f.mb_trackid, file, helpers.cleanName(f_artist+' '+f.album+' '+f.title), f.format])
|
||||
myDB.action('INSERT INTO have (ArtistName, AlbumTitle, TrackNumber, TrackTitle, TrackLength, BitRate, Genre, Date, TrackID, Location, CleanName, Format) VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [f_artist, f.album, f.track, f.title, f.length, f.bitrate, f.genre, f.date, f.mb_trackid, song.decode(headphones.SYS_ENCODING), helpers.cleanName(f_artist+' '+f.album+' '+f.title), f.format])
|
||||
|
||||
logger.info('Completed scanning of directory: %s' % dir)
|
||||
logger.info('Checking filepaths to see if we can find any matches')
|
||||
|
||||
# Now check empty file paths to see if we can find a match based on their folder format
|
||||
tracks = myDB.select('SELECT * from tracks WHERE Location IS NULL')
|
||||
for track in tracks:
|
||||
|
||||
release = myDB.action('SELECT * from albums WHERE AlbumID=?', [track['AlbumID']]).fetchone()
|
||||
|
||||
try:
|
||||
year = release['ReleaseDate'][:4]
|
||||
except TypeError:
|
||||
year = ''
|
||||
|
||||
artist = release['ArtistName'].replace('/', '_')
|
||||
album = release['AlbumTitle'].replace('/', '_')
|
||||
releasetype = release['Type'].replace('/', '_')
|
||||
|
||||
if release['ArtistName'].startswith('The '):
|
||||
sortname = release['ArtistName'][4:]
|
||||
else:
|
||||
sortname = release['ArtistName']
|
||||
|
||||
if sortname.isdigit():
|
||||
firstchar = '0-9'
|
||||
else:
|
||||
firstchar = sortname[0]
|
||||
|
||||
|
||||
albumvalues = { '$Artist': artist,
|
||||
'$Album': album,
|
||||
'$Year': year,
|
||||
'$Type': releasetype,
|
||||
'$First': firstchar,
|
||||
'$artist': artist.lower(),
|
||||
'$album': album.lower(),
|
||||
'$year': year,
|
||||
'$type': releasetype.lower(),
|
||||
'$first': firstchar.lower()
|
||||
}
|
||||
|
||||
|
||||
folder = helpers.replace_all(headphones.FOLDER_FORMAT, albumvalues)
|
||||
folder = folder.replace('./', '_/').replace(':','_').replace('?','_')
|
||||
|
||||
if folder.endswith('.'):
|
||||
folder = folder.replace(folder[len(folder)-1], '_')
|
||||
|
||||
if not track['TrackNumber']:
|
||||
tracknumber = ''
|
||||
else:
|
||||
tracknumber = '%02d' % track['TrackNumber']
|
||||
|
||||
title = track['TrackTitle']
|
||||
|
||||
trackvalues = { '$Track': tracknumber,
|
||||
'$Title': title,
|
||||
'$Artist': release['ArtistName'],
|
||||
'$Album': release['AlbumTitle'],
|
||||
'$Year': year,
|
||||
'$track': tracknumber,
|
||||
'$title': title.lower(),
|
||||
'$artist': release['ArtistName'].lower(),
|
||||
'$album': release['AlbumTitle'].lower(),
|
||||
'$year': year
|
||||
}
|
||||
|
||||
new_file_name = helpers.replace_all(headphones.FILE_FORMAT, trackvalues).replace('/','_') + '.*'
|
||||
|
||||
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)).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=?', [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:
|
||||
f = MediaFile(match[0])
|
||||
f.mb_trackid = track['TrackID']
|
||||
f.save()
|
||||
myDB.action('UPDATE tracks SET BitRate=?, Format=? WHERE TrackID=?', [f.bitrate, f.format, track['TrackID']])
|
||||
|
||||
logger.debug('Wrote mbid to track: %s' % match[0])
|
||||
|
||||
except:
|
||||
logger.error('Error embedding track id into: %s' % match[0])
|
||||
continue
|
||||
|
||||
logger.info('Done checking empty filepaths')
|
||||
logger.info('Done syncing library with directory: %s' % dir)
|
||||
logger.info('Completed scanning directory: %s' % dir)
|
||||
|
||||
# Clean up the new artist list
|
||||
unique_artists = {}.fromkeys(new_artists).keys()
|
||||
|
||||
@@ -418,9 +418,10 @@ def moveFiles(albumpath, release, tracks):
|
||||
except Exception, e:
|
||||
logger.warn('Error renaming %s: %s' % (files, e))
|
||||
break
|
||||
|
||||
try:
|
||||
shutil.move(os.path.join(r, files), os.path.join(destination_path, files))
|
||||
except shutil.Error, e:
|
||||
except Exception, e:
|
||||
logger.warn('Error moving file %s: %s' % (files, e))
|
||||
|
||||
# Chmod the directories using the folder_format (script courtesy of premiso!)
|
||||
|
||||
@@ -916,11 +916,19 @@ def searchTorrent(albumid=None, new=False, losslessOnly=False):
|
||||
|
||||
# Get torrent name from .torrent, this is usually used by the torrent client as the folder name
|
||||
|
||||
|
||||
torrent_name = torrent_folder_name + '.torrent'
|
||||
download_path = os.path.join(headphones.TORRENTBLACKHOLE_DIR, torrent_name)
|
||||
try:
|
||||
torrent_file = open(download_path, 'rb').read()
|
||||
torrent_info = bencode.bdecode(torrent_file)
|
||||
#Write the torrent file to a path derived from the TORRENTBLACKHOLE_DIR and file name.
|
||||
torrent_file = open(download_path, 'wb')
|
||||
torrent_file.write(data)
|
||||
torrent_file.close()
|
||||
#Open the fresh torrent file again so we can extract the proper torrent name
|
||||
#Used later in post-processing.
|
||||
torrent_file = open(download_path, 'rb')
|
||||
torrent_info = bencode.bdecode(torrent_file.read())
|
||||
torrent_file.close()
|
||||
torrent_folder_name = torrent_info['info'].get('name','')
|
||||
logger.info('Torrent folder name: %s' % torrent_folder_name)
|
||||
except Exception, e:
|
||||
|
||||
@@ -138,6 +138,7 @@ class WebInterface(object):
|
||||
myDB.action('DELETE from artists WHERE ArtistID=?', [ArtistID])
|
||||
myDB.action('DELETE from albums WHERE ArtistID=?', [ArtistID])
|
||||
myDB.action('DELETE from tracks WHERE ArtistID=?', [ArtistID])
|
||||
myDB.action('INSERT OR REPLACE into blacklist VALUES (?)', [ArtistID])
|
||||
raise cherrypy.HTTPRedirect("home")
|
||||
deleteArtist.exposed = True
|
||||
|
||||
@@ -148,11 +149,12 @@ class WebInterface(object):
|
||||
|
||||
def markAlbums(self, ArtistID=None, action=None, **args):
|
||||
myDB = db.DBConnection()
|
||||
if action == 'WantedNew':
|
||||
if action == 'WantedNew' or action == 'WantedLossless':
|
||||
newaction = 'Wanted'
|
||||
else:
|
||||
newaction = action
|
||||
for mbid in args:
|
||||
logger.info("Marking %s as %s" % (mbid, newaction))
|
||||
controlValueDict = {'AlbumID': mbid}
|
||||
newValueDict = {'Status': newaction}
|
||||
myDB.upsert("albums", newValueDict, controlValueDict)
|
||||
@@ -160,6 +162,8 @@ class WebInterface(object):
|
||||
searcher.searchforalbum(mbid, new=False)
|
||||
if action == 'WantedNew':
|
||||
searcher.searchforalbum(mbid, new=True)
|
||||
if action == 'WantedLossless':
|
||||
searcher.searchforalbum(mbid, lossless=True)
|
||||
if ArtistID:
|
||||
raise cherrypy.HTTPRedirect("artistPage?ArtistID=%s" % ArtistID)
|
||||
else:
|
||||
@@ -223,7 +227,13 @@ class WebInterface(object):
|
||||
myDB = db.DBConnection()
|
||||
artists = myDB.select('SELECT * from artists order by ArtistSortName COLLATE NOCASE')
|
||||
return serve_template(templatename="manageartists.html", title="Manage Artists", artists=artists)
|
||||
manageArtists.exposed = True
|
||||
manageArtists.exposed = True
|
||||
|
||||
def manageAlbums(self):
|
||||
myDB = db.DBConnection()
|
||||
albums = myDB.select('SELECT * from albums')
|
||||
return serve_template(templatename="managealbums.html", title="Manage Albums", albums=albums)
|
||||
manageAlbums.exposed = True
|
||||
|
||||
def manageNew(self):
|
||||
return serve_template(templatename="managenew.html", title="Manage New Artists")
|
||||
@@ -237,6 +247,7 @@ class WebInterface(object):
|
||||
myDB.action('DELETE from artists WHERE ArtistID=?', [ArtistID])
|
||||
myDB.action('DELETE from albums WHERE ArtistID=?', [ArtistID])
|
||||
myDB.action('DELETE from tracks WHERE ArtistID=?', [ArtistID])
|
||||
myDB.action('INSERT OR REPLACE into blacklist VALUES (?)', [ArtistID])
|
||||
elif action == 'pause':
|
||||
controlValueDict = {'ArtistID': ArtistID}
|
||||
newValueDict = {'Status': 'Paused'}
|
||||
|
||||
Reference in New Issue
Block a user