mirror of
https://github.com/cyberboy666/r_e_c_u_r.git
synced 2025-12-11 19:00:04 +01:00
AutomationSourcePlugin type, to enable recording of WJ params to automation clips (featured in feature_plugin_shader_gadgets)
This commit is contained in:
@@ -221,6 +221,7 @@ class DisplayPlugin(Plugin):
|
|||||||
#display_text.insert(END, 'test from DisplayPlugin')
|
#display_text.insert(END, 'test from DisplayPlugin')
|
||||||
display.display_text.insert(END, '{} \n'.format(display.body_title))
|
display.display_text.insert(END, '{} \n'.format(display.body_title))
|
||||||
|
|
||||||
|
|
||||||
class ModulationReceiverPlugin(Plugin):
|
class ModulationReceiverPlugin(Plugin):
|
||||||
def __init__(self, plugin_collection):
|
def __init__(self, plugin_collection):
|
||||||
super().__init__(plugin_collection)
|
super().__init__(plugin_collection)
|
||||||
@@ -230,6 +231,24 @@ class ModulationReceiverPlugin(Plugin):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class AutomationSourcePlugin(Plugin):
|
||||||
|
@property
|
||||||
|
def frame_key(self):
|
||||||
|
return self.__class__.__name__
|
||||||
|
|
||||||
|
def __init__(self, plugin_collection):
|
||||||
|
super().__init__(plugin_collection)
|
||||||
|
|
||||||
|
def get_frame_data(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def recall_frame_data(self, data):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_frame_diff(self, last_frame, current_frame):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
@@ -303,7 +322,7 @@ class PluginCollection(object):
|
|||||||
for (_, c) in clsmembers:
|
for (_, c) in clsmembers:
|
||||||
# Only add classes that are a sub class of Plugin, but NOT Plugin itself
|
# Only add classes that are a sub class of Plugin, but NOT Plugin itself
|
||||||
# or one of the base classes
|
# or one of the base classes
|
||||||
ignore_list = [ Plugin, ActionsPlugin, SequencePlugin, MidiFeedbackPlugin, DisplayPlugin, ModulationReceiverPlugin ]
|
ignore_list = [ Plugin, ActionsPlugin, SequencePlugin, MidiFeedbackPlugin, DisplayPlugin, ModulationReceiverPlugin, AutomationSourcePlugin ]
|
||||||
if issubclass(c, Plugin) & (c not in ignore_list):
|
if issubclass(c, Plugin) & (c not in ignore_list):
|
||||||
print(' Found plugin class: %s.%s' % (c.__module__,c.__name__))
|
print(' Found plugin class: %s.%s' % (c.__module__,c.__name__))
|
||||||
self.plugins.append(c(self))
|
self.plugins.append(c(self))
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import serial
|
import serial
|
||||||
from serial import Serial
|
from serial import Serial
|
||||||
import data_centre.plugin_collection
|
import data_centre.plugin_collection
|
||||||
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationReceiverPlugin
|
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationReceiverPlugin, AutomationSourcePlugin
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
class WJSendPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin,ModulationReceiverPlugin):
|
class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationReceiverPlugin, AutomationSourcePlugin):
|
||||||
disabled = False#True
|
disabled = False#True
|
||||||
ser = None
|
ser = None
|
||||||
# from http://depot.univ-nc.nc/sources/boxtream-0.9999/boxtream/switchers/panasonic.py
|
# from http://depot.univ-nc.nc/sources/boxtream-0.9999/boxtream/switchers/panasonic.py
|
||||||
@@ -42,9 +42,44 @@ class WJSendPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin,ModulationReceiver
|
|||||||
self.pc.actions.tk.after(500, self.refresh)
|
self.pc.actions.tk.after(500, self.refresh)
|
||||||
#tk.after(500, self.refresh)
|
#tk.after(500, self.refresh)
|
||||||
|
|
||||||
|
# methods/vars for AutomationSourcePlugin
|
||||||
|
last_record = {}
|
||||||
|
def get_frame_data(self):
|
||||||
|
diff = self.last_record.copy()
|
||||||
|
#self.last_record = {}
|
||||||
|
return diff
|
||||||
|
|
||||||
|
def get_frame_diff(self, last_frame, current_frame):
|
||||||
|
lf = last_frame.get(self.frame_key)
|
||||||
|
cf = current_frame.get(self.frame_key)
|
||||||
|
|
||||||
|
if cf is None or not cf:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
if lf is None or not lf:
|
||||||
|
return { self.frame_key: cf.copy() }
|
||||||
|
|
||||||
|
diff = {}
|
||||||
|
for queue,message in cf.items():
|
||||||
|
if lf.get(queue) is None or lf.get(queue)!=message:
|
||||||
|
diff[queue] = message
|
||||||
|
|
||||||
|
#print (">>>>>> returning diff\n%s\n<<<<<" % diff)
|
||||||
|
return diff
|
||||||
|
|
||||||
|
def recall_frame_data(self, data):
|
||||||
|
if data is None:
|
||||||
|
return
|
||||||
|
# print(">>>>recall from data:\n\t%s\n" %data)
|
||||||
|
for queue, item in data.items():
|
||||||
|
self.send_buffered(queue, item, record = False)
|
||||||
|
|
||||||
|
|
||||||
|
# methods for ModulationReceiverPlugin - receives changes to the in-built modulation levels (-1 to +1)
|
||||||
|
# experimental & hardcoded !
|
||||||
def set_modulation_value(self, param, value):
|
def set_modulation_value(self, param, value):
|
||||||
# take modulation value and throw it to local parameter
|
# take modulation value and throw it to local parameter
|
||||||
print("||||| wjsend set_modulation_value for param %s with value %s!" % (param, value))
|
print("||||| wjsend received set_modulation_value for param %s with value %s!" % (param, value))
|
||||||
if param==0:
|
if param==0:
|
||||||
self.set_mix((0.5+value)/2)
|
self.set_mix((0.5+value)/2)
|
||||||
elif param==1:
|
elif param==1:
|
||||||
@@ -56,6 +91,21 @@ class WJSendPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin,ModulationReceiver
|
|||||||
else:
|
else:
|
||||||
print("unknown param %s!" % param)
|
print("unknown param %s!" % param)
|
||||||
|
|
||||||
|
#methods for DisplayPlugin
|
||||||
|
def show_plugin(self, display, display_mode):
|
||||||
|
from tkinter import Text, END
|
||||||
|
#super(DisplayPlugin).show_plugin(display, display_mode)
|
||||||
|
#print("show plugin?")
|
||||||
|
display.display_text.insert(END, '{} \n'.format(display.body_title))
|
||||||
|
display.display_text.insert(END, "test from WJSendPlugin!\n\n")
|
||||||
|
|
||||||
|
for queue, last in self.last.items():
|
||||||
|
display.display_text.insert(END, "last %s:\t%s\n" % (queue,self.last.get(queue)))
|
||||||
|
|
||||||
|
def get_display_modes(self):
|
||||||
|
return ["WJMXSEND","NAV_WJMX"]
|
||||||
|
|
||||||
|
# methods for SerialPlugin (todo!)
|
||||||
def open_serial(self, port='/dev/ttyUSB0', baudrate=9600):
|
def open_serial(self, port='/dev/ttyUSB0', baudrate=9600):
|
||||||
if self.ser is not None:
|
if self.ser is not None:
|
||||||
self.ser.close()
|
self.ser.close()
|
||||||
@@ -79,19 +129,60 @@ class WJSendPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin,ModulationReceiver
|
|||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
def show_plugin(self, display, display_mode):
|
def send_serial_string(self, string):
|
||||||
from tkinter import Text, END
|
try:
|
||||||
#super(DisplayPlugin).show_plugin(display, display_mode)
|
print("sending string %s " % string)
|
||||||
#print("show plugin?")
|
output = b'\2' + string.encode('ascii') + b'\3'
|
||||||
display.display_text.insert(END, '{} \n'.format(display.body_title))
|
self.ser.write(output) #.encode())
|
||||||
display.display_text.insert(END, "test from WJSendPlugin!\n\n")
|
print("sent string '%s'" % output) #.encode('ascii'))
|
||||||
|
#if 'S' in string:
|
||||||
|
# self.get_device_status()
|
||||||
|
except Exception as e:
|
||||||
|
print("%s: send_serial_string failed for '%s'" % (e,string)) #.encode()
|
||||||
|
|
||||||
for queue, last in self.last.items():
|
queue = {}
|
||||||
display.display_text.insert(END, "last %s:\t%s\n" % (queue,self.last.get(queue)))
|
def refresh(self):
|
||||||
|
#print("refresh called!")
|
||||||
|
if not self.ser or self.ser is None:
|
||||||
|
self.open_serial()
|
||||||
|
|
||||||
def get_display_modes(self):
|
try:
|
||||||
return ["WJMXSEND","NAV_WJMX"]
|
for queue, command in self.queue.items():
|
||||||
|
self.send_buffered(queue, command)
|
||||||
|
#self.queue.clear()
|
||||||
|
except Exception:
|
||||||
|
print ("!!! CAUGHT EXCEPTION running queue !!!")
|
||||||
|
import traceback
|
||||||
|
print(traceback.format_exc())
|
||||||
|
finally:
|
||||||
|
self.queue.clear()
|
||||||
|
|
||||||
|
if self.ser is not None:
|
||||||
|
self.pc.shaders.root.after(self.THROTTLE, self.refresh)
|
||||||
|
|
||||||
|
def send(self, queue, output):
|
||||||
|
#self.send_buffered(queue,output)
|
||||||
|
self.queue[queue] = output
|
||||||
|
|
||||||
|
last = {}
|
||||||
|
def send_buffered(self, queue, output, record = True):
|
||||||
|
if self.last.get(queue)!=output:
|
||||||
|
self.send_serial_string(output)
|
||||||
|
self.last[queue] = output
|
||||||
|
if record:
|
||||||
|
print("### send_buffered is setting last_record[%s] to %s" % (queue,output))
|
||||||
|
self.last_record[queue] = output
|
||||||
|
|
||||||
|
def send_append(self, command, value):
|
||||||
|
# append value to the command as a hex value
|
||||||
|
self.send(command.split(':')[0], "{}{:02X}".format(command,int(255*value)))
|
||||||
|
|
||||||
|
def send_append_pad(self, pad, command, value):
|
||||||
|
# append value, padded to length
|
||||||
|
self.send(command.split(':')[0], ("{}{:0%iX}"%pad).format(command,int(255*value)))
|
||||||
|
|
||||||
|
|
||||||
|
# methods for ActionPlugin
|
||||||
@property
|
@property
|
||||||
def parserlist(self):
|
def parserlist(self):
|
||||||
return [
|
return [
|
||||||
@@ -106,42 +197,9 @@ class WJSendPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin,ModulationReceiver
|
|||||||
( r"^wj_send_append_([:0-9a-zA-Z]*)$", self.send_append ),
|
( r"^wj_send_append_([:0-9a-zA-Z]*)$", self.send_append ),
|
||||||
]
|
]
|
||||||
|
|
||||||
def send_serial_string(self, string):
|
# methods for handling some Panasonic control settings
|
||||||
try:
|
# todo: come up with a way to represent this programmatically
|
||||||
print("sending string %s " % string)
|
# todo: add more!
|
||||||
output = b'\2' + string.encode('ascii') + b'\3'
|
|
||||||
self.ser.write(output) #.encode())
|
|
||||||
print("sent string '%s'" % output) #.encode('ascii'))
|
|
||||||
#if 'S' in string:
|
|
||||||
# self.get_device_status()
|
|
||||||
except Exception as e:
|
|
||||||
print("%s: send_serial_string failed for '%s'" % (e,string.encode()))
|
|
||||||
|
|
||||||
queue = {}
|
|
||||||
def refresh(self):
|
|
||||||
#print("refresh called!")
|
|
||||||
if not self.ser or self.ser is None:
|
|
||||||
self.open_serial()
|
|
||||||
|
|
||||||
try:
|
|
||||||
for queue, command in self.queue.items():
|
|
||||||
self.send_buffered(queue, command)
|
|
||||||
self.queue.clear()
|
|
||||||
except:
|
|
||||||
print ("!!! CAUGHT EXCEPTION running queue !!!")
|
|
||||||
|
|
||||||
if self.ser is not None:
|
|
||||||
self.pc.shaders.root.after(self.THROTTLE, self.refresh)
|
|
||||||
|
|
||||||
def send(self, queue, output):
|
|
||||||
#self.send_buffered(queue,output)
|
|
||||||
self.queue[queue] = output
|
|
||||||
|
|
||||||
last = {}
|
|
||||||
def send_buffered(self, queue, output):
|
|
||||||
if self.last.get(queue)!=output:
|
|
||||||
self.send_serial_string(output)
|
|
||||||
self.last[queue] = output
|
|
||||||
|
|
||||||
colour_x = 127
|
colour_x = 127
|
||||||
colour_y = 127
|
colour_y = 127
|
||||||
@@ -155,6 +213,7 @@ class WJSendPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin,ModulationReceiver
|
|||||||
output = "VCC:{}{:02X}{:02X}".format(chan, self.colour_x,self.colour_y)
|
output = "VCC:{}{:02X}{:02X}".format(chan, self.colour_x,self.colour_y)
|
||||||
self.send('VCC', output)
|
self.send('VCC', output)
|
||||||
|
|
||||||
|
# RGB control of matte colour!
|
||||||
back_colour_x = 127
|
back_colour_x = 127
|
||||||
back_colour_y = 127
|
back_colour_y = 127
|
||||||
back_colour_z = 127
|
back_colour_z = 127
|
||||||
@@ -186,7 +245,7 @@ class WJSendPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin,ModulationReceiver
|
|||||||
output = "VBW:{:02X}{:02X}{:02X}".format(self.back_wash_colour_x,self.back_wash_colour_y,self.back_wash_colour_z)
|
output = "VBW:{:02X}{:02X}{:02X}".format(self.back_wash_colour_x,self.back_wash_colour_y,self.back_wash_colour_z)
|
||||||
self.send('VBW', output)
|
self.send('VBW', output)
|
||||||
|
|
||||||
|
# positioner joystick
|
||||||
position_x = 127
|
position_x = 127
|
||||||
position_y = 127
|
position_y = 127
|
||||||
def set_position(self, mode, dim, value):
|
def set_position(self, mode, dim, value):
|
||||||
@@ -198,15 +257,8 @@ class WJSendPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin,ModulationReceiver
|
|||||||
output = "VPS:{}{:02X}{:02X}".format(mode,self.position_x,self.position_y)
|
output = "VPS:{}{:02X}{:02X}".format(mode,self.position_x,self.position_y)
|
||||||
self.send('VPS:{}'.format(mode), output)
|
self.send('VPS:{}'.format(mode), output)
|
||||||
|
|
||||||
|
# wipe / mix level
|
||||||
def set_mix(self, value):
|
def set_mix(self, value):
|
||||||
output = "VMM:{:04X}".format(int(255*255*value))
|
output = "VMM:{:04X}".format(int(255*255*value))
|
||||||
self.send('VMM', output)
|
self.send('VMM', output)
|
||||||
|
|
||||||
|
|
||||||
def send_append(self, command, value):
|
|
||||||
# append value to the command as a hex value
|
|
||||||
self.send(command.split(':')[0], "{}{:02X}".format(command,int(255*value)))
|
|
||||||
|
|
||||||
def send_append_pad(self, pad, command, value):
|
|
||||||
# append value, padded to length
|
|
||||||
self.send(command.split(':')[0], ("{}{:0%iX}"%pad).format(command,int(255*value)))
|
|
||||||
|
|||||||
Reference in New Issue
Block a user