Merge branch 'develop': Split extras into separate categories, better search

options when using preferred_bitrate, fixed bug with post-processor not working if
album isn't in the database
This commit is contained in:
rembo10
2012-08-19 19:22:31 +05:30
11 changed files with 307 additions and 62 deletions

8
TODO Normal file
View File

@@ -0,0 +1,8 @@
##############################
### TODO LIST (18/08/12) ###
##############################
1. Add ability to fetch a specific extra, rather than pull down the whole category
- This requires extra calls to MB right now, so modify 1st mb artist call to pull down the
whole album list, then only send the desried ones to importer.py
2. Update API with newstyle getExtras function (lacking entirely right now)

View File

@@ -170,7 +170,7 @@
function initThisPage() {
$('#album_chooser').click(function() {
$('#dialog').dialog();
$('#dialog').dialog({ width: "500px" });
return false;
});
$('#refresh_artist').click(function() {

View File

@@ -2,6 +2,7 @@
<%!
from headphones import db
import headphones
import string
%>
<%def name="headerIncludes()">
@@ -16,9 +17,21 @@
%endif
%if artist['IncludeExtras']:
<a id="menu_link_removeextra" href="#" onclick="doAjaxCall('removeExtras?ArtistID=${artist['ArtistID']}',$(this),true)" data-success="Extras removed for ${artist['ArtistName']}">Remove Extras</a>
<a class="menu_link_edit" id="menu_link_modifyextra" href="#">Modify Extras</a>
%else:
<a id="menu_link_getextra" href="#" onclick="doAjaxCall('getExtras?ArtistID=${artist['ArtistID']}',$(this),true)" data-success="Getting Extras for ${artist['ArtistName']}">Get Extras</a>
<a id="menu_link_getextra" href="#">Get Extras</a>
%endif
<div id="dialog" title="Choose Which Extras to Fetch" style="display:none" class="configtable">
<form action="getExtras" method="get" class="form">
<input type="hidden" name="ArtistID" value="${artist['ArtistID']}">
<input type="hidden" name="newstyle" value="true">
%for extra in extras:
<input type="checkbox" id="${extra}" name="${extra}" value="1" ${extras[extra]} />${string.capwords(extra)}<br>
%endfor
<br>
<input id="submit" type="submit" value="Fetch Extras">
</form>
</div>
</div>
</div>
<a href="home" class="back">&laquo; Back to overview</a>
@@ -178,6 +191,14 @@
function initThisPage() {
$('#menu_link_getextra').click(function() {
$('#dialog').dialog();
return false;
});
$('#menu_link_modifyextra').click(function() {
$('#dialog').dialog();
});
%if artist['Status'] == 'Loading':
showMsg("Getting artist information",true);
%endif

View File

@@ -1,6 +1,7 @@
m<%inherit file="base.html"/>
<%!
import headphones
import string
%>
<%def name="headerIncludes()">
@@ -315,16 +316,18 @@ m<%inherit file="base.html"/>
<fieldset>
<legend>Quality</legend>
<div class="row radio clearfix">
<input type="radio" name="preferred_quality" value="0" ${config['pref_qual_0']} /><label>Highest Quality excluding Lossless</label>
<input type="radio" name="preferred_quality" value="0" ${config['pref_qual_0']} /><label>Highest Quality excluding Lossless</label>
<input type="radio" name="preferred_quality" value="1" ${config['pref_qual_1']} /><label>Highest Quality including Lossless</label>
<input type="radio" name="preferred_quality" value="3" ${config['pref_qual_3']} /><label>Lossless Only</label>
<input type="radio" name="preferred_quality" value="2" ${config['pref_qual_2']} /><label>Preferred Bitrate:
<input type="text" name="preferred_bitrate" value="${config['pref_bitrate']}" size="3">kbps</label>
</div>
<div class="row checkbox left">
<input type="checkbox" name="detect_bitrate" value="1" ${config['detect_bitrate']} />
<label>Auto-Detect Preferred Bitrate</label>
</div>
<input type="radio" id="preferred_bitrate" name="preferred_quality" value="2" ${config['pref_qual_2']} />Preferred Bitrate: <input type="text" class="override-float" name="preferred_bitrate" value="${config['pref_bitrate']}" size="3">kbps<br>
<div id="preferred_bitrate_options">
Reject if <strong>less than</strong> <input type="text" class="override-float" name="preferred_bitrate_low_buffer" value="${config['pref_bitrate_low']}" size="3">% or <strong>more than</strong> <input type="text" class="override-float" name="preferred_bitrate_high_buffer" value="${config['pref_bitrate_high']}" size="3">% of the target size (leave blank for no limit)<br><br>
<div class="row checkbox left">
<input type="checkbox" name="detect_bitrate" value="1" ${config['detect_bitrate']} />
<label>Auto-Detect Preferred Bitrate</label>
</div>
</div>
</div>
</fieldset>
</td>
@@ -505,9 +508,30 @@ m<%inherit file="base.html"/>
<fieldset>
<legend>Miscellaneous</legend>
<div class="checkbox left row">
<input type="checkbox" name="include_extras" value="1" ${config['include_extras']} /><label>Automatically Include Extras When Adding an Artist <small>(EPs, Compilations, Live Albums, Remix Albums and Singles)</small></label>
</div>
<input type="checkbox" name="include_extras" id="include_extras" value="1" ${config['include_extras']} /><label>Automatically Include Extras When Adding an Artist <br>
<%
which_extras_selected = ""
for extra in config['extras']:
if config['extras'][extra] == "checked":
which_extras_selected += string.capwords(extra) + ', '
# Chop off the last comma & space
if which_extras_selected:
which_extras_selected = which_extras_selected[:-2]
else:
which_extras_selected = "None"
%>
<small>Currently Selected: ${which_extras_selected} <a href="#" id="modify_extras">(Change)</a></small></label>
<div id="dialog" title="Choose Which Extras to Include" style="display:none" class="configtable">
%for extra in config['extras']:
<input type="checkbox" id="${extra}_temp" name="${extra}_temp" value="1" ${config['extras'][extra]} />${string.capwords(extra)}<br>
%endfor
</div>
<div style="display:none">
%for extra in config['extras']:
<input type="checkbox" id="${extra}" name="${extra}" value="1" ${config['extras'][extra]} />${string.capwords(extra)}<br>
%endfor
</div>
</div>
<div class="row left checkbox">
<input type="checkbox" name="autowant_upcoming" value="1" ${config['autowant_upcoming']} /><label>Automatically Mark Upcoming Albums as Wanted</label>
<div class="row leftcheckbox">
@@ -707,6 +731,13 @@ m<%inherit file="base.html"/>
}
};
function openExtrasDialog() {
$("#dialog").dialog({ close: function(){
var elem = '<input type="button" data-success="Changes saved successfully">';
doAjaxCall('configUpdate', elem,'tabs',true);
}}).dialog("open");
};
function initThisPage()
{
@@ -819,6 +850,25 @@ m<%inherit file="base.html"/>
{
$("#nmaoptions").slideUp();
}
});
if ($("#preferred_bitrate").is(":checked"))
{
$("#preferred_bitrate_options").show();
}
else
{
$("#preferred_bitrate_options").hide();
}
$('input[type=radio]').change(function(){
if ($("#preferred_bitrate").is(":checked"))
{
$("#preferred_bitrate_options").slideDown("fast");
}
else
{
$("#preferred_bitrate_options").slideUp("fast");
}
});
$("#mirror").change(handleNewSelection);
@@ -830,6 +880,25 @@ m<%inherit file="base.html"/>
$(this).parent().parent().remove();
deletedNewznabs = deletedNewznabs + 1;
});
$("#modify_extras").click(openExtrasDialog);
$("#include_extras").click(function(){
if ($("#include_extras").is(":checked")){
openExtrasDialog();
}
});
%for extra in config['extras']:
$("#${extra}_temp").click(function(){
if ($(this).is(":checked")){
$("#${extra}").attr("checked", true);
}
else {
$("#${extra}").attr("checked", false);
}
});
%endfor
$("#add_newznab").click(function() {
var intId = $("#newznab_providers > div").size() + deletedNewznabs + 1;

View File

@@ -376,6 +376,10 @@ form .radio label {
padding-top: 1px;
width: auto;
}
.override-float {
float: none !important;
margin-bottom: 0px !important;
}
form .radio input {
float: left;
margin-bottom: 10px;
@@ -674,6 +678,13 @@ footer {
position: relative;
margin-right: 3px;
}
#dialog {
padding: 40px;
}
#dialog input#submit {
margin-left: 50px;
margin-right: auto;
}
#subhead .back {
float: left;
margin-top: -25px;

View File

@@ -90,6 +90,8 @@ FILE_FORMAT = None
PATH_TO_XML = None
PREFERRED_QUALITY = None
PREFERRED_BITRATE = None
PREFERRED_BITRATE_HIGH_BUFFER = None
PREFERRED_BITRATE_LOW_BUFFER = None
DETECT_BITRATE = False
ADD_ARTISTS = False
CORRECT_METADATA = False
@@ -104,6 +106,7 @@ BLACKHOLE = None
BLACKHOLE_DIR = None
USENET_RETENTION = None
INCLUDE_EXTRAS = False
EXTRAS = None
AUTOWANT_UPCOMING = False
AUTOWANT_ALL = False
@@ -241,17 +244,18 @@ def initialize():
global __INITIALIZED__, FULL_PATH, PROG_DIR, VERBOSE, DAEMON, DATA_DIR, CONFIG_FILE, CFG, CONFIG_VERSION, LOG_DIR, CACHE_DIR, \
HTTP_PORT, HTTP_HOST, HTTP_USERNAME, HTTP_PASSWORD, HTTP_ROOT, HTTP_PROXY, LAUNCH_BROWSER, API_ENABLED, API_KEY, GIT_PATH, \
CURRENT_VERSION, LATEST_VERSION, CHECK_GITHUB, CHECK_GITHUB_ON_STARTUP, CHECK_GITHUB_INTERVAL, MUSIC_DIR, DESTINATION_DIR, \
LOSSLESS_DESTINATION_DIR, PREFERRED_QUALITY, PREFERRED_BITRATE, DETECT_BITRATE, \
ADD_ARTISTS, CORRECT_METADATA, MOVE_FILES, RENAME_FILES, FOLDER_FORMAT, FILE_FORMAT, CLEANUP_FILES, INCLUDE_EXTRAS, AUTOWANT_UPCOMING, AUTOWANT_ALL, \
LOSSLESS_DESTINATION_DIR, PREFERRED_QUALITY, PREFERRED_BITRATE, DETECT_BITRATE, ADD_ARTISTS, CORRECT_METADATA, MOVE_FILES, \
RENAME_FILES, FOLDER_FORMAT, FILE_FORMAT, CLEANUP_FILES, INCLUDE_EXTRAS, EXTRAS, AUTOWANT_UPCOMING, AUTOWANT_ALL, \
ADD_ALBUM_ART, EMBED_ALBUM_ART, EMBED_LYRICS, DOWNLOAD_DIR, BLACKHOLE, BLACKHOLE_DIR, USENET_RETENTION, SEARCH_INTERVAL, \
TORRENTBLACKHOLE_DIR, NUMBEROFSEEDERS, ISOHUNT, KAT, MININOVA, WAFFLES, WAFFLES_UID, WAFFLES_PASSKEY, DOWNLOAD_TORRENT_DIR, \
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, NEWZNAB_ENABLED, EXTRA_NEWZNABS,\
NZBSORG, NZBSORG_UID, NZBSORG_HASH, NEWZBIN, NEWZBIN_UID, NEWZBIN_PASSWORD, LASTFM_USERNAME, INTERFACE, FOLDER_PERMISSIONS, \
ENCODERFOLDER, ENCODER, BITRATE, SAMPLINGFREQUENCY, MUSIC_ENCODER, ADVANCEDENCODER, ENCODEROUTPUTFORMAT, ENCODERQUALITY, ENCODERVBRCBR, \
ENCODERLOSSLESS, DELETE_LOSSLESS_FILES, PROWL_ENABLED, PROWL_PRIORITY, PROWL_KEYS, PROWL_ONSNATCH, MIRRORLIST, MIRROR, CUSTOMHOST, CUSTOMPORT, \
CUSTOMSLEEP, HPUSER, HPPASS, XBMC_ENABLED, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, XBMC_UPDATE, XBMC_NOTIFY, NMA_ENABLED, NMA_APIKEY, NMA_PRIORITY, SYNOINDEX_ENABLED, \
ALBUM_COMPLETION_PCT
ENCODERFOLDER, ENCODER, BITRATE, SAMPLINGFREQUENCY, MUSIC_ENCODER, ADVANCEDENCODER, ENCODEROUTPUTFORMAT, ENCODERQUALITY, \
ENCODERVBRCBR, ENCODERLOSSLESS, DELETE_LOSSLESS_FILES, PROWL_ENABLED, PROWL_PRIORITY, PROWL_KEYS, PROWL_ONSNATCH, MIRRORLIST, \
MIRROR, CUSTOMHOST, CUSTOMPORT, CUSTOMSLEEP, HPUSER, HPPASS, XBMC_ENABLED, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, XBMC_UPDATE, \
XBMC_NOTIFY, NMA_ENABLED, NMA_APIKEY, NMA_PRIORITY, SYNOINDEX_ENABLED, ALBUM_COMPLETION_PCT, PREFERRED_BITRATE_HIGH_BUFFER, \
PREFERRED_BITRATE_LOW_BUFFER
if __INITIALIZED__:
return False
@@ -301,6 +305,8 @@ def initialize():
LOSSLESS_DESTINATION_DIR = check_setting_str(CFG, 'General', 'lossless_destination_dir', '')
PREFERRED_QUALITY = check_setting_int(CFG, 'General', 'preferred_quality', 0)
PREFERRED_BITRATE = check_setting_int(CFG, 'General', 'preferred_bitrate', '')
PREFERRED_BITRATE_HIGH_BUFFER = check_setting_int(CFG, 'General', 'preferred_bitrate_high_buffer', '')
PREFERRED_BITRATE_LOW_BUFFER = check_setting_int(CFG, 'General', 'preferred_bitrate_low_buffer', '')
DETECT_BITRATE = bool(check_setting_int(CFG, 'General', 'detect_bitrate', 0))
ADD_ARTISTS = bool(check_setting_int(CFG, 'General', 'auto_add_artists', 1))
CORRECT_METADATA = bool(check_setting_int(CFG, 'General', 'correct_metadata', 0))
@@ -317,6 +323,7 @@ def initialize():
BLACKHOLE_DIR = check_setting_str(CFG, 'General', 'blackhole_dir', '')
USENET_RETENTION = check_setting_int(CFG, 'General', 'usenet_retention', '1500')
INCLUDE_EXTRAS = bool(check_setting_int(CFG, 'General', 'include_extras', 0))
EXTRAS = check_setting_str(CFG, 'General', 'extras', '')
AUTOWANT_UPCOMING = bool(check_setting_int(CFG, 'General', 'autowant_upcoming', 1))
AUTOWANT_ALL = bool(check_setting_int(CFG, 'General', 'autowant_all', 0))
@@ -578,6 +585,8 @@ def config_write():
new_config['General']['lossless_destination_dir'] = LOSSLESS_DESTINATION_DIR
new_config['General']['preferred_quality'] = PREFERRED_QUALITY
new_config['General']['preferred_bitrate'] = PREFERRED_BITRATE
new_config['General']['preferred_bitrate_high_buffer'] = PREFERRED_BITRATE_HIGH_BUFFER
new_config['General']['preferred_bitrate_low_buffer'] = PREFERRED_BITRATE_LOW_BUFFER
new_config['General']['detect_bitrate'] = int(DETECT_BITRATE)
new_config['General']['auto_add_artists'] = int(ADD_ARTISTS)
new_config['General']['correct_metadata'] = int(CORRECT_METADATA)
@@ -594,6 +603,7 @@ def config_write():
new_config['General']['blackhole_dir'] = BLACKHOLE_DIR
new_config['General']['usenet_retention'] = USENET_RETENTION
new_config['General']['include_extras'] = int(INCLUDE_EXTRAS)
new_config['General']['extras'] = EXTRAS
new_config['General']['autowant_upcoming'] = int(AUTOWANT_UPCOMING)
new_config['General']['autowant_all'] = int(AUTOWANT_ALL)
@@ -725,7 +735,7 @@ def dbcheck():
conn=sqlite3.connect(DB_FILE)
c=conn.cursor()
c.execute('CREATE TABLE IF NOT EXISTS artists (ArtistID TEXT UNIQUE, ArtistName TEXT, ArtistSortName TEXT, DateAdded TEXT, Status TEXT, IncludeExtras INTEGER, LatestAlbum TEXT, ReleaseDate TEXT, AlbumID TEXT, HaveTracks INTEGER, TotalTracks INTEGER, LastUpdated TEXT, ArtworkURL TEXT, ThumbURL TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS artists (ArtistID TEXT UNIQUE, ArtistName TEXT, ArtistSortName TEXT, DateAdded TEXT, Status TEXT, IncludeExtras INTEGER, LatestAlbum TEXT, ReleaseDate TEXT, AlbumID TEXT, HaveTracks INTEGER, TotalTracks INTEGER, LastUpdated TEXT, ArtworkURL TEXT, ThumbURL TEXT, Extras TEXT)')
c.execute('CREATE TABLE IF NOT EXISTS albums (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, ReleaseDate TEXT, DateAdded TEXT, AlbumID TEXT UNIQUE, Status TEXT, Type TEXT, ArtworkURL TEXT, ThumbURL TEXT, ReleaseID TEXT, ReleaseCountry TEXT, ReleaseFormat TEXT)') # ReleaseFormat here means CD,Digital,Vinyl, etc. If using the default Headphones hybrid release, ReleaseID will equal AlbumID (AlbumID is releasegroup id)
c.execute('CREATE TABLE IF NOT EXISTS tracks (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, AlbumID TEXT, TrackTitle TEXT, TrackDuration, TrackID TEXT, TrackNumber INTEGER, Location TEXT, BitRate INTEGER, CleanName TEXT, Format TEXT, ReleaseID TEXT)') # Format here means mp3, flac, etc.
c.execute('CREATE TABLE IF NOT EXISTS allalbums (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, ReleaseDate TEXT, AlbumID TEXT, Type TEXT, ReleaseID TEXT, ReleaseCountry TEXT, ReleaseFormat TEXT)')
@@ -880,6 +890,19 @@ def dbcheck():
c.execute('SELECT Matched from have')
except sqlite3.OperationalError:
c.execute('ALTER TABLE have ADD COLUMN Matched TEXT DEFAULT NULL')
try:
c.execute('SELECT Extras from artists')
except sqlite3.OperationalError:
c.execute('ALTER TABLE artists ADD COLUMN Extras TEXT DEFAULT NULL')
# Need to update some stuff when people are upgrading and have 'include extras' set globally/for an artist
if INCLUDE_EXTRAS:
EXTRAS = "1,2,3,4,5,6,7,8"
logger.info("Copying over current artist IncludeExtras information")
artists = c.execute('SELECT ArtistID, IncludeExtras from artists').fetchall()
for artist in artists:
if artist[1]:
c.execute('UPDATE artists SET Extras=? WHERE ArtistID=?', ("1,2,3,4,5,6,7,8", artist[0]))
conn.commit()
c.close()

View File

@@ -116,9 +116,13 @@ def addArtisttoDB(artistid, extrasonly=False):
# Don't replace a known artist name with an "Artist ID" placeholder
dbartist = myDB.action('SELECT * FROM artists WHERE ArtistID=?', [artistid]).fetchone()
if dbartist is None:
# Only modify the Include Extras stuff if it's a new artist. We need it early so we know what to fetch
if not dbartist:
newValueDict = {"ArtistName": "Artist ID: %s" % (artistid),
"Status": "Loading"}
"Status": "Loading",
"IncludeExtras": headphones.INCLUDE_EXTRAS,
"Extras": headphones.EXTRAS }
else:
newValueDict = {"Status": "Loading"}
@@ -149,9 +153,6 @@ def addArtisttoDB(artistid, extrasonly=False):
"DateAdded": helpers.today(),
"Status": "Loading"}
if headphones.INCLUDE_EXTRAS:
newValueDict['IncludeExtras'] = 1
myDB.upsert("artists", newValueDict, controlValueDict)
for rg in artist['releasegroups']:
@@ -469,6 +470,7 @@ def addReleaseById(rid):
if headphones.INCLUDE_EXTRAS:
newValueDict['IncludeExtras'] = 1
newValueDict['Extras'] = headphones.EXTRAS
myDB.upsert("artists", newValueDict, controlValueDict)

View File

@@ -229,16 +229,29 @@ def getArtist(artistid, extrasonly=False):
'type': unicode(rg['type'])
})
# See if we need to grab extras
# See if we need to grab extras. Artist specific extras take precedence over global option
# Global options are set when adding a new artist
myDB = db.DBConnection()
try:
includeExtras = myDB.select('SELECT IncludeExtras from artists WHERE ArtistID=?', [artistid])[0][0]
db_artist = myDB.action('SELECT IncludeExtras, Extras from artists WHERE ArtistID=?', [artistid]).fetchone()
includeExtras = db_artist['IncludeExtras']
except IndexError:
includeExtras = False
if includeExtras or headphones.INCLUDE_EXTRAS:
includes = ["single", "ep", "compilation", "soundtrack", "live", "remix", "spokenword", "audiobook"]
if includeExtras:
# Need to convert extras string from something like '2,5.6' to ['ep','live','remix']
extras = db_artist['Extras']
extras_list = ["single", "ep", "compilation", "soundtrack", "live", "remix", "spokenword", "audiobook"]
includes = []
i = 1
for extra in extras_list:
if str(i) in extras:
includes.append(extra)
i += 1
for include in includes:
artist = None

View File

@@ -65,18 +65,23 @@ def verify(albumid, albumpath):
#TODO: odd things can happen when there are diacritic characters in the folder name, need to translate them?
import mb
release_dict = None
release_list = None
try:
release_dict = mb.getReleaseGroup(albumid)
release_list = mb.getReleaseGroup(albumid)
except Exception, e:
logger.info('Unable to get release information for manual album with rgid: %s. Error: %s' % (albumid, e))
return
if not release_dict:
if not release_list:
logger.info('Unable to get release information for manual album with rgid: %s' % albumid)
return
# Since we're just using this to create the bare minimum information to insert an artist/album combo, use the first release
releaseid = release_list[0]['id']
release_dict = mb.getRelease(releaseid)
logger.info(u"Now adding/updating artist: " + release_dict['artist_name'])
if release_dict['artist_name'].startswith('The '):
@@ -90,10 +95,12 @@ def verify(albumid, albumpath):
"ArtistSortName": sortname,
"DateAdded": helpers.today(),
"Status": "Paused"}
logger.info("ArtistID:ArtistName: " + release_dict['artist_id'] + " : " + release_dict['artist_name'])
logger.info("ArtistID: " + release_dict['artist_id'] + " , ArtistName: " + release_dict['artist_name'])
if headphones.INCLUDE_EXTRAS:
newValueDict['IncludeExtras'] = 1
newValueDict['Extras'] = headphones.EXTRAS
myDB.upsert("artists", newValueDict, controlValueDict)
@@ -104,24 +111,21 @@ def verify(albumid, albumpath):
"ArtistName": release_dict['artist_name'],
"AlbumTitle": release_dict['title'],
"AlbumASIN": release_dict['asin'],
"ReleaseDate": release_dict['releasedate'],
"ReleaseDate": release_dict['date'],
"DateAdded": helpers.today(),
"Type": release_dict['type'],
"Type": release_dict['rg_type'],
"Status": "Snatched"
}
myDB.upsert("albums", newValueDict, controlValueDict)
# I changed the albumid from releaseid -> rgid, so might need to delete albums that have a releaseid
for rel in release_dict['releaselist']:
myDB.action('DELETE from albums WHERE AlbumID=?', [rel['releaseid']])
myDB.action('DELETE from tracks WHERE AlbumID=?', [rel['releaseid']])
# Delete existing tracks associated with this AlbumID since we're going to replace them and don't want any extras
myDB.action('DELETE from tracks WHERE AlbumID=?', [albumid])
for track in release_dict['tracks']:
controlValueDict = {"TrackID": track['id'],
"AlbumID": albumid}
newValueDict = {"ArtistID": release_dict['artist_id'],
"ArtistName": release_dict['artist_name'],
"AlbumTitle": release_dict['title'],

View File

@@ -426,15 +426,38 @@ def searchNZB(albumid=None, new=False, losslessOnly=False):
albumlength = sum([pair[0] for pair in tracks])
targetsize = albumlength/1000 * int(headphones.PREFERRED_BITRATE) * 128
logger.info('Target size: %s' % helpers.bytes_to_mb(targetsize))
newlist = []
for result in resultlist:
delta = abs(targetsize - result[1])
newlist.append((result[0], result[1], result[2], result[3], delta))
nzblist = sorted(newlist, key=lambda title: title[4])
if not targetsize:
logger.info('No track information for %s - %s. Defaulting to highest quality' % (albums[0], albums[1]))
nzblist = sorted(resultlist, key=lambda title: title[1], reverse=True)
else:
logger.info('Target size: %s' % helpers.bytes_to_mb(targetsize))
newlist = []
if headphones.PREFERRED_BITRATE_HIGH_BUFFER:
high_size_limit = targetsize * int(headphones.PREFERRED_BITRATE_HIGH_BUFFER)/100
else:
high_size_limit = None
if headphones.PREFERRED_BITRATE_LOW_BUFFER:
low_size_limit = targetsize * int(headphones.PREFERRED_BITRATE_LOW_BUFFER)/100
else:
low_size_limit = None
for result in resultlist:
if high_size_limit and (result[1] > high_size_limit):
logger.info(result[0] + "is too large for this album - not considering it. (Size: " + helpers.bytes_to_mb(result[1]) + ", Maxsize: " + helpers.bytes_to_mb(high_size_limit))
continue
if low_size_limit and (result[1] < low_size_limit):
logger.info(result[0] + "is too small for this album - not considering it. (Size: " + helpers.bytes_to_mb(result[1]) + ", Minsize: " + helpers.bytes_to_mb(low_size_limit))
continue
delta = abs(targetsize - result[1])
newlist.append((result[0], result[1], result[2], result[3], delta))
nzblist = sorted(newlist, key=lambda title: title[4])
except Exception, e:

View File

@@ -61,9 +61,27 @@ class WebInterface(object):
myDB = db.DBConnection()
artist = myDB.action('SELECT * FROM artists WHERE ArtistID=?', [ArtistID]).fetchone()
albums = myDB.select('SELECT * from albums WHERE ArtistID=? order by ReleaseDate DESC', [ArtistID])
# Serve the extras up as a dict to make things easier for new templates
extras_list = ["single", "ep", "compilation", "soundtrack", "live", "remix", "spokenword", "audiobook"]
extras_dict = {}
if not artist['Extras']:
artist_extras = ""
else:
artist_extras = artist['Extras']
i = 1
for extra in extras_list:
if str(i) in artist_extras:
extras_dict[extra] = "checked"
else:
extras_dict[extra] = ""
i+=1
if artist is None:
raise cherrypy.HTTPRedirect("home")
return serve_template(templatename="artist.html", title=artist['ArtistName'], artist=artist, albums=albums)
return serve_template(templatename="artist.html", title=artist['ArtistName'], artist=artist, albums=albums, extras=extras_dict)
artistPage.exposed = True
@@ -93,10 +111,27 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect("artistPage?ArtistID=%s" % artistid)
addArtist.exposed = True
def getExtras(self, ArtistID):
def getExtras(self, ArtistID, newstyle=False, **kwargs):
# if calling this function without the newstyle, they're using the old format
# which doesn't separate extras, so we'll grab all of them
#
# If they are, we need to convert kwargs to string format
if not newstyle:
extras = "1,2,3,4,5,6,7,8"
else:
temp_extras_list = []
# TODO: Put these extras as a global variable
i = 1
for extra in ["single", "ep", "compilation", "soundtrack", "live", "remix", "spokenword", "audiobook"]:
if extra in kwargs:
temp_extras_list.append(i)
i += 1
extras = ','.join(str(n) for n in temp_extras_list)
myDB = db.DBConnection()
controlValueDict = {'ArtistID': ArtistID}
newValueDict = {'IncludeExtras': 1}
newValueDict = {'IncludeExtras': 1,
'Extras': extras}
myDB.upsert("artists", newValueDict, controlValueDict)
threading.Thread(target=importer.addArtisttoDB, args=[ArtistID, True]).start()
raise cherrypy.HTTPRedirect("artistPage?ArtistID=%s" % ArtistID)
@@ -420,6 +455,8 @@ class WebInterface(object):
"pref_qual_3" : radio(headphones.PREFERRED_QUALITY, 3),
"pref_qual_2" : radio(headphones.PREFERRED_QUALITY, 2),
"pref_bitrate" : headphones.PREFERRED_BITRATE,
"pref_bitrate_high" : headphones.PREFERRED_BITRATE_HIGH_BUFFER,
"pref_bitrate_low" : headphones.PREFERRED_BITRATE_LOW_BUFFER,
"detect_bitrate" : checked(headphones.DETECT_BITRATE),
"move_files" : checked(headphones.MOVE_FILES),
"rename_files" : checked(headphones.RENAME_FILES),
@@ -470,19 +507,38 @@ class WebInterface(object):
"hpuser": headphones.HPUSER,
"hppass": headphones.HPPASS
}
# Need to convert EXTRAS to a dictionary we can pass to the config: it'll come in as a string like 2,5,6,8
extras_list = ["single", "ep", "compilation", "soundtrack", "live", "remix", "spokenword", "audiobook"]
extras_dict = {}
i = 1
for extra in extras_list:
if str(i) in headphones.EXTRAS:
extras_dict[extra] = "checked"
else:
extras_dict[extra] = ""
i+=1
config["extras"] = extras_dict
return serve_template(templatename="config.html", title="Settings", config=config)
config.exposed = True
def configUpdate(self, http_host='0.0.0.0', http_username=None, http_port=8181, http_password=None, launch_browser=0, api_enabled=0, api_key=None, download_scan_interval=None, nzb_search_interval=None, libraryscan_interval=None,
sab_host=None, sab_username=None, sab_apikey=None, sab_password=None, sab_category=None, download_dir=None, blackhole=0, blackhole_dir=None,
usenet_retention=None, nzbmatrix=0, nzbmatrix_username=None, nzbmatrix_apikey=None, newznab=0, newznab_host=None, newznab_apikey=None, newznab_enabled=0,
nzbsorg=0, nzbsorg_uid=None, nzbsorg_hash=None, newzbin=0, newzbin_uid=None, newzbin_password=None, preferred_quality=0, preferred_bitrate=None, detect_bitrate=0, move_files=0,
torrentblackhole_dir=None, download_torrent_dir=None, numberofseeders=10, use_isohunt=0, use_kat=0, use_mininova=0, waffles=0, waffles_uid=None, waffles_passkey=None,
rename_files=0, correct_metadata=0, cleanup_files=0, add_album_art=0, embed_album_art=0, embed_lyrics=0, destination_dir=None, lossless_destination_dir=None, folder_format=None, file_format=None, include_extras=0, autowant_upcoming=False, autowant_all=False, interface=None, log_dir=None,
music_encoder=0, encoder=None, bitrate=None, samplingfrequency=None, encoderfolder=None, advancedencoder=None, encoderoutputformat=None, encodervbrcbr=None, encoderquality=None, encoderlossless=0, delete_lossless_files=0,
prowl_enabled=0, prowl_onsnatch=0, prowl_keys=None, prowl_priority=0, xbmc_enabled=0, xbmc_host=None, xbmc_username=None, xbmc_password=None, xbmc_update=0, xbmc_notify=0,
nma_enabled=False, nma_apikey=None, nma_priority=0, synoindex_enabled=False, mirror=None, customhost=None, customport=None, customsleep=None, hpuser=None, hppass=None, **kwargs):
def configUpdate(self, http_host='0.0.0.0', http_username=None, http_port=8181, http_password=None, launch_browser=0, api_enabled=0, api_key=None,
download_scan_interval=None, nzb_search_interval=None, libraryscan_interval=None, sab_host=None, sab_username=None, sab_apikey=None, sab_password=None,
sab_category=None, download_dir=None, blackhole=0, blackhole_dir=None, usenet_retention=None, nzbmatrix=0, nzbmatrix_username=None, nzbmatrix_apikey=None,
newznab=0, newznab_host=None, newznab_apikey=None, newznab_enabled=0, nzbsorg=0, nzbsorg_uid=None, nzbsorg_hash=None, newzbin=0, newzbin_uid=None,
newzbin_password=None, preferred_quality=0, preferred_bitrate=None, detect_bitrate=0, move_files=0, torrentblackhole_dir=None, download_torrent_dir=None,
numberofseeders=10, use_isohunt=0, use_kat=0, use_mininova=0, waffles=0, waffles_uid=None, waffles_passkey=None, rename_files=0, correct_metadata=0,
cleanup_files=0, add_album_art=0, embed_album_art=0, embed_lyrics=0, destination_dir=None, lossless_destination_dir=None, folder_format=None, file_format=None,
include_extras=0, single=0, ep=0, compilation=0, soundtrack=0, live=0, remix=0, spokenword=0, audiobook=0, autowant_upcoming=False, autowant_all=False,
interface=None, log_dir=None, music_encoder=0, encoder=None, bitrate=None, samplingfrequency=None, encoderfolder=None, advancedencoder=None,
encoderoutputformat=None, encodervbrcbr=None, encoderquality=None, encoderlossless=0, delete_lossless_files=0, prowl_enabled=0, prowl_onsnatch=0,
prowl_keys=None, prowl_priority=0, xbmc_enabled=0, xbmc_host=None, xbmc_username=None, xbmc_password=None, xbmc_update=0, xbmc_notify=0, nma_enabled=False,
nma_apikey=None, nma_priority=0, synoindex_enabled=False, mirror=None, customhost=None, customport=None, customsleep=None, hpuser=None, hppass=None,
preferred_bitrate_high_buffer=None, preferred_bitrate_low_buffer=None, **kwargs):
headphones.HTTP_HOST = http_host
headphones.HTTP_PORT = http_port
@@ -527,6 +583,8 @@ class WebInterface(object):
headphones.WAFFLES_PASSKEY = waffles_passkey
headphones.PREFERRED_QUALITY = int(preferred_quality)
headphones.PREFERRED_BITRATE = preferred_bitrate
headphones.PREFERRED_BITRATE_HIGH_BUFFER = preferred_bitrate_high_buffer
headphones.PREFERRED_BITRATE_LOW_BUFFER = preferred_bitrate_low_buffer
headphones.DETECT_BITRATE = detect_bitrate
headphones.MOVE_FILES = move_files
headphones.CORRECT_METADATA = correct_metadata
@@ -591,7 +649,20 @@ class WebInterface(object):
newznab_enabled = 0
headphones.EXTRA_NEWZNABS.append((newznab_host, newznab_api, newznab_enabled))
# Convert the extras to list then string. Coming in as 0 or 1
temp_extras_list = []
extras_list = [single, ep, compilation, soundtrack, live, remix, spokenword, audiobook]
i = 1
for extra in extras_list:
if extra:
temp_extras_list.append(i)
i+=1
headphones.EXTRAS = ','.join(str(n) for n in temp_extras_list)
# Write the config
headphones.config_write()
raise cherrypy.HTTPRedirect("config")