mirror of
https://github.com/rembo10/headphones.git
synced 2026-05-10 13:49:32 +01:00
Added manage new artists page, fixed some bugs in the importer
This commit is contained in:
@@ -177,19 +177,25 @@ img.albumArt { float: left; padding-right: 5px; }
|
||||
div#albumheader { padding-top: 48px; height: 200px; }
|
||||
div#track_wrapper { margin-left: -50px; padding-top: 20px; font-size: 16px; width: 100%; }
|
||||
|
||||
table#track_table th#number { text-align: right; min-width: 20px; }
|
||||
table#track_table th#name { text-align: center; min-width: 350px; }
|
||||
table#track_table th#number { text-align: right; min-width: 10px; }
|
||||
table#track_table th#name { text-align: center; min-width: 320px; }
|
||||
table#track_table th#duration { width: 175px; text-align: center; min-width: 100px; }
|
||||
table#track_table th#location { text-align: center; min-width: 200px; }
|
||||
table#track_table th#bitrate { text-align: center; min-width: 75px; }
|
||||
|
||||
table#track_table td#number { vertical-align: middle; text-align: right; }
|
||||
table#track_table td#name { vertical-align: middle; text-align: center; }
|
||||
table#track_table td#name { vertical-align: middle; text-align: center; font-size: 15px; }
|
||||
table#track_table td#duration { vertical-align: middle; text-align: center; }
|
||||
table#track_table td#location { vertical-align: middle; text-align: center; font-size: 11px; }
|
||||
table#track_table td#bitrate { vertical-align: middle; text-align: center; font-size: 12px; }
|
||||
|
||||
table#history_table { background-color: white; width: 100%; }
|
||||
table#history_table { background-color: white; width: 100%; font-size: 13px; }
|
||||
|
||||
table#history_table td#dateadded { vertical-align: middle; text-align: center; min-width: 150px; font-size: 14px; }
|
||||
table#history_table td#filename { vertical-align: middle; text-align: center; min-width: 100px; font-size: 15px; }
|
||||
table#history_table td#size { vertical-align: middle; text-align: center; min-width: 75px; font-size: 14px; }
|
||||
table#history_table td#status { vertical-align: middle; text-align: center; font-size: 14px; }
|
||||
table#history_table td#action { vertical-align: middle; text-align: center; font-size: 14px; }
|
||||
|
||||
table#log_table { background-color: white; }
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
%>
|
||||
<tr class="grade${grade}">
|
||||
<td id="dateadded">${item['DateAdded']}</td>
|
||||
<td id="filename"><a href="${item['URL']}">${item['Title']}</a> <a href="albumPage?AlbumID=?${item['AlbumID']}">[album page]</a></td>
|
||||
<td id="filename">${item['Title']} [<a href="${item['URL']}">nzb</a>]<a href="albumPage?AlbumID=${item['AlbumID']}">[album page]</a></td>
|
||||
<td id="size">${helpers.bytes_to_mb(item['Size'])}</td>
|
||||
<td id="status">${item['Status']}</td>
|
||||
<td id="action">[<a href="queueAlbum?AlbumID=${item['AlbumID']}&redirect=history">retry</a>][<a href="queueAlbum?AlbumID=${item['AlbumID']}&new=True&redirect=history">new</a>]</td>
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
<%def name="headerIncludes()">
|
||||
<div id="subhead_container">
|
||||
<ul id="subhead_menu">
|
||||
<li><a href="manageArtists">Manage Artists</a></li>
|
||||
<li><a href="manageArtists">Manage Artists</a></li>
|
||||
%if not headphones.ADD_ARTISTS:
|
||||
<li><a href="manageNew">Manage New Artists</a></li>
|
||||
%endif
|
||||
</ul>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
<%inherit file="base.html" />
|
||||
|
||||
<%!
|
||||
import headphones
|
||||
%>
|
||||
<%def name="body()">
|
||||
<div id="paddingheader">
|
||||
<h1>Manage Artists<h1>
|
||||
<h1>Manage New Artists<h1>
|
||||
</div>
|
||||
<form action="markArtists" method="get">
|
||||
<form action="addArtists" method="get">
|
||||
<p class="indented">
|
||||
<select name="action">
|
||||
<option value="pause">Pause</option>
|
||||
<option value="resume">Resume</option>
|
||||
<option value="refresh">Refresh</option>
|
||||
<option value="delete">Delete</option>
|
||||
</select>
|
||||
selected artists
|
||||
Add selected artists
|
||||
<input type="submit" value="Go">
|
||||
</p>
|
||||
<table class="display" id="artist_table">
|
||||
@@ -20,23 +16,13 @@
|
||||
<tr>
|
||||
<th id="select"><input type="checkbox" onClick="toggle(this)" /></th>
|
||||
<th id="name">Artist Name</th>
|
||||
<th id="status">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
%for artist in artists:
|
||||
<%
|
||||
if artist['Status'] == 'Paused':
|
||||
grade = 'X'
|
||||
elif artist['Status'] == 'Loading':
|
||||
grade = 'C'
|
||||
else:
|
||||
grade = 'Z'
|
||||
%>
|
||||
<tr class="grade${grade}">
|
||||
%for artist in headphones.NEW_ARTISTS:
|
||||
<tr class="gradeZ">
|
||||
<td id="select"><input type="checkbox" name="${artist['ArtistID']}" class="checkbox" /></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>
|
||||
</tr>
|
||||
%endfor
|
||||
</tbody>
|
||||
@@ -58,7 +44,6 @@
|
||||
"aoColumns": [
|
||||
null,
|
||||
{ "sType": "title-string"},
|
||||
null
|
||||
],
|
||||
"bStateSave": true,
|
||||
"bPaginate": false
|
||||
|
||||
51
data/interfaces/default/managenew.html
Normal file
51
data/interfaces/default/managenew.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<%inherit file="base.html" />
|
||||
<%!
|
||||
import headphones
|
||||
%>
|
||||
<%def name="body()">
|
||||
<div id="paddingheader">
|
||||
<h1>Manage New Artists<h1>
|
||||
</div>
|
||||
<form action="addArtists" method="get">
|
||||
<p class="indented">
|
||||
Add selected artists
|
||||
<input type="submit" value="Go">
|
||||
</p>
|
||||
<table class="display" id="artist_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="select"><input type="checkbox" onClick="toggle(this)" /></th>
|
||||
<th id="name">Artist Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
%for artist in headphones.NEW_ARTISTS:
|
||||
<tr class="gradeZ">
|
||||
<td id="select"><input type="checkbox" name="${artist}" class="checkbox" /></td>
|
||||
<td id="name">${artist}</a></td>
|
||||
</tr>
|
||||
%endfor
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</%def>
|
||||
|
||||
<%def name="headIncludes()">
|
||||
<link rel="stylesheet" href="css/data_table.css">
|
||||
</%def>
|
||||
|
||||
<%def name="javascriptIncludes()">
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function()
|
||||
{
|
||||
$('#artist_table').dataTable(
|
||||
{
|
||||
"aaSorting": [[1, 'asc']],
|
||||
"bStateSave": false,
|
||||
"bPaginate": false
|
||||
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
@@ -63,7 +63,7 @@ PREFERRED_QUALITY = None
|
||||
PREFERRED_BITRATE = None
|
||||
DETECT_BITRATE = False
|
||||
ADD_ARTISTS = False
|
||||
NEW_ARTISTS = None
|
||||
NEW_ARTISTS = []
|
||||
CORRECT_METADATA = False
|
||||
MOVE_FILES = False
|
||||
RENAME_FILES = False
|
||||
@@ -432,7 +432,7 @@ def start():
|
||||
SCHED.add_interval_job(librarysync.libraryScan, minutes=LIBRARYSCAN_INTERVAL)
|
||||
SCHED.add_interval_job(versioncheck.checkGithub, minutes=300)
|
||||
SCHED.add_interval_job(postprocessor.checkFolder, minutes=DOWNLOAD_SCAN_INTERVAL)
|
||||
librarysync.libraryScan()
|
||||
|
||||
SCHED.start()
|
||||
|
||||
started = True
|
||||
|
||||
@@ -141,7 +141,6 @@ def addArtisttoDB(artistid, extrasonly=False):
|
||||
myDB.action('DELETE from albums WHERE AlbumID=?', [release['releaseid']])
|
||||
myDB.action('DELETE from tracks WHERE AlbumID=?', [release['releaseid']])
|
||||
|
||||
myDB.action('DELETE from tracks WHERE AlbumID=?', [rg['id']])
|
||||
for track in release_dict['tracks']:
|
||||
|
||||
cleanname = helpers.cleanName(artist['artist_name'] + ' ' + rg['title'] + ' ' + track['title'])
|
||||
@@ -158,18 +157,16 @@ def addArtisttoDB(artistid, extrasonly=False):
|
||||
"CleanName": cleanname
|
||||
}
|
||||
|
||||
location = myDB.action('SELECT Location, BitRate from have WHERE TrackID=?', [track['id']]).fetchone()
|
||||
|
||||
if not location:
|
||||
location = myDB.action('SELECT Location, BitRate from have WHERE CleanName=?', [cleanname]).fetchone()
|
||||
match = myDB.action('SELECT Location, BitRate from have WHERE TrackID=?', [track['id']]).fetchone()
|
||||
|
||||
if not location:
|
||||
location = myDB.action('SELECT Location, BitRate from have WHERE ArtistName LIKE ? AND AlbumTitle LIKE ? AND TrackTitle LIKE ?', [artist['artist_name'], rg['title'], track['title']]).fetchone()
|
||||
|
||||
if location:
|
||||
newValueDict['Location'] = location['Location']
|
||||
newValueDict['BitRate'] = location['BitRate']
|
||||
myDB.action('DELETE from have WHERE Location=?', [location['location']])
|
||||
if not match:
|
||||
match = myDB.action('SELECT Location, BitRate from have WHERE CleanName=?', [cleanname]).fetchone()
|
||||
if not match:
|
||||
match = myDB.action('SELECT Location, BitRate from have WHERE ArtistName LIKE ? AND AlbumTitle LIKE ? AND TrackTitle LIKE ?', [artist['artist_name'], rg['title'], track['title']]).fetchone()
|
||||
if match:
|
||||
newValueDict['Location'] = match['Location']
|
||||
newValueDict['BitRate'] = match['BitRate']
|
||||
myDB.action('DELETE from have WHERE Location=?', [match['Location']])
|
||||
|
||||
myDB.upsert("tracks", newValueDict, controlValueDict)
|
||||
|
||||
@@ -187,7 +184,9 @@ def addArtisttoDB(artistid, extrasonly=False):
|
||||
"TotalTracks": totaltracks,
|
||||
"HaveTracks": havetracks}
|
||||
else:
|
||||
newValueDict = {"Status": "Active"}
|
||||
newValueDict = {"Status": "Active",
|
||||
"TotalTracks": totaltracks,
|
||||
"HaveTracks": havetracks}
|
||||
|
||||
myDB.upsert("artists", newValueDict, controlValueDict)
|
||||
logger.info(u"Updating complete for: " + artist['artist_name'])
|
||||
@@ -284,17 +283,17 @@ def addReleaseById(rid):
|
||||
"CleanName": cleanname
|
||||
}
|
||||
|
||||
location = myDB.action('SELECT Location, BitRate from have WHERE TrackID=?', [track['id']]).fetchone()
|
||||
match = myDB.action('SELECT Location, BitRate from have WHERE TrackID=?', [track['id']]).fetchone()
|
||||
|
||||
if not location:
|
||||
location = myDB.action('SELECT Location, BitRate from have WHERE CleanName=?', [cleanname]).fetchone()
|
||||
if not match:
|
||||
match = myDB.action('SELECT Location, BitRate from have WHERE CleanName=?', [cleanname]).fetchone()
|
||||
|
||||
if not location:
|
||||
location = myDB.action('SELECT Location, BitRate from have WHERE ArtistName LIKE ? AND AlbumTitle LIKE ? AND TrackTitle LIKE ?', [release_dict['artist_name'], release_dict['rg_title'], track['title']]).fetchone()
|
||||
if not match:
|
||||
match = myDB.action('SELECT Location, BitRate from have WHERE ArtistName LIKE ? AND AlbumTitle LIKE ? AND TrackTitle LIKE ?', [release_dict['artist_name'], release_dict['rg_title'], track['title']]).fetchone()
|
||||
|
||||
if location:
|
||||
newValueDict['Location'] = location['Location']
|
||||
newValueDict['BitRate'] = location['BitRate']
|
||||
if match:
|
||||
newValueDict['Location'] = match['Location']
|
||||
newValueDict['BitRate'] = match['BitRate']
|
||||
|
||||
myDB.upsert("tracks", newValueDict, controlValueDict)
|
||||
|
||||
|
||||
@@ -6,10 +6,17 @@ from lib.beets.mediafile import MediaFile
|
||||
import headphones
|
||||
from headphones import db, logger, helpers, importer
|
||||
|
||||
def libraryScan():
|
||||
def libraryScan(dir=None):
|
||||
|
||||
if not headphones.MUSIC_DIR:
|
||||
return
|
||||
if not dir:
|
||||
dir = headphones.MUSIC_DIR
|
||||
|
||||
try:
|
||||
dir = str(dir)
|
||||
except UnicodeEncodeError:
|
||||
dir = unicode(dir).encode('unicode_escape')
|
||||
|
||||
logger.info('Scanning music directory: %s' % dir)
|
||||
|
||||
new_artists = []
|
||||
bitrates = []
|
||||
@@ -17,7 +24,7 @@ def libraryScan():
|
||||
myDB = db.DBConnection()
|
||||
myDB.action('''DELETE from have''')
|
||||
|
||||
for r,d,f in os.walk(headphones.MUSIC_DIR):
|
||||
for r,d,f in os.walk(dir):
|
||||
for files in f:
|
||||
# MEDIA_FORMATS = music file extensions, e.g. mp3, flac, etc
|
||||
if any(files.endswith('.' + x) for x in headphones.MEDIA_FORMATS):
|
||||
@@ -132,17 +139,19 @@ def libraryScan():
|
||||
if match:
|
||||
|
||||
myDB.action('UPDATE tracks SET Location=? WHERE TrackID=?', [match[0], track['TrackID']])
|
||||
myDB.action('DELETE from have WHERE Location=?', [match[0]])
|
||||
|
||||
# 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']
|
||||
myDB.action('UPDATE tracks SET BitRate=? WHERE TrackID=?', [f.bitrate, track['TrackID']])
|
||||
f.save()
|
||||
logger.info('Wrote mbid to track: %s' % match[0])
|
||||
myDB.action('UPDATE tracks SET BitRate=? WHERE TrackID=?', [f.bitrate, track['TrackID']])
|
||||
logger.debug('Wrote mbid to track: %s' % match[0])
|
||||
except:
|
||||
logger.error('Error embedding track id into: %s' % match[0])
|
||||
|
||||
continue
|
||||
|
||||
# Clean up bad filepaths
|
||||
tracks = myDB.select('SELECT Location, TrackID from tracks WHERE Location IS NOT NULL')
|
||||
|
||||
@@ -168,4 +177,4 @@ def libraryScan():
|
||||
headphones.NEW_ARTISTS = artist_list
|
||||
|
||||
if headphones.DETECT_BITRATE:
|
||||
headphones.PREFERRED_BITRATE = round(sum(bitrates))/len(bitrates)/1000
|
||||
headphones.PREFERRED_BITRATE = sum(bitrates)/len(bitrates)/1000
|
||||
@@ -10,7 +10,7 @@ import threading
|
||||
|
||||
import headphones
|
||||
|
||||
from headphones import logger, searcher, db, importer, mb, lastfm
|
||||
from headphones import logger, searcher, db, importer, mb, lastfm, librarysync
|
||||
from headphones.helpers import checked, radio
|
||||
|
||||
|
||||
@@ -148,7 +148,12 @@ class WebInterface(object):
|
||||
else:
|
||||
raise cherrypy.HTTPRedirect("upcoming")
|
||||
markAlbums.exposed = True
|
||||
|
||||
|
||||
def addArtists(self, **args):
|
||||
threading.Thread(target=importer.artistlist_to_mbids, args=[args]).start()
|
||||
time.sleep(5)
|
||||
raise cherrypy.HTTPRedirect("home")
|
||||
addArtists.exposed = True
|
||||
|
||||
def queueAlbum(self, AlbumID, ArtistID=None, new=False, redirect=None):
|
||||
logger.info(u"Marking album: " + AlbumID + "as wanted...")
|
||||
@@ -189,6 +194,10 @@ class WebInterface(object):
|
||||
return serve_template(templatename="manageartists.html", title="Manage Artists", artists=artists)
|
||||
manageArtists.exposed = True
|
||||
|
||||
def manageNew(self):
|
||||
return serve_template(templatename="managenew.html", title="Manage New Artists")
|
||||
manageNew.exposed = True
|
||||
|
||||
def markArtists(self, action=None, **args):
|
||||
myDB = db.DBConnection()
|
||||
for ArtistID in args:
|
||||
@@ -231,7 +240,7 @@ class WebInterface(object):
|
||||
headphones.MUSIC_DIR = path
|
||||
headphones.config_write()
|
||||
try:
|
||||
threading.Thread(target=importer.scanMusic, args=[path]).start()
|
||||
threading.Thread(target=librarysync.libraryScan).start()
|
||||
except Exception, e:
|
||||
logger.error('Unable to complete the scan: %s' % e)
|
||||
time.sleep(10)
|
||||
|
||||
Reference in New Issue
Block a user