示例#1
0
    def __init__(self, machine):
        self.machine = machine
        self.registered_switches = CaseInsensitiveDict()
        # Dictionary of switches and states that have been registered for
        # callbacks.

        self.active_timed_switches = defaultdict(list)
        # Dictionary of switches that are currently in a state counting ms
        # waiting to notify their handlers. In other words, this is the dict that
        # tracks current switches for things like "do foo() if switch bar is
        # active for 100ms."

        self.switches = CaseInsensitiveDict()
        # Dictionary which holds the master list of switches as well as their
        # current states. State here does factor in whether a switch is NO or NC,
        # so 1 = active and 0 = inactive.

        # register for events
        self.machine.events.add_handler('timer_tick', self._tick, 1000)
        self.machine.events.add_handler('init_phase_2',
                                        self._initialize_switches, 1000)
        # priority 1000 so this fires first

        self.machine.events.add_handler('machine_reset_phase_3',
                                        self.log_active_switches)
示例#2
0
    def create_machine_var(self,
                           name,
                           value=0,
                           persist=False,
                           expire_secs=None,
                           silent=False):
        """Creates a new machine variable:

        Args:
            name: String name of the variable.
            value: The value of the variable. This can be any Type.
            persist: Boolean as to whether this variable should be saved to
                disk so it's available the next time MPF boots.
            expire_secs: Optional number of seconds you'd like this variable
                to persist on disk for. When MPF boots, if the expiration time
                of the variable is in the past, it will be loaded with a value
                of 0. For example, this lets you write the number of credits on
                the machine to disk to persist even during power off, but you
                could set it so that those only stay persisted for an hour.

        """
        var = CaseInsensitiveDict()

        var['value'] = value
        var['persist'] = persist
        var['expire_secs'] = expire_secs

        self.machine_vars[name] = var

        if not silent:
            self.set_machine_var(name, value, force_events=True)
示例#3
0
    def set_machine_var(self, name, value, force_events=False):
        """Sets the value of a machine variable.

        Args:
            name: String name of the variable you're setting the value for.
            value: The value you're setting. This can be any Type.
            force_events: Boolean which will force the event posting, the
                machine monitor callback, and writing the variable to disk (if
                it's set to persist). By default these things only happen if
                the new value is different from the old value.

        """
        if name not in self.machine_vars:
            self.log.warning(
                "Received request to set machine_var '%s', but "
                "that is not a valid machine_var.", name)
            return

        prev_value = self.machine_vars[name]['value']
        self.machine_vars[name]['value'] = value

        try:
            change = value - prev_value
        except TypeError:
            if prev_value != value:
                change = True
            else:
                change = False

        if change or force_events:

            if self.machine_vars[name]['persist']:
                disk_var = CaseInsensitiveDict()
                disk_var['value'] = value

                if self.machine_vars[name]['expire_secs']:
                    disk_var['expire'] = (
                        time.time() + self.machine_vars[name]['expire_secs'])

                self.machine_var_data_manager.save_key(name, disk_var)

            self.log.debug(
                "Setting machine_var '%s' to: %s, (prior: %s, "
                "change: %s)", name, value, prev_value, change)
            self.events.post('machine_var_' + name,
                             value=value,
                             prev_value=prev_value,
                             change=change)

            if self.machine_var_monitor:
                for callback in self.monitors['machine_vars']:
                    callback(name=name,
                             value=value,
                             prev_value=prev_value,
                             change=change)
示例#4
0
    def _get_merged_settings(self, section_name):
        # Returns a dict_merged dict of a config section from the machine-wide
        # config with the mode-specific config merged in.

        if section_name in self.machine.config:
            return_dict = copy.deepcopy(self.machine.config[section_name])
        else:
            return_dict = CaseInsensitiveDict()

        if section_name in self.config:
            return_dict = Util.dict_merge(return_dict,
                                          self.config[section_name],
                                          combine_lists=False)

        return return_dict
示例#5
0
    def __init__(self, machine, config_section, path_string, asset_class,
                 asset_attribute, file_extensions):

        self.log = logging.getLogger(config_section + ' Asset Manager')
        self.log.debug("Initializing...")

        self.machine = machine
        self.loader_thread.exception_queue = self.machine.crash_queue
        self.max_memory = None
        self.registered_assets = set()
        self.path_string = path_string
        self.config_section = config_section
        self.asset_class = asset_class
        self.file_extensions = file_extensions

        self.machine.asset_managers[config_section] = self

        if not hasattr(self.machine, asset_attribute):
            setattr(self.machine, asset_attribute, CaseInsensitiveDict())

        self.asset_list = getattr(self.machine, asset_attribute)

        self.machine.mode_controller.register_load_method(self.load_assets,
                                            self.config_section,
                                            load_key='preload',
                                            priority=asset_class.load_priority)

        self.machine.mode_controller.register_start_method(self.load_assets,
                                            self.config_section,
                                            load_key='mode_start',
                                            priority=asset_class.load_priority)

        # register & load systemwide assets
        self.machine.events.add_handler('init_phase_4',
                                        self.register_and_load_machine_assets,
                                        priority=self.asset_class.load_priority)

        self.defaults = self.setup_defaults(self.machine.config)
示例#6
0
    def __init__(self, options):
        self.options = options
        self.log = logging.getLogger("Machine")
        self.log.info("Mission Pinball Framework v%s", version.__version__)
        self.log.debug("Command line arguments: {}".format(self.options))
        self.verify_system_info()

        self.loop_start_time = 0
        self.tick_num = 0
        self.done = False
        self.machine_path = None  # Path to this machine's folder root
        self.monitors = dict()
        self.plugins = list()
        self.scriptlets = list()
        self.modes = list()
        self.asset_managers = dict()
        self.game = None
        self.active_debugger = dict()
        self.machine_vars = CaseInsensitiveDict()
        self.machine_var_monitor = False
        self.machine_var_data_manager = None

        self.flag_bcp_reset_complete = False
        self.asset_loader_complete = False

        self.delay = DelayManager()

        self.crash_queue = Queue.Queue()
        Task.create(self._check_crash_queue)

        FileManager.init()
        self.config = dict()
        self._load_mpf_config()
        self._set_machine_path()
        self._load_machine_config()

        self.configure_debugger()

        self.hardware_platforms = dict()
        self.default_platform = None

        if not self.options['force_platform']:
            for section, platform in self.config['hardware'].iteritems():
                if platform.lower() != 'default' and section != 'driverboards':
                    self.add_platform(platform)
            self.set_default_platform(self.config['hardware']['platform'])

        else:
            self.add_platform(self.options['force_platform'])
            self.set_default_platform(self.options['force_platform'])

        # Do this here so there's a credit_string var even if they're not using
        # the credits mode
        try:
            credit_string = self.config['credits']['free_play_string']
        except KeyError:
            credit_string = 'FREE PLAY'

        self.create_machine_var('credits_string', credit_string, silent=True)

        self._load_system_modules()

        # This is called so hw platforms have a change to register for events,
        # and/or anything else they need to do with system modules since
        # they're not set up yet when the hw platforms are constructed.
        for platform in self.hardware_platforms.values():
            platform.initialize()

        self.validate_machine_config_section('machine')
        self.validate_machine_config_section('timing')
        self.validate_machine_config_section('hardware')
        self.validate_machine_config_section('game')

        self._register_system_events()
        self._load_machine_vars()
        self.events.post("init_phase_1")
        self.events._process_event_queue()
        self.events.post("init_phase_2")
        self.events._process_event_queue()
        self._load_plugins()
        self.events.post("init_phase_3")
        self.events._process_event_queue()
        self._load_scriptlets()
        self.events.post("init_phase_4")
        self.events._process_event_queue()
        self.events.post("init_phase_5")
        self.events._process_event_queue()

        self.reset()
示例#7
0
    def __init__(self, options):
        self.options = options

        self.log = logging.getLogger("MediaController")
        self.log.info("Media Controller Version %s", version.__version__)
        self.log.info("Backbox Control Protocol Version %s",
                      version.__bcp_version__)
        self.log.info("Config File Version %s",
                      version.__config_version__)

        python_version = sys.version_info
        self.log.info("Python version: %s.%s.%s", python_version[0],
                      python_version[1], python_version[2])
        self.log.info("Platform: %s", sys.platform)
        self.log.info("Python executable location: %s", sys.executable)
        self.log.info("32-bit Python? %s", sys.maxsize < 2**32)

        self.config = dict()
        self.done = False  # todo
        self.machine_path = None
        self.asset_managers = dict()
        self.num_assets_to_load = 0
        self.window = None
        self.window_manager = None
        self.pygame = False
        self.pygame_requested = False
        self.registered_pygame_handlers = dict()
        self.pygame_allowed_events = list()
        self.socket_thread = None
        self.receive_queue = Queue.Queue()
        self.sending_queue = Queue.Queue()
        self.crash_queue = Queue.Queue()
        self.game_modes = CaseInsensitiveDict()
        self.player_list = list()
        self.player = None
        self.HZ = 0
        self.next_tick_time = 0
        self.secs_per_tick = 0

        Task.Create(self._check_crash_queue)

        self.bcp_commands = {'hello': self.bcp_hello,
                             'goodbye': self.bcp_goodbye,
                             'reset': self.reset,
                             'mode_start': self.bcp_mode_start,
                             'mode_stop': self.bcp_mode_stop,
                             'error': self.bcp_error,
                             'ball_start': self.bcp_ball_start,
                             'ball_end': self.bcp_ball_end,
                             'game_start': self.bcp_game_start,
                             'game_end': self.bcp_game_end,
                             'player_added': self.bcp_player_add,
                             'player_variable': self.bcp_player_variable,
                             'player_score': self.bcp_player_score,
                             'player_turn_start': self.bcp_player_turn_start,
                             'attract_start': self.bcp_attract_start,
                             'attract_stop': self.bcp_attract_stop,
                             'trigger': self.bcp_trigger,
                             'switch': self.bcp_switch,
                             'get': self.bcp_get,
                             'set': self.bcp_set,
                             'config': self.bcp_config,
                             'timer': self.bcp_timer
                            }

        # load the MPF config & machine defaults
        self.config = (
            Config.load_config_yaml(config=self.config,
                                    yaml_file=self.options['mcconfigfile']))

        # Find the machine_files location. If it starts with a forward or
        # backward slash, then we assume it's from the mpf root. Otherwise we
        # assume it's from the subfolder location specified in the
        # mpfconfigfile location

        if (options['machinepath'].startswith('/') or
                options['machinepath'].startswith('\\')):
            machine_path = options['machinepath']
        else:
            machine_path = os.path.join(self.config['mediacontroller']['paths']
                                        ['machine_files'],
                                        options['machinepath'])

        self.machine_path = os.path.abspath(machine_path)

        # Add the machine folder to our path so we can import modules from it
        sys.path.append(self.machine_path)

        self.log.info("Machine folder: %s", machine_path)

        # Now find the config file location. Same as machine_file with the
        # slash uses to specify an absolute path

        if (options['configfile'].startswith('/') or
                options['configfile'].startswith('\\')):
            config_file = options['configfile']
        else:

            if not options['configfile'].endswith('.yaml'):
                options['configfile'] += '.yaml'

            config_file = os.path.join(self.machine_path,
                                       self.config['mediacontroller']['paths']
                                       ['config'],
                                       options['configfile'])

        self.log.info("Base machine config file: %s", config_file)

        # Load the machine-specific config
        self.config = Config.load_config_yaml(config=self.config,
                                              yaml_file=config_file)

        mediacontroller_config_spec = '''
                        exit_on_disconnect: boolean|True
                        port: int|5050
                        '''

        self.config['mediacontroller'] = (
            Config.process_config(mediacontroller_config_spec,
                                  self.config['mediacontroller']))

        self.events = EventManager(self)
        self.timing = Timing(self)

        # Load the media controller modules
        self.config['mediacontroller']['modules'] = (
            self.config['mediacontroller']['modules'].split(' '))
        for module in self.config['mediacontroller']['modules']:
            self.log.info("Loading module: %s", module)
            module_parts = module.split('.')
            exec('self.' + module_parts[0] + '=' + module + '(self)')

            # todo there's probably a more pythonic way to do this, and I know
            # exec() is supposedly unsafe, but meh, if you have access to put
            # malicious files in the system folder then you have access to this
            # code too.

        self.start_socket_thread()

        self.events.post("init_phase_1")
        self.events.post("init_phase_2")
        self.events.post("init_phase_3")
        self.events.post("init_phase_4")
        self.events.post("init_phase_5")

        self.reset()
示例#8
0
    def __init__(self, options):
        self.options = options

        self.log = logging.getLogger("MediaController")
        self.log.debug("Command line arguments: {}".format(self.options))
        self.log.info("Media Controller Version %s", version.__version__)
        self.log.debug("Backbox Control Protocol Version %s",
                      version.__bcp_version__)
        self.log.debug("Config File Version %s",
                      version.__config_version__)

        python_version = sys.version_info

        if python_version[0] != 2 or python_version[1] != 7:
            self.log.error("Incorrect Python version. MPF requires Python 2.7."
                           "x. You have Python %s.%s.%s.", python_version[0],
                           python_version[1], python_version[2])
            sys.exit()

        self.log.debug("Python version: %s.%s.%s", python_version[0],
                      python_version[1], python_version[2])
        self.log.debug("Platform: %s", sys.platform)
        self.log.debug("Python executable location: %s", sys.executable)
        self.log.debug("32-bit Python? %s", sys.maxsize < 2**32)

        self.active_debugger = dict()

        self.config = dict()
        self.done = False  # todo
        self.machine_path = None
        self.asset_managers = dict()
        self.window = None
        self.window_manager = None
        self.pygame = False
        self.pygame_requested = False
        self.registered_pygame_handlers = dict()
        self.pygame_allowed_events = list()
        self.socket_thread = None
        self.receive_queue = Queue.Queue()
        self.sending_queue = Queue.Queue()
        self.crash_queue = Queue.Queue()
        self.modes = CaseInsensitiveDict()
        self.player_list = list()
        self.player = None
        self.HZ = 0
        self.next_tick_time = 0
        self.secs_per_tick = 0
        self.machine_vars = CaseInsensitiveDict()
        self.machine_var_monitor = False
        self.tick_num = 0
        self.delay = DelayManager()

        self._pc_assets_to_load = 0
        self._pc_total_assets = 0
        self.pc_connected = False

        Task.create(self._check_crash_queue)

        self.bcp_commands = {'ball_start': self.bcp_ball_start,
                             'ball_end': self.bcp_ball_end,
                             'config': self.bcp_config,
                             'error': self.bcp_error,
                             'get': self.bcp_get,
                             'goodbye': self.bcp_goodbye,
                             'hello': self.bcp_hello,
                             'machine_variable': self.bcp_machine_variable,
                             'mode_start': self.bcp_mode_start,
                             'mode_stop': self.bcp_mode_stop,
                             'player_added': self.bcp_player_add,
                             'player_score': self.bcp_player_score,
                             'player_turn_start': self.bcp_player_turn_start,
                             'player_variable': self.bcp_player_variable,
                             'reset': self.reset,
                             'set': self.bcp_set,
                             'shot': self.bcp_shot,
                             'switch': self.bcp_switch,
                             'timer': self.bcp_timer,
                             'trigger': self.bcp_trigger,
                            }

        FileManager.init()
        self.config = dict()
        self._load_mc_config()
        self._set_machine_path()
        self._load_machine_config()

        # Find the machine_files location. If it starts with a forward or
        # backward slash, then we assume it's from the mpf root. Otherwise we
        # assume it's from the subfolder location specified in the
        # mpfconfig file location

        if (options['machine_path'].startswith('/') or
                options['machine_path'].startswith('\\')):
            machine_path = options['machine_path']
        else:
            machine_path = os.path.join(self.config['media_controller']['paths']
                                        ['machine_files'],
                                        options['machine_path'])

        self.machine_path = os.path.abspath(machine_path)

        # Add the machine folder to our path so we can import modules from it
        sys.path.append(self.machine_path)

        self.log.info("Machine folder: %s", machine_path)

        mediacontroller_config_spec = '''
                        exit_on_disconnect: boolean|True
                        port: int|5050
                        '''

        self.config['media_controller'] = (
            Config.process_config(mediacontroller_config_spec,
                                  self.config['media_controller']))

        self.events = EventManager(self, setup_event_player=False)
        self.timing = Timing(self)

        # Load the media controller modules
        self.config['media_controller']['modules'] = (
            self.config['media_controller']['modules'].split(' '))
        self.log.info("Loading Modules...")
        for module in self.config['media_controller']['modules']:
            self.log.debug("Loading module: %s", module)
            module_parts = module.split('.')
            exec('self.' + module_parts[0] + '=' + module + '(self)')

            # todo there's probably a more pythonic way to do this, and I know
            # exec() is supposedly unsafe, but meh, if you have access to put
            # malicious files in the system folder then you have access to this
            # code too.

        self.start_socket_thread()

        self.events.post("init_phase_1")
        self.events._process_event_queue()
        self.events.post("init_phase_2")
        self.events._process_event_queue()
        self.events.post("init_phase_3")
        self.events._process_event_queue()
        self.events.post("init_phase_4")
        self.events._process_event_queue()
        self.events.post("init_phase_5")
        self.events._process_event_queue()

        self.reset()