diff --git a/TODO b/TODO new file mode 100644 index 00000000..f9066c0e --- /dev/null +++ b/TODO @@ -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) diff --git a/data/interfaces/default/album.html b/data/interfaces/default/album.html index 6af0459d..c3609d07 100644 --- a/data/interfaces/default/album.html +++ b/data/interfaces/default/album.html @@ -170,7 +170,7 @@ function initThisPage() { $('#album_chooser').click(function() { - $('#dialog').dialog(); + $('#dialog').dialog({ width: "500px" }); return false; }); $('#refresh_artist').click(function() { diff --git a/data/interfaces/default/artist.html b/data/interfaces/default/artist.html index b0d8af05..49acbef7 100644 --- a/data/interfaces/default/artist.html +++ b/data/interfaces/default/artist.html @@ -2,6 +2,7 @@ <%! from headphones import db import headphones + import string %> <%def name="headerIncludes()"> @@ -16,9 +17,21 @@ %endif %if artist['IncludeExtras']: Remove Extras + Modify Extras %else: - Get Extras + Get Extras %endif + « Back to overview @@ -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 diff --git a/data/interfaces/default/config.html b/data/interfaces/default/config.html index 3dfa2420..75219f33 100644 --- a/data/interfaces/default/config.html +++ b/data/interfaces/default/config.html @@ -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"/>
Quality
- + - -
-
- - -
+ Preferred Bitrate: kbps
+
+ Reject if less than % or more than % of the target size (leave blank for no limit)

+
+ + +
+
+
@@ -505,9 +508,30 @@ m<%inherit file="base.html"/>
Miscellaneous
- - -
+ + +
+ %for extra in config['extras']: + ${string.capwords(extra)}
+ %endfor +
+
@@ -707,6 +731,13 @@ m<%inherit file="base.html"/> } }; + function openExtrasDialog() { + $("#dialog").dialog({ close: function(){ + var elem = ''; + 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; diff --git a/data/interfaces/default/css/style.css b/data/interfaces/default/css/style.css index 54a2bc7c..e171b4db 100644 --- a/data/interfaces/default/css/style.css +++ b/data/interfaces/default/css/style.css @@ -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; diff --git a/headphones/__init__.py b/headphones/__init__.py index 2b938e02..3126e793 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -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() diff --git a/headphones/importer.py b/headphones/importer.py index ecf74a1f..571360e9 100644 --- a/headphones/importer.py +++ b/headphones/importer.py @@ -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) diff --git a/headphones/mb.py b/headphones/mb.py index 5f9d168d..29b5bb8a 100644 --- a/headphones/mb.py +++ b/headphones/mb.py @@ -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 diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index 5f0c9842..f9bfc833 100644 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -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'], diff --git a/headphones/searcher.py b/headphones/searcher.py index 50068271..7470c790 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -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: diff --git a/headphones/webserve.py b/headphones/webserve.py index d00c1f86..7e905a24 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -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")