import templates import config import cherrypy import musicbrainz2.webservice as ws import musicbrainz2.model as m import musicbrainz2.utils as u import os import string import time import datetime import sqlite3 import sys import configobj from headphones import FULL_PATH, config_file import logger database = os.path.join(FULL_PATH, 'headphones.db') class Headphones: def index(self): page = [templates._header] page.append(templates._logobar) page.append(templates._nav) conn=sqlite3.connect(database) c=conn.cursor() c.execute('SELECT ArtistName, ArtistID, Status from artists order by ArtistSortName collate nocase') results = c.fetchall() if len(results): i = 0 page.append('''
''') while i < len(results): c.execute('''SELECT AlbumTitle, ReleaseDate, DateAdded, AlbumID from albums WHERE ArtistID='%s' order by ReleaseDate DESC''' % results[i][1]) latestalbum = c.fetchall() today = datetime.date.today() if len(latestalbum) > 0: if latestalbum[0][1] > datetime.date.isoformat(today): newalbumName = '%s' % (latestalbum[0][3], latestalbum[0][0]) releaseDate = '(%s)' % latestalbum[0][1] else: newalbumName = 'None' releaseDate = "" if len(latestalbum) == 0: newalbumName = 'None' releaseDate = "" if results[i][2] == 'Paused': newStatus = '''%s(resume)''' % (results[i][2], results[i][1]) else: newStatus = '''%s(pause)''' % (results[i][2], results[i][1]) page.append('''''' % (results[i][1], results[i][0], results[i][1], results[i][1], newStatus, newalbumName, releaseDate)) i = i+1 c.close() page.append('''
Artist Name Status Upcoming Albums
%s (link) [delete] %s %s %s
''') page.append(templates._footer) else: page.append("""
Add some artists to the database!
""") return page index.exposed = True def artistPage(self, ArtistID): page = [templates._header] page.append(templates._logobar) page.append(templates._nav) conn=sqlite3.connect(database) c=conn.cursor() c.execute('''SELECT ArtistName from artists WHERE ArtistID="%s"''' % ArtistID) artistname = c.fetchall() c.execute('''SELECT AlbumTitle, ReleaseDate, AlbumID, Status, ArtistName, AlbumASIN from albums WHERE ArtistID="%s" order by ReleaseDate DESC''' % ArtistID) results = c.fetchall() c.close() i = 0 page.append('''

%s

''' % (artistname[0])) while i < len(results): if results[i][3] == 'Skipped': newStatus = '''%s [want]''' % (results[i][3], results[i][2], ArtistID) elif results[i][3] == 'Wanted': newStatus = '''%s[skip]''' % (results[i][3], results[i][2], ArtistID) elif results[i][3] == 'Downloaded': newStatus = '''%s[retry]''' % (results[i][3], results[i][2], ArtistID) elif results[i][3] == 'Snatched': newStatus = '''%s[retry]''' % (results[i][3], results[i][2], ArtistID) else: newStatus = '%s' % (results[i][3]) page.append('''''' % (results[i][5], results[i][2], results[i][0], results[i][2], results[i][1], newStatus)) i = i+1 page.append('''
Album Name Release Date Status
%s (link) %s %s
''') page.append(templates._footer) return page artistPage.exposed = True def albumPage(self, AlbumID): page = [templates._header] page.append(templates._logobar) page.append(templates._nav) conn=sqlite3.connect(database) c=conn.cursor() c.execute('''SELECT ArtistID, ArtistName, AlbumTitle, TrackTitle, TrackDuration, TrackID, AlbumASIN from tracks WHERE AlbumID="%s"''' % AlbumID) results = c.fetchall() if results[0][6]: albumart = '''


''' % results[0][6] else: albumart = '' c.close() i = 0 page.append('''
%s - %s
Download
%s

''' % (results[0][0], results[0][1], results[0][2], AlbumID, results[0][0], albumart)) while i < len(results): if results[i][4]: duration = time.strftime("%M:%S", time.gmtime(int(results[i][4])/1000)) else: duration = 'n/a' page.append('''''' % (i+1, results[i][3], results[i][5], duration)) i = i+1 page.append('''
Track # Track Title Duration
%s %s (link) %s
''') page.append(templates._footer) return page albumPage.exposed = True def findArtist(self, name): page = [templates._header] if len(name) == 0 or name == 'Add an artist': raise cherrypy.HTTPRedirect("/") else: artistResults = ws.Query().getArtists(ws.ArtistFilter(string.replace(name, '&', '%38'), limit=8)) if len(artistResults) == 0: logger.log(u"No results found for " + name) page.append('''No results!Go back''') return page elif len(artistResults) > 1: page.append('''Search returned multiple artists. Click the artist you want to add:

''') for result in artistResults: artist = result.artist page.append('''%s (more info)
''' % (u.extractUuid(artist.id), artist.name, u.extractUuid(artist.id))) return page else: for result in artistResults: artist = result.artist logger.log(u"Found one artist matching your search term: " + artist.name +" ("+ artist.id+")") raise cherrypy.HTTPRedirect("addArtist?artistid=%s" % u.extractUuid(artist.id)) findArtist.exposed = True def artistInfo(self, artistid): page = [templates._header] inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True) artist = ws.Query().getArtistById(artistid, inc) page.append('''Artist Name: %s
''' % artist.name) page.append('''Unique ID: %s

Albums:
''' % u.extractUuid(artist.id)) for rg in artist.getReleaseGroups(): page.append('''%s
''' % rg.title) return page artistInfo.exposed = True def addArtist(self, artistid): inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), ratings=False, releaseGroups=False) artist = ws.Query().getArtistById(artistid, inc) conn=sqlite3.connect(database) c=conn.cursor() c.execute('SELECT ArtistID from artists') artistlist = c.fetchall() if any(artistid in x for x in artistlist): page = [templates._header] page.append('''%s has already been added. Go back.''' % artist.name) logger.log(artist.name + u" is already in the database!", logger.WARNING) c.close() return page else: logger.log(u"Adding " + artist.name + " to the database.") c.execute('INSERT INTO artists VALUES( ?, ?, ?, CURRENT_DATE, ?)', (artistid, artist.name, artist.sortName, 'Active')) for release in artist.getReleases(): releaseid = u.extractUuid(release.id) inc = ws.ReleaseIncludes(artist=True, releaseEvents= True, tracks= True, releaseGroup=True) results = ws.Query().getReleaseById(releaseid, inc) time.sleep(0.6) for event in results.releaseEvents: if event.country == 'US': logger.log(u"Now adding album: " + results.title+ " to the database") c.execute('INSERT INTO albums VALUES( ?, ?, ?, ?, ?, CURRENT_DATE, ?, ?)', (artistid, results.artist.name, results.title, results.asin, results.getEarliestReleaseDate(), u.extractUuid(results.id), 'Skipped')) c.execute('SELECT ReleaseDate, DateAdded from albums WHERE AlbumID="%s"' % u.extractUuid(results.id)) latestrelease = c.fetchall() if latestrelease[0][0] > latestrelease[0][1]: logger.log(results.title + u" is an upcoming album. Setting its status to 'Wanted'...") c.execute('UPDATE albums SET Status = "Wanted" WHERE AlbumID="%s"' % u.extractUuid(results.id)) else: pass for track in results.tracks: c.execute('INSERT INTO tracks VALUES( ?, ?, ?, ?, ?, ?, ?, ?)', (artistid, results.artist.name, results.title, results.asin, u.extractUuid(results.id), track.title, track.duration, u.extractUuid(track.id))) else: logger.log(results.title + " is not a US release. Skipping it for now", logger.DEBUG) conn.commit() c.close() raise cherrypy.HTTPRedirect("/") addArtist.exposed = True def pauseArtist(self, ArtistID): conn=sqlite3.connect(database) c=conn.cursor() logger.log(u"Pausing artist: " + ArtistID) c.execute('UPDATE artists SET status = "Paused" WHERE ArtistId="%s"' % ArtistID) conn.commit() c.close() raise cherrypy.HTTPRedirect("/") pauseArtist.exposed = True def resumeArtist(self, ArtistID): conn=sqlite3.connect(database) c=conn.cursor() logger.log(u"Resuming artist: " + ArtistID) c.execute('UPDATE artists SET status = "Active" WHERE ArtistId="%s"' % ArtistID) conn.commit() c.close() raise cherrypy.HTTPRedirect("/") resumeArtist.exposed = True def deleteArtist(self, ArtistID): conn=sqlite3.connect(database) c=conn.cursor() logger.log(u"Deleting all traces of artist: " + ArtistID) c.execute('''DELETE from artists WHERE ArtistID="%s"''' % ArtistID) c.execute('''DELETE from albums WHERE ArtistID="%s"''' % ArtistID) c.execute('''DELETE from tracks WHERE ArtistID="%s"''' % ArtistID) conn.commit() c.close() raise cherrypy.HTTPRedirect("/") deleteArtist.exposed = True def queueAlbum(self, AlbumID, ArtistID): conn=sqlite3.connect(database) c=conn.cursor() logger.log(u"Marking album: " + AlbumID + "as wanted...") c.execute('UPDATE albums SET status = "Wanted" WHERE AlbumID="%s"' % AlbumID) conn.commit() c.close() import searcher searcher.searchNZB(AlbumID) raise cherrypy.HTTPRedirect("/artistPage?ArtistID=%s" % ArtistID) queueAlbum.exposed = True def unqueueAlbum(self, AlbumID, ArtistID): conn=sqlite3.connect(database) c=conn.cursor() logger.log(u"Marking album: " + AlbumID + "as skipped...") c.execute('UPDATE albums SET status = "Skipped" WHERE AlbumID="%s"' % AlbumID) conn.commit() c.close() raise cherrypy.HTTPRedirect("/artistPage?ArtistID=%s" % ArtistID) unqueueAlbum.exposed = True def upcoming(self): page = [templates._header] page.append(templates._logobar) page.append(templates._nav) today = datetime.date.today() todaysql = datetime.date.isoformat(today) conn=sqlite3.connect(database) c=conn.cursor() c.execute('''SELECT AlbumTitle, ReleaseDate, DateAdded, AlbumASIN, AlbumID, ArtistName, ArtistID from albums WHERE ReleaseDate > date('now') order by ReleaseDate DESC''') albums = c.fetchall() page.append('''
''') if len(albums) == 0: page.append("""
Upcoming Albums

No albums are coming out soon :(
(try adding some more artists!)
""") i = 0 while i < len(albums): if albums[i][3]: albumart = '''


''' % (albums[i][3], albums[i][3]) else: albumart = 'No Album Art... yet.' page.append(''' ''' % (albumart, albums[i][6], albums[i][5], albums[i][4], albums[i][0], albums[i][1])) i += 1 page.append('''
%s %s %s (%s)
''') if len(albums): page.append(templates._footer) return page upcoming.exposed = True def manage(self): config = configobj.ConfigObj(config_file) try: path = config['General']['path_to_xml'] except: path = 'Absolute path to iTunes XML or Top-Level Music Directory' page = [templates._header] page.append(templates._logobar) page.append(templates._nav) page.append('''

Import or Sync Your iTunes Library/Music Folder


Enter the full path to your iTunes XML file or music folder

i.e. /Users/"username"/Music/iTunes/iTunes Music Library.xml
or /Users/"username"/Music/iTunes/iTunes Media/Music

(artists should have their own directories for folder import to work)

note: This process can take a LONG time!

Once you click "Submit" you can navigate away from this page while the process runs.




Force Search


Force Check for Wanted Albums

Force Update Active Artists


''' % path) page.append(templates._footer) return page manage.exposed = True def importItunes(self, path): config = configobj.ConfigObj(config_file) config['General']['path_to_xml'] = path config.write() import itunesimport itunesimport.itunesImport(path) raise cherrypy.HTTPRedirect("/") importItunes.exposed = True def forceUpdate(self): import updater updater.dbUpdate() raise cherrypy.HTTPRedirect("/") forceUpdate.exposed = True def forceSearch(self): import searcher searcher.searchNZB() raise cherrypy.HTTPRedirect("/") forceSearch.exposed = True def history(self): page = [templates._header] page.append(templates._logobar) page.append(templates._nav) conn=sqlite3.connect(database) c=conn.cursor() c.execute('''SELECT AlbumID, Title TEXT, Size INTEGER, URL TEXT, DateAdded TEXT, Status TEXT from snatched order by DateAdded DESC''') snatched = c.fetchall() page.append('''
''') if len(snatched) == 0: page.append("""
History clear all

""") i = 0 while i < len(snatched): mb = snatched[i][2] / 1048576 size = '%.2fM' % mb page.append(''' ''' % (snatched[i][5], snatched[i][1], size, snatched[i][4])) i += 1 page.append('''
%s %s %s %s
''') if len(snatched): page.append(templates._footer) return page history.exposed = True def clearhistory(self): conn=sqlite3.connect(database) c=conn.cursor() logger.log(u"Clearing history") c.execute('''DELETE from snatched''') conn.commit() c.close() raise cherrypy.HTTPRedirect("/history") clearhistory.exposed = True def config(self): page = [templates._header] page.append(templates._logobar) page.append(templates._nav) page.append(config.form) #page.append(templates._footer) return page config.exposed = True def configUpdate(self, http_host='127.0.0.1', http_username=None, http_port=8181, http_password=None, launch_browser=0, sab_host=None, sab_username=None, sab_apikey=None, sab_password=None, sab_category=None, music_download_dir=None, usenet_retention=None, nzbmatrix=0, nzbmatrix_username=None, nzbmatrix_apikey=None, newznab=0, newznab_host=None, newznab_apikey=None, nzbsorg=0, nzbsorg_uid=None, nzbsorg_hash=None, include_lossless=0,flac_to_mp3=0, move_to_itunes=0, path_to_itunes=None, rename_mp3s=0, cleanup=0, add_album_art=0): configs = configobj.ConfigObj(config_file) SABnzbd = configs['SABnzbd'] General = configs['General'] NZBMatrix = configs['NZBMatrix'] Newznab = configs['Newznab'] NZBsorg = configs['NZBsorg'] General['http_host'] = http_host General['http_port'] = http_port General['http_username'] = http_username General['http_password'] = http_password General['launch_browser'] = launch_browser SABnzbd['sab_host'] = sab_host SABnzbd['sab_username'] = sab_username SABnzbd['sab_password'] = sab_password SABnzbd['sab_apikey'] = sab_apikey SABnzbd['sab_category'] = sab_category General['music_download_dir'] = music_download_dir General['usenet_retention'] = usenet_retention NZBMatrix['nzbmatrix'] = nzbmatrix NZBMatrix['nzbmatrix_username'] = nzbmatrix_username NZBMatrix['nzbmatrix_apikey'] = nzbmatrix_apikey Newznab['newznab'] = newznab Newznab['newznab_host'] = newznab_host Newznab['newznab_apikey'] = newznab_apikey NZBsorg['nzbsorg'] = nzbsorg NZBsorg['nzbsorg_uid'] = nzbsorg_uid NZBsorg['nzbsorg_hash'] = nzbsorg_hash General['include_lossless'] = include_lossless General['flac_to_mp3'] = flac_to_mp3 General['move_to_itunes'] = move_to_itunes General['path_to_itunes'] = path_to_itunes General['rename_mp3s'] = rename_mp3s General['cleanup'] = cleanup General['add_album_art'] = add_album_art configs.write() reload(config) raise cherrypy.HTTPRedirect("/config") configUpdate.exposed = True def shutdown(self): sys.exit(0) shutdown.exposed = True def restart(self): logger.log(u"Restarting Headphones.") restart = True #answer = raw_input("Do you want to restart this program ? ") #if answer.strip() in "y Y yes Yes YES".split(): #restart = True if restart: python = sys.executable os.execl(python, python, * sys.argv) restart.exposed = True