Skip to content

Commit

Permalink
Merge branch 'dev' into rpi_platform
Browse files Browse the repository at this point in the history
  • Loading branch information
jabdoa2 committed Jul 1, 2017
2 parents 141d998 + bdcbcce commit f2a3994
Show file tree
Hide file tree
Showing 52 changed files with 2,245 additions and 80 deletions.
2 changes: 2 additions & 0 deletions AUTHORS
Expand Up @@ -13,3 +13,5 @@ their spare time, unpaid, for the love of pinball!
* Mark Incitti <markinc@gmail.com>
* Brian Dominy <brian@oddchange.com>
* Philip Dixon <epotech@ntlworld.com>

Want to contribute to MPF? Get started here: http://docs.missionpinball.org/en/latest/about/contributing_to_mpf.html
4 changes: 2 additions & 2 deletions docs/testing/running_mpf_tests.rst
Expand Up @@ -7,7 +7,7 @@ following command and then press <enter>:

::

python3 -m unittest discover mpf
python3 -m unittest discover mpf/tests

When you do this, you should see a bunch of dots on the screen (one for each
test that's run), and then when it's done, you should see a message showing
Expand Down Expand Up @@ -44,7 +44,7 @@ this):

::

python3 -m unittest discover mpfmc
python3 -m unittest discover mpfmc/tests

(Note that ``mpfmc`` does not have a dash in it, like it did when you installed
it via *pip*.)
Expand Down
2 changes: 1 addition & 1 deletion mpf/_version.py
Expand Up @@ -10,7 +10,7 @@
"""

__version__ = '0.50.0-dev.6'
__version__ = '0.50.0-dev.8'
'''The full version of MPF.'''

__short_version__ = '0.50'
Expand Down
34 changes: 20 additions & 14 deletions mpf/commands/game.py
Expand Up @@ -138,6 +138,9 @@ def __init__(self, mpf_path, machine_path, args):
except OSError:
pass

logger = logging.getLogger()
logger.setLevel(args.loglevel)

# define a Handler which writes INFO messages or higher to the sys.stderr
console_log = logging.StreamHandler()
console_log.setLevel(args.consoleloglevel)
Expand All @@ -151,21 +154,23 @@ def __init__(self, mpf_path, machine_path, args):
console_queue_listener = logging.handlers.QueueListener(console_log_queue, console_log)
console_queue_listener.start()

# initialise file log
file_log = logging.FileHandler(full_logfile_path)
file_log.setFormatter(logging.Formatter('%(asctime)s : %(name)s : %(message)s'))
# add logger
logger.addHandler(console_queue_handler)

file_queue_listener = None
if args.logfile:
# initialise file log
file_log = logging.FileHandler(full_logfile_path)
file_log.setFormatter(logging.Formatter('%(asctime)s : %(name)s : %(message)s'))

# initialise async handler for file log
file_log_queue = Queue()
file_queue_handler = QueueHandler(file_log_queue)
file_queue_listener = logging.handlers.QueueListener(file_log_queue, file_log)
file_queue_listener.start()
# initialise async handler for file log
file_log_queue = Queue()
file_queue_handler = QueueHandler(file_log_queue)
file_queue_listener = logging.handlers.QueueListener(file_log_queue, file_log)
file_queue_listener.start()

# add loggers
logger = logging.getLogger()
logger.addHandler(console_queue_handler)
logger.addHandler(file_queue_handler)
logger.setLevel(args.loglevel)
# add logger
logger.addHandler(file_queue_handler)

if args.syslog_address:
try:
Expand All @@ -187,7 +192,8 @@ def __init__(self, mpf_path, machine_path, args):
logging.shutdown()
# stop threads
console_queue_listener.stop()
file_queue_listener.stop()
if file_queue_listener:
file_queue_listener.stop()

if args.pause:
input('Press ENTER to continue...')
Expand Down
4 changes: 2 additions & 2 deletions mpf/config_players/coil_player.py
Expand Up @@ -10,16 +10,16 @@ class CoilPlayer(DeviceConfigPlayer):

config_file_section = 'coil_player'
show_section = 'coils'
machine_collection_name = 'coils'

def play(self, settings, context, priority=0, **kwargs):
"""Enable, Pulse or disable coils."""
del kwargs
instance_dict = self._get_instance_dict(context)

for coil_name, s in settings.items():
for coil, s in settings.items():
s = deepcopy(s)
action = s.pop('action')
coil = self.machine.coils[coil_name]
coil_action = getattr(coil, action)

if action in ("disable", "off") and coil.name in instance_dict:
Expand Down
6 changes: 5 additions & 1 deletion mpf/config_players/device_config_player.py
Expand Up @@ -16,7 +16,7 @@ def validate_config_entry(self, settings, name):
# that
if not isinstance(settings, dict):
if isinstance(settings, (str, int, float)):
settings = {settings: dict()}
settings = self.get_string_config(settings)
else:
raise AssertionError("Invalid settings for player {}:{}".format(self.show_section, name))

Expand All @@ -27,6 +27,10 @@ def validate_config_entry(self, settings, name):

return validated_config

def get_string_config(self, string):
"""Parse string config."""
return {string: dict()}

def _validate_config_item(self, device, device_settings):
"""Validate show config."""
# override if you need a different show processor from config file
Expand Down
41 changes: 41 additions & 0 deletions mpf/config_players/hardware_sound_player.py
@@ -0,0 +1,41 @@
from typing import TYPE_CHECKING

from mpf.config_players.device_config_player import DeviceConfigPlayer

if TYPE_CHECKING:
from mpf.devices.hardware_sound_system import HardwareSoundSystem


class HardwareSoundPlayer(DeviceConfigPlayer):

"""Generates texts """

config_file_section = 'hardware_sound_player'
show_section = 'hardware_sound_players'

def play(self, settings, context, calling_context, priority=0, **kwargs):
"""Show text on display"""
del kwargs
del context
del calling_context

for sound, s in settings.items():
sound_system = s['sound_system'] # type: HardwareSoundSystem

if s['action'] == "stop":
sound_system.stop_all_sounds()
elif s['action'] == "play":
sound_system.play(sound)
else:
raise AssertionError("Invalid action {}".format(s['action']))

def get_express_config(self, value):
"""Parse express config."""
return dict(action=value)

def get_string_config(self, string):
"""Parse string config."""
if string == "stop":
return {string: dict(action="stop")}
else:
return super().get_string_config(string)
72 changes: 72 additions & 0 deletions mpf/config_players/segment_display_player.py
@@ -0,0 +1,72 @@
from mpf.core.delays import DelayManager

from mpf.config_players.device_config_player import DeviceConfigPlayer


class SegmentDisplayPlayer(DeviceConfigPlayer):

"""Generates texts """

config_file_section = 'segment_display_player'
show_section = 'segment_displays'
machine_collection_name = 'segment_displays'

def __init__(self, machine):
"""Initialise SegmentDisplayPlayer."""
super().__init__(machine)
self.delay = DelayManager(self.machine.delayRegistry)

def play(self, settings, context, calling_context, priority=0, **kwargs):
"""Show text on display"""
del kwargs
instance_dict = self._get_instance_dict(context)
full_context = self._get_full_context(context)

for display, s in settings.items():
action = s['action']
if not display in instance_dict:
instance_dict[display] = {}

key = full_context + "." + display.name

if s['key']:
key += s['key']

if action == "add":
# in case it is already there
self._remove(instance_dict=instance_dict, key=key, display=display)
# add text
display.add_text(s['text'], priority + s['priority'], key)

if s['expire']:
instance_dict[display][key] = self.delay.add(s['expire'], self._remove,
instance_dict=instance_dict,
key=key,
display=display)
else:
instance_dict[display][key] = True
elif action == "remove":
self._remove(instance_dict=instance_dict, key=key, display=display)
else:
raise AssertionError("Invalid action {}".format(action))

def _remove(self, instance_dict, key, display):
if key in instance_dict[display]:
display.remove_text_by_key(key)
if instance_dict[display][key] is not True:
self.delay.remove(instance_dict[display][key])
del instance_dict[display][key]

def clear_context(self, context):
"""Remove all texts."""
full_context = self._get_full_context(context)
instance_dict = self._get_instance_dict(context)
for display, keys in instance_dict.items():
for key in dict(keys).keys():
self._remove(instance_dict=instance_dict, key=key, display=display)

self._reset_instance_dict(context)

def get_express_config(self, value):
"""Parse express config."""
return dict(action="add", text=value)
5 changes: 3 additions & 2 deletions mpf/core/config_player.py
Expand Up @@ -2,6 +2,7 @@
"""Base class used for things that "play" from the config files, such as WidgetPlayer, SlidePlayer, etc."""
import abc

from mpf.core.machine import MachineController
from mpf.core.mode import Mode
from mpf.exceptions.ConfigFileError import ConfigFileError

Expand All @@ -18,7 +19,7 @@ def __init__(self, machine):
"""Initialise config player."""
self.device_collection = None

self.machine = machine
self.machine = machine # type: MachineController

# MPF only
if hasattr(self.machine, "show_controller"):
Expand All @@ -33,7 +34,7 @@ def __init__(self, machine):
self._show_keys = {}

def _add_handlers(self):
self.machine.events.add_handler('init_phase_1', self._initialize_in_mode, priority=2)
self.machine.events.add_handler('init_phase_1', self._initialize_in_mode, priority=20)
self.machine.events.add_handler('init_phase_1', self._initialise_system_wide, priority=1)

def __repr__(self):
Expand Down
46 changes: 46 additions & 0 deletions mpf/core/config_spec.py
Expand Up @@ -211,6 +211,7 @@
skip_if_zero: single|bool|True
coils:
__valid_in__: machine
allow_enable: single|bool|False
number: single|str|
default_recycle: single|bool|False
default_pulse_ms: single|ms|None
Expand Down Expand Up @@ -511,6 +512,7 @@
__valid_in__: machine
platform: list|str|virtual
coils: list|str|default
segment_displays: list|str|default
switches: list|str|default
lights: list|str|default
dmd: list|str|default
Expand All @@ -519,6 +521,15 @@
servo_controllers: list|str|
accelerometers: list|str|
i2c: list|str|
hardware_sound_system: list|str|default
hardware_sound_systems:
__valid_in__: machine
platform: single|str|None
hardware_sound_player:
__valid_in__: machine, mode, show
action: single|enum(play,stop)|play
sound: single|int|None
sound_system: single|machine(hardware_sound_systems)|default
high_score:
__valid_in__: mode
award_slide_display_time: single|ms|4s
Expand Down Expand Up @@ -603,6 +614,16 @@
color: single|str|white
fade: single|ms|None
__allow_others__:
lisy:
__valid_in__: machine
port: single|str|None
baud: single|int|None
poll_hz: single|int|1000
console_log: single|enum(none,basic,full)|none
file_log: single|enum(none,basic,full)|basic
connection: single|enum(network,serial)|network
network_port: single|int|None
network_host: single|str|None
logic_blocks_common:
enable_events: dict|str:ms|None
disable_events: dict|str:ms|None
Expand Down Expand Up @@ -722,6 +743,10 @@
locked_ball_counting_strategy: single|enum(virtual_only,min_virtual_physical,physical_only,no_virtual)|virtual_only
reset_all_counts_events: dict|str:ms|None
reset_count_for_current_player_events: dict|str:ms|None
mypinballs:
__valid_in__: machine
port: single|str|
baud: single|int|115200
named_colors:
__valid_in__: machine
opp:
Expand All @@ -732,6 +757,7 @@
chains: dict|str:str|None
console_log: single|enum(none,basic,full)|none
file_log: single|enum(none,basic,full)|basic
poll_hz: single|int|100
open_pixel_control:
__valid_in__: machine
connection_required: single|bool|False
Expand Down Expand Up @@ -858,6 +884,17 @@
float: single|template_float|None
scriptlets:
__valid_in__: machine # todo add to validator
segment_displays:
__valid_in__: machine
number: single|str|
platform: single|str|None
segment_display_player:
__valid_in__: machine, mode, show
priority: single|int|0
text: single|str|None
action: single|enum(add,remove)|add
key: single|str|None
expire: single|ms|None
servo_controller:
__valid_in__: machine # todo add to validator
servo_controllers:
Expand Down Expand Up @@ -1088,6 +1125,15 @@
__valid_in__: machine
start_event: single|str|machine_reset_phase_3
steps: ignore
sequence_shots:
__valid_in__: machine, mode
switch_sequence: list|machine(switches)|None
event_sequence: list|str|None
cancel_switches: list|machine(switches)|None
cancel_events: dict|str:ms|None
delay_switch_list: dict|machine(switches):ms|None
delay_event_list: dict|str:ms|None
sequence_timeout: single|ms|0
switches:
__valid_in__: machine
number: single|str|
Expand Down

0 comments on commit f2a3994

Please sign in to comment.