Repository: missionpinball/mpf
Issue: Plugin config players require a standalone config section to work

Example machine config:

```
#config_version=4

shows:
  my_show:
    - time: 0
      slides:
        my_slide:
        - type: text
          text: hello

show_player:
  mode_attract_started: my_show

#slide_player:
#  fake: dummy
```

Above config will not work. Uncomment the slide_player section and it's fine.

Has to do with how BCP transports are registered by looking for config sections in the file. Should probably just enumerate the plugins and register all of them.

Changed files:
mpf/config_players/plugin_player.py, mpf/tests/test_PluginConfigPlayer.py, mpf/core/config_player.py, mpf/core/bcp/bcp_transport.py

diff --git a/mpf/config_players/plugin_player.py b/mpf/config_players/plugin_player.py
index fd3c2a7fa..e02ff4063 100644
--- a/mpf/config_players/plugin_player.py
+++ b/mpf/config_players/plugin_player.py
@@ -18,14 +18,6 @@ class PluginPlayer(DeviceConfigPlayer):
         """Return str representation."""
         return 'PluginPlayer.{}'.format(self.show_section)
 
-    def _initialise_system_wide(self, **kwargs):
-        super()._initialise_system_wide(**kwargs)
-
-        self.machine.bcp.interface.add_registered_trigger_event_for_client(
-            self.bcp_client, '{}_play'.format(self.show_section))
-        self.machine.bcp.interface.add_registered_trigger_event_for_client(
-            self.bcp_client, '{}_clear'.format(self.show_section))
-
     def get_express_config(self, value):
         """Not supported."""
         del value
@@ -63,6 +55,11 @@ class PluginPlayer(DeviceConfigPlayer):
             self.machine.bcp.interface.add_registered_trigger_event_for_client(self.bcp_client, event_name)
             event_list.append(event_name)
 
+        self.machine.bcp.interface.add_registered_trigger_event_for_client(
+            self.bcp_client, '{}_play'.format(self.show_section))
+        self.machine.bcp.interface.add_registered_trigger_event_for_client(
+            self.bcp_client, '{}_clear'.format(self.show_section))
+
         return event_list
 
     def unload_player_events(self, event_list):
diff --git a/mpf/core/bcp/bcp_transport.py b/mpf/core/bcp/bcp_transport.py
index 8c8026c44..d2c70bac0 100644
--- a/mpf/core/bcp/bcp_transport.py
+++ b/mpf/core/bcp/bcp_transport.py
@@ -21,6 +21,9 @@ class BcpTransportManager:
         if handler not in self._handlers:
             self._handlers[handler] = []
 
+        if transport is None:
+            raise AssertionError("Cannot register None transport.")
+
         self._handlers[handler].append(transport)
 
     def remove_transport_from_handle(self, handler, transport: BaseBcpClient):
diff --git a/mpf/core/config_player.py b/mpf/core/config_player.py
index bc8d080c7..a5410abb6 100644
--- a/mpf/core/config_player.py
+++ b/mpf/core/config_player.py
@@ -26,6 +26,7 @@ class ConfigPlayer(object, metaclass=abc.ABCMeta):
         self.instances = dict()
         self.instances['_global'] = dict()
         self.instances['_global'][self.config_file_section] = dict()
+        self._show_keys = {}
 
     def _add_handlers(self):
         self.machine.events.add_handler('init_phase_1', self._initialize_in_mode)
@@ -277,11 +278,19 @@ class ConfigPlayer(object, metaclass=abc.ABCMeta):
         if self.config_file_section not in self.instances[context]:
             self.instances[context][self.config_file_section] = dict()
 
+        # register bcp events
+        config = {'bcp_connection': settings['bcp_connection']} if 'bcp_connection' in settings else {}
+        event_keys = self.register_player_events(config, None, priority)
+        self._show_keys[context + self.config_file_section] = event_keys
+
         self.play(settings=settings, priority=priority, calling_context=calling_context,
                   show_tokens=show_tokens, context=context)
 
     def show_stop_callback(self, context):
         """Callback if show stops."""
+        self.unload_player_events(self._show_keys[context + self.config_file_section])
+        del self._show_keys[context + self.config_file_section]
+
         self.clear_context(context)
 
     @abc.abstractmethod
diff --git a/mpf/tests/test_PluginConfigPlayer.py b/mpf/tests/test_PluginConfigPlayer.py
index 6611cedc9..2efedd03f 100644
--- a/mpf/tests/test_PluginConfigPlayer.py
+++ b/mpf/tests/test_PluginConfigPlayer.py
@@ -258,12 +258,12 @@ class TestPluginConfigPlayer(MpfBcpTestCase):
         t3_player = self.machine.show_controller.show_players['test3s']
         t3_player.play = MagicMock()
 
-        self.assertIn('test3s_play', self.machine.bcp.transport._handlers)
-        self.assertIn('test3s_clear', self.machine.bcp.transport._handlers)
-
         self.machine.modes['mode1'].start()
         self.advance_time_and_run()
 
         self.post_event('start_show3')
 
+        self.assertIn('test3s_play', self.machine.bcp.transport._handlers)
+        self.assertIn('test3s_clear', self.machine.bcp.transport._handlers)
+
         self.assertTrue(t3_player.play.called)