ext: Add basic global registry and switch to Extension.setup()

This commit is contained in:
Thomas Adamcik 2013-12-07 01:00:55 +01:00
parent 0d7fea0a43
commit decce4ccf6
4 changed files with 59 additions and 38 deletions

View File

@ -84,7 +84,6 @@ def main():
enabled_extensions.append(extension) enabled_extensions.append(extension)
log_extension_info(installed_extensions, enabled_extensions) log_extension_info(installed_extensions, enabled_extensions)
ext.register_gstreamer_elements(enabled_extensions)
# Config and deps commands are simply special cased for now. # Config and deps commands are simply special cased for now.
if args.command == config_cmd: if args.command == config_cmd:
@ -108,16 +107,13 @@ def main():
args.extension.ext_name) args.extension.ext_name)
return 1 return 1
registry = {'backends': [], 'frontends': [], 'local:library': []}
for extension in enabled_extensions: for extension in enabled_extensions:
registry['backends'].extend(extension.get_backend_classes()) extension.setup()
registry['frontends'].extend(extension.get_frontend_classes())
registry['local:library'].extend(extension.get_library_updaters())
# Anything that wants to exit after this point must use # Anything that wants to exit after this point must use
# mopidy.utils.process.exit_process as actors can have been started. # mopidy.utils.process.exit_process as actors can have been started.
try: try:
return args.command.run(args, proxied_config, registry) return args.command.run(args, proxied_config)
except NotImplementedError: except NotImplementedError:
print root_cmd.format_help() print root_cmd.format_help()
return 1 return 1

View File

@ -4,7 +4,7 @@ import logging
import os import os
import time import time
from mopidy import commands, exceptions from mopidy import commands, exceptions, ext
from mopidy.audio import scan from mopidy.audio import scan
from mopidy.utils import path from mopidy.utils import path
@ -22,14 +22,15 @@ class LocalCommand(commands.Command):
class ScanCommand(commands.Command): class ScanCommand(commands.Command):
help = "Scan local media files and populate the local library." help = "Scan local media files and populate the local library."
def run(self, args, config, registry): def run(self, args, config):
media_dir = config['local']['media_dir'] media_dir = config['local']['media_dir']
scan_timeout = config['local']['scan_timeout'] scan_timeout = config['local']['scan_timeout']
excluded_file_extensions = config['local']['excluded_file_extensions']
excluded_file_extensions = set( excluded_file_extensions = set(
ext.lower() for ext in config['local']['excluded_file_extensions']) file_ext.lower() for file_ext in excluded_file_extensions)
# TODO: select updater / library to use by name # TODO: select updater / library to use by name
updaters = registry['local:library'] updaters = ext.registry['local:library']
if not updaters: if not updaters:
logger.error('No usable library updaters found.') logger.error('No usable library updaters found.')
return 1 return 1

View File

@ -9,7 +9,7 @@ import sys
import glib import glib
import gobject import gobject
from mopidy import config as config_lib from mopidy import config as config_lib, ext
from mopidy.audio import Audio from mopidy.audio import Audio
from mopidy.core import Core from mopidy.core import Core
from mopidy.utils import deps, process, versioning from mopidy.utils import deps, process, versioning
@ -257,22 +257,26 @@ class RootCommand(Command):
type=config_override_type, metavar='OPTIONS', type=config_override_type, metavar='OPTIONS',
help='`section/key=value` values to override config options') help='`section/key=value` values to override config options')
def run(self, args, config, registry): def run(self, args, config):
loop = gobject.MainLoop() loop = gobject.MainLoop()
backend_classes = ext.registry['backend']
frontend_classes = ext.registry['frontend']
try: try:
audio = self.start_audio(config) audio = self.start_audio(config)
backends = self.start_backends(config, registry, audio) backends = self.start_backends(config, backend_classes, audio)
core = self.start_core(audio, backends) core = self.start_core(audio, backends)
self.start_frontends(config, registry, core) self.start_frontends(config, frontend_classes, core)
loop.run() loop.run()
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info('Interrupted. Exiting...') logger.info('Interrupted. Exiting...')
return return
finally: finally:
loop.quit() loop.quit()
self.stop_frontends(registry) self.stop_frontends(frontend_classes)
self.stop_core() self.stop_core()
self.stop_backends(registry) self.stop_backends(backend_classes)
self.stop_audio() self.stop_audio()
process.stop_remaining_actors() process.stop_remaining_actors()
@ -280,9 +284,7 @@ class RootCommand(Command):
logger.info('Starting Mopidy audio') logger.info('Starting Mopidy audio')
return Audio.start(config=config).proxy() return Audio.start(config=config).proxy()
def start_backends(self, config, registry, audio): def start_backends(self, config, backend_classes, audio):
backend_classes = registry['backends']
logger.info( logger.info(
'Starting Mopidy backends: %s', 'Starting Mopidy backends: %s',
', '.join(b.__name__ for b in backend_classes) or 'none') ', '.join(b.__name__ for b in backend_classes) or 'none')
@ -298,9 +300,7 @@ class RootCommand(Command):
logger.info('Starting Mopidy core') logger.info('Starting Mopidy core')
return Core.start(audio=audio, backends=backends).proxy() return Core.start(audio=audio, backends=backends).proxy()
def start_frontends(self, config, registry, core): def start_frontends(self, config, frontend_classes, core):
frontend_classes = registry['frontends']
logger.info( logger.info(
'Starting Mopidy frontends: %s', 'Starting Mopidy frontends: %s',
', '.join(f.__name__ for f in frontend_classes) or 'none') ', '.join(f.__name__ for f in frontend_classes) or 'none')
@ -308,18 +308,18 @@ class RootCommand(Command):
for frontend_class in frontend_classes: for frontend_class in frontend_classes:
frontend_class.start(config=config, core=core) frontend_class.start(config=config, core=core)
def stop_frontends(self, registry): def stop_frontends(self, frontend_classes):
logger.info('Stopping Mopidy frontends') logger.info('Stopping Mopidy frontends')
for frontend_class in registry['frontends']: for frontend_class in frontend_classes:
process.stop_actors_by_class(frontend_class) process.stop_actors_by_class(frontend_class)
def stop_core(self): def stop_core(self):
logger.info('Stopping Mopidy core') logger.info('Stopping Mopidy core')
process.stop_actors_by_class(Core) process.stop_actors_by_class(Core)
def stop_backends(self, registry): def stop_backends(self, backend_classes):
logger.info('Stopping Mopidy backends') logger.info('Stopping Mopidy backends')
for backend_class in registry['backends']: for backend_class in backend_classes:
process.stop_actors_by_class(backend_class) process.stop_actors_by_class(backend_class)
def stop_audio(self): def stop_audio(self):

View File

@ -1,5 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import collections
import logging import logging
import pkg_resources import pkg_resources
@ -61,6 +62,18 @@ class Extension(object):
""" """
pass pass
def setup(self):
for backend_class in self.get_backend_classes():
registry.add('backend', backend_class)
for frontend_class in self.get_frontend_classes():
registry.add('frontend', frontend_class)
for library_updater in self.get_library_updaters():
registry.add('local:library', library_updater)
self.register_gstreamer_elements()
def get_frontend_classes(self): def get_frontend_classes(self):
"""List of frontend actor classes """List of frontend actor classes
@ -112,6 +125,29 @@ class Extension(object):
pass pass
class _Registry(collections.Mapping):
def __init__(self):
self._registry = collections.defaultdict(list)
def add(self, name, cls):
self._registry[name].append(cls)
def __getitem__(self, name):
return self._registry[name]
def __iter__(self):
return iter(self._registry)
def __len__(self):
return len(self._registry)
# TODO: document the registry
# TODO: consider if we should avoid having this as a global and pass an
# instance from __main__ around instead?
registry = _Registry()
def load_extensions(): def load_extensions():
"""Find all installed extensions. """Find all installed extensions.
@ -166,15 +202,3 @@ def validate_extension(extension):
return False return False
return True return True
def register_gstreamer_elements(enabled_extensions):
"""Registers custom GStreamer elements from extensions.
:param enabled_extensions: list of enabled extensions
"""
for extension in enabled_extensions:
logger.debug(
'Registering GStreamer elements for: %s', extension.ext_name)
extension.register_gstreamer_elements()