Merge branch 'feature_plugins' into feature_plugins_shader_gadgets - MultiActions, some fixes and improved handling of action calls

This commit is contained in:
Tristan Rowley
2020-01-31 20:22:11 +00:00
7 changed files with 95 additions and 69 deletions

View File

@@ -1,6 +1,6 @@
# Auto-generated Actions list # Auto-generated Actions list
Fri 10 Jan 17:25:14 UTC 2020 Fri 31 Jan 20:19:55 UTC 2020
for branch=feature_plugins for branch=feature_plugins
@@ -173,13 +173,14 @@ for branch=feature_plugins
* set_shader_speed_layer_([0-2])_amount * set_shader_speed_layer_([0-2])_amount
### Plugin routes ### Plugin routes
* test_plugin (from MidiActionsTestPlugin) * (.*)&&(.*) (from MultiActionsPlugin)
* cycle_shaders (from MidiActionsTestPlugin) * test_plugin (from TestPlugin)
* run_automation (from MidiActionsTestPlugin) * cycle_shaders (from TestPlugin)
* stop_automation (from MidiActionsTestPlugin) * run_automation (from TestPlugin)
* toggle_pause_automation (from MidiActionsTestPlugin) * stop_automation (from TestPlugin)
* pause_automation (from MidiActionsTestPlugin) * toggle_pause_automation (from TestPlugin)
* toggle_loop_automation (from MidiActionsTestPlugin) * pause_automation (from TestPlugin)
* toggle_loop_automation (from TestPlugin)
---- ----

View File

@@ -1,6 +1,7 @@
import subprocess import subprocess
import tracemalloc import tracemalloc
import data_centre.length_setter as length_setter import data_centre.length_setter as length_setter
from inspect import signature
import sys import sys
import shlex import shlex
import os import os
@@ -907,19 +908,19 @@ class Actions(object):
@property @property
def parserlist(self): def parserlist(self):
return { return {
( r"play_shader_([0-9])_([0-9])", self.shaders.play_that_shader ), ( r"^play_shader_([0-9])_([0-9])$", self.shaders.play_that_shader ),
( r"toggle_shader_layer_([0-2])", self.toggle_shader_layer ), ( r"^toggle_shader_layer_([0-2])$", self.toggle_shader_layer ),
( r"start_shader_layer_([0-2])", self.shaders.start_shader ), ( r"^start_shader_layer_([0-2])$", self.shaders.start_shader ),
( r"stop_shader_layer_([0-2])", self.shaders.stop_shader ), ( r"^stop_shader_layer_([0-2])$", self.shaders.stop_shader ),
( r"set_the_shader_param_([0-3])_layer_([0-2])_continuous", self.shaders.set_param_layer_to_amount ), ( r"^set_the_shader_param_([0-3])_layer_([0-2])_continuous$", self.shaders.set_param_layer_to_amount ),
( r"modulate_param_([0-3])_to_amount_continuous", self.shaders.modulate_param_to_amount ), ( r"^modulate_param_([0-3])_to_amount_continuous$", self.shaders.modulate_param_to_amount ),
( r"set_param_([0-3])_layer_([0-2])_modulation_level_continuous", self.shaders.set_param_layer_offset_modulation_level ), ( r"^set_param_([0-3])_layer_([0-2])_modulation_level_continuous$", self.shaders.set_param_layer_modulation_level ),
( r"set_param_([0-3])_layer_offset_([0-2])_modulation_level_continuous", self.shaders.set_param_layer_offset_modulation_level ), ( r"^set_param_([0-3])_layer_offset_([0-2])_modulation_level_continuous$", self.shaders.set_param_layer_offset_modulation_level ),
( r"reset_selected_modulation", self.shaders.reset_selected_modulation ), ( r"^reset_selected_modulation$", self.shaders.reset_selected_modulation ),
( r"reset_modulation_([0-3])", self.shaders.reset_modulation ), ( r"^reset_modulation_([0-3])$", self.shaders.reset_modulation ),
( r"select_shader_modulation_slot_([0-3])", self.shaders.select_shader_modulation_slot ), ( r"^select_shader_modulation_slot_([0-3])$", self.shaders.select_shader_modulation_slot ),
( r"set_shader_speed_layer_offset_([0-2])_amount", self.shaders.set_speed_offset_to_amount ), ( r"^set_shader_speed_layer_offset_([0-2])_amount$", self.shaders.set_speed_offset_to_amount ),
( r"set_shader_speed_layer_([0-2])_amount", self.shaders.set_speed_layer_to_amount ), ( r"^set_shader_speed_layer_([0-2])_amount$", self.shaders.set_speed_layer_to_amount ),
} }
def detect_types(self, args): def detect_types(self, args):
@@ -942,34 +943,46 @@ class Actions(object):
return (found_method, args) return (found_method, args)
return None, None
def call_method_name(self, method_name, argument=None): def call_method_name(self, method_name, argument=None):
# if the target method doesnt exist, call the handler method = None
if not hasattr(self, method_name): arguments = None
self.call_parse_method_name(method_name, argument)
return
# first check if we have a native method to handle this for us
# todo: assess whether it would still be performant/desirable to be able to override core actions with plugins?
if hasattr(self, method_name):
method = getattr(self, method_name)
if argument is not None: if argument is not None:
getattr(self, method_name)(argument) arguments = [argument]
else:
getattr(self, method_name)()
# if not then check if its handled by one of our parserlist dynamic route methods
if method is None:
method, arguments = self.get_callback_for_method(method_name, argument)
def call_parse_method_name(self, method_name, argument): # if still nothing then test if a registered plugin handles this for us -- perhaps this ought to go first?
# first test if a registered plugin handles this for us if method is None:
from data_centre.plugin_collection import ActionsPlugin from data_centre.plugin_collection import ActionsPlugin
for plugin in self.data.plugins.get_plugins(ActionsPlugin): for plugin in self.data.plugins.get_plugins(ActionsPlugin):
if plugin.is_handled(method_name): if plugin.is_handled(method_name):
print ("Plugin %s is handling %s" % (plugin, method_name)) print ("Plugin %s is handling %s" % (plugin, method_name))
method, arguments = plugin.get_callback_for_method(method_name, argument) method, arguments = plugin.get_callback_for_method(method_name, argument)
method(*arguments) break # only deal with the first plugin
return
# if not then fall back to using internal method if method is None:
try:
method, arguments = self.get_callback_for_method(method_name, argument)
method(*arguments)
except:
print ("Failed to find a method for '%s'" % method_name) print ("Failed to find a method for '%s'" % method_name)
import traceback import traceback
traceback.print_exc() traceback.print_exc()
return
try:
#print ("for method_name %s, arguments is %s and len is %s" % (method_name, arguments, len(signature(method).parameters)))
if arguments is not None and len(signature(method).parameters)==len(arguments): # only pass arguments if count matches method sig
method(*arguments)
else:
method()
except:
print ("Exception calling action for '%s' with arguments ( %s ) " % ( method_name, arguments))
import traceback
traceback.print_exc()

View File

@@ -39,12 +39,12 @@ class SequencePlugin(Plugin):
@property @property
def parserlist(self): def parserlist(self):
return [ return [
( r"run_automation", self.run_automation ), ( r"^run_automation$", self.run_automation ),
( r"stop_automation", self.stop_automation ), ( r"^stop_automation$", self.stop_automation ),
( r"toggle_pause_automation", self.toggle_pause_automation ), ( r"^toggle_pause_automation$", self.toggle_pause_automation ),
( r"pause_automation", self.pause_automation ), ( r"^pause_automation$", self.pause_automation ),
( r"toggle_loop_automation", self.toggle_loop_automation ), ( r"^toggle_loop_automation$", self.toggle_loop_automation ),
( r"set_automation_speed", self.set_speed ), ( r"^set_automation_speed$", self.set_speed ),
] ]
def set_speed(self, speed): def set_speed(self, speed):
@@ -194,11 +194,6 @@ class ActionsPlugin(Plugin):
return (found_method, args) return (found_method, args)
#def call_parse_method_name(self, method_name, argument):
# method, arguments = self.actions.get_callback_for_method(method_name, argument)
# method(*arguments)
# adapted from https://github.com/gdiepen/python_plugin_example # adapted from https://github.com/gdiepen/python_plugin_example
class PluginCollection(object): class PluginCollection(object):
"""Upon creation, this class will read the plugins package for modules """Upon creation, this class will read the plugins package for modules

View File

@@ -12,11 +12,11 @@ grep " def " actions.py | grep -v "^#" | sed -e 's/ def //' | sed -e 's/self//'
echo echo
echo "## Dynamic routes" echo "## Dynamic routes"
grep '( r"' actions.py | sed -e 's/\(.*\)"\(.*\)"\(.*\)/ * \2/' grep '( r"' actions.py | sed -e 's/\(.*\)"\(.*\)"\(.*\)/ * \2/' | sed -e 's/\$//' | sed -e 's/\^//'
echo echo
echo "### Plugin routes" echo "### Plugin routes"
grep "( r\"" plugins/*.py | sed -e 's/plugins\/\(.*\)\.py:\(.*\)\( r\"\)\(.*\)\"\(.*\)/ * \4\t(from \1)/' | grep -v "open_serial" grep "( r\"" plugins/*.py | sed -e 's/plugins\/\(.*\)\.py:\(.*\)\( r\"\)\(.*\)\"\(.*\)/ * \4\t(from \1)/' | grep -v "open_serial" | sed -e 's/\$//' | sed -e 's/\^//'
echo echo
echo "----" echo "----"

View File

@@ -89,12 +89,10 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
def feedback_plugin_status(self): def feedback_plugin_status(self):
from data_centre.plugin_collection import SequencePlugin from data_centre.plugin_collection import SequencePlugin
from plugins.MidiActionsTestPlugin import MidiActionsTestPlugin
try: try:
from plugins.ShaderLoopRecordPlugin import ShaderLoopRecordPlugin from plugins.ShaderLoopRecordPlugin import ShaderLoopRecordPlugin
for plugin in self.pc.get_plugins(SequencePlugin): for plugin in self.pc.get_plugins(SequencePlugin):
if isinstance(plugin, ShaderLoopRecordPlugin): #MidiActionsTestPlugin): if isinstance(plugin, ShaderLoopRecordPlugin):
NOTE_PLAY_STATUS = 65 NOTE_PLAY_STATUS = 65
NOTE_RECORD_STATUS = 66 NOTE_RECORD_STATUS = 66
@@ -225,7 +223,7 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
#print("in update device status is %s" % self.status) #print("in update device status is %s" % self.status)
for i,c in self.status.items(): for i,c in self.status.items():
#'print("comparing\n%s to\n%s" % (c, self.last_state[i])) #'print("comparing\n%s to\n%s" % (c, self.last_state[i]))
if self.last_state is None or self.last_state[i]!=c: if self.last_state is None or (i not in self.last_state or self.last_state[i]!=c):
#print("got command: %s: %s" % (i,c)) #print("got command: %s: %s" % (i,c))
self.send_command(**c) self.send_command(**c)
self.last_state = deepcopy(self.status) self.last_state = deepcopy(self.status)

View File

@@ -0,0 +1,19 @@
import data_centre.plugin_collection
from data_centre.plugin_collection import ActionsPlugin
class MultiActionsPlugin(ActionsPlugin):
disabled = False
def __init__(self, plugin_collection):
super().__init__(plugin_collection)
@property
def parserlist(self):
return [
( r"(.*)&&(.*)", self.run_multi ),
]
def run_multi(self, action1, action2, value):
print("multi running %s and %s with value %s" % (action1, action2, value))
self.pc.actions.call_method_name(action1, value)
self.pc.actions.call_method_name(action2, value)

View File

@@ -10,13 +10,13 @@ class MidiActionsTestPlugin(ActionsPlugin,SequencePlugin):
@property @property
def parserlist(self): def parserlist(self):
return [ return [
( r"test_plugin", self.test_plugin ), ( r"^test_plugin$", self.test_plugin ),
( r"cycle_shaders", self.cycle_shaders ), ( r"^cycle_shaders$", self.cycle_shaders ),
( r"run_automation", self.run_automation ), ( r"^run_automation$", self.run_automation ),
( r"stop_automation", self.stop_automation ), ( r"^stop_automation$", self.stop_automation ),
( r"toggle_pause_automation", self.toggle_pause_automation ), ( r"^toggle_pause_automation$", self.toggle_pause_automation ),
( r"pause_automation", self.pause_automation ), ( r"^pause_automation$", self.pause_automation ),
( r"toggle_loop_automation", self.toggle_loop_automation ), ( r"^toggle_loop_automation$", self.toggle_loop_automation ),
] ]
def test_plugin(self): def test_plugin(self):
@@ -42,7 +42,7 @@ class MidiActionsTestPlugin(ActionsPlugin,SequencePlugin):
frequency = 50 frequency = 50
def run_sequence(self, position): def run_sequence(self, position):
self.pc.actions.call_method_name( self.pc.actions.call_method_name(
"set_the_shader_param_0_layer_0_continuous", position "set_the_shader_param_3_layer_0_continuous", position
) )
self.pc.actions.call_method_name( self.pc.actions.call_method_name(