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:
parent
00e88361f3
commit
98bb35d4d1
@ -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():
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user