def __init__(self): """ Initialise the DDRPi Controller app. """ super(DDRPi, self).__init__() logging.info("DDRPi starting...") # Load the application config self.config = self.__load_config__() # Create the dance floor surface self.dance_surface = DanceSurface(self.config) # Set up plugin registry self.__registry__ = PluginRegistry() self.__register_plugins(self.config["system"]["plugin_dir"]) # Initialise pygame pygame.init() # Inititalise Controllers self.__init_controllers__() # Enter debug mode if self.config["system"]["debug_logging"]: logger = logging.getLogger() logger.setLevel(logging.DEBUG)
class DDRPi(object): """ The Main class - should load plugins and manage access to the DanceSurface object """ def __init__(self): """ Initialise the DDRPi Controller app. """ super(DDRPi, self).__init__() logging.info("DDRPi starting...") # Load the application config self.config = self.__load_config__() # Create the dance floor surface self.dance_surface = DanceSurface(self.config) # Set up plugin registry self.__registry__ = PluginRegistry() self.__register_plugins(self.config["system"]["plugin_dir"]) # Initialise pygame pygame.init() # Inititalise Controllers self.__init_controllers__() # Enter debug mode if self.config["system"]["debug_logging"]: logger = logging.getLogger() logger.setLevel(logging.DEBUG) def __load_config__(self): """ Load the config file into a dictionary. Returns: The dictionary resulting from loading the YAML config file. """ f = open('config.yaml') data = yaml.load(f) f.close() return data def __register_plugins(self, plugin_folder): """ Find the loadable plugins in the given plugin folder. The located plugins are then loaded into the plugin registry. """ logging.info("Searching for plugins in %s" % plugin_folder) for root, dirs, files in os.walk(plugin_folder): for fname in files: if fname.endswith(".py") and not fname.startswith("__"): fpath = os.path.join(root, fname) mname = fpath.rsplit('.', 1)[0].replace('/', '.').replace('\\', '.') importlib.import_module(mname) for plugin in DDRPiPlugin.__subclasses__(): name = plugin.__name__ logging.debug("DDRPi: plugin name: %s" % name) pinst = plugin() pinst.configure(self.config, self.dance_surface) self.__registry__.register(name, pinst) def __init_controllers__(self): """ Initialise the attached joypads """ num_c = pygame.joystick.get_count() self.__controllers__ = {} for c in range(0,num_c): self.__controllers__[c] = pygame.joystick.Joystick(c) self.__controllers__[c].init() logging.debug("DDRPi: Initialised %s controllers" % num_c) def changed_layout(self): """ Called on layout change to redefine the DanceFloor size/shape ** Not currently used - we don't allow layout changes ** """ # Get the new size and shape (x,y) = self.layout.calculate_floor_size() # Create a new dance surface self.dance_surface = DanceSurface(x, y) # TODO: Reconfigure the running plugin (or reload the running plugin) # Need to create a layout changed event def start(self): """ Enter main event loop and start drawing to the floor """ # TODO: Pick a display plugin from the registry # (i.e. one of the games or visualisations) available_plugins = self.__registry__.get_names() if len(available_plugins) > 0: # Configure a default plugin # If there is a plugin specified on the command line if (self.get_requested_initial_plugin() == None): logging.info("DDRPi: Starting in menu mode") self.plugin_index = 0 self.temporary_plugin_index = 0 self.mode = "MENU" self.active_plugin = self.__registry__.get_plugin(available_plugins[0]) self.active_plugin.display_preview() else : # Start the active plugin self.active_plugin.start() self.temporary_plugin_index = 0 self.mode = "RUNNING" self._main_loop() else: logging.error("DDRPi: No display plugins found") sys.exit(1) def get_requested_initial_plugin(self): # Skip the name of this file (in 0), and iterate over the rest available_plugins = self.__registry__.get_names() for arg in sys.argv[1:]: if arg in available_plugins: # Find the plugin this_plugin_index = 0 for plugin_name in available_plugins: if (plugin_name == arg): self.active_plugin = self.__registry__.get_plugin(plugin_name) self.plugin_index = this_plugin_index logging.info("Found command line requested plugin %s at index %d" % (arg, this_plugin_index)) return plugin_name if (len(sys.argv[1:]) > 0): logging.error("Unable to load any requested plugins") return None def _main_loop(self): """ Main event loop - each period handle events generated by the user and send those events to the active display plugin to make the appropriate updates on the floor """ try: while(True): for e in pygame.event.get(): # handle special events (e.g. plugin switch) bypass = self._handle(e) if bypass: continue # TODO: decide whether to ONLY pass gamepad events to plugins... # active plugin handle e #logging.debug("Active plugin handling event: %s" % e) self.active_plugin.handle(e) # Update the display # We're just going as fast as the serial port will let us atm if self.mode == "RUNNING": self.active_plugin.update_surface() except IOError as io_e: logging.error("The floor simulator was closed") exit(1) def _preview_plugin(self, plugin_name): logging.debug("DDRPi: Switching to preview plugin %s" % plugin_name) preview_plugin = self.__registry__.get_plugin(plugin_name) preview_plugin.display_preview() def _handle(self, e): """ Handle events for controlling the main application returns: Boolean - does this event bypass the running/paused plugin """ if pygame.event.event_name(e.type) == "JoyButtonDown": if self.mode == "RUNNING": # 2 = B, 8 = SELECT, cancel, go back to running if e.button == 8: logging.debug("DDRPi: Entering menu") self.mode = "MENU" self.active_plugin.pause() return True else: return False elif self.mode == "MENU": # 2 = B, 8 = SELECT, cancel, go back to running if (e.button == 2 or e.button == 8): logging.debug("DDRPi: Exiting menu") self.mode = "RUNNING" self.active_plugin.resume() return True # 1 = A, 9 = START, accept, start this plugin elif (e.button == 1 or e.button == 9): available_plugins = self.__registry__.get_names() logging.debug("DDRPi: Selected plugin") self.mode = "RUNNING" self.active_plugin.stop() self.active_plugin = self.__registry__.get_plugin(available_plugins[self.temporary_plugin_index]) self.active_plugin.configure(self.config, self.dance_surface) self.active_plugin.start() self.plugin_index = self.temporary_plugin_index return True # 4 = LB, scroll left elif (e.button == 4): available_plugins = self.__registry__.get_names() self.temporary_plugin_index = (self.temporary_plugin_index + 1) % len(available_plugins) self._preview_plugin(available_plugins[self.temporary_plugin_index]) logging.debug("DDRPi: Switching to preview plugin %d/%d" % (self.temporary_plugin_index+1, len(available_plugins))) return True # 5 = RB, scroll right elif (e.button == 5): available_plugins = self.__registry__.get_names() self.temporary_plugin_index = (self.temporary_plugin_index - 1) % len(available_plugins) self._preview_plugin(available_plugins[self.temporary_plugin_index]) logging.debug("DDRPi: Switching to preview plugin %d/%d" % (self.temporary_plugin_index+1, len(available_plugins))) return True # 8 = SELECT, go into menu mode, pausing the current plugin elif (e.button == 8): available_plugins = self.__registry__.get_names() logging.debug("DDRPi: Entering menu, %d plugins available" % len(available_plugins)) self.mode = "MENU" if (self.active_plugin != None): # We'll need this to pause the game self.active_plugin.pause() self.active_plugin.display_preview(self.config, self.dance_surface) self.temporary_plugin_index = self.plugin_index else: return False else: return False return False