def main(): args = parse_args() # TODO: support config files and overrides (shared from main?) config_files = [b'/etc/mopidy/mopidy.conf', b'$XDG_CONFIG_DIR/mopidy/mopidy.conf'] config_overrides = [] # TODO: decide if we want to avoid this boilerplate some how. # Initial config without extensions to bootstrap logging. logging_config, _ = config_lib.load(config_files, [], config_overrides) log.setup_root_logger() log.setup_console_logging(logging_config, args.verbosity_level) extensions = ext.load_extensions() config, errors = config_lib.load( config_files, extensions, config_overrides) log.setup_log_levels(config) if not config['local']['media_dir']: logging.warning('Config value local/media_dir is not set.') return if not config['local']['scan_timeout']: logging.warning('Config value local/scan_timeout is not set.') return # TODO: missing config error checking and other default setup code. updaters = {} for e in extensions: for updater_class in e.get_library_updaters(): if updater_class and 'local' in updater_class.uri_schemes: updaters[e.ext_name] = updater_class if not updaters: logging.error('No usable library updaters found.') return elif len(updaters) > 1: logging.error('More than one library updater found. ' 'Provided by: %s', ', '.join(updaters.keys())) return local_updater = updaters.values()[0](config) # TODO: switch to actor? media_dir = config['local']['media_dir'] uris_library = set() uris_update = set() uris_remove = set() logging.info('Checking tracks from library.') for track in local_updater.load(): try: stat = os.stat(path.uri_to_path(track.uri)) if int(stat.st_mtime) > track.last_modified: uris_update.add(track.uri) uris_library.add(track.uri) except OSError: uris_remove.add(track.uri) logging.info('Removing %d moved or deleted tracks.', len(uris_remove)) for uri in uris_remove: local_updater.remove(uri) logging.info('Checking %s for new or modified tracks.', media_dir) for uri in path.find_uris(config['local']['media_dir']): if uri not in uris_library: uris_update.add(uri) logging.info('Found %d new or modified tracks.', len(uris_update)) def store(data): track = translator(data) local_updater.add(track) logging.debug('Added %s', track.uri) def debug(uri, error, debug): logging.warning('Failed %s: %s', uri, error) logging.debug('Debug info for %s: %s', uri, debug) scan_timeout = config['local']['scan_timeout'] logging.info('Scanning new and modified tracks.') # TODO: just pass the library in instead? scanner = Scanner(uris_update, store, debug, scan_timeout) try: scanner.start() except KeyboardInterrupt: scanner.stop() raise logging.info('Done scanning; commiting changes.') local_updater.commit()
def find(self, value): return list(path.find_uris(path_to_data_dir(value)))
def run(self, args, config, extensions): media_dir = config['local']['media_dir'] scan_timeout = config['local']['scan_timeout'] excluded_file_extensions = set( ext.lower() for ext in config['local']['excluded_file_extensions']) updaters = {} for e in extensions: for updater_class in e.get_library_updaters(): if updater_class and 'local' in updater_class.uri_schemes: updaters[e.ext_name] = updater_class if not updaters: logger.error('No usable library updaters found.') return 1 elif len(updaters) > 1: logger.error( 'More than one library updater found. ' 'Provided by: %s', ', '.join(updaters.keys())) return 1 local_updater = updaters.values()[0](config) # TODO: cleanup to consistently use local urls, not a random mix of # local and file uris depending on how the data was loaded. uris_library = set() uris_update = set() uris_remove = set() tracks = local_updater.load() logger.info('Checking %d tracks from library.', len(tracks)) for track in tracks: try: uri = translator.local_to_file_uri(track.uri, media_dir) stat = os.stat(path.uri_to_path(uri)) if int(stat.st_mtime) > track.last_modified: uris_update.add(uri) uris_library.add(uri) except OSError: logger.debug('Missing file %s', track.uri) uris_remove.add(track.uri) logger.info('Removing %d missing tracks.', len(uris_remove)) for uri in uris_remove: local_updater.remove(uri) logger.info('Checking %s for unknown tracks.', media_dir) for uri in path.find_uris(media_dir): file_extension = os.path.splitext(path.uri_to_path(uri))[1] if file_extension.lower() in excluded_file_extensions: logger.debug('Skipped %s: File extension excluded.', uri) continue if uri not in uris_library: uris_update.add(uri) logger.info('Found %d unknown tracks.', len(uris_update)) logger.info('Scanning...') scanner = scan.Scanner(scan_timeout) progress = Progress(len(uris_update)) for uri in sorted(uris_update): try: data = scanner.scan(uri) track = scan.audio_data_to_track(data) local_updater.add(track) logger.debug('Added %s', track.uri) except exceptions.ScannerError as error: logger.warning('Failed %s: %s', uri, error) progress.increment() logger.info('Commiting changes.') local_updater.commit() return 0
def run(self, args, config, extensions): media_dir = config['local']['media_dir'] scan_timeout = config['local']['scan_timeout'] excluded_file_extensions = set( ext.lower() for ext in config['local']['excluded_file_extensions']) updaters = {} for e in extensions: for updater_class in e.get_library_updaters(): if updater_class and 'local' in updater_class.uri_schemes: updaters[e.ext_name] = updater_class if not updaters: logger.error('No usable library updaters found.') return 1 elif len(updaters) > 1: logger.error('More than one library updater found. ' 'Provided by: %s', ', '.join(updaters.keys())) return 1 local_updater = updaters.values()[0](config) # TODO: cleanup to consistently use local urls, not a random mix of # local and file uris depending on how the data was loaded. uris_library = set() uris_update = set() uris_remove = set() tracks = local_updater.load() logger.info('Checking %d tracks from library.', len(tracks)) for track in tracks: try: uri = translator.local_to_file_uri(track.uri, media_dir) stat = os.stat(path.uri_to_path(uri)) if int(stat.st_mtime) > track.last_modified: uris_update.add(uri) uris_library.add(uri) except OSError: logger.debug('Missing file %s', track.uri) uris_remove.add(track.uri) logger.info('Removing %d missing tracks.', len(uris_remove)) for uri in uris_remove: local_updater.remove(uri) logger.info('Checking %s for unknown tracks.', media_dir) for uri in path.find_uris(media_dir): file_extension = os.path.splitext(path.uri_to_path(uri))[1] if file_extension.lower() in excluded_file_extensions: logger.debug('Skipped %s: File extension excluded.', uri) continue if uri not in uris_library: uris_update.add(uri) logger.info('Found %d unknown tracks.', len(uris_update)) logger.info('Scanning...') scanner = scan.Scanner(scan_timeout) progress = Progress(len(uris_update)) for uri in sorted(uris_update): try: data = scanner.scan(uri) track = scan.audio_data_to_track(data) local_updater.add(track) logger.debug('Added %s', track.uri) except exceptions.ScannerError as error: logger.warning('Failed %s: %s', uri, error) progress.increment() logger.info('Commiting changes.') local_updater.commit() return 0
def main(): args = parse_args() # TODO: support config files and overrides (shared from main?) config_files = [ b'/etc/mopidy/mopidy.conf', b'$XDG_CONFIG_DIR/mopidy/mopidy.conf' ] config_overrides = [] # TODO: decide if we want to avoid this boilerplate some how. # Initial config without extensions to bootstrap logging. logging_config, _ = config_lib.load(config_files, [], config_overrides) log.setup_root_logger() log.setup_console_logging(logging_config, args.verbosity_level) extensions = ext.load_extensions() config, errors = config_lib.load(config_files, extensions, config_overrides) log.setup_log_levels(config) if not config['local']['media_dir']: logging.warning('Config value local/media_dir is not set.') return if not config['local']['scan_timeout']: logging.warning('Config value local/scan_timeout is not set.') return # TODO: missing config error checking and other default setup code. updaters = {} for e in extensions: for updater_class in e.get_library_updaters(): if updater_class and 'local' in updater_class.uri_schemes: updaters[e.ext_name] = updater_class if not updaters: logging.error('No usable library updaters found.') return elif len(updaters) > 1: logging.error( 'More than one library updater found. ' 'Provided by: %s', ', '.join(updaters.keys())) return local_updater = updaters.values()[0](config) # TODO: switch to actor? media_dir = config['local']['media_dir'] excluded_extensions = config['local']['excluded_file_extensions'] uris_library = set() uris_update = set() uris_remove = set() logging.info('Checking tracks from library.') for track in local_updater.load(): try: stat = os.stat(path.uri_to_path(track.uri)) if int(stat.st_mtime) > track.last_modified: uris_update.add(track.uri) uris_library.add(track.uri) except OSError: uris_remove.add(track.uri) logging.info('Removing %d moved or deleted tracks.', len(uris_remove)) for uri in uris_remove: local_updater.remove(uri) logging.info('Checking %s for new or modified tracks.', media_dir) for uri in path.find_uris(config['local']['media_dir']): if os.path.splitext(path.uri_to_path(uri))[1] in excluded_extensions: logging.debug('Skipped %s: File extension excluded.', uri) continue if uri not in uris_library: uris_update.add(uri) logging.info('Found %d new or modified tracks.', len(uris_update)) logging.info('Scanning new and modified tracks.') scanner = Scanner(config['local']['scan_timeout']) for uri in uris_update: try: data = scanner.scan(uri) data[b'mtime'] = os.path.getmtime(path.uri_to_path(uri)) track = translator(data) local_updater.add(track) logging.debug('Added %s', track.uri) except exceptions.ScannerError as error: logging.warning('Failed %s: %s', uri, error) logging.info('Done scanning; commiting changes.') local_updater.commit()