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
from mb import getReleaseGroup
import logger
database = os.path.join(FULL_PATH, 'headphones.db')
class Headphones:
def index(self):
raise cherrypy.HTTPRedirect("home")
index.exposed=True
def home(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('''
| Artist Name |
Status |
Upcoming Albums |
|
''')
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 = '%s' % (latestalbum[0][3], latestalbum[0][0])
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('''| %s
(link) [delete] |
%s |
%s %s |
''' % (results[i][1], results[i][0], results[i][1], results[i][1], newStatus, newalbumName, releaseDate))
i = i+1
c.close()
page.append('''
''')
page.append(templates._footer)
else:
page.append("""Add some artists to the database!
""")
return page
home.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
|
Album Name |
Release Date |
Status |
|
''' % (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(''' |
%s
(link) |
%s |
%s |
''' % (results[i][5], results[i][2], results[i][0], results[i][2], results[i][1], newStatus))
i = i+1
page.append('''
''')
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
| Track # |
Track Title |
Duration |
|
''' % (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('''| %s |
%s (link) |
%s |
''' % (i+1, results[i][3], results[i][5], duration))
i = i+1
page.append('''
''')
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("home")
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
detail = artist.getDisambiguation()
if detail:
disambiguation = '(%s)' % detail
else:
disambiguation = ''
page.append('''%s %s (more info)
''' % (u.extractUuid(artist.id), artist.name, disambiguation, 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), releaseGroups=True)
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 rg in artist.getReleaseGroups():
rgid = u.extractUuid(rg.id)
releaseid = getReleaseGroup(rgid)
inc = ws.ReleaseIncludes(artist=True, releaseEvents= True, tracks= True, releaseGroup=True)
results = ws.Query().getReleaseById(releaseid, inc)
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)))
time.sleep(1)
conn.commit()
c.close()
raise cherrypy.HTTPRedirect("home")
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("home")
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("home")
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("home")
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('''
|
Upcoming Albums
|
|
|
''')
if len(albums) == 0:
page.append("""
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('''| %s |
%s |
%s (%s) |
''' % (albumart, albums[i][6], albums[i][5], albums[i][4], albums[i][0], albums[i][1]))
i += 1
page.append('''
''')
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'
try:
path2 = config['General']['path_to_itunes']
except:
path2 = 'Enter a directory to scan'
page = [templates._header]
page.append(templates._logobar)
page.append(templates._nav)
page.append('''
Scan Music Library
Where do you keep your music?
You can put in any directory, and it will scan for audio files in that folder
(including all subdirectories)
For example: '/Users/name/Music'
It may take a while depending on how many files you have. You can navigate away from the page
as soon as you click 'Submit'
Import or Sync Your iTunes Library/Music Folder
This is here for legacy purposes (try the Music Scanner above!)
If you'd rather import an iTunes .xml file, you can enter the full path here.
''' % (path2, 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("home")
importItunes.exposed = True
def musicScan(self, path):
config = configobj.ConfigObj(config_file)
config['General']['path_to_itunes'] = path
config.write()
import itunesimport
itunesimport.scanMusic(path)
raise cherrypy.HTTPRedirect("home")
musicScan.exposed = True
def forceUpdate(self):
import updater
updater.dbUpdate()
raise cherrypy.HTTPRedirect("home")
forceUpdate.exposed = True
def forceSearch(self):
import searcher
searcher.searchNZB()
raise cherrypy.HTTPRedirect("home")
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("""
""")
i = 0
while i < len(snatched):
mb = snatched[i][2] / 1048576
size = '%.2fM' % mb
page.append('''| %s |
%s |
%s |
%s |
''' % (snatched[i][5], snatched[i][1], size, snatched[i][4]))
i += 1
page.append('''
''')
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