1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 08:56:17 +00:00

Changing which methods are available from Scanner and what they do

This commit is contained in:
spl0k 2014-08-04 19:56:45 +02:00
parent 77becdb655
commit deba8aeee4
5 changed files with 63 additions and 63 deletions

View File

@ -141,18 +141,19 @@ class CLI(cmd.Cmd):
print "Scanning '{0}': {1}% ({2}/{3})".format(self.__name, (scanned * 100) / total, scanned, total)
self.__last_display = time.time()
s = Scanner(self.__store)
scanner = Scanner(self.__store)
if folders:
folders = map(lambda n: self.__store.find(Folder, Folder.name == n, Folder.root == True).one() or n, folders)
if any(map(lambda f: isinstance(f, basestring), folders)):
print "No such folder(s): " + ' '.join(f for f in folders if isinstance(f, basestring))
for folder in filter(lambda f: isinstance(f, Folder), folders):
FolderManager.scan(self.__store, folder.id, s, TimedProgressDisplay(folder.name))
scanner.scan(folder, TimedProgressDisplay(folder.name))
else:
for folder in self.__store.find(Folder, Folder.root == True):
FolderManager.scan(self.__store, folder.id, s, TimedProgressDisplay(folder.name))
scanner.scan(folder, TimedProgressDisplay(folder.name))
added, deleted = s.stats()
scanner.finish()
added, deleted = scanner.stats()
self.__store.commit()
print "Scanning done"

View File

@ -47,8 +47,9 @@ class SupysonicWatcherEventHandler(PatternMatchingEventHandler):
store = db.get_store(config.get('base', 'database_uri'))
track = store.find(db.Track, db.Track.path == event.src_path).one()
if track:
folder = track.root_folder
Scanner(store).prune(folder)
scanner = Scanner(store)
scanner.remove_file(track.path)
scanner.finish()
store.commit()
else:
self.__logger.debug("Deleted file %s not in the database", event.src_path)

View File

@ -84,17 +84,19 @@ def del_folder(id):
@app.route('/folder/scan')
@app.route('/folder/scan/<id>')
def scan_folder(id = None):
s = Scanner(store)
scanner = Scanner(store)
if id is None:
for folder in store.find(Folder, Folder.root == True):
FolderManager.scan(store, folder.id, s)
scanner.scan(folder)
else:
status = FolderManager.scan(store, id, s)
status, folder = FolderManager.get(store, id)
if status != FolderManager.SUCCESS:
flash(FolderManager.error_str(status))
return redirect(url_for('folder_index'))
scanner.scan(folder)
added, deleted = s.stats()
scanner.finish()
added, deleted = scanner.stats()
store.commit()
flash('Added: %i artists, %i albums, %i tracks' % (added[0], added[1], added[2]))

View File

@ -20,6 +20,7 @@
import os.path, uuid
from supysonic.db import Folder, Artist, Album, Track
from supysonic.scanner import Scanner
class FolderManager:
SUCCESS = 0
@ -77,24 +78,11 @@ class FolderManager:
if not folder.root:
return FolderManager.NO_SUCH_FOLDER
# delete associated tracks and prune empty albums/artists
potentially_removed_albums = set()
scanner = Scanner(store)
for track in store.find(Track, Track.root_folder_id == folder.id):
potentially_removed_albums.add(track.album)
store.remove(track)
potentially_removed_artists = set()
for album in filter(lambda album: album.tracks.count() == 0, potentially_removed_albums):
potentially_removed_artists.add(album.artist)
store.remove(album)
for artist in filter(lambda artist: artist.albums.count() == 0, potentially_removed_artists):
store.remove(artist)
def cleanup_folder(folder):
for f in folder.children:
cleanup_folder(f)
store.remove(folder)
cleanup_folder(folder)
scanner.remove_file(track.path)
scanner.finish()
store.remove(folder)
store.commit()
return FolderManager.SUCCESS
@ -106,17 +94,6 @@ class FolderManager:
return FolderManager.NO_SUCH_FOLDER
return FolderManager.delete(store, folder.id)
@staticmethod
def scan(store, uid, scanner, progress_callback = None):
status, folder = FolderManager.get(store, uid)
if status != FolderManager.SUCCESS:
return status
scanner.scan(folder, progress_callback)
scanner.prune(folder)
scanner.check_cover_art(folder)
return FolderManager.SUCCESS
@staticmethod
def error_str(err):
if err == FolderManager.SUCCESS:

View File

@ -42,7 +42,16 @@ class Scanner:
extensions = config.get('base', 'scanner_extensions')
self.__extensions = map(str.lower, extensions.split()) if extensions else None
self.__folders_to_check = set()
self.__artists_to_check = set()
self.__albums_to_check = set()
def __del__(self):
if self.__folders_to_check or self.__artists_to_check or self.__albums_to_check:
raise Exception("There's still something to check. Did you run Scanner.finish()?")
def scan(self, folder, progress_callback = None):
# Scan new/updated files
files = [ os.path.join(root, f) for root, _, fs in os.walk(folder.path) for f in fs if self.__is_valid_path(os.path.join(root, f)) ]
total = len(files)
current = 0
@ -53,32 +62,39 @@ class Scanner:
if progress_callback:
progress_callback(current, total)
# Remove files that have been deleted
for track in [ t for t in self.__store.find(Track, Track.root_folder_id == folder.id) if not self.__is_valid_path(t.path) ]:
self.remove_file(track.path)
# Update cover art info
folders = [ folder ]
while folders:
f = folders.pop()
f.has_cover_art = os.path.isfile(os.path.join(f.path, 'cover.jpg'))
folders += f.children
folder.last_scan = int(time.time())
self.__store.flush()
def prune(self, folder):
for track in [ t for t in self.__store.find(Track, Track.root_folder_id == folder.id) if not self.__is_valid_path(t.path) ]:
self.__store.remove(track)
self.__deleted_tracks += 1
# TODO execute the conditional part on SQL
for album in [ a for a in self.__store.find(Album) if a.tracks.count() == 0 ]:
def finish(self):
for album in [ a for a in self.__albums_to_check if not a.tracks.count() ]:
self.__artists_to_check.add(album.artist)
self.__store.remove(album)
self.__deleted_albums += 1
self.__albums_to_check.clear()
# TODO execute the conditional part on SQL
for artist in [ a for a in self.__store.find(Artist) if a.albums.count() == 0 ]:
for artist in [ a for a in self.__artists_to_check if not a.albums.count() ]:
self.__store.remove(artist)
self.__deleted_artists += 1
self.__artists_to_check.clear()
self.__cleanup_folder(folder)
self.__store.flush()
while self.__folders_to_check:
folder = self.__folders_to_check.pop()
if folder.root:
continue
def check_cover_art(self, folder):
folder.has_cover_art = os.path.isfile(os.path.join(folder.path, 'cover.jpg'))
for f in folder.children:
self.check_cover_art(f)
if not folder.tracks.count() and not folder.children.count():
self.__folders_to_check.add(folder.parent)
self.__store.remove(folder)
def __is_valid_path(self, path):
if not os.path.exists(path):
@ -96,8 +112,7 @@ class Scanner:
tag = self.__try_load_tag(path)
if not tag:
self.__store.remove(tr)
self.__deleted_tracks += 1
self.remove_file(path)
return
else:
tag = self.__try_load_tag(path)
@ -134,6 +149,16 @@ class Scanner:
self.__store.add(tr)
self.__added_tracks += 1
def remove_file(self, path):
tr = self.__store.find(Track, Track.path == path).one()
if not tr:
return
self.__folders_to_check.add(tr.folder)
self.__albums_to_check.add(tr.album)
self.__store.remove(tr)
self.__deleted_tracks += 1
def __find_album(self, artist, album):
ar = self.__find_artist(artist)
al = ar.albums.find(name = album).one()
@ -218,12 +243,6 @@ class Scanner:
except:
return default
def __cleanup_folder(self, folder):
for f in folder.children:
self.__cleanup_folder(f)
if folder.children.count() == 0 and folder.tracks.count() == 0 and not folder.root:
self.__store.remove(folder)
def stats(self):
return (self.__added_artists, self.__added_albums, self.__added_tracks), (self.__deleted_artists, self.__deleted_albums, self.__deleted_tracks)