scanner: Convert to using library updater.

This version of the scanner switches to using the updater API, in other words
we are now fairly close to being able to plug in alternate libraries for local
files and populate them with mopidy-scan.
This commit is contained in:
Thomas Adamcik 2013-05-20 23:54:48 +02:00
parent 00e88361f3
commit 98bb35d4d1

View File

@ -5,7 +5,6 @@ import datetime
import logging import logging
import os import os
import sys import sys
import tempfile
import gobject import gobject
gobject.threads_init() gobject.threads_init()
@ -29,7 +28,6 @@ import gst
from mopidy import config as config_lib, ext from mopidy import config as config_lib, ext
from mopidy.audio import dummy as dummy_audio from mopidy.audio import dummy as dummy_audio
from mopidy.frontends.mpd import translator as mpd_translator
from mopidy.models import Track, Artist, Album from mopidy.models import Track, Artist, Album
from mopidy.utils import log, path, versioning from mopidy.utils import log, path, versioning
@ -56,74 +54,60 @@ def main():
logging.warning('Config value local/media_dir is not set.') logging.warning('Config value local/media_dir is not set.')
return return
# TODO: missing error checking and other default setup code. # TODO: missing config error checking and other default setup code.
audio = dummy_audio.DummyAudio() audio = dummy_audio.DummyAudio()
local_backend_classes = extensions['local'].get_backend_classes() local_backend_classes = extensions['local'].get_backend_classes()
local_backend = local_backend_classes[0](config, audio) local_backend = local_backend_classes[0](config, audio)
local_updater = local_backend.updater
tracks = {} # Current lib. media_dir = config['local']['media_dir']
update = [] # Paths to rescan for updates/adds.
remove = [] # Paths to delete from lib.
for track in local_backend.library.search().tracks: uris_library = set()
tracks[track.uri] = track uris_update = set()
uris_remove = set()
logging.info('Checking %d files from library.', len(tracks)) logging.info('Checking tracks from library.')
for track in tracks.itervalues(): for track in local_updater.load():
try: try:
stat = os.stat(path.uri_to_path(track.uri)) stat = os.stat(path.uri_to_path(track.uri))
if int(stat.st_mtime) > track.last_modified: if int(stat.st_mtime) > track.last_modified:
update.append(track.uri) uris_update.add(track.uri)
uris_library.add(track.uri)
except OSError: except OSError:
remove.append(track.uri) uris_remove.add(track.uri)
logging.info('Removing %d files from library.', len(remove)) logging.info('Removing %d moved or deleted tracks.', len(uris_remove))
for uri in remove: for uri in uris_remove:
del tracks[uri] local_updater.remove(uri)
logging.info('Checking %s for changes.', config['local']['media_dir']) logging.info('Checking %s for new or modified tracks.', media_dir)
for p in path.find_files(config['local']['media_dir']): for uri in path.find_uris(config['local']['media_dir']):
uri = path.path_to_uri(p) if uri not in uris_library:
if uri not in tracks: uris_update.add(uri)
update.append(uri)
logging.info('Found %d new or changed tracks.', len(uris_update))
def store(data): def store(data):
track = translator(data) track = translator(data)
tracks[track.uri] = track local_updater.add(track)
logging.debug('Added %s', track.uri) logging.debug('Added %s', track.uri)
def debug(uri, error, debug): def debug(uri, error, debug):
logging.warning('Failed %s: %s', uri, error) logging.warning('Failed %s: %s', uri, error)
logging.debug('Debug info for %s: %s', uri, debug) logging.debug('Debug info for %s: %s', uri, debug)
logging.info('Scanning new and changed tracks.')
logging.info('Scanning %d new/changed files.', len(update)) # TODO: just pass the library in instead?
scanner = Scanner(update, store, debug) scanner = Scanner(uris_update, store, debug)
try: try:
scanner.start() scanner.start()
except KeyboardInterrupt: except KeyboardInterrupt:
scanner.stop() scanner.stop()
raise
logging.info('Done scanning; writing tag cache to temporary file.') logging.info('Done scanning; commiting changes.')
local_updater.commit()
directory, basename = os.path.split(config['local']['tag_cache_file'])
tmp = tempfile.NamedTemporaryFile(
prefix=basename + '.', dir=directory, delete=False)
try:
for row in mpd_translator.tracks_to_tag_cache_format(
tracks.values(), config['local']['media_dir']):
if len(row) == 1:
tmp.write(('%s\n' % row).encode('utf-8'))
else:
tmp.write(('%s: %s\n' % row).encode('utf-8'))
logging.info('Done writing; overwriting active tag cache.')
os.rename(tmp.name, config['local']['tag_cache_file'])
finally:
if os.path.exists(tmp.name):
os.remove(tmp.name)
def parse_args(): def parse_args():