Merge pull request #137 from Cabalist/dev_cleanup

Code cleanup
This commit is contained in:
langolierz
2020-05-05 19:04:46 +02:00
committed by GitHub
32 changed files with 1658 additions and 1684 deletions

View File

@@ -1,20 +1,20 @@
import subprocess
import tracemalloc
import data_centre.length_setter as length_setter
from inspect import signature
import sys
import shlex
import argparse
import os
import re
from pythonosc import osc_message_builder
import subprocess
import sys
import threading
from inspect import signature
import git
from pythonosc import dispatcher
from pythonosc import osc_server
import git
import threading
import argparse
import data_centre.length_setter as length_setter
from video_centre.capture import Capture
from video_centre.of_capture import OfCapture
class Actions(object):
def __init__(self, tk, message_handler, data, video_driver, shaders, display, osc_client):
self.tk = tk
@@ -54,7 +54,6 @@ class Actions(object):
def move_browser_selection_page_up(self):
self.display.browser_menu.navigate_menu_page_up()
def enter_on_browser_selection(self):
self.display.browser_menu.enter_on_browser_selection()
@@ -70,7 +69,6 @@ class Actions(object):
def move_settings_selection_page_up(self):
self.display.settings_menu.navigate_menu_page_up()
def enter_on_settings_selection(self):
is_setting, setting = self.display.settings_menu.enter_on_setting_selection()
if is_setting:
@@ -92,7 +90,6 @@ class Actions(object):
def move_shaders_selection_page_up(self):
self.shaders.shaders_menu.navigate_menu_page_up()
def enter_on_shaders_selection(self):
##want to select shader if its not selected, and want to enter 'param' mode if it already is
is_shader, is_selected_shader, selected_shader = self.shaders.enter_on_shaders_selection()
@@ -135,8 +132,6 @@ class Actions(object):
if self.data.update_next_slot_number(slot, is_current=True):
self.video_driver.reload_current_player()
def load_slot_0_into_next_player(self):
self._load_this_slot_into_next_player(0)
@@ -207,7 +202,6 @@ class Actions(object):
self.data.display_mode = display_modes[next_mode_index][0]
self.data.control_mode = display_modes[next_mode_index][1]
def toggle_action_on_player(self):
play = 'play' in self.data.settings['sampler']['ON_ACTION']['value']
show = 'show' in self.data.settings['sampler']['ON_ACTION']['value']
@@ -234,14 +228,12 @@ class Actions(object):
self.data.update_setting_value('sampler', 'SEEK_TIME', options[(current_index + 1) % len(options)])
self.message_handler.set_message('INFO', 'The Seek Time is now ' + str(self.data.settings['sampler']['SEEK_TIME']['value']) + 's')
def decrease_seek_time(self):
options = self.data.settings['sampler']['SEEK_TIME']['options']
current_index = [index for index, item in enumerate(options) if item == self.data.settings['sampler']['SEEK_TIME']['value']][0]
self.data.update_setting_value('sampler', 'SEEK_TIME', options[(current_index - 1) % len(options)])
self.message_handler.set_message('INFO', 'The Seek Time is now ' + str(self.data.settings['sampler']['SEEK_TIME']['value']) + 's')
def seek_forward_on_player(self):
self.video_driver.current_player.seek(self.data.settings['sampler']['SEEK_TIME']['value'])
@@ -312,7 +304,6 @@ class Actions(object):
# if is_successful and self.video_driver.current_player.status != 'PAUSED':
# self.video_driver.current_player.toggle_pause()
def toggle_capture_recording(self):
is_recording = self.capture.is_recording
if is_recording:
@@ -480,7 +471,6 @@ class Actions(object):
self.data.detour_settings['current_detour'] = number
self.video_driver.osc_client.send_message("/detour/switch_to_detour_number", number)
def set_detour_delay_mode(self, state):
self.video_driver.osc_client.send_message("/detour/set_delay_mode", state == 'enabled')
self.data.update_conjur_delay_mode(state == 'enabled')
@@ -634,7 +624,6 @@ class Actions(object):
self.change_hdmi_settings('CEA 4 HDMI')
def check_dev_mode(self):
#### check if in dev mode:(ie not using the lcd screen)
with open('/boot/config.txt', 'r') as config:
@@ -686,7 +675,6 @@ class Actions(object):
self.refresh_frame_buffer_and_restart_openframeworks()
self.persist_composite_setting(mode, progressive, aspect)
def _refresh_frame_buffer(self):
self.data.open_omxplayer_for_reset()
subprocess.run(["fbset -depth 16; fbset -depth 32; xrefresh -display :0"], shell=True)
@@ -734,7 +722,6 @@ class Actions(object):
else:
self.message_handler.set_message('INFO', 'failed to switch display')
def switch_display_to_lcd(self):
with open('/boot/config.txt', 'r') as config:
with open('/usr/share/X11/xorg.conf.d/99-fbturbo.conf') as framebuffer_conf:
@@ -756,7 +743,6 @@ class Actions(object):
subprocess.call(['xset', 'r', 'on'])
self.data.auto_repeat_on = True
def quit_the_program(self):
self.data._update_json(self.data.SETTINGS_JSON, self.data.settings)
self.data.plugins.quit_plugins()
@@ -808,7 +794,6 @@ class Actions(object):
self.message_handler.set_message('INFO', 'tap: ■ ; < > : back')
self.fixed_length_setter = length_setter.FixedLengthSetter(self.data)
def return_to_default_control_mode(self):
display_list = self.data.get_display_modes_list(with_nav_mode=True)
for display, control in display_list:
@@ -843,7 +828,6 @@ class Actions(object):
self.fixed_length_setter.record_input()
self.display.settings_menu.generate_settings_list()
def setup_osc_server(self):
server_parser = argparse.ArgumentParser()
server_parser.add_argument("--ip", default="127.0.0.1", help="the ip")
@@ -914,7 +898,6 @@ class Actions(object):
def enable_osc(self, osc_setting_state):
self.data.update_setting_value('user_input', 'OSC_INPUT', osc_setting_state)
def show_ip(self, *args):
address = self.data.get_ip_address()
self.message_handler.set_message('INFO', 'ip is {}:8080'.format(address))
@@ -929,7 +912,6 @@ class Actions(object):
self.serial_port_process.kill()
self.serial_port_process = None
def stop_remote_process(self):
if self.remote_process is not None:
self.remote_process.kill()
@@ -1019,7 +1001,6 @@ class Actions(object):
subprocess.call(['sudo', 'eject', '/dev/sda{}'.format(i)])
self.message_handler.set_message('INFO', 'usb ejected')
# TODO: make this interrogate the various components for available routes to parse
# this would include eg a custom script module..
@property
@@ -1114,4 +1095,3 @@ class Actions(object):
print("Exception calling action for '%s' with arguments ( %s ) " % (method_name, arguments))
import traceback
traceback.print_exc()

View File

@@ -1,17 +1,17 @@
import subprocess
import json
import xml.etree.ElementTree as ET
import os
import collections
from random import randint
import inspect
from itertools import cycle
from omxplayer.player import OMXPlayer
from shutil import copyfile
import json
import os
import subprocess
import threading
import xml.etree.ElementTree as ET
from random import randint
from shutil import copyfile
from omxplayer.player import OMXPlayer
from data_centre import plugin_collection
class AsyncWrite(threading.Thread):
def __init__(self, filename, data, mode='json'):
threading.Thread.__init__(self)
@@ -29,7 +29,6 @@ class AsyncWrite(threading.Thread):
class Data(object):
BANK_DATA_JSON = 'display_data.json'
SHADER_BANK_DATA_JSON = 'shader_bank_data.json'
SETTINGS_JSON = 'settings.json'
@@ -274,7 +273,6 @@ class Data(object):
######## setting and adding to shader mapping
def create_new_shader_mapping_in_first_open(self, file_name):
######## used for mapping current shader to next available slot ########
for index, slot in enumerate(self.shader_bank_data[self.shader_layer]):
@@ -297,8 +295,6 @@ class Data(object):
def update_shader_layer_by_amount(self, amount):
self.shader_layer = (self.shader_layer + amount) % len(self.shader_bank_data)
def update_setting_value(self, setting_folder, setting_name, setting_value):
self.settings[setting_folder][setting_name]['value'] = setting_value
self._update_json(self.SETTINGS_JSON, self.settings)
@@ -424,7 +420,6 @@ class Data(object):
self.message_handler.set_message('INFO', 'cannot load video')
return None
def _get_path_for_file(self, file_name):
######## returns full path for a given file name ########
for path in self.PATHS_TO_BROWSER + self.PATHS_TO_SHADERS:
@@ -433,7 +428,6 @@ class Data(object):
return True, '{}/{}'.format(root, file_name)
return False, ''
def is_this_path_broken(self, path):
external_devices = os.listdir(self.PATH_TO_EXTERNAL_DEVICES)
has_device_in_path = self.PATH_TO_EXTERNAL_DEVICES in path
@@ -522,5 +516,3 @@ class Data(object):
def try_remove_file(path):
if os.path.exists(path):
os.remove(path)

View File

@@ -1,5 +1,6 @@
import datetime
class FixedLengthSetter(object):
DELTA_NUMBER = 2

View File

@@ -1,14 +1,15 @@
import inspect
import os
import pkgutil
import re
from plugins.frame_manager import FrameManager, Frame
from plugins.frame_manager import FrameManager
class Plugin(object):
"""Base class that each plugin must inherit from. within this class
you must define the methods that all of your plugins must implement
"""
@property
def disabled(self):
return type(self).__name__ not in self.pc.data.get_enabled_plugin_class_names()
@@ -23,9 +24,11 @@ class Plugin(object):
def start_plugin(self):
print(">>Starting plugin " + type(self).__name__)
class MidiFeedbackPlugin(Plugin):
"""Base class for MIDI feedback plugins
"""
def __init__(self, plugin_collection):
super().__init__(plugin_collection)
self.description = 'Outputs feedback about status to device eg MIDI pads'
@@ -39,8 +42,10 @@ class MidiFeedbackPlugin(Plugin):
def refresh_midi_feedback(self):
raise NotImplementedError
class SequencePlugin(Plugin):
"""Base class for plugins that run constantly or on demand for eg automation"""
def __init__(self, plugin_collection):
super().__init__(plugin_collection)
@@ -60,7 +65,8 @@ class SequencePlugin(Plugin):
speed = 2.0 * (speed - 0.5) # adjust to range -1 to +1
negative = speed < 0.0 # remember negative state cos we'll lose it in next
self.speed = (speed * speed) * 2.0
if negative: self.speed *= -1
if negative:
self.speed *= -1
print("automation speed is now %s" % self.speed)
def toggle_automation(self):
@@ -86,6 +92,7 @@ class SequencePlugin(Plugin):
self.run_automation()
last_delta = -1
def delta(self, now):
if self.last_delta == -1:
self.last_delta = now
@@ -94,6 +101,7 @@ class SequencePlugin(Plugin):
return r
speed = 0.25 # 1.0
def move_delta(self, delta, speed):
self.position += delta * speed
if self.position > 1.0:
@@ -111,6 +119,7 @@ class SequencePlugin(Plugin):
iterations_count = 0
duration = 2000
frequency = 100
def run_automation(self):
import time
@@ -141,6 +150,7 @@ class SequencePlugin(Plugin):
def run_sequence(self, position):
raise NotImplementedError
class ActionsPlugin(Plugin):
def __init__(self, plugin_collection):
super().__init__(plugin_collection)
@@ -185,8 +195,10 @@ class ActionsPlugin(Plugin):
return (found_method, args)
class DisplayPlugin(Plugin):
"""Base class for plugins that want to show a user interface on the recur screen"""
def __init__(self, plugin_collection):
super().__init__(plugin_collection)
@@ -197,12 +209,14 @@ class DisplayPlugin(Plugin):
raise NotImplementedError
def show_plugin(self, display):
from tkinter import Text, END
from tkinter import END
# display_text.insert(END, 'test from DisplayPlugin')
display.display_text.insert(END, '{} \n'.format(display.body_title))
class ModulationReceiverPlugin(Plugin):
"""Base class for plugins that want to be notified of a change to modulation values"""
def __init__(self, plugin_collection):
super().__init__(plugin_collection)
@@ -210,8 +224,10 @@ class ModulationReceiverPlugin(Plugin):
print("||||||set_modulation_value dummy!")
raise NotImplementedError
class AutomationSourcePlugin(Plugin):
"""Base class for plugins that offer things to save&playback to&from automation"""
@property
def frame_key(self):
return self.__class__.__name__
@@ -281,6 +297,7 @@ class AutomationSourcePlugin(Plugin):
### TODO: experimental value interpolation -- doesn't work, and is slow!
cmd_size = {}
def process_interpolate_clip(self, frames):
# loop over every frame
# for each property of each frame
@@ -367,6 +384,7 @@ class AutomationSourcePlugin(Plugin):
self.distance_cache = {}
distance_cache = {}
def get_distance_value_command(self, frames, findex, queue, argindex):
distance_cache = self.distance_cache
@@ -403,7 +421,6 @@ class AutomationSourcePlugin(Plugin):
distance_cache[queue][argindex] = {'position': i, 'value': command[1][argindex]}
return i, command[1][argindex]
"""if frames[search_findex] is not None and frames[search_findex].f.get(self.frame_key,{}).get(queue,[])[argindex] is not None:
return i, frames[search_findex].f.get(self.frame_key,{}).get(queue,[])[argindex]"""
return 0, None
@@ -416,6 +433,7 @@ class PluginCollection(object):
"""Upon creation, this class will read the plugins package for modules
that contain a class definition that is inheriting from the Plugin class
"""
@property
def display(self):
return self.actions.display
@@ -448,6 +466,7 @@ class PluginCollection(object):
def read_json(self, file_name):
return self.data._read_plugin_json(file_name)
def update_json(self, file_name, data):
return self.data._update_plugin_json(file_name, data)
@@ -464,7 +483,8 @@ class PluginCollection(object):
def quit_plugins(self):
# tell each plugin to quit
for plugin in self.get_plugins():
if not plugin.disabled: plugin.stop_plugin()
if not plugin.disabled:
plugin.stop_plugin()
def stop_plugin_name(self, name):
for plugin in self.get_plugins(include_disabled=True):
@@ -479,7 +499,6 @@ class PluginCollection(object):
# print("starting %s" %name)
plugin.start_plugin()
def get_plugins(self, clazz=None, include_disabled=False):
if clazz:
return [c for c in self.plugins if isinstance(c, clazz) and (include_disabled or not c.disabled)]
@@ -510,7 +529,6 @@ class PluginCollection(object):
print(' Found plugin class: %s.%s' % (c.__module__, c.__name__))
self.plugins.append(c(self))
# Now that we have looked at all the modules in the current package, start looking
# recursively for additional modules in sub packages
# disabled 03-2020 to try and avoid problem with subclasses-of-subclasses being listed twice..
@@ -532,7 +550,6 @@ class PluginCollection(object):
for child_pkg in child_pkgs:
self.walk_package(package + '.' + child_pkg)"""
## helpers
def get_variable(self, varname, default=0.0):
from plugins.ManipulatePlugin import ManipulatePlugin

View File

@@ -1,8 +1,10 @@
from tkinter import Text, END
import math
import time
from tkinter import END, Text
import display_centre.menu as menu
class Display(object):
MENU_HEIGHT = 10
SELECTOR_WIDTH = 0.47
@@ -105,7 +107,6 @@ class Display(object):
self.display_text.tag_add("DISPLAY_MODE", 4.19, 4.29)
self.display_text.tag_add("COLUMN_NAME", 5.0, 6.0)
def _load_plugin_page(self, display_mode, plugin):
plugin.show_plugin(self, display_mode)
@@ -202,7 +203,6 @@ class Display(object):
self._highlight_this_row(self.plugins_menu.selected_list_index - self.plugins_menu.top_menu_index)
def _load_shaders(self):
line_count = 0
self.display_text.insert(END, '{} \n'.format(self.body_title))
@@ -358,7 +358,6 @@ class Display(object):
column_offset = 0.1
)"""
def _load_detour(self):
line_count = 0
self.display_text.insert(END, '{} \n'.format(self.body_title))
@@ -426,7 +425,6 @@ class Display(object):
capture_status = ''
preview_alpha = 0
if preview_alpha == None:
preview_alpha = 0
# print('capture alpha is {}'.format(preview_alpha))
@@ -471,8 +469,10 @@ class Display(object):
if value is None:
return " "
value = abs(value / max_value) # abs() so negative values make some sense
if value>1.0: value = 1.0
elif value<0.0: value = 0.0
if value > 1.0:
value = 1.0
elif value < 0.0:
value = 0.0
bar = u"_\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588"
g = '%s' % bar[int(value * (len(bar) - 1))]
return g
@@ -529,8 +529,6 @@ class Display(object):
# s += "#" if selected else "-"
return s
@staticmethod
def create_video_display_banner(start, end, position):
banner_list = ['[', '-', '-', '-', '-', '-', '-', '-', '-',
@@ -639,6 +637,7 @@ class Display(object):
last_refreshed = 0
REFRESH_LIMIT = 100
def refresh_display(self):
if self.data.update_screen:
if time.time() * 1000 - self.last_refreshed < self.REFRESH_LIMIT:

View File

@@ -1,5 +1,6 @@
import os
class Menu(object):
def __init__(self, data, message_handler, menu_height):
self.data = data
@@ -50,7 +51,6 @@ class Menu(object):
self.top_menu_index += self.menu_height
self.selected_list_index = min(self.menu_height + self.selected_list_index, len(self.menu_list) - 1)
def update_open_folders(self, folder_name):
if folder_name not in self.open_folders:
self.open_folders.append(folder_name)
@@ -72,6 +72,7 @@ class Menu(object):
else:
return True, dir_name.lstrip()
class BrowserMenu(Menu):
def __init__(self, data, message_handler, menu_height):
Menu.__init__(self, data, message_handler, menu_height)
@@ -119,7 +120,6 @@ class BrowserMenu(Menu):
return True, '{}-{}'.format(bank_index, slot_index)
return False, ''
def enter_on_browser_selection(self):
is_file, name = self.extract_file_type_and_name_from_menu_format(
self.menu_list[self.selected_list_index]['name'])
@@ -133,7 +133,6 @@ class BrowserMenu(Menu):
class SettingsMenu(Menu):
FOLDER_ORDER = ['video', 'sampler', 'user_input', 'capture', 'shader', 'detour', 'system']
SAMPLER_ORDER = ['LOOP_TYPE', 'LOAD_NEXT', 'RAND_START_MODE', 'RESET_PLAYERS', 'FIXED_LENGTH_MODE', 'FIXED_LENGTH', 'FIXED_LENGTH_MULTIPLY']
VIDEO_ORDER = ['VIDEOPLAYER_BACKEND']
@@ -229,7 +228,6 @@ class ShadersMenu(Menu):
self._add_folder_to_shaders_list(path, 0)
return self.menu_list
def _add_folder_to_shaders_list(self, current_path, current_level):
######## adds the folders and shader files at the current level to the results list. recursively recalls at deeper level if folder is open ########
@@ -249,8 +247,3 @@ class ShadersMenu(Menu):
split_name = os.path.splitext(f)
if (split_name[1].lower() in ['.frag', '.shader', '.glsl', '.glslf', '.fsh']):
self.menu_list.append(dict(name='{}{}'.format(indent, f), is_shader=True))

View File

@@ -1,5 +1,6 @@
import logging
class MessageHandler(object):
def __init__(self):
self.current_message = [None, None, None]

View File

@@ -1,8 +1,8 @@
from pythonosc import osc_message_builder
from pythonosc import udp_client
from pythonosc import dispatcher
import argparse
from pythonosc import udp_client
def setup_osc_client(ip, port):
client_parser = argparse.ArgumentParser()
client_parser.add_argument("--ip", default=ip, help="the ip")
@@ -12,6 +12,7 @@ def setup_osc_client(ip, port):
return udp_client.SimpleUDPClient(client_args.ip, client_args.port)
client = setup_osc_client('127.0.0.1', 5433)
client.send_message("/shutdown", True)

View File

@@ -1,9 +1,9 @@
import math
import data_centre.plugin_collection
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin, DisplayPlugin, AutomationSourcePlugin
from data_centre.plugin_collection import ActionsPlugin, AutomationSourcePlugin, DisplayPlugin, SequencePlugin
class LFOModulationPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, AutomationSourcePlugin):
MAX_LFOS = 4
PRESET_FILE_NAME = "LFOModulationPlugin/config.json"
@@ -25,6 +25,7 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
stop_flag = False
pause_flag = False
def __init__(self, plugin_collection):
super().__init__(plugin_collection)
@@ -58,7 +59,7 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
return ['LFOMODU', 'NAV_LFO']
def show_plugin(self, display, display_mode):
from tkinter import Text, END
from tkinter import END
# super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "LFOModulation is ")
@@ -130,8 +131,10 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
]
def set_lfo_modulation_level(self, slot, value):
if (value<0.0): value = 0.0
if (value>1.0): value = 1.0
if (value < 0.0):
value = 0.0
if (value > 1.0):
value = 1.0
self.level[slot] = value
def set_lfo_speed(self, speed):
@@ -157,25 +160,31 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
def select_next_lfo(self):
self.select_lfo(self.selected_lfo + 1)
def select_previous_lfo(self):
self.select_lfo(self.selected_lfo - 1)
level_step = 0.125
def increase_lfo_level(self, slot):
self.set_lfo_modulation_level(slot, self.level[slot] + self.level_step)
def decrease_lfo_level(self, slot):
self.set_lfo_modulation_level(slot, self.level[slot] - self.level_step)
def increase_selected_lfo_level(self):
self.increase_lfo_level(self.selected_lfo)
def decrease_selected_lfo_level(self):
self.decrease_lfo_level(self.selected_lfo)
lfo_step = 0.25
def increase_lfo_speed(self):
self.set_lfo_speed_direct(self.speed + self.lfo_step)
if self.speed == 0.0: # dont rest on 0 - set to a small amount forward
self.speed = 0.05
def decrease_lfo_speed(self):
self.set_lfo_speed_direct(self.speed - self.lfo_step)
if self.speed == 0.0: # dont rest on 0 - set to a small amount forward
@@ -195,6 +204,7 @@ class LFOModulationPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin, Automation
# run the formula for the stored lfo configuration
last_lfo_status = [None] * MAX_LFOS # for displaying status
last_lfo_value = [None] * MAX_LFOS
# lfo_speed = [1.0]*MAX_LFOS
def getLFO(self, position, lfo):
lfo_value = getattr(self, self.formula[lfo])(position, self.level[lfo])

View File

@@ -1,7 +1,6 @@
import data_centre.plugin_collection
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, ModulationReceiverPlugin # , SequencePlugin
# import math
from math import sin, cos, tan, log, exp, pi
"""
add to midi or osc mapping
@@ -41,8 +40,8 @@ TODO: >> ?? invert|set_the_shader_param_0_layer_>>print_arguments>>set_variab
"""
class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
class ManipulatePlugin(ActionsPlugin, DisplayPlugin, ModulationReceiverPlugin):
DEBUG = False
def __init__(self, plugin_collection):
@@ -62,7 +61,7 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
# DisplayPlugin methods
def show_plugin(self, display, display_mode):
from tkinter import Text, END
from tkinter import END
# super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "test from ManipulatePlugin!\n")
@@ -75,7 +74,8 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
# Actions
def run_multi(self, action1, action2, value):
if self.DEBUG: print("ManipulatePlugin>> multi-running '%s' and '%s' with value %s" % (action1, action2, value))
if self.DEBUG:
print("ManipulatePlugin>> 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)
@@ -91,16 +91,19 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
def formula(self, formula, action, value):
self.variables['x'] = value
if self.DEBUG: print("ManipulatePlugin>> evaluating formula `%s` with value `%s`" % (formula, value))
if self.DEBUG:
print("ManipulatePlugin>> evaluating formula `%s` with value `%s`" % (formula, value))
value = eval(formula, globals(), self.variables)
if self.DEBUG: print("ManipulatePlugin>> got evaluated value `%s`" % value)
if self.DEBUG:
print("ManipulatePlugin>> got evaluated value `%s`" % value)
self.pc.actions.call_method_name(
action, value
)
def set_variable(self, var_name, value):
if self.DEBUG: print("ManipulatePlugin>> set_variable (%s) to %s" % (var_name, value))
if self.DEBUG:
print("ManipulatePlugin>> set_variable (%s) to %s" % (var_name, value))
self.variables[var_name] = value
def get_variable(self, var_name, default):
@@ -110,16 +113,16 @@ class ManipulatePlugin(ActionsPlugin,DisplayPlugin,ModulationReceiverPlugin):
return default
def recall_variable(self, var_name, action, *args):
if self.DEBUG: print ("ManipulatePlugin>> recall_variable (%s) as %s" % (var_name,args))
if self.DEBUG:
print("ManipulatePlugin>> recall_variable (%s) as %s" % (var_name, args))
self.pc.actions.call_method_name(
action, self.variables.get(var_name) # + list(args)
)
# ModulationReceiverPlugin methods
# methods for ModulationReceiverPlugin - receives changes to the in-built modulation levels (-1 to +1)
def set_modulation_value(self, param, value):
# take modulation value and throw it to local parameter
if self.DEBUG: print("||||| ManipulatePlugin received set_modulation_value for param %s with value %s!" % (param, value))
if self.DEBUG:
print("||||| ManipulatePlugin received set_modulation_value for param %s with value %s!" % (param, value))
self.set_variable("MODVALUE%s" % ('ABCD'[param]), value)

View File

@@ -1,7 +1,8 @@
from data_centre import plugin_collection
from data_centre.plugin_collection import MidiFeedbackPlugin
import mido
from data_centre.plugin_collection import MidiFeedbackPlugin
class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
# disabled = False
@@ -70,7 +71,8 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
self.set_status(note=self.NOTE_CAPTURE_PREVIEW, velocity=int(on))
def feedback_shader_on(self, layer, slot, colour=None):
if colour is None: colour = self.COLOUR_GREEN
if colour is None:
colour = self.COLOUR_GREEN
self.set_status(note=(self.NOTE_PLAY_SHADER - (layer) * 8) + slot, velocity=int(colour))
def feedback_shader_off(self, layer, slot):
@@ -231,6 +233,7 @@ class MidiFeedbackAPCKey25Plugin(MidiFeedbackPlugin):
# print("refresh_midi_feedback")
last_state = None
def update_device(self):
from copy import deepcopy
# print("in update device status is %s" % self.status)

View File

@@ -1,11 +1,9 @@
from data_centre import plugin_collection
from data_centre.plugin_collection import MidiFeedbackPlugin
import mido
import plugins
# from plugins.MidiFeedbackAPCKey25Plugin import MidiFeedbackAPCKey25Plugin
class MidiFeedbackLaunchpadPlugin(plugins.MidiFeedbackAPCKey25Plugin.MidiFeedbackAPCKey25Plugin):
status = {}
def __init__(self, plugin_collection):
@@ -31,7 +29,8 @@ class MidiFeedbackLaunchpadPlugin(plugins.MidiFeedbackAPCKey25Plugin.MidiFeedbac
return True
def feedback_shader_on(self, layer, slot, colour=None):
if colour is None: colour = self.COLOUR_GREEN
if colour is None:
colour = self.COLOUR_GREEN
self.set_status(note=(self.NOTE_PLAY_SHADER + (layer) * 16) + slot, velocity=int(colour))
def feedback_shader_off(self, layer, slot):

View File

@@ -1,6 +1,6 @@
import data_centre.plugin_collection
from data_centre.plugin_collection import ActionsPlugin
class MultiActionsPlugin(ActionsPlugin):
disabled = False # this is only a demo of very basic multi-actions plugin -- superceded by ManipulatePlugin

View File

@@ -1,9 +1,8 @@
import data_centre.plugin_collection
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin, DisplayPlugin
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, SequencePlugin
from plugins.frame_manager import Frame
class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
class ShaderLoopRecordPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin):
MAX_CLIPS = 8
frames = []
@@ -54,7 +53,7 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
return ['LOOPREC', 'NAV_LPRC']
def show_plugin(self, display, display_mode):
from tkinter import Text, END
from tkinter import END
# super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "test from ShaderLoopRecordPlugin!\n")
@@ -93,8 +92,6 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
"""for key,value in self.variables.items():
display.display_text.insert(END, "\t" + key + "\t{:03.2f}\n".format(value))"""
@property
def parserlist(self):
return [
@@ -116,7 +113,6 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
def smooth_selected_clip(self):
self.pc.fm.interpolate_clip(self.frames[self.selected_clip])
def toggle_overdub_automation(self):
self.overdub = not self.overdub
if not self.overdub:
@@ -143,7 +139,8 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
clip = self.selected_clip
self.frames[clip] = self.get_empty_clip(self.duration) * self.MAX_CLIPS
self.reset_ignored()
if self.DEBUG_FRAMES: print ("clear_frames set to %s" % (int(self.duration / self.frequency)))
if self.DEBUG_FRAMES:
print("clear_frames set to %s" % (int(self.duration / self.frequency)))
return self.frames
def toggle_clip(self, clip=None):
@@ -180,6 +177,7 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
last_frame = None # for tracking what's changed between frames when overdubbing
last_saved_index = None # for backfilling
DEBUG_FRAMES = False # True
def run_sequence(self, position):
current_frame_index = int(position * (int(self.duration / self.frequency)))
if current_frame_index < 0:
@@ -187,14 +185,16 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
if current_frame_index >= self.duration: # self.duration/self.frequency:
current_frame_index = "(self.duration/self.frequency) +"""(current_frame_index % self.duration)
if self.DEBUG_FRAMES: print (">>>>>>>>>>>>>>frame at %i%%: %i" % (position*100, current_frame_index))
if self.DEBUG_FRAMES:
print(">>>>>>>>>>>>>>frame at %i%%: %i" % (position * 100, current_frame_index))
# print("got frame index %s" % current_frame_index)
if self.recording:
current_frame = self.pc.fm.get_live_frame() # .copy()
selected_clip = self.selected_clip
if self.DEBUG_FRAMES: print("current_frame copy before recall is %s" % current_frame['shader_params'])
if self.DEBUG_FRAMES:
print("current_frame copy before recall is %s" % current_frame['shader_params'])
# print ("%s clips, looks like %s" % (len(self.frames),self.frames))
# print("selected_clip is %s "%selected_clip)
@@ -203,7 +203,8 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
self.running_clips += [self.selected_clip]
if self.recording:
current_frame = self.pc.fm.get_live_frame() # .copy()
if self.DEBUG_FRAMES: print("current_frame copy before recall is %s" % current_frame['shader_params'])
if self.DEBUG_FRAMES:
print("current_frame copy before recall is %s" % current_frame['shader_params'])
for selected_clip in self.running_clips:
saved_frame = self.frames[selected_clip][current_frame_index]
@@ -212,16 +213,21 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
if self.recording and selected_clip == self.selected_clip:
if self.last_frame is None:
self.last_frame = current_frame
if self.DEBUG_FRAMES: print("last frame is \t\t%s" % self.last_frame['shader_params'])
if self.DEBUG_FRAMES: print("current f is \t\t%s" % current_frame['shader_params'])
if self.DEBUG_FRAMES:
print("last frame is \t\t%s" % self.last_frame['shader_params'])
if self.DEBUG_FRAMES:
print("current f is \t\t%s" % current_frame['shader_params'])
diff = self.pc.fm.get_frame_diff(self.last_frame, current_frame)
if self.DEBUG_FRAMES: print("diffed frame is \t%s" % diff['shader_params'])
if self.DEBUG_FRAMES:
print("diffed frame is \t%s" % diff['shader_params'])
if self.overdub and saved_frame:
# add the params tweaked this frame to the params to be ignored by recall
if self.DEBUG_FRAMES: print("saved frame is \t%s" % saved_frame['shader_params'])
if self.DEBUG_FRAMES:
print("saved frame is \t%s" % saved_frame['shader_params'])
self.ignored = self.pc.fm.merge_frames(self.ignored, diff)
if self.DEBUG_FRAMES: print("about to call get_ignored_frames with %s\n and\n %s" % (saved_frame.f, self.ignored.f))
if self.DEBUG_FRAMES:
print("about to call get_ignored_frames with %s\n and\n %s" % (saved_frame.f, self.ignored.f))
"""print("got self.ignored:\n\t%s\n" % self.ignored.f)
print("diff is currently:\n\t%s\n" % diff.f)
print("saved_frame is currently:\n\t%s\n" % saved_frame.f)"""
@@ -232,8 +238,10 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
# print("got merged:\n\t%s\n" % diff.f)
# diff = self.pc.shaders.merge_frames(self.pc.shaders.get_live_frame(), diff)
self.pc.fm.recall_frame(diff)
if self.DEBUG_FRAMES: print("after diff2 is: \t%s" % diff['shader_params'])
if self.DEBUG_FRAMES: print("||||saving frame \t%s" % (diff['shader_params']))
if self.DEBUG_FRAMES:
print("after diff2 is: \t%s" % diff['shader_params'])
if self.DEBUG_FRAMES:
print("||||saving frame \t%s" % (diff['shader_params']))
self.frames[selected_clip][current_frame_index] = diff # self.get_frame_diff(self.last_frame,current_frame)
# backfill frames
"""if self.last_saved_index is not None:
@@ -243,8 +251,8 @@ class ShaderLoopRecordPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
self.frames[selected_clip][(self.last_saved_index+i+1)%len(self.frames[selected_clip])] = diff"""
self.last_saved_index = current_frame_index
self.last_frame = self.pc.fm.get_live_frame() # diff
if self.DEBUG_FRAMES: print("<<<<<<<<<<<<<< frame at %s" % current_frame_index)
if self.DEBUG_FRAMES:
print("<<<<<<<<<<<<<< frame at %s" % current_frame_index)
"""def recall_frame_index(self, index):
self.pc.shaders.recall_frame_params(self.frames[index].copy())"""

View File

@@ -1,8 +1,7 @@
import data_centre.plugin_collection
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin, DisplayPlugin
import copy
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin
from plugins.frame_manager import Frame
class ShaderQuickPresetPlugin(ActionsPlugin, DisplayPlugin): # ,SequencePlugin):
MAX_PRESETS = 8
@@ -55,7 +54,7 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
return ['QUIKSHDR', ['NAV_QKSH', 'PLAY_SHADER']]
def show_plugin(self, display, display_mode):
from tkinter import Text, END
from tkinter import END
# super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "ShaderQuickPresetPlugin")
@@ -115,7 +114,8 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
self.save_presets()
def store_current_preset(self):
if self.selected_preset is None: self.selected_preset = 0
if self.selected_preset is None:
self.selected_preset = 0
insert_position = self.selected_preset
self.presets[insert_position] = self.pc.fm.get_live_frame()
@@ -170,6 +170,3 @@ class ShaderQuickPresetPlugin(ActionsPlugin,DisplayPlugin): #,SequencePlugin):
self.selected_preset -= 1
if self.selected_preset < 0:
self.selected_preset = self.MAX_PRESETS - 1

View File

@@ -1,18 +1,16 @@
import math
import data_centre.plugin_collection
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin, DisplayPlugin, AutomationSourcePlugin
import pyaudio
import numpy as np
from random import randint
from statistics import mean
import numpy as np
import pyaudio
from data_centre.plugin_collection import ActionsPlugin, DisplayPlugin, SequencePlugin
# import matplotlib.pyplot as plt
np.set_printoptions(suppress=True) # don't use scientific notationn
class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
class SoundReactPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin):
DEBUG = False
active = True
@@ -112,7 +110,7 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
return ['SOUNDMOD', 'NAV_SND']
def show_plugin(self, display, display_mode):
from tkinter import Text, END
from tkinter import END
# super(DisplayPlugin).show_plugin(display, display_mode)
display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "SoundReactPlugin - ")
@@ -136,6 +134,7 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
display.display_text.insert(END, "\n\n\n")
energy_history = []
def run_sequence(self, position):
# position is irrelvant for this plugin, we just want to run continuously
if not self.active or self.stream is None:
@@ -168,12 +167,10 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
self.energy_history.append(diff) # self.values.get(sourcename,0.0))
# print("logging %s" % diff) #self.values.get(sourcename,0.0))
config.setdefault('energy', {})['gain'] = 0.5 # how much to multiply signal by
config.setdefault('energy', {})['threshold'] = 0.5 # subtract from post-gain signal (hence ignore all values below this value)
GAIN_MULT = 1.0
def energy(self, data):
peak = np.average(np.abs(data)) * 2
value = (peak / 2 ** 16) / 16 * 100
@@ -187,7 +184,8 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
value = 1.0
bars = "#" * int(50 * value)
if self.DEBUG: print("energy:\t\t%05d %s\t(converted to %s)"%(peak,bars,value))
if self.DEBUG:
print("energy:\t\t%05d %s\t(converted to %s)" % (peak, bars, value))
self.display_values['energy'] = "{} gn:{} trsh:{} trg:{}".format(
self.pc.display.get_bar(value),
self.pc.display.get_bar(self.config['energy']['gain']),
@@ -198,6 +196,7 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
return value
# dont think this works properly, or maybe it do just be like that
def peakfreq(self, data):
data = data.copy() * np.hanning(len(data)) # smooth the FFT by windowing data
fft = abs(np.fft.fft(data).real)
@@ -209,12 +208,12 @@ class SoundReactPlugin(ActionsPlugin,SequencePlugin,DisplayPlugin):
return False
value = freqPeak / 2000 # ?
# value = (value**16)
if self.DEBUG: print("peak frequency:\t%d\tHz\t(converted to %s)"%(freqPeak,value))
if self.DEBUG:
print("peak frequency:\t%d\tHz\t(converted to %s)" % (freqPeak, value))
self.display_values['peakfreq'] = ("%d Hz\t" % freqPeak) + "{:03.2f}".format(value)
return value
# ActionsPlugin methods
@property
def parserlist(self):

View File

@@ -1,6 +1,6 @@
import data_centre.plugin_collection
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin
class TestPlugin(ActionsPlugin, SequencePlugin):
disabled = True
@@ -26,6 +26,7 @@ class TestPlugin(ActionsPlugin,SequencePlugin):
# can now access various parts of recur via self.pc
cycle_count = 0
def cycle_shaders(self):
print("Cycle shaders!!!")
if self.cycle_count > 9:
@@ -42,6 +43,7 @@ class TestPlugin(ActionsPlugin,SequencePlugin):
duration = 5000
frequency = 50
def run_sequence(self, position):
self.pc.actions.call_method_name(
"set_the_shader_param_3_layer_0_continuous", position

View File

@@ -1,13 +1,15 @@
import serial
from serial import Serial
import data_centre.plugin_collection
from data_centre.plugin_collection import ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationReceiverPlugin, AutomationSourcePlugin
import threading
import time
import serial
from data_centre.plugin_collection import ActionsPlugin, AutomationSourcePlugin, DisplayPlugin, ModulationReceiverPlugin, SequencePlugin
class AsyncWriter(threading.Thread):
queue = []
quit_flag = False
def __init__(self, plugin):
super().__init__()
self.plugin = plugin
@@ -112,10 +114,10 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
self.asyncwriter = None
self.save_presets()
# methods/vars for AutomationSourcePlugin
# a lot of the nitty-gritty handled in parent class, these are for interfacing to the plugin
last_record = {}
def get_frame_data(self):
diff = self.last_record.copy()
# self.last_record = {}
@@ -141,13 +143,15 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
# experimental & hardcoded !
# TODO: make this not hardcoded and configurable mapping modulation to parameters, preferably on-the-fly..
modulation_value = [0.0, 0.0, 0.0, 0.0]
def set_modulation_value(self, param, value):
self.modulation_value[param] = value ## invert so that no signal always gives a value ..
# print("storing modulation slot %s as %s" % (param,value))
# take modulation value and throw it to local parameter
if self.DEBUG: print("||||| WJSendPlugin received set_modulation_value for param %s with value %s!" % (param, value))
if self.DEBUG:
print("||||| WJSendPlugin received set_modulation_value for param %s with value %s!" % (param, value))
# v = (0.5+value)/2
"""mapped = [
'mix',
@@ -163,9 +167,11 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
for queue, cmd in sorted(self.command_by_queue.items(), reverse=True):
cmd.setdefault('modulation', [{}, {}, {}, {}])
if self.DEBUG: print("\tparam %s, checking modulation %s" % (param, cmd.get('modulation')))
if self.DEBUG:
print("\tparam %s, checking modulation %s" % (param, cmd.get('modulation')))
if len(cmd['modulation'][param]) > 0:
if self.DEBUG: print("\tParam %s has modulation! sending update of values? %s" %
if self.DEBUG:
print("\tParam %s has modulation! sending update of values? %s" %
(param, [cmd['arguments'][y] for y in cmd['arg_names']]))
# self.send_buffered(cmd['queue'], cmd['form'], [x for x in [ cmd['arguments'][y] for y in cmd['arg_names'] ] ], record=False)
to_send[cmd['queue']] = cmd
@@ -178,7 +184,7 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
# methods for DisplayPlugin
def show_plugin(self, display, display_mode):
from tkinter import Text, END
from tkinter import END
display.display_text.insert(END, '{} \n'.format(display.body_title))
display.display_text.insert(END, "WJSendPlugin {}\n\n".format('ACTIVE' if self.active else 'not active'))
@@ -210,7 +216,6 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
def get_display_modes(self):
return ["WJMXSEND", "NAV_WJMX"]
# methods for SerialPlugin (TODO: if this needs generalising out!) and serial command queueing
def open_serial(self, port='/dev/ttyUSB0', baudrate=9600):
if self.ser is not None:
@@ -237,6 +242,7 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
import threading
serial_lock = threading.Lock()
def send_serial_string(self, string):
# TODO: thread this so can implement throttling and reduce bottleneck...
if not self.active:
@@ -270,6 +276,7 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
queue = {}
import threading
queue_lock = threading.Lock()
# send the queued commands to WJMX
def refresh(self):
if not self.ser or self.ser is None:
@@ -299,6 +306,7 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
last = {}
last_modulated = {}
def send_buffered(self, queue, form, args, record=True):
# only send if new command is different to the last one we sent
mod_args = self.modulate_arguments(self.command_by_queue.get(queue), args)
@@ -308,7 +316,8 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
output = form.format(*mod_args)
self.send_serial_string(output)
else:
if self.DEBUG: print("WJSendPlugin>> skipping sending %s %s as it is similar to what was previously sent" % (form,mod_args))
if self.DEBUG:
print("WJSendPlugin>> skipping sending %s %s as it is similar to what was previously sent" % (form, mod_args))
self.last[queue] = (form, args)
self.last_modulated[queue] = (form, mod_args)
@@ -326,7 +335,6 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
# append value, padded to length - for sending commands that aren't preprogrammed
self.send(command.split(':')[0], "{}{:0%iX}" % pad, [command, int(255 * value)])
# methods for ActionPlugin - preprogrammed parameters
@property
def parserlist(self):
@@ -360,8 +368,10 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
struct['modulation'] = [{}, {}, {}, {}]
def set_modulation_command_argument_level(self, command_name, argument_name, slot, level):
if self.DEBUG: print("set_modulation_command_argument_level(%s, %s, %s, %s)" % (command_name, argument_name, slot, level))
if not argument_name: self.commands[command_name]['arg_names'][0] #argument_name = 'v'
if self.DEBUG:
print("set_modulation_command_argument_level(%s, %s, %s, %s)" % (command_name, argument_name, slot, level))
if not argument_name:
self.commands[command_name]['arg_names'][0] # argument_name = 'v'
self.commands[command_name].setdefault('modulation', [{}, {}, {}, {}])[slot][argument_name] = level
@@ -399,7 +409,8 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
# arguments = packed_arguments.split("_") + [ value ]
# print("commands looks like %s" % self.commands)
msg = self.commands[param]
if len(msg['arg_names'])==1: argument_name = msg['arg_names'][0]
if len(msg['arg_names']) == 1:
argument_name = msg['arg_names'][0]
msg['arguments'][argument_name] = int(value * 255) # = arguments
self.send(msg['queue'], msg['form'], [msg['arguments'][p] for p in msg['arg_names']])
@@ -414,16 +425,19 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
for arg_name, m in modlevels.items():
if m > 0.0:
arg_index = command.get('arg_names').index(arg_name)
if self.DEBUG: print("\t\tupdating modulation slot %s, arg is %s\n\t with modlevel '%s' * modvalue '%s'" % (arg_index, args[arg_index], m, self.modulation_value[slot]))
if self.DEBUG:
print("\t\tupdating modulation slot %s, arg is %s\n\t with modlevel '%s' * modvalue '%s'" % (arg_index, args[arg_index], m, self.modulation_value[slot]))
# amount, value, level
newvalue = self.pc.shaders.get_modulation_value(
args[arg_index] / 255.0,
self.modulation_value[slot],
m
)
if self.DEBUG: print("\t\tnewvalue is %s" %newvalue)
if self.DEBUG:
print("\t\tnewvalue is %s" % newvalue)
args[arg_index] = int(255 * newvalue)
if self.DEBUG: print("modulate_arguments returning:\n\t%s" % args)
if self.DEBUG:
print("modulate_arguments returning:\n\t%s" % args)
return args
# panasonic parameters are 8 bit so go 0-255, so 127 is default of centre value
@@ -473,4 +487,3 @@ class WJSendPlugin(ActionsPlugin, SequencePlugin, DisplayPlugin, ModulationRecei
# }
}
command_by_queue = {}

View File

@@ -1,7 +1,7 @@
import copy
import json
from json import JSONEncoder
def _default(self, obj):
if getattr(obj.__class__, 'to_json'):
# return _default.default(obj.to_json())
@@ -9,9 +9,11 @@ def _default(self, obj):
else:
return _default.default(obj)
_default.default = JSONEncoder().default
JSONEncoder.default = _default
class Frame:
f = {'shader_params': [[None] * 4, [None] * 4, [None] * 4]}
pc = None
@@ -19,7 +21,6 @@ class Frame:
DEBUG_FRAMES = False # True
def __init__(self, pc):
import copy #from copy import deepcopy
self.pc = pc
def to_json(self):
@@ -27,6 +28,7 @@ class Frame:
def get(self, key, default=None):
return self.f.get(key, default)
def has(self, key):
return self.get(key) is not None
@@ -144,8 +146,6 @@ class Frame:
return s
def get_shader_param_summary(self, layer):
if self.get('shader_params') is None:
return ""
@@ -265,7 +265,8 @@ class Frame:
for plugin in self.pc.get_plugins(AutomationSourcePlugin):
f[plugin.frame_key] = plugin.merge_data(f.get(plugin.frame_key), frame2.get(plugin.frame_key))
if self.DEBUG_FRAMES: print("merge_frames: got return\t%s" % f)
if self.DEBUG_FRAMES:
print("merge_frames: got return\t%s" % f)
return Frame(self.pc).store_copy(f)
def get_ignored(self, ignored):
@@ -273,7 +274,8 @@ class Frame:
f = deepcopy(self.f) # frame1.copy()
frame = self.f
ignored = ignored.f
if self.DEBUG_FRAMES: print("get_frame_ignored: got frame\t%s" % self.f)
if self.DEBUG_FRAMES:
print("get_frame_ignored: got frame\t%s" % self.f)
for i, f2 in enumerate(frame.get('shader_params', [])):
for i2, p in enumerate(f2):
if ignored['shader_params'][i][i2] is not None:
@@ -295,14 +297,16 @@ class Frame:
# print("ignoring for %s:\n\t%s\n" % (plugin.frame_key, ignored.get(plugin.frame_key)))
f[plugin.frame_key] = plugin.get_ignored_data(f.get(plugin.frame_key, {}), ignored.get(plugin.frame_key, {}))
if self.DEBUG_FRAMES: print("get_frame_ignored: got return\t%s" % f)
if self.DEBUG_FRAMES:
print("get_frame_ignored: got return\t%s" % f)
return Frame(self.pc).store_copy(f)
def is_empty(self):
# from copy import deepcopy
# f = deepcopy(frame) #frame1.copy()
frame = self.f
if self.DEBUG_FRAMES: print("is_frame_empty: got frame\t%s" % frame)
if self.DEBUG_FRAMES:
print("is_frame_empty: got frame\t%s" % frame)
if self.has('feedback_active'):
return False
@@ -328,7 +332,8 @@ class Frame:
if not plugin.is_frame_data_empty(frame.get(plugin.frame_key)):
return False
if self.DEBUG_FRAMES: print("is_frame_empty: got return true")
if self.DEBUG_FRAMES:
print("is_frame_empty: got return true")
return True
def get_diff(self, current_frame):
@@ -346,7 +351,8 @@ class Frame:
# if self.DEBUG_FRAMES: print("got layer %s params: %s" % (layer, params))
for param, p in enumerate(params):
if p is not None and p != last_frame.get('shader_params')[layer][param]:
if self.DEBUG_FRAMES: print("setting layer %s param %s to %s" % (layer,param,p))
if self.DEBUG_FRAMES:
print("setting layer %s param %s to %s" % (layer, param, p))
param_values[layer][param] = p
if current_frame['feedback_active'] is not None and last_frame['feedback_active'] != current_frame['feedback_active']:
@@ -387,14 +393,12 @@ class Frame:
'strobe_amount': strobe_amount,
}
diff.update(plugin_data)
if self.DEBUG_FRAMES: print("returning\t%s\n^^^^" % diff['shader_params'])
if self.DEBUG_FRAMES:
print("returning\t%s\n^^^^" % diff['shader_params'])
return Frame(self.pc).store_copy(diff)
class FrameManager:
pc = None

View File

@@ -1,24 +1,21 @@
#!/usr/bin/python
import traceback
from tkinter import Tk, Frame
import sys
import tracemalloc
import argparse
import traceback
from tkinter import Frame, Tk
from pythonosc import udp_client
from actions import Actions
from data_centre.data import Data
from display_centre.display import Display
from display_centre.messages import MessageHandler
from user_input.analog_input import AnalogInput
from user_input.midi_input import MidiInput
from user_input.numpad_input import NumpadInput
from user_input.osc_input import OscInput
from user_input.midi_input import MidiInput
from user_input.analog_input import AnalogInput
from video_centre.video_driver import VideoDriver
#from video_centre.capture import Capture
from video_centre.shaders import Shaders
import data_centre
from video_centre.video_driver import VideoDriver
# create tk object
tk = Tk()
@@ -32,6 +29,7 @@ message_handler = MessageHandler()
data = Data(message_handler)
def setup_osc_client():
client_parser = argparse.ArgumentParser()
client_parser.add_argument("--ip", default="127.0.0.1", help="the ip")
@@ -41,6 +39,7 @@ def setup_osc_client():
return udp_client.SimpleUDPClient(client_args.ip, client_args.port)
osc_client = setup_osc_client()
# setup the video driver
video_driver = VideoDriver(tk, osc_client, message_handler, data)
@@ -70,14 +69,12 @@ actions.toggle_x_autorepeat()
frame.pack()
tk.attributes("-fullscreen", True)
def handle_error(exc, val, tb):
print('traceback for error : {}'.format(traceback.format_exc()))
message_handler.set_message('ERROR', val, traceback.format_exc())
tk.report_callback_exception = handle_error
tk.mainloop()

9
requirements.txt Normal file
View File

@@ -0,0 +1,9 @@
adafruit-mcp3008
gitpython
mido
numpy
omxplayer-wrapper
picamera
pyaudio
pyserial
python-osc

View File

@@ -1,6 +1,6 @@
import Adafruit_GPIO.SPI as SPI
import Adafruit_MCP3008
class AnalogInput(object):
def __init__(self, root, message_handler, display, actions, data):
self.root = root
@@ -14,7 +14,6 @@ class AnalogInput(object):
self.analog_input = None
self.check_if_listening_enabled()
def check_if_listening_enabled(self):
if self.data.settings['user_input']['ANALOG_INPUT']['value'] == 'enabled':
if not self.analog_input:
@@ -79,5 +78,3 @@ class AnalogInput(object):
## not sure whether we want to update the screen in general; here - probably not most of the time ...
# if 'cc' not in message_name:
# self.display.refresh_display()

View File

@@ -1,7 +1,5 @@
import string
import datetime
import mido
import subprocess
class MidiInput(object):
def __init__(self, root, message_handler, display, actions, data):
@@ -164,7 +162,6 @@ class MidiInput(object):
if self.midi_output.supports_midi_feedback(self.data.midi_device_name):
self.root.after(self.midi_delay * 5, self.refresh_midi_feedback)
def find_binding_for_action(self, action):
for bind, a in self.midi_mappings.items():
# print("looped over %s : %s " % (bind,a))
@@ -172,4 +169,3 @@ class MidiInput(object):
if action in c:
# print ("find_binding_for_action(%s) got %s" % (action, bind))
return bind

View File

@@ -1,5 +1,5 @@
import string
import sys
class NumpadInput(object):
KEY_000_DELAY = 100
@@ -111,8 +111,6 @@ class NumpadInput(object):
if not value:
self.display.refresh_display()
def check_key_release_settings(self, key):
this_mapping = self.key_mappings[key]
@@ -172,4 +170,3 @@ class NumpadInput(object):
elif (self.additional_0_in_event > 1):
self.in_0_event = False
self.run_action_for_mapped_key('n')

View File

@@ -1,12 +1,9 @@
import argparse
import string
import sys
import threading
from pythonosc import dispatcher
from pythonosc import dispatcher
from pythonosc import osc_server
import threading
import argparse
class OscInput(object):
@@ -66,7 +63,6 @@ class OscInput(object):
except:
self.message_handler.set_message('INFO', 'failed to start osc listener')
def exit_osc_server(self, unused_addr, args):
print('%%%%%%%%%%%%%%%%%%%%% exiting external_osc')
try:
@@ -75,7 +71,6 @@ class OscInput(object):
except:
self.message_handler.set_message('INFO', 'osc shutdown failed')
def on_osc_input(self, addr, args):
if 'keyboard' in addr:
self.on_key_osc_input(addr, args)
@@ -84,7 +79,6 @@ class OscInput(object):
else:
self.on_param_osc_input(addr, args)
def on_key_osc_input(self, addr, args):
args = str(args)
print("!!!!!!!!!!!!!!!!" + args)
@@ -126,4 +120,3 @@ class OscInput(object):
if 'continuous' not in method_name:
self.display.refresh_display()

View File

@@ -1,5 +1,3 @@
def generate_mappings_doc(title, mappings, column_one_header="Note/CC"):
# print(mappings)
output = ""
@@ -20,4 +18,3 @@ def generate_mappings_doc(title, mappings, column_one_header="Note/CC"):
output += "\n----\n"
print(output)

View File

@@ -1,5 +1,3 @@
class AltVideoPlayer:
def __init__(self, root, message_handler, data, osc_client, name):
self.root = root
@@ -23,7 +21,6 @@ class AltVideoPlayer:
self.position = -1
def try_load(self, layer, is_current=False):
load_attempts = 0
while (load_attempts < 2):
@@ -37,7 +34,6 @@ class AltVideoPlayer:
self.status = 'ERROR'
return False
def load(self, layer, is_current=False):
self.get_context_for_player(is_current)
print('the location is {}'.format(self.location))
@@ -73,9 +69,6 @@ class AltVideoPlayer:
else:
self.set_alpha_value(0)
def reload(self, layer, is_current=False):
self.exit()
self.player_running = False
@@ -156,7 +149,6 @@ class AltVideoPlayer:
except:
pass
## not sure if i am going to implement this atm
def set_screen_size_for_dev_mode(self):
if self.data.settings['system']['DEV_MODE_RESET']['value'] == 'on':
@@ -165,17 +157,3 @@ class AltVideoPlayer:
else:
aspect_mode = self.data.settings['video']['SCREEN_MODE']['value']
return False, '--aspect-mode', aspect_mode

View File

@@ -1,8 +1,10 @@
import datetime
import fractions
import os
import subprocess
import datetime
import picamera
import fractions
class Capture(object):
PREVIEW_LAYER = 255
@@ -21,7 +23,6 @@ class Capture(object):
## some capture settings
def create_capture_device(self):
if self.data.settings['capture']['TYPE']['value'] != 'usb':
if self.use_capture:
@@ -68,7 +69,6 @@ class Capture(object):
self.device.framerate = self.framerate
self.device.resolution = self.resolution
def start_preview(self):
if self.use_capture == False:
self.message_handler.set_message('INFO', 'capture not enabled')
@@ -94,7 +94,6 @@ class Capture(object):
else:
self.sensor_mode = 0
def set_preview_screen_size(self):
if self.data.settings['system']['DEV_MODE_RESET']['value'] == 'on':
self.device.preview.fullscreen = False
@@ -170,7 +169,6 @@ class Capture(object):
error_info = e
self.message_handler.set_message('ERROR', error_info)
def wait_for_recording_to_save(self, process, name):
print('the poll is {}'.format(process.poll()))
if process.poll() is not None:
@@ -253,4 +251,3 @@ class Capture(object):
def receive_recording_finished(self, path, value):
pass

View File

@@ -1,10 +1,12 @@
import os
import subprocess
import datetime
import fractions
import picamera
import os
import subprocess
import time
import picamera
class OfCapture(object):
def __init__(self, root, osc_client, message_handler, data):
self.root = root
@@ -35,7 +37,6 @@ class OfCapture(object):
self.has_capture = True
return True
def piCapture_with_no_source(self):
is_piCapture = subprocess.check_output(['pivideo', '--query', 'ready'])
if 'Video Processor was not found' not in str(is_piCapture):
@@ -133,7 +134,6 @@ class OfCapture(object):
self.wait_for_raw_file()
# set status to saving
def wait_for_raw_file(self):
if os.path.exists(self.video_dir + 'raw.h264'):
mp4box_process, recording_name = self.convert_raw_recording()
@@ -167,7 +167,6 @@ class OfCapture(object):
error_info = e
self.message_handler.set_message('ERROR', error_info)
def wait_for_recording_to_save(self, process, name):
print('the poll is {}'.format(process.poll()))
if process.poll() is not None:
@@ -224,6 +223,3 @@ class OfCapture(object):
return int(1000000 / self.framerate)
else:
return int(fractions.Fraction(setting_value) * 1000000)

View File

@@ -1,8 +1,10 @@
import display_centre.menu as menu
import os
from statistics import mean
import display_centre.menu as menu
from data_centre.plugin_collection import ModulationReceiverPlugin
class Shaders(object):
MENU_HEIGHT = 10
EMPTY_SHADER = dict(name='none', is_shader=True, shad_type='-', param_number=4, path='-')
@@ -56,7 +58,6 @@ class Shaders(object):
shaders_menu_list.append(dict(name=line['name'], is_shader=False, shad_type='', param_number=None, path=None))
return shaders_menu_list
def get_path_for_shader(self, file_name):
######## returns full path for a given file name ########
for path in self.data.PATHS_TO_SHADERS:
@@ -77,7 +78,6 @@ class Shaders(object):
else:
return '-'
def determine_shader_parameter_number(self, path):
max_amount = 4
if True: # for now always assume 4 params
@@ -240,8 +240,10 @@ class Shaders(object):
# TODO: read from list of input formulas, from plugins etc to modulate the value
temp_amount = amount + (value * level)
# print("from amount %s, modulation is %s, temp_amount is %s" % (amount, modulation, temp_amount))
if temp_amount < 0: temp_amount = 0 # input range is 0-1 so convert back
if temp_amount > 1: temp_amount = 1 # modulation however is -1 to +1
if temp_amount < 0:
temp_amount = 0 # input range is 0-1 so convert back
if temp_amount > 1:
temp_amount = 1 # modulation however is -1 to +1
return temp_amount
@@ -292,4 +294,3 @@ class Shaders(object):
def set_speed_layer_to_amount(self, layer, amount):
self.osc_client.send_message("/shader/{}/speed".format(str(layer)), amount)
self.selected_speed_list[layer] = amount

View File

@@ -1,8 +1,8 @@
from video_centre.video_player import VideoPlayer
from video_centre.alt_video_player import AltVideoPlayer
from video_centre.video_player import VideoPlayer
class VideoDriver(object):
MAX_LAYER = 254
def __init__(self, root, osc_client, message_handler, data):
@@ -31,8 +31,6 @@ class VideoDriver(object):
self.root.after(self.delay, self.begin_playing)
# self.print_status()
def update_video_settings(self):
self.switch_on_finish = self.data.settings['sampler']['ON_FINISH']['value'] == 'switch'
self.loop_parallel = self.data.settings['sampler']['LOOP_TYPE']['value'] == 'parallel'
@@ -114,7 +112,6 @@ class VideoDriver(object):
else:
self.in_next_load_cycle = False
def get_player_info_for_status(self):
return self.current_player.bankslot_number, self.current_player.status, self.current_player.alpha, \
self.next_player.bankslot_number, self.next_player.status, self.next_player.alpha

View File

@@ -1,5 +1,6 @@
from omxplayer.player import OMXPlayer
class VideoPlayer:
def __init__(self, root, message_handler, data, name):
self.root = root
@@ -20,7 +21,6 @@ class VideoPlayer:
self.alpha = 0
self.show_toggle_on = False
def try_load(self, layer, is_current=False):
load_attempts = 0
while (load_attempts < 2):
@@ -34,7 +34,6 @@ class VideoPlayer:
self.status = 'ERROR'
return False
def load(self, layer, is_current=False):
# try:
self.get_context_for_player(is_current)
@@ -187,5 +186,3 @@ class VideoPlayer:
else:
aspect_mode = self.data.settings['video']['SCREEN_MODE']['value']
return False, '--aspect-mode', aspect_mode